55 lines
1.7 KiB
TypeScript
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;
|
|
}
|