def test_grid(): # Load Data clrd = cl.load_dataset('clrd') medmal_paid = clrd.groupby('LOB').sum().loc['medmal']['CumPaidLoss'] medmal_prem = clrd.groupby( 'LOB').sum().loc['medmal']['EarnedPremDIR'].latest_diagonal medmal_prem.rename('development', ['premium']) # Pipeline dev = cl.Development() tail = cl.TailCurve() benk = cl.Benktander() steps = [('dev', dev), ('tail', tail), ('benk', benk)] pipe = cl.Pipeline(steps) # Prep Benktander Grid Search with various assumptions, and a scoring function param_grid = dict(benk__n_iters=[250], benk__apriori=[1.00]) scoring = {'IBNR': lambda x: x.named_steps.benk.ibnr_.sum()[0]} grid = cl.GridSearch(pipe, param_grid, scoring=scoring) # Perform Grid Search grid.fit(medmal_paid, benk__sample_weight=medmal_prem) assert grid.results_['IBNR'][0] == \ cl.Benktander(n_iters=250, apriori=1).fit(cl.TailCurve().fit_transform(cl.Development().fit_transform(medmal_paid)), sample_weight=medmal_prem).ibnr_.sum()[0]
def test_grid(): # Load Data clrd = cl.load_sample("clrd") medmal_paid = clrd.groupby("LOB").sum().loc["medmal"]["CumPaidLoss"] medmal_prem = (clrd.groupby("LOB").sum().loc["medmal"] ["EarnedPremDIR"].latest_diagonal) medmal_prem.rename("development", ["premium"]) # Pipeline dev = cl.Development() tail = cl.TailCurve() benk = cl.Benktander() steps = [("dev", dev), ("tail", tail), ("benk", benk)] pipe = cl.Pipeline(steps) # Prep Benktander Grid Search with various assumptions, and a scoring function param_grid = dict(benk__n_iters=[250], benk__apriori=[1.00]) scoring = {"IBNR": lambda x: x.named_steps.benk.ibnr_.sum()} grid = cl.GridSearch(pipe, param_grid, scoring=scoring) # Perform Grid Search grid.fit(medmal_paid, benk__sample_weight=medmal_prem) assert (grid.results_["IBNR"][0] == cl.Benktander( n_iters=250, apriori=1).fit( cl.TailCurve().fit_transform( cl.Development().fit_transform(medmal_paid)), sample_weight=medmal_prem, ).ibnr_.sum())
and as ``n_iters`` approaches infinity yields the chainladder. As ``n_iters`` increases the apriori selection becomes less relevant regardless of initial choice. """ import chainladder as cl # Load Data clrd = cl.load_sample('clrd') medmal_paid = clrd.groupby('LOB').sum().loc['medmal', 'CumPaidLoss'] medmal_prem = clrd.groupby('LOB').sum().loc['medmal', 'EarnedPremDIR'].latest_diagonal medmal_prem.rename('development', ['premium']) # Generate LDFs and Tail Factor medmal_paid = cl.Development().fit_transform(medmal_paid) medmal_paid = cl.TailCurve().fit_transform(medmal_paid) # Benktander Model benk = cl.Benktander() # Prep Benktander Grid Search with various assumptions, and a scoring function param_grid = dict(n_iters=list(range(1,100,2)), apriori=[0.50, 0.75, 1.00]) scoring = {'IBNR':lambda x: x.ibnr_.sum()} grid = cl.GridSearch(benk, param_grid, scoring=scoring) # Perform Grid Search grid.fit(medmal_paid, sample_weight=medmal_prem) # Plot data grid.results_.pivot(index='n_iters', columns='apriori', values='IBNR').plot( title='Benktander convergence to Chainladder', grid=True).set(ylabel='IBNR')
==================================================== Basic Assumption Tuning with Pipeline and Gridsearch ==================================================== This example demonstrates testing multiple number of periods in the development transformer to see its influence on the overall ultimate estimate. """ import seaborn as sns sns.set_style('whitegrid') import chainladder as cl tri = cl.load_dataset('abc') # Set up Pipeline steps = [('dev', cl.Development()), ('chainladder', cl.Chainladder())] params = dict(dev__n_periods=[item for item in range(2, 11)]) pipe = cl.Pipeline(steps=steps) # Develop scoring function that returns an Ultimate/Incurred Ratio scoring = lambda x: x.named_steps.chainladder.ultimate_.sum( ) / tri.latest_diagonal.sum() # Run GridSearch grid = cl.GridSearch(pipe, params, scoring).fit(tri) # Plot Results grid.results_.plot(x='dev__n_periods', y='score', marker='o').set(ylabel='Ultimate / Incurred')
we can see that the "Inverse Power" curve fit doesn't converge to its asymptotic value. """ import chainladder as cl tri = cl.load_sample('clrd').groupby('LOB').sum().loc['medmal', 'CumPaidLoss'] # Create a fuction to grab the scalar tail value. def scoring(model): """ Scoring functions must return a scalar """ return model.tail_.iloc[0, 0] # Create a grid of scenarios param_grid = dict(extrap_periods=list(range(1, 100, 6)), curve=['inverse_power', 'exponential']) # Fit Grid model = cl.GridSearch(cl.TailCurve(), param_grid=param_grid, scoring=scoring).fit(tri) # Plot results model.results_.pivot( columns='curve', index='extrap_periods', values='score').plot( grid=True, ylim=(1, None), title='Curve Fit Sensitivity to Extrapolation Period').set( ylabel='Tail Factor')
traditional Bondy method. """ import chainladder as cl # Fit basic development to a triangle tri = cl.load_sample('tail_sample')['paid'] dev = cl.Development(average='simple').fit_transform(tri) # Return both the tail factor and the Bondy exponent in the scoring function scoring = { 'tail_factor': lambda x: x.tail_.values[0, 0], 'bondy_exponent': lambda x: x.b_.values[0, 0] } # Vary the 'earliest_age' assumption in GridSearch param_grid = dict(earliest_age=list(range(12, 120, 12))) grid = cl.GridSearch(cl.TailBondy(), param_grid, scoring) results = grid.fit(dev).results_ ax = results.plot(x='earliest_age', y='bondy_exponent', title='Bondy Assumption Sensitivity', marker='o') results.plot(x='earliest_age', y='tail_factor', grid=True, secondary_y=True, ax=ax, marker='o')