PHP IRR(内部收益率)财务函数

9o685dep  于 2023-03-16  发布在  PHP
关注(0)|答案(3)|浏览(163)

如何在PHP中实现MS Excel的“IRR()”公式?
我尝试了this page中提到的算法,但结果不准确,而且速度真的很慢。

p8ekf7hl

p8ekf7hl1#

在研究了一段时间后,我最终得到了下面复制的函数。
它基于this question

function IRR($investment, $flow, $precision = 0.001) {
    $min = 0;
    $max = 1;
    $net_present_value = 1;
    while(abs($net_present_value - $investment) > $precision) {
        $net_present_value = 0;
        $guess = ($min + $max) / 2;
        foreach ($flow as $period => $cashflow) {
            $net_present_value += $cashflow / (1 + $guess) ** ($period + 1);
        }
        if ($net_present_value - $investment > 0) {
            $min = $guess;
        } else {
            $max = $guess;
        }
    }
    return $guess * 100;
}
ercv8c1e

ercv8c1e2#

这是根据托马斯的答案修改的,它在开始时通过检查来停止无限循环,以确保现金流大于投资,我还提高了精度,最多运行20次。

private function IRR($investment, $flow, $precision = 0.000001) {

    if (array_sum($flow) < $investment):
        return 0;
    endif;
    $maxIterations = 20;
    $i =0;
    if (is_array($flow)):
        $min = 0;
        $max = 1;
        $net_present_value = 1;
        while ((abs($net_present_value - $investment) > $precision)&& ($i < $maxIterations)) {
            $net_present_value = 0;
            $guess = ($min + $max) / 2;
            foreach ($flow as $period => $cashflow) {
                $net_present_value += $cashflow / (1 + $guess) ** ($period + 1);
            }
            if ($net_present_value - $investment > 0) {
                $min = $guess;
            } else {
                $max = $guess;
            }
            $i++;
        }
        return $guess * 100;
    else:
        return 0;
    endif;
}
rryofs0p

rryofs0p3#

function IRR($values, $guess = 0.1) {
    $maxIterations = 100;
    $tolerance = 0.00001;

    $count = count($values);

    $positive = false;
    $negative = false;
    for ($i = 0; $i < $count; $i++) {
        if ($values[$i] > 0) {
            $positive = true;
       } else {
            $negative = true;
       }
    }

    if (!$positive || !$negative) {
        return null;
    }

    $guess = ($guess == 0) ? 0.1 : $guess;

    for ($i = 0; $i < $maxIterations; $i++) {
        $npv = 0;
        $dnpv = 0;

        for ($j = 0; $j < $count; $j++) {
            $npv += $values[$j] / pow(1 + $guess, $j);
            $dnpv -= $j * $values[$j] / pow(1 + $guess, $j + 1);
        }

        $newGuess = $guess - $npv / $dnpv;

        if (abs($newGuess - $guess) < $tolerance) {
            return $newGuess;
        }

        $guess = $newGuess;
    }
    enter code here
    return null;
}

相关问题