Functional Weave
Code in TypeScript

fleet.vehicle-depreciation@1.0.0

README.md

1,928 bytes · view raw

# fleet.vehicle-depreciation

A vehicle's value today from what it cost, its age and its mileage, on
retention curves you supply, and how much it has lost. There is no built-in
market data: residual values differ by make, model and year, and belong to
whoever publishes them (CAP HPI, Glass's, your own disposals). This does the
arithmetic on the curve you have, exactly.

## The curves

- `retainedPerYearBasisPoints` is the share of value kept through each year of
  age, first year first. `[8000, 8500, 8800]` means the vehicle keeps 80% of
  its value in year one, 85% of what is left in year two and 88% in year
  three; from year four on the last entry (88%) repeats. A part year is a
  straight-line share of that year's loss: six months into a year that keeps
  80% keeps 90%.
- `retainedPer10kMilesBasisPoints` is the share kept for every 10,000 miles,
  compounding per whole 10,000 and straight-line within one: at 90% per 10k,
  15,000 miles keeps 0.9 x 0.95 = 85.5%.

The two multiply: value = cost x age factor x mileage factor. Build the age
curve for a vehicle doing no miles (or your curve's baseline mileage) if you
use both; if your age curve already assumes an average mileage, pass `10000`
for the mileage rate and adjust separately.

## Exactness

Every factor is a fraction of integers, so the product is kept as one exact
fraction (in big integers, via `math.round-div-big`) and rounded once to the
minor unit with the `mode` you choose. Valuing year by year and rounding each
year drifts. `retainedBasisPoints` is the exact combined share, rounded
half-up to a basis point, for display; the value is not derived from it.

## Limits and errors

Age 0 to 600 months (50 years); mileage 0 to 2,000,000; every rate 0 to 10000
basis points (a vehicle that gains value is outside this model). A negative
cost, an empty curve, a value out of range, a fractional number or an unknown
rounding mode is an error.