2010-06-23 1 views
2

Я делаю приложение, которое дает клиентам и примерное предложение по кредиту (позднее они рассчитываются другими бэк-офисными системами). Я получил некоторый код от финансовой фирмы, для которого мы делаем калькулятор. Моя проблема в том, что я не понимаю часть кода, которая вычисляет годовую процентную ставку (включая стартовую и месячную плату).Расчет годовой процентной ставки (нужна некоторая помощь с унаследованным кодом)

Это может быть этот метод они используют, но я не могу сказать: http://www.efunda.com/math/num_rootfinding/num_rootfinding.cfm#Newton_Raphson

код работает правильно, но я действительно ненавижу создания приложения на код, который я не в полной мере понять и/или доверия. Окончательный ответ будет исходным кодом, который делает то же самое, но с комментариями и понятными именами переменных (я не исключаю этого :-) Все идеи приветствуются - возможно, у кого-то есть ссылка на статью, которая объясняет это.

(обратите внимание, что я не нахожусь отнюдь не математикой или финансовой) профессионалом

[snip] 
int n = numberOfPayments; 
double a = (amount/(monthlyPayment * Math.Pow(n, 2)) - (monthlyPayment/amount)); 
double d = 0; 
if (a == 0) 
{ 
    d = 0; 
} 
else 
{ 
    for (int qq = 0; qq < 20; qq++) 
    { 
     double b = amount + (monthlyPayment/a) * (1 - (Math.Pow((1 + a), -n))); 
     double c = amount + (monthlyPayment/a) * ((n * (Math.Pow((1 + a), (-n - 1)))) - ((1 - (Math.Pow((1 + a), -n)))/a)); 
     d = a - (b/c); 
     double aa = a; 
     double dd = d; 
     a = d; 
     if (Math.Abs(aa - dd) < Math.Pow(10, -5)) { break; } 
    } 
} 
double apr = ((Math.Pow((1 + d), 12)) - 1) * 100; 
apr = Math.Round(apr * 100)/100; 
[/snip] 

ответ

9

код действительно с помощью метода Ньютона-Рафсона, хотя я понятия не имею, что именно это расчетливый; вы можете скопировать из неправильного раздела. Если вы действительно хотите рассчитать годовую процентную ставку с учетом суммы кредита, ежемесячного платежа и количества месяцев, то вы почти полностью решили это, за исключением того, что вы, вероятно, не знаете, что такое функция , корни которой и это, понятно, камень преткновения.

Ценность, которую ищут, называется internal rate of return (IRR), для которой нет закрытой формы; вы должны рассчитать его с трудом или использовать численные методы. Вычисление годовой процентной ставки является частным случаем IRR, где все платежи равны, а ссуда заканчивается. Это означает, что уравнение выглядит следующим образом:

P является основная сумма/кредита, м ежемесячный платеж, я это процентная ставка, N является количество месяцев

0 = P - Sum[k=1..N](m*(1+i)^(-k)) 

И мы должны решить для i.Приведенное выше уравнение эквивалентно:

P = Sum[k=1..N](m*(1+i)^(-k)) 
P = m * Sum[k=1..N]((1+i)^(-k)) // monthly payments all the same 
P/m = Sum[k=1..N]((1+i)^(-k)) 

Есть некоторые формулы, чтобы получить замкнутую форму на сумму на правой стороне, которая приведет к следующему уравнению, которое относится все величины, которые мы знаем уже (термин, кредит , и сумма ежемесячного платежа) и который является гораздо более сговорчивым:

monthlyPayment = loanAmount * interestRate * ((1 + interestRate)^numberOfPayments)/(((1 + interestRate)^numberOfPayments) - 1) 

Чтобы уменьшить печатая позволить:

  • P является основной суммой/кредита
  • м повторяющегося сумма платежа
  • N является общее число платежей

Так уравнение, корни которого мы должны найти это:

F(x) = P * x * ((1 + x)^N)/(((1 + x)^N) - 1) - m 

Чтобы использовать метод Ньютона-Rhapson нам нужен firstderivative Р относительно х:

F_1(x) = P * ((1 + x)^N/(-1 + (1 + x)^N) - ((N * x * (1 + x)^(-1 + 2*N))/(-1 + (1 + x)^N)^2) + (N * x * (1 + x)^(-1 + N))/(-1 + (1 + x)^N)) 

Следующий код в Groovy делает правильный расчет:

numPay = 360 
payment = 1153.7 
amount = 165000 
double error = Math.pow(10,-5) 
double approx = 0.05/12 // let's start with a guess that the APR is 5% 
double prev_approx 

def F(x) { 
    return amount * x * Math.pow(1 + x,numPay)/(Math.pow(1 + x,numPay) - 1) - payment 
} 

def F_1(x) { 
    return amount * (Math.pow(1 + x,numPay)/(-1 + Math.pow(1 + x,numPay)) - numPay * x * Math.pow(1 + x,-1 + 2*numPay)/Math.pow(-1 + Math.pow(1 + x,numPay),2) + numPay * x * Math.pow(1 + x,-1 + numPay)/(-1 + Math.pow(1 + x,numPay))) 
} 


println "initial guess $approx" 
for (k=0;k<20;++k) { 
     prev_approx = approx 
     approx = prev_approx - F(prev_approx)/F_1(prev_approx) 
     diff = Math.abs(approx-prev_approx) 
     println "new guess $approx diff is $diff" 
     if (diff < error) break 
} 

apr = Math.round(approx * 12 * 10000)/100 // this way we get APRs like 7.5% or 6.55% 
println "APR is ${apr}% final approx $approx " 

Я не использовал предоставленный код, так как он был немного мутным (плюс это не работает для меня). Я получил это из определений уравнения Ньютона-Рапсона и ежемесячного уравнения платежей. Приближение сходится очень быстро (10^-5 в течение 2-х или 3-х итераций)

Примечание: Я не могу получить эту ссылку, чтобы правильно вставить текст, где первая производная впервые упоминается: http://www.wolframalpha.com/input/?i=d/dx(+x+*+((1+%2B+x)^n)/(((1+%2B+x)^n)+-+1)+-m+)

+0

выше, верно, что исходный код пытается вычислить «apr» итеративно, останавливаясь либо на 20 шагов, либо на следующем этапе произойдет изменение не более 10^-5. Я не уверен, является ли исходный код точным; в лучшем случае это непрозрачно. – Borealid

+0

Это не может быть точным. Я пробовал, и это не сработало для меня. Возможно, я допустил ошибку в расшифровке, правда, но я сделал вывод, что, предположительно, эквивалентный код из определений, который не похож на код вопроса. Первая производная, в частности, не выглядит корректной * вообще *. – Allen

+0

Впечатляющий Аллен - большое спасибо! Я должен признать, что некоторые из моих математических разрядов вашего сообщения потеряны на мне, но код Groovy, в частности, сделал мне несколько вещей более ясными. В отрывке, который я опубликовал, «ежемесячный платеж» рассчитывается точно так же, как вы публикуете (но я только разместил часть кода, с которым мне было трудно понять). Отсканированный фрагмент работает, я проверял некоторые другие аналогичные калькуляторы в Excel и javascript (но я ценю, что я мог бы быть мутным, так как он немного ушел из контекста) –