0
1

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-01

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

ファイルの構成の整理

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

はじめに

今回は大きな新機能をしません。
代わりに、これまで作成してきたコードの構造を整理します。
前回は、

  • 保険料レートの作成
  • 保険料積立金レートの作成

を行いました。
続いて、複数商品・複数年齢の将来収支まで行いたいのですが、
すべてを1つのファイルに書き続けると、

  • コードが長くなる
  • 役割が混在する
  • 修正の影響範囲が見えにくくなる

などの問題が発生します。
そこで今回は、コードをその役割ごとにファイルで分割していきます。

今回のポイントについて

  1. 共通部分
    まず、商品共通の部分を切り出します。

    • 死亡率
    • 生命表
    • 計算基数
    • 収入現価・支出現価
    • 端数処理のroundhu関数
    • 年満期を変換するparse_term関数

    これらは養老でも定期でも終身保険でも共通ですのです。
    これを1つのファイルにします。
    ここではcore.pyとしておきます。
     

  2. 次に商品固有のロジックは商品ごとに分けます。

    • endowment.py
    • term.py
    • whole.py

    それぞれのファイルでは、

    • 保険料の計算
    • 保険料積立金の計算
    • 解約返戻金の計算
    • 将来収支の計算前提
    • 将来収支の計算

    を扱います。
    将来収支の計算前提と計算のロジックは、
    いずれ別のファイルに切り離すかもしれませんが、
    今回は分かりやすさを重視して、
    商品ごとのファイルに入れておきます。

ファイルの構成について

  • core.py
  • endowment.py
  • term.py
  • whole.py

は同一の作業フォルダにおきます。
仮にフォルダ名をworkだとすると、

work/
├── core.py
├── endowment.py
├── term.py
└── whole.py

core.pyはコードを移行するだけなので、
特に注意する点はありません。

商品別のファイルの内容は、endowment.pyを例にあげます。
最初にcore.pyの内容を読み込むためのコードを置きます。

endowment.py
from core import *

あとは養老保険の

  • 営業保険料
  • 純保険料
  • 保険料積立金
  • 解約返戻金

を計算する関数を置きます。

emdowment.py
# 養老保険
# 営業保険料の計算
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):
    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)

続いて、将来収支の前提条件と、キャッシュフローの計算を置きます。
前回までと少しだけ異なり、性別を入れるようにしています。

endowment.py
# アサンプションの設定 ###################
c_period = 10  # 計算する期間
c_term = 10    # 保険期間
c_sex = "M"    # 性別
c_age = 40     # 加入年齢
k = 0.7        # 死亡指数
qwx = [0.02] * len(qx[c_sex])    # 解約率
amount = 1000000    # 保険金額

# 残存表の作成 #################
# 初期生存者数
l0 = 100000
lx = [l0]
dx = []
wx = []
# 生命表の作成
for t in range(c_period):
    q = qx[c_sex][c_age + t]
    w = qwx[t]
    next_d = lx[-1] * q * k 
    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)

# 保険金額の推移
lx_amt = [l * amount for l in lx]
dx_amt = [d * amount for d in dx]
wx_amt = [w * amount for w in wx]

# キャッシュフローの項目
inprem = []    # 保険料収入
benefit = []   # 保険金支払い
surrender = [] # 解約返戻金支払い
expenses = []  # 事業費
netcash = []   # キャッシュフロー結果

P = float(PremE(c_sex, c_age, c_term)) # 保険料をfloat型へ
# キャッシュフローの計算
for t in range(0,c_period):
    inprem.append(lx_amt[t] * P)     # 保険料の収入
    if t == c_term - 1:              # 死亡保険金+満期返戻金の支払い
        benefit.append((lx_amt[t] - wx_amt[t]))
    else:                            # 死亡保険金の支払い
        benefit.append(dx_amt[t])
    W = float(SVE(c_sex, c_age, c_term, t + 1)) 
    surrender.append(wx_amt[t] * W)   # 解約返戻金の支払い
    expenses.append(inprem[t] * 0.1)  # 事業費の支払い
    # キャッシュフローの計算
    netcash.append(inprem[t] - benefit[t] - surrender[t] - expenses[t])

ここまでの結果を確認してみます。

print("t", "inprem", "benefit", "surrender", "expenses","netcash")
for t in range(0, c_period):
    print(t, int(inprem[t]/1000000), int(benefit[t]/1000000), \
          int(surrender[t]/1000000), int(expenses[t]/1000000), \
          int(netcash[t]/1000000))

結果は次のようになります。

0 10755 82 148 1075 9448
1 10531 88 341 1053 9047
2 10311 93 527 1031 8658
3 10094 99 706 1009 8279
4 9882 104 879 988 7909
5 9673 111 1045 967 7548
6 9467 119 1205 946 7195
7 9265 129 1359 926 6850
8 9066 139 1507 906 6513
9 8870 80823 1649 887 -74489

保険料積立金も加えた収支は、
次のようにします。
保険料積立金を性別のある計算式に置き換えています。

endowment.py
# 収支(期末保険料積立金を加える)
reserve =[]  # 保険料積立金
inout =[]    # 収支の結果
for t in range(0,c_period):
    # 期末Vの計算
    if t == 0:
        # 初年度はV額そのまま
        V = float(ResE(c_sex, c_age, c_term, 1))
        reserve.append(lx_amt[1] * V)
    elif t == c_term - 1:
        # 最終年度は全額取り崩し
        V = float(ResE(c_sex, c_age, c_term, t))
        reserve.append( - lx_amt[t] * V)
    else:
        # その他はV繰入額を計算
        Vt = float(ResE(c_sex, c_age, c_term, t))
        Vt1 = float(ResE(c_sex, c_age, c_term, t + 1))
        reserve.append(lx_amt[t+1] * Vt1 - lx_amt[t] *Vt)
    
    # 収支の計算
    inout.append(netcash[t] - reserve[t])

計算結果を確認すると、次のようになります。

for t in range(0,c_period):
    print(t, int(inprem[t]/1000000), int(benefit[t]/1000000), \
        int(surrender[t]/1000000), int(expenses[t]/1000000), \
        int(reserve[t]/1000000), int(inout[t]/1000000))
0 10755 82 148 1075 9493 -45
1 10531 88 341 1053 9155 -107
2 10311 93 527 1031 8825 -167
3 10094 99 706 1009 8504 -225
4 9882 104 879 988 8192 -282
5 9673 111 1045 967 7886 -337
6 9467 119 1205 946 7586 -390
7 9265 129 1359 926 7293 -443
8 9066 139 1507 906 7007 -494
9 8870 80823 1649 887 -73945 -544

まとめ

今回は、

  • ファイル構成の整理
  • 共通部分と商品ロジックの分離
  • 養老保険を例にした将来収支の確認

を行いました。

数式そのものはこれまでの延長ですが、
コードを整理したことで、
商品を追加するなどの拡張をしやすくすることができます。

今後もpythonの勉強を進めることによって、
拡張できるような内容があれば追加していきます。


📚 ナビゲーション
前の記事
保険料積立金レート表の作成

次の記事
複数のCFを合計する

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

0
1
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
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?