Function Repository Resource:

ActuarialCommutation

Source Notebook

Creates an Association containing values for the six standard commutation functions used in actuarial mathematics

Contributed by: Seth J. Chandler

ResourceFunction["ActuarialCommutation"][l,v]

computes values for the six standard commutation functions ("D","N","S", "C","M","R") as a function of surviving population fraction l and discount rate v.

Details and Options

ResourceFunction["ActuarialCommutation"] functions can be used to compute a number of quantities of interest in actuarial mathematics, such as the value of an annuity or death benefit.
The parameter l is a list containing the fraction of the initial population surviving at the start of each time unit.
The parameter v is a discount rate generally between 0 and 1, showing the value of money received one year from now.
The "ReturnForm" option directs the form in which the data is returned: permissible option values are as follows:
"FunctionAssociation" returns an association in which the commutation function names are the keys and the values are the values of each function at each successive unit of time;
"TimeAssociation" returns a nested association in which the outer keys are the successive units of time and the values are associations in which the keys are the names of the commutation functions and the values are the value of that function at the specified unit of time.
"FunctionValues" returns a nested list in which each outer list represents the values of a commutation function at a successive unit of time. The lists are ordered as "D", "N", "S", "C", "M", "R". For example, the fourth element of the returned values contains a list of the values for the "C" commutation function.
“TimeValues” returns a nested list in which each outer list represents a unit of time. Each inner list contains six values, one for each of the six commutation functions and in the order "D", "N", "S", "C", "M", "R".
The "InitialTime" option can (and probably should) be used when the mortality table begins at an age other than 0.
Although commutation functions and tables displaying them are used less frequently than in times when computation was less accessible, they are still a useful tool in swiftly computing quanities of interest in actuarial mathematics.

Examples

Basic Examples (3) 

Compute the commutation functions for a mortality table that goes from 1 to 0 in five periods and a discount rate of 0.9:

In[1]:=
ResourceFunction[
 "ActuarialCommutation"][{1, 0.9, 0.8, 0.2, 0.1, 0}, 0.9]
Out[1]=

Do the same computation as immediately above but return the values as a nested Association in which the outer keys represent years. The result is converted into a Dataset to aid visualization:

In[2]:=
ResourceFunction["ActuarialCommutation"][{1, 0.9, 0.8, 0.2, 0.1, 0}, 0.9, "ReturnForm" -> "TimeAssociation"] // Dataset
Out[2]=

Do the same computation as immediately above, but assume the starting age for the mortality vector is age 20:

In[3]:=
ResourceFunction["ActuarialCommutation"][{1, 0.9, 0.8, 0.2, 0.1, 0}, 0.9, "ReturnForm" -> "TimeAssociation", "InitialTime" -> 20] // Dataset
Out[3]=

Scope (3) 

Exact values will be provided where rational numbers are used for the inputs:

In[4]:=
ResourceFunction[
 "ActuarialCommutation"][{1, 9/10, 8/10, 2/10, 1/10, 0}, 9/10, "ReturnForm" -> "FunctionValues"]
Out[4]=

The function works on symbolic arguments:

In[5]:=
ResourceFunction["ActuarialCommutation"][Array[l, 5, 0], v]
Out[5]=

By adjusting the discount rate, the function can be used for mortality tables that go by time units other than a year. Compute the commutation functions of a mortality table that goes by 10-year periods when the annual discount rate is 0.95:

