【検証#11】バックテストが終わらない!リトライ処理の無限ループ¶
この記事の3行まとめ
- 🔄 注文失敗時に
whileでリトライするのは定石だが… - ⚡ バックテストでは Sleep() が無視される ため、一瞬で無限ループする!
- ✅ 対策:テスト中はループを抜けるか、回数制限を厳格にする
はじめに¶
この記事は、「とあるMetaTraderの備忘秘録」様のブログ記事を検証・紹介するシリーズの第11弾です。
EAを作っていると、約定拒否(Requote)や通信エラーに対処するために「注文が通るまでリトライする」処理を書くことがあります。しかし、それがバックテストで牙を剥くことがあります。
元ネタ
MyOrderClose
https://fai-fx.hatenadiary.org/entry/20100627/1277641026
(2010年6月27日 公開)
時代背景に関する注意
元記事はMQL4時代のものですが、MQL5でも「テスターでのSleep挙動」など共通する仕様があります。
問題のコード¶
以下のようなリトライ処理を書いたとします。
// 注文が通るまで諦めない!
while(true)
{
if(OrderSend(...) == true) break;
Print("注文失敗。リトライします...");
Sleep(1000); // 1秒待って再挑戦
}
本番環境(ライブ/デモ口座)では、これは正しく機能します。1秒ごとに再試行し、サーバーに負荷をかけすぎることもありません。
バックテストでの挙動¶
しかし、これをストラテジーテスターで動かすとどうなるでしょうか?
MetaTraderの仕様として、バックテスト中は Sleep() 関数は完全に無視されます。時間は進みませんし、処理ウェイトも発生しません。
その結果: 1. 注文失敗 2. Sleep(1000) が 0ミリ秒 で通過 3. 即座に次回の while ループ 4. 注文失敗 5. ...
これらが 1ティックの間(一瞬) に何万回も繰り返されます。
発生する現象¶
- ログの肥大化: 数GB単位のログファイルが生成され、ディスクを圧迫する。
- テスターのフリーズ: 処理が終わらず、テストが先に進まない。
- Visual Modeの停止: チャート描画更新の暇もなくループし続ける。
MQL5での検証コード¶
実際にこの現象を確認するEAを作成しました。(安全のためリトライ回数制限を設けています)
ファイル名: 11_InfiniteLoop_EA.mq5
保存先: MQL5\Experts
//+------------------------------------------------------------------+
//| 11_InfiniteLoop_EA.mq5 |
//| MQL検証シリーズ #11 検証用EA |
//+------------------------------------------------------------------+
#property copyright "FXおもしろラボ"
#property version "1.00"
input int MaxRetry = 10000; // リトライ上限
input bool UseIsTesting = false; // 対策ON/OFF
void OnTick()
{
static bool isExecuted = false;
if(isExecuted) return;
Print("=== リトライ実験開始 ===");
int retryCount = 0;
while(true)
{
bool result = TryOrder(); // 常にfalseを返す関数
if(result) break;
// バックテスト対策を入れるかどうか
if(UseIsTesting && MQLInfoInteger(MQL_TESTER))
{
Print("テストモード検知:リトライを中止します");
break;
}
retryCount++;
if(retryCount >= MaxRetry) break;
// テスターでは無視される!
Sleep(1000);
}
PrintFormat("実験終了: %d回リトライしました", retryCount);
isExecuted = true;
}
bool TryOrder() { return false; }
結果¶
UseIsTesting = false の場合、一瞬で「10000回リトライしました」と表示されます。もし MaxRetry がなければ、強制終了するまで止まりません。
対策¶
バックテスト中であることを検知し、ループを抜ける処理を入れましょう。
MQL5での実装¶
あるいは、MQL4/MQL5共通で使えるラッパー関数を作るのも良いでしょう。
そもそも無限ループにしない¶
while(true) は避け、必ず for 文で回数制限を設けるのが、防御的プログラミングの基本です。
これもテスターでは一瞬で終わりますが、無限ループによるフリーズは防げます。
まとめ¶
| ポイント | 内容 |
|---|---|
| Sleep()の罠 | バックテスト中は無視される(待ち時間ゼロ) |
| 影響 | 無限リトライが一瞬で行われ、フリーズやログ肥大化を招く |
| 対策 | MQLInfoInteger(MQL_TESTER) でテスト検知し、breakする |
EA開発者は「テスト環境」と「本番環境」の違いを常に意識する必要があります。
ソースコードのダウンロード¶
この記事で紹介したコードをダウンロードできます。
ファイルの種類:EA(Expert Advisor)
保存先: MQL5/Experts/ フォルダ
使い方: MT5のナビゲーターから「エキスパートアドバイザ」を展開し、チャートにドラッグ&ドロップで適用
11_InfiniteLoop_EA.mq5 をダウンロード