ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
Interest.php
Go to the documentation of this file.
1<?php
2
4
9
11{
12 private const FINANCIAL_MAX_ITERATIONS = 128;
13
14 private const FINANCIAL_PRECISION = 1.0e-08;
15
34 public static function payment(
35 $interestRate,
36 $period,
37 $numberOfPeriods,
38 $presentValue,
39 $futureValue = 0,
40 $type = FinancialConstants::PAYMENT_END_OF_PERIOD
41 ) {
42 $interestRate = Functions::flattenSingleValue($interestRate);
43 $period = Functions::flattenSingleValue($period);
44 $numberOfPeriods = Functions::flattenSingleValue($numberOfPeriods);
45 $presentValue = Functions::flattenSingleValue($presentValue);
46 $futureValue = ($futureValue === null) ? 0.0 : Functions::flattenSingleValue($futureValue);
47 $type = ($type === null) ? FinancialConstants::PAYMENT_END_OF_PERIOD : Functions::flattenSingleValue($type);
48
49 try {
50 $interestRate = CashFlowValidations::validateRate($interestRate);
51 $period = CashFlowValidations::validateInt($period);
52 $numberOfPeriods = CashFlowValidations::validateInt($numberOfPeriods);
53 $presentValue = CashFlowValidations::validatePresentValue($presentValue);
54 $futureValue = CashFlowValidations::validateFutureValue($futureValue);
56 } catch (Exception $e) {
57 return $e->getMessage();
58 }
59
60 // Validate parameters
61 if ($period <= 0 || $period > $numberOfPeriods) {
62 return Functions::NAN();
63 }
64
65 // Calculate
66 $interestAndPrincipal = new InterestAndPrincipal(
67 $interestRate,
68 $period,
69 $numberOfPeriods,
70 $presentValue,
71 $futureValue,
72 $type
73 );
74
75 return $interestAndPrincipal->interest();
76 }
77
91 public static function schedulePayment($interestRate, $period, $numberOfPeriods, $principleRemaining)
92 {
93 $interestRate = Functions::flattenSingleValue($interestRate);
94 $period = Functions::flattenSingleValue($period);
95 $numberOfPeriods = Functions::flattenSingleValue($numberOfPeriods);
96 $principleRemaining = Functions::flattenSingleValue($principleRemaining);
97
98 try {
99 $interestRate = CashFlowValidations::validateRate($interestRate);
100 $period = CashFlowValidations::validateInt($period);
101 $numberOfPeriods = CashFlowValidations::validateInt($numberOfPeriods);
102 $principleRemaining = CashFlowValidations::validateFloat($principleRemaining);
103 } catch (Exception $e) {
104 return $e->getMessage();
105 }
106
107 // Validate parameters
108 if ($period <= 0 || $period > $numberOfPeriods) {
109 return Functions::NAN();
110 }
111
112 // Return value
113 $returnValue = 0;
114
115 // Calculate
116 $principlePayment = ($principleRemaining * 1.0) / ($numberOfPeriods * 1.0);
117 for ($i = 0; $i <= $period; ++$i) {
118 $returnValue = $interestRate * $principleRemaining * -1;
119 $principleRemaining -= $principlePayment;
120 // principle needs to be 0 after the last payment, don't let floating point screw it up
121 if ($i == $numberOfPeriods) {
122 $returnValue = 0.0;
123 }
124 }
125
126 return $returnValue;
127 }
128
155 public static function rate(
156 $numberOfPeriods,
157 $payment,
158 $presentValue,
159 $futureValue = 0.0,
160 $type = FinancialConstants::PAYMENT_END_OF_PERIOD,
161 $guess = 0.1
162 ) {
163 $numberOfPeriods = Functions::flattenSingleValue($numberOfPeriods);
164 $payment = Functions::flattenSingleValue($payment);
165 $presentValue = Functions::flattenSingleValue($presentValue);
166 $futureValue = ($futureValue === null) ? 0.0 : Functions::flattenSingleValue($futureValue);
167 $type = ($type === null) ? FinancialConstants::PAYMENT_END_OF_PERIOD : Functions::flattenSingleValue($type);
168 $guess = ($guess === null) ? 0.1 : Functions::flattenSingleValue($guess);
169
170 try {
171 $numberOfPeriods = CashFlowValidations::validateInt($numberOfPeriods);
172 $payment = CashFlowValidations::validateFloat($payment);
173 $presentValue = CashFlowValidations::validatePresentValue($presentValue);
174 $futureValue = CashFlowValidations::validateFutureValue($futureValue);
176 $guess = CashFlowValidations::validateFloat($guess);
177 } catch (Exception $e) {
178 return $e->getMessage();
179 }
180
181 $rate = $guess;
182 // rest of code adapted from python/numpy
183 $close = false;
184 $iter = 0;
185 while (!$close && $iter < self::FINANCIAL_MAX_ITERATIONS) {
186 $nextdiff = self::rateNextGuess($rate, $numberOfPeriods, $payment, $presentValue, $futureValue, $type);
187 if (!is_numeric($nextdiff)) {
188 break;
189 }
190 $rate1 = $rate - $nextdiff;
191 $close = abs($rate1 - $rate) < self::FINANCIAL_PRECISION;
192 ++$iter;
193 $rate = $rate1;
194 }
195
196 return $close ? $rate : Functions::NAN();
197 }
198
199 private static function rateNextGuess($rate, $numberOfPeriods, $payment, $presentValue, $futureValue, $type)
200 {
201 if ($rate == 0.0) {
202 return Functions::NAN();
203 }
204 $tt1 = ($rate + 1) ** $numberOfPeriods;
205 $tt2 = ($rate + 1) ** ($numberOfPeriods - 1);
206 $numerator = $futureValue + $tt1 * $presentValue + $payment * ($tt1 - 1) * ($rate * $type + 1) / $rate;
207 $denominator = $numberOfPeriods * $tt2 * $presentValue - $payment * ($tt1 - 1)
208 * ($rate * $type + 1) / ($rate * $rate) + $numberOfPeriods
209 * $payment * $tt2 * ($rate * $type + 1) / $rate + $payment * ($tt1 - 1) * $type / $rate;
210 if ($denominator == 0) {
211 return Functions::NAN();
212 }
213
214 return $numerator / $denominator;
215 }
216}
An exception for terminatinating execution or to throw for unit testing.
static schedulePayment($interestRate, $period, $numberOfPeriods, $principleRemaining)
ISPMT.
Definition: Interest.php:91
static rateNextGuess($rate, $numberOfPeriods, $payment, $presentValue, $futureValue, $type)
Definition: Interest.php:199
static payment( $interestRate, $period, $numberOfPeriods, $presentValue, $futureValue=0, $type=FinancialConstants::PAYMENT_END_OF_PERIOD)
IPMT.
Definition: Interest.php:34
static rate( $numberOfPeriods, $payment, $presentValue, $futureValue=0.0, $type=FinancialConstants::PAYMENT_END_OF_PERIOD, $guess=0.1)
RATE.
Definition: Interest.php:155
static flattenSingleValue($value='')
Convert an array to a single scalar value by extracting the first element.
Definition: Functions.php:649
$i
Definition: disco.tpl.php:19
$type