Skip to content

pyverret/ratejs

Repository files navigation

@pyverret/ratejs

Lightweight, dependency-free TypeScript financial math library providing pure calculation utilities.

Install

npm i @pyverret/ratejs

Validate Before Push

npm run validate

Live Demo

Run locally:

cd demo
npm install
npm run dev

Usage

All functions take a single options object (no positional args). Rates are decimals (e.g. 0.05 = 5%).

Cash-flow sign convention (Excel-style):

  • Cash paid out is negative, cash received is positive.
  • Loan example: presentValue > 0 and payment < 0.
  • Investment withdrawal example: presentValue < 0 and payment > 0.

Excel-style TVM formulas

  • pmt - Excel PMT: payment per period for a loan/investment.
  • pv - Excel PV: present value from payment stream and future value.
  • fv - Excel FV: future value from present value and payment stream.
  • nper - Excel NPER: number of periods required.
  • rate - Excel RATE: implied rate per period. Supports optional guess, maxIterations, lowerBound, and upperBound.
  • npv - Excel NPV: net present value of a cash flow series.
const payment = pmt({
  ratePerPeriod: 0.06 / 12,
  periods: 360,
  presentValue: 250000,
  futureValue: 0, // optional
  timing: "end", // optional
});

const impliedRate = rate({
  periods: 360,
  payment,
  presentValue: 250000,
  futureValue: 0, // optional
  timing: "end", // optional
  guess: 0.1, // optional
  maxIterations: 100, // optional
  tolerance: 1e-10, // optional
  lowerBound: -0.99, // optional
  upperBound: 10, // optional
});

Edge cases:

  • nper throws RangeError when ratePerPeriod <= -1.
  • rate throws RangeError when no root is found within search bounds.
  • pmt, pv, and fv throw RangeError when ratePerPeriod <= -1.

Interest & growth

  • compound - Final amount for a lump sum with compound interest.
compound({ principal: 1000, rate: 0.05, timesPerYear: 12, years: 10 });
  • futureValue - Future value of a present lump sum.
futureValue({ presentValue: 2500, rate: 0.07, timesPerYear: 4, years: 3 });
  • presentValue - Present value of a future lump sum.
presentValue({ futureValue: 5000, rate: 0.06, timesPerYear: 12, years: 5 });
  • investmentGrowth - Future value with optional periodic contributions. Returns { futureValue, totalContributions, totalInterest }.
investmentGrowth({
  initial: 1000,
  contributionPerPeriod: 100, // optional
  rate: 0.06,
  timesPerYear: 12,
  years: 2,
  contributionTiming: "end", // optional ("end" | "begin")
});
  • effectiveAnnualRate - Convert nominal rate + compounding frequency to effective annual rate (EAR).
effectiveAnnualRate({ nominalRate: 0.06, timesPerYear: 12 });
  • periodsToReachGoal — Number of compounding periods until future value reaches a target (lump sum or with contributions).
periodsToReachGoal({
  principal: 1000,
  targetFutureValue: 2000,
  rate: 0.06,
  timesPerYear: 12,
  contributionPerPeriod: 0, // optional
  contributionTiming: "end", // optional
  maxPeriods: 100000, // optional
});

Edge cases:

  • Returns Infinity when the goal is unreachable.

  • Throws RangeError when rate / timesPerYear <= -1.

  • Throws RangeError when maxPeriods is exceeded for contribution-based iteration.

  • Throws RangeError when contributionTiming is not "end" or "begin".

  • rateToReachGoal - Rate per period required to reach a target future value in a given number of periods.

rateToReachGoal({
  principal: 1000,
  targetFutureValue: 1500,
  periods: 24,
  contributionPerPeriod: 0, // optional
  contributionTiming: "end", // optional
  maxIterations: 100, // optional
  tolerance: 1e-10, // optional
  lowerBound: -0.99, // optional
  upperBound: 10, // optional
});

