Reusable financial formulas
The financial-formulas pack names calculations that repeat across model examples. It works with ordinary fields, calculations, cashflows and metrics, so it can be adopted without changing the engine's model structure. In the Calculator, select Financial formulas; loans and savings select it automatically.
Configure a formula once
const { formulas } = modules["financial-formulas"];
const paymentAmount = formulas.amount.shareOf({
amount: monthlyIncome,
share: paymentShare,
});
const payment = cashflow({
owner: borrower,
direction: outflow,
schedule: schedule.monthly(),
amount: (ctx) => paymentAmount(ctx),
});The factory returns a function for the current model context. It carries nested input references as preconditions. If a callback reads other inputs, declare those inputs on the model or enclosing component. Read a flow through ctx.get(flow) only after declaring the flow in dependsOn.
Period rates and growth
const monthlyRate = formulas.rates.period({ annualRate, convention: "effective" });
const incomeAtMonth = formulas.growth.compound({
base: startingIncome,
periodRate: monthlyRate,
elapsedPeriods: (ctx) => ctx.time.index,
});With an effective annual rate a, the equivalent period rate is (1 + a)^(1/N) - 1, where N comes from the model calendar. A nominal annual rate defaults to a/N. Pass compoundsPerYear when the annual nominal rate is capitalized more often than the model reports. growth.annualStep changes its factor once per full model year; growth.decay models a fixed per-period loss. These closed-form helpers are for fixed assumptions. For a curve or changing periodic amounts, update a balance with a savings or loan plan so each period uses its own rate.
Savings and loans
const { savingsPlan } = modules.savings;
const fund = savingsPlan({
openingBalance: currentSavings,
annualRate,
contribution: monthlyDeposit,
contributionPlacement: "end",
withdrawal: (ctx) => ctx.time.index < 120 ? 0 : ctx.savings.openingBalance / 25,
});The returned component declares the recurring fields, calculations and contribution/withdrawal cashflows. Withdrawals are capped by available assets by default, and withdrawalShortfall remains separate from the actual withdrawal. A fee reduces the balance once and is not emitted as a second external cashflow.
const { loanPlan, repayments } = modules.loans;
const loan = loanPlan({
openingBalance: principal,
annualRate: annualRateCurve,
payment: repayments.annuity({ payments: 360 }),
});loanPlan samples a curve on each model-period date and exposes calculation handles, fields and cashflows. Fixed total payments, fixed-principal payments, interest-only, bullet and recast annuity rules are available. A payment is limited to the amount due, preventing an extra negative balance after payoff. The horizon does not itself create a maturity date.
Metrics, valuation and accounting
formulas.metrics.cumulative({ flows }) sums selected flows through the current period. For NPV, choose a common placement and use the flow's declared placement:
const projectValue = formulas.metrics.discountedCashflows({
cashflows: [
{ flow: investment, placement: "start" },
{ flow: benefits, placement: "start" },
],
annualRate: discountRate,
});The result contains ordinary npv and paybackPeriod metric declarations. A missing payback crossing is undefined, not zero. Use valuation.realValue for nominal amounts divided by a positive price index, and snapshots.atPeriod to retain a calculation at a selected period. accounting.openingDebit and openingCredit expose positive debit/credit balances from an account's prior period; choose one explicitly for the account's sign convention.
Other included formulas
usage.fromEfficiencyandusage.fromIntensitycalculate quantities;usage.costprices a quantity. The model remains responsible for matching units such as miles, kilometres, gallons and litres.business.operatingResult,breakEvenUnits,cashRunwayandratiokeep domain cases readable. Non-positive margins and denominators do not become false numeric zeroes.workingCapital.cycleDays,netBalance,fundingCost,unpaidShareandvat.netencode common working-capital arithmetic. VAT is a signed arithmetic estimate, not a tax engine.dates.shiftMonth("2026-12", 1)returns2027-01and is useful in existing derived date inputs.
Package exports and types are documented in the Financial formulas pack guide.