Freakonometrics

To content | To menu | To search

Friday, June 29 2012

Provisionnement et modélisation individuelle des sinistres

Il y a quelques années, Guillaume Beneteau avait fait son mémoire d'actuariat, en France, sur l'utilisation de données individuelles pour faire du provisionnement (au lieu de travailler sur des donnees aggregées dans des triangles). Dans le même genre d'idées, Ngoc An Dinh et Gilles Chau viennent de soutenir leur mémoire cette semaine à l'ENSAE, encadré par Frédéric Planchet. L'idée était de modéliser les processus de règlements avec deux approches : la première intitulée dynamiques markoviennes qui considère les processus de règlements (avec une certaine dynamique sous-jacente), et une basée sur des modèles linéaires généralisés qui suppose que les règlements appartiennent à une famille de distribution paramétrique et les paramètres dépendent des facteurs liés aux règlements. Le mémoire est en ligne sur le blog, ainsi que le code R.

Wednesday, June 6 2012

Claims reserving and IBNR with R

Following previous posts on life contingencies and longevity and mortality models, I upload additional material for the short course at the 6th R/Rmetrics Meielisalp Workshop & Summer School on Computational Finance and Financial Engineering organized by ETH Zürich, https://www.rmetrics.org/. The third part of the talk (on Actuarial models with R) will be dedicated to IBNR and claims reserving. A complete set of slides can be downloaded from the blog, but again, only some part will be presented. Note that the slides start with a parallel between mortality tables (in life insurance) and payment triangles (in non-life insurance).

Once again, the codes are from a book on actuarial science in R, written with Christophe Dutang and Vincent Goulet (so far in French) that should appear, some day... The code used in the slides above are based on the following datasets,

> source("http://perso.univ-rennes1.fr/arthur.charpentier/
+ bases.R")
We will built our own functions to derive all quantities. One function used can be found here
> source("http://perso.univ-rennes1.fr/arthur.charpentier/
+ merz-wuthrich-triangle.R")
Finally, note that most of the code can be found in the following library
> library(ChainLadder)

Wednesday, December 7 2011

ACT2040: tail factor et cloture de la première ligne des triangles de paiements

La grosse hypothèse que l'on a fait quand on travaillait sur les triangles, était que la première année était close. Et donc, que pour la première ligne de paiements cumulés, le montant final était la charge totale des sinistres survenus cette année là. En fait, en 1999, Thomas Mack avait proposé un modèle relativement simple permettant l'inclusion d'un tail factor. L'idée est que l'on peut supposer que les facteurs de développement dans la méthode Chain Ladder décroissent tranquillement vers 1. Toujours sur le même triangle (mais en utilisant une régression pondérée sans constante - ce qui permet d'éviter les problèmes des valeurs manquantes à n'importe quel endroit dans le triangle), nous avions

> LAMBDA <- rep(NA,nc-1)
> for(k in 1:(nc-1)){
+ LAMBDA[k]=lm(PAID[,k+1]~0+PAID[,k],
+ weights=1/PAID[,k])$coefficients}
> LAMBDA
[1] 1.380933 1.011433 1.004343 1.001858 1.004735
Par "tranquillement", on entend une décroissance exponentielle des coefficients avec le temps. On peut estimer un modèle linéaire sur le logarithme des facteurs de développement
> logL <- log(LAMBDA-1)
> tps <- 1:(nc-1)
> modele <- lm(logL~tps)
> plot(tps,logL,xlim=c(1,20),ylim=c(-30,0),col="red")
> abline(modele)
> tpsP <- seq(6,1000)
> logP <- predict(modele,newdata=data.frame(tps=tpsP))
> points(tpsP,logP ,pch=0,col="blue")

Si on regarde les coefficients de transition, on a

Pour passer de la dernière colonne observé à la charge ultime, il suffit de faire le produit des facteurs de transitions pour les années non encore observées, c'est à dire les points bleus
> (facteur <- prod(exp(logP)+1))
[1] 1.000707
Autrement dit, il faudrait rajouter 0.07% à la charge ultime. Sans ce facteur ultime, le montant de provisions était
> DIAG <- diag(PAID[,6:1])
> PRODUIT <- c(1,rev(LAMBDA))
> sum((cumprod(PRODUIT)-1)*DIAG)
[1] 2426.985
mais si on rajoute le facteur que l'on vient de calculer, on passe à
> sum((cumprod(PRODUIT)*facteur-1)*DIAG)
[1] 2451.764
On retrouve ici la même chose que ce qui est obtenu sous R,
> MackChainLadder(PAID,tail=TRUE)
MackChainLadder(Triangle = PAID, tail = TRUE)
 
Latest Dev.To.Date Ultimate     IBNR Mack.S.E CV(IBNR)
1  4,456       0.999    4,459     3.15    0.299   0.0948
2  4,730       0.995    4,756    25.76    0.712   0.0277
3  5,420       0.993    5,460    39.64    2.528   0.0638
4  6,020       0.988    6,090    70.37    5.064   0.0720
5  6,794       0.977    6,952   157.99   31.357   0.1985
6  5,217       0.708    7,372 2,154.86   68.499   0.0318
 
Totals
Latest:             32,637.00
Dev:                     0.93
Ultimate:           35,088.76
IBNR:                2,451.76
Mack S.E.:              79.37
CV(IBNR):  0.0323730538389919

Tuesday, November 29 2011

ACT2040: chain ladder

Pour la fin du cours, on a commencé à voir le méthode dit Chain Ladder. Pour cela, rappelons que l'on dispose du jeu de données suivants, de paiements cumulés,

> source("http://perso.univ-rennes1.fr/
arthur.charpentier/bases.R")
> PAID
     [,1] [,2] [,3] [,4] [,5] [,6]
[1,] 3209 4372 4411 4428 4435 4456
[2,] 3367 4659 4696 4720 4730   NA
[3,] 3871 5345 5398 5420   NA   NA
[4,] 4239 5917 6020   NA   NA   NA
[5,] 4929 6794   NA   NA   NA   NA
[6,] 5217   NA   NA   NA   NA   NA
> PAID/PREMIUM
       [,1]   [,2]   [,3]   [,4]   [,5]   [,6]
[1,] 0.6989 0.9522 0.9607 0.9644 0.9660 0.9705
[2,] 0.7206 0.9972 1.0051 1.0102 1.0124     NA
[3,] 0.7960 1.0991 1.1100 1.1145     NA     NA
[4,] 0.8191 1.1433 1.1632     NA     NA     NA
[5,] 0.8688 1.1976     NA     NA     NA     NA
[6,] 0.8112     NA     NA     NA     NA     NA

si on visualise l'évolution du ratio sinistre/primes. On peut visualiser les facteurs de transition dans le tableau ci-dessous,

> PAID[,2:6]/PAID[,1:5]
[,1]     [,2]     [,3]     [,4]     [,5]
[1,] 1.362418 1.008920 1.003854 1.001581 1.004735
[2,] 1.383724 1.007942 1.005111 1.002119       NA
[3,] 1.380780 1.009916 1.004076       NA       NA
[4,] 1.395848 1.017407       NA       NA       NA
[5,] 1.378373       NA       NA       NA       NA
[6,]       NA       NA       NA       NA       NA

Toutefois, pour faire le ratio moyen, on ne fait pas la moyenne des ratios, ou alors à condition de pondérer correctement, par exemple pour passer de la première à la seconde ligne du tableau,

> k=1
> weighted.mean(x=PAID[,k+1]/PAID[,k],w=PAID[,k],na.rm=TRUE)
[1] 1.380933
> sum(PAID[1:(6-k),k+1])/sum(PAID[1:(6-k),k])
[1] 1.380933
En itérant, on récupère l'ensemble des coefficients de transition,
> lambda=rep(NA,5)
> for(k in 1:5){
+ lambda[k]=(sum(PAID[1:(6-k),k+1])/sum(PAID[1:(6-k),k]))}
> lambda
[1] 1.380933 1.011433 1.004343 1.001858 1.004735
Une fois récupérés tous les coefficients de transition, on peut compléter la partie inférieure du triangle (ou de la matrice),
> PROJECTION=PAID
> for(k in 1:5){
+ PROJECTION[((7-k):6),k+1]=PROJECTION[((7-k):6),k]*lambda[k]
+ print(PROJECTION)}
[,1]     [,2] [,3] [,4] [,5] [,6]
[1,] 3209 4372.000 4411 4428 4435 4456
[2,] 3367 4659.000 4696 4720 4730   NA
[3,] 3871 5345.000 5398 5420   NA   NA
[4,] 4239 5917.000 6020   NA   NA   NA
[5,] 4929 6794.000   NA   NA   NA   NA
[6,] 5217 7204.327   NA   NA   NA   NA
[,1]     [,2]     [,3] [,4] [,5] [,6]
[1,] 3209 4372.000 4411.000 4428 4435 4456
[2,] 3367 4659.000 4696.000 4720 4730   NA
[3,] 3871 5345.000 5398.000 5420   NA   NA
[4,] 4239 5917.000 6020.000   NA   NA   NA
[5,] 4929 6794.000 6871.672   NA   NA   NA
[6,] 5217 7204.327 7286.691   NA   NA   NA
[,1]     [,2]     [,3]     [,4] [,5] [,6]
[1,] 3209 4372.000 4411.000 4428.000 4435 4456
[2,] 3367 4659.000 4696.000 4720.000 4730   NA
[3,] 3871 5345.000 5398.000 5420.000   NA   NA
[4,] 4239 5917.000 6020.000 6046.147   NA   NA
[5,] 4929 6794.000 6871.672 6901.518   NA   NA
[6,] 5217 7204.327 7286.691 7318.339   NA   NA
[,1]     [,2]     [,3]     [,4]     [,5] [,6]
[1,] 3209 4372.000 4411.000 4428.000 4435.000 4456
[2,] 3367 4659.000 4696.000 4720.000 4730.000   NA
[3,] 3871 5345.000 5398.000 5420.000 5430.072   NA
[4,] 4239 5917.000 6020.000 6046.147 6057.383   NA
[5,] 4929 6794.000 6871.672 6901.518 6914.344   NA
[6,] 5217 7204.327 7286.691 7318.339 7331.939   NA
[,1]     [,2]     [,3]     [,4]     [,5]     [,6]
[1,] 3209 4372.000 4411.000 4428.000 4435.000 4456.000
[2,] 3367 4659.000 4696.000 4720.000 4730.000 4752.397
[3,] 3871 5345.000 5398.000 5420.000 5430.072 5455.784
[4,] 4239 5917.000 6020.000 6046.147 6057.383 6086.065
[5,] 4929 6794.000 6871.672 6901.518 6914.344 6947.084
[6,] 5217 7204.327 7286.691 7318.339 7331.939 7366.656
où on visualise, étape par étape, le remplissage de la partie inférieure de la matrice. La dernière colonne contient des prédictions des charges ultimes, par année de survenance, et sur la diagonale, on a toujours le montant de paiements déjà effectués par année de survenance. Le montant de provision est alors la différence entre ce que l'on pense payer, et ce que l'on a déjà payé.
> PROJECTION[,6]-diag(PAID[,6:1])
[1]    0.00   22.3968   35.7838   66.0646  153.0835 2149.6564
> sum(PROJECTION[,6]-diag(PAID[,6:1]))
[1] 2426.985



Friday, November 25 2011

ACT2040: provisionnement, introduction et devoir maison no2

Mardi, nous commençons la dernière partie du cours, sur le provisionnement (pour sinistres à payer) en assurance IARD. Nous commencerons par évoquer le développement des paiements des sinistres dans le temps (à partir de données réelles). Les graphiques sont en ligne sur le blog. Par exemple l'assurance automobile de particuliers,

qui peut se décomposer en assurance automobile des dommages matériels,

et en assurance automobile des dommages corporels,

Pour les particulier, une autre assurance assez classique est l'assurance multirisque-habitation,

Mais on peut aussi regarder les risques d'entreprise, avec par exemple l'assurance risque industriel,

ou un peu plus compliqué, l'assurance responsabilité civile entreprise,

voire l'assurance responsabilité civile médicale,

Et pour conclure, l'assurance construction,

On discutera la lecture de ces graphiques mardi. Sinon toute les séances reposeront sur l'utilisation du petit jeu de données suivant
> source("http://perso.univ-rennes1.fr/arthur.charpentier/bases.R")
> PAID
     [,1] [,2] [,3] [,4] [,5] [,6]
[1,] 3209 4372 4411 4428 4435 4456
[2,] 3367 4659 4696 4720 4730   NA
[3,] 3871 5345 5398 5420   NA   NA
[4,] 4239 5917 6020   NA   NA   NA
[5,] 4929 6794   NA   NA   NA   NA
[6,] 5217   NA   NA   NA   NA   NA
> NUMBER
       [,1]   [,2]   [,3]   [,4]   [,5]   [,6]
[1,] 1043.4 1045.5 1047.5 1047.7 1047.7 1047.7
[2,] 1043.0 1027.1 1028.7 1028.9 1028.7     NA
[3,]  965.1  967.9  967.8  970.1     NA     NA
[4,]  977.0  984.7  986.8     NA     NA     NA
[5,] 1099.0 1118.5     NA     NA     NA     NA
[6,] 1076.3     NA     NA     NA     NA     NA

>
PREMIUM [1] 4591 4672 4863 5175 5673 6431
Le second devoir maison portera sur ce sujet. Les triangles sont en ligne sous forme de classeur MSExcel. Je vous demande d'utiliser le même numéro de base que pour la tarification des contrats d'assurance auto (premier devoir maison). Pour ceux qui sont sous un environnement Windows, il est possible de faire une requête SQL sous R pour aller chercher son triangle
library(RODBC)
LOC="http://freakonometrics.blog.free.fr/public/data/act2040triangle.xls"
fichier =  odbcConnectExcel(LOC)
TRIANGLE = sqlQuery(fichier, "select * from [triangle1$B2:Q17]")
odbcCloseAll()

à condition que le code tourne (ce que je n'ai pas réussit à faire sans Windows). Une alternative est la suivante

> library(gdata)
> read.xls("http://freakonometrics.blog.free.fr/
public/data/act2040triangle.xls", sheet = 10)
essai de l'URL 'http://freakonometrics.blog.free.fr/
public/data/act2040triangle.xls'
Content type 'application/octet-stream' length 454656 bytes (444 Kb)
URL ouverte
==================================================
downloaded 444 Kb
 
Year   X12   X24   X36   X48   X60   X72   X84   X96  X108  X120  X132
1  1995  1340  3188  5072  6973  8677 10008 11802 12606 13174 13596 14033
2  1996  1857  4297  6864  9438 11820 13594 14783 15710 16439 16972    NA
3  1997  2024  4891  7790 10733 13792 16071 17695 18886 19735    NA    NA
4  1998  2781  6655 10671 14738 18022 20795 23179 24597    NA    NA    NA
5  1999  3439  8272 13325 18551 23386 26861 29409    NA    NA    NA    NA
6  2000  3714  9039 14638 20326 26117 30643    NA    NA    NA    NA    NA
7  2001  4652 11236 18109 25239 31250    NA    NA    NA    NA    NA    NA
8  2002  5292 12974 21106 29611    NA    NA    NA    NA    NA    NA    NA
9  2003  6818 16984 27677    NA    NA    NA    NA    NA    NA    NA    NA
10 2004  9337 23263    NA    NA    NA    NA    NA    NA    NA    NA    NA
11 2005 15073    NA    NA    NA    NA    NA    NA    NA    NA    NA    NA

(il est toutefois préférable de télécharger le fichier sur son disque dur afin de renommer certains noms de variables, les symboles comme + ayant du mal à passer). Pour les personnes normales, il est possible d'utiliser une méthode plus laborieuse, mais qui marche toujours, à savoir sauver la feuille dans un format texte (ou CSV, avec un séparateur de colonnes), puis d'utiliser classiquement

TRIANGLE=read.table("triangle1.csv",header=TRUE,sep=";")

Wednesday, November 17 2010

Course on risk, insurance, and uncertainty

The course on risk and insurance in Luminy, starts at 10.30 on Friday (here) instead of Thursday (I switched with Patrice Bertail). The slides can be found here,

Tuesday, November 9 2010

Bornhuetter-Ferguson and claims reserving, STT6705V part 10

In several posts on this blog, I have mentioned Chain Ladder, Mack's view of Chain Ladder, and the Overdispersed Poisson model for incremental payments. But there is also one important model used when modeling IBNR: the so-called Bornhuetter-Ferguson model (from that paper). The slides for tomorrow can be downloaded here,


Here is also a link to the slides presented by William Panning in 2006. And here and there, it is possible to find papers (or slides) discussing uncertainty in Bornhuetter-Ferguson's model.
Reserving techniques will probably take us half of the course. We will finally discuss mortality models. The dataset we will use can be downloaded from here (with population data here and death data there). I have converted them in csv files, and the R code to use them is the following,
tabB=read.table("http://perso.univ-rennes1.fr/arthur.charpentier/tabB.csv", 
sep=";",header=FALSE)
ANNEE=tabB[,1]
BASEB=tabB[,seq(2,246,by=2)]
BASEB=BASEB[,1:100]
tabC=read.table("http://perso.univ-rennes1.fr/arthur.charpentier/tabC.csv",
sep=";",header=FALSE)
BASEC=tabC[,2:101]
BASEC=BASEC[-c(16,23,43,48,51,53),]
BASEC=BASEC[1:nrow(BASEB),] AGE=0:99


(I will upload soon the code for claims reserving techniques...)

Wednesday, October 6 2010

Incertitude dans les triangles de provisionnement

Comme je l'avais annoncé ici, la numéro 83 de la revue Risques vient de sortir, avec un article coécrit avec Laurent Devineau et Jean Marie Nessi, essayant de vulgariser la notion d'incertitude (et d'incertitude à un an) dans les triangles de liquidation, en assurance dommage. L'article, intitulé "mesurer le risque lors du calcul des provisions pour sinistres à payer", est en ligne ici. Je ne mets pas de code cette fois-ci car il viendra dans  les semaines à venir (nous attaquons précisément le calcul des provisions dans le cours de statistique de l'assurance).

Tuesday, October 5 2010

Statistique de l'assurance STT6705V, partie 6

Avec le cours de mercredi, nous attaquerons la partie sur la modélisation de la dynamique des sinistres, et le calcul des provisions pour sinistres à payer. Les transparents sont en ligne ici. Je peux renvoyer vers un billet que j'avais mis en ligne l'an dernier sur le sujet, ici. Sinon pour compléter les références, la CAS a publié l'an dernier un très joli ouvrage (ici), Estimating Unpaid Claims Using Basic Techniques. Je peux aussi renvoyer vers un article de Swiss Re sur le sujet, ici, ou sur le site du GIRO, . Sinon l'ouvrage de référence pour cette section est le le livre de Mario Wüthrich et Michael Merz, stochastic claims reserving methods in insurance.

Le code pour récuper les bases de données (triangles) est simplementsuivant
>  source("http://perso.univ-rennes1.fr/arthur.charpentier/bases.R")
Sinon, j'ai mis en ligne, ici la base des paiements cumulés sous le format excel (ancienne version). Pour l'importer, sous R, si le fichier a été sauvé sur D:, il suffit d(utiliser la requête sql suivante

>  library(RODBC)
>  fichier =  odbcConnectExcel("D:\\triangle.xls")
>  BASE  = sqlQuery(fichier, "select * from [Feuil1$D9:I15]")
>  odbcCloseAll()
>  (TRIANGLE = as.matrix(BASE) ) 

    F1   F2   F3   F4   F5   F6
1 3209 4372 4411 4428 4435 4456
2 3367 4659 4696 4720 4730   NA
3 3871 5345 5398 5420   NA   NA
4 4239 5917 6020   NA   NA   NA
5 4929 6794   NA   NA   NA   NA
6 5217   NA   NA   NA   NA   NA

Wednesday, March 31 2010

Présentation sur le risque de réserve dans Solvabilité II

Mercredi matin, participation à un petit déjeuner sur "Solvabilité II : Problématiques et enjeux des nouvelles exigences réglementaires pour les assureurs non-vie". Les slides seront bientôt disponibles ici. J'interviendrais principalement sur le risque de réserve, afin d'essayer d'apporter quelques éclaircissements sur la formule standard.
Rappelons que dans le modèle de Mack (qui est celui qui est retenu par Merz & Wüthrich), on suppose que les paiements vérifie

http://perso.univ-rennes1.fr/arthur.charpentier/latex/milli-01.png
où les http://perso.univ-rennes1.fr/arthur.charpentier/latex/milli-02.png sont des variables indépendantes et de même loi. En supposant de plus que les années de survenance sont indépendantes, alors Mack a montré que
http://perso.univ-rennes1.fr/arthur.charpentier/latex/milli-03.png
où, pour rappels,
http://perso.univ-rennes1.fr/arthur.charpentier/latex/milli-04.png
Le terme de gauche (en rouge) correspond à l'erreur de processus, et le terme de droite (en bleu) correspond à l'erreur d'estimation.
Si on regarde maintenant la formule obtenue par Mez & Wüthrich,
http://perso.univ-rennes1.fr/arthur.charpentier/latex/milli-05.png
où cette fois ci, on peut distinguer entre le premier terme (en rouge encore) correspondant à la prise en compte de l’erreur de processus et d’estimation sur la première diagonale, et le second terme (en bleu) correspondant à la prise en compte de l’erreur d’estimation uniquement sur les diagonales suivantes.
Tout cela est sujets aux fautes de typo, et je renvoie aux articles de Mack (ici) et de Merz & Wüthrich () pour ceux qui veulent tout programmer.
Sinon je reviendrais par la suite sur les travaux que nous menons avec Laurent sur le sujet, au plus tard lors de l'école d'été qui se tiendra à l'ISFA en juillet.

Triangles multiples et dépendance

Parmi les problèmes qui ont connu leur heure de gloire il y a quelques années, il y a eu le sujet des triangles multivariés, ou plutôt de la dépendance qui pourrait exister entre des triangles de paiements. Considérons les deux triangles suivants, obtenus auprès d'un même assureur, pour des sinistres en auto matériel entre 1994 et 2003, i.e.

et pareil pour les sinistres en auto-corporel,

On peut alors envisager deux techniques: travailler sur le triangle agrégé, ou travailler sur les triangles séparer, puis les agréger les prédictions ensuites,
  • Comparaison des prédictions par la méthode de Mack (i.e. chain-ladder)
On peut commencer par utiliser la formule de Mack, en supposant que le montant des provisions suit une loi lognormale. Rappelons que si http://perso.univ-rennes1.fr/arthur.charpentier/latex/ln-tr-01.png
alors les deux premiers moments vérifient
http://perso.univ-rennes1.fr/arthur.charpentier/latex/ln-tr-02.png
et
http://perso.univ-rennes1.fr/arthur.charpentier/latex/ln-tr-03.png
ce qui s'inverse simplement, et permet d'écrire
http://perso.univ-rennes1.fr/arthur.charpentier/latex/ln-tr-04.png
et
http://perso.univ-rennes1.fr/arthur.charpentier/latex/ln-tr-05.png
Aussi, à partir du montant prédit et de l'écart-type, on peut en déduire les paramètres de la loi sous-jacente.
> P.corp=read.table("http://perso.univ-rennes1.fr/arthur.charpentier/auto-corporel.csv",
+        header=FALSE,sep=";",na.strings = "NA",dec=",")
> P.corp=as.matrix(P.corp)
> n=nrow(P.corp)
> P.mat =read.table("http://perso.univ-rennes1.fr/arthur.charpentier/auto-materiel.csv",
+        header=FALSE,sep=";",na.strings = "NA",dec=",")
> P.mat=as.matrix(P.mat)
> P.mat=P.mat[1:n,1:n]
>  P.mat = P.mat[2:10,1:9]
>  P.corp= P.corp[2:10,1:9]
> n=9
> P.tot = P.mat + P.corp
> library(ChainLadder)
> V=MackChainLadder(P.tot)$Total.Mack.S.E
> E=sum(MackChainLadder(P.tot)$FullTriangle[,n]-
+ diag(MackChainLadder(P.tot)$FullTriangle[n:1,]))
> mu = log(E) - .5*log(1+V^2/E^2)
> sigma2 = log(1+V^2/E^2)
Les trois distributions sont alors les suivantes (sous hypothèse de lognormalité)

Si on suppose que les deux branches sont indépendantes, on peut alors regarder comment se comporte la convolée des deux lois log-normales,
> library(distr)
> V=MackChainLadder(P.mat)$Total.Mack.S.E
> E=sum(MackChainLadder(P.mat)$FullTriangle[,n]-
+-diag(MackChainLadder(P.mat)$FullTriangle[n:1,]))
> mu = log(E) - .5*log(1+V^2/E^2)
> sigma2 = log(1+V^2/E^2)

> LM = Lnorm(meanlog=mu,sdlog=sqrt(sigma2))
> V=MackChainLadder(P.corp)$Total.Mack.S.E
> E=sum(MackChainLadder(P.corp)$FullTriangle[,n]-
+ diag(MackChainLadder(P.corp)$FullTriangle[n:1,]))
> mu = log(E) - .5*log(1+V^2/E^2)
> sigma2 = log(1+V^2/E^2)

> LC = Lnorm(meanlog=mu,sdlog=sqrt(sigma2))
> LT=LM+LC

On peut alors tracer les densités
> u=seq(0,qlnorm(.95,mu,sqrt(sigma2)),length=1000)
> vtotal=dlnorm(u,mu,sqrt(sigma2))
> vconvol=d(LT)(u)

Si on compare les quantiles (on se contentera du quantile à 90% car on a des soucis numériques sur le calcul du quantile de la convolée pour un niveau trop élevé),
> q(LT)(.9)
[1] 271463.7
> qlnorm(.9,mu,sqrt(sigma2))
[1] 365395.1
Autrement dit, on a le choix sur l'interprétation,
  • travailler sur les triangles agrégés apporte beaucoup trop d'incertitudes,
  • supposer les triangles matériels et corporels indépendants est une hypothèse trop forte.
Un approche un peu extrême consisterait à supposer les risques comonotones, autrement dit le quantile de la somme serait la somme des quantiles,
> qlnorm(.9,mu,sqrt(sigma2))
[1] 64262.87
> qlnorm(.9,mu,sqrt(sigma2))
[1] 230645
dont la somme fait
[1] 294907.9
qu'il faudrait comparer à
> qlnorm(.9,mu,sqrt(sigma2))
[1] 365395.1

Bref, supposer les risques comontones ne suffit manifestement pas (je renvoie ici pour un billet expliquant que le quantile d'une somme est un objet assez complexe).
  • Approche par les GLM
Une autre idée est de supposer que les résidus obtenus suite à un GLM sont - éventuellement - corrélés. Commençons par faire de simples régressions de Poisson (on va mettre les incréments négatifs à 0, comme on le verra ci-dessous, ça ne cahnge pas grand chose sur le montant total de provision.... ceux qui le souhaitent rafineront),
>   an <- n; ligne = rep(1:an, each=an); colonne = rep(1:an, an)
>   passe = (ligne + colonne - 1)<=an; n = sum(passe)
>   PAID=P.corp; INC=PAID
>   INC[,2:an]=PAID[,2:an]-PAID[,1:(an-1)]
>   I.corp = INC
>   PAID=P.mat; INC=PAID
>   INC[,2:an]=PAID[,2:an]-PAID[,1:(an-1)]
>   I.mat = INC
>   Ym = as.vector(I.mat)
>   Ym[Ym<0]=0
>   Yc = as.vector(I.corp)
>   lig = as.factor(ligne)
>   col = as.factor(colonne)
>   base = data.frame(Ym,Yc,col,lig)
>  regm=glm(Ym~col+lig,data=base,family="poisson")
Il y a eu 35 avis (utilisez warnings() pour les visionner)
>  regc=glm(Yc~col+lig,data=base,family="poisson")
Il y a eu 38 avis (utilisez warnings() pour les visionner)
> MackChainLadder(P.mat)
MackChainLadder(Triangle = P.mat)

      Latest Dev.To.Date  Ultimate      IBNR  Mack.S.E CV(IBNR)
1  2,897,694       1.000 2,897,694      0.00      0.00      NaN
2    353,866       1.000   353,873      6.96      4.52    0.649
3    358,922       1.000   358,926      3.97     21.89    5.515
4    342,988       1.000   343,020     32.27     47.55    1.473
5    288,867       1.000   288,920     52.64     52.77    1.002
6    297,708       1.000   297,775     66.67    371.73    5.576
7    270,537       0.999   270,891    354.26    820.88    2.317
8    290,748       0.997   291,570    822.22  1,180.80    1.436
9    276,447       0.993   278,320  1,872.75  2,486.60    1.328
10   224,499       0.896   250,571 26,071.84 39,252.98    1.506

                 Totals
Latest:    5,602,275.93
Ultimate:  5,631,559.51
IBNR:         29,283.58
Mack S.E.:    39,374.90
CV(IBNR):          1.34
>  sum(exp(predict(regm,newdata=base))[passe!=TRUE])
[1] 29669.72
> MackChainLadder(P.corp)
MackChainLadder(Triangle = P.corp)

      Latest Dev.To.Date  Ultimate   IBNR Mack.S.E CV(IBNR)
1  2,231,325       1.000 2,231,325      0        0      NaN
2    182,004       0.991   183,683  1,678    1,060    0.632
3    196,756       0.981   200,589  3,833    2,731    0.712
4    205,591       0.964   213,166  7,575    4,534    0.599
5    176,427       0.943   187,096 10,669    6,128    0.574
6    156,175       0.912   171,227 15,053    9,091    0.604
7    138,483       0.867   159,709 21,226   12,717    0.599
8    109,483       0.803   136,359 26,876   17,557    0.653
9     73,108       0.704   103,835 30,727   29,956    0.975
10    24,322       0.532    45,723 21,401   59,465    2.779

                 Totals
Latest:    3,493,676.24
Ultimate:  3,632,713.12
IBNR:        139,036.88
Mack S.E.:    72,058.66
CV(IBNR):          0.52
>  sum(exp(predict(regc,newdata=base))[passe!=TRUE])
[1] 139036.9
Mais le point important est que l'on peut récupérer les résidus, et étudier leur structure de dépendance,
> plot(residuals(regc,type="pearson"),
+      residuals(regm,type="pearson"),pch=19,col="blue")

et pour les amateurs de copules, on trouvera un beau cas de dépendance très très forte
> plot(rank(residuals(regc,type="pearson"))/56,
+      rank(residuals(regm,type="pearson"))/56,pch=19,col="green")

Notons toutefois que si on supprime la première ligne des triangles (combined all years), on obtient des représentations sensiblement différentes,


et une dépendance également très différente,

malgré l'effet ligne qu iaurait dû être présent dès la première ligne. Visiblement, cette première ligne est trop complexe pour être traitée comme les autres (agrégation de processus de gestion de sinistres trop différents). Notons que la  corrélation au sens de Spearman (corrélation de rang) vaut ici
> u=rank(residuals(regc,type="pearson"))/46
> v=rank(residuals(regm,type="pearson"))/46
> cor(u,v)
[1] 0.3051383

On peut alors tenter de faire du boostrap en tirant les paires de résidus à chaque fois, ce qui permet de prendre en compte cette dépendance qui semble exister entre les triangles.
Dans un second temps, on peut aussi introduire de la dépendance sur les scenarios à venir. Lors des tirages des lois normales (évoqués ici), on peut très bien considérer un vecteur Gaussien bivarié, avec une corrélation arbitrairement fixée. La fonction de simulation dans la méthode Chain-Ladder devient alors,
> CLboot2=function(triangle1,l1,s1,triangle2,l2,s2,rho){
+ m=nrow(triangle1)
+ for(i in 2:m){
+ for(j in (m-i+2):m){
+ E=rmnorm(1, mean=c(triangle1[j,i-1]*l1[i-1],
+  triangle2[j,i-1]*l2[i-1]),
+            varcov=matrix(c(triangle1[j,i-1]*s1[i-1]^2,
+ rho*sqrt(triangle1[j,i-1]*triangle2[j,i-1])*
+ s1[i-1]*s2[i-1],
+ rho*sqrt(triangle1[j,i-1]*triangle2[j,i-1])*
+ s1[i-1]*s2[i-1],triangle2[j,i-1]*s2[i-1]^2),2,2))
+ triangle1[j,i]=E[1,1]
+ triangle2[j,i]=E[1,2]
+ }}
+ ULT1=triangle1[,m]
+ DIAG1=diag(triangle1[,m:1])
+ ULT2=triangle2[,m]
+ DIAG2=diag(triangle2[,m:1])
+ return(c(sum(ULT1-DIAG1),sum(ULT2-DIAG2)))
+ }
(le code est sûrement loin d'être optimal, mais au moins on comprend ce qui se passe). En prenant un peu de temps, on peut alors faire tourner différents scenarios, avec des dépendances plus ou moins fortes,
>  regm=glm(Ym~col+lig,data=base,family="poisson")
>  regc=glm(Yc~col+lig,data=base,family="poisson")
> Ec=residuals(regc,type="pearson")
> Em=residuals(regm,type="pearson")
> YPc=predict(regc,newdata=base)
> YPm=predict(regm,newdata=base)
> n=9
> base=data.frame(YPc,YPm,lig,col)
> nsim=50000
> PROVISION=rep(NA,nsim)
> PROVISIONm=rep(NA,nsim)
> PROVISIONc=rep(NA,nsim)
> PROVISIONc2=rep(NA,nsim)
> PROVISION2=rep(NA,nsim)
> for(k in 1:nsim){
+ I=sample(1:45,size=n^2,replace=TRUE)
+ simEm = Em[I]
+ simEc = Ec[I]
+ I=sample(1:45,size=n^2,replace=TRUE)
+ simEc2= Ec[I]
+
+ bruitm=simEm*sqrt(exp(YPm))
+ bruitc=simEc*sqrt(exp(YPc))
+ bruitc2=simEc2*sqrt(exp(YPc))
+ INCsm=exp(YPm)+bruitm
+ INCsc=exp(YPc)+bruitc
+ INCsc2=exp(YPc)+bruitc2
+ INCMm=matrix(INCsm,n,n)
+ INCMc=matrix(INCsc,n,n)
+ INCMc2=matrix(INCsc2,n,n)
+ CUMMm=INCMm
+ CUMMc=INCMc
+ CUMMc2=INCMc2
+ for(j in 2:n){CUMMm[,j]=CUMMm[,j-1]+INCMm[,j]
+                CUMMc[,j]=CUMMc[,j-1]+INCMc[,j]
+                CUMMc2[,j]=CUMMc2[,j-1]+INCMc2[,j]}
+
+ PROVISIONm[k]=CLb(CUMMm,lambdam,sigmam)
+ PROVISIONc[k]=CLb(CUMMc,lambdac,sigmac)
+ PROVISIONc2[k]=CLb(CUMMc2,lambdac,sigmac)
+ PROVISION[k]=sum(CLb2(CUMMm,lambdam,sigmam,CUMMc,lambdac,sigmac,0.8))
+ PROVISION2[k]=CLb(CUMMm,lambdam,sigmam)+CLb(CUMMc2,lambdac,sigmac)}
où l'on récupère les prédictions marginales (y compris en générant des scénarios indépendants dans la procédure de bootstrap). Ensuite, on regarde la somme des triangles, tout d'abord en tirant les paires d'erreurs obtenus par GLM, puis en tirant un vecteur Gaussien lors des prédiction, et enfin dans le cas complémentement indépendant. On peut commencer par comparer aux montants Chain Ladder obtenu intialement,
>  sum(MackChainLadder(P.mat)$FullTriangle[,n]
+  -diag(MackChainLadder(P.mat)$FullTriangle[n:1,]))
[1] 63895.45
>  sum(MackChainLadder(P.corp)$FullTriangle[,n]
+  -diag(MackChainLadder(P.corp)$FullTriangle[n:1,]))
[1] 324070.2
Bref, marginalement, on est sur des choses comparables. Si on regarde maintenant au niveau agrégé,
> sum(MackChainLadder(P.tot)$FullTriangle[,n]
+  -diag(MackChainLadder(P.tot)$FullTriangle[n:1,]))
[1] 415998.4
> mean(PROVISION)
[1] 387822.1
> mean(PROVISION2)
[1] 387989.9

Autrement dit, on retrouve la fait que la dépendance n'influence pas le best estimate (ce qui est rassurant), mais il devrait influcer l'erreur,
>  plot(density(PROVISION),col="red")
>  lines(density(PROVISION2),col="orange")

On obtient la distribution en rouge est le cas corrélé, et en orange la prédiction des provisions sous hypothèse d'indépendance. Et si l'on regarde les quantiles
> quantile(PROVISION,.995)
   99.5%
464792.2
> quantile(PROVISION2,.995)
   99.5%
452022.6
Bref, on obtient un quantile plus élevé que ce que nous avions en supposant l'indépendance (ce qui nous conforte dans la justesse de notre algorithme). Comme la distribution semble plutôt Gaussienne, et pas trop lognormale, j'ai rajouté la "distribution" obtenue par Mack en supposant la normalité des provisions sur le triangle cumulé, en bleu, en trait plein, et en pointillé le cas log-normal.

Bref, on retrouve l'idée intuitive que provisionner sur des risques non-homogène apporte d'avantage d'incertitude. Il convient donc d'avoir les triangles les plus stables possible, puis de les agréger ensuite...

Tuesday, December 15 2009

Chain Ladder dans les triangles incomplets

 Suite du billet (ici) sur le provisionnement en assurance dommage. On sait depuis le papier d'England et Verrall (1994) que la régression log-Poisson coïncide avec la méthode Chain-Ladder, en tous les cas en moyenne (on peut aller jeter un oeil ici pour les arguments théoriques). Pour les sceptiques, je renvoie au code suivant.
> library(ChainLadder)
>  an <- 10; ligne = rep(1:an, each=an); colonne = rep(1:an, an)
>  passe = (ligne + colonne - 1)<=an; n = sum(passe)
>  PAID=GenIns; INC=PAID
>  INC[,2:an]=PAID[,2:an]-PAID[,1:(an-1)]
>  Y = as.vector(INC)
>  lig = as.factor(ligne)
>  col = as.factor(colonne)
>  base = data.frame(Y,col,lig)
> reg=glm(Y~col+lig,data=base,family="poisson")
> sum(exp(predict(reg,newdata=base))[passe!=TRUE])
[1] 18680856

On peut vérifier avec la fonction MackChainLadder de library(ChainLadder), i.e.
> MackChainLadder(GenIns)
MackChainLadder(Triangle = GenIns)
      Latest Dev.To.Date  Ultimate      IBNR  Mack.S.E CV(IBNR)
1  3,901,463      1.0000 3,901,463         0         0      NaN
2  5,339,085      0.9826 5,433,719    94,634    71,835    0.759
3  4,909,315      0.9127 5,378,826   469,511   119,474    0.254
4  4,588,268      0.8661 5,297,906   709,638   131,573    0.185
5  3,873,311      0.7973 4,858,200   984,889   260,530    0.265
6  3,691,712      0.7223 5,111,171 1,419,459   410,407    0.289
7  3,483,130      0.6153 5,660,771 2,177,641   557,796    0.256
8  2,864,498      0.4222 6,784,799 3,920,301   874,882    0.223
9  1,363,294      0.2416 5,642,266 4,278,972   970,960    0.227
10   344,014      0.0692 4,969,825 4,625,811 1,362,981    0.295
                  Totals
Latest:    34,358,090.00
Ultimate:  53,038,945.61
IBNR:      18,680,855.61
Mack S.E.:  2,441,364.13
CV(IBNR):           0.13

Bref, les deux  coïncident. Tout en étant fondamentalement très différents, comme l'avait noté Mack et Venter (2000). Mais que se passe-t-il si on ne dispose pas d'un triangle de données, mais d'un losange (par exemple en enlevant les 6 données du coin en haut à gauche).
> M=GenIns
> M[1,1:3]=NA
> M[2,1:2]=NA
> M[3,1]=NA
>  an <- 10; ligne = rep(1:an, each=an); colonne = rep(1:an, an)
>  passe = (ligne + colonne - 1)<=an; n = sum(passe)
>  PAID=M; INC=PAID
>  INC[,2:an]=PAID[,2:an]-PAID[,1:(an-1)]
>  Y = as.vector(INC)
>  lig = as.factor(ligne)
>  col = as.factor(colonne)
>  base = data.frame(Y,col,lig)
> reg=glm(Y~col+lig,data=base,family="poisson")
> sum(exp(predict(reg,newdata=base))[passe!=TRUE])
[1] 17810100

Le montant de provision est ici inférieur au montant obtenu par Chain Ladder (et qui est correct pour avoir refait les calculs),
> MackChainLadder(M)
MackChainLadder(Triangle = M)
      Latest Dev.To.Date  Ultimate      IBNR  Mack.S.E CV(IBNR)
1  3,901,463      1.0000 3,901,463         0         0      NaN
2  5,339,085      0.9826 5,433,719    94,634    69,796    0.738
3  4,909,315      0.9127 5,378,826   469,511   118,278    0.252
4  4,588,268      0.8661 5,297,906   709,638   130,514    0.184
5  3,873,311      0.7973 4,858,200   984,889   260,065    0.264
6  3,691,712      0.7223 5,111,171 1,419,459   410,087    0.289
7  3,483,130      0.6153 5,660,771 2,177,641   557,519    0.256
8  2,864,498      0.4155 6,893,493 4,028,995   861,372    0.214
9  1,363,294      0.2341 5,824,117 4,460,823   998,750    0.224
10   344,014      0.0684 5,028,331 4,684,317 1,492,354    0.319
                  Totals
Latest:    34,358,090.00
Ultimate:  53,387,997.33
IBNR:      19,029,907.33
Mack S.E.:  2,533,277.54
CV(IBNR):           0.13

Bref, si l'on ne dispose que de données incomplètes, il faut faire attention quand on fait une régression log-Poisson...  

Incertitude et boni-mali en provisionnement

Formation lundi dans le cadre de la formation continue de l'Institut des Actuaires sur le thème "incertitudes dans les modèles de provisionnement en assurance non-vie". Au programme, on a retrouvé des noms connus du blog,
  • Yannnick Appert Raulin "provisionnement et solvabilité II" [slides ici]
  • Arthur Charpentier "modélisation des boni-mali" [slides ici]
  • Jérémie Payen "modéles GLM en provisionnement" [slides ici]
  • Arnaud Lacoume "le risque à un an" [slides ici] (malheureusement cloué au lit à cause de la grippe et que j'ai remplacé autant que fait se pu)
Sinon je remets en ligne quelques références classiques sur le sujet, avec le papier du GIRO (ici) ou celui de Panning (). Sur l'incertitude à un an, je renvoie vers des vieux billets que j'ai pu faire (ici ou là), mais le coeur du sujet se trouve évoqué dans les documents récents du CEIOPS (),


où clairement il est dit que ce qui nous intéressera sera le "risque à un an",

où l'on retrouve explicitement l'idée de calculer  des msep selon la méthode de Merz & Wüthrich (2008).
Il existe aussi une étude menée auprès d'assureurs que je trouve un trop peu uniforme, dans le rapport dit AISAM-ACME (ici)

Il est mentionné que sur l'étude menée, le risque à un an était plus faible que le risque à ultime tel qu'il était calculé initialement,

Il y a aussi des documents récents sur le sujet, en particulier les slides utilisés par Peter England à Zürich le mois dernier (ici) ou les travaux originaux de Merz et Wüthrich sur le sujet ().
Mais j'attends toujours des réactions concrètes d'assureurs qui auraient essayé de mettre en oeuvre ces nouvelles résolutions. Pour ma part, je pense que certains auront la mauvaise surprise d'être loins des "gains" annoncés par le rapport AISAM-ACME... Mais comme le faisaient remarquer des participants à la formation, je suis mauvaise langue à vouloir voir le mal partout (ce que j'admet entièrement).

Remarque: histoire de me faire râler davantage, je vais reprendre un passage du rapport AISAM-ACME. Après m'être emporté sur les annologies simplistes liant VaR et TVaR (ici), voilà qu'on nous explique que les aspects temporels ne jouent pas vraiment... Si j'ai le temps de travailler sur ce point, je ferais un billet !

 

Tuesday, May 5 2009

GAM and claims reserving

Yesterday I posted a note on generalized additive models with R (here). I finally decided to mention the application on run-off triangle.I consider here the run-off triangle from table 4 in Distribution-free Calculation of the Standard Error of Chain Ladder Reserve Estimates by Thomas Mack (here, ASTIN Bulletin 23, 213-225).
The standard log-Poisson model (glm) is based on the regression of incremental payments on 2 kinds of factors: origin year, and development. Hence, on this 9 year triangle, there is the intercept, plus 8 coefficients for origin years, and 8 for development years. This yield a 17 coefficient model, with - only - 45 observations.
An alternative is to consider a log-Poisson gam, where smoothed transforms of origin and developments years are considered. First, we consider splines functions as nonparametric smoothing terms, with respectively 4 and 8 knots.
It is also possible (instead of spline regressions) some loess smoth terms,