【初心者向け】モンテカルロシミュレーションで株式投資のリスクを測る

基礎知識・戦略

※本記事のコードや情報は執筆時点の仕様に基づいています。投資は自己責任であり、必ずデモ環境や少額資金でテストした上で運用してください。

モンテカルロシミュレーションとは何か

モンテカルロシミュレーションとは、乱数を使って大量の「もしもシナリオ」を計算し、その結果の分布から確率的な予測を行う手法です。カジノの街モナコのモンテカルロに由来しています。

株式投資への応用では「将来の株価がどのような範囲に収まるか」を確率で表現します。

概念 説明
シミュレーション回数 多いほど精度が上がる(1000〜10000回が一般的)
ドリフト 平均的な株価上昇傾向(過去リターンの平均)
ランダム変動 正規分布に従う乱数で日々のブレを再現
VaR(バリューアットリスク) 「X%の確率でこれ以上の損失は起きない」という損失上限

VaR(バリューアットリスク)とは

VaRは「95%VaR = -5%」なら「95%の確率で損失は5%以内」という意味です。逆に言えば「5%の確率で5%以上の損失が起きる」可能性があることも示しています。機関投資家のリスク管理でよく使われます。

PythonでモンテカルロシミュレーションとVaRを計算する

import yfinance as yf
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib

matplotlib.rcParams['font.family'] = 'Meiryo'
np.random.seed(42)  # 再現性のために乱数シードを固定

# ==============================
# 設定エリア
# ==============================
SYMBOL     = "7203.T"    # シミュレーション対象銘柄
PERIOD     = "2y"        # 過去データ取得期間
SIM_DAYS   = 252         # シミュレーション日数(1年分)
NUM_SIMS   = 1000        # シミュレーション回数
CONF_LEVEL = 0.95        # VaRの信頼水準(95%)

# ==============================
# 過去データからパラメータ推定
# ==============================
df = yf.Ticker(SYMBOL).history(period=PERIOD)
log_ret = np.log(df["Close"] / df["Close"].shift(1)).dropna()

mu    = log_ret.mean()   # 日次平均リターン(ドリフト)
sigma = log_ret.std()    # 日次標準偏差(ボラティリティ)
S0    = df["Close"].iloc[-1]  # 現在の株価

print(f"銘柄: {SYMBOL}  現在株価: {S0:,.0f}円")
print(f"日次平均リターン: {mu*100:.3f}%")
print(f"日次標準偏差: {sigma*100:.3f}%")

# ==============================
# モンテカルロシミュレーション(GBM: 幾何ブラウン運動)
# ==============================
# 各シミュレーションのパス格納配列
sim_paths = np.zeros((SIM_DAYS, NUM_SIMS))

for i in range(NUM_SIMS):
    prices = [S0]
    for _ in range(SIM_DAYS - 1):
        # 幾何ブラウン運動: S(t+1) = S(t) * exp(μ - σ²/2 + σ*Z)
        shock = (mu - 0.5 * sigma**2) + sigma * np.random.normal()
        prices.append(prices[-1] * np.exp(shock))
    sim_paths[:, i] = prices

# ==============================
# VaRの計算
# ==============================
final_prices  = sim_paths[-1, :]   # 1年後の最終株価(全シミュレーション)
final_returns = (final_prices - S0) / S0  # リターン(比率)

var_value = np.percentile(final_returns, (1 - CONF_LEVEL) * 100)
print(f"
--- 1年後のシミュレーション結果 ---")
print(f"平均予測株価: {np.mean(final_prices):,.0f}円")
print(f"中央値予測株価: {np.median(final_prices):,.0f}円")
print(f"95% VaR: {var_value*100:.1f}%  (95%の確率でこれ以上の損失は起きない)")
print(f"最悪シナリオ(下位1%): {np.percentile(final_returns,1)*100:.1f}%")

# ==============================
# グラフ描画
# ==============================
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 5))

# 左:株価パス(最初の100本のみ表示)
ax1.plot(sim_paths[:, :100], alpha=0.1, linewidth=0.5, color='steelblue')
ax1.axhline(y=S0, color='red', linestyle='--', linewidth=1.5, label=f'現在株価 {S0:,.0f}円')
ax1.set_title(f"モンテカルロシミュレーション({NUM_SIMS}回)")
ax1.set_xlabel("日数")
ax1.set_ylabel("株価(円)")
ax1.legend()

# 右:最終株価のヒストグラム(VaRを表示)
ax2.hist(final_returns * 100, bins=60, color='steelblue', alpha=0.7, edgecolor='white')
ax2.axvline(x=var_value * 100, color='red', linestyle='--', linewidth=2,
            label=f"95% VaR = {var_value*100:.1f}%")
ax2.set_title("1年後のリターン分布")
ax2.set_xlabel("リターン(%)")
ax2.set_ylabel("頻度")
ax2.legend()

plt.tight_layout()
plt.savefig("monte_carlo.png", dpi=150)
plt.show()
print("グラフを保存しました: monte_carlo.png")

まとめ

  • モンテカルロシミュレーションは乱数を使って大量のシナリオを計算する手法
  • GBM(幾何ブラウン運動)で現実に近い株価パスを生成できる
  • VaRは「X%の確率でこれ以上の損失は起きない」という損失上限を示す
  • シミュレーション回数を増やすほど精度が向上する(1000〜10000回推奨)
タイトルとURLをコピーしました