乙Py先生のプログラミング教室
初学者のためのプログラミング学習サイト

シミュレーション

南海トラフ地震はいつ起きるのか
過去データから予測してみる事としました。

解説動画はこちら





南海トラフ地震とは

駿河湾から日向灘沖にかけてのプレート境界を震源域として
概ね100~150年間隔で繰り返し発生してきた大規模地震

静岡県から宮崎県にかけての一部では震度7となる可能性があります。

過去の発生年

発生年 名称
1946年 昭和南海地震
1944年 昭和東南海地震
1854年 安政南海地震
1707年 宝永地震
1605年 慶長地震
1498年 明応地震
1361年 正平南海地震


地震の発生確率の計算方法


最近の調査ではBPT分布というものを
用いた予測が基本になっています。

BPT分布
(Brownian Passage Time:ブラウン通過時間)
地震の発生間隔をモデル化する確率分布

確率的に「平均的な間隔」の周辺で起こるが
バラつきがあるというモデル


ポアソン分布は発生確率が常に一定(ランダム)とする一方
BPT分布は時間経過による「成熟度」を考慮したものです。



BPT分布の基本式

BPT分布の確率密度関数  𝑓(𝑡)  は、以下の式で表されます。
スクリーンショット 2026-03-14 17.25.49



条件付き確率の考え方

「前回の地震から  𝑡  年経過した時点で
今後  Δ𝑡  年以内に地震が発生する確率」

𝑃(𝑡,Δ𝑡)  は、以下の式で計算します。

スクリーンショット 2026-03-14 17.26.44


コード上では下記が確率計算部分になります。
prob = (f_future - f_t) / (1 - f_t)

分子:(f_future - f_t)
「現在からXX年の期間内に地震が発生する」という確率

分母:(1 - f_t)
「現在で、まだ地震が起きていない」という確率

BPTモデルでは時間が経つほど  𝐹(𝑡)  が大きくなるため
分母はどんどん小さくなっていき、確率が高まります。


Pythonで地震確率をシミュレーションする

あらかじめことわりますが
政府予測とは異なります!!!!


予測条件

平均再来間隔 (南海トラフの直近データ 1361 ~ 1946)
97.5

ばらつき係数 (地震調査委員会採用値)
0.24

前回の発生年 (昭和南海地震)
1946

今後30年間の地震発生確率を求めるコードは以下です。
import numpy as np
from scipy.stats import norm

def bpt_cdf_30(t, mu, alpha, delta_t=30):
    """
    BPT分布に基づき、今後 delta_t 年以内の地震発生確率を計算する
    
    Parameters:
    t: 前回からの経過年数
    mu: 平均再来間隔
    alpha: ばらつき係数
    delta_t: 評価期間(デフォルトは30年)
    """
    if t <= 0:
        return 0.0
    
    # 現在までの間に、既に地震が起きているはずだった累積確率
    inv_alpha_sq = 2 / (alpha**2)
    term1_t = norm.cdf((t / mu - 1) / (alpha * np.sqrt(t / mu)))
    term2_t = np.exp(inv_alpha_sq) * norm.cdf(-(t / mu + 1) / (alpha * np.sqrt(t / mu)))
    f_t = term1_t + term2_t
    
    # delta_t 年後までの間に、地震が起きる累積確率
    t_future = t + delta_t
    term1_f = norm.cdf((t_future / mu - 1) / (alpha * np.sqrt(t_future / mu)))
    term2_f = np.exp(inv_alpha_sq) * norm.cdf(-(t_future / mu + 1) / (alpha * np.sqrt(t_future / mu)))
    f_future = term1_f + term2_f
    
    if f_t >= 1.0:
        return 1.0
        
    prob = (f_future - f_t) / (1 - f_t)
    return max(0.0, min(prob, 1.0))

mu = 97.5       # 平均再来間隔 (南海トラフの直近データ 1361 ~ 1946)
alpha = 0.24    # ばらつき係数 (地震調査委員会採用値)
last_event = 1946  # 前回の発生年 (昭和南海地震)
target_year = 2026
t = target_year - last_event

# 30年分を予測
for delta_t in range(1, 31):
  prob = bpt_cdf_30(t, mu, alpha, delta_t)
  print(f"今後 {delta_t} 年以内の発生確率: {prob:.2%}")

今後30年間の発生確率は
ぜひ動画を見てみてください。




まとめ

地震の発生確率は確率分布をもとに
予測が行われています。

政府予測では
今後、30年の間に 60%~90%程度以上の確率で
南海トラフ地震来るという予測です

