0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

アクチュアリーのためのPython入門(保有契約の将来収支2)

0
Last updated at Posted at 2026-04-04

アクチュアリーのためのPython入門(応用編第2回)

保有契約の将来収支の実例

📚 アクチュアリーのためのPython入門
この記事は応用編の一部です。
目次はこちら

はじめに

前回に引き続き、複数の保有契約の将来収支を作成していきます。
前回は、次のことを取り上げました。

  • 保有契約の将来収支の考え方
  • 計算期間を保険期間へ変更することに伴う変更
  • 残存表に満期を追加する

今回はそれらも踏まえて、
保有契約の将来収支の中心部分を整理していきます。

保有契約の保険収支

今回は養老保険の保険収支を計算します。
Excelファイルの契約内容は次とし、
ファイル名をcontr_endowment.xlsxとしておきます。
policyの項は契約年度で、各契約は年度始に加入の前提です。

image.png

計算基準年度は2022として、
(2022年度末の保有契約という意味です)
2023年度から2030年度までの
保険収支を計算して出力します。

おさらいと確認のため、
現在の養老保険の
保険料と保険料積立金の計算部分も載せます。

endowment.py
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があるので、
termintを外しています。

endowment.py
# 計算基準年度
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としていた部分がなくなりました。
満期に合わせて、満期保険金を保険金支払いに加えています。

endowment.py
    # 保険収支の項目
    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年度始の保有金額

cashflow.py
        # 補整値の計算
        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として出力しています。

endowment.py
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)

作成されたファイルを開くと次のようになっています。
image.png

まとめ

2回にわたって保有契約の将来収支について作成してきました。
実務でここまですることは多くありません。

  • 数理ソフトウェアを改修したときのテスト用とか
  • 簡易的でいいので感応度分析やストレステストを行いたいとか

そういった限られた場面になると思います。
ポイントがいくつかありますので、それを理解して、
保有契約の収支の考え方を知っておくことが、
数理ソフトウェアを使いこなす上で
重要と考えています。

前の記事
保有契約の将来収支1

次の記事
複数商品のキャッシュフロー

📚 目次
アクチュアリーのためのPython入門

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?