なぜ標準のK-Foldは金融市場で破綻するのか

scikit-learnなどの標準ライブラリに搭載されている KFold や train_test_split は、すべてのサンプルが独立同分布(I.I.D.:互いに無関係に生成される)であることを前提としています。例えば、犬と猫の画像分類であれば、画像をランダムにシャッフルして学習用とテスト用に分割しても何の問題もありません。

しかし、金融市場のデータは時間順に強く結合した「時系列プロセス」です。特にトレード戦略では、シグナルが発生した時点 \(t_{i,0}\) から、利確・損切りまたは時間制限でポジションが決済される時点 \(t_{i,1}\) まで、ある有限の時間幅が存在します。

I_i = [t_{i,0}, t_{i,1}]

※\(t_{i,0}\) は特徴量を観測して予測した時刻、\(t_{i,1}\) はリターン(正解ラベル \(y_i\))が確定した決済時刻。

例えば、金曜日の15:00にエントリーし、翌週火曜日の10:00に利確されたトレードを考えます。このトレードの損益ラベル \(y_i\) は、「月曜日と火曜日の市場価格の変動」によって決定されています。

もし月曜日以降の期間が「テストデータ(Test)」に割り当てられていた場合、学習データに入っているこの金曜日のサンプルは、「未来のテスト期間の値動きを正解ラベルとして知っているスパイ」になってしまいます。この状態で学習したモデルは、未知のデータで勝てるはずがありません。

時間軸 (Time) → テストデータ期間 (Test Fold) Embargo 自己相関遮断 学習サンプルA(安全:重複なし) 学習サンプルB(危険:テスト期間に食い込む!) 【Purge除外】 学習サンプルC(直後リーク) 【Embargo除外】
図1:テスト期間にラベルが食い込むサンプルのPurging除外と、直後の自己相関を遮断するEmbargoバッファ

Purging(パージング):区間重複の数学的排除

Marcos López de Prado (2018) が提唱したPurging(パージング:浄化)は、テストデータと時間的に重複する学習サンプルを数学的に定義して完全に排除するアルゴリズムです。

テストセットに含まれるサンプルのインデックス集合を \(S_{ ext{test}}\) とします。学習候補サンプル \(i \in S_{ ext{train\_candidates}}\) の情報区間を \(I_i = [t_{i,0}, t_{i,1}]\) とするとき、Purgingの除外ルールは以下のように定義されます。

i ext{ を学習データから除外 (Purge)} \iff \exists j \in S_{ ext{test}} ext{ such that } I_i \cap I_j eq \emptyset

※2つの区間が交差する条件:\(\max(t_{i,0}, t_{j,0}) \le \min(t_{i,1}, t_{j,1})\)

実務上、テスト期間が連続した区間 \([T_{ ext{test\_start}}, T_{ ext{test\_end}}]\) である場合、学習サンプル \(i\) がテストの前に位置する場合のPurge判定条件は極めてシンプルです。

Embargo(エンバーゴ):自己相関遮断バッファ

Purgingによって「ラベル期間の直接の重複」は完全に解消されます。しかし、金融時系列にはもう一つの厄介な性質があります。それが「自己相関(Autocorrelation)」と「特徴量の過去参照ラグ(Lookback Window)」です。

テスト期間の最終日 \(T_{ ext{test\_end}}\) の直後の相場は、テスト期間中のボラティリティやトレンドの記憶(残響)を強く引きずっています。また、モデルの特徴量に「直近20日間のEMA」や「14日間のRSI」を使っていた場合、テスト終了直後の学習サンプルは、テスト期間内の価格データを特徴量計算に直接使用してしまいます。

これを防ぐために、テスト期間の終了点の直後に長さ \(h\) の空白期間を強制的に挿入します。これがEmbargo(エンバーゴ:通商停止措置)です。

E_j = (T_{ ext{test\_end}}, T_{ ext{test\_end}} + h]

※この区間 \(E_j\) 内で開始するすべての学習サンプル(\(t_{i,0} \in E_j\))を学習データから除外します。

実務におけるEmbargo幅 \(h\) の目安は、データセット全体の \(1\% \sim 5\%\)(日次データであれば数営業日から1ヶ月程度)です。特徴量の最大ルックバック期間(例: 200日移動平均線なら200日)を考慮して設定します。

前処理リーケージの罠:変換器はTrainのみでfitする

