Files
simo/src/lib/financial.ts

55 lines
1.7 KiB
TypeScript

/**
* Core financial functions replicating Excel's PMT, IPMT, PPMT.
* All functions return positive values (Excel returns negative for payments).
*/
/**
* PMT — Fixed periodic payment for a loan.
* Equivalent to Excel: -PMT(rate, nper, pv)
*/
export function pmt(rate: number, nper: number, pv: number): number {
if (pv <= 0 || nper <= 0) return 0;
if (rate === 0) return pv / nper;
const factor = Math.pow(1 + rate, nper);
return (pv * rate * factor) / (factor - 1);
}
/**
* IPMT — Interest portion of a specific payment period.
* Equivalent to Excel: -IPMT(rate, per, nper, pv)
* @param per 1-based period number
*/
export function ipmt(rate: number, per: number, nper: number, pv: number): number {
if (rate === 0 || pv <= 0 || nper <= 0) return 0;
const bal = remainingBalance(rate, per - 1, nper, pv);
return bal * rate;
}
/**
* PPMT — Principal portion of a specific payment period.
* Equivalent to Excel: -PPMT(rate, per, nper, pv)
* @param per 1-based period number
*/
export function ppmt(rate: number, per: number, nper: number, pv: number): number {
if (pv <= 0 || nper <= 0) return 0;
return pmt(rate, nper, pv) - ipmt(rate, per, nper, pv);
}
/**
* Remaining balance after `per` payments.
* @param per Number of payments already made (0 = initial balance)
*/
export function remainingBalance(rate: number, per: number, nper: number, pv: number): number {
if (pv <= 0 || nper <= 0) return 0;
if (per <= 0) return pv;
if (per >= nper) return 0;
if (rate === 0) {
return pv - pmt(rate, nper, pv) * per;
}
const payment = pmt(rate, nper, pv);
const factor = Math.pow(1 + rate, per);
return pv * factor - payment * (factor - 1) / rate;
}