【検証#12】その時刻判定、遅くない?文字列操作の罠¶

図:ベンチマーク実行結果
この記事の3行まとめ
- 🐢
TimeToStr()で時刻判定するとバックテストが激重になる - 🐇 整数計算(
TimeCurrent() % 86400)なら10倍以上高速 - ⚡
OnTick内で文字列操作(String関数)は極力避けるべし
はじめに¶
この記事は、「とあるMetaTraderの備忘秘録」様のブログ記事を検証・紹介するシリーズの第12弾です。
EAのバックテスト(最適化)において、もっともボトルネックになりやすいのが OnTick 内の処理です。特に「特定の時間だけトレードする」というロジックでやりがちなミスがあります。
元ネタ
最適化を最適化する・・・MQL4の高速化(4)
https://fai-fx.hatenadiary.org/entry/20100705/1278263593
(2010年7月5日 公開)
遅いコード vs 速いコード¶
例えば「毎日 12:00 にトレードする」というロジックを考えます。
❌ 遅い実装(文字列変換)¶
// 現在時刻を文字列に変換:"2026.01.27 12:00"
string timeStr = TimeToString(TimeCurrent(), TIME_MINUTES);
// 文字列比較
if(StringSubstr(timeStr, 11, 5) == "12:00")
{
// ...
}
人間には直感的で分かりやすいですが、コンピュータにとっては重労働です。 1. メモリ確保(文字列用) 2. 日時のフォーマット変換 3. 文字列の部分抽出 4. 文字列比較 5. メモリ解放
これを1回のティックごとに毎回行います。バックテストでは数百万回呼ばれるため、大きなロスになります。
✅ 速い実装(整数計算)¶
// 1日は 86400秒
// 12:00 は 0時から 12*3600 = 43200秒後
long seconds = TimeCurrent() % 86400; // 今日の経過秒数
if(seconds == 43200)
{
// ...
}
これなら単純な割り算と整数の比較だけです。メモリ確保も発生しません。
MQL5での検証コード¶
実際にどれくらい速度差があるのか、1000万回ループで比較してみました。
ファイル名: 12_SpeedTest_Time.mq5
保存先: MQL5\Scripts
//+------------------------------------------------------------------+
//| 12_SpeedTest_Time.mq5 |
//| MQL検証シリーズ #12 検証用スクリプト |
//+------------------------------------------------------------------+
#property script_show_inputs
input int LoopCount = 10000000;
void OnStart()
{
Print("=== 時刻判定 高速化ベンチマーク ===");
datetime now = TimeCurrent();
ulong start, timeStr, timeInt;
// A: 文字列変換
start = GetMicrosecondCount();
int countA = 0;
for(int i=0; i<LoopCount; i++)
{
datetime t = now + (datetime)i; // 毎回異なる時刻
string s = TimeToString(t, TIME_MINUTES);
if(StringSubstr(s, 11, 5) == "12:00") countA++;
}
timeStr = GetMicrosecondCount() - start;
PrintFormat("A (String): %.3f ms", timeStr/1000.0);
// B: 整数計算
start = GetMicrosecondCount();
int countB = 0;
long target = 12 * 3600;
for(int i=0; i<LoopCount; i++)
{
long t = (long)now + i;
long seconds = t % 86400;
if(seconds == target) countB++;
}
timeInt = GetMicrosecondCount() - start;
PrintFormat("B (Integer): %.3f ms", timeInt/1000.0);
// 結果
if(timeInt > 0)
PrintFormat("高速化倍率: %.1f倍", (double)timeStr / timeInt);
}
実行結果の目安¶
手元の環境での実行結果です:
なんと 200倍以上の差 が出ました。 文字列操作がいかに重いかがわかります。最適化のためにループ変数を使ってもこの差です。
実践テクニック¶
時間範囲(9時から15時まで)の判定¶
long now = TimeCurrent() % 86400;
long start = 9 * 3600; // 09:00
long end = 15 * 3600; // 15:00
if(now >= start && now < end)
{
// トレード時間内
}
分単位の判定(毎時30分など)¶
まとめ¶
| ポイント | 内容 |
|---|---|
| TimeToStr | デバッグログなど、人間が見る時だけ使う |
| ロジック判定 | 必ず整数計算(割り算・余り)を使う |
| 効果 | バックテスト時間が大幅に短縮される |
「動けばいい」段階から「最適化を回す」段階になったら、ぜひこの高速化テクニックを取り入れてください。
ソースコードのダウンロード¶
この記事で紹介したコードをダウンロードできます。
ファイルの種類:スクリプト
保存先: MQL5/Scripts/ フォルダ
使い方: MT5のナビゲーターから「スクリプト」を展開し、チャートにドラッグ&ドロップで実行
関連記事・用語¶
- #07 バックテスト高速化テクニック — その他の高速化手法
- 用語集 - TimeCurrent