{"id":"cashflow-xirr","version":"1.0.0","description":"Annual IRR of dated cash flows on the Excel XIRR 365-day basis, with all roots and the chosen root reported.","supported_operations":["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"],"unsupported_operations":["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"],"semantics":["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."],"limits":{"max_items":1000,"max_string_bytes":64,"max_iterations_per_root":200},"pricing":{"status":"unpriced","charge_usd":null},"input_schema":{"type":"object","additionalProperties":false,"required":["cash_flows"],"properties":{"cash_flows":{"type":"array","minItems":2,"maxItems":1000,"items":{"type":"object","additionalProperties":false,"required":["date","amount"],"properties":{"date":{"type":"string","pattern":"^[0-9]{4}-[0-9]{2}-[0-9]{2}$","maxLength":10},"amount":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)(\\.[0-9]+)?$","maxLength":64}}}},"guess":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)(\\.[0-9]+)?$","maxLength":64},"rate_scale":{"type":"integer","minimum":0,"maximum":12},"rounding":{"type":"string","enum":["half-up","half-even","half-down","up","down","ceiling","floor"]}}},"output_schema":{"type":"object","additionalProperties":false,"required":["xirr","roots","sign_changes","multiple_roots_possible","method"],"properties":{"xirr":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)(\\.[0-9]+)?$","maxLength":64},"roots":{"type":"array","minItems":1,"maxItems":48,"items":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)(\\.[0-9]+)?$","maxLength":64}},"sign_changes":{"type":"integer","minimum":1,"maximum":999},"multiple_roots_possible":{"type":"boolean"},"method":{"type":"string","enum":["brent"]}}},"examples":[{"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},"output":{"xirr":"0.3733625","roots":["0.3733625"],"sign_changes":1,"multiple_roots_possible":false,"method":"brent"}},{"input":{"cash_flows":[{"date":"2021-01-01","amount":"-100"},{"date":"2022-01-01","amount":"230"},{"date":"2023-01-01","amount":"-132"}],"guess":"0.25","rate_scale":8},"output":{"xirr":"0.20000000","roots":["0.10000000","0.20000000"],"sign_changes":2,"multiple_roots_possible":true,"method":"brent"}}],"execute_url":"/v1/tools/cashflow-xirr/versions/1.0.0/execute"}