← Issues一覧 完了 暗号資産

Issue #003: 予測アーキテクチャ刷新

報告日

2026-02-22


開発ルール

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

# 精度検証・バックテストは自律実行OK(ユーザーレビュー不要)
# コーディング・設計変更はユーザーレビューを求める

関連issue

002 学習基盤改善  完了
003 予測アーキテクチャ刷新  完了このissue
004 方向予測の強化  active実装中

改修一覧

# 項目 効果 工数 状態
1 OHLC → HLC(Open予測廃止) モデルの焦点を絞る 完了
2 Close+レンジ方式(HLCアーキ変更) H/L精度向上、制約違反解消 完了
3 値の信頼度(モデル合意度) 予測値の確からしさを可視化 完了
4 抵抗帯/支持帯のチャート表示 抵抗帯の可視化 完了
5 config不整合・コード品質の解消 保守性向上、バグ予防 完了
6 データ品質の改善 不正特徴量の防止 完了
7 confirm_predictions の改善 確定精度・性能向上 完了
8 002からの引き継ぎ(パイプライン品質) 予測精度の基盤強化 完了

実施順

0. ベースライン記録  完了
  
#1 OHLC  HLC + #2 Close+レンジ方式 + #5 コード重複解消 + 002#2ループ速度改善  完了
  
#8 002引き継ぎ損失関数統一  アンサンブル重み再最適化)← 完了
  
#5 003-1指摘事項: コード重複config整理  完了
  
#3 値の信頼度  次にやる重みが確定した状態で実装
  
#6 データ品質欠損ローソク足デリバティブ0埋め
  
#4 抵抗帯チャート表示 + #7 confirm改善表示運用系最後に対応

ベースライン記録(完了)

改修前後の精度比較基準として記録済み:

テスト Close MAE High MAE Low MAE
D ultra-fast +1d 2.91% 2.37% 2.69%
D ultra-fast +3d 5.11% 4.76% 5.21%
30M ultra-fast +1bar 0.32% 0.27% 0.30%
30M ultra-fast +2bar 0.44% 0.41% 0.45%
30M ultra-fast +6bar 0.77% 0.76% 0.79%

改修後もultra-fastのMAEはベースラインと完全一致を確認済み。


#1. OHLC → HLC(Open予測廃止)【完了】

実施内容

当初方針との差異

issueは「カラム完全削除」を指示していたが、既存データ保持のため「nullable化 + effective_openプロパティ」で段階的廃止とした。


#2. Close+レンジ方式(HLC予測アーキテクチャ変更)【完了】

実施内容

精度検証結果(改修前後、ultra-fast)

テスト 改修前 改修後 差異
D +1d Close 2.91% 2.91% 完全一致
30M +1bar Close 0.32% 0.32% 完全一致

誤差伝播の評価

未実施(A vs B比較)。現時点ではH/L MAEに顕著な悪化は見られず、優先度を下げている。


#3. 値の信頼度(モデル合意度)

現状

3モデル(XGBoost, LightGBM, CatBoost)の予測値を加重平均して最終予測としているが、 個別予測値は捨てている。モデル間のばらつき情報が失われている。

改修内容

3モデルの個別予測値のばらつき(標準偏差)を「値の信頼度」として算出・保存する。

preds = [pred_xgb, pred_lgbm, pred_cat]
ensemble_pred = xgb_w * pred_xgb + lgbm_w * pred_lgbm + cat_w * pred_cat
model_std = np.std(preds)  # モデル間のばらつき

0-100スコア化

stdをATR基準で正規化し、0-100のスコアにする。

std_pct = model_std / base_price * 100       # ばらつきを価格比%に変換
ratio = 1 - min(std_pct / atr_pct, 1.0)      # ATR比で正規化(0〜1)
value_confidence = round(ratio * 100)         # 0-100スコア

2軸の信頼度

意味 ソース
値の信頼度 予測値がどれだけ確からしいか 3モデルの標準偏差
方向の信頼度 方向感がどれだけ確からしいか テクニカル指標の一致度

DB保存

# BtcPredictionDetail に追加
value_confidence = models.SmallIntegerField("値の信頼度", null=True)  # 0-100スコア
value_confidence_detail = models.JSONField("値の信頼度詳細", null=True)
# JSONの中身(HLCターゲットごと)
{
    "close": {"xgb": 0.12, "lgbm": 0.08, "cat": 0.15, "std": 0.035},
    "high":  {"xgb": 0.45, "lgbm": 0.38, "cat": 0.52, "std": 0.070},
    "low":   {"xgb": -0.30, "lgbm": -0.25, "cat": -0.35, "std": 0.050},
    "atr_pct": 0.8,
    "score": 96
}

