Created
December 3, 2017 18:22
-
-
Save gillesdemey/6e34f99e622e16b64cf03ee85f1ed766 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict' | |
const AMOUNT = 300000 | |
const YEARS = 25 | |
const RATE = 2.19 | |
const MONTHS = yearsToMonths(YEARS) | |
const MONTHLY = monthly(AMOUNT, YEARS, RATE) | |
// generate an array with shorted name of each month | |
const MONTHNAMES = new Array(12).fill().map((_, i) => { | |
return new Date(0, i).toLocaleString('en', { month: 'short' }) | |
}) | |
function monthly (amount, years, rate) { | |
const mPrate = prate(rate) | |
const months = yearsToMonths(years) | |
const mPow = Math.pow(1 + mPrate, months) | |
return amount * (mPrate * mPow) / (mPow - 1) | |
} | |
function monthlyBreakdown (amount, years, rate) { | |
let leftToPay = amount | |
let totalInterest = 0 | |
const monthlyPay = monthly(amount, years, rate) | |
return new Array(yearsToMonths(years)).fill().map((_, month) => { | |
const interest = getInterest(leftToPay, rate) | |
const aflos = monthlyPay - interest | |
leftToPay -= aflos | |
totalInterest += interest | |
return { month, monthlyPay, aflos, interest, leftToPay } | |
}) | |
} | |
const breakdown = monthlyBreakdown(AMOUNT, YEARS, RATE) | |
const totalCap = sum(breakdown, 'aflos') | |
const totalInterest = sum(breakdown, 'interest') | |
const totalSum = totalCap + totalInterest | |
const monthlyBreakdownLines = breakdown.map((perMonth, i) => { | |
const { month, monthlyPay, aflos, interest, leftToPay } = perMonth | |
return `${MONTHNAMES[i]} ${monthlyPay.toFixed(2)} ${aflos.toFixed(2)} ${interest.toFixed(2)} ${leftToPay.toFixed(2)}` | |
}) | |
const yearlyBreakdownLines = chunk(breakdown, 12).map((months, i) => { | |
const yearlyPay = sum(months, 'monthlyPay').toFixed(2) | |
const yearlyAflos = sum(months, 'aflos').toFixed(2) | |
const yearlyInterest = sum(months, 'interest').toFixed(2) | |
const leftToPay = months.slice(12) | |
return `Year ${i + 1} ${yearlyPay} ${yearlyAflos} ${yearlyInterest} ${leftToPay}` | |
}) | |
console.log(` | |
Quick & dirty mortgage simulator | |
Written by nib, (c) GPL | |
Modified by Gilles De Mey | |
Amount loaned ..... : € ${AMOUNT} | |
Duration .......... : ${YEARS} years | |
Duration .......... : ${yearsToMonths(YEARS)} months | |
Fixed rate ........ : ${RATE} % | |
Periodic rate...... : ${(prate(RATE) * 100).toFixed(3)} % | |
Monthly pay ....... : € ${MONTHLY.toFixed(6)} | |
Year 1 | |
${monthlyBreakdownLines.slice(0, 12).join('\n ')} | |
${yearlyBreakdownLines.slice(1).join('\n')} | |
Total capital ..... : € ${totalCap.toFixed(2)} | |
Total interest .... : € ${totalInterest.toFixed(2)} | |
Sum ................: € ${totalSum.toFixed(2)} | |
`) | |
function yearsToMonths (years) { | |
return years * 12 | |
} | |
function prate (rate) { | |
return Math.pow((rate / 100) + 1, 1 / 12) - 1 | |
} | |
function getInterest (amount, rate) { | |
return prate(rate) * amount | |
} | |
// split array in smaller chunks | |
function chunk (list, size) { | |
return new Array(Math.ceil(list.length / size)).fill().map(_ => list.splice(0, size)) | |
} | |
// sum of a property in an array | |
function sum (array, prop) { | |
return array.reduce((sum, obj) => sum += obj[prop], 0) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment