アクチュアリーのためのPython入門(保険数理モデリング編第7回)
死亡リスク額の計算2
📚 アクチュアリーのためのPython入門
この記事は保険数理モデリング編の一部です。
▶ 目次はこちら
▶ 逆引きガイドはこちら
はじめに
前回は、死亡ストレスを与えた場合の現在推計と、
1年後の死亡ストレス後の現在推計を計算しました。
今回は、それを一般化し、
t年後の死亡ストレスありの現在推計を計算します。
また、t年後の標準の現在推計も計算し、
t年後の死亡リスクも計算できるようにします。
キャッシュフローの修正
キャッシュフローの計算するファイルcashflow_mort.pyでは、
死亡ストレス部分を修正します。
引数にストレスを与える年度と、
ストレスありとなしを選択できる値を加えます。
# 死亡ストレスの計算(mode=0:ストレスなし,1:ストレスあり)
def mort_stress(policy_y, t, stress_y, mode):
if mode == 0:
str = 1
else:
if policy_y + t >= stress_y:
str = 1.125
else:
str = 1
return str
また、キャッシュフローを計算する関数create_cashflowにも、
同様に引数にstress_yearとmodeを加えます。
ここでは、デフォルト値も与えておきます。
# キャッシュフロー計算の関数化 base_yearは計算基準年度
def create_cashflow(base_year = 2022, stress_year = 2023, mode = 0):
残存表の死亡率に、
先に作成した死亡ストレスの結果を乗じます。
# 生命表の作成
for t in range(n):
str = mort_stress(policy, t, stress_year ,mode)
q = qdx(sex, age + t)
w = qwx(product, t, m)
next_d = lx[-1] * q * mort_k(product) * str
next_w = lx[-1] * w
if t == n - 1:
next_m = lx[-1] - next_d - next_w
next_l = 0
else:
next_m = 0
next_l = lx[-1] - next_d - next_w
他は今までと同じです。
以下に、コード全体も載せておきます。
# t年経過後の死亡リスク(一般化)
from core import *
from endowment import PremE, SVE
from term import PremT, SVT
from whole import PremW, SVW
import pandas as pd
# 死亡指数の関数化
def mort_k(product):
match product:
case "E":
k = 0.8
case "T":
k = 0.7
case "W":
k = 0.85
return k
# 死亡率の関数
def qdx(sex, age):
return qx[sex][age]
# 保険料の計算式
premium_func = {
"E":PremE,
"T":PremT,
"W":PremW
}
def prem_func(product, sex, age, term):
return premium_func[product](sex, age, term)
# 解約率(養老保険)
def qwxE(t, m):
if t == 0:
w = 0.05
elif t < 3:
w = 0.03
else:
w = 0.02
return w
# 解約率(定期保険)
def qwxT(t, m):
if t == 0:
w = 0.08
elif t < 3:
w = 0.05
else:
w = 0.03
return w
# 解約率(終身保険)
def qwxW(t, m):
if t == 0:
w = 0.03
elif t >= m:
w = 0.01
else:
w = 0.02
return w
# 解約率の関数
surrender_func = {
"E":qwxE,
"T":qwxT,
"W":qwxW
}
def qwx(product, t, m):
return surrender_func[product](t, m)
# 解約返戻金の計算式
surrendervalue_func = {
"E":SVE,
"T":SVT,
"W":SVW
}
def sv_func(product, sex, age, term ,t):
return surrendervalue_func[product](sex, age, term, t)
# 満期保険金
def maturity(product):
if product == "T":
value = 0 # 定期保険は0
else:
value = 1 # 他は1
return value
# 最終年齢(終身保険用)
def omega(sex):
o = len(qx[sex]) - 1
return o
# 保険料払込期間
def PremPeriod(product, sex, age, term):
n = parse_term(term, age)
return n
# 保険期間
def InsPeriod(product, sex, age, term):
if product == "W":
value = omega(sex) - age # 終身は最終年齢
else:
value = parse_term(term, age) # 他はそのまま
return value
# 死亡ストレスの計算(mode=0:ストレスなし,1:ストレスあり)
def mort_stress(policy_y, t, stress_y, mode):
if mode == 0:
str = 1
else:
if policy_y + t >= stress_y:
str = 1.125
else:
str = 1
return str
# キャッシュフロー計算の関数化 base_yearは計算基準年度
def create_cashflow(base_year = 2022, stress_year = 2023, mode = 0):
# 結果を入れる変数
results1 = []
df = pd.read_excel("contr_all.xlsx")
for _, row in df.iterrows():
product = row["product"]
policy = int(row["policy"])
sex = row["sex"]
age = int(row["age"])
term = row["term"]
amount = int(row["amount"])
# 保険収支の計算
l0 = amount # 初期保険金額
# 残存表の作成
lx = [l0] # 保有保険金額
dx = [] # 死亡保険金額
wx = [] # 解約保険金額
mx = [] # 満期保険金額
n = InsPeriod(product, sex, age, term) # 保険期間
m = PremPeriod(product, sex, age, term) # 保険料払込期間
# 生命表の作成
for t in range(n):
str = mort_stress(policy, t, stress_year ,mode)
q = qdx(sex, age + t)
w = qwx(product, t, m)
next_d = lx[-1] * q * mort_k(product) * str
next_w = lx[-1] * w
if t == n - 1:
next_m = lx[-1] - next_d - next_w
next_l = 0
else:
next_m = 0
next_l = lx[-1] - next_d - next_w
lx.append(next_l)
dx.append(next_d)
wx.append(next_w)
mx.append(next_m)
# 保険収支の項目
inprem = [] # 保険料収入
benefit = [] # 保険金支払い
surrender = [] # 解約返戻金支払い
expenses = [] # 事業費
cashflow = [] # キャッシュフロー
P = float(prem_func(product, sex, age, term))
# キャッシュフローの計算
for t in range(n):
# 保険料の収入
if t < m:
inprem.append(lx[t] * P)
else:
inprem.append(0)
# 保険金の支払い
if t == n - 1:
# 死亡+満期保険金の支払い
pay_ben = dx[t] + mx[t] * maturity(product)
else:
# 死亡保険金の支払い
pay_ben = dx[t]
benefit.append(pay_ben)
# 解約返戻金の支払い
W = float(sv_func(product, sex, age, term, t + 1))
surrender.append(wx[t] * W)
# 事業費の支払い
expenses.append(inprem[t] * 0.3)
# キャッシュフロー
cashflow.append(benefit[t] +surrender[t] \
+ expenses[t] - inprem[t])
# 補整値の計算
af = amount / lx[base_year - policy + 1]
# 商品別のキャッシュフロー
results1.append({"product":product,
"year":policy + t,
"benefit":int(benefit[t] * af),
"surrender":int(surrender[t] * af),
"expenses":int(expenses[t] * af),
"inprem":int(inprem[t] * af),
"cashflow":int(cashflow[t] * af)
})
result_df = pd.DataFrame(results1)
# 商品別の集計
grouped_product = result_df.groupby(["product", "year"]).sum()
summary_product = grouped_product.reset_index()
# 合計の集計
grouped_total = result_df.groupby("year").sum()
summary_total = grouped_total.reset_index()
# Totalのラベルを付ける
summary_total["product"] = "Total"
# 結合
summary = pd.concat([summary_product, summary_total], ignore_index=True)
# 年度のフィルタ
summary = summary[summary["year"] >= base_year + 1]
return summary
# キャッシュフローの出力
if __name__ == "__main__":
summary = create_cashflow()
summary.to_excel("result_mort.xlsx", index=False)
現在推計の修正
続いて、現在推計を計算するファイルpresentvalue_mort.pyです。
こちらは修正点が多いので、全文を区切りながら載せます。
まずは、死亡リスク額をデータフレーム化するため、
ここではpandasを使います。
金利は前回と同じです。
# t年経過後死亡リスク(一般化)
from core import *
from cashflow_mort import create_cashflow
import pandas as pd
rate0 = [
0.00178,0.00295,0.00328,0.00400,0.00478,0.00519,0.00588,0.00680,0.00769,0.00877,
0.00972,0.01053,0.01129,0.01204,0.01283,0.01367,0.01452,0.01532,0.01605,0.01667,
0.01718,0.01759,0.01795,0.01827,0.01856,0.01885,0.01914,0.01944,0.01977,0.02012,
0.02051,0.02092,0.02135,0.02178,0.02221,0.02263,0.02305,0.02345,0.02384,0.02421,
0.02458,0.02492,0.02526,0.02558,0.02590,0.02619,0.02648,0.02676,0.02702,0.02728,
0.02753,0.02776,0.02799,0.02821,0.02842,0.02863,0.02883,0.02902,0.02920,0.02938,
0.02956,0.02972,0.02988,0.03004,0.03019,0.03034,0.03049,0.03063,0.03076,0.03089,
0.03102,0.03114,0.03126,0.03138,0.03150,0.03161,0.03172,0.03182,0.03193,0.03203,
0.03212,0.03222,0.03231,0.03240,0.03249,0.03258,0.03267,0.03275,0.03283
]
現価率はフォワードレートを使います。
s年後のt年金利を計算し、そこから現価率を計算します。
(tは0からはじまるので乗数は+1していることに注意してください)
# 現価率(s年経過後のt年金利)
def DF(s, t):
if s + t < len(rate0):
r1 = rate0[s + t]
else:
r1 = rate0[-1]
r0 = rate0[s-1]
fr = (((1 + r1) ** (s + t + 1))/(1 + r0) ** s) ** (1/(t+1))
value = fr ** (-t-0.5)
return value
続いて、現在推計の計算です。
ストレス開始年度やストレスありなしを変更しながら
現在推計を計算するので関数化します。
死亡ストレス対象外の期間exclude_tを設定します。
base_year=2022, stress_year=2023なら0
base_year=2022, stress_year=2024なら1
$\cdots$
となるようにします。
また、経過年数tを0からはじまるように付け直します。
現在推計の計算用の現価率は修正したDF関数を使います。
# base_year:計算基準年度
# stress_year:ストレス開始年度
# mode:(0:ストレスあり、1:ストレスなし)
def present_value(base_year, stress_year, mode):
# キャッシュフローの計算
summary = create_cashflow(base_year, stress_year, mode)
# 死亡ストレス対象外の期間
exclude_t = stress_year - base_year - 1
# Totalのみ抽出
summary = summary[summary["product"] == "Total"]
# ストレス年度以降を抽出
summary = summary[summary["year"] >= stress_year]
# 経過年数を追加
summary["t"] = summary["year"] - base_year - exclude_t - 1
# 現在価値を計算
PV = 0
for _, row in summary.iterrows():
t = int(row["t"])
cf = int(row["cashflow"])
PV += cf * DF(exclude_t, t)
return PV
現在推計を計算する関数ができましたので、
あとはfor文でループさせて死亡リスク額を計算ます。
死亡リスクを入れるリストmort_riskを初期化。
計算基準年度を2022で固定しています。
iを0~9までfor文で回し、0年後から9年後までの
死亡リスク額を計算します。
2つ目のfor文で、死亡ストレスなしの現在推計と
死亡ストレスありの現在推計を計算します。
最後にmort_riskへそれぞれの値を追加し、リスト化します。
mort_risk = []
base_year = 2022
for i in range(10):
year = base_year + i + 1
PV = []
for j in range(2):
PV.append(present_value(base_year, year, j))
mort_risk.append({"t":i,
"Curent_Estimate":int(PV[0]),
"Mortality_up":int(PV[1]),
"Mortality_risk":int(PV[1] - PV[0])})
また、pandasを使ってデータフレーム化します。
ここでは、期間が短いので内容をprintで出力します。
mort_chrono = pd.DataFrame(mort_risk)
print(mort_chrono)
結果は次のようになります。tは経過年度なので、
t=0は計算基準年度での死亡リスク額、
t=1は1年後の死亡リスク額、
t=2は2年後の死亡リスク額というようになります。
t Curent_Estimate Mortality_up Mortality_risk
0 0 812213 977670 165457
1 1 1488397 1648879 160482
2 2 2133682 2289428 155745
3 3 2745382 2896185 150802
4 4 3331089 3477018 145929
5 5 3892174 4033154 140980
6 6 4421658 4557269 135610
7 7 2753029 2883826 130797
8 8 3106192 3232290 126097
9 9 3303445 3424758 121312
まとめ
今回は、t年後の死亡リスク額を計算できるように、
前回まで計算した内容を一般化しました。
すぐに一般化するのは難しいので、
実際の数値例をいくつか計算して、
それから一般化していくのが分かりやすいかと思います。
実務では、こういった計算を将来収支の中に組み込んで、
将来の経済価値ベースの指標(ESR)を計算したり、
保険負債に含まれるMOCEの計算に使ったりします。
Pythonだけですぐに内容を理解するのは難しいので、
Excelなどでもっと簡単なモデルでも計算して理解を深めてみましょう。
📚 ナビゲーション
◀ 前の記事
死亡リスク額の計算1
▶ 次の記事
月次キャッシュフロー1
📚 目次
アクチュアリーのためのPython入門