CLRS 2016 Reserve Example
Executive Summary
SFR consulting was retained by the CLRS 2016 R Workshop participants to prepare this analysis of unpaid claims and claims expenses. In this document, we present a analysis of unpaid claims and claim expenses. We developed this analysis using R and used R Markdown to create this document.
The relevant dates for our analysis are as follows:
- Accounting date: 1997-12-31
- Valuation date: 1997-12-31
- Information date: 1997-12-31
The scope of our analysis is to estimate the unpaid claims and claims expenses for the automobile liability coverage for CLRS Insurance Company.
Findings
Acknowledgement
Any questions related to this report should be directed to:
Rajesh Sahasrabuddhe, FCAS, MAAA
(215) 246-1028
rajesh_saharabuddhe@oliverwyman.com
Brian A. Fannin, ACAS
Emma Ran Li
(814) 753-0321
ril5077@gmail.com
Setting up the R Environment
We used several R packages to prepare this analysis.
# load packages
my_packages <- list("dplyr", "magrittr", "lubridate", "htmlTable", "knitr",
"xtable", "ChainLadder", "scales", "highcharter", "ggplot2")
sapply(X = my_packages, FUN = library, character.only = TRUE)Data
The data underlying this analysis was provided by the Casualty Actuarial Society (CAS) which was available at http://www.casact.org/research/reserve_data/ppauto_pos.csv. We downloaded the data on Sunday, Sep 18, 2016 at 3:52:09 PM.
We summarize that data in the table below:
| Data Summary as of 1997-12-31 | ||||
| Year | Premium | Incurred | Paid | Case |
|---|---|---|---|---|
| 1988 | 7,922,457 | 6,826,501 | 6,815,646 | 10,855 |
| 1989 | 8,893,210 | 7,733,559 | 7,712,077 | 21,482 |
| 1990 | 9,948,988 | 8,405,128 | 8,364,955 | 40,173 |
| 1991 | 10,803,190 | 8,291,065 | 8,215,810 | 75,255 |
| 1992 | 11,690,069 | 9,060,858 | 8,876,813 | 184,045 |
| 1993 | 12,533,746 | 9,714,779 | 9,337,099 | 377,680 |
| 1994 | 13,590,797 | 10,462,749 | 9,640,098 | 822,651 |
| 1995 | 14,401,255 | 10,612,837 | 9,006,113 | 1,606,724 |
| 1996 | 14,900,682 | 10,479,410 | 7,486,113 | 2,993,297 |
| 1997 | 15,065,713 | 10,648,978 | 4,344,144 | 6,304,834 |
| Total | 119,750,107 | 92,235,864 | 79,798,868 | 12,436,996 |
Loss Development
Paid Loss Development Experience
We present paid loss development experience in the triangle below.
Incurred Loss Development Experience
We present incurred loss development experience in the triangle below:
Obseravtions and Comments
In our review of the development experience, we noted the following:
- Paid development patterns have been generally lengthening particularly at intermediate maturities such as 2:3 and 3:4
- Incurred development experience indicates that a negative IBNR is most likely appropriate. More recent accident years have exhibited more favorable incurred development that older accident years.
Ultimate Loss Projections
We used the R package ChainLadder to project ultimate losses using the following methods:
- Mack Chain-Ladder Model applied to paid and incurred losses
- Bootstrap-Chain-Ladder Model applied to paid and incurred losses
- The Munich Chain-Ladder Model
- Traditional incurred and paid loss development Models
Mack-Chain-Ladder Model
mcl_paid <- MackChainLadder(Triangle = my_triangles$paid)
mcl_paid## MackChainLadder(Triangle = my_triangles$paid)
##
## Latest Dev.To.Date Ultimate IBNR Mack.S.E CV(IBNR)
## 1988 6,815,646 1.000 6,815,646 0 0 NaN
## 1989 7,712,077 0.999 7,719,821 7,744 1,549 0.2000
## 1990 8,364,955 0.996 8,396,601 31,646 5,103 0.1613
## 1991 8,215,810 0.991 8,288,545 72,735 6,042 0.0831
## 1992 8,876,813 0.982 9,043,728 166,915 10,809 0.0648
## 1993 9,337,099 0.962 9,702,726 365,627 26,568 0.0727
## 1994 9,640,098 0.925 10,422,621 782,523 45,702 0.0584
## 1995 9,006,113 0.852 10,571,471 1,565,358 71,775 0.0459
## 1996 7,486,113 0.714 10,490,872 3,004,759 146,538 0.0488
## 1997 4,344,144 0.397 10,933,658 6,589,514 508,516 0.0772
##
## Totals
## Latest: 79,798,868.00
## Dev: 0.86
## Ultimate: 92,385,689.36
## IBNR: 12,586,821.36
## Mack.S.E 549,869.43
## CV(IBNR): 0.04
plot(mcl_paid)mcl_incurred <- MackChainLadder(Triangle = my_triangles$incurred)
mcl_incurred## MackChainLadder(Triangle = my_triangles$incurred)
##
## Latest Dev.To.Date Ultimate IBNR Mack.S.E CV(IBNR)
## 1988 6,826,501 1.00 6,826,501 0 0 NaN
## 1989 7,733,559 1.00 7,730,688 -2,871 1,399 -0.487
## 1990 8,405,128 1.00 8,402,250 -2,878 2,975 -1.034
## 1991 8,291,065 1.00 8,285,251 -5,814 5,140 -0.884
## 1992 9,060,858 1.01 9,013,604 -47,254 7,495 -0.159
## 1993 9,714,779 1.01 9,611,411 -103,368 32,760 -0.317
## 1994 10,462,749 1.02 10,254,451 -208,298 62,572 -0.300
## 1995 10,612,837 1.03 10,268,035 -344,802 95,934 -0.278
## 1996 10,479,410 1.06 9,903,561 -575,849 170,716 -0.296
## 1997 10,648,978 1.09 9,739,379 -909,599 272,002 -0.299
##
## Totals
## Latest: 92,235,864.00
## Dev: 1.02
## Ultimate: 90,035,131.06
## IBNR: -2,200,732.94
## Mack.S.E 370,195.79
## CV(IBNR): -0.17
plot(mcl_incurred)Bootstrap-Chain-Ladder Model
bcl_paid <- BootChainLadder(Triangle = my_triangles$paid, R = 999,
process.distr = "gamma")
bcl_paid## BootChainLadder(Triangle = my_triangles$paid, R = 999, process.distr = "gamma")
##
## Latest Mean Ultimate Mean IBNR IBNR.S.E IBNR 75% IBNR 95%
## 1988 6,815,646 6,815,646 0 0 0 0
## 1989 7,712,077 7,720,017 7,940 11,095 12,928 29,469
## 1990 8,364,955 8,396,876 31,921 19,050 42,268 65,947
## 1991 8,215,810 8,288,992 73,182 24,734 88,695 117,596
## 1992 8,876,813 9,043,419 166,606 37,424 190,405 228,953
## 1993 9,337,099 9,702,904 365,805 56,433 402,836 465,502
## 1994 9,640,098 10,429,620 789,522 82,693 843,737 933,537
## 1995 9,006,113 10,575,586 1,569,473 119,093 1,651,655 1,770,856
## 1996 7,486,113 10,496,129 3,010,016 168,483 3,124,542 3,284,932
## 1997 4,344,144 10,950,888 6,606,744 347,976 6,848,884 7,151,304
##
## Totals
## Latest: 79,798,868
## Mean Ultimate: 92,420,077
## Mean IBNR: 12,621,209
## IBNR.S.E 469,377
## Total IBNR 75%: 12,936,532
## Total IBNR 95%: 13,391,252
plot(bcl_paid)bcl_incurred <- BootChainLadder(Triangle = my_triangles$incurred, R = 999, process.distr = "gamma")
bcl_incurred## BootChainLadder(Triangle = my_triangles$incurred, R = 999, process.distr = "gamma")
##
## Latest Mean Ultimate Mean IBNR IBNR.S.E IBNR 75% IBNR 95%
## 1988 6,826,501 6,826,501 0 0 0.00e+00 0
## 1989 7,733,559 7,729,945 -3,614 30,266 4.97e+00 20,848
## 1990 8,405,128 8,401,645 -3,483 35,647 1.34e+02 28,106
## 1991 8,291,065 8,287,959 -3,106 42,575 8.45e+02 43,282
## 1992 9,060,858 9,019,090 -41,768 71,322 -2.00e+03 34,741
## 1993 9,714,779 9,617,239 -97,540 93,176 -3.07e+04 8,478
## 1994 10,462,749 10,258,152 -204,597 134,185 -1.03e+05 -32,799
## 1995 10,612,837 10,284,705 -328,132 166,827 -2.09e+05 -97,298
## 1996 10,479,410 9,915,060 -564,350 214,457 -4.13e+05 -265,696
## 1997 10,648,978 9,775,586 -873,392 249,031 -6.96e+05 -492,919
##
## Totals
## Latest: 92,235,864
## Mean Ultimate: 90,115,883
## Mean IBNR: -2,119,981
## IBNR.S.E 532,978
## Total IBNR 75%: -1,758,975
## Total IBNR 95%: -1,296,160
plot(bcl_incurred)Munich-Chain-Ladder Model
munich <- MunichChainLadder(Paid = my_triangles$paid, Incurred = my_triangles$incurred,
est.sigmaP = 0.1, est.sigmaI = 0.1)
munich## MunichChainLadder(Paid = my_triangles$paid, Incurred = my_triangles$incurred,
## est.sigmaP = 0.1, est.sigmaI = 0.1)
##
## Latest Paid Latest Incurred Latest P/I Ratio Ult. Paid Ult. Incurred
## 1988 6,815,646 6,826,501 0.998 6,815,646 6,826,501
## 1989 7,712,077 7,733,559 0.997 7,719,654 7,730,629
## 1990 8,364,955 8,405,128 0.995 8,392,987 8,401,359
## 1991 8,215,810 8,291,065 0.991 8,277,687 8,282,288
## 1992 8,876,813 9,060,858 0.980 9,007,620 9,004,087
## 1993 9,337,099 9,714,779 0.961 9,594,069 9,576,316
## 1994 9,640,098 10,462,749 0.921 10,201,439 10,171,389
## 1995 9,006,113 10,612,837 0.849 10,142,317 10,095,103
## 1996 7,486,113 10,479,410 0.714 9,616,895 9,547,866
## 1997 4,344,144 10,648,978 0.408 9,335,620 9,266,960
## Ult. P/I Ratio
## 1988 0.998
## 1989 0.999
## 1990 0.999
## 1991 0.999
## 1992 1.000
## 1993 1.002
## 1994 1.003
## 1995 1.005
## 1996 1.007
## 1997 1.007
##
## Totals
## Paid Incurred P/I Ratio
## Latest: 8.0e+07 9.2e+07 0.87
## Ultimate: 8.9e+07 8.9e+07 1.00
plot(munich)Incurred Loss Development Method with Selected Factors
In the chart below, we first present the observed incremental development factors.
paid_dev_analysis <- dev_factor_df(my_triangles$paid)## Joining, by = c("acc_yr", "lag")
paid_dev_analysis$ggWe then select the following development factors:
paid_dev_analysis$sel_ldf_df$sel_ldf = c(
1.72, 1.18, 1.08,
1.04, 1.02, 1.01,
1.00, 1.00, 1.00)
paid_dev_analysis$sel_ldf_df$sel_cldf <- paid_dev_analysis$sel_ldf_df$sel_ldf %>%
rev() %>%
cumprod() %>%
rev()
paid_tail <- 1.02
paid_dev_analysis$sel_ldf_df$sel_cldf <-
paid_dev_analysis$sel_ldf_df$sel_cldf * paid_tail
paid_dev_analysis$sel_ldf_df## # A tibble: 9 × 3
## lag sel_ldf sel_cldf
## <dbl> <dbl> <dbl>
## 1 1 1.72 2.395462
## 2 2 1.18 1.392710
## 3 3 1.08 1.180263
## 4 4 1.04 1.092836
## 5 5 1.02 1.050804
## 6 6 1.01 1.030200
## 7 7 1.00 1.020000
## 8 8 1.00 1.020000
## 9 9 1.00 1.020000
We now add our selected incremental loss development factors (in red) to the chart.
Comparison of Methods
We now compare estimates by method
ultimates <- data_frame(acc_yr = row.names(summary(bcl_incurred)$ByOrigin),
bcl_incurred = summary(bcl_incurred)$ByOrigin$'Mean Ultimate',
bcl_paid = summary(bcl_paid)$ByOrigin$'Mean Ultimate',
mcl_incurred = summary(mcl_incurred)$ByOrigin$'Ultimate',
mcl_paid = summary(mcl_paid)$ByOrigin$'Ultimate',
munich_incurred = summary(munich)$ByOrigin$'Ult. Incurred',
munich_paid = summary(munich)$ByOrigin$'Ult. Paid',
incurred = summary(munich)$ByOrigin$'Latest Incurred',
paid = summary(munich)$ByOrigin$'Latest Paid')
ultimates## # A tibble: 10 × 9
## acc_yr bcl_incurred bcl_paid mcl_incurred mcl_paid munich_incurred
## <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 1988 6826501 6815646 6826501 6815646 6826501
## 2 1989 7729945 7720017 7730688 7719821 7730629
## 3 1990 8401645 8396876 8402250 8396601 8401359
## 4 1991 8287959 8288992 8285251 8288545 8282288
## 5 1992 9019090 9043419 9013604 9043728 9004087
## 6 1993 9617239 9702904 9611411 9702726 9576316
## 7 1994 10258152 10429620 10254451 10422621 10171389
## 8 1995 10284705 10575586 10268035 10571471 10095103
## 9 1996 9915060 10496129 9903561 10490872 9547866
## 10 1997 9775586 10950888 9739379 10933658 9266960
## # ... with 3 more variables: munich_paid <dbl>, incurred <dbl>, paid <dbl>
R packages
We used the following R packages to develop this analysis:
- Base R: R Core Team (2016). R: A language and environment for statistical computing. R Foundation for Statistical Computing, Vienna, Austria. URL https://www.R-project.org/.
We used rmdformats to produce this report.
- rmdformats: Julien Barnier (2016). rmdformats: HTML Output Formats and Templates for ‘rmarkdown’ Documents. R package version 0.3. https://CRAN.R-project.org/package=rmdformats
We used the following packages to prepare the analysis.
- Hadley Wickham and Romain Francois (2016). dplyr: A Grammar of Data Manipulation. R package version 0.5.0. https://CRAN.R-project.org/package=dplyr
- Stefan Milton Bache and Hadley Wickham (2014). magrittr: A Forward-Pipe Operator for R. R package version 1.5. https://CRAN.R-project.org/package=magrittr
- Garrett Grolemund, Hadley Wickham (2011). Dates and Times Made Easy with lubridate. Journal of Statistical Software, 40(3), 1-25. URL http://www.jstatsoft.org/v40/i03/.
- Max Gordon (2016). htmlTable: Advanced Tables for Markdown/HTML. R package version 1.6. https://CRAN.R-project.org/package=htmlTable
- Yihui Xie (2016). knitr: A General-Purpose Package for Dynamic Report Generation in R. R package version 1.14.
- Yihui Xie (2015) Dynamic Documents with R and knitr. 2nd edition. Chapman and Hall/CRC. ISBN 978-1498716963
- Yihui Xie (2014) knitr: A Comprehensive Tool for Reproducible Research in R. In Victoria Stodden, Friedrich Leisch and Roger D. Peng, editors, Implementing Reproducible Computational Research. Chapman and Hall/CRC. ISBN 978-1466561595
- David B. Dahl (2016). xtable: Export Tables to LaTeX or HTML. R package version 1.8-2. https://CRAN.R-project.org/package=xtable
- Markus Gesmann, Daniel Murphy, Yanwei (Wayne) Zhang, Alessandro Carrato, Giuseppe Crupi, Mario Wuthrich and Fabio Concina (2015). ChainLadder: Statistical Methods and Models for Claims Reserving in General Insurance. R package version 0.2.2. https://CRAN.R-project.org/package=ChainLadder
- Hadley Wickham (2016). scales: Scale Functions for Visualization. R package version 0.4.0. https://CRAN.R-project.org/package=scales
- Joshua Kunst (2016). highcharter: A Wrapper for the ‘Highcharts’ Library. R package version 0.4.0. https://CRAN.R-project.org/package=highcharter
- H. Wickham. ggplot2: Elegant Graphics for Data Analysis. Springer-Verlag New York, 2009.
Session Information
## R version 3.3.1 (2016-06-21)
## Platform: x86_64-w64-mingw32/x64 (64-bit)
## Running under: Windows 7 x64 (build 7601) Service Pack 1
##
## locale:
## [1] LC_COLLATE=English_United States.1252
## [2] LC_CTYPE=English_United States.1252
## [3] LC_MONETARY=English_United States.1252
## [4] LC_NUMERIC=C
## [5] LC_TIME=English_United States.1252
##
## attached base packages:
## [1] stats graphics grDevices utils datasets methods base
##
## other attached packages:
## [1] ggplot2_2.1.0.9000 highcharter_0.4.0 scales_0.4.0
## [4] ChainLadder_0.2.2 xtable_1.8-2 knitr_1.14
## [7] htmlTable_1.6 lubridate_1.6.0 magrittr_1.5
## [10] dplyr_0.5.0
##
## loaded via a namespace (and not attached):
## [1] tidyr_0.6.0 viridisLite_0.1.3 jsonlite_1.1
## [4] splines_3.3.1 shiny_0.14 assertthat_0.1
## [7] statmod_1.4.26 TTR_0.23-1 highr_0.6
## [10] stats4_3.3.1 yaml_2.1.13 lattice_0.20-33
## [13] quantreg_5.29 rlist_0.4.6.1 chron_2.3-47
## [16] digest_0.6.10 minqa_1.2.4 colorspace_1.2-6
## [19] sandwich_2.3-4 htmltools_0.3.5 httpuv_1.3.3
## [22] Matrix_1.2-6 plyr_1.8.4 psych_1.6.9
## [25] broom_0.4.1 biglm_0.9-1 SparseM_1.72
## [28] questionr_0.5 bookdown_0.1 purrr_0.2.2
## [31] lme4_1.1-12 MatrixModels_0.4-1 tibble_1.2
## [34] mgcv_1.8-12 car_2.1-3 lazyeval_0.2.0
## [37] nnet_7.3-12 pbkrtest_0.4-6 quantmod_0.4-6
## [40] mnormt_1.5-4 mime_0.5 evaluate_0.9
## [43] nlme_3.1-128 MASS_7.3-45 xts_0.9-7
## [46] foreign_0.8-66 data.table_1.9.6 tools_3.3.1
## [49] formatR_1.4 stringr_1.1.0 munsell_0.4.3
## [52] systemfit_1.1-18 grid_3.3.1 nloptr_1.0.4
## [55] rstudioapi_0.6 tweedie_2.2.1 htmlwidgets_0.7
## [58] igraph_1.0.1 miniUI_0.1.1 labeling_0.3
## [61] rmarkdown_1.0 codetools_0.2-14 gtable_0.2.0
## [64] DBI_0.5-1 reshape2_1.4.1 R6_2.1.3
## [67] cplm_0.7-4 zoo_1.7-13 actuar_1.2-2
## [70] stringi_1.1.1 parallel_3.3.1 rmdformats_0.3
## [73] Rcpp_0.12.7 coda_0.18-1 lmtest_0.9-34