絶対は無いけど、明日来るかもしれない
いつ来ても良いように備えておきましょう!!!

それでは
 

今回は老後の資産をどうやって取り崩すか
資産取り崩しのシミュレーションです


解説動画はこちら




老後資産取り崩し


老後の資産を年利 X % で運用しつつ
毎月 X 万円取り崩していく際の
資産推移をシミュレーションします。


資産金額、年利、リスク確率から
破産確率がどれくらいになるのか
これを導き出します。



モンテカルロシミュレーション


資産取り崩しの際のシミュレーションに使うのが
モンテカルロシミュレーションです。

これはサイコロをたくさん振って
結果を求めるようなイメージです。

おおよその内容としては


資産がスタート(例:5,000万円)
毎月、資産が「投資リターン」で少し増えたり減ったりする

例:平均 4%/年、リスク(ブレ幅) 1%/年
これを「正規分布」というサイコロで乱数を作って計算
その後「毎月の生活費を取り崩す」。(例:20万円ずつ減らす)
これを1シナリオとして 最後まで計算

これを 1,000回くらい繰り返す
サイコロを振って、資産の未来を1000通り描くイメージです。

コードでは1000回の結果を可視化していきます。



ライブラリのインストール



Google Colab で使用するには
日本語のライブラリが必要なのでこれを入れておいてください

# 可視化ライブラリのインストール
pip install japanize-matplotlib


モンテカルロシミュレーションのコード

ipywidgetsとmatplotlibで可視化するコードです。

コピペして上から実行していくと
スライダーとボタンが出るはずです。
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import japanize_matplotlib
import ipywidgets as widgets
from IPython.display import display, clear_output

# シミュレーション関数
def simulate_withdrawal(start_age, years, initial_assets, monthly_withdraw, annual_return, annual_risk, n_sim=1000):
    months = years * 12
    results = []
    for _ in range(n_sim):
        assets = initial_assets
        monthly_returns = np.random.normal(
            loc=(annual_return/100)/12,
            scale=(annual_risk/100)/np.sqrt(12),
            size=months
        )
        trajectory = []
        for r in monthly_returns:
            assets *= (1 + r)           
            assets -= monthly_withdraw  
            assets = max(0, assets)     
            trajectory.append(assets)
        results.append(trajectory)
    return pd.DataFrame(results).T  


# 実行関数
def run_simulation(b):
    clear_output(wait=True)
    display(ui)
    
    # 入力値取得
    start_age = age_slider.value
    years = years_slider.value
    initial_assets = assets_slider.value
    monthly_withdraw = withdraw_slider.value
    annual_return = return_slider.value
    annual_risk = risk_slider.value

    # シミュレーション実行
    df = simulate_withdrawal(start_age, years, initial_assets, monthly_withdraw, annual_return, annual_risk)
    mean_path = df.mean(axis=1)
    median_path = df.median(axis=1)
    best_path = df.max(axis=1)
    worst_path = df.min(axis=1)
    months = np.arange(1, years*12 + 1)

    # 最終結果テキスト
    final_assets = df.iloc[-1]
    print(
        f"最終結果:"
        f"  破産確率: {100 * (final_assets==0).mean():.1f}%"
        f"  平均資産額: {final_assets.mean():,.0f} 万円"
        f"  中央資産額: {final_assets.median():,.0f} 万円"
        f"  最良ケース: {final_assets.max():,.0f} 万円"
        f"  最悪ケース: {final_assets.min():,.0f} 万円"
    )

    # グラフ描画 (matplotlib)
    plt.figure(figsize=(10,6))
    #plt.plot(months, best_path, label="最良ケース", color="green")
    plt.plot(months, worst_path, label="最悪ケース", color="red")
    plt.plot(months, mean_path, label="平均ケース", color="blue")
    plt.plot(months, median_path, label="中央値ケース", color="orange")
    plt.title(f"資産取り崩しシミュレーション(開始年齢: {start_age}歳, 期間: {years}年)")
    plt.xlabel("経過月数")
    plt.ylabel("資産額 (万円)")
    plt.legend()
    plt.grid(True)
    plt.show()


# スライダーUI
age_slider = widgets.IntSlider(value=65, min=50, max=100, step=1, description="開始年齢")
years_slider = widgets.IntSlider(value=30, min=10, max=50, step=1, description="年数")
assets_slider = widgets.IntSlider(value=5000, min=1000, max=20000, step=100, description="資産(万円)")
withdraw_slider = widgets.IntSlider(value=20, min=10, max=100, step=1, description="月取崩(万円)")
return_slider = widgets.IntSlider(value=4, min=1, max=20, step=1, description="利回り%")
risk_slider = widgets.IntSlider(value=1, min=1, max=30, step=1, description="リスク%")

