Functional Weave
Code in TypeScript

banking.savings-aer@1.0.0

impl/typescript.ts

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.
 */
export function savingsAer(grossRateBasisPoints: number, paymentsPerYear: number): number {
  if (!Number.isInteger(grossRateBasisPoints) || grossRateBasisPoints < 0 || grossRateBasisPoints > 100000) {
    throw new RangeError(`grossRateBasisPoints must be between 0 and 100000, received ${grossRateBasisPoints}`);
  }
  if (!Number.isInteger(paymentsPerYear) || paymentsPerYear < 1 || paymentsPerYear > 365) {
    throw new 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));
}