定常性を正確に定義する
確率過程Xtが強定常なら、任意の時点集合を同じ幅だけずらしても同時分布が変わりません。実務で多く使う弱定常は、平均が一定で、共分散が時点そのものではなくラグだけに依存するという、より弱い条件です。
平均・分散・自己共分散の構造が時間で変わらない。
金融市場では、この条件が永久に成立すると期待するのは現実的ではありません。そこで「検証窓の中では変化が許容範囲」という局所定常の近似を置きます。ただし窓を短くすると古いレジームの混入は減る一方、推定分散は増えます。
差分・対数化・季節調整で決定的トレンドなどを除ける場合があります。またLLNやCLTにも、独立同分布以外で成立する一般形があります。重要なのは用語の断言ではなく、採用した変換後の過程に必要な仮定が妥当かを検査することです。
無条件成績を条件付きへ分解する
収益Rと、意思決定時点の状態S∈{1,…,K}を考えます。無条件期待値は、状態別期待値を状態確率で加重したものです。
無条件期待値が低下したとき、原因は二つあります。状態別のエッジE[R|S=s]が弱くなったのか、利益を生む状態P(S=s)が出現しなくなったのかです。両者は運用対応が異なります。
分散も状態内のばらつきと、状態間の平均差へ分けられます。
第1項は状態内リスク、第2項はレジーム平均の違いが作るリスク。
| 観測された変化 | 考えられる原因 | 確認するもの |
|---|---|---|
| P(S)だけ変化 | 相場状態の出現頻度が変わった | 状態占有率、継続時間 |
| E[R|S]が変化 | 状態内のエッジが劣化 | 状態別CI、勝率、ペイオフ |
| Var(R|S)が増加 | 同じ状態名でも内部が不安定 | 尾部、DD、分布距離 |
| すべて変化 | 状態定義自体が陳腐化 | 上流特徴量と分類器 |
レジームを事前情報で定義する
状態変数Ztには、直前までの実現ボラティリティ、スプレッド、出来高、金利差、トレンド強度などを使えます。必要条件は、注文時点の情報集合ℱtで測定できることです。
- 当日高値・安値を終値前のシグナルへ使わない。
- 全期間の33%・66%分位で低中高ボラを作らない。
- 景気後退の確定日など、後から改定・公表されたラベルを当時既知としない。
- HMMやクラスタの標準化・パラメータをテスト期間込みで学習しない。
レジーム定義は経済的意味を先に置きます。「高ボラだから逆張りを止める」なら、なぜその状態で約定・尾部・平均回帰速度が変わるのかを説明します。色分け後に一番良い区分を選べば、新しい探索です。
K状態に分けると各セルの標本数は急減します。年×時間×通貨×ボラ×トレンドを同時に切れば、見かけの差は簡単に作れます。各セルn、95%CI、探索した全定義数を報告します。
分布ドリフトを測る
平均差だけでなく、trainとOOSの分布全体を比べます。一変量なら経験CDF間のWasserstein-1距離が直感的です。
離散化した分布にはJensen–Shannon距離も使えます。KL divergenceは一方のビン確率が0だと発散し、ビン幅にも敏感です。どの距離も単独の普遍的合格ラインはないため、train内の自然変動やブロック・ブートストラップから基準を事前に作ります。
| 比較対象 | 目的 | 最低限の併記 |
|---|---|---|
| P(Z) | 入力状態の出現分布 | 状態占有率、継続時間 |
| P(R|S) | 状態内の損益分布 | 平均CI、下位分位、DD |
| P(features|S) | 状態定義の上流安定性 | 分布距離、欠損率 |
| P(fill|signal,S) | 執行可能性 | 滑り、拒否、スプレッド |
fold内で検証する
レジーム分析はCPCVやウォークフォワードの外に付ける後処理ではありません。各foldのtrainだけで変換と状態定義を学習し、testへ固定適用します。
for train_idx, test_idx in purged_splits:
scaler.fit(features[train_idx])
z_train = scaler.transform(features[train_idx])
regime_model.fit(z_train)
s_train = regime_model.predict(z_train)
s_test = regime_model.predict(
scaler.transform(features[test_idx])
)
strategy.fit(train_idx, s_train)
r_oos = strategy.evaluate(test_idx, s_test, costs=True)
report_by_regime(r_oos, s_test)
compare_train_oos_distributions(...)レジーム変数の窓が将来へ伸びる場合は、その区間もPurging対象です。境界、状態数、距離指標、窓幅、分類器を比較した数は候補数として実行前にNへ加えます。
複雑なモデルは柔軟ですが、推定に長い履歴を必要とします。長い履歴は古い構造を混ぜます。モデル複雑度と学習窓長は別々に後付け調整せず、一つの事前登録された選択問題として扱います。
運用中の変化検知
フォワードでは、状態別期待値の基準μ0から負方向へずれた累積を監視できます。単純な片側CUSUMは次の形です。
kは許容する小さな変化、hは警報閾値です。損失を見て動かすのではなく、バックテストまたはシミュレーションで誤警報率と検出遅延を決めます。自己相関があるため、iid前提の閾値をそのまま使いません。
データ欠損、時刻、注文、スプレッド、状態占有率の変化を先に診断します。警報後に閾値を緩める場合は、新しい研究IDと追加Nが必要です。
限界とチェックリスト
- 将来に未知の状態を、過去の状態分類から保証できない。
- 条件付けは交絡を減らせても因果関係を証明しない。
- 分布距離が小さくても、尾部の経済的に重要な差を隠すことがある。
- 状態別分析は標本を細分化し、推定誤差を増やす。
- 危機時だけ働く戦略は、平常時の不安定さだけで棄却しない。
- 強定常・弱定常・局所定常を区別した
- 状態変数が意思決定時点で観測可能
- 境界・標準化・分類器をtrain内だけでfitした
- P(S)とP(R|S)を分けて報告した
- 状態別n・95%CI・下位分位を掲載した
- 試したレジーム定義をNへ加えた
- ドリフト警報と停止後診断を事前登録した
ミニテスト
4問で確認します。
Q1. 無条件期待値が変わる二つの主因は?
P(S)とE[R|S]を分けます。
Q2. ボラ分位の境界を推定する正しい範囲は?
test情報を境界作成へ漏らしません。
Q3. レジーム定義を5通り比較して選んだら?
結果選択へ使った比較は試行です。
Q4. CUSUM警報が直接証明するものは?
まずデータ・実装・執行・市場状態を切り分けます。
参考資料
着想と実装例はQuant GuildのNon-Stationarity and Why Market Timing Fails、Profitable vs Tradable、Law of Total Expectation。数理的背景は Hamilton, A New Approach to the Economic Analysis of Nonstationary Time Series、Capponi et al., The Nonstationarity-Complexity Tradeoff in Return Prediction、逐次変化検知は Page, Continuous Inspection Schemesを参照してください。