ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
Interest.php
Go to the documentation of this file.
1 <?php
2 
4 
9 
10 class Interest
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 }
static schedulePayment($interestRate, $period, $numberOfPeriods, $principleRemaining)
ISPMT.
Definition: Interest.php:91
$type
static rate( $numberOfPeriods, $payment, $presentValue, $futureValue=0.0, $type=FinancialConstants::PAYMENT_END_OF_PERIOD, $guess=0.1)
RATE.
Definition: Interest.php:155
static payment( $interestRate, $period, $numberOfPeriods, $presentValue, $futureValue=0, $type=FinancialConstants::PAYMENT_END_OF_PERIOD)
IPMT.
Definition: Interest.php:34
static rateNextGuess($rate, $numberOfPeriods, $payment, $presentValue, $futureValue, $type)
Definition: Interest.php:199
$i
Definition: disco.tpl.php:19
static flattenSingleValue($value='')
Convert an array to a single scalar value by extracting the first element.
Definition: Functions.php:649