アクチュアリーのためのPython入門(第2回)
生命表から基数表(Dx, Cx, Nx, Mx)を作成する
はじめに
前回は、生保標準生命表の死亡率を使って、
生存者数 $l_x$と死亡者数 $d_x$をPythonで作成しました。
今回は保険料計算や責任準備金計算の基礎となる
「計算基数表」である
- Dx
- Cx
- Nx
- Mx
を作成します。
実務ではExcelやVBAで作成している方も多いと思いますが、
ここでは分かりやすい形を意識します。
今回の前提
前回からの続きとして、次の前提を置きます。
- 死亡率:生保標準生命表2018
- 年齢:40~49歳
全年齢に拡張する場合は、データを入れ替えて動く構造にしています。
Pythonでの設計方針
今回のポイントは次の2つです。
- すべてリストで管理する
- for文で順番に処理できる形にする
理由は、年齢・利率・解約率などを変えた計算を
後で行いやすいことからです。
計算基数表の作成
まず前回からの次にとして、現価率$v$の設定を行います。
ここでは、予定利率を0.6%としておきます。
# 利率
i = 0.006
v = 1 / (1 + i)
次に、$D_x$ と$C_x$ を作成します。
生存者数$l_x$、死亡者数$d_x$のときと同じようにリストを用意して、
$D_x$=$l_x$×$v^x$、$C_x$=$d_x$×$v^{x+0.5}$で計算します。
# DxとCxの作成
Dx = []
Cx = []
for age, l, d in zip(ages, lx, dx):
Dx.append(l * v ** age)
Cx.append(d * v ** (age + 0.5))
ここで、前回同様にfor文の zip はages, lx, dxの組を
1つずつ取り出す意味です。
appendはDx, Cxのリストに計算結果を足していきます。
続いて、$N_x$・$M_x$ は「後ろから足す」ことがポイントです。
最後にreversedで順序を入れ替えます。
Nx = []
Mx = []
Dx_sum = 0
Cx_sum = 0
for D, C in zip(reversed(Dx), reversed(Cx)):
Dx_sum += D
Cx_sum += C
Nx.append(Dx_sum)
Mx.append(Cx_sum)
# 元の順序に戻す
Nx = list(reversed(Nx))
Mx = list(reversed(Mx))
最後に計算結果を確認してみます。
for age, D, C, N, M in zip(ages, Dx, Cx, Nx, Mx):
print(age, round(D, 2), round(C, 2), round(N, 2), round(M, 2))
出力例は次のようになります。
40 78719.22 92.61 761310.11 1344.48
41 78157.39 100.52 682590.89 1251.86
42 77591.02 108.3 604433.51 1151.34
43 77020.27 115.95 526842.49 1043.04
44 76445.29 124.23 449822.22 927.09
45 75865.5 133.88 373376.93 802.85
46 75279.54 145.61 297511.43 668.97
47 74685.38 159.35 222231.9 523.37
48 74081.07 174.31 147546.51 364.02
49 73465.44 189.71 73465.44 189.71
まとめ
- Dx・Cx・Nx・Mx は 生命保険数理の共通言語
- Pythonでは
「リスト+for文」 で素直に書くのが一番分かりやすい - この形を作っておくと、
- 保険料の計算
- 責任準備金の計算
- 解約率考慮の基数表
に使いまわせます。