注意点

予測モニタリングとの連携

信頼度スコアを導入するなら、以下の監視も合わせて設計すべき: - 信頼度の時系列推移(信頼度が継続的に低下していないか) - 信頼度と実際の予測精度の相関(信頼度が高い予測は実際に精度が高いか) - 予測スキップ回数の追跡(データ取得失敗による無予測期間の検出)

影響範囲


#4. 抵抗帯/支持帯のチャート表示

背景

cluster_r_price / cluster_s_price は既に計算・保存可能だが、表示していない。 クラスタリング方式(_add_cluster_levels)はヒストグラムのビン幅で価格帯を算出しており、ライン(線)ではなくゾーン(帯)のデータが取れる。

改修内容

予測OHLCチャートにクラスタ抵抗帯/支持帯を半透明の帯として重ねる。

データ構造定義

004#3(抵抗帯バッジ表示)でも同じデータを使うため、ここで定義しておく: - クラスタ価格帯: ビン上端/下端、タッチ回数 - views → テンプレートへの受け渡し: コンテキスト変数名、JSON構造

# 例: viewsからテンプレートへ渡す構造
resistance_zones = [
    {"upper": 68500, "lower": 68200, "touches": 5},
    {"upper": 67800, "lower": 67500, "touches": 3},
]
support_zones = [
    {"upper": 66500, "lower": 66200, "touches": 4},
]

計算パス

_add_cluster_levels は feature_engineering で特徴量として計算されるが、 チャート表示用にはゾーン(帯の上端/下端)のデータが必要。

方針: 予測時にゾーン情報を計算し、BtcPredictionDetail にJSON保存する。 views はDBから読むだけ。 - 予測時点の抵抗帯が記録として残る - views に計算ロジックを持たせない

影響範囲


#5. config不整合・コード品質の解消【完了】

003本体のコードレビューにより19項目の指摘を検出(003-1)。 コード重複解消(~755行対象)とconfig集約を実施。

指摘事項の対応判定

# 内容 重要度 判定 備考
#1 ultra-fast信頼度設計 004で対応 null保存を暫定採用
#2 decay_half_life矛盾 解決済み config.py修正済み(99)
#3 Lasso役割再検討 対応不要 Stage1として現行維持、TSS適用済み
#4 regime_ensemble二重管理 解決済み #8で対応済み
#5 特徴量選択 除外→包含 004で対応 004-1 特徴量マトリクスで実施
#6 15M decay 48本 暫定維持 004で検証予定
#7 完了判定基準 対応済み 下記参照
#8 model.py 3モデル学習コピペ 対応済み _fit_predict_ensemble()
#9 model.py regime正規化4箇所 対応済み _normalize_regime()
#10 model.py validation split 2箇所 対応済み _setup_validation_split()
#11 predict_ohlc.py D/W/M初期化重複 対応済み _setup_longer_prediction() + _predict_longer_timeframe()
#12 predict_ohlc.py 親レコード4箇所 対応済み _create_parent_prediction()
#13 predict_ohlc.py 自動実行6箇所 対応済み _run_auto_for_timeframe()
#14 predict_ohlc.py 統計出力3箇所 対応済み _print_backtest_stats()
#15 predict_ohlc.py カラム抽出4箇所 対応済み _extract_column_safe()
#16 data_loader.py intraday 3関数 対応済み _load_intraday_data()
#17 config.py ハードコード未集約 対応済み config.pyに集約
#18 ATR計算の重複実装 対応済み calculate_atr_from_ohlc()
#19 乖離率計算の散在 対応済み calculate_deviation()

