1,190 bytes · the TypeScript implementation · view raw
/** * The AER of a gross rate paid `paymentsPerYear` times a year: * (1 + i / n)^n − 1, per the UK Finance / BSA AER Practice Note formula (d), * rounded half-up to two decimal places of a percent (a whole basis point). * * With i = b / 10000 and D = 10000 × n the exact value in basis points is * 10000 × ((D + b)^n − D^n) / D^n, computed in integers and rounded once. */exportfunction savingsAer(grossRateBasisPoints: number, paymentsPerYear: number): number {
if (!Number.isInteger(grossRateBasisPoints) || grossRateBasisPoints < 0 || grossRateBasisPoints > 100000) {
thrownew RangeError(`grossRateBasisPoints must be between 0 and 100000, received ${grossRateBasisPoints}`);
}
if (!Number.isInteger(paymentsPerYear) || paymentsPerYear < 1 || paymentsPerYear > 365) {
thrownew RangeError(`paymentsPerYear must be between 1 and 365, received ${paymentsPerYear}`);
}
const n = BigInt(paymentsPerYear);
const d = 10000n * n;
const whole = d ** n;
const numerator = 10000n * ((d + BigInt(grossRateBasisPoints)) ** n - whole);
// Half-up for a non-negative fraction: floor((2N + M) / 2M).return Number((2n * numerator + whole) / (2n * whole));
}