has_apc <- requireNamespace("apc", quietly = TRUE) if (!has_apc) { knitr::opts_chunk$set(eval = FALSE) knitr::knit_exit() }
knitr::opts_chunk$set( collapse = TRUE, comment = "#>" )
t2c <- function(x){ " Function to transform an upper run-off triangle into a half-square. This function takes an upper run-off triangle as input. It returns a half square. " I= dim(x)[1] J= dim(x)[2] mx=matrix(NA,nrow=I,ncol=J) for(i in 1:(I)){ for(j in 1:(J)){ if(i+j<=J+1){ mx[j,(i+j-1)]=x[i,j] } } } return(mx) } c2t <- function(x){ " Function to transform a square into an upper run-off triangle. This function takes a half square as input. It returns an upper run-off triangle. " I= dim(x)[1] J= dim(x)[2] mx=matrix(NA,nrow=I,ncol=J) for(i in 1:(I)){ for(j in 1:(J)){ if(i+j<=J+1){ mx[i,j]=x[j,(i+j-1)] } } } return(mx) }
The clmplus
package aims to offer a fast and user-friendly implementation of the modeling framework introduced in our paper, @pittarello25.
In this vignette:
We replicate the chain-ladder model using an age-model for the claim development. We can replicate the chain ladder model using an age-model for the claim development. As discussed in the paper, modeling claim development allows us to replicate chain-ladder estimate for claims reserve using fewer parameters than modeling claim amounts (@england99).
We provide an example illustrating how incorporating a cohort effect can enhance model fit.
Before proceeding, we summarise in a table the notation of the claim development models implemented in clmplus
package. The implementation of the models for the claim development available in the clmplus
is based on the implementation of the models for human mortality implemented in the StMoMo
package. Users can either rely on our default models or set their own configuration for the claim development.
| Model | Lexis dimension |Claims reserving | | :-------------: |:-------------------------------:|---------------------------------:| | a | age |development (chain-ladder model) | | ac | age-cohort |development-accident | | ap | age-period |development-calendar | | apc | age-period-cohort |development-calendar-accident |
clmplus
packageFor this tutorial, we use the AutoBIPaid
run-off triangle available in the ChainLadder
package (@chainladderpackage). Please make sure that the ChainLadder
package is installed on your computer before executing the following code.
library(ChainLadder) data("AutoBI") dataset=AutoBI$AutoBIPaid input_data <- incr2cum(dataset)
The data is pre-processed using the AggregateDataPP
method.
library(clmplus) pp_data <- AggregateDataPP(cumulative.payments.triangle = input_data)
The desired model is fit using the clmplus
method.
a.model.fit=clmplus(AggregateDataPP = pp_data, hazard.model = "a")
Out of the fitted model, it is possible to extract the fitted development factors:
a.model.fit$fitted_development_factors
It is also possible to extract the fitted effects on the claims development.
a.model.fit$fitted_effects
Predictions can be computed with the predict
method.
a.model <- predict(a.model.fit)
Out of the model predictions, we can extract the predicted development factors, the full and lower triangle of predicted cumulative claims.
a.model$development_factors_predicted
a.model$lower_triangle
a.model$full_triangle
We can also predict for different forecasting horizons. Below predictions for one calendar period ahead. The forecasting horizon can be specified with the forecasting_horizon
argument in the predict
method.
a.model.2 <- predict(a.model.fit, forecasting_horizon=1)
We compare our estimates with those obtained with the Mack chain-ladder method (@mack93) as implemented in the ChainLadder
package. We predict the same reserve as the literature benchmark.
mck.chl <- MackChainLadder(input_data) ultimate.chl=mck.chl$FullTriangle[,dim(mck.chl$FullTriangle)[2]] diagonal=rev(t2c(mck.chl$FullTriangle)[,dim(mck.chl$FullTriangle)[2]])
Estimates are gathered in a data.frame
for comparison.
data.frame(ultimate.cost.mack=ultimate.chl, ultimate.cost.clmplus=a.model$ultimate_cost, reserve.mack=ultimate.chl-diagonal, reserve.clmplus=a.model$reserve ) cat('\n Total reserve:', sum(a.model$reserve))
We fit the stochastic model replicating the chain-ladder with an age-cohort GLM for the claim amounts described in @england99 using the apc
package @apcpackage.
library(apc) ds.apc = apc.data.list(cum2incr(dataset), data.format = "CL") ac.model.apc = apc.fit.model(ds.apc, model.family = "od.poisson.response", model.design = "AC")
Inspect the model coefficients derived from the output:
ac.model.apc$coefficients.canonical[,'Estimate'] ac.fcst.apc = apc.forecast.ac(ac.model.apc) data.frame(reserve.mack=ultimate.chl-diagonal, reserve.apc=c(0,ac.fcst.apc$response.forecast.coh[,'forecast']), reserve.clmplus=a.model$reserve )
Our method is able to replicate the chain-ladder results without adding the cohort component.
a.model.fit$fitted_effects
Further inspection can be performed with the clmplus
package, which provides the graphical tools to inspect the fitted effects. The fitted effects can be plotted using the plot
function on the output of the predict
method.
plot(a.model)
By adding a cohort component to the claim development model, we improve the scaled-deviance residuals. The scaled-deviance residuals can be plotted using the plot
function on the output of the clmplus
method.
#make it triangular plot(a.model.fit)
The red and blue areas suggest that there are some trends that the age-model wasn't able to catch.
ac.model.fit <- clmplus(pp_data, hazard.model="ac") ac.model <- predict(ac.model.fit, gk.fc.model='a') plot(ac.model.fit)
The fitted effect are displayed below. The cohort component is extrapolated for the last available accident period as discussed in our paper.
plot(ac.model)
It is also possible to add a period component and choose an age-period model or an age-period-cohort model.
ap.model.fit = clmplus(pp_data, hazard.model = "ap") ap.model<-predict(ap.model.fit, ckj.fc.model='a', ckj.order = c(0,1,0)) apc.model.fit = clmplus(pp_data,hazard.model = "apc") apc.model<-predict(apc.model.fit, gk.fc.model='a', ckj.fc.model='a', gk.order = c(1,1,0), ckj.order = c(0,1,0))
There is no clear difference between the residuals plot obtained using an age-period model compared to the residuals plot obtained using the age-cohort model. Conversely, the plot seems to improve using an age-period-cohort model.
plot(ap.model.fit)
plot(apc.model.fit)
Below, the effects of the age-period-cohort model.
plot(apc.model)
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.