アクチュアリーのためのPython入門(第13回)
保険料積立金レート表の作成
📚 アクチュアリーのためのPython入門
この記事は入門編の一部です。
▶ 目次はこちら
はじめに
前回までで商品別の保険料レート表を作成してきました。
今回はその発展として「保険料積立金レート表」を作成します。
設計のポイントについて
今回は養老保険、定期保険、終身保険のみで、
保険期間も3パターンしかなく、分岐も少ないのですが、
その先の拡張を考えたときに、保険料とは異なり難しい点がありました。
養老保険と定期保険では、
保険期間=保険料払込期間
ですが、終身保険では、
保険期間=最終年齢(男性109歳、女性113歳)
ですので、この差異をif文で分岐させるのではなく、
商品ごとに期間解釈を持たせることにしました。
純保険料の計算
まずは、純保険料に性別を追加して、
なお、終身保険は、払込後の予定事業費を加えた
調整純保険料としています。
# 純保険料
# 養老保険
def netPremE(sex, start_age, term):
n = parse_term(term, start_age)
return Axn(sex, start_age, n) / axn(sex, start_age, n)
# 定期保険
def netPremT(sex, start_age, term):
n = parse_term(term, start_age)
return A1xn(sex, start_age, n) / axn(sex, start_age, n)
# 終身保険
def netPremW(sex, start_age, term):
n = parse_term(term, start_age)
gamma2 = 0.002
A = A1x(sex, start_age)
an = axn(sex, start_age, n)
a = ax(sex, start_age)
return (A + gamma2 * (a - an)) / an
n = parse_term(term, start_age)を入れて、
どの保険でも年齢満期を年満期へ変換できるようにしています。
また、終身保険は計算式でaxn(sex, start_age, n)が2回出てくるので、
一旦変数anにコピーしています。
続いて保険料積立金を計算する関数です。
まずは養老保険と定期保険のものです。
前回までのものに性別を加えています。
# 保険料積立金
# 養老保険
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 ResT(sex, start_age, term, t):
n = parse_term(term, start_age)
benefit = A1xn(sex, start_age + t, n - t)
income = netPremT(sex, start_age, n) \
* axn(sex, start_age + t, n - t)
# 確定時にDecimalへ
value = Decimal(str(benefit)) - Decimal(str(income))
return roundhu(value, 6)
続いて、終身保険の保険料積立金を計算する関数です。
保険料払込期間中と払込後で計算式が変わるので、
if文で分岐を入れています。
なお、計算式は調整純保険料式としています。
# 終身保険
def ResW(sex, start_age, term, t):
n = parse_term(term, start_age)
gamma2 = 0.002
if t < n:
a = axn(sex, start_age + t, n - t)
benefit = A1x(sex, start_age + t)
income = netPremW(sex, start_age, n) * a
expense = gamma2 * (ax(sex, start_age + t) - a)
value = Decimal(str(benefit)) - Decimal(str(income)) + Decimal(str(expense))
else:
benefit = A1x(sex, start_age + t)
expense = gamma2 * ax(sex, start_age + t)
value = Decimal(str(benefit)) + Decimal(str(expense))
return roundhu(value, 6)
続いて、保険料積立金の計算とレート表の出力を行います。
まずは、終身保険のため、最終年齢を定義しておきます。
# 最終年齢
omega ={"M":109, "F":113}
保険料のときと同じように、保険種類ごとに異なる要素をリスト化します。
これで保険種類が増えたときでも対応できるようにします。
ここでは保険期間を追加しておきます。
# 保険種類, 保険料積立金の関数, 払込期間, 保険期間
product2 = [
("Endowment", ResE, (10, 20, 30), None), # 養老保険
("Term", ResT, (10, 20, 30), None), # 定期保険
("Whole", ResW, ("A60", "A65", "A70"), omega) # 終身保険
]
次に計算する期間(保険期間)を設定します。
先ほどの設計のポイントの部分です。
# 保険期間がNoneなら保険期間
def t_max(period, age, sex, max_age):
m = parse_term(period, age)
if max_age is None:
n = m
else:
n = max_age[sex] - age
if n <=0:
raise ValueError("期間が不正です")
return m, n
保険種類別の設定項目で、保険期間がNoneの場合は、
払込期間と同じとし、異なる場合は入っている値
(この場合はomega)とします。
戻り値はm(払込期間)、n(保険期間)とします。
そして、計算と出力です。
import csv
# 出力ファイル名
file_name = r"C:\Users\〇〇\Documents\reserve_rate.csv"
# 上記の〇〇にはユーザー名が入ります。
with open(file_name, mode="w", newline="", encoding="utf-8-sig") as f:
writer = csv.writer(f)
# 1行目:カラム名
writer.writerow(["product", "sex", "age", "period", "t", "reserve"])
# 各要素は [商品種類, 性別, 加入年齢, 保険期間, 保険料]
for product_name, func, PremPeriod, InsPeriod in product2:
for sex in ("M","F"):
for p in PremPeriod:
for x in range(20, 51):
m, n = t_max(p, x, sex, InsPeriod)
for t in range(0, n + 1):
res = func(sex, x, m, t)
writer.writerow ([product_name, sex, x, p, t, res])
保険料と同じように一度rowsに計算結果を入れて、
それを出力という方法にしようとしました。
今回は大丈夫ですが、計算が多くなったときに、
メモリがあふれてしまう可能性があるので、
都度、計算して出力の形にしています。
計算結果のCSVを開いてみます。
次のようになるかと思います。
| product | sex | age | period | t | reserve |
|---|---|---|---|---|---|
| Endowment | M | 20 | 10 | 0 | 0 |
| Endowment | M | 20 | 10 | 1 | 0.097094 |
| ・・・ | |||||
| Whole | F | 50 | A70 | 62 | 0.998076 |
| Whole | F | 50 | A70 | 63 | 0.999013 |
まとめ
今回は、
- 保険料積立金の計算
- 積立金レートの一括作成
- CSVへの出力
を行いました。
これで保険料の計算だけではなく、
保険料積立金の計算もPythonで再現できるようになりました。
📚 ナビゲーション
◀ 前の記事
保険料レート表の作成
▶ 次の記事
ファイルの構成
📚 目次
アクチュアリーのためのPython入門