UNPKG

financial-calcs

Version:

Reusable financial calculation library for FERS, Social Security, retirement savings, and mortgage amortization

75 lines 3.01 kB
export function validateMortgageInput(input) { const errors = []; const { loanAmount, annualRate, termYears, extraPayment } = input; if (loanAmount <= 0) errors.push({ field: "loanAmount", message: "Loan amount must be greater than 0" }); if (annualRate < 0) errors.push({ field: "annualRate", message: "Annual interest rate cannot be negative" }); if (termYears <= 0) errors.push({ field: "termYears", message: "Loan term must be greater than 0" }); if (extraPayment !== undefined && extraPayment < 0) errors.push({ field: "extraPayment", message: "Extra payment cannot be negative" }); return errors; } // --- Pure calculation: monthly amortization --- export function calculateMortgageAmortization(input) { const { loanAmount, annualRate, termYears, startDate = new Date(), extraPayment = 0, } = input; const errors = validateMortgageInput(input); if (errors.length > 0) { const err = new Error("Mortgage Amortization input validation failed"); err.validationErrors = errors; throw err; } const monthlyRate = annualRate / 100 / 12; const totalMonths = termYears * 12; const basePayment = monthlyRate === 0 ? loanAmount / totalMonths : loanAmount * (monthlyRate * Math.pow(1 + monthlyRate, totalMonths)) / (Math.pow(1 + monthlyRate, totalMonths) - 1); let balance = loanAmount; const data = []; for (let i = 1; balance > 0.01 && i <= totalMonths; i++) { const interest = balance * monthlyRate; const principal = Math.min(basePayment + extraPayment - interest, balance); balance -= principal; const paymentDate = new Date(startDate.getFullYear(), startDate.getMonth() + i); data.push({ year: Math.ceil(i / 12), month: i, date: paymentDate.toLocaleDateString(), payment: principal + interest, principal, interest, balance: Math.max(balance, 0), }); } return data; } // --- Pure calculation: yearly aggregation --- export function groupByYear(rows) { const yearlyMap = {}; rows.forEach((row) => { const year = Math.floor((row.month - 1) / 12) + 1; // Loan year #1, #2, etc. if (!yearlyMap[year]) { yearlyMap[year] = { year, month: row.month, date: row.date, payment: 0, principal: 0, interest: 0, balance: row.balance, }; } yearlyMap[year].payment += row.payment; yearlyMap[year].principal += row.principal; yearlyMap[year].interest += row.interest; // overwrite with last month’s values yearlyMap[year].month = row.month; yearlyMap[year].date = row.date; yearlyMap[year].balance = row.balance; }); return Object.values(yearlyMap); } //# sourceMappingURL=amortization.js.map