完了判定基準(#7 対応)

  1. コード重複解消: ヘルパー関数に抽出し、元の重複箇所がヘルパー呼び出しに置換されていること
  2. Config集約: ハードコード値が config.py に移動し、get_config() 経由で参照されていること
  3. 検証: predict_ohlc -t D --backtest --periods 50 --step 5 のMAEがリファクタ前と一致すること
  4. 回帰なし: 30M/H/D/W/M の全時間軸でバックテストが正常実行できること

実装内容

feature_engineering.py 共通化(~400行削減)

共通関数 統合元 削減行数
_add_technical_indicators_generic() 4つの _add_*_technical_indicators ~100行
_add_higher_timeframe_features_generic() _add_30min/15min_higher_timeframe_features ~200行
_add_rsi_divergence_features() 同上 ~50行
_add_derivative_features() 同上 ~50行

バックテストループ速度改善(002#2引き継ぎ)

predict_v3_multioscillator_values: dict パラメータ追加。 バックテストループ内の df_slice = df_model.iloc[:i+1] を完全排除。

model.py ヘルパー抽出(#8-10, ~168行削減)

ヘルパー関数 統合元 効果
_normalize_regime() 4関数の同一regime正規化 ~28行削減
_setup_validation_split() 2関数のvalidation split ~20行削減
_fit_predict_ensemble() XGB/LGBM/CatBoost学習・予測・加重平均 ~120行削減

predict_ohlc.py ヘルパー抽出(#11-15, ~430行削減)

ヘルパー関数 統合元 効果
_setup_longer_prediction() D/W/M共通初期化 ~150行削減(#11)
_predict_longer_timeframe() W/M共通予測ループ 同上(#11)
_create_parent_prediction() 4箇所のupdate_or_create ~100行削減(#12)
_run_auto_for_timeframe() 6時間軸チェック分岐 ~70行削減(#13)
_print_backtest_stats() 曜日別/セッション別統計 ~60行削減(#14)
_extract_column_safe() 4連続カラム抽出 ~50行削減(#15)

data_loader.py + _utils.py(#16-19, ~157行削減)

ヘルパー関数 対象ファイル 効果
_load_intraday_data() data_loader.py 3関数をラッパー化(~87行削減)
calculate_atr_from_ohlc() _utils.py(新規) ATR計算統合(~50行削減)
calculate_deviation() _utils.py(新規) 乖離率計算統合(~20行削減)

Config集約(#17)

設計決定

# 決定事項 理由
#1 ultra-fast信頼度: null保存(暫定) バックテスト専用。ライブ運用時はtree varianceで代替(004で対応)
#3 Lasso: Stage1として現行維持 Close+レンジ移行後もベース予測として機能。TSS適用済み
#5 特徴量選択: 004で包含ベース化 004-1 特徴量マトリクスと同時に対応。003で変更すると重複
#6 15M decay 48本: 暫定維持 短期予測では直近データ重視で実用上問題なし。004で最適値検証

検証結果

全Phase(A-D)でMAEが一致し、回帰なしを確認:

D足バックテスト(50d, step=5):
  +1d | Close 3.23%  High 2.82%  Low 3.25%
  +3d | Close 5.67%  High 5.31%  Low 5.81%

30M足バックテスト(100bars, step=50):
  +1bar | Close 0.27%  High 0.24%  Low 0.22%
  +2bar | Close 0.38%  High 0.36%  Low 0.38%
  +6bar | Close 0.81%  High 0.82%  Low 0.86%

git diff: +435 / -478(ネット -43行)


#6. データ品質の改善

欠損ローソク足の未検出

サブ日足データ(15M/30M)で取引所ダウンや API 障害によるギャップがあっても、 pct_change(), rolling(), shift() がそのまま計算され、不正な特徴量が生成される。 data_loader.py にもデータ連続性チェックがない。

→ データロード後にタイムスタンプの連続性チェックを追加。ギャップが閾値を超える場合は警告 or 学習から除外

デリバティブ特徴量の 0 埋め問題

# feature_engineering.py — 現状
deriv_cols = ['funding_rate', 'long_short_ratio', ...]
df[col] = df[col].fillna(0)

has_derivative_data インジケータ特徴量を追加し、欠損時は中央値/平均値で補完


#7. confirm_predictions の改善

確定ロジックの脆弱性

# confirm_predictions.py — 現状
return actual.updated_at >= candle_close_time

updated_at がローソク足確定前に更新された場合、未確定データで判定してしまう。 → ローソク足のタイムスタンプ検証を追加

N+1 クエリ問題

_get_atr が各 detail レコードごとに DB クエリを発行。100件の確定処理で100回の個別クエリ。 → ATR 計算を一括プリフェッチに変更


#8. 002からの引き継ぎ(パイプライン品質)【完了】

対応結果

指摘 内容 対応
LassoCV temporal leakage Stage1のLassoCV(cv=5)が標準k-fold TimeSeriesSplitに変更済み
損失関数不一致 CatBoostがRMSE ✅ 全モデルMAEに統一、Optunaで重み再最適化済み
バックテスト fast_mode固定 ライブとの精度乖離 --full-modeオプション追加済み
inf未チェック 除算系特徴量でinf発生 np.isinfnp.nan0変換追加済み

002 残課題(全て反映済み)

項目 002での結果 003での扱い
decay_half_life 99に決着。config.py修正済み 003で99を前提としてパイプライン改修完了
max_depth統一 depth=4に統一 全条件depth=4で運用中
15M足専用 decay_half_life 48本を維持 config参照に統一済み
特徴量削減 分析完了 004で実施予定(004-1 特徴量マトリクス)