← Issues一覧 完了 暗号資産

Issue #002: 学習基盤改善

報告日

2026-02-22


開発ルール

# コマンド実行は必ず poetry run を使うこと
poetry run python manage.py predict_ohlc ...
poetry run python manage.py confirm_predictions ...

# ジョブを走らせる前にユーザーに確認すること(バックテスト実行中の場合があるため)
# 精度検証・バックテストは自律実行OK(ユーザーレビュー不要)
# コーディング・設計変更はユーザーレビューを求める

関連issue

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. ultra-fastバックテストモード

問題: バックテストが遅すぎて改修のイテレーションが回らない

現状の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

ultra-fastの内容

項目 通常 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時間

H/Lの扱い(ultra-fast時)

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時間)→ 本番投入の判断

影響範囲


#2. バックテストループの速度改善

問題: ループ内のDataFrameスライスがボトルネック

特徴量のnumpy化(X_all = df_model[feature_cols].values)は実装済み。 残るボトルネックは以下の2つのDataFrameスライス:

  1. df_slice = df_model.iloc[:i+1] — predict_v3_multiにDFを渡している(オシレータ値1行のため)
  2. df_for_direction = df_copy.loc[:current_idx] — 方向予測にDFを渡している

改修内容

A. predict_v3_multiのオシレータスライス排除(効果: 大)

# 現状: 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]})

B. 方向予測のDataFrameスライス排除(効果: 中)

# 現状: 方向予測にDataFrameを渡している
df_for_direction = df_copy.loc[:current_idx]   # 重いコピー

# 改善: 必要なのはRSI, Stoch K等の最新値のみ
# → ループ前に各指標の配列を準備、ループ内はインデックスアクセスのみ

C. バッチDB保存の最適化(効果: 小)

bulk_create で一括保存に変更。

適用タイミング

A〜Cは issue 003 の改修(HLC化、Close+レンジ方式)と同時に実施するのが効率的。 コードを書き換えるタイミングで一緒にnumpy化する。


#3. early_stopping + validation split

問題: 過学習しているかどうか分からない

現状のモデル構成:

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

検証方法

補足: decay_half_life の矛盾解決 ✅

解決済み: 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) 変更なし(整合)

補足: 004#4/#5 前倒し判断

early_stoppingの結果次第で、003のアーキ変更前にこれらを先行実施すべきか判断する: - 004#4: max_depth統一(高ボラ時 depth=6 → 4) - 004#5: 特徴量の絞り込み(30M/15M足で100〜140特徴量は過剰)

影響範囲


#4. 曜日・時間帯別の精度分析

背景

時間特徴量(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%  ...

実装方針

補足: 15M足専用パラメータの検討

将来拡張

影響範囲


総合評価

実施状況

# 項目 状態 備考
1 ultra-fastバックテストモード 完了 30倍以上の高速化を確認
2 バックテストループ速度改善 完了 003 Phase1にて同時実施(oscillator_valuesスカラー渡し)
3 early_stopping + validation split 完了 両アンサンブル関数に適用
4 曜日・時間帯別精度分析 完了 曜日別+セッション別を表示

検証結果

ultra-fast vs 通常モード(日足、step=5/10)

モード Close MAE 所要時間
ultra-fast (step=5, 449samples) 3.06% 18秒
通常 + early_stopping (step=10, 225samples) 3.26% 1147秒

→ ultra-fastは精度を大きく損なわず30倍以上高速。パラメータ検証に十分使える。

曜日別精度(日足 ultra-fast)

曜日 Close MAE 傾向
3.75% 最良
3.46% 最良(想定に反する)
4.66% 最悪(週末分の調整の影響か)
4.07% やや悪い

→ 想定では「週末=精度低い」だったが、実際は月曜が最も精度が低い。 週末の動きは小さく予測しやすいが、週明けの反動が読みにくいと推測。

時間帯別精度(時間足 ultra-fast)

セッション 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 参照。

003への引き継ぎ

002で整備した検証基盤(ultra-fast、early_stopping、曜日/時間帯分析)を使って、 003(予測アーキテクチャ刷新: HLC化、Close+レンジ方式)の効果を効率的に検証できる体制が整った。

2(ループ速度改善)は003 Phase1にて実施済み。

002レビュー指摘(Lasso temporal leakage, 損失関数不一致, fast_mode固定, inf未チェック)は003に引き継ぎ済み。