如何在PHP中进行XIRR计算?

时间:2015-08-19 11:07:06

标签: php xirr

我使用过来的http://www.phpclasses.org/ PHP类,但它多次给出-1571465320791500131898188521929991589462016.00 %这个答案(你可以举这个例子,date1 = 04/14/2015,date2 = 08/19/2015 (mm / dd / yyyy格式),value1 = -110,value2 = 5)有没有解决方案,还有其他更好的方法吗? 这个问题先前被问过,但没有令人满意的答案..

-110    14-Apr-15
   5    19-Aug-15
--------------------
    -0.99986137

以上是Excel显示的,

以下是php class的代码

///////////for xirr calc////////////////
function DATEDIFF($datepart, $startdate, $enddate)
{
    switch (strtolower($datepart)) {
        case 'yy':
        case 'yyyy':
        case 'year':
            $di = getdate($startdate);
            $df = getdate($enddate);
            return $df['year'] - $di['year'];
            break;
        case 'q':
        case 'qq':
        case 'quarter':
            die("Unsupported operation");
            break;
        case 'n':
        case 'mi':
        case 'minute':
            return ceil(($enddate - $startdate) / 60); 
            break;
        case 'hh':
        case 'hour':
            return ceil(($enddate - $startdate) / 3600); 
            break;
        case 'd':
        case 'dd':
        case 'day':
            return ceil(($enddate - $startdate) / 86400); 
            break;
        case 'wk':
        case 'ww':
        case 'week':
            return ceil(($enddate - $startdate) / 604800); 
            break;
        case 'm':
        case 'mm':
        case 'month':
            $di = getdate($startdate);
            $df = getdate($enddate);
            return ($df['year'] - $di['year']) * 12 + ($df['mon'] - $di['mon']);
            break;
        default:
            die("Unsupported operation");
    }
}

function XNPV($rate, $values, $dates)
{
    if ((!is_array($values)) || (!is_array($dates))) return null;
    if (count($values) != count($dates)) return null;

    $xnpv = 0.0;
    for ($i = 0; $i < count($values); $i++)
    {
        $xnpv += $values[$i] / pow(1 + $rate, $this->DATEDIFF('day', $dates[0], $dates[$i]) / 365);
    }
    return (is_finite($xnpv) ? $xnpv: null);
}

function XIRR($values, $dates, $guess = 0.1)
{
    if ((!is_array($values)) && (!is_array($dates))) return null;
    if (count($values) != count($dates)) return null;

    // create an initial bracket, with a root somewhere between bot and top
    $x1 = 0.0;
    $x2 = $guess;
    $f1 = $this->XNPV($x1, $values, $dates);
    $f2 = $this->XNPV($x2, $values, $dates);
    for ($i = 0; $i < FINANCIAL_MAX_ITERATIONS; $i++)
    {
        if (($f1 * $f2) < 0.0) break;
        if (abs($f1) < abs($f2)) {
            $f1 = $this->XNPV($x1 += 1.6 * ($x1 - $x2), $values, $dates);
        } else {
            $f2 = $this->XNPV($x2 += 1.6 * ($x2 - $x1), $values, $dates);
        }
    }
    if (($f1 * $f2) > 0.0) return null;

    $f = $this->XNPV($x1, $values, $dates);
    if ($f < 0.0) {
        $rtb = $x1;
        $dx = $x2 - $x1;
    } else {
        $rtb = $x2;
        $dx = $x1 - $x2;
    }

    for ($i = 0;  $i < FINANCIAL_MAX_ITERATIONS; $i++)
    {
        $dx *= 0.5;
        $x_mid = $rtb + $dx;
        $f_mid = $this->XNPV($x_mid, $values, $dates);
        if ($f_mid <= 0.0) $rtb = $x_mid;
        if ((abs($f_mid) < FINANCIAL_ACCURACY) || (abs($dx) < FINANCIAL_ACCURACY)) return $x_mid;
    }
    return null;
}

我们必须这样称呼它

echo 'XIRR: ' . $f->XIRR(array(-10000,2750,4250,3250,2750), array(
mktime(0,0,0,1,1,2008),
mktime(0,0,0,3,1,2008),
mktime(0,0,0,10,30,2008),
mktime(0,0,0,2,15,2009),
mktime(0,0,0,4,1,2009),
), 0.1) . "\n";

0 个答案:

没有答案