Edge cases:

  • Throws RangeError when no root is found within search bounds.

  • Throws RangeError when contributionTiming is not "end" or "begin".

  • ruleOf72 - Approximate years to double a lump sum at a given annual rate. Optional constant: 69 for rule of 69.

ruleOf72({ rate: 0.07 }); // ~10.3 years
ruleOf72({ rate: 0.07, constant: 69 });

Returns

  • cagr - Compound annual growth rate between a start and end value over years.
cagr({ startValue: 1000, endValue: 2000, years: 10 });
  • irr - Internal rate of return: discount rate that makes NPV of cash flows zero. cashFlows[0] is typically the initial outlay (negative). Supports optional guess, maxIterations, lowerBound, and upperBound.
irr({
  cashFlows: [-1000, 300, 400, 500],
  guess: 0.1, // optional
  maxIterations: 100, // optional
  lowerBound: -0.99, // optional
  upperBound: 10, // optional
});

Edge cases:

  • Throws RangeError when cashFlows is empty.
  • Throws RangeError when cashFlows does not contain at least one positive and one negative value.
  • Throws RangeError when no root is found within search bounds.

Inflation

  • realReturn - Real (inflation-adjusted) return from nominal return and inflation rate.
realReturn({ nominalReturn: 0.07, inflationRate: 0.02 });
  • inflationAdjustedAmount - Purchasing power across time. toPast: value years ago with same purchasing power; toFuture: nominal amount in the future with same purchasing power.
inflationAdjustedAmount({
  amount: 100,
  annualInflationRate: 0.03,
  years: 10,
  direction: "toPast",
});
inflationAdjustedAmount({
  amount: 100,
  annualInflationRate: 0.03,
  years: 10,
  direction: "toFuture",
});

Annuities

  • presentValueOfAnnuity - Present value of a series of equal payments. timing: "end" (ordinary) or "begin" (annuity due).
presentValueOfAnnuity({
  paymentPerPeriod: 100,
  ratePerPeriod: 0.01,
  periods: 36,
  timing: "end", // optional
});
  • paymentFromPresentValue - Periodic payment to pay off a present value (e.g. loan) over a number of periods.
paymentFromPresentValue({
  presentValue: 100000,
  ratePerPeriod: 0.005,
  periods: 360,
  timing: "end", // optional
});

Loans

  • loanPayment - Fixed periodic payment for an amortizing loan (nominal annual rate, payments per year, years).
loanPayment({
  principal: 200000,
  annualRate: 0.06,
  paymentsPerYear: 12,
  years: 30,
});

Edge cases:

  • Throws RangeError when annualRate / paymentsPerYear <= -1.

  • amortizationSchedule - Full schedule: { paymentPerPeriod, schedule, totalPaid, totalInterest }. Optional extraPaymentPerPeriod.

amortizationSchedule({
  principal: 200000,
  annualRate: 0.06,
  paymentsPerYear: 12,
  years: 30,
  extraPaymentPerPeriod: 50, // optional
});
  • remainingBalance - Balance remaining after a given number of payments (1-based afterPeriodNumber).
remainingBalance({
  principal: 200000,
  annualRate: 0.06,
  paymentsPerYear: 12,
  years: 30,
  afterPeriodNumber: 12,
});
  • payoffPeriodWithExtra — Number of periods until the loan is paid off with base payment + extra payment.
payoffPeriodWithExtra({
  principal: 100000,
  annualRate: 0.06,
  paymentsPerYear: 12,
  basePaymentPerPeriod: 599.55,
  extraPaymentPerPeriod: 100,
});

Edge cases:

  • Returns Infinity when payment is zero or does not cover per-period interest.

Utils

  • roundToCurrency - Round to decimal places (default 2). mode: "half-up" or "half-even" (banker's rounding).
roundToCurrency({ value: 2.125 }); // 2.13
roundToCurrency({ value: 2.125, decimals: 2, mode: "half-even" }); // decimals/mode optional

Design

  • Pure functions only
  • No runtime dependencies
  • Object-parameter inputs (no positional args)
  • Deterministic outputs
  • Tree-shakeable (import only what you use)

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages