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入門(感応度分析)

0
Last updated at Posted at 2026-03-13

アクチュアリーのためのPython入門(第16回)

前提条件を変化させる

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

はじめに

前回は、養老保険を例に複数契約のキャッシュフローを合算し、
新契約全体のキャッシュフローを計算しました。

今回は、このような収支モデルを用いて、
前提条件が変化した場合に収支がどれくらい変化するか確認してみます。
このような分析を感応度分析といいます。
(感応度分析の説明を折りたたみ形式で記載しています)

感応度分析とは(初学者向け) 入力変数の値を変化させたときにモデル結果がどの程度変化するかを評価することです。 一般的には、金利を上下させたの資産価値の変動がよく使われます。

生命保険では、金利以外に次のような前提を変化させます。

  • 死亡率
  • 解約率
  • 事業費

これらを変化させた結果の保険収支への影響から、
ストレスへの耐性や、その影響の度合いなどを確認します。

引用先:一般社団法人生命保険協会
保険監督者国際機構 マクロ健全性監督に関する適用文書(仮訳)

今回は定期保険の保険収支モデルを用いて、
死亡指数が変化した場合に、
収支がどれくらい変化するかをPythonで確認します。

今回のような繰り返し計算はPythonの強みです。

今回の前提

今回は、定期保険のファイルterm.pyを使い、
次のような契約内容を仮定して、
保険収支(キャッシュフローに利息収入と保険料積立金繰入を追加)
を計算します。

ただし、ここでは利息収入は予定利息と同じとさせてください。
また、予定利息はハーディの公式で計算します。

保険期間 年齢 男性_保険金額 女性_保険金額
10年 20歳 10,000,000 15,000,000
10年 30歳 20,000,000 25,000,000
10年 40歳 30,000,000 35,000,000
20年 20歳 15,000,000 10,000,000
20年 30歳 25,000,000 20,000,000
20年 40歳 35,000,000 30,000,000
60歳 20歳 20,000,000 30,000,000
60歳 30歳 40,000,000 20,000,000
60歳 40歳 30,000,000 15,000,000

また、死亡指数は基本の0.7以外に、0.5, 1.1のパターンで計算します。
また、以下の関数は同ファイルまたはimportされている前提とします。

  • PremT :保険料の計算
  • netPremT :純保険料の計算
  • ResT :保険料積立金の計算
  • SVT :解約返戻金の計算

保険収支の計算

まずは、死亡指数を変化させます。
アサンプションと契約内容の一覧です。
計算結果が長いので、サンプルでは計算期間を10年にしています。
c_periodの数値で変更できるので、
必要に応じて変更してください。

term.py
# アサンプションの設定
c_period = 10  # 計算する期間
k = (0.5, 0.7, 1.1)        # 死亡指数
qwx = [0.02] * c_period    # 解約率

# 契約内容
contracts = [
    {"sex":"M", "age":20, "term":10, "amount":10_000_000},
    {"sex":"F", "age":20, "term":10, "amount":15_000_000},
    {"sex":"M", "age":30, "term":10, "amount":20_000_000},
    {"sex":"F", "age":30, "term":10, "amount":25_000_000},
    {"sex":"M", "age":40, "term":10, "amount":30_000_000},
    {"sex":"F", "age":40, "term":10, "amount":35_000_000},
    {"sex":"M", "age":20, "term":20, "amount":15_000_000},
    {"sex":"F", "age":20, "term":20, "amount":10_000_000},
    {"sex":"M", "age":30, "term":20, "amount":25_000_000},
    {"sex":"F", "age":30, "term":20, "amount":20_000_000},
    {"sex":"M", "age":40, "term":20, "amount":35_000_000},
    {"sex":"F", "age":40, "term":20, "amount":30_000_000},
    {"sex":"M", "age":20, "term":30, "amount":20_000_000},
    {"sex":"F", "age":20, "term":30, "amount":30_000_000},
    {"sex":"M", "age":30, "term":30, "amount":40_000_000},
    {"sex":"F", "age":30, "term":30, "amount":20_000_000},
    {"sex":"M", "age":40, "term":30, "amount":30_000_000},
    {"sex":"F", "age":40, "term":30, "amount":15_000_000}
]

