30 if (!defined(
'PHPEXCEL_ROOT')) {
34 define(
'PHPEXCEL_ROOT', dirname(__FILE__) .
'/../../');
35 require(PHPEXCEL_ROOT .
'PHPExcel/Autoloader.php');
40 define(
'FINANCIAL_MAX_ITERATIONS', 128);
43 define(
'FINANCIAL_PRECISION', 1.0e-08);
56 $date = clone $testDate;
57 $date->modify(
'+1 day');
58 return ($date->format(
'd') == 1);
63 $date = clone $testDate;
64 return ($date->format(
'd') == 1);
69 $months = 12 / $frequency;
75 $result->modify(
'-'.$months.
' months');
78 $result->modify(
'+'.$months.
' months');
82 $result->modify(
'-1 day');
90 if (($frequency == 1) || ($frequency == 2) || ($frequency == 4)) {
94 (($frequency == 6) || ($frequency == 12))) {
128 for ($i = 1; $i<= $per; ++$i) {
129 $interest = (
$type && $i == 1) ? 0 : -$capital * $rate;
130 $principal = $pmt - $interest;
131 $capital += $principal;
133 return array($interest, $principal);
155 public static function ACCRINT($issue, $firstinter, $settlement, $rate, $par=1000, $frequency=1, $basis=0) {
165 if ((is_numeric($rate)) && (is_numeric($par))) {
166 if (($rate <= 0) || ($par <= 0)) {
170 if (!is_numeric($daysBetweenIssueAndSettlement)) {
172 return $daysBetweenIssueAndSettlement;
175 return $par * $rate * $daysBetweenIssueAndSettlement;
198 public static function ACCRINTM($issue, $settlement, $rate, $par=1000, $basis=0) {
206 if ((is_numeric($rate)) && (is_numeric($par))) {
207 if (($rate <= 0) || ($par <= 0)) {
211 if (!is_numeric($daysBetweenIssueAndSettlement)) {
213 return $daysBetweenIssueAndSettlement;
215 return $par * $rate * $daysBetweenIssueAndSettlement;
221 public static function AMORDEGRC($cost, $purchased, $firstPeriod, $salvage, $period, $rate, $basis=0) {
230 $fUsePer = 1.0 / $rate;
232 if ($fUsePer < 3.0) {
233 $amortiseCoeff = 1.0;
234 } elseif ($fUsePer < 5.0) {
235 $amortiseCoeff = 1.5;
236 } elseif ($fUsePer <= 6.0) {
237 $amortiseCoeff = 2.0;
239 $amortiseCoeff = 2.5;
242 $rate *= $amortiseCoeff;
245 $fRest = $cost - $salvage;
247 for ($n = 0; $n < $period; ++$n) {
248 $fNRate = round($rate * $cost,0);
252 switch ($period - $n) {
254 case 1 :
return round($cost * 0.5,0);
256 default :
return 0.0;
266 public static function AMORLINC($cost, $purchased, $firstPeriod, $salvage, $period, $rate, $basis=0) {
275 $fOneRate = $cost * $rate;
276 $fCostDelta = $cost - $salvage;
282 $yearFrac *= 365 / 366;
285 $f0Rate = $yearFrac * $rate * $cost;
286 $nNumOfFullPeriods = intval(($cost - $salvage - $f0Rate) / $fOneRate);
290 } elseif ($period <= $nNumOfFullPeriods) {
292 } elseif ($period == ($nNumOfFullPeriods + 1)) {
293 return ($fCostDelta - $fOneRate * $nNumOfFullPeriods - $f0Rate);
300 public static function COUPDAYBS($settlement, $maturity, $frequency, $basis=0) {
313 if (($settlement > $maturity) ||
314 (!self::_validFrequency($frequency)) ||
315 (($basis < 0) || ($basis > 4))) {
326 public static function COUPDAYS($settlement, $maturity, $frequency, $basis=0) {
339 if (($settlement > $maturity) ||
340 (!self::_validFrequency($frequency)) ||
341 (($basis < 0) || ($basis > 4))) {
347 return 365 / $frequency;
349 if ($frequency == 1) {
351 return ($daysPerYear / $frequency);
355 return ($next - $prev);
358 return 360 / $frequency;
364 public static function COUPDAYSNC($settlement, $maturity, $frequency, $basis=0) {
377 if (($settlement > $maturity) ||
378 (!self::_validFrequency($frequency)) ||
379 (($basis < 0) || ($basis > 4))) {
390 public static function COUPNCD($settlement, $maturity, $frequency, $basis=0) {
403 if (($settlement > $maturity) ||
404 (!self::_validFrequency($frequency)) ||
405 (($basis < 0) || ($basis > 4))) {
413 public static function COUPNUM($settlement, $maturity, $frequency, $basis=0) {
426 if (($settlement > $maturity) ||
427 (!self::_validFrequency($frequency)) ||
428 (($basis < 0) || ($basis > 4))) {
435 switch ($frequency) {
437 return ceil($daysBetweenSettlementAndMaturity / 360);
439 return ceil($daysBetweenSettlementAndMaturity / 180);
441 return ceil($daysBetweenSettlementAndMaturity / 90);
443 return ceil($daysBetweenSettlementAndMaturity / 60);
445 return ceil($daysBetweenSettlementAndMaturity / 30);
451 public static function COUPPCD($settlement, $maturity, $frequency, $basis=0) {
464 if (($settlement > $maturity) ||
465 (!self::_validFrequency($frequency)) ||
466 (($basis < 0) || ($basis > 4))) {
488 public static function CUMIPMT($rate, $nper, $pv, $start, $end,
$type = 0) {
500 if ($start < 1 || $start > $end) {
506 for ($per = $start; $per <= $end; ++$per) {
528 public static function CUMPRINC($rate, $nper, $pv, $start, $end,
$type = 0) {
540 if ($start < 1 || $start > $end) {
546 for ($per = $start; $per <= $end; ++$per) {
569 public static function DB($cost, $salvage, $life, $period, $month=12) {
577 if ((is_numeric($cost)) && (is_numeric($salvage)) && (is_numeric($life)) && (is_numeric($period)) && (is_numeric($month))) {
580 } elseif (($cost < 0) || (($salvage / $cost) < 0) || ($life <= 0) || ($period < 1) || ($month < 1)) {
584 $fixedDepreciationRate = 1 - pow(($salvage / $cost), (1 / $life));
585 $fixedDepreciationRate = round($fixedDepreciationRate, 3);
588 $previousDepreciation = 0;
589 for ($per = 1; $per <= $period; ++$per) {
591 $depreciation = $cost * $fixedDepreciationRate * $month / 12;
592 } elseif ($per == ($life + 1)) {
593 $depreciation = ($cost - $previousDepreciation) * $fixedDepreciationRate * (12 - $month) / 12;
595 $depreciation = ($cost - $previousDepreciation) * $fixedDepreciationRate;
597 $previousDepreciation += $depreciation;
600 $depreciation = round($depreciation,2);
602 return $depreciation;
621 public static function DDB($cost, $salvage, $life, $period, $factor=2.0) {
629 if ((is_numeric($cost)) && (is_numeric($salvage)) && (is_numeric($life)) && (is_numeric($period)) && (is_numeric($factor))) {
630 if (($cost <= 0) || (($salvage / $cost) < 0) || ($life <= 0) || ($period < 1) || ($factor <= 0.0) || ($period > $life)) {
634 $fixedDepreciationRate = 1 - pow(($salvage / $cost), (1 / $life));
635 $fixedDepreciationRate = round($fixedDepreciationRate, 3);
638 $previousDepreciation = 0;
639 for ($per = 1; $per <= $period; ++$per) {
640 $depreciation = min( ($cost - $previousDepreciation) * ($factor / $life), ($cost - $salvage - $previousDepreciation) );
641 $previousDepreciation += $depreciation;
644 $depreciation = round($depreciation,2);
646 return $depreciation;
671 public static function DISC($settlement, $maturity, $price, $redemption, $basis=0) {
679 if ((is_numeric($price)) && (is_numeric($redemption)) && (is_numeric($basis))) {
680 if (($price <= 0) || ($redemption <= 0)) {
684 if (!is_numeric($daysBetweenSettlementAndMaturity)) {
686 return $daysBetweenSettlementAndMaturity;
689 return ((1 - $price / $redemption) / $daysBetweenSettlementAndMaturity);
705 public static function DOLLARDE($fractional_dollar = Null, $fraction = 0) {
710 if (is_null($fractional_dollar) || $fraction < 0) {
713 if ($fraction == 0) {
717 $dollars = floor($fractional_dollar);
718 $cents = fmod($fractional_dollar,1);
720 $cents *= pow(10,ceil(log10($fraction)));
721 return $dollars + $cents;
735 public static function DOLLARFR($decimal_dollar = Null, $fraction = 0) {
740 if (is_null($decimal_dollar) || $fraction < 0) {
743 if ($fraction == 0) {
747 $dollars = floor($decimal_dollar);
748 $cents = fmod($decimal_dollar,1);
750 $cents *= pow(10,-ceil(log10($fraction)));
751 return $dollars + $cents;
764 public static function EFFECT($nominal_rate = 0, $npery = 0) {
769 if ($nominal_rate <= 0 || $npery < 1) {
773 return pow((1 + $nominal_rate / $npery), $npery) - 1;
789 public static function FV($rate = 0, $nper = 0, $pmt = 0, $pv = 0,
$type = 0) {
802 if (!is_null($rate) && $rate != 0) {
803 return -$pv * pow(1 + $rate, $nper) - $pmt * (1 + $rate *
$type) * (pow(1 + $rate, $nper) - 1) / $rate;
805 return -$pv - $pmt * $nper;
818 foreach($schedule as $n) {
819 $principal *= 1 + $n;
845 public static function INTRATE($settlement, $maturity, $investment, $redemption, $basis=0) {
853 if ((is_numeric($investment)) && (is_numeric($redemption)) && (is_numeric($basis))) {
854 if (($investment <= 0) || ($redemption <= 0)) {
858 if (!is_numeric($daysBetweenSettlementAndMaturity)) {
860 return $daysBetweenSettlementAndMaturity;
863 return (($redemption / $investment) - 1) / ($daysBetweenSettlementAndMaturity);
882 public static function IPMT($rate, $per, $nper, $pv, $fv = 0,
$type = 0) {
894 if ($per <= 0 || $per > $nper) {
900 return $interestAndPrincipal[0];
904 public static function IRR($values, $guess = 0.1) {
915 if (($f1 * $f2) < 0.0)
break;
916 if (abs($f1) < abs($f2)) {
917 $f1 =
self::NPV($x1 += 1.6 * ($x1 - $x2), $values);
919 $f2 =
self::NPV($x2 += 1.6 * ($x2 - $x1), $values);
937 if ($f_mid <= 0.0) $rtb = $x_mid;
966 $interestRate = array_shift($aArgs);
967 $period = array_shift($aArgs);
968 $numberPeriods = array_shift($aArgs);
969 $principleRemaining = array_shift($aArgs);
972 $principlePayment = ($principleRemaining * 1.0) / ($numberPeriods * 1.0);
973 for($i=0; $i <= $period; ++$i) {
974 $returnValue = $interestRate * $principleRemaining * -1;
975 $principleRemaining -= $principlePayment;
977 if($i == $numberPeriods) {
981 return($returnValue);
985 public static function MIRR($values, $finance_rate, $reinvestment_rate) {
992 $rr = 1.0 + $reinvestment_rate;
993 $fr = 1.0 + $finance_rate;
995 $npv_pos = $npv_neg = 0.0;
996 foreach($values as $i => $v) {
998 $npv_pos += $v / pow($rr, $i);
1000 $npv_neg += $v / pow($fr, $i);
1004 if (($npv_neg == 0) || ($npv_pos == 0) || ($reinvestment_rate <= -1)) {
1008 $mirr = pow((-$npv_pos * pow($rr, $n))
1009 / ($npv_neg * ($rr)), (1.0 / ($n - 1))) - 1.0;
1024 public static function NOMINAL($effect_rate = 0, $npery = 0) {
1029 if ($effect_rate <= 0 || $npery < 1) {
1034 return $npery * (pow($effect_rate + 1, 1 / $npery) - 1);
1050 public static function NPER($rate = 0, $pmt = 0, $pv = 0, $fv = 0,
$type = 0) {
1063 if (!is_null($rate) && $rate != 0) {
1064 if ($pmt == 0 && $pv == 0) {
1067 return log(($pmt * (1 + $rate *
$type) / $rate - $fv) / ($pv + $pmt * (1 + $rate * $type) / $rate)) / log(1 + $rate);
1072 return (-$pv -$fv) / $pmt;
1086 public static function NPV() {
1094 $rate = array_shift($aArgs);
1095 for ($i = 1; $i <= count($aArgs); ++$i) {
1097 if (is_numeric($aArgs[$i - 1])) {
1098 $returnValue += $aArgs[$i - 1] / pow(1 + $rate, $i);
1103 return $returnValue;
1119 public static function PMT($rate = 0, $nper = 0, $pv = 0, $fv = 0,
$type = 0) {
1132 if (!is_null($rate) && $rate != 0) {
1133 return (-$fv - $pv * pow(1 + $rate, $nper)) / (1 + $rate *
$type) / ((pow(1 + $rate, $nper) - 1) / $rate);
1135 return (-$pv - $fv) / $nper;
1153 public static function PPMT($rate, $per, $nper, $pv, $fv = 0,
$type = 0) {
1165 if ($per <= 0 || $per > $nper) {
1171 return $interestAndPrincipal[1];
1175 public static function PRICE($settlement, $maturity, $rate, $yield, $redemption, $frequency, $basis=0) {
1191 if (($settlement > $maturity) ||
1192 (!self::_validFrequency($frequency)) ||
1193 (($basis < 0) || ($basis > 4))) {
1199 $n =
self::COUPNUM($settlement, $maturity, $frequency, $basis);
1202 $baseYF = 1.0 + ($yield / $frequency);
1203 $rfp = 100 * ($rate / $frequency);
1206 $result = $redemption / pow($baseYF, (--$n + $de));
1207 for($k = 0; $k <= $n; ++$k) {
1208 $result += $rfp / (pow($baseYF, ($k + $de)));
1210 $result -= $rfp * ($a / $e);
1235 public static function PRICEDISC($settlement, $maturity, $discount, $redemption, $basis=0) {
1243 if ((is_numeric($discount)) && (is_numeric($redemption)) && (is_numeric($basis))) {
1244 if (($discount <= 0) || ($redemption <= 0)) {
1248 if (!is_numeric($daysBetweenSettlementAndMaturity)) {
1250 return $daysBetweenSettlementAndMaturity;
1253 return $redemption * (1 - $discount * $daysBetweenSettlementAndMaturity);
1279 public static function PRICEMAT($settlement, $maturity, $issue, $rate, $yield, $basis=0) {
1288 if (is_numeric($rate) && is_numeric($yield)) {
1289 if (($rate <= 0) || ($yield <= 0)) {
1293 if (!is_numeric($daysPerYear)) {
1294 return $daysPerYear;
1297 if (!is_numeric($daysBetweenIssueAndSettlement)) {
1299 return $daysBetweenIssueAndSettlement;
1301 $daysBetweenIssueAndSettlement *= $daysPerYear;
1303 if (!is_numeric($daysBetweenIssueAndMaturity)) {
1305 return $daysBetweenIssueAndMaturity;
1307 $daysBetweenIssueAndMaturity *= $daysPerYear;
1309 if (!is_numeric($daysBetweenSettlementAndMaturity)) {
1311 return $daysBetweenSettlementAndMaturity;
1313 $daysBetweenSettlementAndMaturity *= $daysPerYear;
1315 return ((100 + (($daysBetweenIssueAndMaturity / $daysPerYear) * $rate * 100)) /
1316 (1 + (($daysBetweenSettlementAndMaturity / $daysPerYear) * $yield)) -
1317 (($daysBetweenIssueAndSettlement / $daysPerYear) * $rate * 100));
1335 public static function PV($rate = 0, $nper = 0, $pmt = 0, $fv = 0,
$type = 0) {
1348 if (!is_null($rate) && $rate != 0) {
1349 return (-$pmt * (1 + $rate *
$type) * ((pow(1 + $rate, $nper) - 1) / $rate) - $fv) / pow(1 + $rate, $nper);
1351 return -$fv - $pmt * $nper;
1360 public static function RATE($nper, $pmt, $pv, $fv = 0.0,
$type = 0, $guess = 0.1) {
1370 $y = $pv * (1 + $nper * $rate) + $pmt * (1 + $rate *
$type) * $nper + $fv;
1372 $f = exp($nper * log(1 + $rate));
1373 $y = $pv *
$f + $pmt * (1 / $rate +
$type) * (
$f - 1) + $fv;
1375 $y0 = $pv + $pmt * $nper + $fv;
1376 $y1 = $pv *
$f + $pmt * (1 / $rate +
$type) * (
$f - 1) + $fv;
1382 $rate = ($y1 * $x0 - $y0 * $x1) / ($y1 - $y0);
1387 $y = $pv * (1 + $nper * $rate) + $pmt * (1 + $rate *
$type) * $nper + $fv;
1389 $f = exp($nper * log(1 + $rate));
1390 $y = $pv *
$f + $pmt * (1 / $rate +
$type) * (
$f - 1) + $fv;
1420 public static function RECEIVED($settlement, $maturity, $investment, $discount, $basis=0) {
1428 if ((is_numeric($investment)) && (is_numeric($discount)) && (is_numeric($basis))) {
1429 if (($investment <= 0) || ($discount <= 0)) {
1433 if (!is_numeric($daysBetweenSettlementAndMaturity)) {
1435 return $daysBetweenSettlementAndMaturity;
1438 return $investment / ( 1 - ($discount * $daysBetweenSettlementAndMaturity));
1454 public static function SLN($cost, $salvage, $life) {
1460 if ((is_numeric($cost)) && (is_numeric($salvage)) && (is_numeric($life))) {
1464 return ($cost - $salvage) / $life;
1481 public static function SYD($cost, $salvage, $life, $period) {
1488 if ((is_numeric($cost)) && (is_numeric($salvage)) && (is_numeric($life)) && (is_numeric($period))) {
1489 if (($life < 1) || ($period > $life)) {
1492 return (($cost - $salvage) * ($life - $period + 1) * 2) / ($life * ($life + 1));
1510 public static function TBILLEQ($settlement, $maturity, $discount) {
1517 if (is_string($testValue)) {
1532 return (365 * $discount) / (360 - $discount * $daysBetweenSettlementAndMaturity);
1548 public static function TBILLPRICE($settlement, $maturity, $discount) {
1558 if (is_numeric($discount)) {
1559 if ($discount <= 0) {
1566 if (!is_numeric($daysBetweenSettlementAndMaturity)) {
1568 return $daysBetweenSettlementAndMaturity;
1574 if ($daysBetweenSettlementAndMaturity > 360) {
1578 $price = 100 * (1 - (($discount * $daysBetweenSettlementAndMaturity) / 360));
1600 public static function TBILLYIELD($settlement, $maturity, $price) {
1606 if (is_numeric($price)) {
1614 if (!is_numeric($daysBetweenSettlementAndMaturity)) {
1616 return $daysBetweenSettlementAndMaturity;
1622 if ($daysBetweenSettlementAndMaturity > 360) {
1626 return ((100 - $price) / $price) * (360 / $daysBetweenSettlementAndMaturity);
1632 public static function XIRR($values, $dates, $guess = 0.1) {
1645 if (($f1 * $f2) < 0.0)
break;
1646 if (abs($f1) < abs($f2)) {
1647 $f1 =
self::XNPV($x1 += 1.6 * ($x1 - $x2), $values, $dates);
1649 $f2 =
self::XNPV($x2 += 1.6 * ($x2 - $x1), $values, $dates);
1665 $x_mid = $rtb + $dx;
1666 $f_mid =
self::XNPV($x_mid, $values, $dates);
1667 if ($f_mid <= 0.0) $rtb = $x_mid;
1688 public static function XNPV($rate, $values, $dates) {
1694 $valCount = count($values);
1699 for ($i = 0; $i < $valCount; ++$i) {
1726 public static function YIELDDISC($settlement, $maturity, $price, $redemption, $basis=0) {
1734 if (is_numeric($price) && is_numeric($redemption)) {
1735 if (($price <= 0) || ($redemption <= 0)) {
1739 if (!is_numeric($daysPerYear)) {
1740 return $daysPerYear;
1743 if (!is_numeric($daysBetweenSettlementAndMaturity)) {
1745 return $daysBetweenSettlementAndMaturity;
1747 $daysBetweenSettlementAndMaturity *= $daysPerYear;
1749 return (($redemption - $price) / $price) * ($daysPerYear / $daysBetweenSettlementAndMaturity);
1775 public static function YIELDMAT($settlement, $maturity, $issue, $rate, $price, $basis=0) {
1784 if (is_numeric($rate) && is_numeric($price)) {
1785 if (($rate <= 0) || ($price <= 0)) {
1789 if (!is_numeric($daysPerYear)) {
1790 return $daysPerYear;
1793 if (!is_numeric($daysBetweenIssueAndSettlement)) {
1795 return $daysBetweenIssueAndSettlement;
1797 $daysBetweenIssueAndSettlement *= $daysPerYear;
1799 if (!is_numeric($daysBetweenIssueAndMaturity)) {
1801 return $daysBetweenIssueAndMaturity;
1803 $daysBetweenIssueAndMaturity *= $daysPerYear;
1805 if (!is_numeric($daysBetweenSettlementAndMaturity)) {
1807 return $daysBetweenSettlementAndMaturity;
1809 $daysBetweenSettlementAndMaturity *= $daysPerYear;
1811 return ((1 + (($daysBetweenIssueAndMaturity / $daysPerYear) * $rate) - (($price / 100) + (($daysBetweenIssueAndSettlement / $daysPerYear) * $rate))) /
1812 (($price / 100) + (($daysBetweenIssueAndSettlement / $daysPerYear) * $rate))) *
1813 ($daysPerYear / $daysBetweenSettlementAndMaturity);