# 実行ボタン
run_button = widgets.Button(description="シミュレーション実行", button_style="success")
run_button.on_click(run_simulation)

# UIまとめて表示
ui = widgets.VBox([age_slider, years_slider, assets_slider,withdraw_slider, return_slider, risk_slider,run_button])
display(ui)
スクリーンショット 2025-08-30 17.39.21

スライダーを調整して
シミュレーションボタンクリックで
結果が出ます。

スクリーンショット 2025-08-30 17.12.13


老後の資産と毎月の取り崩しの金額
利回りとリスクを変更すると

どれくらいの確率で資産が破産するか
求めることができます。

破産確率が0%になるように
取り崩しをしていくと資産が残る形になります。

毎月どれくらい取り崩せるのか
おおよその金額を算出できるので
老後資金が足りるかどうか
資産したい場合は、ぜひ使ってみてください。

老後2000万円問題とか
言われていますが
2000万円では全然足りないですねーーーーーー


資産が底を尽きないように
どんどん増やしていけるように
したいと思っています。

今後も投資系のシミュレーションを
どんどんやっていきますので
リクエストがあれば、どんどん
動画のコメントに書き込んでみてください

それでは。

夏休みの時期ですねー
夏休みの課題は決まりましたか?

今回は2重振り子のシミュレーションです


解説動画はこちら



2重振り子のシミュレーション


スクリーンショット 2025-07-26 16.28.53
こんな感じの2重振り子
よく有りますよね

支点があって
2個の振り子がついてて
ブルンブルンしちゃうやつです。

今回はこれをPythonで計算して
動画にするやつです。



ルンゲ・クッタ法

2重振り子をシミュレーションするには
2点の位置

2つのx,y軸の座標を求める必要があります。

この計算を行うために使用するのが
ルンゲ・クッタ法というものです。


4次のルンゲ・クッタ法(Runge-Kutta 4次法)

微分方程式の数値解法の一つで
特に4次までを考慮したテイラー展開を用いることで
より精度の高い近似解を求める方法だそうです。


この方法では、変化率の推定値を4通り計算し
それらを加重平均することで
次のステップの値を計算することになります。

計算手順は以下のようになります。

k1 → 現在の変化率
k2 → 半歩進んだ時点の変化率(k1からの推定)
k3 → さらに半歩進んだ時点の変化率(k2からの推定)
k4 → 1ステップ進んだ時点の変化率

これらを 1:2:2:1 の比率で足し合わせて
現在の状態を更新します。

𝑑𝑡 / 6 * (𝑘1 + 2*𝑘2 + 2*𝑘3 + 𝑘4) 

4次のルンゲ・クッタ法は、傾きを4回サンプリングし
テイラー展開の4次項まで考慮した近似になるため、
長時間シミュレーションでも精度が高いみたいです。

早速これをコードに落とし込んでいきましょう。


シミュレーションコード

Google colabで実行できるコードになっているので
コピペして実行することができると思います。

まずはライブラリのインポートです。
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
import warnings
warnings.filterwarnings('ignore')


次にパラメータ設定と
数値計算部分のコードです。
# パラメータ設定
g = 9.81   # 重力加速度
L1, L2 = 1.0, 1.0  # 振り子の長さ
m1, m2 = 1.0, 1.0  # 振り子の質量

# 初期条件(角度と角速度)
theta1 = np.pi/2
theta2 = np.pi/2 + 0.1
omega1 = 0.0
omega2 = 0.0
state = np.array([theta1, omega1, theta2, omega2])

# 時間設定
dt = 0.05
t_max = 25
steps = int(t_max/dt)

# 保存用リスト
x1_list, y1_list = [], []
x2_list, y2_list = [], []

# 二重振り子の運動方程式
def derivatives(state):
    theta1, omega1, theta2, omega2 = state
    delta = theta2 - theta1
    denom1 = (m1 + m2) * L1 - m2 * L1 * np.cos(delta)**2
    denom2 = (L2/L1) * denom1
    a1 = (m2*L1*omega1**2*np.sin(delta)*np.cos(delta) +
          m2*g*np.sin(theta2)*np.cos(delta) +
          m2*L2*omega2**2*np.sin(delta) -
          (m1+m2)*g*np.sin(theta1)) / denom1
    a2 = (-m2*L2*omega2**2*np.sin(delta)*np.cos(delta) +
          (m1+m2)*(g*np.sin(theta1)*np.cos(delta) -
                   L1*omega1**2*np.sin(delta) -
                   g*np.sin(theta2))) / denom2
    return np.array([omega1, a1, omega2, a2])

