Skip to content

Repository files navigation

finprecise

A reference-grade financial calculation engine for TypeScript.

Explicit assumptions. Reproducible results. Verifiable answers.

finprecise is not another collection of financial helper functions. It is a calculation foundation where every assumption — rate convention, day count, rounding rule, solver behavior — is visible in the API and reproducible across Node.js, Bun, Deno, and browsers.

Why finprecise?

Existing TypeScript/JavaScript financial libraries have gaps:

  • financial covers numpy-financial basics but explicitly excludes arbitrary-precision decimals
  • financejs and xirr are aging implementations (2017, 2020) with no day-count or rounding controls
  • None expose solver diagnostics ("did it converge?", "why did it fail?")

finprecise fills these gaps:

  • Decimal-first: All calculations use decimal.js — no floating-point surprises
  • Assumptions are explicit: Day count convention, compounding frequency, payment timing, and rounding mode are API parameters — sensible defaults exist where industry convention is clear, but nothing is hidden
  • Solver transparency: IRR/XIRR/rate return SolveResult — convergence status, iteration count, and failure reasons
  • Verification-ready: Ships with fixtures cross-referenced against numpy-financial and Excel

Packages

PackageDescription
@finprecise/coreDecimal, Rate, DayCount, Rounding, Solver
@finprecise/cashflowPV, FV, PMT, NPER, RATE, NPV, XNPV, IRR, XIRR, MIRR
@finprecise/loansAmortization schedules: level-payment, level-principal, interest-only, bullet, variable-rate, prepayment
@finprecise/depreciationSLN, DB, DDB, SYD (Excel-compatible)
@finprecise/bondsBond pricing, YTM, Macaulay/modified duration, convexity
@finprecise/formatDisplay formatting via Intl.NumberFormat (separated from calculation)
@finprecise/fixturesVerification data for numpy-financial and Excel compatibility

Quick Start

npm install @finprecise/core @finprecise/cashflow

Time Value of Money

import{periodicRate}from"@finprecise/core";import{pv,pmt,irr,xirr}from"@finprecise/cashflow";// Monthly payment on a $200,000 mortgage at 6% annual for 30 yearsconstmonthlyRate=periodicRate("0.06","monthly");// → 0.005constpayment=pmt(monthlyRate,"360","200000");// → -1199.10 (you pay $1,199.10/month)// Present value of $1,000/year for 10 years at 5%constpresentValue=pv("0.05","10","-1000");// → 7721.73// IRR with solver diagnosticsconstresult=irr(["-100000","30000","35000","40000","25000"]);if(result.ok){console.log(`IRR: ${result.value.toFixed(4)}, converged in ${result.iterations} iterations`);}else{console.log(`Failed: ${result.reason}${result.detail}`);}

XIRR with Explicit Day Count

import{xirr}from"@finprecise/cashflow";constresult=xirr({cashflows: [{amount: "-100000",date: "2025-01-10"},{amount: "25000",date: "2025-06-30"},{amount: "90000",date: "2026-03-01"},],dayCount: "act/365-fixed",solver: {method: "hybrid",guess: "0.10",maxIterations: 128,tolerance: "1e-12",},});

Loan Amortization Schedule

import{loanSchedule}from"@finprecise/loans";constschedule=loanSchedule({principal: "350000",periods: 360,repayment: {kind: "level-payment"},rateSteps: [{from: 1,annualRate: "0.0475"},{from: 37,annualRate: "0.0610"},],accrual: {dayCount: "30e/360",compounding: "monthly"},rounding: {interest: "half-up",payment: "half-up",balance: "half-up",scale: 2,},});// Every row shows: period, beginBalance, payment, principal, interest, endBalance, annualRatefor(constrowofschedule.rows.slice(0,3)){console.log(`#${row.period} | Balance: ${row.beginBalance} | Payment: ${row.payment} | `+`Principal: ${row.principal} | Interest: ${row.interest} | End: ${row.endBalance}`);}console.log(`Total interest: ${schedule.summary.totalInterest}`);

Depreciation

import{sln,ddb,syd}from"@finprecise/depreciation";// Straight-line: $30,000 asset, $7,500 salvage, 10 yearssln("30000","7500","10");// → 2250// Double-declining balanceddb("1000000","100000","6","1");// → 333333.33// Sum-of-years-digitssyd("30000","7500","10","1");// → 4090.91

Rate Conversions

import{effectiveAnnualRate,nominalAnnualRate}from"@finprecise/core";// 12% nominal with monthly compounding → 12.68% effectiveeffectiveAnnualRate("0.12","monthly");// → 0.126825...// Convert backnominalAnnualRate("0.126825","monthly");// → 0.12...

Design Principles

1. Assumptions Are API Parameters

Every function that depends on conventions exposes them as API parameters. Sensible defaults are provided where industry convention is clear, but all can be overridden explicitly:

  • PaymentTiming: "begin" or "end" (default "end" — ordinary annuity, matching Excel/numpy-financial)
  • DayCountConvention: "act/365-fixed", "30/360", "act/act-isda", etc. (default "act/365-fixed" for XIRR/XNPV)
  • CompoundingFrequency: "monthly", "quarterly", "continuous", etc.
  • RoundingMode: "half-up", "half-even", "down", etc.
  • SolverConfig: method, guess, maxIterations, tolerance (default: hybrid, 0.10, 128, 1e-12)

2. Solver Results Are Transparent

IRR, XIRR, and RATE return a discriminated union:

typeSolveResult=|{ok: true;value: Decimal;iterations: number}|{ok: false;reason: "no-bracket"|"no-convergence";detail?: string}

3. Decimal-First, Display-Last

  • All calculations use decimal.js for arbitrary precision
  • Inputs accept string | number | Decimal (strings recommended)
  • Display formatting is in a separate @finprecise/format package using Intl.NumberFormat
  • Computation and display are strictly separated

4. Verification Over Documentation

The @finprecise/fixtures package provides cross-referenced expected values from numpy-financial and Excel, so users can verify results against authoritative sources.

Compatibility

Functionnumpy-financialExcelNotes
pvnpf.pvPVIdentical sign convention
fvnpf.fvFVIdentical sign convention
pmtnpf.pmtPMTIdentical sign convention
npernpf.nperNPER
ratenpf.rateRATEReturns SolveResult
ipmtnpf.ipmtIPMT
ppmtnpf.ppmtPPMT
npvnpf.npvFirst cashflow discounted (numpy convention)
xnpvXNPVConfigurable day count
irrnpf.irrIRRReturns SolveResult
xirrXIRRReturns SolveResult, configurable day count
mirrnpf.mirrMIRR
yearFracYEARFRACAll 6 basis types
slnSLN
ddbDDB
sydSYD

Project Structure

packages/
core/ — Decimal, Rate, DayCount, Rounding, Solver
cashflow/ — TVM functions, NPV, IRR, XIRR, MIRR
loans/ — Amortization schedule engine
depreciation/ — SLN, DB, DDB, SYD
bonds/ — Bond pricing, YTM, duration, convexity
format/ — Display formatting (Intl.NumberFormat)
fixtures/ — Verification data

Development

pnpm install
pnpm build
pnpm test

Tests include:

  • Unit tests against numpy-financial and Excel expected values
  • Property-based tests with fast-check (TVM round-trips, IRR→NPV=0)
  • Day count convention tests for all 6 basis types
  • Solver convergence tests

Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Add tests (including fixtures for new functions)
  4. Ensure pnpm test passes
  5. Submit a pull request

License

MIT

About

No description, website, or topics provided.

Resources

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages