50 lines
2.5 KiB
JavaScript
50 lines
2.5 KiB
JavaScript
import {currency, revive, persist, labelInput, labelSelect} from '/js/util.js';
|
|
export default {
|
|
id:'interest', name:'Interest (Simple & Compound)', about:'Compute simple or compound interest with flexible compounding and contributions.',
|
|
render(root){
|
|
const key='calc_interest_v1';
|
|
const s = revive(key,{principal:1000, rate:5, years:3, compound:'12', contrib:0, contribFreq:'12'});
|
|
const ui = document.createElement('div');
|
|
ui.append(
|
|
labelInput('Principal','number','principal', s.principal,{step:'0.01',min:'0'}),
|
|
labelInput('Annual rate (%)','number','rate', s.rate,{step:'0.0001',min:'0'}),
|
|
labelSelect('Compounding','compound', s.compound, [['1','Yearly'],['4','Quarterly'],['12','Monthly'],['365','Daily'],['0','Simple (no compounding)']]),
|
|
labelInput('Years','number','years', s.years,{step:'0.1',min:'0'}),
|
|
labelInput('Recurring contribution (per period below)','number','contrib', s.contrib,{step:'0.01',min:'0'}),
|
|
labelSelect('Contribution frequency','contribFreq', s.contribFreq, [['1','Yearly'],['4','Quarterly'],['12','Monthly']])
|
|
);
|
|
const out = document.createElement('div'); out.className='result'; ui.append(out);
|
|
|
|
function calc(){
|
|
const P = +ui.querySelector('[name=principal]').value||0;
|
|
const r = (+ui.querySelector('[name=rate]').value||0)/100;
|
|
const years = +ui.querySelector('[name=years]').value||0;
|
|
const n = +ui.querySelector('[name=compound]').value; // 0 => simple
|
|
const A = +ui.querySelector('[name=contrib]').value||0;
|
|
const f = +ui.querySelector('[name=contribFreq]').value||1;
|
|
|
|
let future=0, interest=0;
|
|
if(n===0){
|
|
interest = P * r * years;
|
|
const contribs = A * f * years;
|
|
future = P + interest + contribs;
|
|
}else{
|
|
const periods = n * years;
|
|
const i = r / n;
|
|
future = P * Math.pow(1+i, periods);
|
|
if(A>0){
|
|
const eff = Math.pow(1+i, n/f) - 1;
|
|
const m = Math.round(periods * f / n);
|
|
future += A * ((Math.pow(1+eff, m) - 1) / eff);
|
|
}
|
|
interest = future - P - (A>0?A*Math.round(n*years * f / n):0);
|
|
}
|
|
out.innerHTML = `
|
|
<div><strong>Future value:</strong> ${currency(future)}</div>
|
|
<div class="muted">Estimated interest earned: ${currency(Math.max(0,interest))}</div>
|
|
`;
|
|
persist(key,{principal:P, rate:r*100, years, compound:String(n), contrib:A, contribFreq:String(f)});
|
|
}
|
|
ui.addEventListener('input', calc); calc(); root.append(ui);
|
|
}
|
|
}
|