Obliczanie harmonogramu spłat kredytu - Javascript
Liczba osób, które mają, mieli lub będą mieć zaciągnięty kredyt hipoteczny idzie w setki tysięcy. Skłoniło mnie to do tego, aby pokazać, w jaki sposób samemu przygotować sobie takie wyliczenia przy pomocy HTML i Javascript. Aplikację można zoabaczyć tutaj: Harmonogram spłat kredytu hipotecznego - raty annuitetowe (równe).
Podstawy teoretyczne obliczania kredytu
Aby zrozumieć kod, należy najpierw przyjrzeć się sposobowi wyliczania rat. Wbrew pozorom nie jest to takie oczywiste. Po pierwsze, harmonogram to tylko plan. Jednym z głównych czynników wpływających na wysokość odsetek są stopy procentowe. Potrafią się one zmienić kilka razy w ciągu jednego roku, nie mówiąc już o wahaniach tego wskaźnika na przestrzeni 30 lat, bo na taki okres udzielana jest większość kredytów, o których słyszałem. Stopy procentowe podaję się najczęściej w stosunku rocznym, natomiast odsetki nalicza się w odstępach miesięcznych. Oznacza to, że do obliczeń należy przyjąć miesięczną stopę procentową, która jest równa pierwiastkowi dwunastego stopnia ze znormalizowanej stawki procentowej pomniejszonej o jeden. Brzmi to groźnie, ale popatrzmy na przykład i wszystko się wyjaśni.
Aby wyliczyć miesięczną stopę, wyciągamy pierwiastek dwunastego stopnia z rocznej wartości znormalizowanej. Pierwiastek dwunastego stopnia z A jest równe A do potęgi 1/12. Mamy wobec tego:
Jak to działa dalej? Od pożyczonej kwoty odejmowana jest miesięczna wpłata (rata kredytu), a do pozostałej kwoty doliczane są odsetki. I tak przez, powiedzmy, 30 lat. W rzeczywistości wygląda to trochę inaczej. Rzadko zdarza się, żeby instytucje finansowe oferowały produkt prosty i przejrzysty. Często doliczają opłaty za kontrolę nieruchomości, za uruchomienie kredytu, za obowiązkowe ubezpieczenia. Nie będę się tym zajmował, bo nie jest to zagrywka wykonywana tylko przez banki. Nie szukając daleko - wystarczy się przyjrzeć ofertom telefoniii komórkowej. Co istotne, obliczanie najczęściej nie rozpoczyna się też od pożyczonej kwoty. Zanim dojdzie do pierwszej raty, zostaniemy hojnie obdarowani odsetkami.
Przyjmijmy, że pożyczamy kwotę W0. Co się dzieje po miesiącu? Wartość pozostałą do spłaty obliczamy ze wzoru:
W1 oznacza saldo rachunku, W oznacza wpłatę (czyli ratę), a P znormalizowaną miesięczną stopę procentową. Proste. Po dwóch miesiącach mamy:
W2 = W0P2 - WP2 - WP
Przedstawię jeszcze wyliczenia na trzeci miesiąc, po których większość dostrzeże pewną prawidłowość.
Podejrzewam, że już wszystko jasne. Po N miesiącach będziemy mieli
Wystarczy teraz z tego śmiesznego równania wyliczyć W, czyli naszą stałą miesięczną wpłatę. P i W0 są znane. Czeka nass jeszcze jedna podmiana. Po N miesiącach mamy mieć na koncie 0 długu, więc WN musi być równ 0. Popatrzmy na przekształcenia:
0 = W0PN - WPN - WPN-1 - ... - WP2 - WP
Przenosimy szukane wartości na lewo WPN + WPN-1 + ... + WP2 + WP = W0PN
W(PN + PN-1 + ... + P2 + P) = W0PN
Dzielimy stronami przez ten wielki nawias po lewej W = W0PN/(PN + PN-1 + ... + P2 + P)
Taki właśnie sposób wyliczania raty annuitetowej (równej) przyjęty został w algorytmie zaimplementowanym w języku Javascript.
Implemetacja algorytmu w Javascript
Poniżej zamieściłem kod pełnej strony, która może posłużyć za wzorzec innych, podobnych rozwiązań. Kod można skopiować i bez wprowadzania zmian uruchomić w przelglądarce. Dodałem też prosty styl i jakiś miły obrazek, aby strona nie wyglądała zbyt ubogo (zobacz: Harmonogram spłat kredytu hipotecznego - raty annuitetowe (równe)). Oto kod:
<head>
<title>Harmonogram spłat kredytu</title>
<script type="text/javascript">
//Kolejne parametry to
//P - roczna stopa procentowa w postaci dziesiętnej, np 0.06 (czyli 6%)
//R - liczba miesięcznych rat
//W - wartość kredytu, np. 280000
function ObliczRate(P,R,W)
{
P = P/100.0;
//P1 - znormalizowana wartość procentowa
//Jeżeli stopa procentowa jest równa 0.06, postać znormalizowana wynosi 1.06
//Licząc odsetki mnożmymy znormalizowaną wartość przez wartość początkową
var P1 = P+1.0;
//PN - znormalizowana wartość do potęgi N, N - liczba miesięcy
var PN = 1.0;
//PM - miesięczne odsetki, wyliczane ze stopy rocznej jako pierwiastek
//dwunastego stopnia
var PM = Math.pow(P1,1.0/12.0);
//PS - Suma ciągu PM+PM^2+...+PM^(N-1)+PM^N
var PS = 0.0;
for (i=0; i<R; i++)
{
PN *= PM;
PS += PN;
}
//RT - miesięczna rata annuitetowa z dokładnością do dwóch miejsc po przecinku
//Powiększona o odsetki z pierwszego miesiąca, bo zanim zapłacimy pierwszą ratę,
//bank już zdąży naliczyć co trzeba
var RT = Math.round(100*PM*W*PN/PS)/100.0;
//Dynamiczne tworzenie tabeli wynikowej
var res=document.getElementById("ResultTable");
while (res.hasChildNodes())
{
res.removeChild(res.lastChild);
}
var naglowki=["Miesiąc","Rata","Saldo przed spłatą","Kapitał","Odsetki","Saldo po spłacie"];
var tab=document.createElement("table");
var row=document.createElement("tr");
for (i=0;i<naglowki.length;i++)
{
var th=document.createElement("th");
th.innerHTML=naglowki[i];
row.appendChild(th);
}
tab.appendChild(row);
var sumaRat=0.0;
var doSplaty=Math.round(100*W)/100.0;
for (i=0;i<R;i++)
{
//Wartość do spłaty, zaczynamy od wartości początkowej powiększonej o odsetki
//z pierwszego miesiąca
doSplaty=Math.round(100*doSplaty*PM)/100.0;
//Wyrównanie ostatniej raty spowodowane zaokrągleniami
if (i==R-1)
RT=doSplaty;
sumaRat+=RT;
row=document.createElement("tr");
var td=document.createElement("td");
td.innerHTML=(i+1);
row.appendChild(td);
td=document.createElement("td");
td.innerHTML=RT.toFixed(2);
row.appendChild(td);
td=document.createElement("td");
td.innerHTML=doSplaty.toFixed(2);
row.appendChild(td);
//Wartość odsetek w ramach wpłacanej raty
var odsetki=Math.round(100*doSplaty*(PM-1)/PM)/100.0;
td=document.createElement("td");
//Wartość spłacanego kapitału w ramach raty
td.innerHTML=(RT-odsetki).toFixed(2);
row.appendChild(td);
td=document.createElement("td");
td.innerHTML=odsetki.toFixed(2);
row.appendChild(td);
doSplaty=doSplaty-RT;
td=document.createElement("td");
td.innerHTML=doSplaty.toFixed(2);
row.appendChild(td);
tab.appendChild(row);
}
res.appendChild(tab);
}
function ObliczRateClick()
{
var P = parseFloat(document.getElementById("P").value.replace(",", "."));
var R = parseInt(document.getElementById("P").value);
var W = parseInt(document.getElementById("W").value);
ObliczRate(P,R,W);
}
</script>
<style type="text/css">
#ResultTable table{border:solid 1px;border-collapse: collapse;}
#ResultTable table tr th{border: 1px solid;text-align: center;font-weight: bold;background:Yellow;padding: 0 5px;}
#ResultTable table tr td:first-child{text-align: center;padding:0;font-weight: bold;}
#ResultTable table tr td{border: 1px solid;text-align: right;padding: 0 5px 0 10px;}
#ResultTable tr:nth-child(even) {background: #EEE;}
#ResultTable tr:nth-child(odd) {background: #FFF;}
.ClickSpan{background:Yellow;border: 1px solid;font-weight: bold;padding: 2px 5px;cursor:pointer;}
</style>
</head>
<body>
<h1>Harmonogram spłat kredytu</h1>
<p>Sprawdź przybliżony harmonogram spłat kredytu przy ratach annuitetowych (równych).</p>
<table>
<tr><td><b>Liczba miesięcy:</b></td><td><input id="R" type="text" value="360"/></td>
<td rowspan="4"><img src="Skarbonka_Harmonogram_splat.png" title="Harmonogram spłat kredytu"/></td></tr>
<tr><td><b>Oprocentowanie:</b></td><td><input id="P" type="text" value="6,8"/></td></tr>
<tr><td><b>Kwota:</b></td><td><input id="W" type="text" value="280000"/></td></tr>
<tr><td></td><td><span class="ClickSpan" onclick="ObliczRateClick();">Oblicz</span></td></tr>
</table>
<hr/>
<div id="ResultTable"></div>
</body>
</html>
Przykład 1. Harmonogram spłat kredytu hipotecznego - raty annuitetowe (równe).
Kategoria:HTMLJavaScript
Komentarze: