開発実務ノート

MQL5 OnTimerの使い方|外部連携・通知・定期処理を分ける設計

EAファンクラブ

MQL5でEAを作る時、すべての処理をOnTickに入れると、処理が重くなったり、ログが増えすぎたり、外部連携の失敗原因を追いにくくなったりします。

OnTimerは、一定間隔で処理を実行するためのイベント関数です。EAの売買判定や注文処理はOnTick側に残し、通知、外部連携、状態監視、ログ抑制、定期チェックをOnTimerへ分けることで、EA全体の責務を整理しやすくなります。

特に、Discord通知、Google Sheets連携、WebRequest、CSV出力、稼働状態ログ、外部制御の取得などは、tickごとに実行するよりも、OnTimerで周期を決めて処理する方が扱いやすい場合があります。

このページでは、MQL5のOnTimerの使い方を、EventSetTimer、EventKillTimer、外部連携、通知、ログ抑制、バックテスト負荷対策の観点から整理します。

なお、このページはMQL5開発における技術確認を目的とした内容です。売買判断、推奨エントリー、推奨ロット、利益保証、損失回避保証を行うものではありません。

OnTimerとは何か

OnTimerは、Timerイベントが発生した時に呼ばれるイベント関数です。

EAやインジケーターでタイマー処理を使う場合、通常はOnInitでEventSetTimerを呼び、指定した秒数ごとにOnTimerを実行します。

int OnInit()
{
   if(!EventSetTimer(10))
   {
      PrintFormat("[TIMER_SET_NG] seconds=10 last_error=%d", GetLastError());
      return INIT_FAILED;
   }

   Print("[TIMER_SET_OK] seconds=10");
   return INIT_SUCCEEDED;
}

void OnTimer()
{
   Print("[TIMER_TICK] periodic task");
}

void OnDeinit(const int reason)
{
   EventKillTimer();
   PrintFormat("[TIMER_KILL] reason=%d", reason);
}

OnTimerを使う場合は、開始、実行、終了をログで確認できるようにしてください。

OnTickとOnTimerの役割を分ける

EA開発では、OnTickとOnTimerの責務を混同しないことが重要です。

OnTickは価格変動に応じた売買判定や注文処理に向いています。一方、OnTimerは、一定間隔でよい処理、外部連携、状態監視、ログ抑制、通知再送などに向いています。

イベント主な役割入れやすい処理
OnTick価格変動に応じた処理signal判定、entry gate、発注前チェック、注文処理、決済判定
OnTimer一定間隔の処理外部制御取得、通知送信、CSV出力、稼働監視、ログ抑制、状態同期
OnInit初期化処理input確認、timer設定、handle生成、初期ログ
OnDeinit終了処理timer停止、handle解放、終了ログ

外部連携や通知処理をOnTickに直接入れると、tickが多い時間帯に処理回数が増えすぎる場合があります。定期処理でよいものはOnTimerへ分離してください。

OnTimerに向いている処理

OnTimerは、毎tickで実行する必要がない処理に向いています。

特に、外部連携、通知、状態監視、ログ抑制、定期スナップショットは、OnTimerへ分けると構造が分かりやすくなります。

処理OnTimerに向く理由確認ログ
Discord通知tickごとに送る必要がなく、送信間隔を制御しやすいNOTIFY_SEND / NOTIFY_SKIP
Google Sheets連携定期的な状態送信や集計送信に向いているSHEET_WRITE / SHEET_THROTTLE
外部制御取得外部シートやAPIから一定間隔で設定を読む場合に向いているEXTERNAL_FETCH / EXTERNAL_APPLY
CSV出力tickごとではなく、一定間隔やイベント後の記録に向いているCSV_WRITE / CSV_SKIP
状態監視口座状態、ポジション状態、稼働状態を周期的に確認できるRUNTIME_SNAPSHOT
ログ抑制同じ状態を毎tick出さず、一定間隔で要約できるLOG_THROTTLE / TIMER_SUMMARY

ただし、OnTimerに重い処理を入れすぎると、タイマーイベントの処理自体が詰まる場合があります。処理時間、通信失敗時の戻り、再送制御を設計してください。

OnTimerに入れすぎない方がよい処理

OnTimerは便利ですが、すべての処理を移す場所ではありません。

価格変動に即応する処理や、発注・決済の中心処理は、OnTickや専用のexecution処理へ分けた方が確認しやすくなります。

OnTimerに入れすぎない処理理由推奨する分離
毎tick必要なentry判定Timer間隔中の価格変化を見落とす場合があるOnTick / signal層
発注処理そのもの外部連携や通知と注文責務が混ざるexecution層へ分離
重いWebRequestの連続実行通信失敗時に処理が詰まりやすいthrottle、timeout、queue管理
大量CSV出力ファイルI/Oが増え、BTや長時間稼働で重くなるイベント時出力、要約出力
毎秒大量ログExpertsログが膨らみ、確認しづらくなるログ間隔、状態変化時のみ出力

OnTimerは、EA本体の売買ロジックを置き換えるものではありません。定期処理、外部処理、補助処理を整理するために使います。

EventSetTimerの基本

EventSetTimerは、Timerイベントの発生間隔を秒単位で設定します。

通常はOnInitで一度だけ呼び出し、失敗した場合はGetLastErrorをログに残します。

input int InpTimerSeconds = 10;

bool SetupTimer()
{
   if(InpTimerSeconds <= 0)
   {
      PrintFormat("[TIMER_CONFIG_NG] seconds=%d reason=must_be_positive", InpTimerSeconds);
      return false;
   }

   ResetLastError();

   if(!EventSetTimer(InpTimerSeconds))
   {
      PrintFormat("[TIMER_SET_NG] seconds=%d last_error=%d",
                  InpTimerSeconds,
                  GetLastError());
      return false;
   }

   PrintFormat("[TIMER_SET_OK] seconds=%d", InpTimerSeconds);
   return true;
}

int OnInit()
{
   if(!SetupTimer())
      return INIT_FAILED;

   return INIT_SUCCEEDED;
}

タイマー間隔は短くしすぎないようにしてください。外部連携や通知では、5秒、10秒、30秒、60秒など、用途に応じて十分な間隔を取る方が扱いやすくなります。

EventKillTimerの基本

OnInitでEventSetTimerを使った場合は、OnDeinitでEventKillTimerを呼びます。

EA削除、時間足変更、再コンパイル、チャート終了などの場面で、終了ログとあわせてTimerを停止しておくと確認しやすくなります。

void OnDeinit(const int reason)
{
   EventKillTimer();

   PrintFormat("[DEINIT_TIMER_KILL] reason=%d", reason);
}

OnDeinitでは、Timer停止、handle解放、必要最小限の終了ログに留める設計が安全です。広範囲のObject削除や重い通信処理を終了時に詰め込みすぎないようにしてください。

ミリ秒タイマーの扱い

EventSetMillisecondTimerを使うと、1秒未満の間隔でTimerイベントを発生させることができます。

ただし、短い間隔でOnTimerを呼び出すほど、処理回数が増え、バックテスト時間や端末負荷に影響します。通常の通知、外部連携、状態監視では、秒単位のEventSetTimerで十分な場合が多いです。

方式用途注意点
EventSetTimer秒単位の定期処理通常の通知、外部連携、状態監視に向く
EventSetMillisecondTimer1秒未満の高頻度処理処理負荷やBT時間が増えやすい

高頻度タイマーは、必要性が明確な場合だけ使ってください。ログ確認や外部連携目的で安易に短い周期を設定すると、検証しづらくなる場合があります。

外部連携処理をOnTimerへ分ける

WebRequest、Discord通知、Google Sheets連携などは、OnTimerで周期管理すると整理しやすくなります。

OnTick側では、売買判定や内部状態の更新だけを行い、外部へ送る必要がある情報をキューや状態変数として保持します。OnTimer側で、送信間隔、失敗回数、再送可否を確認してから外部連携を実行します。

datetime g_last_external_sync = 0;
input int InpExternalSyncSeconds = 60;

bool CanRunExternalSync()
{
   datetime now = TimeCurrent();

   if(g_last_external_sync > 0 && (now - g_last_external_sync) < InpExternalSyncSeconds)
   {
      PrintFormat("[EXTERNAL_SYNC_SKIP] reason=throttle wait_sec=%d",
                  InpExternalSyncSeconds - (int)(now - g_last_external_sync));
      return false;
   }

   g_last_external_sync = now;
   return true;
}

