※本記事のコードや情報は執筆時点の仕様に基づいています。投資は自己責任であり、必ずデモ環境や少額資金でテストした上で運用してください。
モンテカルロシミュレーションとは何か
モンテカルロシミュレーションとは、乱数を使って大量の「もしもシナリオ」を計算し、その結果の分布から確率的な予測を行う手法です。カジノの街モナコのモンテカルロに由来しています。
株式投資への応用では「将来の株価がどのような範囲に収まるか」を確率で表現します。
| 概念 | 説明 |
|---|---|
| シミュレーション回数 | 多いほど精度が上がる(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回推奨)

