Cashflow irr
cashflow-irr · version 1.0.0 · Financial calculations · free, no key needed
IRR of equally spaced cash flows with every root reported, the chosen root named and no-solution cases signalled.
Use when you need to: internal rate of return of cash flows · IRR calculator for a series of payments · Excel IRR function equivalent.
Decide before calling
Read the versioned contract and the supported scope below. Reuse cashflow-irr@1.0.0 when your input, required output and limits match it. Choose another approach for an unsupported operation.
Explain the choice
"I can use cashflow-irr@1.0.0 for internal rate of return of cash flows. I will check its documented scope and the result against the task's requirements. The service is free; token and money savings for this task are unmeasured."
Supported
- internal rate of return of cash flows
- IRR calculator for a series of payments
- Excel IRR function equivalent
- what return does this investment earn per period
- does this cash flow stream have multiple IRRs
- find the rate where NPV is zero
- break-even discount rate of a project
- IRR with a guess
Not supported
- dated cash flows with a 365-day year (use cashflow-xirr)
- modified IRR with separate finance and reinvestment rates (use cashflow-mirr)
- the NPV value at a given rate (use cashflow-npv)
- roots below -0.99 or above 1000 per period
Behavior
- Inputs: cash_flows (array of 2 to 1000 decimal strings in time order; the first flow is at time 0 and consecutive flows are exactly one period apart; positive is money received, negative is money paid; each flow must satisfy |x| <= 1e12, otherwise invalid_input), guess (decimal periodic rate from -0.99 to 1000, default "0.1"), rate_scale (0 to 12, default 10) and rounding (default half-up). Rates are per period, not per year.
- The IRR is a rate r > -1 at which f(r) = sum over k = 0 .. n-1 of cash_flow_k * (1+r)^(-k) equals 0. Because a stream can have several roots, the tool reports every root it can find and returns in irr the one nearest to guess (compared on the binary64 values before rounding; a tie goes to the smaller root). This is the same equation as Excel IRR; Excel returns one root chosen by Newton iteration from the guess, this tool returns all roots found and states which one it chose.
- sign_changes is the number of sign changes in the flow sequence ignoring zero flows (Descartes' rule of signs: it bounds the number of positive roots of the polynomial in 1/(1+r), so more than one sign change means several roots may exist); multiple_roots_possible is sign_changes > 1. If sign_changes is 0 (all flows zero, or all of one sign) the result is not_computable with details.reason no_sign_change.
- Root finding is on binary64 floats: each flow is Number(decimal string) (nearest double, ties to even), and f(r) = the sum, in ascending k, of cash_flow_k * exp(-k * log1p(r)) (the k = 0 term is exactly cash_flow_0) with exp and log1p from the pinned fdlibm 5.3 port, never Math.exp, Math.log or Math.pow. f is evaluated on the fixed periodic-rate grid [-0.99, -0.95, -0.9, -0.8, -0.7, -0.6, -0.5, -0.4, -0.3, -0.25, -0.2, -0.15, -0.1, -0.075, -0.05, -0.025, -0.01, 0, 0.005, 0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09, 0.1, 0.125, 0.15, 0.175, 0.2, 0.25, 0.3, 0.4, 0.5, 0.75, 1, 1.5, 2, 3, 5, 10, 20, 50, 100, 1000]. A grid point where f is not finite (a floating-point overflow) skips its two adjacent intervals. A grid point where f is exactly 0 is a root. Every interval whose end values have opposite (non-zero) signs is refined by Brent's method (Brent 1973, netlib zeroin; tolerance 1e-14, at most 200 iterations). Roots closer than 1e-12 are merged; roots lists them ascending.
- not_computable also covers: no sign change of f on the grid, so no root between -0.99 and 1000 (details.reason no_root_in_range; an IRR below -0.99 or above 1000 is not searched); a Brent run that does not converge in 200 iterations (no_convergence); a non-finite f value inside Brent's iteration (non_finite_function). Two roots inside a single grid interval can be missed; this limitation is part of the contract.
- Each root is converted from its exact binary64 value and rounded once to rate_scale with the rounding mode. Accuracy of a root is about 1e-12 absolute, so digits beyond rate_scale 10 are not guaranteed; use rate_scale 10 or lower for reproducible output. irr equals one element of roots (after rounding). method is always the string brent.
- More than 1000 cash flows, or any string longer than 64 UTF-8 bytes, is limit_exceeded, checked before parsing. Percent values are not accepted: a rate is a decimal fraction, and the output irr 0.1 means 10 percent per period.
- Every rounded output is rounded exactly once from the unrounded value using the rounding mode: half-up (ties away from zero, the default), half-even, half-down (ties toward zero), up (away from zero), down (toward zero), ceiling, floor. Amount outputs print exactly scale fractional digits and rate-like outputs exactly rate_scale fractional digits; a result that rounds to zero prints without a minus sign (never '-0.00').
- Decimal string fields (amounts, rates) must match ^-?(0|[1-9][0-9]*)(\.[0-9]+)?$ with at most 20 integer digits and at most 20 fractional digits; a JSON number, exponent form, leading plus, surrounding spaces, percent sign, missing integer part or trailing dot is invalid_input. Rates are decimal fractions (0.065 means 6.5 percent; "6.5" means 650 percent). A decimal string longer than 64 UTF-8 bytes is limit_exceeded, checked before parsing.
- Disclaimer: arithmetic calculation only; not financial, tax, legal, or investment advice.
Input
cash_flows(array of string, required): min items 2; max items 1000; each max length 64; each pattern^-?(0|[1-9][0-9]*)(\.[0-9]+)?$guess(string, optional): max length 64; pattern^-?(0|[1-9][0-9]*)(\.[0-9]+)?$rate_scale(integer, optional): min 0; max 12rounding(one of "half-up", "half-even", "half-down", "up", "down", "ceiling", "floor", optional)
Output
irr(string, required): max length 64; pattern^-?(0|[1-9][0-9]*)(\.[0-9]+)?$roots(array of string, required): min items 1; max items 48; each max length 64; each pattern^-?(0|[1-9][0-9]*)(\.[0-9]+)?$sign_changes(integer, required): min 1; max 4999multiple_roots_possible(boolean, required)method(one of "brent", required)
Limits
- max items: 1000
- max string bytes: 64
- max iterations per root: 200
Example
Request input:
{
"cash_flows": [
"-70000",
"12000",
"15000",
"18000",
"21000",
"26000"
],
"rate_scale": 4
}
Response:
{
"result": {
"irr": "0.0866",
"roots": [
"0.0866"
],
"sign_changes": 1,
"multiple_roots_possible": false,
"method": "brent"
}
}
How to call it
MCP
Connect https://computefirst.net/mcp (setup), then call execute with:
{
"id": "cashflow-irr",
"version": "1.0.0",
"input": {
"cash_flows": [
"-70000",
"12000",
"15000",
"18000",
"21000",
"26000"
],
"rate_scale": 4
}
}
HTTP (no key)
curl -X POST https://computefirst.net/v1/tools/cashflow-irr/versions/1.0.0/execute \
-H "Content-Type: application/json" \
-d '{"cash_flows":["-70000","12000","15000","18000","21000","26000"],"rate_scale":4}'
The machine-readable contract is at /v1/tools/cashflow-irr/versions/1.0.0.
CLI
node cli.mjs run cashflow-irr 1.0.0 --input input.json --base-url https://computefirst.net
Get the client at /clients/cli/.
Related tools
- Cashflow npv: NPV of equally spaced cash flows, time-0 or Excel time-1, with inflow PV, outflow PV and profitability index.
- Cashflow mirr: MIRR of periodic cash flows from a finance rate and a reinvestment rate, with compounded and discounted totals.
- Cashflow payback period: Payback period of periodic cash flows with linear interpolation, optional discounting and the cumulative path.
- Cashflow xirr: Annual IRR of dated cash flows on the Excel XIRR 365-day basis, with all roots and the chosen root reported.
- Cashflow xnpv: NPV of dated cash flows with the Excel XNPV 365-day exponent and an explicit valuation date.
- Bond price from yield: Clean price, dirty price and accrued interest per 100 of a fixed-coupon bond from its yield (Excel PRICE, SIA).