walk-forward-validation について
金融時系列における取引戦略や機械学習モデルを評価するための検証フレームワーク兼スキルです。時系列分割、パージとエンバーゴ、CPCV、バックテストの過学習検出指標を扱い、暗号資産向けの指針も示します。
主な機能
- 01ローリング・拡大型ウィンドウ検証
- 02ラベル重複に対するパージとエンバーゴ
- 03コンビナトリアル・パージド交差検証
- 04Deflated Sharpe ratio と PBO
- 05暗号資産向けの検証指針
活用シーン
- 01ランダム分割の先読みバイアスを避けた戦略評価
- 02市場レジーム変化に対するモデルの検証
- 03複数のパスによるバックテスト過学習の評価
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ agiprolabs/ claude-trading-skills --skill walk-forward-validationインストール後、Claude Code で/walk-forward-validationを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/methodology.mdoverfit_detection.mdpractical_guide.mdscripts/overfit_detector.pywalk_forward.py詳細
ウォークフォワード検証
トレーディング戦略と ML モデル向けのウォークフォワード検証フレームワークです。標準的な交差検証(k 分割、ランダム分割)は、先読みバイアスを生み、自己相関を無視するため、金融時系列では致命的な問題を引き起こします。このスキルでは、ローリングウィンドウや拡張ウィンドウ、パージド交差検証、組み合わせパージド交差検証(CPCV)、過学習検出指標など、適切な時系列検証手法を扱います。
標準的な交差検証が機能しない理由
標準的な k 分割交差検証(CV)は、データポイントが独立同分布(IID)であることを前提とします。金融時系列では、この両方の前提が成り立ちません。
- 先読みバイアス — ランダム分割では、モデルが未来のデータで学習し、過去を予測することになり、パフォーマンスが人為的に高く見積もられます。
- 自己相関 — 隣接する観測値は相関しています。月曜日をテストデータ、火曜日を学習データにするランダム分割では、情報が漏洩します。
- レジーム依存性 — 市場はレジーム間を移行します。強気相場で学習し、強気相場でテストしたモデルからは、弱気相場でのパフォーマンスについて何もわかりません。
- ラベルの重複 — ラベルがウィンドウ(例:24 時間先のリターン)にわたって計算される場合、学習サンプルとテストサンプルが隣接していると、ラベル計算期間が重なり、情報が漏洩します。
ウォークフォワードフレームワーク
ローリングウィンドウ(学習サイズ固定)
学習ウィンドウのサイズを固定し、時間とともに前方へ移動させます。古いデータほど関連性が低いと考える場合(暗号資産では一般的)に適しています。
Window 1: [===TRAIN===][=TEST=]
Window 2: [===TRAIN===][=TEST=]
Window 3: [===TRAIN===][=TEST=]
パラメーター:
train_size:学習ウィンドウ内のバー数/日数test_size:テストウィンドウ内のバー数/日数step_size:各分割の間に進める幅(多くの場合、test_sizeと同じ)
拡張ウィンドウ(学習サイズを拡大)
学習ウィンドウを最初の時点から開始し、前方へ拡張させます。利用可能な過去のデータをすべて使うため、データが少ない場合に役立ちます。
Window 1: [==TRAIN==][=TEST=]
Window 2: [====TRAIN====][=TEST=]
Window 3: [======TRAIN======][=TEST=]
パラメーター:
min_train_size:最初の分割より前に必要な最小学習サンプル数test_size:固定のテストウィンドウサイズstep_size:各分割の間に進める幅
選択の目安
| 要素 | ローリング | 拡張 |
|---|---|---|
| データの新しさ | 直近のデータを優先 | すべての履歴を使用 |
| レジーム変化 | 新しいレジームへの適応に優れる | 直近のレジームの影響が薄まる可能性がある |
| サンプルサイズ | 固定で、少ない場合がある | 時間とともに増加 |
| 暗号資産での選好 | 6 か月未満の期間で推奨 | レジームが安定したモデルに適する |
パージとエンバーゴ
パージ
ラベルがテストセットの期間と重複する学習サンプルを取り除きます。ラベルが時刻 t から始まる 24 時間先のリターンとして計算される場合、t + 24h がテスト期間に入る学習サンプルはすべてパージする必要があります。
def purge_train_indices(
train_idx: list[int],
test_start: int,
label_horizon: int,
timestamps: list[int],
) -> list[int]:
"""Remove train samples whose label windows overlap test period."""
test_start_time = timestamps[test_start]
return [
i for i in train_idx
if timestamps[i] + label_horizon < test_start_time
]
エンバーゴ
パージだけでは除去できない系列相関を考慮し、学習の終了とテストの開始の間にバッファー期間を設けます。
[===TRAIN===][--EMBARGO--][=TEST=]
一般的なエンバーゴサイズ:
- 1 分足:60~240 本(1~4 時間)
- 5 分足:12~48 本(1~4 時間)
- 時間足:6~24 本(6~24 時間)
- 日足:2~5 本(2~5 日)
- 暗号資産の経験則:エンバーゴ >= ラベル計算期間の 2 倍
組み合わせパージド交差検証(CPCV)
CPCV(Lopez de Prado、2018)は、時間順序を維持しながら、N 個のグループから可能なすべての学習/テストの組み合わせを生成します。これにより、標準的なウォークフォワードよりも多くのテストパスが得られ、過学習の統計的検定が可能になります。
主な特性:
- データを連続する
N個のグループに分割します - テストグループを
k個選ぶ各組み合わせについて、残りのN-k個のグループを学習セットにします - 学習/テスト境界ごとにパージとエンバーゴを適用します
C(N, k)個のバックテストパスを生成します(例:N=6、k=2 の場合は 15 パス)
CPCV のアルゴリズムと数式の詳細については、references/methodology.md を参照してください。
過学習の検出
デフレート・シャープレシオ(DSR)
観測されたシャープレシオは、以下の要素を考慮して調整する必要があります。
- テストした戦略の数(多重検定)
- リターンの非正規性(歪度、尖度)
- バックテストの期間
import numpy as np
from scipy.stats import norm
def deflated_sharpe_ratio(
observed_sr: float,
num_trials: int,
backtest_length: int,
skewness: float = 0.0,
kurtosis: float = 3.0,
) -> float:
"""Compute the probability that observed SR > 0 after deflation.
Args:
observed_sr: Annualized Sharpe ratio of the selected strategy.
num_trials: Number of strategies tested (including discarded ones).
backtest_length: Number of return observations.
skewness: Skewness of returns.
kurtosis: Excess kurtosis of returns.
Returns:
p-value (probability SR is genuinely > 0).
"""
sr_std = np.sqrt(
(1 - skewness * observed_sr + (kurtosis - 1) / 4 * observed_sr**2)
/ (backtest_length - 1)
)
# Expected max SR under null (Euler-Mascheroni approximation)
euler_mascheroni = 0.5772156649
expected_max_sr = norm.ppf(1 - 1 / num_trials) * (
1 - euler_mascheroni
) + euler_mascheroni * norm.ppf(1 - 1 / (num_trials * np.e))
dsr = norm.cdf((observed_sr - expected_max_sr) / sr_std)
return dsr
DSR が 0.95 を下回る場合、観測されたパフォーマンスは、テストした試行を通じた過学習による可能性が高いことを示します。
バックテスト過学習確率(PBO)
PBO は CPCV を使用して、サンプル内で最適な戦略がサンプル外の中央値を下回るバックテストパスの割合を測定します。PBO が 0.50 を超える場合、過学習の可能性が高いことを示します。
導出と実装の詳細については、references/overfit_detection.md を参照してください。
暗号資産特有の考慮事項
- 短いウィンドウ:暗号資産のレジームは株式よりも速く変化します。252 日よりも 90 日のローリングウィンドウのほうが適切な場合があります。
- 24 時間 365 日の市場:週末や祝日を考慮する必要はありませんが、資金調達率のリセット(無期限先物では 8 時間ごと)がマイクロストラクチャーに影響を与えます。
- サバイバーシップバイアス:多くのトークンが上場廃止になります。検証には上場廃止されたトークンを含めるか、少なくともこの制約を明示する必要があります。
- 流動性レジームの変化:トークンの流動性プロファイルは大きく変化することがあります(新たな CEX への上場、流動性マイニングの終了など)。訓練データとテストデータの分割では、できれば大きな流動性イベントをまたがないようにします。
- データの利用可能性:1 年未満のデータしかないトークンも多くあります。小さな
min_train_sizeを設定した拡張ウィンドウが必要になる場合があります。
暗号資産における実用的なウィンドウサイズ
| 戦略の時間軸 | 訓練ウィンドウ | テストウィンドウ | エンバーゴ |
|---|---|---|---|
| スキャルピング(1〜5 分) | 3〜7 日 | 1 日 | 2〜4 時間 |
| 日中取引(15 分〜1 時間) | 14〜30 日 | 3〜7 日 | 12〜24 時間 |
| スイングトレード(4 時間〜日足) | 30〜90 日 | 7〜14 日 | 2〜5 日 |
| ポジショントレード(日足〜週足) | 90〜180 日 | 30 日 | 5〜10 日 |
クイックスタート
from walk_forward import WalkForwardValidator, WalkForwardConfig
config = WalkForwardConfig(
train_size=90,
test_size=14,
step_size=14,
window_type="rolling",
embargo_size=3,
purge_horizon=1,
)
validator = WalkForwardValidator(config)
for fold in validator.split(price_data):
model.fit(fold.train_X, fold.train_y)
predictions = model.predict(fold.test_X)
fold.record_performance(predictions, fold.test_y)
results = validator.aggregate_results()
print(f"OOS Sharpe: {results.oos_sharpe:.3f}")
print(f"Train/Test Sharpe ratio: {results.sharpe_ratio_ratio:.2f}")
ファイル
リファレンス
references/methodology.md— ウォークフォワード理論、ウィンドウの種類、パージ、エンバーゴ、数式付き CPCV アルゴリズムreferences/overfit_detection.md— デフレート・シャープレシオ、バックテスト過学習確率、多重検定の補正references/practical_guide.md— 暗号資産におけるウィンドウサイズの選定、レジームに関する考慮事項、よくある検証の誤り
スクリプト
scripts/walk_forward.py— ローリングウィンドウと拡張ウィンドウに対応したウォークフォワード検証エンジン。合成データを使用する--demoモードscripts/overfit_detector.py— デフレート・シャープレシオと PBO の計算。合成バックテスト結果を使用する--demoモード