← Issues一覧 完了 暗号資産

Issue #004: 方向予測の強化

報告日

2026-02-22


開発ルール

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

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

関連issue

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

完了報告

完了日: 2026-02-23

成果

精度結果

TF 的中率 サンプル数 sideways除外 改善前
D 50.7% 897 51.0% 50.4%
H 39.4% 33 44.8%
30M 58.8% 301 64.1% 54.6%

予測期間別

TF 期間 005後 004時 改善
D +1d 54.1% 52.1% +2.0%
D +3d 47.3% 48.7% -1.4%
30M +1 bars 66.3% 56.9% +9.4%
30M +2 bars 53.5% 54.9% -1.4%
30M +6 bars 56.6% 52.0% +4.6%

Optuna最適化パラメータ(#005)

Parameter D 30M H
rsi_buy 25 40 25
rsi_sell 75 75 65
stoch_buy 15 20 35
stoch_sell 85 70 75
pred_weight 3 1 5
conf_ratio 60 80 70

個別シグナル有効性(30M、301件)

Signal Agree件数 AgHit% 評価
stoch_level 65 69.2% 有効
stoch_cross 67 67.2% 有効
momentum_1h 207 64.3% 有効
rsi_cross50 30 63.3% やや有効
rsi_level 38 63.2% やや有効
macd_hist 166 62.0% やや有効
trend_4h 89 59.6% 微弱

残存課題

  1. D足のDOWNバイアス(予測66% vs 実際51%)
  2. 信頼度と的中率の逆相関
  3. +3d, +2barsの精度低下

改修一覧

# 項目 効果 工数 状態
1 クロスシグナル追加 判定材料が2個→8-9個に 完了
2 方向の信頼度 0-100スコア化 離散5段階→連続スコアに改善 完了
3 シグナルバッジ表示 判定根拠の可視化 完了
4 オシレータ補正見直し 個別ON/OFFで検証可能に 基盤完了(enabledフラグ追加済み、検証未実施)
5 特徴量の絞り込み 次元の呪い対策 Phase1完了(Zero重要度9個削除済み)
6 target_price 計算式の統一 predicted/actual の矛盾解消 部分解決(003でcalculate_targetをbase_price基準に統一済み)
7 session 定義の統一 + バグ修正 us_session デッドコード除去、定義一元化 完了

実施順(実績)

Step 1: 基盤修正
  #7 session定義統一 → config.pyに一元化、feature_engineering 3箇所 + predict_ohlc backtest修正
  004-1#8 RSI計算統一 → _utils.py に共通 calculate_rsi(EWM方式) 追加
  
Step 2: 核心(#1 + #2 統合)
  8-9シグナル判定(pred, rsi_level, stoch_level, macd_hist, stoch_cross, rsi_cross50, macd_cross + TF固有
  連続スコア(0-100): signal_score(0-70) + strength_score(0-30)
  30M多数決モード廃止、全TF統一方式
  
Step 3: #3 バッジ表示
  prediction_ohlc.html + prediction_detail.html にシグナルバッジ追加
  
Step 4: #4 + #5
  オシレータ補正: 6ルール個別ON/OFFフラグ追加
  特徴量削減: Phase1 Zero重要度9個をexclude追加
  
Step 5: #6 命名統一 → コード変更不要(003で対応済み)

残作業(後続タスク)

項目 内容
#4 検証 オシレータ補正ルール個別のバックテスト検証
#5 Phase 2-3 Low重要度の選択的削除、相関特徴量統合
レンジ判定 予測変化率から上昇/レンジ/下落ラベル付与(#2仕様に記載、未実装)
抵抗帯バッジ R/S距離バッジ表示(#3仕様に記載、未実装)

#1. クロスシグナル追加

現状の方向判定の補助条件

H/15M足: | 指標 | 買い条件 | 売り条件 | |------|---------|---------| | Stoch K (14期間) | K < 25 | K > 75 | | RSI (14期間) | RSI < 35 | RSI > 65 |

日足: | 指標 | 買い条件 | 売り条件 | |------|---------|---------| | Stoch K (14期間) | K < 30 | K > 70 | | RSI (14期間) | RSI < 35 | RSI > 65 |

30M足(多数決モード: 変化率 < 0.05%時): | 指標 | 買い条件 | 売り条件 | |------|---------|---------| | RSI (28本) | RSI < 40 | RSI > 60 | | Stoch K | K < 30 | K > 70 | | MACD hist | hist > 0 | hist < 0 | | 4Hトレンド | trend > 0 | trend <= 0 | | 1Hモメンタム | momentum > 0 | momentum < 0 | | 連続方向 | >= 2本陽線 | <= -2本陰線 |

問題

計算済みだが方向判定に未使用のクロス指標

クロス指標 特徴量名 買い 売り
MA ゴールデン/デッドクロス ma_golden_cross / ma_death_cross MA20>MA50転換 MA20<MA50転換
Stoch %K/%D クロス stoch_cross_up / stoch_cross_down K>D (K<30圏) K70圏)
RSI 50ライン クロス rsi_cross_50_up / rsi_cross_50_down RSI>50転換 RSI<50転換
MACD/シグナル クロス macd_cross_up / macd_cross_down MACD>Signal転換 MACD<Signal転換
DI クロス(ADX) di_cross_up / di_cross_down +DI > -DI転換 -DI > +DI転換
RSI 30/70 クロス rsi_cross_30_up / rsi_cross_70_down 30上抜け 70下抜け

改修内容

上記クロス指標を方向予測の補助条件に追加する。 バックテストでシグナル別の的中率を確認し、有効なものを採用。


#2. 方向の信頼度 0-100スコア化 + レンジ判定

003#3「値の信頼度」とは別軸。003=モデル合意度(3モデルの予測値のばらつき)、004=シグナル合意度(テクニカル指標の一致度)。両方必要。

現状の問題

CONFIDENCE_MAP で条件数→信頼度%に変換しているが、5段階の離散値(55/65/75/85/92)に飛ぶだけ。 表示側ではさらに高/中/低の3段階に丸めており、情報が大幅に失われている。

改修方針: 連続的な0-100スコアに変更

シグナル一致数だけでなく、各シグナルの強度も加味して連続スコアを算出する。

# 案: シグナル加点 + 強度ボーナス(base_scoreなし)
signal_score = agreement_ratio * 70      # 一致率0〜1 → 0〜70点
strength_score = abs(change_pct) * k     # 変化率の大きさ → 0〜30点
confidence = min(100, signal_score + strength_score)

設計判断: base_score = 0 とする。シグナルが全く合致しない場合は0点が自然。 agreement_ratio の分母は #1 で採用されたシグナル総数に依存する(#1 → #2 の順で実施)。

抵抗帯/支持帯との距離は信頼度に混ぜない。「方向の確かさ」と「どこまで行けるか」は別の情報。 抵抗帯/支持帯は 003#4(チャート表示)と #3(バッジ表示)で独立して可視化し、人間の判断材料として提供する。

レンジ判定(島田メモより)

方向の信頼度とは別に、予測変化率から上昇/レンジ/下落のラベルを付与する。

判定 条件案
上昇 予測変化率 > +閾値
レンジ 予測変化率が ±閾値 以内
下落 予測変化率 < -閾値

→ 閾値はバックテストで最適値を探る。表示例: 「上昇 方向:82」「レンジ 方向:35」「下落 方向:91」

表示: 両方0-100の数値

信頼度 ラベル ソース 表示例
値の信頼度(003#3) 3モデルの予測値ばらつき 値: 68
方向の信頼度(004#2) 方向 シグナル一致度 方向: 82

#3. シグナルバッジ表示

各テクニカル指標を常にバッジで表示し、シグナル発生状況を可視化する。

状態 表示
シグナルなし グレーバッジ(指標名のみ)
買いシグナル 緑バッジ(指標名 + 値)
売りシグナル 赤バッジ(指標名 + 値)

表示候補:

オシレータ系: | バッジ名 | 買い | 売り | |---------|------|------| | RSI | < 35 | > 65 | | Stoch | K < 25 | K > 75 |

クロス系: | バッジ名 | 買い | 売り | |---------|------|------| | MA GC/DC | ゴールデンクロス | デッドクロス | | MACD GC/DC | MACD > Signal転換 | MACD < Signal転換 | | Stochクロス | K > D (底値圏) | K < D (天井圏) | | RSI 50 | 50上抜け | 50下抜け |

上位足: | バッジ名 | 買い | 売り | |---------|------|------| | 4Hトレンド | 上昇 | 下降 | | 1Hモメンタム | 正 | 負 |

シグナル総数と反応数の表示(島田メモより)

「8シグナル中5個が買い」のように、判定に使われるシグナルの総数と反応状況を表示する。

抵抗帯/支持帯の距離表示(島田メモより)

予測High/Lowから最寄りの1つずつをバッジ表示する。トレードで意識するのは最初にぶつかる壁なので、複数表示は不要。

既存のクラスタリング方式(_add_cluster_levels)がヒストグラムのビン幅で価格帯を算出しているため、ライン→帯への変更はデータ側の変更不要。

バッジ 意味
R: +1.0%〜+1.5% 予測Highから最寄りの抵抗帯までの距離(ゾーン)
S: -0.5%〜-0.8% 予測Lowから最寄りの支持帯までの距離(ゾーン)

チャート上では半透明の帯として描画(003#4 と連携)。

将来的に、帯が厚い(タッチ回数が多い)ほど突破しにくいことを示す強度表示も検討


#4. オシレータ補正見直し

max_depth統一 → 002で完了済み

002にて以下を実施・検証済み: - regime_ensemble 高ボラ: depth 6→4 - _ensemble_residual_predict 高ボラ: depth 6→4, 通常: depth 6→5 - 精度同等、過学習リスク低減を確認

残作業: オシレータ補正ルールの見直し

8種のオシレータ補正ルールの有効性をバックテストで検証し、効果の薄いルールを削除する。

過学習リスク要因(参考)

要素 現状 問題
~~ツリー深さ~~ ~~高ボラ時 depth=6~~ ~~002で depth=4 に修正済み~~
3段階パイプライン Lasso→残差→補正 各段階の誤差が累積
オシレータ補正 8種類のルールベース 過剰適合しやすい
サンプル重み 4種の掛け算 有効サンプル数が減少

#5. 特徴量の絞り込み

分析は完了済み(poetry run python manage.py tool_analyze_features で実施)。 詳細データは 004-3_特徴量分析結果.md を参照。

分析結果サマリー

時間軸 総数 削除候補 削除率 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%

全時間軸共通でZero重要度(即時削除可能)

rsi_oversold, rsi_overbought, stoch_oversold, stoch_overbought, strong_trend, asia_session, europe_session, us_session, is_weekend → バイナリフラグは連続値特徴量と重複しており不要

削除フェーズ

Phase 内容 リスク
Phase 1 Zero重要度の一括削除
Phase 2 Low重要度(1-5)の選択的削除(ultra-fastで検証)
Phase 3 相関特徴量の統合(MACD系, return系, dist系) 中(003と同時)

注意: 日足はTop20カバー率40.8%と低く重要度が分散 → 削減は慎重に


#6. target_price 計算式の統一【部分解決】

003での対応

残課題


#7. session 定義の統一 + バグ修正

バグ: us_session の dead code

# feature_engineering.py
df['us_session'] = ((hours >= 16) | (hours < 0)).astype(int)

hours < 0df.index.hour(0-23)に対して常に False。実質 hours >= 16 のみで動作。

不一致: session 定義が feature_engineering と backtest で異なる

feature_engineering backtest (predict_ohlc)
米国 hours >= 16 UTC 14 <= hour < 21 UTC

対応方針


指摘事項(旧004-1)

報告日: 2026-02-22

# 対象 種別 重要度 対応状況
1 #7 session定義 — #1の前に解決必要 依存関係漏れ ✅ 対応済み config.pyに一元化
2 #1 クロスシグナル — timeframe別の閾値差異が未定義 設計漏れ ✅ 部分対応 RSI列名はTF別、Stoch/MACD閾値は全TF共通
3 #2 スコア化 — 003#3との表示統合が未設計 設計漏れ ✅ 対応済み UIに方向/値の両信頼度表示
4 #5 特徴量削減 — 003#5(包含ベース化)との順序依存 依存関係漏れ ✅ 対応済み Phase1実施済み
5 #1 クロスシグナル — 30M足だけ多数決モードがある非対称性 設計懸念 ✅ 対応済み 30M多数決廃止、全TF統一方式
6 #3 バッジ表示 — データの受け渡し設計が未定義 設計漏れ ✅ 対応済み direction_conditionsのJSON構造確定
7 #4 オシレータ補正 — 3段階パイプライン自体の要否 設計判断 ✅ 対応済み enabledフラグ追加済み
8 direction_prediction.py — RSI計算方式がfeature_engineeringと異なる 実装不整合 ✅ 対応済み calculate_rsi()をEWM統一
9 direction_prediction.py — sidewaysパラメータのハードコード重複 不整合 ✅ 対応済み config.py参照で統一