Я пытаюсь рассчитать проценты по кредиту с учетом первоначальной суммы кредита, количества выплат и суммы выплат. Я не могу получить достаточно близкую цифру, используя базовую формулу, поэтому я пытался использовать метод Ньютона Рафсона, который можно увидеть здесь: http://www.efunda.com/formulae/finance /loan_calculator.cfm (это точная функциональность, которую я ищу для реализации)
Я попытался использовать функцию RATE () из PHPExcel, однако я не получаю правильный вывод для своих входов, т. Е. Процентная ставка возвращается как 0,1% или аналогичная (когда на самом деле это больше похоже на 5.75%)
Это соответствующий код для PHPExcel
/** FINANCIAL_MAX_ITERATIONS */ define('FINANCIAL_MAX_ITERATIONS', 128); /** FINANCIAL_PRECISION */ define('FINANCIAL_PRECISION', 1.0e-08); /** * Convert an array to a single scalar value by extracting the first element * * @param mixed $value Array or scalar value * @return mixed */ function flattenSingleValue($value = '') { while (is_array($value)) { $value = array_pop($value); } return $value; } /** * 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]]]) * * @access public * @category Financial Functions * @param float nper The total number of payment periods in an annuity. * @param float pmt 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 float pv The present value - the total amount that a series of future * payments is worth now. * @param float fv 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 integer 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 float guess Your guess for what the rate will be. * If you omit guess, it is assumed to be 10 percent. * @return float **/ function RATE($nper, $pmt, $pv, $fv = 0.0, $type = 0, $guess = 0.1) { $nper = (int) flattenSingleValue($nper); $pmt = flattenSingleValue($pmt); $pv = flattenSingleValue($pv); $fv = (is_null($fv)) ? 0.0 : flattenSingleValue($fv); $type = (is_null($type)) ? 0 : (int) flattenSingleValue($type); $guess = (is_null($guess)) ? 0.1 : flattenSingleValue($guess); $rate = $guess; if (abs($rate) < FINANCIAL_PRECISION) { $y = $pv * (1 + $nper * $rate) + $pmt * (1 + $rate * $type) * $nper + $fv; } else { $f = exp($nper * log(1 + $rate)); $y = $pv * $f + $pmt * (1 / $rate + $type) * ($f - 1) + $fv; } $y0 = $pv + $pmt * $nper + $fv; $y1 = $pv * $f + $pmt * (1 / $rate + $type) * ($f - 1) + $fv; // find root by secant method $i = $x0 = 0.0; $x1 = $rate; while ((abs($y0 - $y1) > FINANCIAL_PRECISION) && ($i < FINANCIAL_MAX_ITERATIONS)) { $rate = ($y1 * $x0 - $y0 * $x1) / ($y1 - $y0); $x0 = $x1; $x1 = $rate; if (($nper * abs($pmt)) > ($pv - $fv)) $x1 = abs($x1); if (abs($rate) < FINANCIAL_PRECISION) { $y = $pv * (1 + $nper * $rate) + $pmt * (1 + $rate * $type) * $nper + $fv; } else { $f = exp($nper * log(1 + $rate)); $y = $pv * $f + $pmt * (1 / $rate + $type) * ($f - 1) + $fv; } $y0 = $y1; $y1 = $y; ++$i; } return $rate; } // function RATE()
Мой вход в функцию:
RATE(60, 1100, 50000); // Outputs 0.00420298759161 RATE(60, -1100, 50000); // Outputs 0.00959560344752 RATE(60, 1100, 66000); // Outputs -1.05036370955
Если 60 – это количество месяцев в 5 лет, 1100 или -1100 – это сумма, выплачиваемая каждый месяц, а 50 000 – это общая сумма заимствований.
Я не математик, эта функция не имеет для меня никакого смысла, но в моем чтении говорится, что это лучший способ рассчитать ставку. Надеюсь, я просто делаю глупую ошибку …
Вы можете использовать «Двоичный поиск» вместо «Метод Ньютона Рафсона».
function rate($month, $payment, $amount) { // make an initial guess $error = 0.0000001; $high = 1.00; $low = 0.00; $rate = (2.0 * ($month * $payment - $amount)) / ($amount * $month); while(true) { // check for error margin $calc = pow(1 + $rate, $month); $calc = ($rate * $calc) / ($calc - 1.0); $calc -= $payment / $amount; if ($calc > $error) { // guess too high, lower the guess $high = $rate; $rate = ($high + $low) / 2; } elseif ($calc < -$error) { // guess too low, higher the guess $low = $rate; $rate = ($high + $low) / 2; } else { // acceptable guess break; } } return $rate * 12; } var_dump(rate(60, 1000, 20000)); // Return 0.56138305664063, which means 56.1383%
«Бинарный поиск» и «Метод Ньютона Рафсона» в основном являются методом угадывания. Он делает первоначальное предположение и улучшает свое предположение с течением времени, пока не встретит приемлемую догадку. «Метод Ньютона Рафсона» обычно быстрее, чем «бинарный поиск», потому что он имеет лучшую стратегию «угадать».
Концепция проста:
Мы хотим знать, что это процентная ставка. Мы знаем, N, C и P. Мы не знаем, что такое r
, но давайте просто угадать любое число от 0,00 до 1,00. (В этом случае мы предполагаем, что процентная ставка не может превышать 100%).
r
– ежемесячная ставка. Несколько на 12, чтобы получать годовые ставки.