続いて、養老のときと同じように合計結果を入れる変数を定義します。
今回は保険料積立金と利息収入があるので、それも変数に加えます。

term.py
inprem_total = {}    # 保険料収入
interest_total = {}  # 利息収入
benefit_total = {}   # 保険金支払
surrender_total = {} # 解約返戻金支払
expenses_total = {}  # 事業費
reserve_total = {}   # 保険料積立金繰入
profit_total = {}    # 利益

死亡指数をfor文で繰り返します。
今回はここがポイントになります。
また前回と同じように、合計の初期値0を入れておきます。

term.py
for scale in k:
# 保険収支の合計の初期値
    inprem_total[scale] = [0] * c_period    # 保険料収入
    interest_total[scale] = [0] * c_period  # 利息収入
    benefit_total[scale] = [0] * c_period   # 保険金支払い
    surrender_total[scale] = [0] * c_period # 解約返戻金支払い
    expenses_total[scale] = [0] * c_period  # 事業費
    reserve_total[scale] = [0] * c_period   # 保険料積立金繰入
    profit_total[scale] = [0] * c_period    # 利益

保険収支の計算自体は、
前回の養老保険から満期保険金を除き、
利息収入と保険料積立金繰入を加えています。
事業費は単純に保険料の40%としておきます。

上記以外は基本的に養老保険のときから変更していません。

term.py
   # 保険収支の計算
    for c in contracts:
        sex = c["sex"]   # 性別
        age = c["age"]   # 加入年齢
        term = c["term"] # 保険期間
        l0 =c["amount"]  # 初期保険金額

        # 残存表の作成
        lx = [l0]        # 保有保険金額
        dx = []          # 死亡保険金額
        wx = []          # 解約保険金額
        # 生命表の作成
        for t in range(c_period):
            q = qx[sex][age + t]
            w = qwx[t]
            next_d = lx[-1] * q * scale 
            next_w = lx[-1] * w
            next_l = lx[-1] - next_d - next_w
            lx.append(next_l)
            dx.append(next_d)
            wx.append(next_w)

        # 保険収支の項目
        inprem = []    # 保険料収入
        interest =[]   # 利息収入
        benefit = []   # 保険金支払い
        surrender = [] # 解約返戻金支払い
        expenses = []  # 事業費
        reserve = []   # 保険料積立金繰入
        profit = []    # 利益

        P = float(PremT(sex, age, term))
        # 保険収支の計算
        for t in range(0, c_period):
            if t < term:
                inprem.append(lx[t] * P)    # 保険料の収入
                Vt = float(ResT(sex, age, term, t)) # 期始保険料積立金
                Vt1 = float(ResT(sex, age, term, t + 1)) # 期末保険料積立金
                interest.append((lx[t + 1] * Vt1 + lx[t] * Vt) * 0.006 / (2 + 0.006)) # ハーディの公式
                benefit.append(dx[t])       # 死亡保険金の支払い
                W = float(SVT(sex, age, term, t + 1))
                surrender.append(wx[t] * W)   # 解約返戻金の支払い
                expenses.append(inprem[t] * 0.4)  # 事業費の支払い
                # 保険料積立金繰入
                if t == 0:
                    reserve.append(lx[1] * Vt1)
                else:
                    reserve.append(lx[t + 1] * Vt1 - lx[t] * Vt)
                # 保険収支の計算
                profit.append(inprem[t] + interest[t] - benefit[t] \
                    - surrender[t] - expenses[t] - reserve[t])

            # 満期後は0を入力
            else:
                inprem.append(0)
                interest.append(0)
                benefit.append(0)
                surrender.append(0)
                expenses.append(0)
                reserve.append(0)
                profit.append(0)
        
            inprem_total[scale][t] += inprem[t]       # 保険料収入の合計
            interest_total[scale][t] += interest[t]   # 利息収入の合計
            benefit_total[scale][t] += benefit[t]     # 保険金支払いの合計
            surrender_total[scale][t] += surrender[t] # 解約返戻金支払いの合計
            expenses_total[scale][t] += expenses[t]   # 事業費の合計
            reserve_total[scale][t] += reserve[t]     # 保険料積立金繰入の合計
            profit_total[scale][t] += profit[t]       # 保険収支の合計

