Cashflow xirr
cashflow-xirr · version 1.0.0 · Financial calculations · free, no key needed
Annual IRR of dated cash flows on the Excel XIRR 365-day basis, with all roots and the chosen root reported.
Use when you need to: XIRR of dated cash flows · annualized return with irregular dates · Excel XIRR function equivalent.
Decide before calling
Read the versioned contract and the supported scope below. Reuse cashflow-xirr@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-xirr@1.0.0 for XIRR of dated 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
- XIRR of dated cash flows
- annualized return with irregular dates
- Excel XIRR function equivalent
- internal rate of return with actual dates
- money-weighted return of deposits and withdrawals
- return on an investment with uneven payment dates
- rate that makes XNPV zero
- XIRR with multiple roots
Not supported
- equally spaced flows without dates (use cashflow-irr)
- valuing dated flows at a given rate (use cashflow-xnpv)
- time-weighted return or benchmark-relative performance
- roots below -0.99 or above 1000 per year
Behavior
- Inputs: cash_flows (2 to 1000 objects {date, amount}: date an ISO calendar date YYYY-MM-DD from 1900-01-01 to 2200-12-31, amount a decimal string with |amount| <= 1e12, positive received and negative paid), guess (annual effective rate as a decimal from -0.99 to 1000, default "0.1"), rate_scale (0 to 12, default 10) and rounding (default half-up). Dates may repeat and need not be sorted.
- The XIRR is an annual effective rate r > -1 at which f(r) = sum over the flows of amount_i * (1+r)^(-(d_i - d_1)/365) equals 0, where d_i - d_1 is the exact number of calendar days from the FIRST LISTED date and 365 is used for every year (Excel XIRR). A flow dated before the first listed flow is invalid_input (details.reason date_before_first), matching Excel's #NUM!; list the earliest flow first.
- Several roots can exist. The tool reports every root it finds in roots (ascending) and returns in xirr the one nearest to guess (compared on the binary64 values before rounding; a tie goes to the smaller root). Excel returns a single Newton result near the guess, so where several roots exist the Excel value may differ from xirr; roots lists all of them.
- sign_changes: the amounts are first summed by calendar date, then taken in ascending date order, zeros ignored, and the sign changes of that sequence are counted (Descartes' rule of signs for the exponents d_i/365); multiple_roots_possible is sign_changes > 1. If sign_changes is 0 (for example all flows of one sign, or flows that cancel on the same date, or all flows on a single date) the result is not_computable with details.reason no_sign_change.
- Root finding is on binary64 floats with the pinned fdlibm port: amount_i = Number(decimal string); w_i = ((d_i - d_1) / 365) * log1p(r) (an IEEE division of the integer day count by 365, then a multiplication); f(r) is the sum of amount_i * exp(-w_i) in the listed order (never Math.exp, Math.log or Math.pow). f is evaluated on the fixed annual-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 skips its two adjacent intervals; a grid point where f is exactly 0 is a root; every interval with opposite non-zero end signs is refined by Brent's method (tolerance 1e-14, at most 200 iterations). Roots closer than 1e-12 are merged.
- 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); non-convergence within 200 iterations (no_convergence); a non-finite f value inside Brent's iteration (non_finite_function). Two roots inside one 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 is about 1e-12 absolute, so digits beyond rate_scale 10 are not guaranteed. method is always the string brent. Percent values are not accepted: 0.373362535 means 37.3362535 percent per year.
- More than 1000 cash flows, or any string longer than 64 UTF-8 bytes, is limit_exceeded, checked before parsing.
- 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 object, required): min items 2; max items 1000guess(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
xirr(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 999multiple_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": [
{
"date": "2008-01-01",
"amount": "-10000"
},
{
"date": "2008-03-01",
"amount": "2750"
},
{
"date": "2008-10-30",
"amount": "4250"
},
{
"date": "2009-02-15",
"amount": "3250"
},
{
"date": "2009-04-01",
"amount": "2750"
}
],
"rate_scale": 7
}
Response:
{
"result": {
"xirr": "0.3733625",
"roots": [
"0.3733625"
],
"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-xirr",
"version": "1.0.0",
"input": {
"cash_flows": [
{
"date": "2008-01-01",
"amount": "-10000"
},
{
"date": "2008-03-01",
"amount": "2750"
},
{
"date": "2008-10-30",
"amount": "4250"
},
{
"date": "2009-02-15",
"amount": "3250"
},
{
"date": "2009-04-01",
"amount": "2750"
}
],
"rate_scale": 7
}
}
HTTP (no key)
curl -X POST https://computefirst.net/v1/tools/cashflow-xirr/versions/1.0.0/execute \
-H "Content-Type: application/json" \
-d '{"cash_flows":[{"date":"2008-01-01","amount":"-10000"},{"date":"2008-03-01","amount":"2750"},{"date":"2008-10-30","amount":"4250"},{"date":"2009-02-15","amount":"3250"},{"date":"2009-04-01","amount":"2750"}],"rate_scale":7}'
The machine-readable contract is at /v1/tools/cashflow-xirr/versions/1.0.0.
CLI
node cli.mjs run cashflow-xirr 1.0.0 --input input.json --base-url https://computefirst.net
Get the client at /clients/cli/.
Related tools
- Cashflow xnpv: NPV of dated cash flows with the Excel XNPV 365-day exponent and an explicit valuation date.
- Cashflow irr: IRR of equally spaced cash flows with every root reported, the chosen root named and no-solution cases signalled.
- Cashflow mirr: MIRR of periodic cash flows from a finance rate and a reinvestment rate, with compounded and discounted totals.
- Cashflow npv: NPV of equally spaced cash flows, time-0 or Excel time-1, with inflow PV, outflow PV and profitability index.
- Cashflow payback period: Payback period of periodic cash flows with linear interpolation, optional discounting and the cumulative path.
- Growth cagr compute: CAGR from start and end values or a total return over years or dates, with a sub-year warning.