# Runge-Kutta 4次法で数値計算
for _ in range(steps):
    k1 = derivatives(state)
    k2 = derivatives(state + dt*k1/2)
    k3 = derivatives(state + dt*k2/2)
    k4 = derivatives(state + dt*k3)
    state += (dt/6)*(k1 + 2*k2 + 2*k3 + k4)
    theta1, omega1, theta2, omega2 = state

    # 座標変換
    x1 = L1 * np.sin(theta1)
    y1 = -L1 * np.cos(theta1)
    x2 = x1 + L2 * np.sin(theta2)
    y2 = y1 - L2 * np.cos(theta2)
    x1_list.append(x1)
    y1_list.append(y1)
    x2_list.append(x2)
    y2_list.append(y2)
for文のところがルンゲクッタ法の部分です。
ここでk1 - k4までを計算し
次のステップに状態を更新しています。

最後に描画用に 2点のx,y 軸としてデータ化します。

動画の生成部分です。
fig, ax = plt.subplots(figsize=(6, 6))
ax.set_xlim(-2.2, 2.2)
ax.set_ylim(-2.2, 2.2)
ax.set_aspect('equal')
ax.axis("off")
line, = ax.plot([], [], 'o-', lw=2)       # 振り子本体
trace, = ax.plot([], [], 'r-', alpha=0.5) # 軌跡

# 軌跡用リスト
trace_x, trace_y = [], []
def update(i):
    # 点の位置(始点 → 中点 → 先端)
    thisx = [0, x1_list[i], x2_list[i]]
    thisy = [0, y1_list[i], y2_list[i]]
    line.set_data(thisx, thisy)
    trace_x.append(x2_list[i])
    trace_y.append(y2_list[i])
    trace.set_data(trace_x, trace_y)
    return line, trace

ani = FuncAnimation(fig, update, frames=len(x1_list), interval=40, blit=True)
ani.save("double_pendulum.mp4", fps=30, dpi=150)
plt.close(fig)
matplotlibで描画を計算して
最終的にはmp4にします。


ファイル置き場にできた動画を見てみると
from IPython.display import Video
Video("double_pendulum.mp4", embed=True)
スクリーンショット 2025-07-26 16.50.32
こんな感じで軌跡が赤く残るような
動画が作成できます。

なかなか面白いので
長い時間で作ってみるのも
面白いかもしれません。

頑張れば振り子の数を増やしたり
色々なエフェクトを加えたりして
より面白くすることもできるかもしれません。

夏休みの課題が無くて困っているご家庭は
ぜひ面白い改造に挑戦してみてください。

今日はここまでです
それでは。

今回はドルコスト平均法による
積立投資のシミュレーションです

解説動画はこちら



ドルコスト平均法とは

価格が変動する金融商品に対して
一定金額を定期的に購入していく投資方法のことです

今回は毎月10万円積み立てるとして
それがどうなるかをシミュレーションしていきます。



eMaxisSlim米国株式S&P500

リンク先

S&P500指数(配当込み、円換算ベース)に
連動する運用成果を目指す投資信託
2018年7月3日に設定された商品です。

今回はこのデータを用いて
シミュレーションをしていきます。



eMAXIS Slim 米国株式 S&P500の価格推移

価格のデータを定義して
価格推移をだしてみます。

import numpy as np
import pandas as pd
import plotly.express as px
import seaborn as sns
import matplotlib.pyplot as plt

# データ定義
data = {
    2018 : [0,0,0,0,0,0,10038,10458,10709,11051,10188,10468],
    2019 : [8809,9854,10408,10565,10900,10031,10725,10978,10491,10890,11106,11680],
    2020 : [11873,11892,10825,9474,10655,11205,11465,11886,12707,12182,11767,12989],
    2021 : [13339,13407,14010,15217,15754,15924,16540,16712,17301,16677,18267,18005],
    2022 : [19291,18130,17601,19347,18798,18658,18052,19265,19394,18280,20283,19728],
    2023 : [17690,18714,19167,19388,20234,20666,22867,23260,23411,22911,22677,24155],
    2024 : [24154,25486,27473,28563,28573,29833,31693,29763,29789,29974,31336,32768],
    2025 : [33928,34065,32500,30512,28931,30867]
}

