Vignette 1

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)
}

Introduction

The clmplus package aims to offer a fast and user-friendly implementation of the modeling framework introduced in our paper, @pittarello25.

In this vignette:

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 |

Replicate the chain-ladder with the clmplus package

For 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))

Claims reserving with GLMs compared to hazard models

We fit the stochastic model replicating the chain-ladder with an age-cohort GLM for the claim amounts described in @england99 using the apcpackage @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)

Adding a cohort effect on the claim development 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)

Modelling a period effect on the claim development

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)

References



Try the clmplus package in your browser

Any scripts or data that you put into this service are public.

clmplus documentation built on Aug. 8, 2025, 6:06 p.m.