npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@pyverret/ratejs

v1.1.3

Published

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

Readme

@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)