records = []
for year, prices in data.items():
    for month_idx, price in enumerate(prices):
        month = month_idx + 1
        if price == 0:
            continue
        date_str = f"{year}-{month:02d}-01"
        date = pd.to_datetime(date_str)
        records.append({"Date": date, "Price": price})

df = pd.DataFrame(records)
df = df.sort_values("Date")

# Plotlyでプロット
fig = px.line(df, x="Date", y="Price", title="Emaxis Slim value")
fig.show()
スクリーンショット 2025-06-21 16.43.01


良い感じに右肩上がりのようですが
この商品を毎月10万円ずつ積み立てたらどうなっていたでしょうか



2018年から2025年まで毎月積み立てた際のシミュレーション

毎月10万円
購入できる購入数量を算出して
2025年の最後の価格で
どれだけのリターンになっているかを算出します。
monthly_investment = 100000  # 毎月XX万円

# シミュレーション開始
total_units = 0  # 累計購入数量
total_invested = 0  # 累計投資金額
for year in sorted(data.keys()):
    for month_idx, price in enumerate(data[year], 1):
        if price == 0:
            continue
        units_bought = monthly_investment / price
        total_units += units_bought
        total_invested += monthly_investment

latest_year = max(data.keys())
latest_price = data[latest_year][-1]
current_value = total_units * latest_price
profit = current_value - total_invested
roi = (current_value / total_invested - 1) * 100

# 結果表示
print(f"総投資額: {total_invested:,.0f}円")
print(f"最終評価額: {current_value:,.0f}円")
print(f"損益: {profit:,.0f}円")
print(f"累計購入数量: {total_units:.4f}口")
print(f"リターン: {roi:.2f}%")
total_return = (100 + roi) / 100
years = 8
cagr = (total_return ** (1 / years)) - 1
print(f"年平均リターン: {cagr * 100:.2f}%")

総投資額: 8,400,000円
最終評価額: 16,458,895円
損益: 8,058,895円
累計購入数量: 533.2198口
リターン: 95.94%
年平均リターン: 8.77%


この価格推移のデータ上では
年平均8%超

7年で二倍近くの運用成績になっています。



ターンヒートマップ


今度は開始年から終了年までの
リターンヒートマップを出してみましょう。


開始と終了年を設定して
開始終了までのリターンを算出します。

years = list(data.keys())
monthly_invest = 100000
results = pd.DataFrame(index=years[:-1], columns=years[1:])
for start in years[:-1]:
    for end in years[years.index(start)+1:]:
        total_invest = 0
        total_units = 0
        for y in range(start, end+1):
            for price in data[y]:
                if price == 0:
                    continue
                units = monthly_invest / price
                total_units += units
                total_invest += monthly_invest
        # 最後の年の最後の価格で評価額計算
        final_price = [p for p in data[end] if p != 0][-1]
        final_value = total_units * final_price
        return_pct = (final_value - total_invest) / total_invest * 100
        results.loc[start, end] = return_pct

# ヒートマップ描画
results = results.astype(float)
plt.figure(figsize=(10, 7))
sns.heatmap(results, annot=True, fmt=".2f", cmap="coolwarm", center=0)
plt.title("dollar cost averaging method return heatmap (%)")
plt.xlabel("end year")
plt.ylabel("start year")
plt.show()
download

年単位だとどの年で買って売っても
プラスにはなっているようです。



まとめ

eMAXIS Slim 米国株式 S&P500のドルコスト平均法による積み立ては
年単位での運用であればマイナスは無いようです。

ただし、月単位だと乱高下があり
損する場合も有ったので、やはり長期積立で
見守るのが良いのではないかと思われます。

投資は自己判断で行うことが大切です。
その金融商品の良し悪しを判断し
投資するかどうかは人に言われるでなく
自分自身の判断で行うのが重要です。

投資判断を行うための材料作りとして
プログラムを用いたシミュレーションは
かなり役に立ちます。

データさえあればシミュレーションでき
結果の良し悪しから
投資判断の材料に使えるようになると思うので
プログラミングが出来るようになっていると
すぐに試すことができるのでお勧めです。

投資 x プログラミング
というテーマを今後も取り扱っていくので
両方できるようになりたい方は
要チェックしてみてください。

それでは


今回は昔懐かしい
カイジの沼のシミュレーションです。

解説動画はこちら




カイジの沼のシミュレーション

沼とは

