Select Life Table#
Select and ultimate life model#
A newly selected policyholder is in the best health condition possible, compared to the general population with the same age. The life table can be expanded to tabulate the select period when selection has an effect on mortality. Since this selection process wears off after a few years, the ultimate part of the table can be then be used when select age is assumed to no longer have an effect on mortality.
Future survival probabilities depend on the individual’s current age and on the age at which the individual joined the group (i.e. was selected). Current age is written \([x]+s\), where \(x\) is the selected age and \(s\) is the number of years after selection.
If an individual joined the group more than \(d\) years ago (called the select period), future survival probabilities (called the ultimate mortality) depend only on current age. The initial selection effect is assumed to have worn off after \(d\) years. Current age can be written as \(x+s\) after the select period \(s \ge d\)
Select life tables reflect duration as well as age during the select period. A select and ultimate mortality table is shown in tabular form by listing agex vertically and the selection durations horizontally. If the select period is \(n\), there are \(n\) columns followed by a column with ultimate mortality. To find the mortality at a duration after a selection age, we read across the row corresponding to that selection age then continue down the last column.
Notation for select survival models:
\(_tp_{[x]+ s} =\) Pr(a life aged \(x + s\), selected at age \(x\), survives to age \(x +s +t\))
defines survival probability in the select period
\(_tq_{[x]+ s} =\) Pr(a life aged \(x + s\), selected at age \(x\), dies before age \(x +s + t\))
defines mortality rate in the select period
\(l_{[x]+s} = \dfrac{l_{x+d}}{_{d-s}p_{[x]+s}} =\) number of lives, selected at age \(x\), who are aged \(x+s\), given that \(l_{x+d}\) survived to age \(x+d\).
defines the life table within the select period, by working backwards from the value of \(l_{x+d}\) in the ultimate part of the table which only depends on current age.
With a select period \(d\) and for \(s \ge d\) (i.e. durations beyond the select period) the values of \(p_{[x-s]+s}, q_{[x-s]+s}, l_{[x-s]+s}\) depend only on current age \(x\) and not on \(s\). So for \(s \ge d\), these terms are all equal to and can be written simply as \(p_x, q_x, l_x\) respectively.
Methods#
The SelectLife class specifies a given select life table to be the survival model. It inherits all the general methods for computing life contingency risks, and overrides those methods where values can be looked up or calculated from select life table entries.
from actuarialmath import SelectLife
import describe
describe.methods(SelectLife)
class SelectLife - Calculate select life table, and iteratively fill in missing values
Args:
periods : number of select period years
verbose : whether to echo update steps
Notes:
6 types of columns can be loaded and calculated in the select table:
- 'q' : probability [x]+s dies in one year
- 'l' : number of lives aged [x]+s
- 'd' : number of deaths of age [x]+s
- 'A' : whole life insurance
- 'a' : whole life annuity
- 'e' : expected future curtate lifetime of [x]+s
Methods:
--------
set_table(fill, l, d, q, A, a, e):
Update from table, every age has row for all select durations
set_select(s, age_selected, fill, l, d, q, A, a, e):
Update a table column, for a particular duration s in the select period
fill_table(radix):
Fills in missing table values (does not check for consistency)
__getitem__(table):
Returns values from a select and ultimate table
frame(table):
Returns select and ultimate table values as a DataFrame
l_x(x, s):
Returns number of lives aged [x]+s computed from select table
p_x(x, s, t):
t_p_[x]+s by chain rule: prod(1_p_[x]+s+y) for y in range(t)
q_x(x, s, t, u):
t|u_q_[x]+s = [x]+s survives u years, does not survive next t
e_x(x, s, t, curtate):
Returns expected life time computed from select table
A_x(x, s, moment, discrete, kwargs):
Returns insurance value computed from select table
a_x(x, s, moment, discrete, kwargs):
Returns annuity value computed from select table
Examples#
The set_table method is called to load a life table, by age and duration, with given values of number of lives, number of deaths, mortality rate, insurance, annuity and/or life expectancy. The set_select method can also be called instead to update values of the same functions but for a particular duration \(s\) only. If the fill flag is set to True, fill_table is automatically called to fill in any missing values using recursion and identify formulas. All other computational methods can then be called in the usual manner, which will use the survival model provided by the select life table.
SOA Question 3.2:
You are given:
The following extract from a mortality table with a one-year select period:
\(x\) |
\(l_{[x]}\) |
\(d_{[x]}\) |
\(l_{x+1}\) |
\(x + 1\) |
|---|---|---|---|---|
65 |
1000 |
40 |
− |
66 |
66 |
955 |
45 |
− |
67 |
Deaths are uniformly distributed over each year of age
\(\overset{\circ}{e}_{[65]} = 15.0\)
Calculate \(\overset{\circ}{e}_{[66]}\).
print("SOA Question 3.2: (D) 14.7")
e_curtate = SelectLife.e_approximate(e_complete=15)
life = SelectLife(udd=True).set_table(l={65: [1000, None,],
66: [955, None]},
e={65: [e_curtate, None]},
d={65: [40, None,],
66: [45, None]})
print(life.e_r(66))
print(life.frame('e'))
SOA Question 3.2: (D) 14.7
14.67801047120419
e_[x]+s: 0 1
Age
65 14.50000 14.104167
66 14.17801 13.879121
SOA Question 4.16
You are given the following extract of ultimate mortality rates from a two-year select and ultimate mortality table:
\(x\) |
\(q_x\) |
|---|---|
50 |
0.045 |
51 |
0.050 |
52 |
0.055 |
53 |
0.060 |
The select mortality rates satisfy the following:
\(q_{[x]} = 0.7 q_x\)
\(q_{[x]+1} = 0.8 q_{x + 1}\)
You are also given that \(i = 0.04\).
Calculate \(A^1_{[50]:\overline{3|}}\).
print("SOA Question 4.16: (D) .1116")
q = [.045, .050, .055, .060]
q_ = {50+x: [0.7 * q[x] if x < 4 else None,
0.8 * q[x+1] if x+1 < 4 else None,
q[x+2] if x+2 < 4 else None]
for x in range(4)}
life = SelectLife().set_table(q=q_).set_interest(i=.04)
print(life.term_insurance(50, t=3))
SOA Question 4.16: (D) .1116
0.1115661982248521
SOA Question 4.13
For a 2-year deferred, 2-year term insurance of 2000 on [65], you are given:
The following select and ultimate mortality table with a 3-year select period:
\(x\) |
\(q_{[x]}\) |
\(q_{[x]+1}\) |
\(q_{[x]+2}\) |
\(q_{x+3}\) |
\(x+3\) |
|---|---|---|---|---|---|
65 |
0.08 |
0.10 |
0.12 |
0.14 |
68 |
66 |
0.09 |
0.11 |
0.13 |
0.15 |
69 |
67 |
0.10 |
0.12 |
0.14 |
0.16 |
70 |
68 |
0.11 |
0.13 |
0.15 |
0.17 |
71 |
69 |
0.12 |
0.14 |
0.16 |
0.18 |
72 |
\(i = 0.04\)
The death benefit is payable at the end of the year of death
Calculate the actuarial present value of this insurance.
print("SOA Question 4.13: (C) 350 ")
life = SelectLife().set_interest(i=0.04)\
.set_table(q={65: [.08, .10, .12, .14],
66: [.09, .11, .13, .15],
67: [.10, .12, .14, .16],
68: [.11, .13, .15, .17],
69: [.12, .14, .16, .18]})
print(life.deferred_insurance(65, t=2, u=2, b=2000))
SOA Question 4.13: (C) 350
351.0578236056159
SOA Question 3.13
A life is subject to the following 3-year select and ultimate table:
\([x]\) |
\(\ell_{[x]}\) |
\(\ell_{[x]+1}\) |
\(\ell_{[x]+2}\) |
\(\ell_{x+3}\) |
\(x+3\) |
|---|---|---|---|---|---|
55 |
10,000 |
9,493 |
8,533 |
7,664 |
58 |
56 |
8,547 |
8,028 |
6,889 |
5,630 |
59 |
57 |
7,011 |
6,443 |
5,395 |
3,904 |
60 |
58 |
5,853 |
4,846 |
3,548 |
2,210 |
61 |
You are also given:
\(e_{60} = 1\)
Deaths are uniformly distributed over each year of age
Calculate \(\overset{\circ}{e}_{[58]+2}\) .
print("SOA Question 3.13: (B) 1.6")
life = SelectLife().set_table(l={55: [10000, 9493, 8533, 7664],
56: [8547, 8028, 6889, 5630],
57: [7011, 6443, 5395, 3904],
58: [5853, 4846, 3548, 2210]},
e={57: [None, None, None, 1]})
print(life.e_r(58, s=2))
SOA Question 3.13: (B) 1.6
1.6003382187147688
SOA Question 3.12
X and Y are both age 61. X has just purchased a whole life insurance policy. Y purchased a whole life insurance policy one year ago.
Both X and Y are subject to the following 3-year select and ultimate table:
\(x\) |
\(\ell_{[x]}\) |
\(\ell_{[x]+1}\) |
\(\ell_{[x] + 2}\) |
\(\ell_{x+3}\) |
\(x+3\) |
|---|---|---|---|---|---|
60 |
10,000 |
9,600 |
8,640 |
7,771 |
63 |
61 |
8,654 |
8,135 |
6,996 |
5,737 |
64 |
62 |
7,119 |
6,549 |
5,501 |
4,016 |
65 |
63 |
5,760 |
4,954 |
3,765 |
2,410 |
66 |
The force of mortality is constant over each year of age.
Calculate the difference in the probability of survival to age 64.5 between X and Y.
print("SOA Question 3.12: (C) 0.055 ")
life = SelectLife(udd=False).set_table(l={60: [10000, 9600, 8640, 7771],
61: [8654, 8135, 6996, 5737],
62: [7119, 6549, 5501, 4016],
63: [5760, 4954, 3765, 2410]})
print(life.q_r(60, s=1, t=3.5) - life.q_r(61, s=0, t=3.5))
SOA Question 3.12: (C) 0.055
0.05465655938591829
SOA Question 3.7
For a mortality table with a select period of two years, you are given:
\(x\) |
\(q_{[x]}\) |
\(q_{[x]+1}\) |
\(q_{x+2}\) |
\(x+2\) |
|---|---|---|---|---|
50 |
0.0050 |
0.0063 |
0.0080 |
52 |
51 |
0.0060 |
0.0073 |
0.0090 |
53 |
52 |
0.0070 |
0.0083 |
0.0100 |
54 |
53 |
0.0080 |
0.0093 |
0.0110 |
55 |
The force of mortality is constant between integral ages.
Calculate \(1000 ~_{2.5}q_{[50]+0.4}\).
print("SOA Question 3.7: (b) 16.4")
life = SelectLife().set_table(q={50: [.0050, .0063, .0080],
51: [.0060, .0073, .0090],
52: [.0070, .0083, .0100],
53: [.0080, .0093, .0110]})
print(1000*life.q_r(50, s=0, r=0.4, t=2.5))
SOA Question 3.7: (b) 16.4
16.420207214428586
SOA Question 3.6
You are given the following extract from a table with a 3-year select period:
\(x\) |
\(q_{[x]}\) |
\(q_{[x]+1}\) |
\(q_{[x]+2}\) |
\(q_{x+3}\) |
\(x+3\) |
|---|---|---|---|---|---|
60 |
0.09 |
0.11 |
0.13 |
0.15 |
63 |
61 |
0.10 |
0.12 |
0.14 |
0.16 |
64 |
62 |
0.11 |
0.13 |
0.15 |
0.17 |
65 |
63 |
0.12 |
0.14 |
0.16 |
0.18 |
66 |
64 |
0.13 |
0.15 |
0.17 |
0.19 |
67 |
\(e_{64} = 5.10\)
Calculate \(e_{[61]}\).
print("SOA Question 3.6: (D) 5.85")
life = SelectLife().set_table(q={60: [.09, .11, .13, .15],
61: [.1, .12, .14, .16],
62: [.11, .13, .15, .17],
63: [.12, .14, .16, .18],
64: [.13, .15, .17, .19]},
e={61: [None, None, None, 5.1]})
print(life.e_x(61))
SOA Question 3.6: (D) 5.85
5.846832
SOA Question 3.3
You are given:
An excerpt from a select and ultimate life table with a select period of 2 years:
\(x\) |
\(\ell_{[ x ]}\) |
\(\ell_{[ x ] + 1}\) |
\(\ell_{x + 2}\) |
\(x + 2\) |
|---|---|---|---|---|
50 |
99,000 |
96,000 |
93,000 |
52 |
51 |
97,000 |
93,000 |
89,000 |
53 |
52 |
93,000 |
88,000 |
83,000 |
54 |
53 |
90,000 |
84,000 |
78,000 |
55 |
Deaths are uniformly distributed over each year of age
Calculate \(10,000 ~ _{2.2}q_{[51]+0.5}\).
print("SOA Question 3.3: (E) 1074")
life = SelectLife().set_table(l={50: [99, 96, 93],
51: [97, 93, 89],
52: [93, 88, 83],
53: [90, 84, 78]})
print(10000*life.q_r(51, s=0, r=0.5, t=2.2))
SOA Question 3.3: (E) 1074
1073.684210526316
SOA Question 3.1
You are given:
An excerpt from a select and ultimate life table with a select period of 3 years:
\(x\) |
\(\ell_{[ x ]}\) |
\(\ell_{[x]+1}\) |
\(\ell_{[x]+2}\) |
\(\ell_{x+3}\) |
\(x+3\) |
|---|---|---|---|---|---|
60 |
80,000 |
79,000 |
77,000 |
74,000 |
63 |
61 |
78,000 |
76,000 |
73,000 |
70,000 |
64 |
62 |
75,000 |
72,000 |
69,000 |
67,000 |
65 |
63 |
71,000 |
68,000 |
66,000 |
65,000 |
66 |
Deaths follow a constant force of mortality over each year of age
Calculate \(1000~ _{23}q_{[60] + 0.75}\).
print("SOA Question 3.1: (B) 117")
life = SelectLife().set_table(l={60: [80000, 79000, 77000, 74000],
61: [78000, 76000, 73000, 70000],
62: [75000, 72000, 69000, 67000],
63: [71000, 68000, 66000, 65000]})
print(1000*life.q_r(60, s=0, r=0.75, t=3, u=2))
SOA Question 3.1: (B) 117
116.7192429022082
show verbose calculations:
table={21: [0.00120, 0.00150, 0.00170, 0.00180],
22: [0.00125, 0.00155, 0.00175, 0.00185],
23: [0.00130, 0.00160, 0.00180, 0.00195]}
life = SelectLife(verbose=True).set_table(q=table)
print(life.p_x(x=21, s=1, t=4)) # 0.9931
life.frame('l')
1 l(x=21, s=1) = 99880.0
2 l(x=21, s=2) = 99730.18000000001
3 l(x=21, s=3) = 99560.63869400001
4 l(x=22, s=3) = 99381.4295443508
5 l(x=23, s=3) = 99197.57389969376
6 d(x=21, s=0) = 120.0
7 d(x=21, s=1) = 149.81999999999243
8 d(x=21, s=2) = 169.54130599999917
9 d(x=21, s=3) = 179.20914964920667
10 d(x=22, s=3) = 183.85564465704374
11 l(x=22, s=2) = 99555.65193523747
12 l(x=23, s=2) = 99376.45151241611
13 d(x=22, s=2) = 174.22239088667266
14 d(x=23, s=2) = 178.87761272235366
15 l(x=22, s=1) = 99710.2027494992
16 l(x=23, s=1) = 99535.70864625012
17 d(x=22, s=1) = 154.55081426173274
18 d(x=23, s=1) = 159.2571338340058
19 l(x=22, s=0) = 99834.9964951181
20 l(x=23, s=0) = 99665.27350180245
21 d(x=22, s=0) = 124.79374561889563
22 d(x=23, s=0) = 129.56485555233667
0.9931675400449915
| l_[x]+s: | 0 | 1 | 2 | 3 |
|---|---|---|---|---|
| Age | ||||
| 21 | 100000.000000 | 99880.000000 | 99730.180000 | 99560.638694 |
| 22 | 99834.996495 | 99710.202749 | 99555.651935 | 99381.429544 |
| 23 | 99665.273502 | 99535.708646 | 99376.451512 | 99197.573900 |