アクチュアリーのためのPython入門(応用編第2回)
保有契約の将来収支の実例
📚 アクチュアリーのためのPython入門
この記事は応用編の一部です。
▶ 目次はこちら
はじめに
前回に引き続き、複数の保有契約の将来収支を作成していきます。
前回は、次のことを取り上げました。
- 保有契約の将来収支の考え方
- 計算期間を保険期間へ変更することに伴う変更
- 残存表に満期を追加する
今回はそれらも踏まえて、
保有契約の将来収支の中心部分を整理していきます。
保有契約の保険収支
今回は養老保険の保険収支を計算します。
Excelファイルの契約内容は次とし、
ファイル名をcontr_endowment.xlsxとしておきます。
policyの項は契約年度で、各契約は年度始に加入の前提です。
計算基準年度は2022として、
(2022年度末の保有契約という意味です)
2023年度から2030年度までの
保険収支を計算して出力します。
おさらいと確認のため、
現在の養老保険の
保険料と保険料積立金の計算部分も載せます。
from core import *
import pandas as pd
# 養老保険
# 営業保険料の計算
def PremE(sex, start_age, term):
n = parse_term(term, start_age)
# 予定事業費
alpha = 0.025
delta = 0.02
gamma = 0.00215
beta = 0.03
# 営業保険料の計算
An = Axn(sex, start_age, n)
an = axn(sex, start_age, n)
value = (An + alpha + gamma * an) / ((1 - beta - delta) * an)
# 端数処理
value = roundhu(value, 6)
return value
# 純保険料の計算
def netPremE(sex, start_age, term):
n = parse_term(term, start_age)
return Axn(sex, start_age, n) / axn(sex, start_age, n)
# 保険料積立金の計算
def ResE(sex, start_age, term, t):
n = parse_term(term, start_age)
benefit = Axn(sex, start_age + t, n - t)
income = netPremE(sex, start_age, n) \
* axn(sex, start_age + t, n - t)
value = Decimal(str(benefit)) - Decimal(str(income))
return roundhu(value, 6)
# 解約返戻金の計算
def SVE(sex, start_age, n, t):
n = parse_term(term, start_age)
if t <= 10:
surrender_fact = 0.025 * (1 - t / min(n , 10))
else:
surrender_fact = 0
value = ResE(sex, start_age, n, t) - Decimal(str(surrender_fact))
return max(roundhu(value, 6),0)
# 死亡率の関数
def qdx(sex, age):
return qx[sex][age]
# 解約率の関数
def qwx(t):
if t == 0:
w = 0.05
elif t < 3:
w = 0.03
else:
w = 0.02
return w
前回の解約率の関数と死亡率の関数も追加してあります。
続いて残存表の部分です。
計算基準年度base_yearを設定しておきます。
Excelから取り込んだ契約内容には、
契約年度がありますので、policyに設定しています。
また、細かいですが、保険期間に60歳満期のA60があるので、
termのintを外しています。
# 計算基準年度
base_year = 2022
# 死亡指数
k = 0.7
# 結果を入れる変数
results = []
# Excelファイルの読み込み
df = pd.read_excel("contr_endowment.xlsx")
# 保険収支の計算
for _, row in df.iterrows():
policy = row["policy"]
sex = row["sex"]
age = int(row["age"])
term = row["term"]
amount = int(row["amount"])
l0 = amount # 初期保険金額
# 残存表の作成
lx = [l0] # 保有保険金額
dx = [] # 死亡保険金額
wx = [] # 解約保険金額
mx = [] # 満期保険金額
# 保険期間の変換
InsPeriod = parse_term(term, age)
# 生命表の作成
for t in range(InsPeriod):
q = qdx(sex, age + t)
w = qwx(t)
next_d = lx[-1] * q * k
next_w = lx[-1] * w
if t == InsPeriod - 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)
前回の満期も反映しています。
次は、保険収支の部分です。
変更点は満期を入れたことにより、
収支において、if文で保険期間を超えた場合は、
各収支項目を0としていた部分がなくなりました。
満期に合わせて、満期保険金を保険金支払いに加えています。
# 保険収支の項目
inprem = [] # 保険料収入
interest = [] # 利息収入
benefit = [] # 保険金支払い
surrender = [] # 解約返戻金支払い
expenses = [] # 事業費
reserve = [] # 保険料積立金繰入
profit = [] # 利益
P = float(PremE(sex, age, term))
for t in range(InsPeriod):
inprem.append(lx[t] * P) # 保険料の収入
Vt = float(ResE(sex, age, term, t)) # 期始保険料積立金
Vt1 = float(ResE(sex, age, term, t + 1)) # 期末保険料積立金
interest.append(((lx[t + 1] + mx[t]) * Vt1 + lx[t] * Vt) \
* 0.006 / (2 + 0.006)) # ハーディの公式
if t == InsPeriod - 1:
pay_ben = dx[t] + mx[t] # 死亡+満期保険金の支払い
else:
pay_ben = dx[t] # 死亡保険金の支払い
benefit.append(pay_ben)
W = float(SVE(sex, age, term, t + 1))
surrender.append(wx[t] * W) # 解約返戻金の支払い
expenses.append(inprem[t] * 0.1) # 事業費の支払い
# 保険料積立金繰入
if t == 0:
res = lx[1] * Vt1
elif t == InsPeriod - 1:
res = -lx[t] * Vt
else:
res = lx[t + 1] * Vt1 - lx[t] * Vt
reserve.append(res)
# 保険収支の計算
profit.append(inprem[t] + interest[t] - benefit[t] \
- surrender[t] - expenses[t] - reserve[t])
このあと、変数results1に計算結果を取りまとめますが、
そこで補整値を乗じるのが今回のポイントです。
モデルで計算した保有保険金額が、
計算基準年度末時点の保有金額と一致するように補整を行います。
ここでは、2023年度始の保有保険金額が設定値と一致するように、
契約ごとに補整値を計算し、各収支項目に乗じています。
補整値af = 元の保険金額 / 2023年度始の保有金額
# 補整値の計算
af = amount / lx[base_year - policy + 1]
results.append({"year":policy + t,
"inprem":int(inprem[t] * af),
"interest":int(interest[t] * af),
"benefit":int(benefit[t] * af),
"surrender":int(surrender[t] * af),
"expenses":int(expenses[t] * af),
"reserve":int(reserve[t] * af),
"profit":int(profit[t] * af)
})
Excelファイルで出力する部分は、
前回のとおりyearをキーにして合算しています。
また、2023年以上2030年以下を指定します。
結果はendowment_result.xlsxとして出力しています。
result_df = pd.DataFrame(results)
grouped = result_df.groupby("year").sum()
summary = grouped.reset_index()
summary = summary[(summary["year"] >= base_year + 1) & (summary["year"] <= 2030)]
summary.to_excel("endowment_result.xlsx", index=False)
まとめ
2回にわたって保有契約の将来収支について作成してきました。
実務でここまですることは多くありません。
- 数理ソフトウェアを改修したときのテスト用とか
- 簡易的でいいので感応度分析やストレステストを行いたいとか
そういった限られた場面になると思います。
ポイントがいくつかありますので、それを理解して、
保有契約の収支の考え方を知っておくことが、
数理ソフトウェアを使いこなす上で
重要と考えています。
◀ 前の記事
保有契約の将来収支1
▶ 次の記事
複数商品のキャッシュフロー
📚 目次
アクチュアリーのためのPython入門