漫画『賭博破戒録カイジ』に登場する架空のパチンコ台

帝愛グループの運営するカジノに設置されている
パチンコの中でも特別な台で玉が1発あたり4000円
挑戦は最低300万円からという設定

その一方で、今までの挑戦者が消費した玉が
全てプールされる仕組みになっており
運良く大当たりを引ければ総取りで莫大な額の金を手にできるとか


仕掛け・役物

ここからは確率を計算するための
沼のギミックについてです。

1.釘の森

釘が密集した配置になっている「釘の森」
通常時の設定Cは1/100程度

2.スル

開閉する羽根のある電動役物「スルー」
釘の森を突破した玉を更にふるい落とす
確率は不明なので
ここでは通過率を1/5としておきます

3.3段クルーン

沼の本丸である「三段クルーン」
円形の皿に穴が3つ/4つ/5つ空いていて
当たりの穴に入ると次の段に進める

数学的にはクルーンに入ってさえしまえば
約1/60の確立で当たる


というような設定にはなっていますが
漫画の設定上ではこの台にはイカサマがあり
この確率では入らないようにはなっています。

しかし、今回は考慮しないで
イカサマなしだとどうなるかを見ていきたいと思います。



沼のシミュレーションコード


簡易な確率計算で大当たりしたかどうかだけ返す関数を用いて
シミュレーションしていきます。
最大回数は10万回(4億円相当)とします。

import numpy as np
import random
import pandas as pd
import matplotlib.pyplot as plt

# 確率でヒットするかどうかを判定する
def is_hit(n: int) -> bool:
    return random.randint(1, n) == 1

def numa_charenge():
  # 釘の森の通過
  mori = is_hit(100)
  if not mori:
    return False

  # スルーの通過
  throw = is_hit(5)
  if not throw:
    return False

  # クルーン1段目通過
  first = is_hit(3)
  if not first:
    return False

  # クルーン2段目通過
  second = is_hit(4)
  if not second:
    return False

  # クルーン3段目通過
  third = is_hit(5)
  if not third:
    return False
  else:
    return True


# 1000回施行して測ってみる
ball_price = 4000 # パチンコ玉の価格

def numa_result(num):
  all_result = []
  for a in range(1000):
    cumulative = 0
    for i in range(num):
      cumulative += ball_price
      is_atari = numa_charenge()
      if is_atari:
        all_result.append([i+1, cumulative,1])
        break
      if i == num-1:
        all_result.append([i+1, cumulative,0])
  return all_result

num = 100000 # 1回あたりの最大施行回数
all_result = numa_result(num)

df = pd.DataFrame(all_result,columns=["balls","cumulative","hit"])
df.head()
balls cumulative hit
0 30959 123836000 1
1 29604 118416000 1
...

plt.figure(figsize=(12, 6))
df["cumulative"].hist(bins=20)
plt.show()
download

おおよそこのような結果になります。


どれくらい注ぎ込めば当たるのか?


シミュレーション結果は使った額の累計を入れているので
それを用いれば、その金額以下の回数と
全体の回数から大体の確率を求められます。
times_300 = len(df[df["cumulative"]<3000000])
print(f"300万円で大当たりになる可能性 : {times_300/1000*100} % ")

なおこのシミュレーションの結果は
幾何分布に近似するため以下のようなコードで
回数あたりの大当たり確率の理論値が出せます。
# 幾何分布上の理論値
for i in range(10):
  p = 1 / 30000
  n = (i+1) * 10000
  prob = 1 - (1 - p)**n
  print(f"{i+1:02}万回で当たる確率 : {prob:.6f}")
01万回で当たる確率 : 0.283473
02万回で当たる確率 : 0.486589
03万回で当たる確率 : 0.632127
04万回で当たる確率 : 0.736409
05万回で当たる確率 : 0.811130
06万回で当たる確率 : 0.864669
07万回で当たる確率 : 0.903032
08万回で当たる確率 : 0.930520
09万回で当たる確率 : 0.950215
10万回で当たる確率 : 0.964328


シミュレーション結果もこの理論値に
近似してますね。


まとめ


沼の設定が玉が1発あたり4000円
3万発に1回の確率(100x5x3x4x5)
で当たるのだとしたら3億注ぎ込めば
9割くらいは大当たりするのではないか?

あくまでイカサマが無い事が前提ですが.....
イカサマさえなければ無尽蔵にお金を注ぎ込めるなら
勝てる気がしなくもない今日この頃でした。

それでは

このページのトップヘ