In[6]:=
ResourceFunction[
 "ActuarialCommutation"][{1, 0.9846173379875812`, 0.9639606131621938`,
   0.9325133217994516`, 0.8639769154117698`, 0.7361732007375918`, 0.5120752978556353`, 0.18294306933939167`, 0}, 0.95^10]
Out[6]=

Options (2) 

Changing the "ReturnForm" option changes the form of the output:

In[7]:=
Table[ResourceFunction[
  "ActuarialCommutation"][{1, 0.9, 0.8, 0.2, 0.1, 0}, 0.9, "ReturnForm" -> form], {form, {"FunctionAssociation", "TimeAssociation", "FunctionValues", "TimeValues"}}]
Out[7]=

Changing the "InitialTime" option changes the keys of the "TimeAssociation" return form; the values of each association remain the same:

In[8]:=
Table[ResourceFunction[
  "ActuarialCommutation"][{1, 0.9, 0.8, 0.2, 0.1, 0}, 0.9, "ReturnForm" -> "TimeAssociation", "InitialTime" -> x], {x, {0, 20, 40}}]
Out[8]=

Applications (8) 

Get the commutation functions for males based on "U.S. Historical Population Mortality Rates 2000-2017 for 2017" and a discount rate of 0.95:

In[9]:=
(maleMortality = 100000 ResourceFunction["MortalityConvert"][
     ReplacePart[CompressedData["
1:eJw9UnssFAAc1jq5XNKDyKs5rc0rvTwW9cnRJJ07r8q5w53DPEPOqyONxJJ3
Wh4zCVlh4rTU6dwk5Cqi2OlQ8lrMvNsklfXHt+/3z/f4bZ8uO8yZu0VOTo6+
geOrfoWavS7IW9rmdc/RDXrG+U16Re6o5+jtqp2+iL0+4l5D7mUYU7SmR808
8CK2mhJ6k4GjElmyDcETrwihQ90uTPjmZD+tq2QipyvRvoXPxPybAzusllkQ
rbtvWHlju2YJS7/LG6q3HaYIJ3xAMxtTnI3wQaD6aXKFLfs/u4mqyqnWHBRJ
Z2kqExzMBXy91bjiC7+X6p1pPC4skg1M40u5OKU8IxkM8YepvvwQqycAXgqS
/fTBoM38EBS4U0Z1zoch4tchFfLwlU3/CDBbvM2DGVexOF9BVn3N2/wzGqT4
wZHajjhE8Y5ZOLD4m72v41KVabclNQn71Ouf90XegMaDKFfTM8mQ7qaSWAsp
mNzJ9lcsTsUSiScW2KWhrIBu1NSQju9dpLpMagaIj7U8fC0zUfWIG8TPzoL8
vwOZD5WZNFkOhIHcVpPFXHT5x+pIi/NRvCCca/S/C4VrCeq6Vvfha70Ut9xe
CO2OMZTLSuDoGqYUnF8KW3qp07dzZbCXciYpauX40UxekTlUIFnJqTaPW4UZ
YqW8yc9qtG3trPAceQLKOkHNMLAOKV5T4xfs6rF2xCamIbwB0k9JkWfzBJBp
fDYQjT5DFpW5avSuGcPzYuLIByHSearOCc4ijGtXTtgfFiN1RI/tcLANDGIE
rdWxHZROp2r+yU6sMzruZFi/RU1J7hdzoQSC+bWPMZPv4RjuNhBt1wN+jYCd
ONCLkEhOXOuePsj/mY12Pwh/hf34DZ6gLtg=
"], -1 -> 1], "Hazard" -> "Survival"]) // Short
Out[9]=
In[10]:=
males2017 = ResourceFunction["ActuarialCommutation"][maleMortality, 0.95, "ReturnForm" -> "TimeAssociation", "InitialTime" -> 20] // Dataset
Out[10]=

Use the commutation dataset to compute the value of an "increasing annuity" issued to a 60 year old male that pays $1 its first year, $2 its second year, and one additional dollar each year thereafter:

In[11]:=
Query[Key@(60 + 1), #S &][males2017]/Query[Key@60, #D &][males2017]
Out[11]=

For a person aged 33, compute the net single premium for a 20-year term insurance payable at the end of the year of death, where $1 is paid if the death occurs in the first year, $2 is paid is the death occurs in the second year, and so on:

In[12]:=
(Query[Key@33, #R &][males2017] - Query[Key@(33 + 20), #R &][males2017] - Query[Key@53, 20*#M &][males2017])/Query[Key@33, #D &][males2017]
Out[12]=

Use the commutation dataset to plot the level annual premium for a term life insurance policy of 20 years as a function of the issue age of the insured:

In[13]:=
With[{m = Normal@Query[All, #M &][males2017], n = Normal@Query[All, #N &][males2017]},
 ListLinePlot[
  Table[(m[[Key@x]] - m[[Key@(x + 20)]])/(
   n[[Key@(x + 1)]] - n[[Key@(x + 20 + 1)]]), {x, 20, 78}], Sequence[
  DataRange -> {20, 78}, Frame -> True, FrameLabel -> {"issue age", "premium"}, "PlotLabel" -> "Annual net level premiums by issue age\nfor 20 year term policy"]]]
Out[13]=

Use the commutation dataset to compute the annual level premium (paid at the beginning of the year) per $1 of whole life coverage for a purchaser with issue age of 25:

In[14]:=
premiumMale25 = Query[Key@25, #M/#N &][males2017]
Out[14]=

Use the same dataset to plot the retrospective reserve on this policy according tothe attained age of the insured:

In[15]:=
retrospectiveReserve = Query[(Key /@ Range[25, 100])/*
    ListLinePlot, (#M/#D - premiumMale25*#N/#D &)/*Chop][males2017]
Out[15]=

Compute the net single premium needed to fund a life insurance policy of $1,000,000 on a 61 year old male for 10 years, with death benefits paid at the end of the year of death:

In[16]:=
1000000*((Query[Key@61, #M &][males2017] - Query[Key@(61 + 10), #M &][males2017])/
   Query[Key@61, #D &][males2017])
Out[16]=

Do the same computation using the commutation dataset but make the notation more transparent:

In[17]:=
With[{\[ScriptCapitalM] = Normal[males2017[All, "M"]], \[ScriptCapitalD] = Normal[males2017[All, "D"]]}, 1000000 (\[ScriptCapitalM][61] - \[ScriptCapitalM][
    61 + 10])/\[ScriptCapitalD][61]]
Out[17]=

Properties and Relations (1) 

The resource function MortalityConvert permits use of mortality data provided as a hazard or probability instead of as survival:

In[18]:=
ResourceFunction["ActuarialCommutation"][
 ResourceFunction["MortalityConvert"][{0.1, 0.2, 0.3, 0.4, 1}, "Hazard" -> "Survival"], 0.9]
Out[18]=

Neat Examples (1) 

Determine the amount an insurer would be willing to pay to rid itself of a $1,000,000 insurance policy issued to a 25 year-old priced under the mortality table contained in "U.S. Historical Population Mortality Rates 2000-2017 for 2017" when the insurer becomes aware that the insured’s hazards are 80% greater than contained in the table:

In[19]:=
insuredMortality = 100000 ResourceFunction["MortalityConvert"][
   ReplacePart[1.8*CompressedData["
1:eJw9UnssFAAc1jq5XNKDyKs5rc0rvTwW9cnRJJ07r8q5w53DPEPOqyONxJJ3
Wh4zCVlh4rTU6dwk5Cqi2OlQ8lrMvNsklfXHt+/3z/f4bZ8uO8yZu0VOTo6+
geOrfoWavS7IW9rmdc/RDXrG+U16Re6o5+jtqp2+iL0+4l5D7mUYU7SmR808
8CK2mhJ6k4GjElmyDcETrwihQ90uTPjmZD+tq2QipyvRvoXPxPybAzusllkQ
rbtvWHlju2YJS7/LG6q3HaYIJ3xAMxtTnI3wQaD6aXKFLfs/u4mqyqnWHBRJ
Z2kqExzMBXy91bjiC7+X6p1pPC4skg1M40u5OKU8IxkM8YepvvwQqycAXgqS
/fTBoM38EBS4U0Z1zoch4tchFfLwlU3/CDBbvM2DGVexOF9BVn3N2/wzGqT4
wZHajjhE8Y5ZOLD4m72v41KVabclNQn71Ouf90XegMaDKFfTM8mQ7qaSWAsp
mNzJ9lcsTsUSiScW2KWhrIBu1NSQju9dpLpMagaIj7U8fC0zUfWIG8TPzoL8
vwOZD5WZNFkOhIHcVpPFXHT5x+pIi/NRvCCca/S/C4VrCeq6Vvfha70Ut9xe
CO2OMZTLSuDoGqYUnF8KW3qp07dzZbCXciYpauX40UxekTlUIFnJqTaPW4UZ
YqW8yc9qtG3trPAceQLKOkHNMLAOKV5T4xfs6rF2xCamIbwB0k9JkWfzBJBp
fDYQjT5DFpW5avSuGcPzYuLIByHSearOCc4ijGtXTtgfFiN1RI/tcLANDGIE
rdWxHZROp2r+yU6sMzruZFi/RU1J7hdzoQSC+bWPMZPv4RjuNhBt1wN+jYCd
ONCLkEhOXOuePsj/mY12Pwh/hf34DZ6gLtg=
"], -1 -> 1], "Hazard" -> "Survival"]
Out[19]=
In[20]:=
insuredCommutation = ResourceFunction["ActuarialCommutation"][insuredMortality, 0.95, "ReturnForm" -> "TimeAssociation", "InitialTime" -> 20] // Dataset
Out[20]=
In[21]:=
Legended[
 Show[retrospectiveReserve, Query[(Key /@ Range[25, 100])/*(ListLinePlot[#, PlotStyle -> Red] &), (#M/#D - premiumMale25*#N/#D &)/*Chop][
   insuredCommutation], Sequence[
  Frame -> True, FrameLabel -> {"attained age", "$"}, GridLines -> Automatic]], LineLegend[{
ColorData[1][1], Red}, {"with assumed mortality", "with 180% assumed mortality"}]]
Out[21]=

Publisher

Seth J. Chandler

Version History

  • 1.0.0 – 28 August 2019

Source Metadata

Related Resources

Author Notes

This function can not handle so-called multiple decrement or competing risk models in which the insured may get different payouts depending on the cause of the policy terminating. Allegedly there is a way to extend commutation functions to handle this, but I have not yet acquired the material. If so, I will likely write something like MultipleDecrementCommutation as a separate Resource Function. I think this one should be kept relatively simple.

License Information