Functional Weave
Code in TypeScript

invest.cagr@1.0.0

README.md

1,677 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.