init
This commit is contained in:
commit
97f9a95415
21 changed files with 2963 additions and 0 deletions
50
public/calculators/interest.js
Normal file
50
public/calculators/interest.js
Normal file
|
@ -0,0 +1,50 @@
|
|||
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);
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue