GARCHモデルでドル円のボラティリティを予測する【Python×archライブラリ入門】

Python実装・コード

子供が生まれてから、夜中のドル円急変動を寝たまま食らうことが増えた。先月も米CPIの発表前後で1円以上動いて、翌朝ポジションを見て青ざめた。「ボラティリティが高い日だけポジションを小さくする」とか、事前に分かれば対処できるのに——そう思って調べたのがGARCHモデルだ。

GARCHモデルって何?(3行で)

GARCH(Generalized Autoregressive Conditional Heteroskedasticity)は、金融時系列のボラティリティが「大きく動いた後はしばらく大きく動く傾向がある」という性質(ボラティリティ・クラスタリング)をモデル化する統計手法だ。難しい名前だけど、要は「昨日荒れてたら今日も荒れやすい」を数式にしたもの。ドル円みたいにFXに向いてる。

なぜGARCHを調べたか

僕がよくやっていたのは「ATRでポジションサイズを調整する」方法だ(以前の記事で書いた)。でも ATRは過去N日の平均レンジであって、「明日のボラを予測する」モデルじゃない。GARCH なら条件付き分散を1日先予測できるので、「明日は荒れそうだからロット半分」という判断に使えるかもしれない。そういう動機で調べ始めた。

環境準備:archライブラリのインストール

PythonでGARCHを実装するなら arch ライブラリが定番だ。インストールは一行。

pip install arch yfinance pandas numpy matplotlib

ドル円データを取得してGARCH(1,1)を当てはめる

まずyfinanceでドル円の日足データを取得し、対数収益率を計算してGARCH(1,1)モデルに当てはめる。

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

# ドル円日足データ取得(2年分)
ticker = yf.Ticker("JPY=X")
df = ticker.history(period="2y")

# 対数収益率(%スケールにするとGARCHの収束が安定)
df["log_ret"] = np.log(df["Close"] / df["Close"].shift(1)) * 100
df = df.dropna()

print(df["log_ret"].describe())

出力例:

count    502.000000
mean      -0.003412
std        0.512834
min       -2.847100
25%       -0.271903
50%        0.002150
75%        0.280412
max        2.156300

次にGARCH(1,1)モデルを当てはめる。arch_modelp=1, q=1 がGARCH(1,1)の指定だ。

# GARCH(1,1) モデルの定義と推定
model = arch_model(
    df["log_ret"],
    vol="Garch",   # ボラティリティモデル
    p=1,           # GARCH項のラグ次数
    q=1,           # ARCH項のラグ次数
    dist="normal"  # 誤差分布(t分布も試す価値あり)
)

result = model.fit(disp="off")  # disp="off" で推定過程の出力を抑制
print(result.summary())

result.summary() の出力にはω(定数項)、α(ARCH係数)、β(GARCH係数)が表示される。α+βが1に近いほど「ボラティリティの持続性が高い」ことを意味する。ドル円は往々にして0.95前後になる。

1日先ボラティリティを予測する

# 1日先の条件付き分散を予測
forecast = result.forecast(horizon=1, reindex=False)

# 予測ボラティリティ(標準偏差、%単位)
pred_vol = np.sqrt(forecast.variance.values[-1, 0])
print(f"明日の予測ボラティリティ: {pred_vol:.4f}%")

# 過去の条件付きボラティリティの推移を可視化
cond_vol = result.conditional_volatility

plt.figure(figsize=(12, 5))
plt.plot(cond_vol.index, cond_vol.values, color="#f87171", linewidth=1)
plt.title("ドル円 条件付きボラティリティ(GARCH推定)")
plt.ylabel("ボラティリティ (%)")
plt.xlabel("日付")
plt.tight_layout()
plt.savefig("usdjpy_garch_vol.png", dpi=150)
plt.show()

予測ボラを使ってポジションサイジングに組み込む

実用的な使い方として、予測ボラティリティをポジションサイズ調整に使う例を示す。

# 過去の中央値ボラを基準にポジション倍率を計算
median_vol = cond_vol.median()
latest_vol = cond_vol.iloc[-1]

position_ratio = median_vol / latest_vol  # ボラが高いほど小さくなる
position_ratio = np.clip(position_ratio, 0.25, 1.5)  # 最小25%〜最大150%

print(f"基準ボラ(中央値): {median_vol:.4f}%")
print(f"直近ボラ: {latest_vol:.4f}%")
print(f"→ ポジション倍率: {position_ratio:.2f}x")

これで「ボラが平均の2倍→ポジション半分」みたいな機械的なリスク管理ができる。指標発表前後に自動でロットを下げたい僕には、まさに求めていた機能だった。

GARCH(1,1)の限界と注意点

GARCHにはいくつか注意点がある。まず、価格の方向(上か下か)は予測しない——あくまで「どれくらい動くか」の予測だ。また、急激なフラッシュクラッシュには過去データだけでは対応しきれない。誤差分布を正規分布ではなくt分布(dist="t")にすると、テールリスクをより適切にモデル化できるので試してみてほしい。

まとめ

GARCHモデルを使うと、過去のボラティリティの推移から1日先のリスクをある程度定量化できる。実装自体はarchライブラリのおかげで10行程度で済む。個人的には「指標発表日の前日に予測ボラをチェックして、高ければポジション半減」くらいの使い方が現実的だと感じた。次はt分布GARCHとEGARCH(非対称性あり)の比較をやってみたい。

タイトルとURLをコピーしました