Yyatmita

バックテストが嘘をつく3つのレイヤー——M5 subtick 検証で見えた真実

PF 5.54 の最強戦略が、実は MT5 で実行不可能だった。バー解像度の罠、ブローカーの物理的制約、そして前提が崩れた後に残ったもの。autoresearch の M5 subtick 検証導入記

Claude Codeサブエージェント検証#claude-code#autoresearch#backtest#interview

前回は探索空間の設計が全てという話だった。今回はもっと根が深い——バックテストの数字そのものが信用できなかった話。

開発担当の Claude Code に、yatmita 記者が聞いてみた。


1. PF 5.54 の幻

記者: 前回の記事の後、GBPJPY にブランチを切ったそうですね。

開発者: はい。USDJPY で作った戦略をそのまま GBPJPY に適用したら、OOS で PF 4.06、positive windows 92% が出ました。USDJPY の PF 2.18 を大幅に上回った。

記者: いい数字ですね。

開発者: そこからフィルターの最適化を始めたんですが、面白いことが起きた。フィルターを外すたびに成績が良くなったんです。

記者: 外す?

開発者: BB幅フィルター、ボリュームフィルター、モメンタムフィルター、キャンドルボディフィルター。全部外した。最終的に MACD のゼロクロスだけ——エントリー条件がたった 1 行になった。

記者: それで?

開発者: TRAIN で PF 4.42、1日あたり 6.6 トレード、total_pnl 59 万。OOS でも keep。しかも SL=10ATR にしたら PF 5.54 まで跳ね上がった。

記者: SL 10ATR……ATR の 10 倍のストップロスって、相当広いですよね。

開発者: GBPJPY の ATR が 0.3 円くらいなので、SL は 3 円幅。でも実際には SL にほとんど当たらない。TS=0.0001 がほぼ即座に利益をロックするので。

2. 全トレードが 30 分で終わる

記者: TS=0.0001 というのは?

開発者: トレーリングストップの距離が ATR の 0.0001 倍。事実上ゼロです。価格が 1 pip でも有利な方向に動いたら、そこに SL がロックされる。

記者: それはもう「次のバーで強制決済」と同じでは?

開発者: まさにそうでした。保有期間を調べたら、4,118 トレード中 4,101 件が 2 バー(30 分)で決済。中央値も 2 バー。実質「MACD がゼロクロスした次の M15 バーで勝敗が決まる 1 バー予測ゲーム」になっていた。

記者: 勝率は?

開発者: 70%。次のバーが順方向に動く確率が 70% で、それだけで PF 4.4。

記者: ……本当ですか?

開発者: いい質問です。

3. M5 subtick で嘘を剥がす

記者: 何がおかしかったんですか?

開発者: バックテストは M15 バー単位で評価しています。バーの open, high, low, close だけを見る。でも実際の価格はバーの中で動いている。

記者: つまり?

開発者: TS=0.0001 の場合、バー内で一瞬逆行しただけで TS がヒットするはず。でも M15 バーの close だけ見ると「最終的には順方向だった」ので勝ち判定になる。バー内の逆行を見逃している

記者: それを検証するために?

開発者: M5 データを取得しました。M15 の 1 バーの中に M5 が 3 本入る。validate_research.py に --subtick m5 モードを追加して、SL/TS を M5 バーごとに 3 回評価するようにした。

記者: 結果は?

開発者: M15 で PF 4.15 だったのが、M5 subtick で PF 2.49。約 40% の嵩上げでした。勝率も 71% から 63% に落ちた。

記者: 4 割……。

開発者: バックテストの解像度が粗いと、タイトなトレーリングストップの効果を過大評価する。これは構造的な問題です。

4. MT5 が教えてくれた最後の嘘

記者: M5 で検証し直して PF 2.49。それでも利益は出ていた?

開発者: はい。ただ、もう 1 つ問題がありました。

記者: まだあるんですか。

開発者: TS=0.0001 を実際に MT5 で実行しようとしたら、全部拒否された。ライブトレーダーのログを見たら、トレーリングストップの更新が全て「Trailing SL update failed」になっていた。

記者: なぜ?

開発者: MT5 には SYMBOL_TRADE_STOPS_LEVEL という制約があります。現在価格から最低 10 points 離さないと SL を設定できない。GBPJPY だと 0.01 円。ATR が 0.1 円なら、TS の最小値は 0.1×ATR

記者: TS=0.0001 は桁が 3 つ足りない。

開発者: そう。PF 5.54 の最強戦略は、そもそも実行不可能だった

5. 前提が崩れた後に残ったもの

記者: USDJPY のライブ稼働も同じ問題を?

開発者: はい。TS 更新が全部失敗していたので、実質 SL 固定で動いていた。利益が出ていたのは別の理由——エントリーの方向性自体は正しかったから。

記者: じゃあ全部やり直し?

開発者: やり直しました。TS=0.1×ATR(MT5 の物理的下限)を新しい制約にして、p16 として再スタート。

記者: フィルターなしの MACD ゼロクロスだけで?

開発者: 面白いことに、TS=0.1 だとフィルターが効くようになった。TS=0.0001 では即ロックなのでエントリーの質が関係なかった。でも TS=0.1 だと 0.1ATR 分の逆行を許容するので、質の悪いエントリーがそのまま SL ヒットに繋がる。

記者: 前回外したフィルターを戻した?

開発者: はい。3 バーモメンタム、Stochastic 方向確認、MA ギャップ、ボリューム。1 つずつ追加して、M5 subtick の OOS で keep が出るものだけ残した。

記者: 結果は?

開発者: TRAIN で PF 3.49、M5 subtick の自己検証で PF 2.48。windows 98%。

6. 3 段パイプライン

記者: 「M5 subtick の自己検証」というのは?

開発者: M5 データを前半と後半に分けました。

  • TRAIN(M15): 高速にスクリーニング
  • SELF-CHECK(M5 前半): M5 精度で数値を見る。エージェントが判断に使える
  • VALIDATION(M5 後半): keep/discard のみ。過学習防止

記者: TRAIN で嵩上げされた数字に騙されない仕組み。

開発者: はい。以前は TRAIN で PF 3.5 が出ても M5 OOS で discard される、というのを繰り返していた。SELF-CHECK があれば、M5 で効かない変更を早期に弾ける。

7. バックテストを信じるな、検証の層を増やせ

記者: 今回の教訓をまとめると?

開発者: バックテストは 3 つのレイヤーで嘘をつきます。

1 つ目はバー解像度。M15 で評価して「勝ち」でも、M5 で見るとバー内の逆行で負けている。タイトなストップほど影響が大きい。

2 つ目はブローカーの物理的制約。最小ストップレベル、スプレッド、スリッページ。バックテストにはこれが入っていない。実行環境の制約を先に調べるべきだった。

3 つ目は前提の連鎖崩壊。TS=0.0001 が最適 → フィルター不要 → SL は広くていい → PF 5.54。全部が 1 つの前提に乗っていて、前提が崩れたら全部崩れる。

記者: でも PF 2.5 は残った。

開発者: はい。正しい前提で探せば、正しい答えが出る。幻の PF 5 を追うより、実行可能な PF 2.5 の方がはるかに価値がある


前回の記事: 探索空間の設計——autoresearch は「何を試すか」で決まる

次の記事: エージェントは保守的なオプティマイザーである——674回の実験から見えた分業

この記事は Claude Code(開発担当)への実際のインタビューをもとに構成しています。

本記事はバックテスト手法の技術的検証記録であり、特定の金融商品の売買を推奨するものではありません。投資判断はご自身の責任でお願いします。