Chain-ladder claims reserving on a run-off triangle — development factors, ultimates, IBNR, and a leave-one-diagonal-out backtest.
Open-source insurance-AI starter. A clean, dependency-free implementation of the chain-ladder method: from a cumulative claims run-off triangle it estimates volume-weighted development factors, squares the triangle, and computes ultimates and IBNR (incurred-but-not-reported) reserves — plus a simple backtest so you can sanity-check the projection.
⚠️ Starter / research code. Deterministic chain-ladder only — no tail factors, bootstrap, or Mack standard errors yet (good next steps).
git clone https://github.com/Vaynork/reserving-ml
cd reserving-ml
pip install -e ".[dev]"No runtime dependencies — pure standard library.
from reserving_ml import ChainLadder, development_factors, ibnr
# cumulative paid claims, ragged run-off triangle (row i observed up to development n-1-i)
triangle = [
[1000, 1500, 1800, 1980],
[1100, 1650, 1980],
[1200, 1800],
[1300],
]
development_factors(triangle) # [1.5, 1.2, 1.1]
cl = ChainLadder(triangle).fit()
cl.ultimates() # projected ultimate per accident year
cl.ibnr() # {'per_accident_year': [...], 'total': ...}Run the demo: python -m reserving_ml
development_factors— volume-weighted age-to-age factors.project— squares the triangle by applying the factors down the run-off.ultimates— projected ultimate cost per accident year.ibnr— ultimate minus the latest reported diagonal (the held reserve), per year and total.backtest_last_diagonal— drops the most recent diagonal, re-predicts it and reports MAE/MAPE.