MQL5で一定時間ごとに処理する方法|タイマーは1つだけ
MQL5で一定時間ごとに処理を動かすには、OnInit で EventSetTimer を呼び、OnTimer に処理を書きます。単位は秒です。
ここで知っておくべき制約が2つあります。①1つのプログラムで動かせるタイマーは1つだけ ②前回の処理が終わっていないと、次のタイマーイベントはキューに入らない。どちらもMQL5公式リファレンスに明記されています。
(確認環境:MetaTrader 5 / Windows 11)
最小の構成
int OnInit()
{
EventSetTimer(60); // 60秒ごと
return(INIT_SUCCEEDED);
}
void OnTimer()
{
Print("60秒経過 ", TimeToString(TimeTradeServer(), TIME_SECONDS));
}
void OnDeinit(const int reason)
{
EventKillTimer();
}
EventSetTimer の引数は秒です。1秒より細かくしたい場合は EventSetMillisecondTimer を使います。
🔴 なぜ OnTick ではだめなのか
「一定時間ごと」を OnTick の中で時刻を見て判定する書き方をよく見かけます。これは動く時と動かない時があります。
理由は単純です。OnTick は価格が更新された時にしか呼ばれません。
- 値動きが止まっている時間帯 — 呼ばれない
- 取引時間外 — 呼ばれない
- 薄商いの早朝 — 間隔が空く
つまり「22時になったら閉じる」という処理を OnTick に書くと、22時に値が動かなければ実行されません。時刻で何かをする処理は OnTimer に置くのが正しい形です。
🔴 タイマーは1つしか持てない
公式リファレンスには「1つのプログラムにつき、動かせるタイマーは1つを超えない」と書かれています。
「5秒ごとの監視」と「60秒ごとの記録」を両方やりたい場合、タイマーを2つ作ることはできません。短い方の間隔でタイマーを回し、OnTimer の中で回数を数えます。
int count = 0;
void OnTimer()
{
count++;
// 5秒ごとの処理
if(count % 12 == 0)
{
// 60秒ごとの処理
}
}
🔴 処理が重いと間隔どおりに来ない
もう1つの制約です。公式リファレンスによると、Timerイベントが既にキューにある、または処理中の場合、新しいTimerイベントはキューに入りません。
つまり1秒タイマーにしても、1回の処理に3秒かかっていれば1秒ごとには来ません。取りこぼした分は後からまとめて来るわけでもありません。
対策は2つです。
- 間隔を処理時間より十分長くする
OnTimerの中で重い処理をしない — 判定だけ行い、実処理は条件を満たした時だけにする
「タイマーを短くすれば精度が上がる」とは限らないということです。
🔴 時刻の取り方を間違えると発火しない
OnTimer の中で現在時刻を見る時、どの関数を使うかで結果が変わります。
| 関数 | 返すもの |
|---|---|
TimeCurrent() |
最後にクォートを受信した時刻 |
TimeTradeServer() |
取引サーバーの現在時刻 |
TimeLocal() |
PCの時刻 |
問題になるのは1つ目です。TimeCurrent() は相場が動かないと進みません。
タイマー自体は1秒ごとに回っていても、TimeCurrent() で「22時を過ぎたか」を判定していると、22時前に最後のクォートが止まった場合、いつまでも22時になりません。
時刻で区切る処理では TimeTradeServer() を使ってください。この3つの違いはMT5の時刻がずれる理由で詳しく扱っています。
EventKillTimer は書いておく
公式リファレンスによると、プログラムが停止すればタイマーは自動で破棄されます。EventKillTimer を書き忘れても残り続けるわけではありません。
それでも OnDeinit に書いておくべき理由は、途中でタイマーを止めたり、間隔を変えたりする場合に必要になるからです。間隔を変えるには一度止めてから設定し直します。
何に使えるか
- 指定時刻での決済 — 値動きに依存せず実行できる
- 定期的な記録 — 一定間隔で値をファイルに書き出す(MQL5でCSVを出力する方法)
- 保有時間の監視 — 一定時間を超えたポジションを探す
1つ目が実用上いちばん効きます。エントリーは自分で判断し、閉じる方だけを時間で機械的に行う使い方です。考え方はMT5で決済だけを自動化する方法に、実際に閉じるコードはMQL5でポジションを決済する方法にまとめています。
まとめ
OnInitでEventSetTimer(秒)、処理はOnTimer- 🔴 時刻で動かす処理を
OnTickに書かない。値が動かないと呼ばれない - 🔴 タイマーは1プログラムに1つだけ。複数間隔は回数で分ける
- 🔴 処理中は次のイベントがキューに入らない。短くすれば精度が上がるわけではない
- 🔴 判定に
TimeCurrent()を使わない。相場が止まると時刻も止まる
ストラテジーテスターの中では、OnTimer はモデルに関係なく呼ばれます。テスターでの時刻の進み方とモデルの違いはMT5ストラテジーテスターのモデルの選び方にあります。
本記事はMQL5の仕様と実装方法を説明したものであり、特定の売買を推奨するものではありません。仕様はビルドによって変わる可能性があります。投資判断はご自身の責任で行ってください。


