リスク管理を「ちゃんとやってる感」を出したくて、保有中の製造業株のVaR(バリュー・アット・リスク)を正規分布の式でサクッと計算したことがあります。「99%の確率で1日の損失はこの範囲に収まります」と自分に言い聞かせていたら、その1週間後にまさかの決算ショックで想定の3倍近く下落。。。あれ、99%のはずじゃ。と青ざめました。
なぜ正規分布を疑うことになったのか
株価のリターンって、教科書的には「正規分布に従う」という前提で語られることが多いです。平均と標準偏差(σ)さえ分かれば、「±1σの範囲に約68%、±2σに約95%、±3σに約99.7%が収まる」という便利な性質が使えるので、VaR計算などによく使われます。ただ僕がハマったショックのように、実際の株価には正規分布の想定より明らかに極端な値動きが出ることがある。これを「ファットテール(fat tail)」と呼びます。
ファットテールとは何か
正規分布の裾(テール)は理論上どんどん薄くなっていくので、「3σを超える下落」はめったに起きない前提になっています。ところが実際の株式リターンの分布は、真ん中付近が正規分布より尖っていて(レプトカーティック)、裾のほうは正規分布より厚い、という形になりがちです。専門的には「尖度(kurtosis)が3より大きい」状態です。決算発表・地政学リスク・金融危機のような非連続なイベントが、この「太い裾」を作り出しています。
数式で言うと、正規分布の確率密度関数は次の形です。
f(x) = 1 / (σ√(2π)) × exp( -(x-μ)² / (2σ²) )
この式が仮定しているのは「極端な値ほど指数関数的に急激に起きにくくなる」という滑らかな世界。でも現実の株価は、決算やFOMCの日だけ急にルールが変わる世界線に近い。この「モデルと現実のズレ」を知っているかどうかが、ポジションサイズの取り方に直結してくるな、と痛感しました。
Pythonで実際のリターン分布を見てみる
手元のドル円日次リターンで、正規分布とどれくらいズレているか尖度を計算してみました。
import yfinance as yf
import pandas as pd
from scipy import stats
# ドル円の日次データを取得(例:直近2年)
df = yf.download("JPY=X", period="2y", interval="1d")
returns = df["Close"].pct_change().dropna()
mean = returns.mean()
std = returns.std()
kurt = stats.kurtosis(returns) # 正規分布なら0に近い値(excess kurtosis)
skew = stats.skew(returns)
print(f"平均: {mean:.5f}, 標準偏差: {std:.5f}")
print(f"尖度(excess kurtosis): {kurt:.2f}") # 0より大きいほどファットテール
print(f"歪度(skewness): {skew:.2f}")
# 正規分布を仮定した場合の「3σを超える下落」が起きる理論確率
theoretical_3sigma = stats.norm.cdf(-3)
# 実際に3σを超える下落が起きた日数の割合
actual_3sigma = (returns < mean - 3 * std).mean()
print(f"理論値: {theoretical_3sigma:.5f}, 実際: {actual_3sigma:.5f}")
実際にドル円や日本株で計算してみると、excess kurtosisがプラスに出るケースが多く、「3σ超えの下落」は理論値よりも数倍〜十数倍の頻度で発生していました。正規分布を鵜呑みにしたVaRは、平常時は良さそうに見えて、肝心の暴落時にこそ役に立たないという皮肉な結果です。
投資への応用:じゃあどうするか
完璧な代替モデルを追い求めるより、まず「正規分布は近似にすぎない、裾は必ず太くなる」と割り切ることが実践的だと感じています。具体的には、正規分布ベースのVaRより余裕を持ったポジションサイズにする、決算前後はポジションを軽くする、ヒストリカル法(実際の過去分布をそのまま使う)やt分布(裾が太いモデル)も併用してみる、といった対策です。統計モデルを疑ってかかる姿勢そのものがリスク管理だな、と今回学びました。
正規分布、名前だけは知ってたつもりでしたが、ちゃんと手を動かして尖度を計算してみると想像以上に奥が深かったです。次はこのファットテールを踏まえたポジションサイジングのルールを、実際のドル円戦略に組み込んでみようと思っています。