クロスバリデーション(CV)を正しく分割しても、機械学習エンジニアが最も頻繁にやらかすミスが「データ前処理におけるリーケージ」です。

Python:致命的なリーケージコードの例
# × 致命的な誤り(全期間でfitしてしまっている)
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X) # 全データ(未来のテストデータ含む)の平均と分散を使って標準化している!

# その後に交差検証に投入...
for train_idx, test_idx in cv.split(X_scaled):
    model.fit(X_scaled[train_idx], y[train_idx]) # 未来の統計量が染み出している!

全期間のデータで平均や標準偏差を計算すると、「未来のテスト期間における平均価格やボラティリティの大きさ」が学習データに漏れ出します。正しいパイプラインは、必ず各Foldの学習データ(Train)の中だけで fit し、テストデータにはそのパラメータを使って transform だけを適用することです。

Python:正しいクロスバリデーション前処理
# ◎ 正しい実装(FoldごとにTrainのみでfitする)
for train_idx, test_idx in cv.split(X):
    X_train, X_test = X[train_idx], X[test_idx]
    y_train, y_test = y[train_idx], y[test_idx]
    
    # 変換器の初期化と学習
    scaler = StandardScaler()
    X_train_scaled = scaler.fit_transform(X_train) # 学習データだけでfit
    X_test_scaled = scaler.transform(X_test)       # テストデータには適用するだけ
    
    model.fit(X_train_scaled, y_train)
    score = model.score(X_test_scaled, y_test)

金融機械学習における4大情報漏洩と対策

実務で必ず監査すべき情報漏洩の種類と、その遮断メカニズムを整理しました。

漏洩の種類 発生する原因とメカニズム 遮断するための具体策
1. ラベル重複リーク トレード保有期間が学習とテストの境界を跨ぎ、未来の決済損益が学習データに混入する。 Purging(パージング):各サンプルの決済時刻 \(t_{i,1}\) を記録し、テスト区間と交差するサンプルを全消去。
2. 特徴量ラグ・相関リーク テスト期間直後の相場が、テスト内のボラティリティや自己相関、ルックバックを記憶している。 Embargo(エンバーゴ):テスト終了地点の直後に \(1\%\sim 5\%\) の空白期間を強制挿入。
3. 前処理統計量リーク 正規化スケーラー、主成分分析(PCA)、欠損補完値の計算をデータセット全体で行ってしまう。 Fold内fitの徹底:sklearn.pipeline.Pipeline を使い、各分割のTrainのみで統計量を算出。
4. ハイパーパラメータリーク テストデータの成績を見てパラメータや特徴量を人間がいじり直す。 OOSの完全封印:交差検証のさらに外側に、最後の最後まで一切触らない完全未見データを隔離する。
次回への接続:単一のOOSから「複数のOOS」へ

PurgingとEmbargoによって、時系列データの情報漏洩を遮断する準備が整いました。しかし、「過去の1箇所だけをテスト期間にする」単一のバックテストでは、たまたまその期間の相場と戦略の相性が良かっただけかもしれません。次回は、複数のOOSを組み合わせて過学習確率(PBO)を測定する究極の検証手法、CPCV(Combinatorial Purged Cross-Validation)の全貌を解き明かします。

ミニテスト

4問の理解度テストです。

Q1. 金融時系列クロスバリデーションにおける「Purging(パージング)」の判定基準はどれ?

正解はBです。開始日がテスト期間より前であっても、利確・損切り等のラベル確定がテスト期間へはみ出していれば未来情報を知っていることになるため、除外(Purge)します。

Q2. テスト期間の直後に設けられる「Embargo(エンバーゴ)」の主たる目的はどれ?

正解はAです。テスト期間の直後は強い自己相関や過去価格を参照する特徴量を通じて未来情報が漏洩しやすいため、追加の空白期間(Embargo)を設けます。

Q3. 機械学習モデルの特徴量標準化(StandardScaler)において、平均と標準偏差を計算(fit)すべき範囲はどこか?

正解はCです。全データでfitしてしまうとテスト期間の統計量(ボラティリティや平均)が学習に漏れ出すため、必ず各Foldの学習データのみでfitします。

Q4. 保有期間が相場に応じて変化する可変保有戦略(トリプルバリア法など)でPurgingを実装する際に不可欠なデータはどれ?

正解はBです。可変保有ではトレードごとに決済時刻が異なるため、固定のバー数ではなく標本ごとの実際の決済時刻を用いてテスト期間との重複を判定します。

学術文献・参考資料