Skip to content

Quickstart

Loading data

From a long-format DataFrame (e.g. the CAS Loss Reserve Database):

import pandas as pd
from reserving import Triangle

df = pd.read_csv("wkcomp_pos.csv")
tri = Triangle.from_dataframe(
    df,
    origin="AccidentYear",
    dev="DevelopmentLag",
    values="CumPaidLoss"
)
print(tri)

From a pivot-format DataFrame:

import pandas as pd
from reserving import Triangle

data = pd.DataFrame(
    {1: [1000, 1200, 900],
     2: [1100, 1300, None],
     3: [1150, None, None]},
    index=[2021, 2022, 2023]
)
tri = Triangle(data)

Chain-ladder

from reserving import ChainLadder

cl = ChainLadder(tri).fit()
print(cl.factors())       # ATA development factors
print(cl.ultimates())     # projected ultimate losses
print(cl.ibnr())          # IBNR by accident year
print(cl.total_ibnr())    # total reserve
print(cl.summary())       # ultimates + 95% bootstrap CIs

Bornhuetter-Ferguson

from reserving import BornhuetterFerguson

bf = BornhuetterFerguson(tri, apriori=0.65, premium=10000).fit()
print(bf.ultimates())
print(bf.summary())

Cape Cod

from reserving import CapeCod

cc = CapeCod(tri, premium=10000).fit()
print(cc.elr())           # derived expected loss ratio
print(cc.ultimates())
print(cc.summary())

Comparing all three methods

import reserving.plot as rvplot

fig = rvplot.comparison_chart({
    "Chain-ladder": cl,
    "BF": bf,
    "Cape Cod": cc,
})
fig.savefig("comparison.png")

Bootstrap confidence intervals

All three methods support summary(alpha, n_boot):

# 90% CI with 2000 bootstrap resamples
summary = cl.summary(alpha=0.10, n_boot=2000)
print(summary)