void OnTimer()
{
   if(!CanRunExternalSync())
      return;

   RunExternalSync();
}

外部連携は、失敗しても売買ロジックを直接止めない設計にすることが多くあります。ただし、外部シートによる売買停止など、取引制御に関係する場合は、影響範囲を明確にしてください。

WebRequestをOnTimerで扱う時の注意点

WebRequestを使う場合は、URL許可、timeout、HTTPステータス、戻り値、レスポンス内容、失敗時の扱いを分けて確認します。

WebRequestが失敗した時に、EAの注文処理まで止めるのか、外部連携だけ停止するのか、次回OnTimerで再試行するのかを仕様として決めてください。

確認項目内容ログ例
URL許可MT5のオプションでWebRequest許可URLに入っているかWEBREQUEST_URL_CHECK
timeout通信待ち時間を長くしすぎていないかWEBREQUEST_TIMEOUT
HTTPステータス200、400、403、500などを確認するWEBREQUEST_STATUS
レスポンスJSON、CSV、テキストなどを解析できるかWEBREQUEST_PARSE
再試行失敗時にすぐ連続送信しないかWEBREQUEST_RETRY_SKIP
売買への影響外部連携失敗時にentryを止めるかどうかEXTERNAL_CONTROL_STATE

外部連携失敗をすべて注文失敗として扱うと原因が分かりにくくなります。通信失敗、解析失敗、外部制御による停止、EA内部のentry gateは分けてログ化してください。

Discord通知をOnTimerで送る考え方

Discord通知は、状態変化やイベント発生時に送ることが多い処理です。

ただし、同じ状態を毎tick送ると通知が多くなりすぎます。OnTimer側で送信間隔や重複通知を制御すると、運用しやすくなります。

datetime g_last_notify_time = 0;
string   g_last_notify_key  = "";

bool CanNotify(const string notify_key, const int min_interval_sec)
{
   datetime now = TimeCurrent();

   if(g_last_notify_key == notify_key && (now - g_last_notify_time) < min_interval_sec)
   {
      PrintFormat("[NOTIFY_SKIP] key=%s reason=duplicate_interval", notify_key);
      return false;
   }

   g_last_notify_key = notify_key;
   g_last_notify_time = now;
   return true;
}

void SendTimerNotification()
{
   string key = "runtime_alive";

   if(!CanNotify(key, 300))
      return;

   Print("[NOTIFY_SEND] key=runtime_alive");
}

通知処理では、通知対象、送信間隔、失敗時の再送、Webhook URLの管理、ログの出し方を分けて設計してください。

Google Sheets連携をOnTimerで扱う考え方

Google Sheets連携では、EAの状態、ポジション数、外部制御、稼働状態、検証メモなどを一定間隔で読み書きすることがあります。

このような処理は、tickごとではなく、OnTimerで間隔を決めて実行する方が扱いやすくなります。

処理OnTimerで確認することログ例
外部制御取得停止フラグ、BUY/SELL許可、稼働時間などSHEET_FETCH_CONTROL
状態送信EA稼働状態、ポジション数、最終更新時刻SHEET_WRITE_STATUS
エラー記録通信失敗、解析失敗、認証失敗SHEET_ERROR
送信間隔制御短時間で連続送信しないSHEET_THROTTLE
取引への影響外部制御がentry gateに影響するかEXTERNAL_GATE_STATE

外部シートを使ってEAの動作制御を行う場合は、OnTimerで取得した制御値をruntime状態へ反映し、OnTick側ではその状態を参照する設計にすると責務を分けやすくなります。

状態スナップショットをOnTimerで出す

OnTimerは、EAの稼働状態を一定間隔でログ化する用途にも向いています。

毎tickログを出すと確認しづらくなるため、状態が変わった時、または一定間隔ごとに要約ログを出す設計が有効です。

void PrintRuntimeSnapshot()
{
   int positions = PositionsTotal();
   double equity = AccountInfoDouble(ACCOUNT_EQUITY);
   double margin = AccountInfoDouble(ACCOUNT_MARGIN);
   double margin_free = AccountInfoDouble(ACCOUNT_MARGIN_FREE);

   PrintFormat("[RUNTIME_SNAPSHOT] symbol=%s positions=%d equity=%.2f margin=%.2f margin_free=%.2f",
               _Symbol,
               positions,
               equity,
               margin,
               margin_free);
}

