Skip to content

Instantly share code, notes, and snippets.

@vhchung
Created July 20, 2016 07:02
Show Gist options
  • Save vhchung/88418322287699f1d350e7aad187141b to your computer and use it in GitHub Desktop.
Save vhchung/88418322287699f1d350e7aad187141b to your computer and use it in GitHub Desktop.
<?php
function calculateRate($nper, $pmt, $pv, $fv, $type, $guess) {
//FROM MS http://office.microsoft.com/en-us/excel-help/rate-HP005209232.aspx
$FINANCIAL_MAX_ITERATIONS = 20;//Bet accuracy with 128
$FINANCIAL_PRECISION = 0.0000001;//1.0e-8
$y, $y0, $y1, $x0, $x1 = 0, $f = 0, $i = 0;
$rate = $guess;
if (abs($rate) < $FINANCIAL_PRECISION) {
$y = $pv * (1 + $nper * $rate) + $pmt * (1 + $rate * $type) * $nper + $fv;
} else {
$f = exp($nper * log(1 + $rate));
$y = $pv * $f + $pmt * (1 / $rate + $type) * ($f - 1) + $fv;
}
$y0 = $pv + $pmt * $nper + $fv;
$y1 = $pv * $f + $pmt * (1 / $rate + $type) * ($f - 1) + $fv;
// find root by Newton secant method
$i = $x0 = 0.0;
$x1 = $rate;
while ((abs($y0 - $y1) > $FINANCIAL_PRECISION) && ($i < $FINANCIAL_MAX_ITERATIONS)) {
$rate = ($y1 * $x0 - $y0 * $x1) / ($y1 - $y0);
$x0 = $x1;
$x1 = $rate;
if (abs($rate) < $FINANCIAL_PRECISION) {
$y = $pv * (1 + $nper * $rate) + $pmt * (1 + $rate * $type) * $nper + $fv;
} else {
$f = exp($nper * log(1 + $rate));
$y = $pv * $f + $pmt * (1 / $rate + $type) * ($f - 1) + $fv;
}
$y0 = $y1;
$y1 = $y;
++$i;
}
return $rate;
}
echo calculateRate();
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment