Select Life Table

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