void OnTimer()
{
   PrintRuntimeSnapshot();
}

実際のEAでは、毎回すべての情報を出すのではなく、ログプロファイルやdebug設定に応じて出力範囲を切り替えると運用しやすくなります。

バックテストでOnTimerを使う時の注意点

バックテストでOnTimerを使う場合、Timerイベントの回数が多くなるとテスト時間が伸びることがあります。

特に、1秒タイマーやミリ秒タイマーで詳細ログ、WebRequest相当の処理、CSV出力、状態スナップショットを多く出すと、検証が重くなります。

注意点問題対策
短いTimer周期OnTimer実行回数が増えるBT用は周期を長めにする
詳細ログ過多Expertsログが膨らむNG時だけ詳細、通常時は要約にする
CSV出力過多ファイルI/Oが増えるイベント時だけ記録する
外部連携相当処理検証速度や再現性に影響するBT時は外部連携をOFFまたはモック化する
ミリ秒タイマー実行回数が非常に多くなる必要な場合だけ使う

Strategy Testerでの検証では、OnTimer用のログ設定、外部連携ON/OFF、Timer周期を別inputにしておくと、速度と確認しやすさを調整できます。

OnTimerログの設計

OnTimerのログは、定期処理の開始、スキップ、成功、失敗、次回実行予定を分けると確認しやすくなります。

ログ名意味確認内容
TIMER_SET_OKTimer設定成功interval、mode、EA version
TIMER_SET_NGTimer設定失敗interval、GetLastError
TIMER_TICKOnTimer開始現在時刻、処理対象
TIMER_SKIP処理見送りthrottle、外部連携OFF、BTモードなど
EXTERNAL_SYNC_OK外部同期成功HTTP status、更新件数、反映状態
EXTERNAL_SYNC_NG外部同期失敗last_error、HTTP status、理由
TIMER_SUMMARY定期要約ログpositions、state、last_sync、last_notify
TIMER_KILLTimer停止deinit reason

OnTimerログは、毎回同じ量を出すのではなく、通常時は要約、異常時は詳細に切り替えると確認しやすくなります。

ログ出力例

[TIMER_SET_OK] seconds=30 mode=external_sync
[TIMER_TICK] server_time=2026.05.26 10:15:00 task=external_sync
[EXTERNAL_SYNC_SKIP] reason=throttle wait_sec=18
[SHEET_FETCH_CONTROL] status=200 result=ok entry_control=ALLOW
[NOTIFY_SKIP] key=runtime_alive reason=duplicate_interval
[RUNTIME_SNAPSHOT] symbol=GOLD positions=2 equity=10000.50 margin=250.00 margin_free=9750.50
[TIMER_SUMMARY] last_sync=2026.05.26 10:15:00 last_notify=2026.05.26 10:10:00
[TIMER_KILL] reason=1

ログ例の時刻、数値、HTTP status、状態名は確認用です。実際のEAでは、外部連携先やログプロファイルに合わせて調整してください。

よくある失敗パターン

失敗パターン問題点確認方法
EventSetTimerを呼んでいないOnTimerが実行されないOnInitでTIMER_SET_OKが出ているか確認する
EventKillTimerを忘れる終了処理の見通しが悪くなるOnDeinitでTIMER_KILLを出す
Timer周期が短すぎるログ過多やBT低速化につながるBT用・実運用用で周期を分ける
WebRequestを毎tick実行する通信回数が多くなり、処理が重くなるOnTimerへ分けてthrottleする
外部連携失敗で売買処理まで止める影響範囲が不明確になる外部連携失敗とentry gateを分ける
通知を重複送信するDiscordやメール通知が多すぎるnotify keyと最小間隔で制御する
BTで外部連携ログを出しすぎる検証ログが膨らみ、速度が落ちるBT時は簡易ログまたはOFFにする

OnTimer処理とあわせて確認したいイベント・時刻管理

OnTimerで外部連携、通知、定期監視を分ける場合は、サーバー時間の扱い、OnTradeTransactionとの責務分離、長時間稼働時の処理負荷もあわせて確認します。

