2026-02-24
008 方向予測ロジック再設計(active)— R8-3で急変動検知の課題を認識
009 急変動検知と予測改善 ← このissue
DB実績データ441件から計算:
30M 方向精度: 48.8% (ランダム=50%を下回る)
UP: 126/255 = 49.4%
DOWN: 89/186 = 47.8%
比較:
H足 方向精度: 74.5% (585件、バックテスト)
UP: 209/269 = 77.7%
DOWN: 227/316 = 71.8%
30M足はシグナルとして機能していない。 H足との差が25ポイント以上。
30M足の急変動時(上位25%、110件):
| 指標 | 30M | H |
|---|---|---|
| Avg MagRatio | 0.19 | 0.68 |
| Direction agree | 62.7% | 98.6% |
| Under-predict率 | 100% | 72.6% |
274件の3モデル比較分析で判明:
| 特性 | XGBoost | LightGBM | CatBoost |
|---|---|---|---|
| バイアス | +0.0006(中立) | +0.0086(やや強気) | -0.0125(弱気) |
| 方向精度 | 56.2% | 56.9% | 53.6% |
| 予測振幅(Stdev) | 0.1139% | 0.1225%(大胆) | 0.0858%(保守的) |
| 実績との相関 | +0.028 | +0.025 | -0.084(負の相関) |
| 急変動MagRatio | 0.078 | 0.081 | 0.063 |
| 不一致時正答率 | 52.5% | 55.9% | 40.7% |
| 3モデル一致率 | — | — | 78.5% |
CatBoostの問題: - 実績と負の相関 — 実績が上がるとモデルは下がると予測する傾向 - 不一致時の正答率40.7% — 他2モデルと意見が違う時に間違いやすい - 予測振幅が最も保守的(急変動への追従力が最低) - 現在の重み: xgb:0.50, lgbm:0.37, cat:0.13
1. 損失関数(MAE)の限界
- 3モデルとも objective='mae' / loss_function='MAE' を使用
- MAEは中央値への収束を促し、テール事象(急変動)を構造的に無視する
- 急変動を正確に予測しても、多数の通常時予測の精度が下がるため、モデルは保守的な予測に収束
2. 急変動の「予兆」を捉える特徴量の不足
- 既存: price_shock(2σ超で検出)→ 既に起きた後の検出
- 既存: atr_ratio(短期/長期ATR)→ 遅行指標
- 欠如: BBスクイーズ(低ボラ→急変動の前兆)
- 欠如: OI+FRの組合せ(清算カスケードの前兆)
- 欠如: ボラティリティの急変そのものを表す特徴量
| 既存施策 | 場所 | 問題点 |
|---|---|---|
price_shock フラグ |
feature_engineering.py | 2σ超の検出のみ。予兆は捉えない |
atr_ratio(短期/長期ATR) |
feature_engineering.py | 既に動いた後のスパイク検出(遅行) |
_compute_sample_weights ショック3倍 |
model.py | 一律3倍では不十分。大きな急変動も小さな急変動も同じ重み |
| 高ボラ時クリッピング ±10% | model.py | 急変動を抑制してしまう逆効果 |
scale_prediction_by_volatility |
model.py | 現在のATR使用(予測ATRではない) |
| レジーム別パラメータ調整 | model.py | 高ボラ時にn_est↓、depth↓ = むしろ表現力低下 |
| TF | XGB | LGBM | CAT | 備考 |
|---|---|---|---|---|
| 15M | 47% | 47% | 47% | ランダム以下。ノイズが多すぎる |
| 30M | 63% | 61% | - | 方向はバランス良好だが振幅が足りない |
| H | - | 78% | - | 方向は優秀だが振幅をほぼ無視(MagRatio 0.015-0.019) |
| 指標 | 値 |
|---|---|
| 方向精度 | 48.8% (215/441) |
| RMSE | $338.63 |
| MAE | $202.10 |
| 急変動 MagRatio | 0.1891 |
| 急変動 方向一致 | 62.7% |
| 急変動 Under-predict率 | 100% |
| 期間 | Close | High | Low |
|---|---|---|---|
| +1 bars (30min先) | 0.33% | 0.29% | 0.32% |
| +2 bars (1h先) | 0.48% | 0.45% | 0.49% |
| +6 bars (3h先) | 0.87% | 0.83% | 0.89% |
| セッション(UTC) | Close | High | Low | n |
|---|---|---|---|---|
| Asia (0-8) | 0.48% | 0.46% | 0.49% | 2,535 |
| Europe (8-14) | 0.50% | 0.47% | 0.49% | 1,902 |
| US (14-21) | 0.73% | 0.68% | 0.76% | 2,184 |
| Late (21-24) | 0.48% | 0.45% | 0.50% | 936 |
USセッションのMAEが突出(0.73% vs Asia 0.48%)。ボラティリティが高い時間帯の予測精度が低い。
| 指標 | 値 |
|---|---|
| 方向精度 | 74.5% (436/585) |
| RMSE | $379.16 |
| MAE | $254.26 |
| 急変動 MagRatio | 0.6842 |
| 急変動 方向一致 | 98.6% |
| 急変動 Under-predict率 | 72.6% |
ヘルパー関数 _add_bb_squeeze_features() を作成し、4TF(D/H/30M/15M)全てに適用。
| 追加特徴量 | 計算式 | 意味 |
|---|---|---|
bb_width |
(bb_upper - bb_lower) / MA | バンド幅(正規化) |
bb_width_percentile |
過去100期間でのbb_widthの百分位 | 現在の幅が歴史的にどの位置か |
bb_squeeze |
1 if bb_width < 過去20期間min × 1.1 | スクイーズ検出フラグ |
bb_expansion_rate |
bb_widthのpct_change | 急拡大検知 |
根拠: 「低ボラ後に急変動が来る」は最も再現性の高い知見(Bollinger Squeeze then Surge)
挿入箇所:
| TF | 関数 | MA列 | 挿入位置 |
|----|------|------|---------|
| D | create_daily_features() | ma20 | BB計算直後 |
| H | create_hourly_features() | ma_24h | BB計算直後 |
| 30M | create_30min_features() | ma_48 | BB計算直後 |
| 15M | create_15min_features() | ma_96 | BB計算直後 |
_add_derivative_features() に3特徴量を追加。
| 追加特徴量 | 計算式 | 意味 |
|---|---|---|
oi_spike |
abs(oi_change) > 5 |
OI急変(5%超) |
fr_oi_combo |
FR極端 AND OIスパイクの同時発生 | 清算カスケード前兆 |
liquidation_risk |
FR極端 AND OIスパイク AND LS比極端 | 最も危険なコンボ |
根拠: 清算カスケードは「OI増加 → FR偏り → 価格圧縮 → カスケード」の明確なシーケンスを踏む
_compute_sample_weights() を変更。
| 項目 | Before | After |
|---|---|---|
| ショック重み | 一律3倍 | 1 + abs(return) / median(abs(return))(変動幅に比例) |
| 上限 | なし | 5倍(np.minimum(proportional_weight, 5.0)) |
| y_train利用 | なし | Close変化率の第1列を使用 |
| フォールバック | — | y_trainがNoneの場合は従来の3倍を維持 |
当初計画の「ボラティリティ分類器」を、より直接的な「振幅予測器」に変更。
[predict_magnitude] abs(close_change_pct)を別途予測
モデル: LightGBM (MAE) — abs値は常に正なので中央値回帰でも有効
[既存予測パイプライン] → pred_pct(方向+振幅)
[振幅補正] final = pred_pct * (blended_mag / current_mag)
blended_mag = current_mag × (1-α) + predicted_mag × α
α = magnitude_blend_ratio (default 0.5)
挿入箇所: model.py → regime_ensemble_predict_multi() 内、高ボラクリッピングの前
| 変更 | 内容 |
|---|---|
| LightGBM | objective='quantile', alpha=0.90/0.10 で上下分位点を予測 |
| 活用 | q_width / hist_iqr = vol_scale として予測値に乗算 |
| 結果 | 単独効果は小さい(MagRatio +0.006、方向精度 +2%) |
挿入箇所: model.py → predict_quantile_width(), _fit_predict_quantile()
config.pyの30M/15M重みを [0.54, 0.46, 0.00] に変更。効果ゼロ — 元の重み0.06が小さすぎた。
ただしCatBoostスキップ最適化(if cat_w > 0: チェック)で速度28%改善。
ヘルパー関数 _add_har_j_features() を作成し、4TF(D/H/30M/15M)全てに適用。
| 追加特徴量 | 意味 |
|---|---|
rv_short |
短期リターン二乗和(実現ボラティリティ) |
rv_long |
長期リターン二乗和 |
bv_short |
短期Bipower Variation(連続成分) |
jump_component |
RV - BV(ジャンプ成分、≥0にクリップ) |
rv_up |
上昇方向のsemivariance |
rv_down |
下落方向のsemivariance |
rv_asymmetry |
rv_down / rv_total(下落リスク指標) |
rv_ratio |
rv_short / rv_long(急変シグナル) |
パラメータ: | TF | window_short | window_long | |----|-------------|-------------| | D | 14 | 60 | | H | 12 | 48 | | 30M | 12 | 48 | | 15M | 24 | 96 |
根拠: HAR-Jモデルは学術的裏付けが最も強い。BTC市場では下落方向のsemivarianceが将来ボラティリティに強い予測力を持つ。
50サンプルでblend_ratio 0.0-1.0を比較。
| ratio | MAE | RMSE | MagR>0.5 |
|---|---|---|---|
| 0.0 | 0.1700 | 0.2498 | 26% |
| 0.3 | 0.1660 | 0.2379 | 54% |
| 0.5 | 0.1668 | 0.2345 | 68% |
| 0.6 | 0.1680 | 0.2343 | 70% |
| 1.0 | 0.1815 | 0.2428 | 84% |
結論: RMSE最小は0.6。MAE/RMSE/MagRatioのバランスから0.6を採用(0.5→0.6に更新)。
30M足の方向精度が39.9%と低い原因: predシグナルが投票から完全除外されていた(#008で変更)。 30M/15M足に限り、predを投票に復帰。
| 設定 | 精度 | 評価件数 | レンジ判定 |
|---|---|---|---|
| A: pred除外(旧) | 54.2% | 24件 | 76% |
| B: pred復帰 | 90.0% | 20件 | 80% |
| C: pred復帰+閾値0.55 | 79.2% | 24件 | 76% |
結論: pred投票復帰で54.2% → 90.0%に劇的改善。direction_pred_in_voting_30M=Trueを採用。
| TF | 指標 | Baseline | P2-1 | 改善 |
|---|---|---|---|---|
| H足 | MagR>0.5 | 4% | 60% | +56pt |
| H足 | MAE | 0.2552 | 0.2803 | +0.025 |
| 15M足 | MagR>0.5 | 14% | 62% | +48pt |
| 15M足 | MAE | 0.2584 | 0.2588 | +0.0004 |
結論: P2-1はH足・15M足でもMagRatioを大幅改善。MAE微増は許容範囲。全TFで有効。
predict_magnitude() は毎予測で実行されて振幅補正に使われるが、予測値自体はDB保存されず捨てられていた。
この予測値を活用し「次の足が通常より大きく動く可能性がある」ことを示す急変動シグナルを出す。
| 変更箇所 | 内容 |
|---|---|
crypto/models.py |
BtcPredictionDetailにpredicted_magnitude(予測振幅%), volatility_alert(0=通常,1=警戒)追加 |
_predict_ohlc/model.py |
predict_v3_multiとregime_ensemble_predict_multiにmagnitude_result引数追加(ミュータブルリストパターン) |
predict_ohlc.py |
_predict_singleでmagnitude取得、直近100足のmedian×2.0閾値で判定、DB保存 |
crypto/views.py |
historical_rows/prediction_rowsにpN_volatility_alertを追加 |
prediction_ohlc.html |
シグナル列3段目に急変動バッジ(通常:グレーフェードアウト、警戒:赤bg-danger) |
閾値判定ロジック:
- pred_mag > median(直近100足のabs(return_1d)) × 2.0 → volatility_alert = 1(警戒)
- それ以外 → volatility_alert = 0(通常)
predict_volatility() 関数をmodel.pyに実装。ATR%を1期先予測するLightGBMモデル。
ただしP2-1(振幅補正)と機能重複のため、regime_ensemble_predict_multiへの統合は保留。
P2-1がMagRatio +149%を達成済みで、追加の独立ボラティリティモデルの限界効果は小さい。
上記「ベースライン指標」セクション参照。
検証方法:
- バックテスト: predict_ohlc -t 30M --backtest --periods 3 --step 1 --save(65分)
- DB実績データ: BtcPredictionDetail の確定済み441件から方向精度/RMSE/MagRatio算出
- スクリプト: test_scripts/009_baseline_metrics.py, test_scripts/009_30m_metrics.py
注意: periods=100は1バーあたり約25分で非現実的。periods=3(65分)を標準条件とする。
P1-1 + P1-2 + P1-3 を全て適用した状態でバックテスト実行。
結果: 特徴量追加だけでは改善しない
| 指標 | ベースライン | Phase 1 | 変化 |
|---|---|---|---|
| 特徴量数 | 96 | 103 (+7) | — |
| MAE +1 Close | 0.33% | 0.34% | +0.01(横ばい) |
| MAE +2 Close | 0.48% | 0.48% | ±0 |
| MAE +6 Close | 0.87% | 0.88% | +0.01(横ばい) |
| 急変動 MagRatio | 0.1891 | 0.1839 | -0.005(横ばい) |
| 急変動 Under率 | 100% | 98.4% | わずかに改善 |
| 急変動 方向一致 | 62.7% | 72.6% | +10pt(データ母集団が異なる※) |
※ベースラインはリアル予測441件、Phase 1はバックテスト7662件(期間が異なるため単純比較不可)
考察: - 特徴量を7つ追加しても、MAEとMagRatioはほぼ変化なし - これは根本原因が損失関数(MAE)にあることを裏付ける - MAE損失はテール事象を構造的に無視するため、急変動の「予兆」特徴量を入れても中央値予測に収束する - Phase 2(損失関数の変更・モデル構造の改善)が必要
50ケース(上位25%高ボラ + ランダム25件)での A/B テスト結果:
| Method | MAE | RMSE | MagRatio | DirAcc |
|---|---|---|---|---|
| baseline | 1.0048 | 1.3575 | 0.1523 | 86.0% |
| magnitude (P2-1) | 0.8740 | 1.1878 | 0.2631 | 84.0% |
| quantile (P2-2) | 0.9851 | 1.3570 | 0.1587 | 88.0% |
| both | 0.8783 | 1.2256 | 0.2518 | 88.0% |
分析: - P2-1(振幅補正)が最も効果的: MagRatio 0.15 → 0.26 (+73%!)、MAE 1.00 → 0.87 (-13%) - P2-2(分位点): MagRatio微増のみ、方向精度+2% - 振幅補正の方向精度は微減(-2%) — 振幅拡大により誤方向時のペナルティも増加するため - Top10ケースでは全て方向は正しく追従、振幅も1.5-5倍に拡大
結論: P2-1を採用、P2-2は保留
ensemble_weights_30M: [0.54, 0.46, 0.00] でフルバックテスト(30M, 7662件)。
結果: CatBoost除外の効果はほぼゼロ - MAE +1: 0.34% (変化なし) - MagRatio: 0.1831 (0.1839 → わずかに低下) - 元の重み0.06(6%)が小さすぎて全体への影響が限定的
CatBoost除外 + P2-1振幅補正の組み合わせで7662件のフルバックテスト。
| 指標 | ベースライン | CatBoost除外 | P2-1有効 | 改善率 |
|---|---|---|---|---|
| MagRatio | 0.1891 | 0.1831 | 0.4698 | +149% |
| RMSE | $490.41 | $490.41 | $468.69 | -4.4% |
| Direction | 38.6% | 38.6% | 39.9% | +1.3pt |
| Under率 | 98.5% | 98.5% | 96.4% | -2.1pt |
| OK(0.8-1.2)率 | 1.4% | 1.4% | 3.6% | +2.5x |
| MAE +1 Close | 0.34% | 0.34% | 0.33% | -3% |
| MAE +6 Close | 0.88% | 0.88% | 0.83% | -6% |
| 実行時間 | 3781s | 3635s | 2710s | -28% |
P2-1の効果は絶大:
- MagRatio 2.5倍改善: 実績の19%追従 → 47%追従
- MAEも全期間で改善(特に+6 bars -6%)
- CatBoostスキップ最適化で速度28%向上(cat_w > 0 チェック追加)
50サンプルでblend_ratio 0.0-1.0を9段階比較。RMSE最小は0.6。 MAE/RMSE/MagRatioのバランスから0.6を採用(config更新済み)。
100サンプルで3設定を比較。pred投票復帰で54.2% → 90.0%に改善。
30M/15M足でdirection_pred_in_voting=Trueを採用。
50サンプルで各TFのP2-1効果を確認。 - H足: MagR>0.5が4% → 60% - 15M足: MagR>0.5が14% → 62% 全TFでP2-1有効を確認。
| ファイル | 変更内容 | Phase | 状態 |
|---|---|---|---|
_predict_ohlc/feature_engineering.py |
BBスクイーズ4特徴量、デリバティブ3特徴量、HAR-J 8特徴量(全4TF) | P1+P2 | 実装済み |
_predict_ohlc/model.py |
サンプル重み比例化、predict_magnitude、predict_quantile_width、predict_volatility、P2統合、CatBoostスキップ最適化 |
P1+P2+P3 | 実装済み |
_predict_ohlc/config.py |
CatBoost除外重み、P2フラグ、magnitude_blend_ratio:0.6、volatility_prediction_enabled、pred投票復帰 |
P2 | 実装済み |
_predict_ohlc/direction_prediction.py |
pred投票復帰(direction_pred_in_votingフラグで制御) |
P2-6 | 実装済み |
crypto/models.py |
BtcPredictionDetailにpredicted_magnitude, volatility_alert追加 |
P4 | 実装済み |
crypto/views.py |
rowデータにpN_volatility_alert追加 |
P4 | 実装済み |
templates/crypto/prediction_ohlc.html |
シグナル列3段目に急変動バッジ追加 | P4 | 実装済み |
test_scripts/009_baseline_metrics.py |
ベースライン指標算出スクリプト | 検証 | 作成済み |
test_scripts/009_30m_metrics.py |
30M足専用指標算出スクリプト | 検証 | 作成済み |
test_scripts/009_p2_effect_test.py |
P2効果測定(50ケースA/B) | 検証 | 作成済み |
test_scripts/009_p2_debug.py |
P2統合デバッグ | 検証 | 作成済み |
test_scripts/009_blend_ratio_optimize.py |
blend_ratio最適化(50サンプルグリッドサーチ) | 検証 | 作成済み |
test_scripts/009_direction_test.py |
方向予測A/Bテスト(pred投票復帰検証) | 検証 | 作成済み |
test_scripts/009_p2_h15m_test.py |
H足/15M足P2-1展開検証 | 検証 | 作成済み |
test_scripts/test_harj.py |
HAR-J特徴量単体テスト | 検証 | 作成済み |
test_scripts/test_harj_integration.py |
HAR-J統合テスト(create_30min_features) | 検証 | 作成済み |