Functional Weave
Code in Rust

invest.cagr@1.0.1

README.md

2,758 bytes · view raw

# invest.cagr

The compound annual growth rate: the constant yearly rate that turns the start
value into the end value over the holding period,

    CAGR = (end / start)^(1 / years) − 1

returned in basis points (718 = 7.18% a year).

## Why it is shaped this way

- **Years are a fraction**, `yearsNumerator / yearsDenominator`, so 18 months
  is `3, 2` and 30 days is `30, 365`. A float number of years would put the
  platform's `pow` back into the answer, and it differs by an ulp across
  languages.
- **Short periods are annualised by compounding**, not scaled: 5% in six
  months is 10.25% a year, not 10%. Whether a return under a year should be
  annualised at all is the caller's decision (GIPS says not to present one);
  this function does what it is asked.
- **Exact arithmetic.** end / start is taken to 18 decimal places (floored),
  and raised to 1 / years with `math.fractional-power`'s 18-place fixed point,
  which floors every step in the same order in every language. The result is
  then rounded to a whole basis point, **half away from zero**: +0.5 bp is 1,
  −0.5 bp is −1. The fixed-point error is around 10^-16, far below the half
  basis point, and a power that is exact in 18 places (1.21^(1/2) = 1.1) comes
  out exact.

## Edge cases

- An end value of zero is a total loss, −10000 (−100%), for any period.
- Equal values are 0.
- The start must be greater than zero, the end must not be negative, and both
  must be in the same currency.
- `yearsNumerator` and `yearsDenominator` are whole numbers from 1 to 100000.
- A growth so large the rate cannot be held (e.g. a thousandfold rise in a
  week) is an error rather than an overflow.

## Before you rely on this

**Not professional advice.** This capability calculates investment figures from published rules. It is a software component for developers, not financial advice. Rules change and every rate here has an effective date. Check that the dates cover your case. Verify results against the official sources listed above, and have a tax adviser review how you use it, before anyone relies on the output. Provided "as is" under its licence, without warranty.

**Unreviewed.** This capability's implementations agree in every language and pass its published test vectors, which were worked out from the official sources cited. But no qualified tax adviser has yet checked those vectors, or confirmed that the capability covers the cases it claims. Treat it as a draft. Do not use it for real people, money or decisions without your own expert review. Once a qualified reviewer signs off, this notice is replaced with their name, qualification and the date. Each new version needs fresh sign-off.

1.0.1 marks it unreviewed. The code and the tests are unchanged.