2026-02-22
# コマンド実行は必ず poetry run を使うこと
poetry run python manage.py predict_ohlc ...
poetry run python manage.py confirm_predictions ...
# ジョブを走らせる前にユーザーに確認すること(バックテスト実行中の場合があるため)
# 精度検証・バックテストは自律実行OK(ユーザーレビュー不要)
# コーディング・設計変更はユーザーレビューを求める
002 学習基盤改善 ← このissue(最優先)
003 予測アーキテクチャ刷新(HLC化, Close+レンジ, 信頼度)
004 方向予測の強化(クロスシグナル, レーティング, バッジ, チューニング)
実施順: 002 → 003 → 004
| # | 項目 | 効果 | 工数 |
|---|---|---|---|
| 1 | ultra-fastバックテストモード新設 | 検証速度28倍 | 小 |
| 2 | バックテストループ速度改善 | 通常モードも2-5倍高速化 | 中 |
| 3 | early_stopping + validation split | 過学習防止。全改修の土台 | 小 |
| 4 | 曜日・時間帯別の精度分析 | 精度の弱点を特定、信頼度調整 | 小 |
#1 ultra-fast実装(検証基盤。これがないと始まらない)
↓
#3 early_stopping + validation split(最もインパクトが大きい)
→ ultra-fastで効果検証
→ 今の精度がモデルの実力か過学習の結果かを切り分ける
↓
#4 曜日・時間帯別精度分析(#3と同時に結果を確認)
↓
#2 ループ速度改善(issue 003のコード書き換え時に同時実施が効率的)
現状の1予測ポイントあたりのmodel.fit回数:
3モデル(XGB/LGBM/Cat) × 4ターゲット(OHLC) × 2段階(Lasso+残差) = 24回
+ Lasso 4回 = 28回
30M足200期間・step1で約3時間。改修ごとにこれでは検証不能。
--ultra-fast オプション新設# ultra-fastバックテスト(傾向確認用、精度は落ちる)
poetry run python manage.py predict_ohlc -t 30M --backtest --periods 200 --ultra-fast --save
# 通常バックテスト(最終検証用)
poetry run python manage.py predict_ohlc -t 30M --backtest --periods 50 --step 10 --save
| 項目 | 通常 | fast_mode | ultra-fast |
|---|---|---|---|
| モデル | XGB+LGBM+CatBoost | 同左 | LightGBMのみ |
| ターゲット | OHLC 4値 | 同左 | Closeのみ |
| Stage 1 (Lasso) | あり | あり | 省略 |
| Stage 3 (補正) | あり | あり | 省略 |
| n_estimators | 150 | 55 | 20 |
| max_depth | 4 | 4 | 3 |
| fit回数/ポイント | 28回 | 28回 | 1回 |
→ 1ポイントあたり28回 → 1回 = 約28倍高速
| モード | 用途 | 所要時間(30M/200期間) |
|---|---|---|
--ultra-fast |
改修の方向性確認、A/Bテスト | 約5-10分 |
--backtest --step 10 |
通常検証 | 約30分 |
--backtest --step 1 |
最終精度検証 | 約3時間 |
Closeのみ予測し、H/Lはルールベースで概算する:
predicted_close = base_price * (1 + pred_close_pct / 100)
predicted_high = predicted_close * (1 + atr_pct * 0.5 / 100) # ATRベースの概算
predicted_low = predicted_close * (1 - atr_pct * 0.5 / 100)
base_priceとは: 予測起点のBTC価格(=直前足の終値)。モデルは変動率(%)で予測するため、実価格への変換起点として使う。BtcPrediction.base_priceに保存されている。 Openは予測しないため、表示側でOpen値が必要な場合はbase_price(直前終値≒次の始値)をそのまま使う。
1. ultra-fast で A/B テスト(5-10分)→ 方向性の判断
2. step=10 で通常検証(30分)→ パラメータ調整
3. step=1 で最終確認(3時間)→ 本番投入の判断
predict_ohlc.py: --ultra-fast オプション追加、_run_backtest_for_timeframe に分岐model.py: ultra-fast用の軽量予測関数追加特徴量のnumpy化(X_all = df_model[feature_cols].values)は実装済み。
残るボトルネックは以下の2つのDataFrameスライス:
df_slice = df_model.iloc[:i+1] — predict_v3_multiにDFを渡している(オシレータ値1行のため)df_for_direction = df_copy.loc[:current_idx] — 方向予測にDFを渡している# 現状: df_sliceからオシレータ値を取得(ループごとにDFスライス発生)
df_slice = df_model.iloc[:i+1]
pred_pct_arr = predict_v3_multi(df_slice, X_train, ...)
# 改善: オシレータ値を事前にnumpy化し、スカラーで渡す
rsi_all = df_model['rsi_14'].values # ループ前に1回
pred_pct_arr = predict_v3_multi(X_train, ..., oscillator_values={'rsi_14': rsi_all[i]})
# 現状: 方向予測にDataFrameを渡している
df_for_direction = df_copy.loc[:current_idx] # 重いコピー
# 改善: 必要なのはRSI, Stoch K等の最新値のみ
# → ループ前に各指標の配列を準備、ループ内はインデックスアクセスのみ
bulk_create で一括保存に変更。
A〜Cは issue 003 の改修(HLC化、Close+レンジ方式)と同時に実施するのが効率的。 コードを書き換えるタイミングで一緒にnumpy化する。
現状のモデル構成:
Stage 1: LassoCV(トレンド系特徴量のみ)→ ベース予測
Stage 2: XGB/LGBM/CatBoostアンサンブル(全特徴量)→ 残差予測
Stage 3: オシレータ補正(ルールベース8種)→ 最終調整
| 要素 | 現状 | 問題 |
|---|---|---|
| early_stopping | なし | 学習が止まらず訓練データに適合し続ける |
| validation split | なし | 訓練データの性能しか見ていない |
これを入れるだけで精度が変わる可能性がある。 今の予測精度がモデルの実力か過学習の結果かを切り分ける、全改修の土台。
# 時系列なので末尾をvalidationに使う
val_size = max(int(len(X_train) * 0.1), 20)
X_val, y_val = X_train[-val_size:], y_t[-val_size:]
X_train_fit, y_train_fit = X_train[:-val_size], y_t[:-val_size]
# 各モデルにearly_stopping_rounds=10を追加
| パラメータ | 通常 | 高ボラ | fast_mode | 備考 |
|---|---|---|---|---|
| n_estimators | 150 | 100 | 55/40 | |
| max_depth | 4 | ~~6~~ → 4 | 4/3 | 002で修正 |
| learning_rate | 0.04 | 0.02 | 0.04 |
アンサンブル重み(Optuna最適化済み): XGB 0.21 / LGBM 0.20 / CatBoost 0.59
解決済み: 002検証で99が全指標で改善 → config.pyを99に修正。
| 箇所 | 修正前 | 修正後 |
|---|---|---|
| config.py | decay_half_life: 180 |
decay_half_life: 99 |
| model.py コメント | 「Optuna: 180 → 99」 | 変更なし(整合) |
| model.py fallback | get_config('decay_half_life', 99) |
変更なし(整合) |
early_stoppingの結果次第で、003のアーキ変更前にこれらを先行実施すべきか判断する: - 004#4: max_depth統一(高ボラ時 depth=6 → 4) - 004#5: 特徴量の絞り込み(30M/15M足で100〜140特徴量は過剰)
model.py: 各モデルのfit呼び出しにearly_stopping追加時間特徴量(hour_sin/cos, day_of_week, session flags等)は学習に組み込み済み。 しかし「曜日・時間帯ごとにどれだけ精度が違うか」の分析手段がない。
| 区分 | 想定 | 理由 |
|---|---|---|
| 平日 | 精度高め | 機関投資家参加、流動性高、テクニカルが効きやすい |
| 週末 | 精度低め | 薄商い、突発的な動き |
| 月曜 | 週末分の調整 | 窓開け的な動き |
| アジア時間 (9-17 JST) | 安定 | ボラ低め |
| 欧州時間 (17-23 JST) | やや不安定 | ボラ上昇 |
| 米国時間 (23-6 JST) | 最も不安定 | 最大ボラ、マクロ指標影響 |
[MAE by Day of Week]
Mon: Close 1.2% High 1.5% Low 1.4% (n=120)
Tue: Close 0.9% High 1.1% Low 1.0% (n=118)
...
Sat: Close 2.1% High 2.8% Low 2.5% (n=95)
Sun: Close 1.8% High 2.3% Low 2.2% (n=98)
[MAE by Session]
アジア (9-17 JST): Close 1.0% High 1.2% Low 1.1% (n=200)
欧州 (17-23 JST): Close 1.3% High 1.6% Low 1.5% (n=180)
米国 (23-6 JST): Close 1.5% High 1.9% Low 1.8% (n=210)
深夜 (6-9 JST): Close 1.1% High 1.3% Low 1.2% (n=80)
[Direction Hit Rate by Day of Week]
Mon: 62% Tue: 58% Wed: 55% ...
_run_backtest のループ内で曜日・時間帯をキーにした辞書に結果を蓄積_compute_sample_weights で15M足は decay_half_life_30m(48本)を流用decay_half_life_15m の導入を判断predict_ohlc.py: _run_backtest にサマリー集計・出力追加| # | 項目 | 状態 | 備考 |
|---|---|---|---|
| 1 | ultra-fastバックテストモード | 完了 | 30倍以上の高速化を確認 |
| 2 | バックテストループ速度改善 | 完了 | 003 Phase1にて同時実施(oscillator_valuesスカラー渡し) |
| 3 | early_stopping + validation split | 完了 | 両アンサンブル関数に適用 |
| 4 | 曜日・時間帯別精度分析 | 完了 | 曜日別+セッション別を表示 |
| モード | Close MAE | 所要時間 |
|---|---|---|
| ultra-fast (step=5, 449samples) | 3.06% | 18秒 |
| 通常 + early_stopping (step=10, 225samples) | 3.26% | 1147秒 |
→ ultra-fastは精度を大きく損なわず30倍以上高速。パラメータ検証に十分使える。
| 曜日 | Close MAE | 傾向 |
|---|---|---|
| 金 | 3.75% | 最良 |
| 土 | 3.46% | 最良(想定に反する) |
| 月 | 4.66% | 最悪(週末分の調整の影響か) |
| 木 | 4.07% | やや悪い |
→ 想定では「週末=精度低い」だったが、実際は月曜が最も精度が低い。 週末の動きは小さく予測しやすいが、週明けの反動が読みにくいと推測。
| セッション | Close MAE | 想定通り? |
|---|---|---|
| アジア (9-17 JST) | 1.25% | 想定通り(安定) |
| 深夜 (6-9 JST) | 1.07% | 想定以上に安定 |
| 欧州 (17-23 JST) | 1.63% | 想定通り(やや不安定) |
| 米国 (23-6 JST) | 1.77% | 想定通り(最も不安定) |
→ アジア時間と深夜帯は予測精度が高く、米国時間が最も低い。信頼度調整の材料になる。
| 補足課題 | 結果 | 対応 |
|---|---|---|
| decay_half_life 180 vs 99 | 99が全指標で改善 (+1d Close: 3.06→3.02%) | config.pyを99に修正。矛盾解消 |
| max_depth統一 (高ボラ6→4) | 精度同等 (+1d: 3.27% vs 3.26%) | 高ボラ時をdepth=4に修正。regime_ensemble_predict_multiは全条件depth=4、_ensemble_residual_predictは高ボラ=4/通常=5を維持 |
| 15M足専用 decay_half_life | 48本(12h)を維持 (96本と差なし) | decay_half_life_15mをconfig追加、値は48 |
| 特徴量分析 | 全時間軸で36-58%が削除候補 | 分析結果を004-1に記録 |
| 時間軸 | 総数 | 削除候補 | Top20カバー率 |
|---|---|---|---|
| 15M | 108 | 59 (55%) | 64.2% |
| 30M | 106 | 61 (58%) | 59.6% |
| H | 58 | 21 (36%) | 68.8% |
| D | 129 | 65 (50%) | 40.8% |
→ バイナリフラグ系(rsi_oversold, stoch_overbought, asia_session等)は全時間軸でゼロ。
連続値特徴量(RSI数値, hour_sin/cos等)と重複しており不要。
詳細は 004-1_特徴量分析結果.md 参照。
002で整備した検証基盤(ultra-fast、early_stopping、曜日/時間帯分析)を使って、 003(予測アーキテクチャ刷新: HLC化、Close+レンジ方式)の効果を効率的に検証できる体制が整った。
002レビュー指摘(Lasso temporal leakage, 損失関数不一致, fast_mode固定, inf未チェック)は003に引き継ぎ済み。