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入門(破産確率とVaR)

0
Last updated at Posted at 2026-09-05

アクチュアリーのためのPython入門(アクチュアリー数学編第6回)

破産確率とVaRのシミュレーション

📚 アクチュアリーのためのPython入門
この記事はアクチュアリー数学編の一部です。
目次はこちら
逆引きガイドはこちら

はじめに

前回は複合分布をシミュレーションを行い、
最終的に破産確率まで計算することができました。

ただ、前回の破産確率の計算は、
過去問の解答通りの確率分布をシミュレーションしただけで、
本当にこの公式どおりになるのかPythonで確認するには至っていません。

今回は、もとの条件に沿った形の破産確率を計算して、
公式と近い値が求められるということを確認しましょう。

過去問は前回と同じく2022年の損保数理の問題2(3)です。

破産確率

まずは、前回と同じ前提条件で、問題ともに同じですが、
問題ではクレーム件数のパラメータは$\lambda$となっていますので、
ここでは平均lam=1としておきます。
年間に1回のクレーム回数の意味です。

# 2022年2(3)
import numpy as np

np.random.seed(42)

u0 = 75
lam = 1
mu = 10
theta = 0.25

# 収入保険料
c = lam * mu * (1 + theta)

trial = 100000  # 試行回数
bankruptcy = 0  # 破産回数初期値
max_time = 200  # 計算する年数

計算する年数ですが、理論値の計算では期間を無限に近づけて、
収束値を取るのですが、シミュレーションではできませんので、
200年まで計算して破産するかを確認することにします。
試行回数は100,000回です。

次に破産確率の部分です。
ut = t0 = 75からはじめて、
クレーム件数が平均1のポアソン分布に従うので、
そのクレーム間隔は平均1の指数分布になります。
ですので、指数分布の乱数dtを生成して、
その間の収入保険料をc * dtとします。

そして、クレームが発生するので、
今度はクレーム額の平均10の指数分布の乱数を生成し、
収入保険料を加えた後のutから差し引きます。

whilet < max_timeの間は繰り返すの意味です。


for i in range(trial):
    ut = u0
    t = 0
    while t < max_time:
        # クレーム間隔
        dt = np.random.exponential(scale = 1/lam)
        t += dt 
        # 収入保険料
        ut += c * dt
        # クレーム額
        claim_x = np.random.exponential(scale = 10)
        # クレーム後
        ut -= claim_x

最後にutがマイナスなら、
破産回数を+1して、breakwhileのループから抜けます。

        if ut < 0:
            bankruptcy += 1
            break

この計算で、結果がどうなるか確認してみます。

print(bankruptcy / trial)

0.17888

と、理論値と少し離れていますが、近い数値となります。
なお、1000年にすると、0.17853とほぼ理論値が出てきますが、
最大で1000年×100000回の計算をしていることになるので、
さすがのPythonでも計算終了までかなり時間がかかります。

以上で、公式で破産確率を導き出せていることが分かります。

対数正規分布

上記は理論値が公式を使って計算できますが、
今度は、理論値が簡単には計算できない
ポアソン分布+対数正規分布をシミュレーションしてみることにします。

この複合分布は簡単な関数では表せないので、
破産確率をシミュレーションで計算した方が早いです。

今回は、その複合分布のVaR95%、TVaR95%を計算してみます。

# ポアソン分布と対数正規分布の複合分布
import numpy as np
import pandas as pd

np.random.seed(42)

claim_n = np.random.poisson(lam=4, size=100000)

result = []
for n in claim_n:
    claim_sum = 0
    claim_x = np.random.lognormal(mean=0, sigma=1, size=n)
    claim_sum = sum(claim_x)
    result.append(claim_sum)

df = pd.DataFrame(result, columns=["claim_sum"])
# VaR95%
var95 = df["claim_sum"].quantile(0.95)
print(var95)
# TVaR95%
tvar95 = df.loc[df["claim_sum"] > var95, "claim_sum"].mean()
print(tvar95)

VaRとTVaRは次のとおりです。

16.750791157202485
22.276998163980704

ヒストグラムを確認すると次のようになります。

compound_distribution3.png

まとめ

今回は、破産確率を基本に戻って計算してみました。
また、複雑な複合分布の例として、
ポアソン分布+対数正規分布のVaR、TVaRを計算してみました。

対数正規分布の複合分布のように簡単な関数で表せない場合は、
実際にシミュレーションを行って、VaRやTVaRを計算することがあります。

Pythonはいくつもの関数の乱数が生成できること、
繰り返し計算に強いことから、シミュレーションではよく使われます。


📚 ナビゲーション
前の記事
複合分布

次の記事
閾値超過モデル

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