
コード監査で見つけた差異を、直す前に測って仕分けた話
実機EAの全数バグ監査で見つかった20件の指摘のうち、『検証コードとの差異』2件を反射的に直さず実測で仕分けた記録。1件は直しても無意味、1件は小さいが本物の改善。テスターの1窓に騙されない方法と、検証と実機のズレを許さない運用哲学まで。
実口座で動いているEAのソースコード約2,500行を、全数バグ監査にかけたことがあります。出てきた指摘は20件。再起動で停止ラッチが消える穴のような「即修正すべき実害」から、「検証コードと実機で細部の挙動が違う」という気になる差異まで、重さは様々でした。
実害系は優先度順に潰しました(停止状態の永続化、SL無し建玉の穴、発注価格の正規化など)。この記事で書きたいのは、その後に残った「検証コードとの差異」2件の話です。普通の感覚なら「検証と実機は一致すべき。全部直そう」となるところですが、このプロジェクトでは直す前に必ず測ることにしています。修正にもリスクとコストがあり、そして測ってみると、直す価値は差異ごとに全く違うからです。
はじめに: このブログと、前提の説明
初めての方向けに。このブログは、私(個人)がFXの自動売買プログラム(EA=MetaTrader5上で動く売買ロジック)を自作し、統計検証の記録を勝敗問わず公開している検証日記です。文中の「研究N」は検証ノートの通し番号。
私の開発体制は少し特殊で、検証用のPythonコード(過去11年の実データで手法を測る側)と、実口座で動くMT5のEA(測った結果を移植した側)の2本立てです。用語はPF=総利益÷総損失(1超で黒字)、DD=資産が最高値からどれだけ下がったか、の2つだけで読めます。

図: 検証側が示す「あるべき姿」。この曲線と実機の挙動がズレていないかを数え続けるのが、この記事のテーマである監査です。
なぜ「差異=即修正」にしないのか
前提の整理から。私の開発フローでは、Pythonの検証基盤が「正」で、MT5のEAはその移植です。移植には必ず細部の判断が入ります。フィルタをどのスリーブに適用するか、オーバーレイをどこまで掛けるか。移植時の解釈が検証側と食い違うと、「検証した姿」と「実際に動いている姿」がズレます。
このズレには2種類あります。性能を変えるズレと、変えないズレ。前者は直すべきですが、後者を反射的に「直す」と、実機の挙動を変えるという新しいリスクを、便益ゼロで背負うことになります。どちらか見分ける方法は1つしかありません。両方の挙動でバックテストを回して、差を測ることです。
件1(監査D3): 直しても無意味だった差異
1件目はequityフィルタの適用範囲です。米国株が200日線を割ったら核のサイズを半分にする防御機構を、検証コードはトレンド核だけに適用しているのに、実機EAは指数スリーブと第2サテライトにも掛けていました。このフィルタが作動している局面は全日数の25%。4分の1の期間で3つのスリーブのサイズが違うのだから、無視できる差には見えません。
全期間+期間分割で両方を測りました。
| 構成 | PF | 月利 | 最大DD |
|---|---|---|---|
| 是正版(検証と一致) | 1.69 | +1.060% | -8.33% |
| 現状のEA | 1.68 | +1.039% | -7.98% |
月利差は+0.021%。DDに至っては現状のEAの方が0.35pt浅い。未使用期間(2023年以降)だけで見ると月利+1.392% vs +1.405%で、ほぼコインフリップです。取引数は8,478件で完全に同一(このフィルタはサイズだけを変えるため)。
判定は「無差」。性能を理由に挙動を変える動機はありません。そしてこの検証の本当の収穫は副産物のほうでした。実機EAの成績(月利+1.039%/DD-7.98%)が、公表している検証値(+1.060%/-8.33%)からほぼズレていないことを、初めて数字で確認できたんです。監査の不合格項目を測りにいったら、システム全体の健全性証明が手に入った形です。
件2(監査B3): 小さいが本物だった差異
2件目はカレンダー・スリーブのオーバーレイです。検証コードには存在しない「ボラ調整+equityフィルタ」が、実機のカレンダー・スリーブにだけ掛かっていました。移植時に「他のスリーブと同じ扱いにしておこう」とされた、悪意のない実装差です。
これを検証準拠(オーバーレイなし)に修正したところ、事件が起きます。MT5のストラテジーテスター(USDJPY・2022年Q1の窓)でPFが1.27→1.34へ跳ね上がったんです。0.07の改善は大きい。……大きすぎます。この手の「出来すぎた改善」を見たときこそ、全期間で測り直す規律の出番です。
| 構成 | PF | 月利 | 最大DD |
|---|---|---|---|
| 修正後(検証と一致) | 1.69 | +1.060% | -8.33% |
| 修正前 | 1.67 | +1.049% | -8.72% |
真の差はPF+0.02、月利+0.010%、DDが0.39pt浅くなる程度でした。テスター窓の派手な+0.07は、たまたまその3ヶ月がUSDJPYのカレンダー取引にとって差の出やすい窓だっただけです。
ただし、方向は本物でした。データを前半(〜2023)と後半(2023〜)に割っても、どちらの区間でもPF+0.02・月利+0.01%前後・DD改善と、同じ向きに同じくらい改善しています。偶然の窓ならここで符号が揺れるはずです。小さいが頑健な、真の改善。しかも修正の中身は「未検証の逸脱を検証済みの姿に戻す」ことなので、原理的にも正しい向きです。
2件が対照的だったからこそ見える運用ルール
この2件、表面的にはどちらも「検証と実機の差異」で、どちらも修正候補でした。測って初めて、片方は無意味・片方は正解と分かれた。ここから抽出できるルールを3つ書いておきます。
- 監査の指摘は測ってから直す。 実害系(お金が漏れる穴)は即修正でいい。でも「一致していない」だけの指摘は、修正自体が挙動変更リスクなので、性能差を測ってから判断する
- テスターの1窓の改善幅は信じない。 方向の参考にはなるが、判定は必ず全期間+期間分割で行う。窓は差を平気で3倍に誇張します(0.07 vs 真値0.02)
- 検証済みコードからの無断の逸脱は、性能差ゼロでも負債。 件2のように、逸脱は偶然マイナス側に出ていることがある。そして逸脱が積もると、「何を検証したのか」自体が分からなくなる
EAを長期運用する上で一番怖いのは、大きなバグではありません(大きなバグはすぐ見つかります)。怖いのは、検証した姿と実機の姿が数年かけて静かに乖離していくことです。この2件の検証は、その乖離を定期的に数えて潰す仕組みが機能している、という監査報告でもあります。ちなみにこの後、EA本体は挙動不変を機械検証(正規化コード2,009行の一致確認)しながら13モジュールに分割リファクタリングしました。測ってから動く、はコード構造の変更でも同じです。