結果を確認してみます。

term.py
for index in k:
    print("mortality_index","t", "inprem", "interest", \
        "benefit", "surrender", "expenses","reserve","profit")
    for t in range(0, c_period):
        print(index, t, int(inprem_total[index][t]), 
            int(interest_total[index][t]),
            int(benefit_total[index][t]),
            int(surrender_total[index][t]),
            int(expenses_total[index][t]),
            int(reserve_total[index][t]),
            int(profit_total[index][t]))
mortality_index t inprem interest benefit surrender expenses reserve profit
0.5 0 1345735 1195 152325 3275 538294 399674 253361
0.5 1 1318272 3489 158812 10104 527308 367295 258240
0.5 2 1291332 5590 165445 17455 516532 335170 262317
0.5 3 1264905 7503 171851 24294 505962 304243 266056
0.5 4 1238981 9228 179046 30598 495592 272579 270393
0.5 5 1213546 10759 187373 36260 485418 239321 275931
0.5 6 1188587 12074 199047 41122 475435 200270 284786
0.5 7 1164081 13146 212632 45095 465632 158169 295698
0.5 8 1140011 13959 227943 48131 456004 113598 308291
0.5 9 1116363 14508 243192 50257 446545 69979 320897
mortality_index t inprem interest benefit surrender expenses reserve profit
0.7 0 1345735 1195 213255 3275 538294 399600 192505
0.7 1 1318052 3488 222298 10102 527221 367075 194843
0.7 2 1290887 5587 231538 17448 516355 334808 196324
0.7 3 1264229 7497 240454 24279 505691 303744 197556
0.7 4 1238069 9219 250466 30572 495227 271949 199072
0.7 5 1212392 10746 262053 36221 484956 238568 201338
0.7 6 1187181 12056 278307 41067 474872 199406 205583
0.7 7 1162411 13123 297215 45022 464964 157212 211119
0.7 8 1138061 13930 318517 48039 455224 112574 217635
0.7 9 1114115 14472 339707 50144 445646 68918 224171
mortality_index t inprem interest benefit surrender expenses reserve profit
1.1 0 1345735 1194 335115 3275 538294 399453 70792
1.1 1 1317614 3486 349202 10098 527045 366635 68117
1.1 2 1289999 5582 363579 17434 515999 334084 64482
1.1 3 1262879 7486 377426 24249 505151 302747 60791
1.1 4 1236247 9201 392967 30521 494499 270692 56769
1.1 5 1210086 10720 410949 36143 484034 237068 52610
1.1 6 1184375 12021 436213 40957 473750 197686 47788
1.1 7 1159078 13076 465582 44877 463631 155308 42756
1.1 8 1134172 13872 498634 47855 453668 110537 37346
1.1 9 1109635 14402 531439 49919 443854 66812 32012

想像通り、死亡指数が上がると利益が減少していきます。
死亡指数が1を超えています(死亡率が予定死亡率を超えている)が、
利益はプラスのままです。次回はここを分解してみます。

同様の方法で解約率が変動する場合も可能ですが、
ここまで理解できていれば、みなさんでも可能と思いますので、
省略させてください。

まとめ

今回は定期保険の収支モデルを用いて、
死亡指数が変化した場合の保険収支を確認しました。

このように前提条件を変更して結果の変化を見る感応度分析は、
収益に影響する要因を把握するために実務でもよく行われます。

次回はここに死差損益の計算を加えてみたいと考えています。


📚 ナビゲーション
前の記事
複数のCFを合計する

次の記事
利源分析

📚 目次
アクチュアリーのための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?