コンテンツにスキップ

【移植#36】「99%」を鵜呑みにしない — バックテスト履歴の証拠をMQL5で点検する

EURUSDの確定M1足5000本についてOHLC整合性、時刻重複、履歴ギャップ、スプレッド記録を点検したMT5画面

この記事の3行まとめ

  • バックテスト画面の大きな百分率だけでなく、その数字が何を測っているかを確認します
  • 確定M1足5,000本のOHLC、時刻順、ギャップ、出来高、スプレッド記録を点数化せず表示します
  • 専用MT5で12バッファを独立照合し、壊した人工データでも異常を検出できることを確認しました

今回の原典は「99%という数字はどこから来たのか」

投稿日順で次に当たる2010年1月25日の記事では、MT4のバックテスト結果に表示されていたModeling Qualityが取り上げられていました。

元記事「Modeling Quality 99% は都市伝説?」を読む

当時の標準的なMT4テストでは、1分足から各時間足とティックを組み立てたときの計算上限が90%とされていました。一方、生のティックをFXTファイルへ変換する「99%テスト」も知られるようになります。

生ティックを使う考え方自体は、1分足内の架空の値動きを実際の値動きへ近づけるという意味があります。しかし原典が問題にしたのは、FXTヘッダー内のmodelqualityへ書いた値がレポートの百分率として表示される点でした。実際に99.98を書けば、画面にも99.98%と出せたと報告されています。

つまり、表示が99%だから生ティックを正しく使ったとは限りません。大切なのは、数字の大きさではなく、次の証拠です。

  • どの価格履歴を使ったか
  • ティックは実測か生成か
  • 欠損や不整合がないか
  • スプレッド、手数料、スリッページをどう扱ったか
  • 同じ条件で再現できるか

今回のMQL5版は、別の「品質99%」を計算しません。手元の履歴から確認できる事実を、そのまま並べる道具へ再構成します。


MT5のHistory Qualityは何を測るのか

現在のMT5テストレポートにもHistory Qualityがあります。ただし、昔のMT4と名前が似ていても定義は同じではありません。

MT5公式ヘルプでは、テストに使った1分足について、正しいデータと不正なデータの割合で履歴品質を求めます。出来高が1なのにOHLCが異なる足や、履歴ギャップが不正データとして扱われ、期間を複数区間へ分けて評価します。詳しい定義は公式のTesting Reportに記載されています。

これは価格履歴の整合性を調べる有用な指標です。しかし、次のすべてを保証する総合点ではありません。

  • ティック生成モードが戦略に適切だったか
  • 実ティックが全期間に存在したか
  • 実運用と同じスプレッドや手数料だったか
  • 約定遅延やスリッページを再現できたか
  • パラメータを過剰最適化していないか
  • 将来も利益が続くか

数字を否定するのではなく、「その数字の測定範囲を越えて読まない」ことがポイントです。


ティックモードも一緒に記録する

MT5のテスターには、速度と細かさが異なる複数のモードがあります。

モード 主な使い方 注意点
始値のみ 新バーだけで動くロジックの高速確認 バー内の値動きを扱えない
1分足OHLC 各M1足の4本値による概算 M1内の細かな順序は再現しない
全ティック M1からティックを生成 実際に配信されたティックそのものではない
リアルティックに基づく全ティック ブローカーの実ティック履歴を利用 欠けた区間では生成ティックが使われる場合がある

MetaQuotesの比較記事でも、同じEAがモードによって取引数、利益、ドローダウンを変える例が示されています。詳細は公式のTesting trading strategies on real ticksを参照してください。

そのため、レポートを残すときはHistory Qualityだけでなく、テストモード、ティック数、期間、銘柄、ブローカー、コスト条件もセットにします。


MQL5版は確定M1足5,000本を点検する

配布インジケーターは、現在のチャート時間足にかかわらず、対象銘柄の確定済みM1足をCopyRates()で5,000本まとめて取得します。形成中のM1足は含めません。

検査する内容は次のとおりです。

検査 内容
履歴同期 M1系列が端末と同期済みか
OHLC整合性 高値が始値・終値以上、安値が始値・終値以下、高値が安値以上か
時刻順 古い足から新しい足へ時刻が増加しているか
ギャップ 隣接するM1足の間隔が60秒を超えた箇所
出来高1の不整合 tick_volume=1なのにOHLCが異なる足
スプレッド記録 M1足に保存されたspreadの最小・最大・0の本数
実行環境 ターミナルビルドとチャート/テスターの別

