def test_voting_ultimate(): clrd = cl.load_sample("clrd")[["CumPaidLoss", "EarnedPremDIR"]] clrd = clrd[clrd["LOB"] == "wkcomp"] bcl_ult = cl.Chainladder().fit(clrd["CumPaidLoss"].sum(), ).ultimate_ bf_ult = cl.BornhuetterFerguson().fit( clrd["CumPaidLoss"].sum(), sample_weight=clrd["EarnedPremDIR"].sum().latest_diagonal).ultimate_ cc_ult = cl.CapeCod().fit( clrd["CumPaidLoss"].sum(), sample_weight=clrd["EarnedPremDIR"].sum().latest_diagonal).ultimate_ bcl = cl.Chainladder() bf = cl.BornhuetterFerguson() cc = cl.CapeCod() estimators = [('bcl', bcl), ('bf', bf), ('cc', cc)] weights = np.array([[0.25, 0.25, 0.5]] * 4 + [[0, 0.5, 0.5]] * 3 + [[0, 0, 1]] * 3) vot_ult = cl.VotingChainladder(estimators=estimators, weights=weights).fit( clrd["CumPaidLoss"].sum(), sample_weight=clrd["EarnedPremDIR"].sum().latest_diagonal, ).ultimate_ weights = weights[..., np.newaxis] assert abs((bcl_ult * weights[..., 0, :] + bf_ult * weights[..., 1, :] + cc_ult * weights[..., 2, :]).sum() - vot_ult.sum()) < 1
def test_pipeline(): tri = cl.load_sample('clrd').groupby('LOB').sum()[[ 'CumPaidLoss', 'IncurLoss', 'EarnedPremDIR' ]] tri['CaseIncurredLoss'] = tri['IncurLoss'] - tri['CumPaidLoss'] X = tri[['CumPaidLoss', 'CaseIncurredLoss']] sample_weight = tri['EarnedPremDIR'].latest_diagonal dev = [ cl.Development(), cl.ClarkLDF(), cl.Trend(), cl.IncrementalAdditive(), cl.MunichAdjustment(paid_to_incurred=('CumPaidLoss', 'CaseIncurredLoss')), cl.CaseOutstanding(paid_to_incurred=('CumPaidLoss', 'CaseIncurredLoss')) ] tail = [cl.TailCurve(), cl.TailConstant(), cl.TailBondy(), cl.TailClark()] ibnr = [ cl.Chainladder(), cl.BornhuetterFerguson(), cl.Benktander(n_iters=2), cl.CapeCod() ] for model in list(itertools.product(dev, tail, ibnr)): print(model) cl.Pipeline( steps=[('dev', model[0]), ('tail', model[1]), ('ibnr', model[2])]).fit_predict( X, sample_weight=sample_weight).ibnr_.sum( 'origin').sum('columns').sum()
def test_voting_ultimate(triangle_data, estimators, weights): bcl_ult = cl.Chainladder().fit( triangle_data["CumPaidLoss"].sum(), ).ultimate_ bf_ult = cl.BornhuetterFerguson().fit( triangle_data["CumPaidLoss"].sum(), sample_weight=triangle_data["EarnedPremDIR"].sum( ).latest_diagonal).ultimate_ cc_ult = cl.CapeCod().fit(triangle_data["CumPaidLoss"].sum(), sample_weight=triangle_data["EarnedPremDIR"].sum( ).latest_diagonal).ultimate_ vot_ult = cl.VotingChainladder( estimators=estimators, weights=weights, default_weighting=(1, 2, 3)).fit( triangle_data["CumPaidLoss"].sum(), sample_weight=triangle_data["EarnedPremDIR"].sum().latest_diagonal, ).ultimate_ direct_weight = np.array([[1, 2, 3]] * 4 + [[0, 0.5, 0.5]] * 3 + [[0, 0, 1]] * 3) direct_weight = direct_weight[..., np.newaxis] assert abs(( (bcl_ult * direct_weight[..., 0, :] + bf_ult * direct_weight[..., 1, :] + cc_ult * direct_weight[..., 2, :]) / direct_weight.sum(axis=-2)).sum() - vot_ult.sum()) < 1
def test_bf_eq_cl_when_using_cl_apriori(): cl_ult = cl.Chainladder().fit(cl.load_sample('quarterly')).ultimate_ cl_ult.rename('development', ['apriori']) bf_ult = cl.BornhuetterFerguson().fit(cl.load_sample('quarterly'), sample_weight=cl_ult).ultimate_ xp = cl_ult.get_array_module() assert xp.allclose(cl_ult.values, bf_ult.values, atol=1e-5)
def test_weight_broadcasting(): clrd = cl.load_sample("clrd")[["CumPaidLoss", "EarnedPremDIR"]] clrd = clrd[clrd["LOB"] == "wkcomp"] bcl = cl.Chainladder() bf = cl.BornhuetterFerguson() cc = cl.CapeCod() estimators = [('bcl', bcl), ('bf', bf), ('cc', cc)] min_dim_weights = np.array([[1, 2, 3]] * 4 + [[0, 0.5, 0.5]] * 3 + [[0, 0, 1]] * 3) mid_dim_weights = np.array( [[[1, 2, 3]] * 4 + [[0, 0.5, 0.5]] * 3 + [[0, 0, 1]] * 3] * 1) max_dim_weights = np.array( [[[[1, 2, 3]] * 4 + [[0, 0.5, 0.5]] * 3 + [[0, 0, 1]] * 3] * 1] * 132) min_dim_ult = cl.VotingChainladder( estimators=estimators, weights=min_dim_weights).fit( clrd['CumPaidLoss'], sample_weight=clrd["EarnedPremDIR"].latest_diagonal, ).ultimate_.sum() mid_dim_ult = cl.VotingChainladder( estimators=estimators, weights=mid_dim_weights).fit( clrd['CumPaidLoss'], sample_weight=clrd["EarnedPremDIR"].latest_diagonal, ).ultimate_.sum() max_dim_ult = cl.VotingChainladder( estimators=estimators, weights=max_dim_weights).fit( clrd['CumPaidLoss'], sample_weight=clrd["EarnedPremDIR"].latest_diagonal, ).ultimate_.sum() assert (abs(min_dim_ult - mid_dim_ult - max_dim_ult) < 1)
def estimators(): bcl = cl.Chainladder() bf = cl.BornhuetterFerguson() cc = cl.CapeCod() estimators = [('bcl', bcl), ('bf', bf), ('cc', cc)] return estimators
def test_pipeline_json_io(): pipe = cl.Pipeline( steps=[("dev", cl.Development()), ("model", cl.BornhuetterFerguson())] ) pipe2 = cl.read_json(pipe.to_json()) assert {item[0]: item[1].get_params() for item in pipe.get_params()["steps"]} == { item[0]: item[1].get_params() for item in pipe2.get_params()["steps"] }
def test_pipeline_json_io(): pipe = cl.Pipeline( steps=[('dev', cl.Development()), ('model', cl.BornhuetterFerguson())]) pipe2 = cl.read_json(pipe.to_json()) assert {item[0]: item[1].get_params() for item in pipe.get_params()['steps']} == \ {item[0]: item[1].get_params() for item in pipe2.get_params()['steps']}
def test_bs_random_state_predict(): tri = (cl.load_sample("clrd").groupby("LOB").sum().loc[ "wkcomp", ["CumPaidLoss", "EarnedPremNet"]]) X = cl.BootstrapODPSample(random_state=100).fit_transform( tri["CumPaidLoss"]) bf = cl.BornhuetterFerguson( apriori=0.6, apriori_sigma=0.1, random_state=42).fit( X, sample_weight=tri["EarnedPremNet"].latest_diagonal) assert (abs( bf.predict(X, sample_weight=tri["EarnedPremNet"].latest_diagonal). ibnr_.sum().sum() / bf.ibnr_.sum().sum() - 1) < 5e-3)
def test_bs_random_state_predict(): tri = cl.load_dataset('clrd').groupby('LOB').sum().loc[ 'wkcomp', ['CumPaidLoss', 'EarnedPremNet']] X = cl.BootstrapODPSample(random_state=100).fit_transform( tri['CumPaidLoss']) bf = cl.BornhuetterFerguson( apriori=0.6, apriori_sigma=0.1, random_state=42).fit( X, sample_weight=tri['EarnedPremNet'].latest_diagonal) assert bf.predict( X, sample_weight=tri['EarnedPremNet'].latest_diagonal).ibnr_ == bf.ibnr_
def test_voting_predict(): bcl = cl.Chainladder() bf = cl.BornhuetterFerguson() cc = cl.CapeCod() estimators = [('bcl', bcl), ('bf', bf), ('cc', cc)] weights = np.array([[1, 2, 3]] * 3 + [[0, 0.5, 0.5]] * 3 + [[0, 0, 1]] * 3) vot = cl.VotingChainladder(estimators=estimators, weights=weights).fit( raa_1989, sample_weight=apriori_1989, ) vot.predict(raa_1990, sample_weight=apriori_1990)
def test_different_backends(): clrd = cl.load_sample("clrd")[["CumPaidLoss", "EarnedPremDIR"]] clrd = clrd[clrd["LOB"] == "wkcomp"] model = cl.BornhuetterFerguson().fit( clrd["CumPaidLoss"].sum().set_backend("numpy"), sample_weight=clrd["EarnedPremDIR"].sum().latest_diagonal.set_backend( "numpy"), ) assert (abs((model.predict( clrd["CumPaidLoss"].set_backend("sparse"), sample_weight=clrd["EarnedPremDIR"].latest_diagonal.set_backend( "sparse"), ).ibnr_.sum() - model.ibnr_).sum()) < 1)
def test_different_backends(): clrd = cl.load_sample("clrd")[["CumPaidLoss", "EarnedPremDIR"]] clrd = clrd[clrd["LOB"] == "wkcomp"] bcl = cl.Chainladder() bf = cl.BornhuetterFerguson() cc = cl.CapeCod() estimators = [('bcl', bcl), ('bf', bf), ('cc', cc)] weights = np.array([[1, 2, 3]] * 4 + [[0, 0.5, 0.5]] * 3 + [[0, 0, 1]] * 3) model = cl.VotingChainladder(estimators=estimators, weights=weights).fit( clrd["CumPaidLoss"].sum().set_backend("numpy"), sample_weight=clrd["EarnedPremDIR"].sum().latest_diagonal.set_backend( "numpy"), ) assert (abs( (model.predict(clrd["CumPaidLoss"].sum().set_backend("sparse"), sample_weight=clrd["EarnedPremDIR"].sum(). latest_diagonal.set_backend("sparse")).ultimate_.sum() - model.ultimate_.sum())) < 1)
def test_bf_predict(): cc = cl.BornhuetterFerguson().fit(raa_1989, sample_weight=apriori_1989) cc.predict(raa, sample_weight=apriori)
import chainladder as cl # Simulation parameters random_state = 42 n_sims = 1000 # Get data loss = cl.load_dataset('genins') premium = loss.latest_diagonal * 0 + 8e6 # Simulate loss triangles sim = cl.BootstrapODPSample(random_state=random_state, n_sims=n_sims) sim.fit(loss, sample_weight=premium) # Fit Bornhuetter-Ferguson to stochastically generated data model = cl.BornhuetterFerguson(0.65, apriori_sigma=0.10).fit( sim.resampled_triangles_, sample_weight=premium) # Grab completed triangle replacing simulated known data with actual known data full_triangle = model.full_triangle_ - model.X_ + loss.broadcast_axis( 'index', sim.resampled_triangles_.index) # Limiting to the current year for plotting current_year = full_triangle[full_triangle.origin == full_triangle.origin.max()].to_frame().T # Plot the data current_year.reset_index(drop=True).plot( color='orange', legend=False, alpha=0.1, title='Current Accident Year BornFerg Distribution',
def test_bf_eq_cl_when_using_cl_apriori(): cl_ult = cl.Chainladder().fit(cl.load_dataset('quarterly')).ultimate_ cl_ult.rename('development', ['apriori']) bf_ult = cl.BornhuetterFerguson().fit(cl.load_dataset('quarterly'), sample_weight=cl_ult).ultimate_ assert_allclose(cl_ult.triangle, bf_ult.triangle, atol=1e-5)
""" ==================================== Picking Bornhuetter-Ferguson Apriori ==================================== This example demonstrates how you can can use the output of one method as the apriori selection for the Bornhuetter-Ferguson Method. """ import chainladder as cl import pandas as pd import seaborn as sns sns.set_style('whitegrid') # Create Aprioris as the mean AY chainladder ultimate raa = cl.load_dataset('RAA') cl_ult = cl.Chainladder().fit(raa).ultimate_ # Chainladder Ultimate apriori = cl_ult * 0 + (cl_ult.sum() / 10) # Mean Chainladder Ultimate bf_ult = cl.BornhuetterFerguson(apriori=1).fit(raa, sample_weight=apriori).ultimate_ # Plot of Ultimates plot_data = cl_ult.to_frame().rename({'values': 'Chainladder'}, axis=1) plot_data['BornhuetterFerguson'] = bf_ult.to_frame() plot_data = plot_data.stack().reset_index() plot_data.columns = ['Accident Year', 'Method', 'Ultimate'] plot_data['Accident Year'] = plot_data['Accident Year'].dt.year pd.pivot_table(plot_data, index='Accident Year', columns='Method', values='Ultimate').plot()
loss = cl.load_dataset('genins') premium = loss.latest_diagonal*0+8e6 # Simulate loss triangles sim = cl.BootstrapODPSample(random_state=random_state, n_sims=n_sims) sim.fit(loss, sample_weight=premium) # Repeat the premium triangle to align with simulated losses sim_p = premium.broadcast_axis('index', sim.resampled_triangles_.index) # Simulate aprioris using numpy apriori_mu = 0.65 apriori_sigma = .10 aprioris = np.random.normal(apriori_mu, apriori_sigma, n_sims) sim_p.values = (sim_p.values * aprioris.reshape(n_sims,-1)[..., np.newaxis, np.newaxis]) # Fit Bornhuetter-Ferguson to stochastically generated data model = cl.BornhuetterFerguson().fit(sim.resampled_triangles_, sample_weight=sim_p) # Grab completed triangle replacing simulated known data with actual known data full_triangle = model.full_triangle_ - model.X_ + \ loss.broadcast_axis('index', sim.resampled_triangles_.index) # Limiting to the current year for plotting current_year = full_triangle[full_triangle.origin==full_triangle.origin.max()].to_frame().T # Plot the data current_year.reset_index(drop=True).plot( color='orange', legend=False, alpha=0.1, title='Current Accident Year BornFerg Distribution', grid=True);
import chainladder as cl # Simulation parameters random_state = 42 n_sims = 1000 # Get data loss = cl.load_sample('genins') premium = loss.latest_diagonal * 0 + 8e6 # Simulate loss triangles sim = cl.BootstrapODPSample(random_state=random_state, n_sims=n_sims) sim.fit(loss, sample_weight=premium) # Fit Bornhuetter-Ferguson to stochastically generated data model = cl.BornhuetterFerguson(0.65, apriori_sigma=0.10) model.fit(sim.resampled_triangles_, sample_weight=premium) # Grab completed triangle replacing simulated known data with actual known data full_triangle = (model.full_triangle_ - model.X_ + loss) / premium # Limiting to the current year for plotting current_year = full_triangle[full_triangle.origin == full_triangle.origin.max()].to_frame().T # Plot the data current_year.iloc[:-1].plot( color='orange', legend=False, alpha=0.1, grid=True,
def test_bf_eq_cl_when_using_cl_apriori(qtr): cl_ult = cl.Chainladder().fit(qtr).ultimate_ bf_ult = cl.BornhuetterFerguson().fit(qtr, sample_weight=cl_ult).ultimate_ xp = cl_ult.get_array_module() assert xp.allclose(cl_ult.values, bf_ult.values, atol=1e-5)