確認したい内容関連ページ確認ポイント
サーバー時間の確認MQL5 TimeCurrentの使い方TimeCurrent、OnTick、OnTimer、サーバー時間、EA稼働時間判定の違いを確認します。
約定イベントの追跡MQL5 OnTradeTransactionで約定を追跡する方法約定、決済、履歴追加、コピーEA同期、重複記録防止をイベント単位で整理します。
長時間稼働EAの実務MQL5長時間稼働EA実務ノートOnTick負荷、OnTimer分離、ログ過多、Object残存、フリーズ対策を確認します。

関連ページ

OnTimerは、イベント処理、WebRequest、長時間稼働、ログファースト開発、CSV出力、外部連携の確認と合わせて整理すると理解しやすくなります。

関連ページ確認できること
MQL5長時間稼働・安定化完全ガイドメモリ、handle、ログ、Object管理、長時間稼働の確認
MQL5デバッグ・ログファースト開発完全ガイドExpertsログ、再現条件、ログ設計の確認
MQL5ファイル操作関数辞典FileOpen、FileWrite、CSV出力、Commonフォルダの確認
EAに外部シート連携を追加したい時に整理することGoogle Sheets、CSV、WebRequest連携の依頼前確認
EAに通知機能を追加したい時に整理することDiscord、メール、通知ログ、送信条件の整理

イベント処理と外部連携全体を確認する場合

OnTimerは、一定間隔で処理を行うためのイベント関数です。外部連携、通知、状態監視、CSV出力、ログ抑制などをOnTickから分けたい場合に使います。イベント処理全体やWebRequestを使った外部連携の設計を確認したい場合は、関連する親記事もあわせて確認してください。

確認したいこと確認するページ主な確認内容
MQL5イベント処理の全体を確認したいMQL5イベント処理完全ガイドOnInit、OnTick、OnTimer、OnTradeTransaction、OnChartEventの使い分け
WebRequestや外部API連携を確認したいMQL5 WebRequest・JSON・外部API実装完全ガイドWebRequest、JSON、Discord通知、Google Sheets連携、外部API処理

OnTimerで外部連携を扱う場合は、Timer周期、WebRequestのtimeout、通知間隔、再送制御、失敗時の扱い、売買処理への影響を分けて確認してください。

開発依頼前に整理したい情報

OnTimerを使った外部連携、通知、CSV出力、状態監視を相談する場合は、次の情報を整理してください。

整理する情報確認内容
対象EA新規EA、既存EA改修、通知ツール、外部連携ツールのどれか
Timer周期何秒ごとに処理したいか、BT用と実運用用を分けるか
処理内容通知、外部制御取得、Google Sheets書き込み、CSV出力、状態監視など
外部連携先Discord、Google Sheets、GAS、外部API、CSVファイルなど
売買への影響外部連携失敗時にentryを止めるか、通知だけ止めるか
ログ方針通常時は要約、失敗時は詳細、BT時は軽量化など
再送制御通知やWebRequestを連続送信しない条件
バックテスト対応外部連携をOFFにするか、モック化するか、ログだけ出すか
機密情報Webhook URL、GAS URL、APIキー、認証情報を公開ログに出さない設計

外部連携や通知の不具合を相談する場合は、Timer設定ログ、WebRequest結果、HTTP status、送信間隔、通知スキップ理由、Expertsログ、Journalログを合わせて確認してください。

MT4/MT5の開発・改修相談はこちら

まとめ

OnTimerは、MQL5 EAで一定間隔の処理を行うためのイベント関数です。

売買判定や注文処理はOnTickやexecution層に残し、外部連携、通知、CSV出力、状態監視、ログ抑制はOnTimerへ分けると、EAの責務を整理しやすくなります。

EventSetTimerは通常OnInitで設定し、EventKillTimerはOnDeinitで呼びます。Timer周期は短くしすぎず、バックテスト時の負荷やログ量も考慮してください。

WebRequest、Discord通知、Google Sheets連携をOnTimerで扱う場合は、送信間隔、失敗時の扱い、再送制御、売買への影響、機密情報の扱いを分けて設計することが重要です。

ABOUT ME
記事URLをコピーしました