履歴がまだ5,000本取得できない場合は、OnCalculate()から0を返して再試行します。少ない本数を完全な履歴と誤認してPASSにはしません。

ギャップの数には週末や取引休止時間も含まれます。ギャップがあるだけでデータ破損とは断定せず、「いつ、どれだけ空いているかを次に調べる入口」として表示します。


実測すると、スプレッド欄の弱点も見えた

専用MT5のEURUSD履歴を調べた結果は次のとおりです。

確認項目 実測値
対象履歴 EURUSD・M1確定足
検査本数 5,000本
検査期間 2026-07-16 19:50〜2026-07-22 07:15
履歴同期 YES
OHLC整合性違反 0本
時刻重複・逆行 0本
ギャップ 2件
欠けた時計上の分数 2,886分
出来高1でOHLC不一致 0本
記録スプレッド最小/最大 0/117ポイント
スプレッド0の足 4,733本
ターミナルビルド 5836
構造判定 PASS

spread=0が4,733本あったからといって、当時の実スプレッドが本当に0だったとは判断できません。この欄が履歴へ十分に保存されていない可能性があります。つまり、このM1履歴だけでは取引コストを復元できないという証拠です。

ここで架空の総合点を作ると、OHLCと時刻が正しいことに引っ張られて、この欠落が見えにくくなります。配布版がSTRUCTURE: PASSと表示する条件は、履歴同期、取得本数、OHLC整合性、時刻順だけです。コストまで合格したという意味ではありません。


独立実装と壊したデータで検証する

検証EAは、配布インジケーターの集計関数を呼び出しません。別に取得した同じ5,000本を独立実装で走査し、12本の診断バッファと照合しました。

さらに、5本の人工M1足へ意図的に次の異常を入れています。

  • 高値が始値を下回るOHLC違反
  • 出来高1なのにOHLCが異なる足
  • 前の足と同じ時刻を持つ重複
  • 180秒空けた履歴ギャップ
  • スプレッド0の足

検証側は、OHLC違反1、出来高不整合1、時刻重複1、ギャップ1、欠損2分、スプレッド0をそれぞれ検出しました。正常な実履歴だけでなく、異常時に検査が発火することも確認しています。

検証項目 結果
配布物の診断バッファ 12本一致
人工エッジケース 5種類を検出
CopyRates()取得件数 5,000本一致
コンパイル 0エラー・0警告
売買注文 なし
ファイル改変 なし
実画面キャプチャー 成功

ダウンロードと使い方

36_Backtest_History_Evidence_v1_00.mq5 をダウンロード

MT5のIndicatorsへ保存してコンパイルし、調べたい銘柄のチャートへ適用してください。チャートがH1やD1でも、検査対象は確定M1足です。

InpBarsToAuditで100〜100,000本の範囲を指定できます。本数を増やすほど長い期間を見られますが、初回取得と走査の負荷も増えます。

このパネルの数値は、テスト条件を記録するための補助資料です。EAのバックテストレポート、テストモード、コスト設定と一緒に保存してください。


使えないこと・注意点

  • MT5テストレポートのHistory Qualityを再計算するインジケーターではありません。
  • M1足の検査だけでは、実ティックが存在する区間や生成ティックへ切り替わった区間を特定できません。
  • ギャップには週末や正規の取引休止も含まれるため、件数だけで異常判定しません。
  • M1足のspreadが0でも、実際のスプレッド0を意味するとは限りません。
  • 手数料、スワップ、スリッページ、約定拒否、通信遅延は検査しません。
  • 履歴構造がPASSでも、EAの収益性、頑健性、将来成績は保証しません。
  • 異なるブローカーや取得時点では、履歴範囲と各件数が変わります。

ロジック評価の結論

原典の「99%問題」は、古いMT4のファイル形式だけの話ではありません。大きく表示された数字を見ると、私たちはつい「ほぼ完璧」と読みたくなります。しかし、測っていないものまで数字に含まれているわけではありません。

MQL5では実ティックを使えるようになり、履歴品質の定義も明確になりました。それでも、モード、データ源、コスト、期間、欠損を分けて記録する姿勢は変わりません。

良い検証は、きれいな点数を作ることではなく、他の人が同じ条件を追える証拠を残すことです。今回は、MT4の百分率への疑問を、MQL5で履歴の根拠を1項目ずつ見える化する道具へ移植しました。


前後の記事

前: 【移植#35】メール本文の改行を送信前に整える — SendMail用CRLFプリフライトをMQL5で作る

— SPONSORED —