Tuesday, 1 April 2014

Mortality Projections

Introduction

As mentioned in earlier posts, one key element missing from Mortality Manager is handling of future mortality improvements.

This post will start to address this limitation, by adding a facility to generate mortality projections in line with the model provided by the Continuous Mortality Investigation (CMI) under CMI Working paper 63 in the spreadsheet Cmi2012model.xls. This is referred to as the CMI_2012 model and can be downloaded at:
http://www.actuaries.org.uk/research-and-resources/documents/cmi-mortality-projections-model-cmi2012

(Note that there is an updated CMI_2013 model, but this has not been made publicly available.)

The Model

Although the spreadsheet is complicated, the model itself is relatively simple. It depends heavily on a large amount of data stored in the spreadsheet. These can be adjusted, if the model is used in Advanced mode.

It is much simpler just to use the model in Core mode. In this mode, the model depends only on three factors entered in the Inputs sheet:
  1. Gender - Male or Female
  2. Long-Term Rates of Mortality Improvement - for example, 0.1%
  3. Constant Additional Rate of Mortality Improvement - for example, 0.01%
 These inputs can be held within F# using a Discriminated Union Type and a Record Type:
 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
//MODEL INPUTS
//types
type gender = 
    | Male
    | Female
    
type cmiInputs = 
    { Gender : gender
      LongTermRate : float
      ConstantAddition : float }

The data from the spreadsheets used to drive the model can be stored as 2D arrays in F#. For example, the data stored in sheet CoreParameters, Columns K:AC, Rows 145:245 is stored in variable initRatesF as a float[,].

Note that to be consistent with the other parts of Mortality Manager, the results are calculated from age 0 to age 120. The CMI model uses ages 20 to 150. Note that I have used the (unrealistic) assumption that all ages 20 and below are modelled identically.

Initial Results

In the first update to Mortality Manager I have replicated the creation of the main projection results under Core mode. I have replicated the results generated in sheet:
  • Proj Mort Imps -  Projection of Aggregate Annual Rates of Mortality Improvement
The results are calculated by projecting separately an age/period effect and a cohort effect. Both of these are calculated using a cubic convergence function to smooth results for past periods included in the spreadsheet with the assumed long term effects. The F# code mimics the spreadsheet structure. For example, the following code replicates the results in sheet Convergence Fn by Age:

1: 
2: 
3: 
4: 
5: 
6: 
7: 
8: 
/// gets the convergence function by age: Sheet "Convergence Fn by Age", Columns G:BE
let convAge (inps : cmiInputs) = 
    ((perAgePerElems inps), convParams)
    ||> Array.map2 (fun p (a, b, c) -> 
            [| 0..50 |] |> Array.map (fun cl -> 
                                if cl > p then 0.0
                                else a * (float (cl) / float (p)) ** 3.0 + b * (float (cl) / float (p)) ** 2.0 + c * (float (cl) / float (p)) + 1.0))
    |> array2D

This function takes as input the record type holding the assumptions. On line 3, it uses other functions that produce arrays by age (0-120) for the periods for interpolation and the factors a, b and c used by the cubic function. On line 4, these two arrays are double piped (||>) to a map2 higher order function, which then applies the cubic function for projected years 0-50, but set to zero if above the limit for that age. On line 8 the result of an array of arrays is converted to a 2D array.

The main result is created using the following function:

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
/// gets the projected mortality improvements: Sheet "Proj Mort Imps", Columns D:BK
let projImps (inps : cmiInputs) = 
    let irs = initRates inps
    let pa = projAge inps
    let pc = projCoh inps
    let iyr = 2009
    [| 0..120 |]
    |> Array.map (fun i -> 
            [| 1991..2059 |] |> Array.map (fun y -> 
                                    if y <= iyr then irs.[i, y - 1991]
                                    else pa.[i, y - iyr] + pc.[(max 0 (i - y + iyr)), y - iyr] + inps.ConstantAddition))
    |> array2D

Lines 3 to 5 pull in results from other functions that generate the initial rates on mortality improvement, the projected improvements by age/period and the projected improvements by cohort. In lines 9 to 11, the initial rates are used up to 2009 and in later years the sum of the projected rate by age/period and by cohort and the assumed constant addition is used.

The complete code is held in module CmiProj in the file CmiProj.fs, which is stored on bitbucket.

Custom Task Pane

To start using this code I have created a Mortality Projections Custom Task Pane in Mortality Manager. In this first version, it simply allows specifying the three Core assumptions. On pressing the Generate Projection button, one sheet is created giving the projected mortality improvements. This sheets is given a suitable name depending on the input chosen.

This is what the Mortality Manager looks like using this functionality:



In later posts, I will add more functionality to replicate the samples provided in the CMI spreadsheet, add functionality to be able to use the projections with any mortality tables held in mortality manager and to calculate mortality, commutation and present value functions allowing for mortality improvements.



No comments:

Post a Comment