2026-02-22
# コマンド実行は必ず poetry run を使うこと
poetry run python manage.py predict_ohlc ...
# 精度検証・バックテストは自律実行OK(ユーザーレビュー不要)
# コーディング・設計変更はユーザーレビューを求める
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はベースラインと完全一致を確認済み。
predicted_open はnullable化(段階的廃止、既存データ保持)BtcPredictionDetail.effective_open プロパティ追加: predicted_open ?? prediction.base_priceviews.py 4箇所で d.effective_open に統一predict_ohlc.py: target_open = base_price を設定(Open予測モデルは不使用)direction_prediction.py: predicted_open 引数は後方互換で残すが内部で無視、ref_price = base_price に統一confirm_predictions.py: detail.effective_open を使用0010_predicted_open_nullableissueは「カラム完全削除」を指示していたが、既存データ保持のため「nullable化 + effective_openプロパティ」で段階的廃止とした。
predict_range() を model.py に追加(LightGBMのみ、軽量レンジ予測)_predict_single(): Close予測(predict_v3_multi, 1ターゲット) + Range予測(predict_range, 2ターゲット)pred_high = pred_close * (1 + max(0, upper_range) / 100) — クリッピングでH>C>L構造保証apply_ohlc_constraints 呼び出し全削除(構造的に不要)| テスト | 改修前 | 改修後 | 差異 |
|---|---|---|---|
| D +1d Close | 2.91% | 2.91% | 完全一致 |
| 30M +1bar Close | 0.32% | 0.32% | 完全一致 |
未実施(A vs B比較)。現時点ではH/L MAEに顕著な悪化は見られず、優先度を下げている。
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) # モデル間のばらつき
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スコア
| 軸 | 意味 | ソース |
|---|---|---|
| 値の信頼度 | 予測値がどれだけ確からしいか | 3モデルの標準偏差 |
| 方向の信頼度 | 方向感がどれだけ確からしいか | テクニカル指標の一致度 |
# 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
}
信頼度スコアを導入するなら、以下の監視も合わせて設計すべき: - 信頼度の時系列推移(信頼度が継続的に低下していないか) - 信頼度と実際の予測精度の相関(信頼度が高い予測は実際に精度が高いか) - 予測スキップ回数の追跡(データ取得失敗による無予測期間の検出)
model.py: 個別予測値とstdを返すpredict_ohlc.py: スコア算出・DB保存models.py: value_confidence + value_confidence_detail 追加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 に計算ロジックを持たせない
templates/crypto/prediction_ohlc.html: チャートに半透明帯を描画crypto/views.py: クラスタ価格帯を計算してコンテキストに渡す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() |
config.py に移動し、get_config() 経由で参照されていることpredict_ohlc -t D --backtest --periods 50 --step 5 のMAEがリファクタ前と一致すること| 共通関数 | 統合元 | 削減行数 |
|---|---|---|
_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行 |
predict_v3_multi に oscillator_values: dict パラメータ追加。
バックテストループ内の df_slice = df_model.iloc[:i+1] を完全排除。
| ヘルパー関数 | 統合元 | 効果 |
|---|---|---|
_normalize_regime() |
4関数の同一regime正規化 | ~28行削減 |
_setup_validation_split() |
2関数のvalidation split | ~20行削減 |
_fit_predict_ensemble() |
XGB/LGBM/CatBoost学習・予測・加重平均 | ~120行削減 |
| ヘルパー関数 | 統合元 | 効果 |
|---|---|---|
_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) |
| ヘルパー関数 | 対象ファイル | 効果 |
|---|---|---|
_load_intraday_data() |
data_loader.py | 3関数をラッパー化(~87行削減) |
calculate_atr_from_ohlc() |
_utils.py(新規) | ATR計算統合(~50行削減) |
calculate_deviation() |
_utils.py(新規) | 乖離率計算統合(~20行削減) |
sideways_range_ratio: 0.45, sideways_change_pct: 0.1 → config.pyatr_periods: {15M:48, 30M:24, H:12, D:14} → config.pyget_config() 参照| # | 決定事項 | 理由 |
|---|---|---|
| #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行)
サブ日足データ(15M/30M)で取引所ダウンや API 障害によるギャップがあっても、
pct_change(), rolling(), shift() がそのまま計算され、不正な特徴量が生成される。
data_loader.py にもデータ連続性チェックがない。
→ データロード後にタイムスタンプの連続性チェックを追加。ギャップが閾値を超える場合は警告 or 学習から除外
# feature_engineering.py — 現状
deriv_cols = ['funding_rate', 'long_short_ratio', ...]
df[col] = df[col].fillna(0)
funding_rate = 0 は「中立ファンディング」という実際の市場情報。「データ欠損」と区別できないlong_short_ratio = 0 は「ショート極端偏り」を意味してしまう→ has_derivative_data インジケータ特徴量を追加し、欠損時は中央値/平均値で補完
# confirm_predictions.py — 現状
return actual.updated_at >= candle_close_time
updated_at がローソク足確定前に更新された場合、未確定データで判定してしまう。
→ ローソク足のタイムスタンプ検証を追加
_get_atr が各 detail レコードごとに DB クエリを発行。100件の確定処理で100回の個別クエリ。
→ ATR 計算を一括プリフェッチに変更
| 指摘 | 内容 | 対応 |
|---|---|---|
| LassoCV temporal leakage | Stage1のLassoCV(cv=5)が標準k-fold |
✅ TimeSeriesSplitに変更済み |
| 損失関数不一致 | CatBoostがRMSE | ✅ 全モデルMAEに統一、Optunaで重み再最適化済み |
| バックテスト fast_mode固定 | ライブとの精度乖離 | ✅ --full-modeオプション追加済み |
| inf未チェック | 除算系特徴量でinf発生 | ✅ np.isinf→np.nan→0変換追加済み |
| 項目 | 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 特徴量マトリクス) |