PHP IRR (Внутренняя норма доходности) финансовая функция

Как я могу реализовать формулу MS Excel «IRR()» в PHP?

Я попробовал алгоритм, упомянутый в эту страницу, но результаты были неточными, и это было очень медленно.


person Tomas Gonzalez    schedule 21.07.2017    source источник


Ответы (2)


После некоторого исследования я получил функцию, скопированную ниже.

Он основан на этом вопросе.

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;
}
person Tomas Gonzalez    schedule 21.07.2017
comment
Вы всегда могли взглянуть на реализацию в PHPExcel - person Mark Baker; 22.07.2017
comment
Как справиться с бесконечным циклом, когда сумма всех денежных потоков меньше суммы инвестиций? - person Dipendra Gurung; 03.04.2019
comment
PHPExcel заархивирован, вместо этого он находится на github.com/PHPOffice/PhpSpreadsheet. - person roelleor; 18.02.2020

Это изменено из ответа Томаса. Он останавливает бесконечный цикл, проверяя в начале, чтобы убедиться, что денежный поток превышает инвестиции. Я также увеличил точность и прогнал ее максимум 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;
}
person user3560396    schedule 03.12.2019