Life Table

Contents

Life Table#

A life table, from some initial age \(x_0\) to a maximum age \(\omega\), represents a survival model with probabilities \(_tp_x\). A life table is typically tabulated for the number of lives \(l_x\) at integer ages \(x\) only – fractional age assumptions would be needed to calculate survival probabilities for non-integer ages and durations.

\(l_{x_0+t} = l_{x_0}~_tp_{x_0}\).

  • \(l_{x_0}\) is an arbitrary positive number of lives at starting age \(x_0\) called the radix

\(d_x = l_x - l_{x+1}\)

  • it is usual for a life table to also show the values of \(d_x\), the expected of deaths in the year of age \(x\) to \(x+1\).

\(q_x = \dfrac{d_x}{l_x}\)

  • the mortality rate can then be derived, which is the probability that a life aged \(x\) dies within one year.

Recursion formulas from earlier sections allow the recursive construction of a table of other life contingent values, such as life expectancy, insurance, and annuities, at all ages.

Methods#

The LifeTable class specifies a given 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 life table entries.

from actuarialmath import LifeTable
import describe
describe.methods(LifeTable)
class LifeTable - Calculate life table, and iteratively fill in missing values

    Args:
      udd : assume UDD or constant force of mortality for fractional ages
      verbose : whether to echo update steps

    Notes:
      4 types of columns can be loaded and calculated in the life table:

      - 'q' : probability (x) dies in one year
      - 'l' : number of lives aged x
      - 'd' : number of deaths of age x
      - 'p' : probability (x) survives at least one year

    Methods:
    --------

    set_table(fill, minage, maxage, l, d, p, q):
      Update life table

    fill_table(radix):
      Iteratively fill in missing table cells (does not check consistency)

    frame():
      Return life table columns and values in a DataFrame

    __getitem__(col):
      Returns a column of the life table

Examples#

The set_table method is called to load a life table, by age, with given values of number of lives, number of deaths, mortality rate, and/or survival probability: if the fill flag is set to True (by default), 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 life table.

AMLCR2 Exercise 3.2

You are given the following life table extract.

Age,x

\(l_x\)

52

89948

53

89089

54

88176

55

87208

56

86181

57

85093

58

83940

59

82719

60

81429

Calculate

  • \(_{0.2}q_{52.4}\) assuming UDD (fractional age assumption),

  • \(_{0.2}q_{52.4}\) assuming constant force of mortality (fractional age assumption),

  • \(_{5.7}p_{52.4}\) assuming UDD,

  • \(_{5.7}p_{52.4}\) assuming constant force of mortality,

  • \(_{3.2|2.5}q_{52.4}\) assuming UDD, and

  • \(_{3.2|2.5}q_{52.4}\) assuming constant force of mortality.

table = {x:l for x,l in zip(range(52, 61), 
                            [89948, 89089, 88176, 87208, 86181, 
                             85093, 83940, 82719, 81429])}
life1 = LifeTable(udd=True).set_table(l=table)
life2 = LifeTable(udd=False).set_table(l=table)
print([round(r, 6) for r in [life1.q_r(x=52, r=0.4, t=0.2),   # 0.001917                                 
                             life2.q_r(x=52, r=0.4, t=0.2),   # 0.001917                                 
                             life1.p_r(x=52, r=0.4, t=5.7),   # 0.935422                                 
                             life2.p_r(x=52, r=0.4, t=5.7),   # 0.935423                                 
                             life1.q_r(x=52, r=0.4, u=3.2, t=2.5),  # 0.030957                           
                             life2.q_r(x=52, r=0.4, u=3.2, t=2.5)]])  # 0.030950 
[0.001917, 0.001917, 0.935422, 0.935423, 0.030957, 0.03095]

SOA Question 6.53

A warranty pays 2000 at the end of the year of the first failure if a washing machine fails within three years of purchase. The warranty is purchased with a single premium, G, paid at the time of purchase of the washing machine. You are given:

  • 10% of the washing machines that are working at the start of each year fail by the end of that year

  • i = 0.08

  • The sales commission is 35% of G

  • G is calculated using the equivalence principle

Calculate G.

print("SOA Question 6.53:  (D) 720")
x = 0
life = LifeTable().set_interest(i=0.08)\
                   .set_table(q={x: 0.1, x+1: 0.1, x+2: 0.1})
A = life.term_insurance(x, t=3)
G = life.gross_premium(a=1, A=A, benefit=2000, initial_premium=0.35)
print(A, G)
print(life.frame())
SOA Question 6.53:  (D) 720
0.23405349794238678 720.1646090534978
          l        d    q    p
0  100000.0  10000.0  0.1  0.9
1   90000.0   9000.0  0.1  0.9
2   81000.0   8100.0  0.1  0.9
3   72900.0      NaN  NaN  NaN

SOA Question 6.41

For a special fully discrete 2-year term insurance on (x), you are given:

  • \(q_x = 0.01\)

  • \(q_{x + 1} = 0.02\)

  • \(i = 0.05\)

  • The death benefit in the first year is 100,000

  • Both the benefits and premiums increase by 1% in the second year

Calculate the annual net premium in the first year.

print("SOA Question 6.41:  (B) 1417")
x = 0
life = LifeTable().set_interest(i=0.05)\
                  .set_table(q={x:.01, x+1:.02})
P = 1416.93
a = 1 + life.E_x(x, t=1) * 1.01
A = (life.deferred_insurance(x, u=0, t=1)
     + 1.01 * life.deferred_insurance(x, u=1, t=1))
print(a, A)
P = 100000 * A / a
print(P)
print(life.frame())
SOA Question 6.41:  (B) 1417
1.9522857142857144 0.027662585034013608
1416.9332301924137
          l       d     q     p
0  100000.0  1000.0  0.01  0.99
1   99000.0  1980.0  0.02  0.98
2   97020.0     NaN   NaN   NaN

SOA Question 3.11

For the country of Bienna, you are given:

  • Bienna publishes mortality rates in biennial form, that is, mortality rates are of the form: \(_2q_{2x},\) for \(x = 0,1, 2,...\)

  • Deaths are assumed to be uniformly distributed between ages \(2x\) and \(2x + 2\), for \(x = 0,1, 2,...\)

  • \(_2q_{50} = 0.02\)

  • \(_2q_{52} = 0.04\) Calculate the probability that (50) dies during the next 2.5 years.

print("SOA Question 3.11:  (B) 0.03")
life = LifeTable(udd=True).set_table(q={50//2: .02, 52//2: .04})
print(life.q_r(50//2, t=2.5/2))
print(life.frame())
SOA Question 3.11:  (B) 0.03
0.0298
           l       d     q     p
25  100000.0  2000.0  0.02  0.98
26   98000.0  3920.0  0.04  0.96
27   94080.0     NaN   NaN   NaN

SOA Question 3.5

You are given:

\(x\)

60

61

62

63

64

65

66

67

\(l_x\)

99,999

88,888

77,777

66,666

55,555

44,444

33,333

22,222

\(a =~ _{3.4|2.5}q_{60}\) assuming a uniform distribution of deaths over each year of age

\(b =~ _{3.4|2.5}q_{60}\) assuming a constant force of mortality over each year of age

Calculate \(100,000( a − b )\)

print("SOA Question 3.5:  (E) 106")
l = {60+x: n*11111 for x,n in enumerate([9, 8, 7, 6, 5, 4, 3, 2])}
a, b = (LifeTable(udd=udd).set_table(l=l).q_r(60, u=3.4, t=2.5)
        for udd in [True, False])
print(100000 * (a - b))
SOA Question 3.5:  (E) 106
106.16575827938624

SOA Question 3.14

You are given the following information from a life table:

x

\(l_x\)

\(d_x\)

\(p_x\)

\(q_x\)

95

0.40

96

0.20

97

72

1.00

You are also given:

  • \(l_{90} = 1000\) and \(l_{93} = 825\)

  • Deaths are uniformly distributed over each year of age.

Calculate the probability that (90) dies between ages 93 and 95.5.

print("SOA Question 3.14:  (C) 0.345")
life = LifeTable(udd=True).set_table(l={90: 1000, 93: 825},
                                     d={97: 72},
                                     p={96: .2},
                                     q={95: .4, 97: 1})
print(life.q_r(90, u=93-90, t=95.5-93))
print(life.frame())
SOA Question 3.14:  (C) 0.345
0.345
         l      d    q    p
90  1000.0    NaN  NaN  NaN
93   825.0    NaN  NaN  NaN
95   600.0  240.0  0.4  0.6
96   360.0  288.0  0.8  0.2
97    72.0   72.0  1.0  0.0
98     0.0    NaN  NaN  NaN