R Bloggers iconR BloggersSep 21, 2026 ~7 min source read

When Chain-Ladder Factors Misbehave: Chain-Ladder in Polars and Whittaker-Henderson Smoothing

A practical walk-through of running Chain-Ladder reserving for 233 insurers using polars, validation against R's ChainLadder, and handling a non-monotonic development pattern with Whittaker-Henderson smoothing that materially alters reserve estimates.

When Chain-Ladder Factors Misbehave: Smoothing Reserves with Polars and Whittaker-Henderson

Share this story

Send the public story page.

Useful takeaways from this story.

You can implement a full Chain-Ladder reserving run for hundreds of companies using a modern dataframe library (polars) in a few lines and avoid manual Excel work.

One insurer in the CAS Other Liability dataset shows a non-monotonic incurred development pattern that causes parametric curve fits to struggle.

Whittaker-Henderson smoothing (now available as scipy.signal.whittaker_henderson) handles that difficult pattern and changes the estimated reserve by about 3% compared with a straight Chain-Ladder run.

# What this exercise covers This work reproduces Chain-Ladder reserving across 233 US insurers for the CAS Other Liability line of business (accident years 1998–2007, development lags 1–10) using polars dataframes. Results are cross-checked against R's ChainLadder package. The focus is both on scalable implementation and on a specific data issue: a non-monotonic incurred development pattern that breaks many standard curve-fitting approaches.

# Dataset and setup The data are the CAS loss reserving dataset for Other Liability, aggregated to paid and incurred values by insurer (GRNAME), accident year, and development lag. The reporting year is treated as 2007 to simulate a year-end closing. The triangle is kept in long (tidy) format rather than wide triangle matrices.

# Chain-Ladder in polars The Chain-Ladder steps are implemented with group_by and window operations: aggregate cumulative values, filter to the observed upper-left triangle, compute previous-period columns with shift(...). Volume-weighted development factors are computed per development lag and per insurer for both paid and incurred. The polars pipeline avoids explicit loops and reproduces R's ChainLadder output for at least one insurer (Grinnell Mut Grp), confirming correctness of the implementation.

# The problem case: a non-monotonic incurred pattern Most development patterns are monotonic or smoothly varying. One insurer in the dataset shows a non-monotonic incurred development pattern. Such patterns are problematic for typical parametric curve fits and some smoothing approaches because they contradict the usual assumption of monotone, smoothly decaying development.

# Applying Whittaker-Henderson smoothing Whittaker-Henderson smoothing, accessible in scipy as scipy.signal.whittaker_henderson, is applied to the difficult incurred curve. The method handles the non-monotonic shape without producing unstable parametric fits. When used to smooth the development factors and re-calculate reserves, the smoothed approach shifts the estimated reserve by about 3% relative to the raw Chain-Ladder result for that insurer.

# Practical implications for reserving workflows

  • Validate automated implementations against trusted packages (R's ChainLadder was used here) for at least a sample of companies.
  • Watch for non-monotonic development patterns: they can produce materially different reserves if smoothed differently.

# What changed and what to watch next The workflow demonstrates a reproducible, auditable way to run Chain-Ladder for many insurers and to apply alternative smoothing treatments where needed. For reserving teams, the immediate next steps are to (1) inspect triangles for non-monotonic shapes, (2) validate smoothing choices against business and actuarial judgment, and (3) quantify sensitivity of reserves to smoothing method choices.

More context around this story.

Loading more related stories...

Keep reading in the app

Open the app view to save this story, compare related coverage, and continue from the same source.

Open in app