more extraction of Excel Financial functions (#1989)
* More Financial function extracts, this time looking at the Periodic Cashflow functions * Initial extract of Constant Periodic Interest and Payment functions
This commit is contained in:
parent
063496dbe0
commit
bc18fb7e77
|
|
@ -745,12 +745,12 @@ class Calculation
|
|||
],
|
||||
'CUMIPMT' => [
|
||||
'category' => Category::CATEGORY_FINANCIAL,
|
||||
'functionCall' => [Financial::class, 'CUMIPMT'],
|
||||
'functionCall' => [Financial\CashFlow\Constant\Periodic\Cumulative::class, 'interest'],
|
||||
'argumentCount' => '6',
|
||||
],
|
||||
'CUMPRINC' => [
|
||||
'category' => Category::CATEGORY_FINANCIAL,
|
||||
'functionCall' => [Financial::class, 'CUMPRINC'],
|
||||
'functionCall' => [Financial\CashFlow\Constant\Periodic\Cumulative::class, 'principal'],
|
||||
'argumentCount' => '6',
|
||||
],
|
||||
'DATE' => [
|
||||
|
|
@ -1137,12 +1137,12 @@ class Calculation
|
|||
],
|
||||
'FV' => [
|
||||
'category' => Category::CATEGORY_FINANCIAL,
|
||||
'functionCall' => [Financial::class, 'FV'],
|
||||
'functionCall' => [Financial\CashFlow\Constant\Periodic::class, 'futureValue'],
|
||||
'argumentCount' => '3-5',
|
||||
],
|
||||
'FVSCHEDULE' => [
|
||||
'category' => Category::CATEGORY_FINANCIAL,
|
||||
'functionCall' => [Financial::class, 'FVSCHEDULE'],
|
||||
'functionCall' => [Financial\CashFlow\Single::class, 'futureValue'],
|
||||
'argumentCount' => '2',
|
||||
],
|
||||
'GAMMA' => [
|
||||
|
|
@ -1434,12 +1434,12 @@ class Calculation
|
|||
],
|
||||
'IPMT' => [
|
||||
'category' => Category::CATEGORY_FINANCIAL,
|
||||
'functionCall' => [Financial::class, 'IPMT'],
|
||||
'functionCall' => [Financial\CashFlow\Constant\Periodic\Interest::class, 'payment'],
|
||||
'argumentCount' => '4-6',
|
||||
],
|
||||
'IRR' => [
|
||||
'category' => Category::CATEGORY_FINANCIAL,
|
||||
'functionCall' => [Financial::class, 'IRR'],
|
||||
'functionCall' => [Financial\CashFlow\Variable\Periodic::class, 'rate'],
|
||||
'argumentCount' => '1,2',
|
||||
],
|
||||
'ISBLANK' => [
|
||||
|
|
@ -1506,7 +1506,7 @@ class Calculation
|
|||
],
|
||||
'ISPMT' => [
|
||||
'category' => Category::CATEGORY_FINANCIAL,
|
||||
'functionCall' => [Financial::class, 'ISPMT'],
|
||||
'functionCall' => [Financial\CashFlow\Constant\Periodic\Interest::class, 'schedulePayment'],
|
||||
'argumentCount' => '4',
|
||||
],
|
||||
'ISREF' => [
|
||||
|
|
@ -1691,7 +1691,7 @@ class Calculation
|
|||
],
|
||||
'MIRR' => [
|
||||
'category' => Category::CATEGORY_FINANCIAL,
|
||||
'functionCall' => [Financial::class, 'MIRR'],
|
||||
'functionCall' => [Financial\CashFlow\Variable\Periodic::class, 'modifiedRate'],
|
||||
'argumentCount' => '3',
|
||||
],
|
||||
'MMULT' => [
|
||||
|
|
@ -1826,12 +1826,12 @@ class Calculation
|
|||
],
|
||||
'NPER' => [
|
||||
'category' => Category::CATEGORY_FINANCIAL,
|
||||
'functionCall' => [Financial::class, 'NPER'],
|
||||
'functionCall' => [Financial\CashFlow\Constant\Periodic::class, 'periods'],
|
||||
'argumentCount' => '3-5',
|
||||
],
|
||||
'NPV' => [
|
||||
'category' => Category::CATEGORY_FINANCIAL,
|
||||
'functionCall' => [Financial::class, 'NPV'],
|
||||
'functionCall' => [Financial\CashFlow\Variable\Periodic::class, 'presentValue'],
|
||||
'argumentCount' => '2+',
|
||||
],
|
||||
'NUMBERVALUE' => [
|
||||
|
|
@ -1893,7 +1893,7 @@ class Calculation
|
|||
],
|
||||
'PDURATION' => [
|
||||
'category' => Category::CATEGORY_FINANCIAL,
|
||||
'functionCall' => [Financial::class, 'PDURATION'],
|
||||
'functionCall' => [Financial\CashFlow\Single::class, 'periods'],
|
||||
'argumentCount' => '3',
|
||||
],
|
||||
'PEARSON' => [
|
||||
|
|
@ -1958,7 +1958,7 @@ class Calculation
|
|||
],
|
||||
'PMT' => [
|
||||
'category' => Category::CATEGORY_FINANCIAL,
|
||||
'functionCall' => [Financial::class, 'PMT'],
|
||||
'functionCall' => [Financial\CashFlow\Constant\Periodic\Payments::class, 'annuity'],
|
||||
'argumentCount' => '3-5',
|
||||
],
|
||||
'POISSON' => [
|
||||
|
|
@ -1978,7 +1978,7 @@ class Calculation
|
|||
],
|
||||
'PPMT' => [
|
||||
'category' => Category::CATEGORY_FINANCIAL,
|
||||
'functionCall' => [Financial::class, 'PPMT'],
|
||||
'functionCall' => [Financial\CashFlow\Constant\Periodic\Payments::class, 'interestPayment'],
|
||||
'argumentCount' => '4-6',
|
||||
],
|
||||
'PRICE' => [
|
||||
|
|
@ -2013,7 +2013,7 @@ class Calculation
|
|||
],
|
||||
'PV' => [
|
||||
'category' => Category::CATEGORY_FINANCIAL,
|
||||
'functionCall' => [Financial::class, 'PV'],
|
||||
'functionCall' => [Financial\CashFlow\Constant\Periodic::class, 'presentValue'],
|
||||
'argumentCount' => '3-5',
|
||||
],
|
||||
'QUARTILE' => [
|
||||
|
|
@ -2073,7 +2073,7 @@ class Calculation
|
|||
],
|
||||
'RATE' => [
|
||||
'category' => Category::CATEGORY_FINANCIAL,
|
||||
'functionCall' => [Financial::class, 'RATE'],
|
||||
'functionCall' => [Financial\CashFlow\Constant\Periodic\Interest::class, 'rate'],
|
||||
'argumentCount' => '3-6',
|
||||
],
|
||||
'RECEIVED' => [
|
||||
|
|
@ -2140,7 +2140,7 @@ class Calculation
|
|||
],
|
||||
'RRI' => [
|
||||
'category' => Category::CATEGORY_FINANCIAL,
|
||||
'functionCall' => [Financial::class, 'RRI'],
|
||||
'functionCall' => [Financial\CashFlow\Single::class, 'interestRate'],
|
||||
'argumentCount' => '3',
|
||||
],
|
||||
'RSQ' => [
|
||||
|
|
|
|||
|
|
@ -16,21 +16,6 @@ class Financial
|
|||
|
||||
const FINANCIAL_PRECISION = 1.0e-08;
|
||||
|
||||
private static function interestAndPrincipal($rate = 0, $per = 0, $nper = 0, $pv = 0, $fv = 0, $type = 0)
|
||||
{
|
||||
$pmt = self::PMT($rate, $nper, $pv, $fv, $type);
|
||||
$capital = $pv;
|
||||
$interest = 0;
|
||||
$principal = 0;
|
||||
for ($i = 1; $i <= $per; ++$i) {
|
||||
$interest = ($type && $i == 1) ? 0 : -$capital * $rate;
|
||||
$principal = $pmt - $interest;
|
||||
$capital += $principal;
|
||||
}
|
||||
|
||||
return [$interest, $principal];
|
||||
}
|
||||
|
||||
/**
|
||||
* ACCRINT.
|
||||
*
|
||||
|
|
@ -140,7 +125,8 @@ class Financial
|
|||
*
|
||||
* @Deprecated 1.18.0
|
||||
*
|
||||
* @see Use the AMORDEGRC() method in the Financial\Amortization class instead
|
||||
* @see Financial\Amortization::AMORDEGRC()
|
||||
* Use the AMORDEGRC() method in the Financial\Amortization class instead
|
||||
*
|
||||
* @param float $cost The cost of the asset
|
||||
* @param mixed $purchased Date of the purchase of the asset
|
||||
|
|
@ -174,7 +160,8 @@ class Financial
|
|||
*
|
||||
* @Deprecated 1.18.0
|
||||
*
|
||||
* @see Use the AMORLINC() method in the Financial\Amortization class instead
|
||||
* @see Financial\Amortization::AMORLINC()
|
||||
* Use the AMORLINC() method in the Financial\Amortization class instead
|
||||
*
|
||||
* @param float $cost The cost of the asset
|
||||
* @param mixed $purchased Date of the purchase of the asset
|
||||
|
|
@ -206,7 +193,8 @@ class Financial
|
|||
*
|
||||
* @Deprecated 1.18.0
|
||||
*
|
||||
* @see Use the COUPDAYBS() method in the Financial\Coupons class instead
|
||||
* @see Financial\Coupons::COUPDAYBS()
|
||||
* Use the COUPDAYBS() method in the Financial\Coupons class instead
|
||||
*
|
||||
* @param mixed $settlement The security's settlement date.
|
||||
* The security settlement date is the date after the issue
|
||||
|
|
@ -242,7 +230,8 @@ class Financial
|
|||
*
|
||||
* @Deprecated 1.18.0
|
||||
*
|
||||
* @see Use the COUPDAYS() method in the Financial\Coupons class instead
|
||||
* @see Financial\Coupons::COUPDAYS()
|
||||
* Use the COUPDAYS() method in the Financial\Coupons class instead
|
||||
*
|
||||
* @param mixed $settlement The security's settlement date.
|
||||
* The security settlement date is the date after the issue
|
||||
|
|
@ -278,7 +267,8 @@ class Financial
|
|||
*
|
||||
* @Deprecated 1.18.0
|
||||
*
|
||||
* @see Use the COUPDAYSNC() method in the Financial\Coupons class instead
|
||||
* @see Financial\Coupons::COUPDAYSNC()
|
||||
* Use the COUPDAYSNC() method in the Financial\Coupons class instead
|
||||
*
|
||||
* @param mixed $settlement The security's settlement date.
|
||||
* The security settlement date is the date after the issue
|
||||
|
|
@ -314,7 +304,8 @@ class Financial
|
|||
*
|
||||
* @Deprecated 1.18.0
|
||||
*
|
||||
* @see Use the COUPNCD() method in the Financial\Coupons class instead
|
||||
* @see Financial\Coupons::COUPNCD()
|
||||
* Use the COUPNCD() method in the Financial\Coupons class instead
|
||||
*
|
||||
* @param mixed $settlement The security's settlement date.
|
||||
* The security settlement date is the date after the issue
|
||||
|
|
@ -352,7 +343,8 @@ class Financial
|
|||
*
|
||||
* @Deprecated 1.18.0
|
||||
*
|
||||
* @see Use the COUPNUM() method in the Financial\Coupons class instead
|
||||
* @see Financial\Coupons::COUPNUM()
|
||||
* Use the COUPNUM() method in the Financial\Coupons class instead
|
||||
*
|
||||
* @param mixed $settlement The security's settlement date.
|
||||
* The security settlement date is the date after the issue
|
||||
|
|
@ -388,7 +380,8 @@ class Financial
|
|||
*
|
||||
* @Deprecated 1.18.0
|
||||
*
|
||||
* @see Use the COUPPCD() method in the Financial\Coupons class instead
|
||||
* @see Financial\Coupons::COUPPCD()
|
||||
* Use the COUPPCD() method in the Financial\Coupons class instead
|
||||
*
|
||||
* @param mixed $settlement The security's settlement date.
|
||||
* The security settlement date is the date after the issue
|
||||
|
|
@ -423,47 +416,26 @@ class Financial
|
|||
* Excel Function:
|
||||
* CUMIPMT(rate,nper,pv,start,end[,type])
|
||||
*
|
||||
* @Deprecated 1.18.0
|
||||
*
|
||||
* @see Financial\CashFlow\Constant\Periodic\Cumulative::interest()
|
||||
* Use the interest() method in the Financial\CashFlow\Constant\Periodic\Cumulative class instead
|
||||
*
|
||||
* @param float $rate The Interest rate
|
||||
* @param int $nper The total number of payment periods
|
||||
* @param float $pv Present Value
|
||||
* @param int $start The first period in the calculation.
|
||||
* Payment periods are numbered beginning with 1.
|
||||
* Payment periods are numbered beginning with 1.
|
||||
* @param int $end the last period in the calculation
|
||||
* @param int $type A number 0 or 1 and indicates when payments are due:
|
||||
* 0 or omitted At the end of the period.
|
||||
* 1 At the beginning of the period.
|
||||
* 0 or omitted At the end of the period.
|
||||
* 1 At the beginning of the period.
|
||||
*
|
||||
* @return float|string
|
||||
*/
|
||||
public static function CUMIPMT($rate, $nper, $pv, $start, $end, $type = 0)
|
||||
{
|
||||
$rate = Functions::flattenSingleValue($rate);
|
||||
$nper = (int) Functions::flattenSingleValue($nper);
|
||||
$pv = Functions::flattenSingleValue($pv);
|
||||
$start = (int) Functions::flattenSingleValue($start);
|
||||
$end = (int) Functions::flattenSingleValue($end);
|
||||
$type = (int) Functions::flattenSingleValue($type);
|
||||
|
||||
// Validate parameters
|
||||
if ($type != 0 && $type != 1) {
|
||||
return Functions::NAN();
|
||||
}
|
||||
if ($start < 1 || $start > $end) {
|
||||
return Functions::VALUE();
|
||||
}
|
||||
|
||||
// Calculate
|
||||
$interest = 0;
|
||||
for ($per = $start; $per <= $end; ++$per) {
|
||||
$ipmt = self::IPMT($rate, $per, $nper, $pv, 0, $type);
|
||||
if (is_string($ipmt)) {
|
||||
return $ipmt;
|
||||
}
|
||||
|
||||
$interest += $ipmt;
|
||||
}
|
||||
|
||||
return $interest;
|
||||
return Financial\CashFlow\Constant\Periodic\Cumulative::interest($rate, $nper, $pv, $start, $end, $type);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -474,47 +446,26 @@ class Financial
|
|||
* Excel Function:
|
||||
* CUMPRINC(rate,nper,pv,start,end[,type])
|
||||
*
|
||||
* @Deprecated 1.18.0
|
||||
*
|
||||
* @see Financial\CashFlow\Constant\Periodic\Cumulative::principal()
|
||||
* Use the principal() method in the Financial\CashFlow\Constant\Periodic\Cumulative class instead
|
||||
*
|
||||
* @param float $rate The Interest rate
|
||||
* @param int $nper The total number of payment periods
|
||||
* @param float $pv Present Value
|
||||
* @param int $start The first period in the calculation.
|
||||
* Payment periods are numbered beginning with 1.
|
||||
* Payment periods are numbered beginning with 1.
|
||||
* @param int $end the last period in the calculation
|
||||
* @param int $type A number 0 or 1 and indicates when payments are due:
|
||||
* 0 or omitted At the end of the period.
|
||||
* 1 At the beginning of the period.
|
||||
* 0 or omitted At the end of the period.
|
||||
* 1 At the beginning of the period.
|
||||
*
|
||||
* @return float|string
|
||||
*/
|
||||
public static function CUMPRINC($rate, $nper, $pv, $start, $end, $type = 0)
|
||||
{
|
||||
$rate = Functions::flattenSingleValue($rate);
|
||||
$nper = (int) Functions::flattenSingleValue($nper);
|
||||
$pv = Functions::flattenSingleValue($pv);
|
||||
$start = (int) Functions::flattenSingleValue($start);
|
||||
$end = (int) Functions::flattenSingleValue($end);
|
||||
$type = (int) Functions::flattenSingleValue($type);
|
||||
|
||||
// Validate parameters
|
||||
if ($type != 0 && $type != 1) {
|
||||
return Functions::NAN();
|
||||
}
|
||||
if ($start < 1 || $start > $end) {
|
||||
return Functions::VALUE();
|
||||
}
|
||||
|
||||
// Calculate
|
||||
$principal = 0;
|
||||
for ($per = $start; $per <= $end; ++$per) {
|
||||
$ppmt = self::PPMT($rate, $per, $nper, $pv, 0, $type);
|
||||
if (is_string($ppmt)) {
|
||||
return $ppmt;
|
||||
}
|
||||
|
||||
$principal += $ppmt;
|
||||
}
|
||||
|
||||
return $principal;
|
||||
return Financial\CashFlow\Constant\Periodic\Cumulative::principal($rate, $nper, $pv, $start, $end, $type);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -532,7 +483,8 @@ class Financial
|
|||
*
|
||||
* @Deprecated 1.18.0
|
||||
*
|
||||
* @see Use the DB() method in the Financial\Depreciation class instead
|
||||
* @see Financial\Depreciation::DB()
|
||||
* Use the DB() method in the Financial\Depreciation class instead
|
||||
*
|
||||
* @param float $cost Initial cost of the asset
|
||||
* @param float $salvage Value at the end of the depreciation.
|
||||
|
|
@ -562,7 +514,8 @@ class Financial
|
|||
*
|
||||
* @Deprecated 1.18.0
|
||||
*
|
||||
* @see Use the DDB() method in the Financial\Depreciation class instead
|
||||
* @see Financial\Depreciation::DDB()
|
||||
* Use the DDB() method in the Financial\Depreciation class instead
|
||||
*
|
||||
* @param float $cost Initial cost of the asset
|
||||
* @param float $salvage Value at the end of the depreciation.
|
||||
|
|
@ -646,7 +599,8 @@ class Financial
|
|||
*
|
||||
* @Deprecated 1.18.0
|
||||
*
|
||||
* @see Use the decimal() method in the Financial\Dollar class instead
|
||||
* @see Financial\Dollar::decimal()
|
||||
* Use the decimal() method in the Financial\Dollar class instead
|
||||
*
|
||||
* @param float $fractional_dollar Fractional Dollar
|
||||
* @param int $fraction Fraction
|
||||
|
|
@ -670,7 +624,8 @@ class Financial
|
|||
*
|
||||
* @Deprecated 1.18.0
|
||||
*
|
||||
* @see Use the fractional() method in the Financial\Dollar class instead
|
||||
* @see Financial\Dollar::fractional()
|
||||
* Use the fractional() method in the Financial\Dollar class instead
|
||||
*
|
||||
* @param float $decimal_dollar Decimal Dollar
|
||||
* @param int $fraction Fraction
|
||||
|
|
@ -693,7 +648,8 @@ class Financial
|
|||
*
|
||||
* @Deprecated 1.18.0
|
||||
*
|
||||
* @see Use the effective() method in the Financial\InterestRate class instead
|
||||
* @see Financial\InterestRate::effective()
|
||||
* Use the effective() method in the Financial\InterestRate class instead
|
||||
*
|
||||
* @param float $nominalRate Nominal interest rate
|
||||
* @param int $periodsPerYear Number of compounding payments per year
|
||||
|
|
@ -713,6 +669,11 @@ class Financial
|
|||
* Excel Function:
|
||||
* FV(rate,nper,pmt[,pv[,type]])
|
||||
*
|
||||
* @Deprecated 1.18.0
|
||||
*
|
||||
* @see Financial\CashFlow\Constant\Periodic::futureValue()
|
||||
* Use the futureValue() method in the Financial\CashFlow\Constant\Periodic class instead
|
||||
*
|
||||
* @param float $rate The interest rate per period
|
||||
* @param int $nper Total number of payment periods in an annuity
|
||||
* @param float $pmt The payment made each period: it cannot change over the
|
||||
|
|
@ -728,23 +689,7 @@ class Financial
|
|||
*/
|
||||
public static function FV($rate = 0, $nper = 0, $pmt = 0, $pv = 0, $type = 0)
|
||||
{
|
||||
$rate = Functions::flattenSingleValue($rate);
|
||||
$nper = Functions::flattenSingleValue($nper);
|
||||
$pmt = Functions::flattenSingleValue($pmt);
|
||||
$pv = Functions::flattenSingleValue($pv);
|
||||
$type = Functions::flattenSingleValue($type);
|
||||
|
||||
// Validate parameters
|
||||
if ($type != 0 && $type != 1) {
|
||||
return Functions::NAN();
|
||||
}
|
||||
|
||||
// Calculate
|
||||
if ($rate !== null && $rate != 0) {
|
||||
return -$pv * (1 + $rate) ** $nper - $pmt * (1 + $rate * $type) * ((1 + $rate) ** $nper - 1) / $rate;
|
||||
}
|
||||
|
||||
return -$pv - $pmt * $nper;
|
||||
return Financial\CashFlow\Constant\Periodic::futureValue($rate, $nper, $pmt, $pv, $type);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -825,11 +770,17 @@ class Financial
|
|||
/**
|
||||
* IPMT.
|
||||
*
|
||||
* Returns the interest payment for a given period for an investment based on periodic, constant payments and a constant interest rate.
|
||||
* Returns the interest payment for a given period for an investment based on periodic, constant payments
|
||||
* and a constant interest rate.
|
||||
*
|
||||
* Excel Function:
|
||||
* IPMT(rate,per,nper,pv[,fv][,type])
|
||||
*
|
||||
* @Deprecated 1.18.0
|
||||
*
|
||||
* @see Financial\CashFlow\Constant\Periodic\Interest::payment()
|
||||
* Use the payment() method in the Financial\CashFlow\Constant\Periodic class instead
|
||||
*
|
||||
* @param float $rate Interest rate per period
|
||||
* @param int $per Period for which we want to find the interest
|
||||
* @param int $nper Number of periods
|
||||
|
|
@ -841,25 +792,7 @@ class Financial
|
|||
*/
|
||||
public static function IPMT($rate, $per, $nper, $pv, $fv = 0, $type = 0)
|
||||
{
|
||||
$rate = Functions::flattenSingleValue($rate);
|
||||
$per = (int) Functions::flattenSingleValue($per);
|
||||
$nper = (int) Functions::flattenSingleValue($nper);
|
||||
$pv = Functions::flattenSingleValue($pv);
|
||||
$fv = Functions::flattenSingleValue($fv);
|
||||
$type = (int) Functions::flattenSingleValue($type);
|
||||
|
||||
// Validate parameters
|
||||
if ($type != 0 && $type != 1) {
|
||||
return Functions::NAN();
|
||||
}
|
||||
if ($per <= 0 || $per > $nper) {
|
||||
return Functions::NAN();
|
||||
}
|
||||
|
||||
// Calculate
|
||||
$interestAndPrincipal = self::interestAndPrincipal($rate, $per, $nper, $pv, $fv, $type);
|
||||
|
||||
return $interestAndPrincipal[0];
|
||||
return Financial\CashFlow\Constant\Periodic\Interest::payment($rate, $per, $nper, $pv, $fv, $type);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -876,6 +809,9 @@ class Financial
|
|||
*
|
||||
* @Deprecated 1.18.0
|
||||
*
|
||||
* @see Financial\CashFlow\Variable\Periodic::rate()
|
||||
* Use the rate() method in the Financial\CashFlow\Variable\Periodic class instead
|
||||
*
|
||||
* @param mixed $values An array or a reference to cells that contain numbers for which you want
|
||||
* to calculate the internal rate of return.
|
||||
* Values must contain at least one positive value and one negative value to
|
||||
|
|
@ -883,9 +819,6 @@ class Financial
|
|||
* @param mixed $guess A number that you guess is close to the result of IRR
|
||||
*
|
||||
* @return float|string
|
||||
*
|
||||
*@see Financial\CashFlow\Variable\Periodic::rate()
|
||||
* Use the IRR() method in the Financial\CashFlow\Variable\Periodic class instead
|
||||
*/
|
||||
public static function IRR($values, $guess = 0.1)
|
||||
{
|
||||
|
|
@ -898,7 +831,12 @@ class Financial
|
|||
* Returns the interest payment for an investment based on an interest rate and a constant payment schedule.
|
||||
*
|
||||
* Excel Function:
|
||||
* =ISPMT(interest_rate, period, number_payments, PV)
|
||||
* =ISPMT(interest_rate, period, number_payments, pv)
|
||||
*
|
||||
* @Deprecated 1.18.0
|
||||
*
|
||||
* @see Financial\CashFlow\Constant\Periodic\Interest::schedulePayment()
|
||||
* Use the schedulePayment() method in the Financial\CashFlow\Constant\Periodic class instead
|
||||
*
|
||||
* interest_rate is the interest rate for the investment
|
||||
*
|
||||
|
|
@ -906,32 +844,11 @@ class Financial
|
|||
*
|
||||
* number_payments is the number of payments for the annuity
|
||||
*
|
||||
* PV is the loan amount or present value of the payments
|
||||
* pv is the loan amount or present value of the payments
|
||||
*/
|
||||
public static function ISPMT(...$args)
|
||||
{
|
||||
// Return value
|
||||
$returnValue = 0;
|
||||
|
||||
// Get the parameters
|
||||
$aArgs = Functions::flattenArray($args);
|
||||
$interestRate = array_shift($aArgs);
|
||||
$period = array_shift($aArgs);
|
||||
$numberPeriods = array_shift($aArgs);
|
||||
$principleRemaining = array_shift($aArgs);
|
||||
|
||||
// Calculate
|
||||
$principlePayment = ($principleRemaining * 1.0) / ($numberPeriods * 1.0);
|
||||
for ($i = 0; $i <= $period; ++$i) {
|
||||
$returnValue = $interestRate * $principleRemaining * -1;
|
||||
$principleRemaining -= $principlePayment;
|
||||
// principle needs to be 0 after the last payment, don't let floating point screw it up
|
||||
if ($i == $numberPeriods) {
|
||||
$returnValue = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return $returnValue;
|
||||
return Financial\CashFlow\Constant\Periodic\Interest::schedulePayment(...$args);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -946,7 +863,7 @@ class Financial
|
|||
* @Deprecated 1.18.0
|
||||
*
|
||||
* @see Financial\CashFlow\Variable\Periodic::modifiedRate()
|
||||
* Use the MIRR() method in the Financial\CashFlow\Variable\Periodic class instead
|
||||
* Use the modifiedRate() method in the Financial\CashFlow\Variable\Periodic class instead
|
||||
*
|
||||
* @param mixed $values An array or a reference to cells that contain a series of payments and
|
||||
* income occurring at regular intervals.
|
||||
|
|
@ -971,7 +888,8 @@ class Financial
|
|||
*
|
||||
* @Deprecated 1.18.0
|
||||
*
|
||||
* @see Use the nominal() method in the Financial\InterestRate class instead
|
||||
* @see Financial\InterestRate::nominal()
|
||||
* Use the nominal() method in the Financial\InterestRate class instead
|
||||
*
|
||||
* @param float $effectiveRate Effective interest rate
|
||||
* @param int $periodsPerYear Number of compounding payments per year
|
||||
|
|
@ -988,6 +906,8 @@ class Financial
|
|||
*
|
||||
* Returns the number of periods for a cash flow with constant periodic payments (annuities), and interest rate.
|
||||
*
|
||||
* @Deprecated 1.18.0
|
||||
*
|
||||
* @param float $rate Interest rate per period
|
||||
* @param int $pmt Periodic payment (annuity)
|
||||
* @param float $pv Present Value
|
||||
|
|
@ -995,33 +915,13 @@ class Financial
|
|||
* @param int $type Payment type: 0 = at the end of each period, 1 = at the beginning of each period
|
||||
*
|
||||
* @return float|string Result, or a string containing an error
|
||||
*
|
||||
*@see Financial\CashFlow\Constant\Periodic::periods()
|
||||
* Use the periods() method in the Financial\CashFlow\Constant\Periodic class instead
|
||||
*/
|
||||
public static function NPER($rate = 0, $pmt = 0, $pv = 0, $fv = 0, $type = 0)
|
||||
{
|
||||
$rate = Functions::flattenSingleValue($rate);
|
||||
$pmt = Functions::flattenSingleValue($pmt);
|
||||
$pv = Functions::flattenSingleValue($pv);
|
||||
$fv = Functions::flattenSingleValue($fv);
|
||||
$type = Functions::flattenSingleValue($type);
|
||||
|
||||
// Validate parameters
|
||||
if ($type != 0 && $type != 1) {
|
||||
return Functions::NAN();
|
||||
}
|
||||
|
||||
// Calculate
|
||||
if ($rate !== null && $rate != 0) {
|
||||
if ($pmt == 0 && $pv == 0) {
|
||||
return Functions::NAN();
|
||||
}
|
||||
|
||||
return log(($pmt * (1 + $rate * $type) / $rate - $fv) / ($pv + $pmt * (1 + $rate * $type) / $rate)) / log(1 + $rate);
|
||||
}
|
||||
if ($pmt == 0) {
|
||||
return Functions::NAN();
|
||||
}
|
||||
|
||||
return (-$pv - $fv) / $pmt;
|
||||
return Financial\CashFlow\Constant\Periodic::periods($rate, $pmt, $pv, $fv, $type);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1031,10 +931,10 @@ class Financial
|
|||
*
|
||||
* @Deprecated 1.18.0
|
||||
*
|
||||
* @return float
|
||||
* @see Financial\CashFlow\Variable\Periodic::presentValue()
|
||||
* Use the presentValue() method in the Financial\CashFlow\Variable\Periodic class instead
|
||||
*
|
||||
*@see Financial\CashFlow\Variable\Periodic::presentValue()
|
||||
* Use the NPV() method in the Financial\CashFlow\Variable\Periodic class instead
|
||||
* @return float
|
||||
*/
|
||||
public static function NPV(...$args)
|
||||
{
|
||||
|
|
@ -1067,6 +967,11 @@ class Financial
|
|||
*
|
||||
* Returns the constant payment (annuity) for a cash flow with a constant interest rate.
|
||||
*
|
||||
* @Deprecated 1.18.0
|
||||
*
|
||||
* @see Financial\CashFlow\Constant\Periodic\Payments::annuity()
|
||||
* Use the annuity() method in the Financial\CashFlow\Constant\Periodic\Payments class instead
|
||||
*
|
||||
* @param float $rate Interest rate per period
|
||||
* @param int $nper Number of periods
|
||||
* @param float $pv Present Value
|
||||
|
|
@ -1077,29 +982,19 @@ class Financial
|
|||
*/
|
||||
public static function PMT($rate = 0, $nper = 0, $pv = 0, $fv = 0, $type = 0)
|
||||
{
|
||||
$rate = Functions::flattenSingleValue($rate);
|
||||
$nper = Functions::flattenSingleValue($nper);
|
||||
$pv = Functions::flattenSingleValue($pv);
|
||||
$fv = Functions::flattenSingleValue($fv);
|
||||
$type = Functions::flattenSingleValue($type);
|
||||
|
||||
// Validate parameters
|
||||
if ($type != 0 && $type != 1) {
|
||||
return Functions::NAN();
|
||||
}
|
||||
|
||||
// Calculate
|
||||
if ($rate !== null && $rate != 0) {
|
||||
return (-$fv - $pv * (1 + $rate) ** $nper) / (1 + $rate * $type) / (((1 + $rate) ** $nper - 1) / $rate);
|
||||
}
|
||||
|
||||
return (-$pv - $fv) / $nper;
|
||||
return Financial\CashFlow\Constant\Periodic\Payments::annuity($rate, $nper, $pv, $fv, $type);
|
||||
}
|
||||
|
||||
/**
|
||||
* PPMT.
|
||||
*
|
||||
* Returns the interest payment for a given period for an investment based on periodic, constant payments and a constant interest rate.
|
||||
* Returns the interest payment for a given period for an investment based on periodic, constant payments
|
||||
* and a constant interest rate.
|
||||
*
|
||||
* @Deprecated 1.18.0
|
||||
*
|
||||
* @see Financial\CashFlow\Constant\Periodic\Payments::interestPayment()
|
||||
* Use the interestPayment() method in the Financial\CashFlow\Constant\Periodic\Payments class instead
|
||||
*
|
||||
* @param float $rate Interest rate per period
|
||||
* @param int $per Period for which we want to find the interest
|
||||
|
|
@ -1112,25 +1007,7 @@ class Financial
|
|||
*/
|
||||
public static function PPMT($rate, $per, $nper, $pv, $fv = 0, $type = 0)
|
||||
{
|
||||
$rate = Functions::flattenSingleValue($rate);
|
||||
$per = (int) Functions::flattenSingleValue($per);
|
||||
$nper = (int) Functions::flattenSingleValue($nper);
|
||||
$pv = Functions::flattenSingleValue($pv);
|
||||
$fv = Functions::flattenSingleValue($fv);
|
||||
$type = (int) Functions::flattenSingleValue($type);
|
||||
|
||||
// Validate parameters
|
||||
if ($type != 0 && $type != 1) {
|
||||
return Functions::NAN();
|
||||
}
|
||||
if ($per <= 0 || $per > $nper) {
|
||||
return Functions::NAN();
|
||||
}
|
||||
|
||||
// Calculate
|
||||
$interestAndPrincipal = self::interestAndPrincipal($rate, $per, $nper, $pv, $fv, $type);
|
||||
|
||||
return $interestAndPrincipal[1];
|
||||
return Financial\CashFlow\Constant\Periodic\Payments::interestPayment($rate, $per, $nper, $pv, $fv, $type);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1140,7 +1017,8 @@ class Financial
|
|||
*
|
||||
* @Deprecated 1.18.0
|
||||
*
|
||||
* @see Use the price() method in the Financial\Securities\Price class instead
|
||||
* @see Financial\Securities\Price::price()
|
||||
* Use the price() method in the Financial\Securities\Price class instead
|
||||
*
|
||||
* @param mixed $settlement The security's settlement date.
|
||||
* The security settlement date is the date after the issue date when the security
|
||||
|
|
@ -1175,7 +1053,8 @@ class Financial
|
|||
*
|
||||
* @Deprecated 1.18.0
|
||||
*
|
||||
* @see Use the priceDiscounted() method in the Financial\Securities\Price class instead
|
||||
* @see Financial\Securities\Price::priceDiscounted()
|
||||
* Use the priceDiscounted() method in the Financial\Securities\Price class instead
|
||||
*
|
||||
* @param mixed $settlement The security's settlement date.
|
||||
* The security settlement date is the date after the issue date when the security
|
||||
|
|
@ -1205,7 +1084,8 @@ class Financial
|
|||
*
|
||||
* @Deprecated 1.18.0
|
||||
*
|
||||
* @see Use the priceAtMaturity() method in the Financial\Securities\Price class instead
|
||||
* @see Financial\Securities\Price::priceAtMaturity()
|
||||
* Use the priceAtMaturity() method in the Financial\Securities\Price class instead
|
||||
*
|
||||
* @param mixed $settlement The security's settlement date.
|
||||
* The security's settlement date is the date after the issue date when the security
|
||||
|
|
@ -1234,6 +1114,11 @@ class Financial
|
|||
*
|
||||
* Returns the Present Value of a cash flow with constant payments and interest rate (annuities).
|
||||
*
|
||||
* @Deprecated 1.18.0
|
||||
*
|
||||
* @see Financial\CashFlow\Constant\Periodic::presentValue()
|
||||
* Use the presentValue() method in the Financial\CashFlow\Constant\Periodic class instead
|
||||
*
|
||||
* @param float $rate Interest rate per period
|
||||
* @param int $nper Number of periods
|
||||
* @param float $pmt Periodic payment (annuity)
|
||||
|
|
@ -1244,23 +1129,7 @@ class Financial
|
|||
*/
|
||||
public static function PV($rate = 0, $nper = 0, $pmt = 0, $fv = 0, $type = 0)
|
||||
{
|
||||
$rate = Functions::flattenSingleValue($rate);
|
||||
$nper = Functions::flattenSingleValue($nper);
|
||||
$pmt = Functions::flattenSingleValue($pmt);
|
||||
$fv = Functions::flattenSingleValue($fv);
|
||||
$type = Functions::flattenSingleValue($type);
|
||||
|
||||
// Validate parameters
|
||||
if ($type != 0 && $type != 1) {
|
||||
return Functions::NAN();
|
||||
}
|
||||
|
||||
// Calculate
|
||||
if ($rate !== null && $rate != 0) {
|
||||
return (-$pmt * (1 + $rate * $type) * (((1 + $rate) ** $nper - 1) / $rate) - $fv) / (1 + $rate) ** $nper;
|
||||
}
|
||||
|
||||
return -$fv - $pmt * $nper;
|
||||
return Financial\CashFlow\Constant\Periodic::presentValue($rate, $nper, $pmt, $fv, $type);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1274,6 +1143,11 @@ class Financial
|
|||
* Excel Function:
|
||||
* RATE(nper,pmt,pv[,fv[,type[,guess]]])
|
||||
*
|
||||
* @Deprecated 1.18.0
|
||||
*
|
||||
* @see Financial\CashFlow\Constant\Periodic\Interest::rate()
|
||||
* Use the rate() method in the Financial\CashFlow\Constant\Periodic class instead
|
||||
*
|
||||
* @param mixed $nper The total number of payment periods in an annuity
|
||||
* @param mixed $pmt The payment made each period and cannot change over the life
|
||||
* of the annuity.
|
||||
|
|
@ -1294,47 +1168,7 @@ class Financial
|
|||
*/
|
||||
public static function RATE($nper, $pmt, $pv, $fv = 0.0, $type = 0, $guess = 0.1)
|
||||
{
|
||||
$nper = (int) Functions::flattenSingleValue($nper);
|
||||
$pmt = Functions::flattenSingleValue($pmt);
|
||||
$pv = Functions::flattenSingleValue($pv);
|
||||
$fv = ($fv === null) ? 0.0 : Functions::flattenSingleValue($fv);
|
||||
$type = ($type === null) ? 0 : (int) Functions::flattenSingleValue($type);
|
||||
$guess = ($guess === null) ? 0.1 : Functions::flattenSingleValue($guess);
|
||||
|
||||
$rate = $guess;
|
||||
// rest of code adapted from python/numpy
|
||||
$close = false;
|
||||
$iter = 0;
|
||||
while (!$close && $iter < self::FINANCIAL_MAX_ITERATIONS) {
|
||||
$nextdiff = self::rateNextGuess($rate, $nper, $pmt, $pv, $fv, $type);
|
||||
if (!is_numeric($nextdiff)) {
|
||||
break;
|
||||
}
|
||||
$rate1 = $rate - $nextdiff;
|
||||
$close = abs($rate1 - $rate) < self::FINANCIAL_PRECISION;
|
||||
++$iter;
|
||||
$rate = $rate1;
|
||||
}
|
||||
|
||||
return $close ? $rate : Functions::NAN();
|
||||
}
|
||||
|
||||
private static function rateNextGuess($rate, $nper, $pmt, $pv, $fv, $type)
|
||||
{
|
||||
if ($rate == 0) {
|
||||
return Functions::NAN();
|
||||
}
|
||||
$tt1 = ($rate + 1) ** $nper;
|
||||
$tt2 = ($rate + 1) ** ($nper - 1);
|
||||
$numerator = $fv + $tt1 * $pv + $pmt * ($tt1 - 1) * ($rate * $type + 1) / $rate;
|
||||
$denominator = $nper * $tt2 * $pv - $pmt * ($tt1 - 1) * ($rate * $type + 1) / ($rate * $rate)
|
||||
+ $nper * $pmt * $tt2 * ($rate * $type + 1) / $rate
|
||||
+ $pmt * ($tt1 - 1) * $type / $rate;
|
||||
if ($denominator == 0) {
|
||||
return Functions::NAN();
|
||||
}
|
||||
|
||||
return $numerator / $denominator;
|
||||
return Financial\CashFlow\Constant\Periodic\Interest::rate($nper, $pmt, $pv, $fv, $type, $guess);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1343,17 +1177,18 @@ class Financial
|
|||
* Returns the price per $100 face value of a discounted security.
|
||||
*
|
||||
* @param mixed $settlement The security's settlement date.
|
||||
* The security settlement date is the date after the issue date when the security is traded to the buyer.
|
||||
* The security settlement date is the date after the issue date when the security
|
||||
* is traded to the buyer.
|
||||
* @param mixed $maturity The security's maturity date.
|
||||
* The maturity date is the date when the security expires.
|
||||
* The maturity date is the date when the security expires.
|
||||
* @param mixed $investment The amount invested in the security
|
||||
* @param mixed $discount The security's discount rate
|
||||
* @param mixed $basis The type of day count to use.
|
||||
* 0 or omitted US (NASD) 30/360
|
||||
* 1 Actual/actual
|
||||
* 2 Actual/360
|
||||
* 3 Actual/365
|
||||
* 4 European 30/360
|
||||
* 0 or omitted US (NASD) 30/360
|
||||
* 1 Actual/actual
|
||||
* 2 Actual/360
|
||||
* 3 Actual/365
|
||||
* 4 European 30/360
|
||||
*
|
||||
* @return float|string Result, or a string containing an error
|
||||
*/
|
||||
|
|
@ -1410,7 +1245,8 @@ class Financial
|
|||
*
|
||||
* @Deprecated 1.18.0
|
||||
*
|
||||
* @see Use the SLN() method in the Financial\Depreciation class instead
|
||||
* @see Financial\Depreciation::SLN()
|
||||
* Use the SLN() method in the Financial\Depreciation class instead
|
||||
*
|
||||
* @param mixed $cost Initial cost of the asset
|
||||
* @param mixed $salvage Value at the end of the depreciation
|
||||
|
|
@ -1430,7 +1266,8 @@ class Financial
|
|||
*
|
||||
* @Deprecated 1.18.0
|
||||
*
|
||||
* @see Use the SYD() method in the Financial\Depreciation class instead
|
||||
* @see Financial\Depreciation::SYD()
|
||||
* Use the SYD() method in the Financial\Depreciation class instead
|
||||
*
|
||||
* @param mixed $cost Initial cost of the asset
|
||||
* @param mixed $salvage Value at the end of the depreciation
|
||||
|
|
@ -1451,10 +1288,12 @@ class Financial
|
|||
*
|
||||
* @Deprecated 1.18.0
|
||||
*
|
||||
* @see Use the bondEquivalentYield() method in the Financial\TreasuryBill class instead
|
||||
* @see Financial\TreasuryBill::bondEquivalentYield()
|
||||
* Use the bondEquivalentYield() method in the Financial\TreasuryBill class instead
|
||||
*
|
||||
* @param mixed $settlement The Treasury bill's settlement date.
|
||||
* The Treasury bill's settlement date is the date after the issue date when the Treasury bill is traded to the buyer.
|
||||
* The Treasury bill's settlement date is the date after the issue date when the
|
||||
* Treasury bill is traded to the buyer.
|
||||
* @param mixed $maturity The Treasury bill's maturity date.
|
||||
* The maturity date is the date when the Treasury bill expires.
|
||||
* @param int $discount The Treasury bill's discount rate
|
||||
|
|
@ -1473,7 +1312,8 @@ class Financial
|
|||
*
|
||||
* @Deprecated 1.18.0
|
||||
*
|
||||
* @see Use the price() method in the Financial\TreasuryBill class instead
|
||||
* @see Financial\TreasuryBill::price()
|
||||
* Use the price() method in the Financial\TreasuryBill class instead
|
||||
*
|
||||
* @param mixed $settlement The Treasury bill's settlement date.
|
||||
* The Treasury bill's settlement date is the date after the issue date
|
||||
|
|
@ -1496,7 +1336,8 @@ class Financial
|
|||
*
|
||||
* @Deprecated 1.18.0
|
||||
*
|
||||
* @see Use the yield() method in the Financial\TreasuryBill class instead
|
||||
* @see Financial\TreasuryBill::yield()
|
||||
* Use the yield() method in the Financial\TreasuryBill class instead
|
||||
*
|
||||
* @param mixed $settlement The Treasury bill's settlement date.
|
||||
* The Treasury bill's settlement date is the date after the issue date
|
||||
|
|
@ -1554,13 +1395,15 @@ class Financial
|
|||
* Use the presentValue() method in the Financial\CashFlow\Variable\NonPeriodic class instead
|
||||
*
|
||||
* @param float $rate the discount rate to apply to the cash flows
|
||||
* @param float[] $values A series of cash flows that corresponds to a schedule of payments in dates.
|
||||
* The first payment is optional and corresponds to a cost or payment that occurs at the beginning of the investment.
|
||||
* If the first value is a cost or payment, it must be a negative value. All succeeding payments are discounted based on a 365-day year.
|
||||
* The series of values must contain at least one positive value and one negative value.
|
||||
* @param mixed[] $dates A schedule of payment dates that corresponds to the cash flow payments.
|
||||
* The first payment date indicates the beginning of the schedule of payments.
|
||||
* All other dates must be later than this date, but they may occur in any order.
|
||||
* @param float[] $values A series of cash flows that corresponds to a schedule of payments in dates.
|
||||
* The first payment is optional and corresponds to a cost or payment that occurs
|
||||
* at the beginning of the investment.
|
||||
* If the first value is a cost or payment, it must be a negative value.
|
||||
* All succeeding payments are discounted based on a 365-day year.
|
||||
* The series of values must contain at least one positive value and one negative value.
|
||||
* @param mixed[] $dates A schedule of payment dates that corresponds to the cash flow payments.
|
||||
* The first payment date indicates the beginning of the schedule of payments.
|
||||
* All other dates must be later than this date, but they may occur in any order.
|
||||
*
|
||||
* @return float|mixed|string
|
||||
*/
|
||||
|
|
@ -1619,11 +1462,11 @@ class Financial
|
|||
* @param int $rate The security's interest rate at date of issue
|
||||
* @param int $price The security's price per $100 face value
|
||||
* @param int $basis The type of day count to use.
|
||||
* 0 or omitted US (NASD) 30/360
|
||||
* 1 Actual/actual
|
||||
* 2 Actual/360
|
||||
* 3 Actual/365
|
||||
* 4 European 30/360
|
||||
* 0 or omitted US (NASD) 30/360
|
||||
* 1 Actual/actual
|
||||
* 2 Actual/360
|
||||
* 3 Actual/365
|
||||
* 4 European 30/360
|
||||
*
|
||||
* @return float|string Result, or a string containing an error
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -0,0 +1,190 @@
|
|||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Calculation\Financial\CashFlow\Constant;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Exception;
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Financial\BaseValidations;
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
||||
|
||||
class Periodic
|
||||
{
|
||||
use BaseValidations;
|
||||
|
||||
/**
|
||||
* FV.
|
||||
*
|
||||
* Returns the Future Value of a cash flow with constant payments and interest rate (annuities).
|
||||
*
|
||||
* Excel Function:
|
||||
* FV(rate,nper,pmt[,pv[,type]])
|
||||
*
|
||||
* @param mixed $rate The interest rate per period
|
||||
* @param mixed $numberOfPeriods Total number of payment periods in an annuity as an integer
|
||||
* @param mixed $payment The payment made each period: it cannot change over the
|
||||
* life of the annuity. Typically, pmt contains principal
|
||||
* and interest but no other fees or taxes.
|
||||
* @param mixed $presentValue present Value, or the lump-sum amount that a series of
|
||||
* future payments is worth right now
|
||||
* @param mixed $type A number 0 or 1 and indicates when payments are due:
|
||||
* 0 or omitted At the end of the period.
|
||||
* 1 At the beginning of the period.
|
||||
*
|
||||
* @return float|string
|
||||
*/
|
||||
public static function futureValue($rate, $numberOfPeriods, $payment = 0, $presentValue = 0, $type = 0)
|
||||
{
|
||||
$rate = Functions::flattenSingleValue($rate);
|
||||
$numberOfPeriods = Functions::flattenSingleValue($numberOfPeriods);
|
||||
$payment = ($payment === null) ? 0.0 : Functions::flattenSingleValue($payment);
|
||||
$presentValue = ($presentValue === null) ? 0.0 : Functions::flattenSingleValue($presentValue);
|
||||
$type = ($type === null) ? 0 : Functions::flattenSingleValue($type);
|
||||
|
||||
try {
|
||||
$rate = self::validateFloat($rate);
|
||||
$numberOfPeriods = self::validateInt($numberOfPeriods);
|
||||
$payment = self::validateFloat($payment);
|
||||
$presentValue = self::validateFloat($presentValue);
|
||||
$type = self::validateInt($type);
|
||||
} catch (Exception $e) {
|
||||
return $e->getMessage();
|
||||
}
|
||||
|
||||
// Validate parameters
|
||||
if ($numberOfPeriods < 0 || ($type !== 0 && $type !== 1)) {
|
||||
return Functions::NAN();
|
||||
}
|
||||
|
||||
return self::calculateFutureValue($rate, $numberOfPeriods, $payment, $presentValue, $type);
|
||||
}
|
||||
|
||||
/**
|
||||
* PV.
|
||||
*
|
||||
* Returns the Present Value of a cash flow with constant payments and interest rate (annuities).
|
||||
*
|
||||
* @param mixed $rate Interest rate per period
|
||||
* @param mixed $numberOfPeriods Number of periods as an integer
|
||||
* @param mixed $payment Periodic payment (annuity)
|
||||
* @param mixed $futureValue Future Value
|
||||
* @param mixed $type Payment type: 0 = at the end of each period, 1 = at the beginning of each period
|
||||
*
|
||||
* @return float|string Result, or a string containing an error
|
||||
*/
|
||||
public static function presentValue($rate, $numberOfPeriods, $payment = 0, $futureValue = 0, $type = 0)
|
||||
{
|
||||
$rate = Functions::flattenSingleValue($rate);
|
||||
$numberOfPeriods = Functions::flattenSingleValue($numberOfPeriods);
|
||||
$payment = ($payment === null) ? 0.0 : Functions::flattenSingleValue($payment);
|
||||
$futureValue = ($futureValue === null) ? 0.0 : Functions::flattenSingleValue($futureValue);
|
||||
$type = ($type === null) ? 0 : Functions::flattenSingleValue($type);
|
||||
|
||||
try {
|
||||
$rate = self::validateFloat($rate);
|
||||
$numberOfPeriods = self::validateInt($numberOfPeriods);
|
||||
$payment = self::validateFloat($payment);
|
||||
$futureValue = self::validateFloat($futureValue);
|
||||
$type = self::validateInt($type);
|
||||
} catch (Exception $e) {
|
||||
return $e->getMessage();
|
||||
}
|
||||
|
||||
// Validate parameters
|
||||
if ($numberOfPeriods < 0 || ($type !== 0 && $type !== 1)) {
|
||||
return Functions::NAN();
|
||||
}
|
||||
|
||||
return self::calculatePresentValue($rate, $numberOfPeriods, $payment, $futureValue, $type);
|
||||
}
|
||||
|
||||
/**
|
||||
* NPER.
|
||||
*
|
||||
* Returns the number of periods for a cash flow with constant periodic payments (annuities), and interest rate.
|
||||
*
|
||||
* @param mixed $rate Interest rate per period
|
||||
* @param mixed $payment Periodic payment (annuity)
|
||||
* @param mixed $presentValue Present Value
|
||||
* @param mixed $futureValue Future Value
|
||||
* @param mixed $type Payment type: 0 = at the end of each period, 1 = at the beginning of each period
|
||||
*
|
||||
* @return float|string Result, or a string containing an error
|
||||
*/
|
||||
public static function periods($rate, $payment, $presentValue, $futureValue = 0, $type = 0)
|
||||
{
|
||||
$rate = Functions::flattenSingleValue($rate);
|
||||
$payment = Functions::flattenSingleValue($payment);
|
||||
$presentValue = Functions::flattenSingleValue($presentValue);
|
||||
$futureValue = ($futureValue === null) ? 0.0 : Functions::flattenSingleValue($futureValue);
|
||||
$type = ($type === null) ? 0 : Functions::flattenSingleValue($type);
|
||||
|
||||
try {
|
||||
$rate = self::validateFloat($rate);
|
||||
$payment = self::validateFloat($payment);
|
||||
$presentValue = self::validateFloat($presentValue);
|
||||
$futureValue = self::validateFloat($futureValue);
|
||||
$type = self::validateInt($type);
|
||||
} catch (Exception $e) {
|
||||
return $e->getMessage();
|
||||
}
|
||||
|
||||
// Validate parameters
|
||||
if ($payment == 0.0 || ($type != 0 && $type != 1)) {
|
||||
return Functions::NAN();
|
||||
}
|
||||
|
||||
return self::calculatePeriods($rate, $payment, $presentValue, $futureValue, $type);
|
||||
}
|
||||
|
||||
private static function calculateFutureValue(
|
||||
float $rate,
|
||||
int $numberOfPeriods,
|
||||
float $payment,
|
||||
float $presentValue,
|
||||
int $type
|
||||
): float {
|
||||
if ($rate !== null && $rate != 0) {
|
||||
return -$presentValue *
|
||||
(1 + $rate) ** $numberOfPeriods - $payment * (1 + $rate * $type) * ((1 + $rate) ** $numberOfPeriods - 1)
|
||||
/ $rate;
|
||||
}
|
||||
|
||||
return -$presentValue - $payment * $numberOfPeriods;
|
||||
}
|
||||
|
||||
private static function calculatePresentValue(
|
||||
float $rate,
|
||||
int $numberOfPeriods,
|
||||
float $payment,
|
||||
float $futureValue,
|
||||
int $type
|
||||
): float {
|
||||
if ($rate != 0.0) {
|
||||
return (-$payment * (1 + $rate * $type)
|
||||
* (((1 + $rate) ** $numberOfPeriods - 1) / $rate) - $futureValue) / (1 + $rate) ** $numberOfPeriods;
|
||||
}
|
||||
|
||||
return -$futureValue - $payment * $numberOfPeriods;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return float|string
|
||||
*/
|
||||
private static function calculatePeriods(
|
||||
float $rate,
|
||||
float $payment,
|
||||
float $presentValue,
|
||||
float $futureValue,
|
||||
int $type
|
||||
) {
|
||||
if ($rate != 0.0) {
|
||||
if ($presentValue == 0.0) {
|
||||
return Functions::NAN();
|
||||
}
|
||||
|
||||
return log(($payment * (1 + $rate * $type) / $rate - $futureValue) /
|
||||
($presentValue + $payment * (1 + $rate * $type) / $rate)) / log(1 + $rate);
|
||||
}
|
||||
|
||||
return (-$presentValue - $futureValue) / $payment;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,136 @@
|
|||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Calculation\Financial\CashFlow\Constant\Periodic;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Exception;
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Financial;
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
||||
|
||||
class Cumulative
|
||||
{
|
||||
use Financial\BaseValidations;
|
||||
|
||||
/**
|
||||
* CUMIPMT.
|
||||
*
|
||||
* Returns the cumulative interest paid on a loan between the start and end periods.
|
||||
*
|
||||
* Excel Function:
|
||||
* CUMIPMT(rate,nper,pv,start,end[,type])
|
||||
*
|
||||
* @param mixed $rate The Interest rate
|
||||
* @param mixed $periods The total number of payment periods
|
||||
* @param mixed $presentValue Present Value
|
||||
* @param mixed $start The first period in the calculation.
|
||||
* Payment periods are numbered beginning with 1.
|
||||
* @param mixed $end the last period in the calculation
|
||||
* @param mixed $type A number 0 or 1 and indicates when payments are due:
|
||||
* 0 or omitted At the end of the period.
|
||||
* 1 At the beginning of the period.
|
||||
*
|
||||
* @return float|string
|
||||
*/
|
||||
public static function interest($rate, $periods, $presentValue, $start, $end, $type = 0)
|
||||
{
|
||||
$rate = Functions::flattenSingleValue($rate);
|
||||
$periods = Functions::flattenSingleValue($periods);
|
||||
$presentValue = Functions::flattenSingleValue($presentValue);
|
||||
$start = Functions::flattenSingleValue($start);
|
||||
$end = Functions::flattenSingleValue($end);
|
||||
$type = ($type === null) ? 0 : Functions::flattenSingleValue($type);
|
||||
|
||||
try {
|
||||
$rate = self::validateFloat($rate);
|
||||
$periods = self::validateInt($periods);
|
||||
$presentValue = self::validateFloat($presentValue);
|
||||
$start = self::validateInt($start);
|
||||
$end = self::validateInt($end);
|
||||
$type = self::validateInt($type);
|
||||
} catch (Exception $e) {
|
||||
return $e->getMessage();
|
||||
}
|
||||
|
||||
// Validate parameters
|
||||
if ($type !== 0 && $type !== 1) {
|
||||
return Functions::NAN();
|
||||
}
|
||||
if ($start < 1 || $start > $end) {
|
||||
return Functions::NAN();
|
||||
}
|
||||
|
||||
// Calculate
|
||||
$interest = 0;
|
||||
for ($per = $start; $per <= $end; ++$per) {
|
||||
$ipmt = Financial::IPMT($rate, $per, $periods, $presentValue, 0, $type);
|
||||
if (is_string($ipmt)) {
|
||||
return $ipmt;
|
||||
}
|
||||
|
||||
$interest += $ipmt;
|
||||
}
|
||||
|
||||
return $interest;
|
||||
}
|
||||
|
||||
/**
|
||||
* CUMPRINC.
|
||||
*
|
||||
* Returns the cumulative principal paid on a loan between the start and end periods.
|
||||
*
|
||||
* Excel Function:
|
||||
* CUMPRINC(rate,nper,pv,start,end[,type])
|
||||
*
|
||||
* @param mixed $rate The Interest rate
|
||||
* @param mixed $periods The total number of payment periods as an integer
|
||||
* @param mixed $presentValue Present Value
|
||||
* @param mixed $start The first period in the calculation.
|
||||
* Payment periods are numbered beginning with 1.
|
||||
* @param mixed $end the last period in the calculation
|
||||
* @param mixed $type A number 0 or 1 and indicates when payments are due:
|
||||
* 0 or omitted At the end of the period.
|
||||
* 1 At the beginning of the period.
|
||||
*
|
||||
* @return float|string
|
||||
*/
|
||||
public static function principal($rate, $periods, $presentValue, $start, $end, $type = 0)
|
||||
{
|
||||
$rate = Functions::flattenSingleValue($rate);
|
||||
$periods = Functions::flattenSingleValue($periods);
|
||||
$presentValue = Functions::flattenSingleValue($presentValue);
|
||||
$start = Functions::flattenSingleValue($start);
|
||||
$end = Functions::flattenSingleValue($end);
|
||||
$type = ($type === null) ? 0 : Functions::flattenSingleValue($type);
|
||||
|
||||
try {
|
||||
$rate = self::validateFloat($rate);
|
||||
$periods = self::validateInt($periods);
|
||||
$presentValue = self::validateFloat($presentValue);
|
||||
$start = self::validateInt($start);
|
||||
$end = self::validateInt($end);
|
||||
$type = self::validateInt($type);
|
||||
} catch (Exception $e) {
|
||||
return $e->getMessage();
|
||||
}
|
||||
|
||||
// Validate parameters
|
||||
if ($type !== 0 && $type !== 1) {
|
||||
return Functions::NAN();
|
||||
}
|
||||
if ($start < 1 || $start > $end) {
|
||||
return Functions::VALUE();
|
||||
}
|
||||
|
||||
// Calculate
|
||||
$principal = 0;
|
||||
for ($per = $start; $per <= $end; ++$per) {
|
||||
$ppmt = Payments::interestPayment($rate, $per, $periods, $presentValue, 0, $type);
|
||||
if (is_string($ppmt)) {
|
||||
return $ppmt;
|
||||
}
|
||||
|
||||
$principal += $ppmt;
|
||||
}
|
||||
|
||||
return $principal;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,209 @@
|
|||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Calculation\Financial\CashFlow\Constant\Periodic;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Exception;
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Financial\BaseValidations;
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
||||
|
||||
class Interest
|
||||
{
|
||||
use BaseValidations;
|
||||
|
||||
private const FINANCIAL_MAX_ITERATIONS = 128;
|
||||
|
||||
private const FINANCIAL_PRECISION = 1.0e-08;
|
||||
|
||||
/**
|
||||
* IPMT.
|
||||
*
|
||||
* Returns the interest payment for a given period for an investment based on periodic, constant payments
|
||||
* and a constant interest rate.
|
||||
*
|
||||
* Excel Function:
|
||||
* IPMT(rate,per,nper,pv[,fv][,type])
|
||||
*
|
||||
* @param float $interestRate Interest rate per period
|
||||
* @param int $period Period for which we want to find the interest
|
||||
* @param int $numberOfPeriods Number of periods
|
||||
* @param float $presentValue Present Value
|
||||
* @param float $futureValue Future Value
|
||||
* @param int $type Payment type: 0 = at the end of each period, 1 = at the beginning of each period
|
||||
*
|
||||
* @return float|string
|
||||
*/
|
||||
public static function payment($interestRate, $period, $numberOfPeriods, $presentValue, $futureValue = 0, $type = 0)
|
||||
{
|
||||
$interestRate = Functions::flattenSingleValue($interestRate);
|
||||
$period = Functions::flattenSingleValue($period);
|
||||
$numberOfPeriods = Functions::flattenSingleValue($numberOfPeriods);
|
||||
$presentValue = Functions::flattenSingleValue($presentValue);
|
||||
$futureValue = Functions::flattenSingleValue($futureValue);
|
||||
$type = Functions::flattenSingleValue($type);
|
||||
|
||||
try {
|
||||
$interestRate = self::validateFloat($interestRate);
|
||||
$period = self::validateInt($period);
|
||||
$numberOfPeriods = self::validateInt($numberOfPeriods);
|
||||
$presentValue = self::validateFloat($presentValue);
|
||||
$futureValue = self::validateFloat($futureValue);
|
||||
$type = self::validateInt($type);
|
||||
} catch (Exception $e) {
|
||||
return $e->getMessage();
|
||||
}
|
||||
|
||||
// Validate parameters
|
||||
if ($type != 0 && $type != 1) {
|
||||
return Functions::NAN();
|
||||
}
|
||||
if ($period <= 0 || $period > $numberOfPeriods) {
|
||||
return Functions::NAN();
|
||||
}
|
||||
|
||||
// Calculate
|
||||
$interestAndPrincipal = new InterestAndPrincipal(
|
||||
$interestRate,
|
||||
$period,
|
||||
$numberOfPeriods,
|
||||
$presentValue,
|
||||
$futureValue,
|
||||
$type
|
||||
);
|
||||
|
||||
return $interestAndPrincipal->interest();
|
||||
}
|
||||
|
||||
/**
|
||||
* ISPMT.
|
||||
*
|
||||
* Returns the interest payment for an investment based on an interest rate and a constant payment schedule.
|
||||
*
|
||||
* Excel Function:
|
||||
* =ISPMT(interest_rate, period, number_payments, pv)
|
||||
*
|
||||
* interest_rate is the interest rate for the investment
|
||||
*
|
||||
* period is the period to calculate the interest rate. It must be betweeen 1 and number_payments.
|
||||
*
|
||||
* number_payments is the number of payments for the annuity
|
||||
*
|
||||
* pv is the loan amount or present value of the payments
|
||||
*/
|
||||
public static function schedulePayment($interestRate, $period, $numberOfPeriods, $principleRemaining)
|
||||
{
|
||||
$interestRate = Functions::flattenSingleValue($interestRate);
|
||||
$period = Functions::flattenSingleValue($period);
|
||||
$numberOfPeriods = Functions::flattenSingleValue($numberOfPeriods);
|
||||
$principleRemaining = Functions::flattenSingleValue($principleRemaining);
|
||||
|
||||
try {
|
||||
$interestRate = self::validateFloat($interestRate);
|
||||
$period = self::validateInt($period);
|
||||
$numberOfPeriods = self::validateInt($numberOfPeriods);
|
||||
$principleRemaining = self::validateFloat($principleRemaining);
|
||||
} catch (Exception $e) {
|
||||
return $e->getMessage();
|
||||
}
|
||||
|
||||
if ($period <= 0 || $period > $numberOfPeriods) {
|
||||
return Functions::NAN();
|
||||
}
|
||||
// Return value
|
||||
$returnValue = 0;
|
||||
|
||||
// Calculate
|
||||
$principlePayment = ($principleRemaining * 1.0) / ($numberOfPeriods * 1.0);
|
||||
for ($i = 0; $i <= $period; ++$i) {
|
||||
$returnValue = $interestRate * $principleRemaining * -1;
|
||||
$principleRemaining -= $principlePayment;
|
||||
// principle needs to be 0 after the last payment, don't let floating point screw it up
|
||||
if ($i == $numberOfPeriods) {
|
||||
$returnValue = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
return $returnValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* RATE.
|
||||
*
|
||||
* Returns the interest rate per period of an annuity.
|
||||
* RATE is calculated by iteration and can have zero or more solutions.
|
||||
* If the successive results of RATE do not converge to within 0.0000001 after 20 iterations,
|
||||
* RATE returns the #NUM! error value.
|
||||
*
|
||||
* Excel Function:
|
||||
* RATE(nper,pmt,pv[,fv[,type[,guess]]])
|
||||
*
|
||||
* @param mixed $numberOfPeriods The total number of payment periods in an annuity
|
||||
* @param mixed $payment The payment made each period and cannot change over the life of the annuity.
|
||||
* Typically, pmt includes principal and interest but no other fees or taxes.
|
||||
* @param mixed $presentValue The present value - the total amount that a series of future payments is worth now
|
||||
* @param mixed $futureValue The future value, or a cash balance you want to attain after the last payment is made.
|
||||
* If fv is omitted, it is assumed to be 0 (the future value of a loan,
|
||||
* for example, is 0).
|
||||
* @param mixed $type A number 0 or 1 and indicates when payments are due:
|
||||
* 0 or omitted At the end of the period.
|
||||
* 1 At the beginning of the period.
|
||||
* @param mixed $guess Your guess for what the rate will be.
|
||||
* If you omit guess, it is assumed to be 10 percent.
|
||||
*
|
||||
* @return float|string
|
||||
*/
|
||||
public static function rate($numberOfPeriods, $payment, $presentValue, $futureValue = 0.0, $type = 0, $guess = 0.1)
|
||||
{
|
||||
$numberOfPeriods = Functions::flattenSingleValue($numberOfPeriods);
|
||||
$payment = Functions::flattenSingleValue($payment);
|
||||
$presentValue = Functions::flattenSingleValue($presentValue);
|
||||
$futureValue = ($futureValue === null) ? 0.0 : Functions::flattenSingleValue($futureValue);
|
||||
$type = ($type === null) ? 0 : Functions::flattenSingleValue($type);
|
||||
$guess = ($guess === null) ? 0.1 : Functions::flattenSingleValue($guess);
|
||||
|
||||
try {
|
||||
$numberOfPeriods = self::validateInt($numberOfPeriods);
|
||||
$payment = self::validateFloat($payment);
|
||||
$presentValue = self::validateFloat($presentValue);
|
||||
$futureValue = self::validateFloat($futureValue);
|
||||
$type = self::validateInt($type);
|
||||
$guess = self::validateFloat($guess);
|
||||
} catch (Exception $e) {
|
||||
return $e->getMessage();
|
||||
}
|
||||
|
||||
$rate = $guess;
|
||||
// rest of code adapted from python/numpy
|
||||
$close = false;
|
||||
$iter = 0;
|
||||
while (!$close && $iter < self::FINANCIAL_MAX_ITERATIONS) {
|
||||
$nextdiff = self::rateNextGuess($rate, $numberOfPeriods, $payment, $presentValue, $futureValue, $type);
|
||||
if (!is_numeric($nextdiff)) {
|
||||
break;
|
||||
}
|
||||
$rate1 = $rate - $nextdiff;
|
||||
$close = abs($rate1 - $rate) < self::FINANCIAL_PRECISION;
|
||||
++$iter;
|
||||
$rate = $rate1;
|
||||
}
|
||||
|
||||
return $close ? $rate : Functions::NAN();
|
||||
}
|
||||
|
||||
private static function rateNextGuess($rate, $nper, $pmt, $pv, $fv, $type)
|
||||
{
|
||||
if ($rate == 0) {
|
||||
return Functions::NAN();
|
||||
}
|
||||
$tt1 = ($rate + 1) ** $nper;
|
||||
$tt2 = ($rate + 1) ** ($nper - 1);
|
||||
$numerator = $fv + $tt1 * $pv + $pmt * ($tt1 - 1) * ($rate * $type + 1) / $rate;
|
||||
$denominator = $nper * $tt2 * $pv - $pmt * ($tt1 - 1) * ($rate * $type + 1) / ($rate * $rate)
|
||||
+ $nper * $pmt * $tt2 * ($rate * $type + 1) / $rate
|
||||
+ $pmt * ($tt1 - 1) * $type / $rate;
|
||||
if ($denominator == 0) {
|
||||
return Functions::NAN();
|
||||
}
|
||||
|
||||
return $numerator / $denominator;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Calculation\Financial\CashFlow\Constant\Periodic;
|
||||
|
||||
class InterestAndPrincipal
|
||||
{
|
||||
protected $interest;
|
||||
|
||||
protected $principal;
|
||||
|
||||
public function __construct(
|
||||
float $rate = 0.0,
|
||||
int $period = 0,
|
||||
int $numberOfPeriods = 0,
|
||||
float $presentValue = 0,
|
||||
float $futureValue = 0,
|
||||
int $type = 0
|
||||
) {
|
||||
$payment = Payments::annuity($rate, $numberOfPeriods, $presentValue, $futureValue, $type);
|
||||
$capital = $presentValue;
|
||||
$interest = 0.0;
|
||||
$principal = 0.0;
|
||||
for ($i = 1; $i <= $period; ++$i) {
|
||||
$interest = ($type && $i == 1) ? 0 : -$capital * $rate;
|
||||
$principal = $payment - $interest;
|
||||
$capital += $principal;
|
||||
}
|
||||
|
||||
$this->interest = $interest;
|
||||
$this->principal = $principal;
|
||||
}
|
||||
|
||||
public function interest(): float
|
||||
{
|
||||
return $this->interest;
|
||||
}
|
||||
|
||||
public function principal(): float
|
||||
{
|
||||
return $this->principal;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,119 @@
|
|||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Calculation\Financial\CashFlow\Constant\Periodic;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Exception;
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Financial\BaseValidations;
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
||||
|
||||
class Payments
|
||||
{
|
||||
use BaseValidations;
|
||||
|
||||
/**
|
||||
* PMT.
|
||||
*
|
||||
* Returns the constant payment (annuity) for a cash flow with a constant interest rate.
|
||||
*
|
||||
* @param mixed $interestRate Interest rate per period
|
||||
* @param mixed $numberOfPeriods Number of periods
|
||||
* @param mixed $presentValue Present Value
|
||||
* @param mixed $futureValue Future Value
|
||||
* @param mixed $type Payment type: 0 = at the end of each period, 1 = at the beginning of each period
|
||||
*
|
||||
* @return float|string Result, or a string containing an error
|
||||
*/
|
||||
public static function annuity($interestRate, $numberOfPeriods, $presentValue, $futureValue = 0, $type = 0)
|
||||
{
|
||||
$interestRate = Functions::flattenSingleValue($interestRate);
|
||||
$numberOfPeriods = Functions::flattenSingleValue($numberOfPeriods);
|
||||
$presentValue = Functions::flattenSingleValue($presentValue);
|
||||
$futureValue = ($futureValue === null) ? 0.0 : Functions::flattenSingleValue($futureValue);
|
||||
$type = ($type === null) ? 0 : Functions::flattenSingleValue($type);
|
||||
|
||||
try {
|
||||
$interestRate = self::validateFloat($interestRate);
|
||||
$numberOfPeriods = self::validateInt($numberOfPeriods);
|
||||
$presentValue = self::validateFloat($presentValue);
|
||||
$futureValue = self::validateFloat($futureValue);
|
||||
$type = self::validateInt($type);
|
||||
} catch (Exception $e) {
|
||||
return $e->getMessage();
|
||||
}
|
||||
|
||||
// Validate parameters
|
||||
if ($type != 0 && $type != 1) {
|
||||
return Functions::NAN();
|
||||
}
|
||||
|
||||
// Calculate
|
||||
if ($interestRate != 0.0) {
|
||||
return (-$futureValue - $presentValue * (1 + $interestRate) ** $numberOfPeriods) /
|
||||
(1 + $interestRate * $type) / (((1 + $interestRate) ** $numberOfPeriods - 1) / $interestRate);
|
||||
}
|
||||
|
||||
return (-$presentValue - $futureValue) / $numberOfPeriods;
|
||||
}
|
||||
|
||||
/**
|
||||
* PPMT.
|
||||
*
|
||||
* Returns the interest payment for a given period for an investment based on periodic, constant payments
|
||||
* and a constant interest rate.
|
||||
*
|
||||
* @param mixed $interestRate Interest rate per period
|
||||
* @param mixed $period Period for which we want to find the interest
|
||||
* @param mixed $numberOfPeriods Number of periods
|
||||
* @param mixed $presentValue Present Value
|
||||
* @param mixed $futureValue Future Value
|
||||
* @param mixed $type Payment type: 0 = at the end of each period, 1 = at the beginning of each period
|
||||
*
|
||||
* @return float|string Result, or a string containing an error
|
||||
*/
|
||||
public static function interestPayment(
|
||||
$interestRate,
|
||||
$period,
|
||||
$numberOfPeriods,
|
||||
$presentValue,
|
||||
$futureValue = 0,
|
||||
$type = 0
|
||||
) {
|
||||
$interestRate = Functions::flattenSingleValue($interestRate);
|
||||
$period = Functions::flattenSingleValue($period);
|
||||
$numberOfPeriods = Functions::flattenSingleValue($numberOfPeriods);
|
||||
$presentValue = Functions::flattenSingleValue($presentValue);
|
||||
$futureValue = ($futureValue === null) ? 0.0 : Functions::flattenSingleValue($futureValue);
|
||||
$type = ($type === null) ? 0 : Functions::flattenSingleValue($type);
|
||||
|
||||
try {
|
||||
$interestRate = self::validateFloat($interestRate);
|
||||
$period = self::validateInt($period);
|
||||
$numberOfPeriods = self::validateInt($numberOfPeriods);
|
||||
$presentValue = self::validateFloat($presentValue);
|
||||
$futureValue = self::validateFloat($futureValue);
|
||||
$type = self::validateInt($type);
|
||||
} catch (Exception $e) {
|
||||
return $e->getMessage();
|
||||
}
|
||||
|
||||
// Validate parameters
|
||||
if ($type != 0 && $type != 1) {
|
||||
return Functions::NAN();
|
||||
}
|
||||
if ($period <= 0 || $period > $numberOfPeriods) {
|
||||
return Functions::NAN();
|
||||
}
|
||||
|
||||
// Calculate
|
||||
$interestAndPrincipal = new InterestAndPrincipal(
|
||||
$interestRate,
|
||||
$period,
|
||||
$numberOfPeriods,
|
||||
$presentValue,
|
||||
$futureValue,
|
||||
$type
|
||||
);
|
||||
|
||||
return $interestAndPrincipal->principal();
|
||||
}
|
||||
}
|
||||
|
|
@ -178,14 +178,12 @@ class NonPeriodic
|
|||
$valCount = count($values);
|
||||
|
||||
try {
|
||||
self::validateXnpv($rate, $values, $dates);
|
||||
$date0 = DateTimeExcel\Helpers::getDateValue($dates[0]);
|
||||
} catch (Exception $e) {
|
||||
return $e->getMessage();
|
||||
}
|
||||
$rslt = self::validateXnpv($rate, $values, $dates);
|
||||
if ($rslt) {
|
||||
return $rslt;
|
||||
}
|
||||
|
||||
$xnpv = 0.0;
|
||||
for ($i = 0; $i < $valCount; ++$i) {
|
||||
if (!is_numeric($values[$i])) {
|
||||
|
|
@ -212,23 +210,17 @@ class NonPeriodic
|
|||
return is_finite($xnpv) ? $xnpv : Functions::VALUE();
|
||||
}
|
||||
|
||||
private static function validateXnpv($rate, $values, $dates)
|
||||
private static function validateXnpv($rate, $values, $dates): void
|
||||
{
|
||||
if (!is_numeric($rate)) {
|
||||
return Functions::VALUE();
|
||||
throw new Exception(Functions::VALUE());
|
||||
}
|
||||
$valCount = count($values);
|
||||
if ($valCount != count($dates)) {
|
||||
return Functions::NAN();
|
||||
throw new Exception(Functions::NAN());
|
||||
}
|
||||
if ($valCount > 1 && ((min($values) > 0) || (max($values) < 0))) {
|
||||
return Functions::NAN();
|
||||
throw new Exception(Functions::NAN());
|
||||
}
|
||||
$date0 = DateTimeExcel\Helpers::getDateValue($dates[0]);
|
||||
if (is_string($date0)) {
|
||||
return Functions::VALUE();
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\Financial;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Financial;
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class PmtTest extends TestCase
|
||||
{
|
||||
protected function setUp(): void
|
||||
{
|
||||
Functions::setCompatibilityMode(Functions::COMPATIBILITY_EXCEL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider providerPMT
|
||||
*
|
||||
* @param mixed $expectedResult
|
||||
*/
|
||||
public function testPMT($expectedResult, array $args): void
|
||||
{
|
||||
$interestRate = array_shift($args);
|
||||
$numberOfPeriods = array_shift($args);
|
||||
$presentValue = array_shift($args);
|
||||
$result = Financial::PMT($interestRate, $numberOfPeriods, $presentValue, ...$args);
|
||||
self::assertEqualsWithDelta($expectedResult, $result, 1E-8);
|
||||
}
|
||||
|
||||
public function providerPMT()
|
||||
{
|
||||
return require 'tests/data/Calculation/Financial/PMT.php';
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\Financial;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Financial;
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class PpmtTest extends TestCase
|
||||
{
|
||||
protected function setUp(): void
|
||||
{
|
||||
Functions::setCompatibilityMode(Functions::COMPATIBILITY_EXCEL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider providerPPMT
|
||||
*
|
||||
* @param mixed $expectedResult
|
||||
*/
|
||||
public function testPPMT($expectedResult, array $args): void
|
||||
{
|
||||
$result = Financial::PPMT(...$args);
|
||||
self::assertEqualsWithDelta($expectedResult, $result, 1E-8);
|
||||
}
|
||||
|
||||
public function providerPPMT()
|
||||
{
|
||||
return require 'tests/data/Calculation/Financial/PPMT.php';
|
||||
}
|
||||
}
|
||||
|
|
@ -5,7 +5,7 @@
|
|||
return [
|
||||
[
|
||||
-11135.232130750999,
|
||||
0.0074999999999999997,
|
||||
0.0075,
|
||||
360,
|
||||
125000,
|
||||
13,
|
||||
|
|
@ -14,7 +14,7 @@ return [
|
|||
],
|
||||
[
|
||||
-937.5,
|
||||
0.0074999999999999997,
|
||||
0.0075,
|
||||
360,
|
||||
125000,
|
||||
1,
|
||||
|
|
@ -22,8 +22,8 @@ return [
|
|||
0,
|
||||
],
|
||||
[
|
||||
-2294.9775375120998,
|
||||
0.0041666666669999998,
|
||||
-2299.6141712553544,
|
||||
0.004175,
|
||||
60,
|
||||
50000,
|
||||
1,
|
||||
|
|
@ -31,8 +31,8 @@ return [
|
|||
0,
|
||||
],
|
||||
[
|
||||
-1833.1000667254,
|
||||
0.0041666666669999998,
|
||||
-1836.8883999349455,
|
||||
0.004175,
|
||||
60,
|
||||
50000,
|
||||
13,
|
||||
|
|
@ -40,8 +40,8 @@ return [
|
|||
0,
|
||||
],
|
||||
[
|
||||
-1347.5920679425001,
|
||||
0.0041666666669999998,
|
||||
-1350.4402595996685,
|
||||
0.004175,
|
||||
60,
|
||||
50000,
|
||||
25,
|
||||
|
|
@ -49,8 +49,8 @@ return [
|
|||
0,
|
||||
],
|
||||
[
|
||||
-837.24455850309005,
|
||||
0.0041666666669999998,
|
||||
-839.0535854569902,
|
||||
0.004175,
|
||||
60,
|
||||
50000,
|
||||
37,
|
||||
|
|
@ -58,8 +58,8 @@ return [
|
|||
0,
|
||||
],
|
||||
[
|
||||
-300.78670189938998,
|
||||
0.0041666666669999998,
|
||||
-301.4498641014851,
|
||||
0.004175,
|
||||
60,
|
||||
50000,
|
||||
49,
|
||||
|
|
@ -68,7 +68,7 @@ return [
|
|||
],
|
||||
[
|
||||
'#VALUE!',
|
||||
0.0074999999999999997,
|
||||
'NaN',
|
||||
360,
|
||||
125000,
|
||||
24,
|
||||
|
|
@ -76,21 +76,66 @@ return [
|
|||
0,
|
||||
],
|
||||
[
|
||||
'#NUM!',
|
||||
0.0074999999999999997,
|
||||
'#VALUE!',
|
||||
0.0075,
|
||||
'NaN',
|
||||
125000,
|
||||
24,
|
||||
13,
|
||||
0,
|
||||
],
|
||||
[
|
||||
'#VALUE!',
|
||||
0.0075,
|
||||
360,
|
||||
'NaN',
|
||||
24,
|
||||
13,
|
||||
0,
|
||||
],
|
||||
[
|
||||
'#VALUE!',
|
||||
0.0075,
|
||||
360,
|
||||
125000,
|
||||
'NaN',
|
||||
13,
|
||||
0,
|
||||
],
|
||||
[
|
||||
'#VALUE!',
|
||||
0.0075,
|
||||
360,
|
||||
125000,
|
||||
24,
|
||||
'NaN',
|
||||
0,
|
||||
],
|
||||
[
|
||||
'#VALUE!',
|
||||
0.0075,
|
||||
360,
|
||||
125000,
|
||||
24,
|
||||
13,
|
||||
'NaN',
|
||||
],
|
||||
[
|
||||
'#NUM!',
|
||||
0.0075,
|
||||
360,
|
||||
125000,
|
||||
13,
|
||||
24,
|
||||
2,
|
||||
],
|
||||
[
|
||||
'#NUM!',
|
||||
0.0074999999999999997,
|
||||
0.0075,
|
||||
10,
|
||||
125000,
|
||||
13,
|
||||
24,
|
||||
13,
|
||||
0,
|
||||
],
|
||||
];
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
return [
|
||||
[
|
||||
-934.10712342088004,
|
||||
0.0074999999999999997,
|
||||
0.0075,
|
||||
360,
|
||||
125000,
|
||||
13,
|
||||
|
|
@ -14,7 +14,7 @@ return [
|
|||
],
|
||||
[
|
||||
-68.278271180977001,
|
||||
0.0074999999999999997,
|
||||
0.0075,
|
||||
360,
|
||||
125000,
|
||||
1,
|
||||
|
|
@ -22,8 +22,8 @@ return [
|
|||
0,
|
||||
],
|
||||
[
|
||||
-9027.7626490046005,
|
||||
0.0041666666669999998,
|
||||
-9025.875084814226,
|
||||
0.004175,
|
||||
60,
|
||||
50000,
|
||||
1,
|
||||
|
|
@ -31,8 +31,8 @@ return [
|
|||
0,
|
||||
],
|
||||
[
|
||||
-9489.6401197913001,
|
||||
0.0041666666669999998,
|
||||
-9488.600856134633,
|
||||
0.004175,
|
||||
60,
|
||||
50000,
|
||||
13,
|
||||
|
|
@ -40,8 +40,8 @@ return [
|
|||
0,
|
||||
],
|
||||
[
|
||||
-9975.1481185740995,
|
||||
0.0041666666669999998,
|
||||
-9975.04899646991,
|
||||
0.004175,
|
||||
60,
|
||||
50000,
|
||||
25,
|
||||
|
|
@ -49,8 +49,8 @@ return [
|
|||
0,
|
||||
],
|
||||
[
|
||||
-10485.495628014,
|
||||
0.0041666666669999998,
|
||||
-10486.435670612591,
|
||||
0.004175,
|
||||
60,
|
||||
50000,
|
||||
37,
|
||||
|
|
@ -58,8 +58,8 @@ return [
|
|||
0,
|
||||
],
|
||||
[
|
||||
-11021.953484617001,
|
||||
0.0041666666669999998,
|
||||
-11024.039391968092,
|
||||
0.004175,
|
||||
60,
|
||||
50000,
|
||||
49,
|
||||
|
|
@ -68,7 +68,61 @@ return [
|
|||
],
|
||||
[
|
||||
'#VALUE!',
|
||||
0.0074999999999999997,
|
||||
'NaN',
|
||||
360,
|
||||
125000,
|
||||
13,
|
||||
24,
|
||||
0,
|
||||
],
|
||||
[
|
||||
'#VALUE!',
|
||||
0.0075,
|
||||
'NaN',
|
||||
125000,
|
||||
13,
|
||||
24,
|
||||
0,
|
||||
],
|
||||
[
|
||||
'#VALUE!',
|
||||
0.0075,
|
||||
360,
|
||||
'NaN',
|
||||
13,
|
||||
24,
|
||||
0,
|
||||
],
|
||||
[
|
||||
'#VALUE!',
|
||||
0.0075,
|
||||
360,
|
||||
125000,
|
||||
'NaN',
|
||||
24,
|
||||
0,
|
||||
],
|
||||
[
|
||||
'#VALUE!',
|
||||
0.0075,
|
||||
360,
|
||||
125000,
|
||||
13,
|
||||
'NaN',
|
||||
0,
|
||||
],
|
||||
[
|
||||
'#VALUE!',
|
||||
0.0075,
|
||||
360,
|
||||
125000,
|
||||
13,
|
||||
24,
|
||||
'NaN',
|
||||
],
|
||||
[
|
||||
'#VALUE!',
|
||||
0.0075,
|
||||
360,
|
||||
125000,
|
||||
24,
|
||||
|
|
@ -77,7 +131,7 @@ return [
|
|||
],
|
||||
[
|
||||
'#NUM!',
|
||||
0.0074999999999999997,
|
||||
0.0075,
|
||||
360,
|
||||
125000,
|
||||
24,
|
||||
|
|
@ -86,7 +140,7 @@ return [
|
|||
],
|
||||
[
|
||||
'#NUM!',
|
||||
0.0074999999999999997,
|
||||
0.0075,
|
||||
10,
|
||||
125000,
|
||||
13,
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
return [
|
||||
[
|
||||
2581.4033740600998,
|
||||
0.0050000000000000001,
|
||||
0.005,
|
||||
10,
|
||||
-200,
|
||||
-500,
|
||||
|
|
@ -18,8 +18,8 @@ return [
|
|||
-1000,
|
||||
],
|
||||
[
|
||||
82846.246372417998,
|
||||
0.0091666666670000008,
|
||||
82859.19732763403,
|
||||
0.009175,
|
||||
35,
|
||||
-2000,
|
||||
null,
|
||||
|
|
@ -27,34 +27,26 @@ return [
|
|||
],
|
||||
[
|
||||
2301.4018303408998,
|
||||
0.0050000000000000001,
|
||||
0.005,
|
||||
12,
|
||||
-100,
|
||||
-1000,
|
||||
1,
|
||||
],
|
||||
[
|
||||
68006.082841536001,
|
||||
0.0041666666669999998,
|
||||
68023.43754198513,
|
||||
0.004175,
|
||||
60,
|
||||
-1000,
|
||||
],
|
||||
[
|
||||
39729.460894165997,
|
||||
0.025000000000000001,
|
||||
0.025,
|
||||
16,
|
||||
-2000,
|
||||
0,
|
||||
1,
|
||||
],
|
||||
[
|
||||
'#NUM!',
|
||||
0.10000000000000001,
|
||||
12,
|
||||
-100,
|
||||
0,
|
||||
2,
|
||||
],
|
||||
[
|
||||
1300,
|
||||
0.0,
|
||||
|
|
@ -62,4 +54,64 @@ return [
|
|||
-100,
|
||||
-100,
|
||||
],
|
||||
[
|
||||
'#VALUE!',
|
||||
'NaN',
|
||||
12,
|
||||
-100,
|
||||
-100,
|
||||
],
|
||||
[
|
||||
'#VALUE!',
|
||||
0.0,
|
||||
'NaN',
|
||||
-100,
|
||||
-100,
|
||||
],
|
||||
[
|
||||
'#VALUE!',
|
||||
0.0,
|
||||
12,
|
||||
'NaN',
|
||||
-100,
|
||||
],
|
||||
[
|
||||
'#VALUE!',
|
||||
0.0,
|
||||
12,
|
||||
-100,
|
||||
'NaN',
|
||||
],
|
||||
[
|
||||
'#VALUE!',
|
||||
0.0,
|
||||
12,
|
||||
-100,
|
||||
-100,
|
||||
'NaN',
|
||||
],
|
||||
[
|
||||
'#NUM!',
|
||||
0.10,
|
||||
-1,
|
||||
-100,
|
||||
0,
|
||||
1,
|
||||
],
|
||||
[
|
||||
'#NUM!',
|
||||
0.10,
|
||||
12,
|
||||
-100,
|
||||
0,
|
||||
2,
|
||||
],
|
||||
[
|
||||
'#NUM!',
|
||||
0.10,
|
||||
12,
|
||||
-100,
|
||||
0,
|
||||
-1,
|
||||
],
|
||||
];
|
||||
|
|
|
|||
|
|
@ -4,36 +4,36 @@
|
|||
|
||||
return [
|
||||
[
|
||||
-22.406893015021002,
|
||||
0.0083333333329999992,
|
||||
-22.858787457480013,
|
||||
0.0085,
|
||||
3,
|
||||
3,
|
||||
8000,
|
||||
],
|
||||
[
|
||||
-292.44712990937001,
|
||||
0.10000000000000001,
|
||||
0.10,
|
||||
3,
|
||||
3,
|
||||
8000,
|
||||
],
|
||||
[
|
||||
-208.33333335,
|
||||
0.0041666666669999998,
|
||||
-212.50,
|
||||
0.00425,
|
||||
1,
|
||||
60,
|
||||
50000,
|
||||
],
|
||||
[
|
||||
-205.26988189617001,
|
||||
0.0041666666669999998,
|
||||
-209.38324500656188,
|
||||
0.00425,
|
||||
2,
|
||||
60,
|
||||
50000,
|
||||
],
|
||||
[
|
||||
0.0,
|
||||
0.0087500000000000008,
|
||||
0.00875,
|
||||
1,
|
||||
8,
|
||||
10000,
|
||||
|
|
@ -42,7 +42,7 @@ return [
|
|||
],
|
||||
[
|
||||
-70.968650395558996,
|
||||
0.0087500000000000008,
|
||||
0.00875,
|
||||
2,
|
||||
8,
|
||||
10000,
|
||||
|
|
@ -50,17 +50,80 @@ return [
|
|||
1,
|
||||
],
|
||||
[
|
||||
'#NUM!',
|
||||
0.0050000000000000001,
|
||||
'#VALUE!',
|
||||
'NaN',
|
||||
2,
|
||||
8,
|
||||
2500,
|
||||
200,
|
||||
6,
|
||||
10000,
|
||||
5000,
|
||||
1,
|
||||
],
|
||||
[
|
||||
'#VALUE!',
|
||||
0.00875,
|
||||
'NaN',
|
||||
8,
|
||||
10000,
|
||||
5000,
|
||||
1,
|
||||
],
|
||||
[
|
||||
'#VALUE!',
|
||||
0.00875,
|
||||
2,
|
||||
'NaN',
|
||||
10000,
|
||||
5000,
|
||||
1,
|
||||
],
|
||||
[
|
||||
'#VALUE!',
|
||||
0.00875,
|
||||
2,
|
||||
8,
|
||||
'NaN',
|
||||
5000,
|
||||
1,
|
||||
],
|
||||
[
|
||||
'#VALUE!',
|
||||
0.00875,
|
||||
2,
|
||||
8,
|
||||
10000,
|
||||
'NaN',
|
||||
1,
|
||||
],
|
||||
[
|
||||
'#VALUE!',
|
||||
0.00875,
|
||||
2,
|
||||
8,
|
||||
10000,
|
||||
5000,
|
||||
'NaN',
|
||||
],
|
||||
[
|
||||
'#NUM!',
|
||||
0.0050000000000000001,
|
||||
0.00875,
|
||||
2,
|
||||
8,
|
||||
10000,
|
||||
5000,
|
||||
2,
|
||||
],
|
||||
[
|
||||
'#NUM!',
|
||||
0.005,
|
||||
-1,
|
||||
8,
|
||||
2500,
|
||||
200,
|
||||
1,
|
||||
],
|
||||
[
|
||||
'#NUM!',
|
||||
0.005,
|
||||
8,
|
||||
2,
|
||||
2500,
|
||||
|
|
|
|||
|
|
@ -4,31 +4,87 @@
|
|||
|
||||
return [
|
||||
[
|
||||
-64814.814812222001,
|
||||
0.0083333333329999992,
|
||||
-66111.111111111,
|
||||
0.0085,
|
||||
1,
|
||||
36,
|
||||
8000000,
|
||||
],
|
||||
[
|
||||
-533333.33333333,
|
||||
0.10000000000000001,
|
||||
0.10,
|
||||
1,
|
||||
3,
|
||||
8000000,
|
||||
],
|
||||
[
|
||||
-204.86111112750001,
|
||||
0.0041666666669999998,
|
||||
-205.270833333,
|
||||
0.004175,
|
||||
1,
|
||||
60,
|
||||
50000,
|
||||
],
|
||||
[
|
||||
-201.38888890499999,
|
||||
0.0041666666669999998,
|
||||
-201.791666667,
|
||||
0.004175,
|
||||
2,
|
||||
60,
|
||||
50000,
|
||||
],
|
||||
[
|
||||
0.0,
|
||||
0.00,
|
||||
1,
|
||||
3,
|
||||
8000000,
|
||||
],
|
||||
[
|
||||
0.0,
|
||||
0.125,
|
||||
3,
|
||||
3,
|
||||
8000000,
|
||||
],
|
||||
[
|
||||
'#VALUE!',
|
||||
'NaN',
|
||||
3,
|
||||
3,
|
||||
8000000,
|
||||
],
|
||||
[
|
||||
'#VALUE!',
|
||||
0.125,
|
||||
'NaN',
|
||||
3,
|
||||
8000000,
|
||||
],
|
||||
[
|
||||
'#VALUE!',
|
||||
0.125,
|
||||
3,
|
||||
'NaN',
|
||||
8000000,
|
||||
],
|
||||
[
|
||||
'#VALUE!',
|
||||
0.125,
|
||||
3,
|
||||
3,
|
||||
'NaN',
|
||||
],
|
||||
[
|
||||
'#NUM!',
|
||||
0.125,
|
||||
-1,
|
||||
3,
|
||||
800000,
|
||||
],
|
||||
[
|
||||
'#NUM!',
|
||||
0.125,
|
||||
4,
|
||||
3,
|
||||
800000,
|
||||
],
|
||||
];
|
||||
|
|
|
|||
|
|
@ -26,21 +26,69 @@ return [
|
|||
],
|
||||
[
|
||||
54.787577259999999,
|
||||
0.0033333333329999999,
|
||||
0.003333333333,
|
||||
-1000,
|
||||
50000,
|
||||
],
|
||||
[
|
||||
11.90373729,
|
||||
0.014999999999999999,
|
||||
0.015,
|
||||
-1200,
|
||||
9000,
|
||||
5000,
|
||||
1,
|
||||
],
|
||||
[
|
||||
11.666666667,
|
||||
0.0,
|
||||
-1200,
|
||||
9000,
|
||||
5000,
|
||||
1,
|
||||
],
|
||||
[
|
||||
'#VALUE!',
|
||||
'NaN',
|
||||
-1200,
|
||||
9000,
|
||||
5000,
|
||||
1,
|
||||
],
|
||||
[
|
||||
'#VALUE!',
|
||||
0.015,
|
||||
'NaN',
|
||||
9000,
|
||||
5000,
|
||||
1,
|
||||
],
|
||||
[
|
||||
'#VALUE!',
|
||||
0.015,
|
||||
-1200,
|
||||
'NaN',
|
||||
5000,
|
||||
1,
|
||||
],
|
||||
[
|
||||
'#VALUE!',
|
||||
0.015,
|
||||
-1200,
|
||||
9000,
|
||||
'NaN',
|
||||
1,
|
||||
],
|
||||
[
|
||||
'#VALUE!',
|
||||
0.015,
|
||||
-1200,
|
||||
9000,
|
||||
5000,
|
||||
'NaN',
|
||||
],
|
||||
[
|
||||
'#NUM!',
|
||||
0.014999999999999999,
|
||||
0.015,
|
||||
-1200,
|
||||
9000,
|
||||
5000,
|
||||
|
|
@ -48,7 +96,7 @@ return [
|
|||
],
|
||||
[
|
||||
'#NUM!',
|
||||
0.014999999999999999,
|
||||
0.015,
|
||||
0.0,
|
||||
0.0,
|
||||
5000,
|
||||
|
|
@ -63,10 +111,10 @@ return [
|
|||
1,
|
||||
],
|
||||
[
|
||||
-2.0,
|
||||
'#NUM!',
|
||||
0.25,
|
||||
0.5,
|
||||
0.0,
|
||||
-50,
|
||||
-250,
|
||||
150,
|
||||
1,
|
||||
],
|
||||
|
|
|
|||
|
|
@ -0,0 +1,52 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
[
|
||||
-1037.032089359164,
|
||||
[0.08 / 12, 10, 10000],
|
||||
],
|
||||
[
|
||||
-1030.164327177977,
|
||||
[0.08 / 12, 10, 10000, null, 1],
|
||||
],
|
||||
[
|
||||
-129.081160867995,
|
||||
[0.06 / 12, 18 * 12, 0.0, 50000],
|
||||
],
|
||||
[
|
||||
-943.56168220055,
|
||||
[0.05 / 12, 60, 50000],
|
||||
],
|
||||
[
|
||||
-600.85202718047,
|
||||
[0.035 / 4, 8, 0, 5000, 1],
|
||||
],
|
||||
[
|
||||
-750.00,
|
||||
[0.0, 8, 1000, 5000, 1],
|
||||
],
|
||||
[
|
||||
'#VALUE!',
|
||||
['NaN', 8, 0, 5000, 1],
|
||||
],
|
||||
[
|
||||
'#VALUE!',
|
||||
[0.035 / 4, 'NaN', 0, 5000, 1],
|
||||
],
|
||||
[
|
||||
'#VALUE!',
|
||||
[0.035 / 4, 8, 'NaN', 5000, 1],
|
||||
],
|
||||
[
|
||||
'#VALUE!',
|
||||
[0.035 / 4, 8, 0, 'NaN', 1],
|
||||
],
|
||||
[
|
||||
'#VALUE!',
|
||||
[0.035 / 4, 8, 0, 5000, 'NaN'],
|
||||
],
|
||||
[
|
||||
'#NUM!',
|
||||
[0.035 / 4, 8, 0, 5000, 2],
|
||||
],
|
||||
];
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
[
|
||||
-75.623186008367,
|
||||
[0.10 / 12, 1, 2 * 12, 2000],
|
||||
],
|
||||
[
|
||||
-27598.053462421,
|
||||
[0.08, 10, 10, 200000],
|
||||
],
|
||||
[
|
||||
-735.22834886722,
|
||||
[0.05 / 12, 1, 60, 50000],
|
||||
],
|
||||
[
|
||||
-738.29180032083,
|
||||
[0.05 / 12, 2, 60, 50000],
|
||||
],
|
||||
[
|
||||
-600.85202718047,
|
||||
[0.035 / 4, 1, 8, 0, 5000, 1],
|
||||
],
|
||||
[
|
||||
-606.109482418299,
|
||||
[0.035 / 4, 2, 8, 0, 5000, 1],
|
||||
],
|
||||
[
|
||||
'#VALUE!',
|
||||
['NaN', 2, 8, 0, 5000, 1],
|
||||
],
|
||||
[
|
||||
'#VALUE!',
|
||||
[0.035 / 4, 'NaN', 8, 0, 5000, 1],
|
||||
],
|
||||
[
|
||||
'#VALUE!',
|
||||
[0.035 / 4, 2, 'NaN', 0, 5000, 1],
|
||||
],
|
||||
[
|
||||
'#VALUE!',
|
||||
[0.035 / 4, 2, 8, 'NaN', 5000, 1],
|
||||
],
|
||||
[
|
||||
'#VALUE!',
|
||||
[0.035 / 4, 2, 8, 0, 'NaN', 1],
|
||||
],
|
||||
[
|
||||
'#VALUE!',
|
||||
[0.035 / 4, 2, 8, 0, 5000, 'NaN'],
|
||||
],
|
||||
[
|
||||
'#NUM!',
|
||||
[0.035 / 4, 0, 8, 0, 5000, 1],
|
||||
],
|
||||
[
|
||||
'#NUM!',
|
||||
[0.035 / 4, 4, 2, 0, 5000, 1],
|
||||
],
|
||||
[
|
||||
'#NUM!',
|
||||
[0.035 / 4, 2, 8, 0, 5000, 2],
|
||||
],
|
||||
];
|
||||
|
|
@ -21,4 +21,40 @@ return [
|
|||
-762.8840472202697,
|
||||
[0.0525 / 1, 10 * 1, 100, null, 0],
|
||||
],
|
||||
[
|
||||
-1000.0,
|
||||
[0.0, 10 * 1, 100, null, 0],
|
||||
],
|
||||
[
|
||||
'#VALUE!',
|
||||
['NaN', 10 * 1, 100, null, 0],
|
||||
],
|
||||
[
|
||||
'#VALUE!',
|
||||
[0.0525 / 1, 'NaN', 100, null, 0],
|
||||
],
|
||||
[
|
||||
'#VALUE!',
|
||||
[0.0525 / 1, 10 * 1, 'NaN', null, 0],
|
||||
],
|
||||
[
|
||||
'#VALUE!',
|
||||
[0.0525 / 1, 10 * 1, 100, 'NaN', 0],
|
||||
],
|
||||
[
|
||||
'#VALUE!',
|
||||
[0.0525 / 1, 10 * 1, 100, null, 'NaN'],
|
||||
],
|
||||
[
|
||||
'#NUM!',
|
||||
[0.0525 / 1, 10 * 1, 100, null, -1],
|
||||
],
|
||||
[
|
||||
'#NUM!',
|
||||
[0.0525 / 1, 10 * 1, 100, null, 2.5],
|
||||
],
|
||||
[
|
||||
'#NUM!',
|
||||
[0.0525 / 1, 10 * -1, 100, null, 1],
|
||||
],
|
||||
];
|
||||
|
|
|
|||
|
|
@ -103,4 +103,58 @@ return [
|
|||
-700,
|
||||
137600,
|
||||
],
|
||||
[
|
||||
'#VALUE!',
|
||||
'NaN',
|
||||
-700,
|
||||
8000,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
],
|
||||
[
|
||||
'#VALUE!',
|
||||
208,
|
||||
'NaN',
|
||||
8000,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
],
|
||||
[
|
||||
'#VALUE!',
|
||||
208,
|
||||
-700,
|
||||
'NaN',
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
],
|
||||
[
|
||||
'#VALUE!',
|
||||
208,
|
||||
-700,
|
||||
8000,
|
||||
'NaN',
|
||||
0,
|
||||
0,
|
||||
],
|
||||
[
|
||||
'#VALUE!',
|
||||
208,
|
||||
-700,
|
||||
8000,
|
||||
0,
|
||||
'NaN',
|
||||
0,
|
||||
],
|
||||
[
|
||||
'#VALUE!',
|
||||
208,
|
||||
-700,
|
||||
8000,
|
||||
0,
|
||||
0,
|
||||
'NaN',
|
||||
],
|
||||
];
|
||||
|
|
|
|||
Loading…
Reference in New Issue