MQL4のOnTick・OnInit・OnDeinitなどのイベント関数は、決まったタイミングでMT4から自動的に呼ばれ、EAやインジケーターの動きを決めます。
結論として、EAではOnInit(読み込み時)→OnTick(ティック受信ごと)→OnDeinit(終了時)の順に呼ばれ、売買ロジックはOnTickに書きます。時間足・通貨ペアやパラメータを変えたときは、OnDeinitのあとOnInitがもう一度呼ばれます。スクリプトはOnStart、インジケーターはOnCalculateが中心で、定期処理はOnTimerで行います。
各関数の書き方をコード例で示し、旧形式(init/start/deinit)との対応、つまずきやすい点、MQL5(MT5)での違いもまとめました。
イベント関数とは?
イベント関数とは、特定の事象や状態変化が発生した際にMT4から自動的に呼び出される関数です。自分で呼び出すのではなく、決まった名前で定義しておくとMT4が適切なタイミングで実行してくれます。
EAでイベント関数が呼ばれる流れ
MQL4のイベント関数にはどんな種類がある?一覧表
MQL4の主なイベント関数は8つで、プログラムの種類(EA・インジケーター・スクリプト)ごとに使える関数が決まっています。
主なイベント関数
ここでは8つのイベント関数それぞれについて、呼ばれるタイミング・書くべき処理・最小限のコード例を順に説明します。EAを作るなら、まずOnInit・OnTick・OnDeinitの3つを押さえれば動かせます。
OnStart
スクリプトの開始時に1回だけ呼び出される関数です。「全ポジションを一括決済する」のような、1回きりの処理を書きます。EAでは使いません。
void OnStart()
{
// ここに処理を記載
}
OnInit
EAやカスタムインジケーターがチャートにロードされる際に呼び出されます。通貨ペア・時間足や入力パラメータを変えたとき、再コンパイルしたとき(EAは口座を切り替えたときも)にも、OnDeinitのあとで再び呼ばれます。パラメータの検証、タイマーの設定、グローバル変数の初期化など、起動時の処理を書きます。
int OnInit()
{
// ここに処理を記載
// 処理結果
return(INIT_SUCCEEDED);
}
戻り値でINIT_FAILEDを返すと初期化失敗として扱われ、EAは動作を始めずに停止します。パラメータが不正なときにEAを止める用途に使えます。ただしMQL4では、ソースに#property strictを書いてコンパイルしたときだけ戻り値が評価されます。
OnDeinit
EAやインジケーターがチャートから削除されるときやターミナルを閉じるときのほか、通貨ペア・時間足・パラメータを変えたときや再コンパイルしたときにも(再初期化の前に)実行されます。どの理由で呼ばれたかは引数reasonで分かります(下の表)。オブジェクトの削除やタイマーの停止など、後片付けを書きます。
void OnDeinit(const int reason)
{
// ここに処理を記載
}
OnTick
新しい価格データ(ティック)が受信されるたびに呼び出されます。EAの売買ロジックは基本的にこの中に書きます。
void OnTick()
{
// ここに処理を記載
}
OnTickはティックを受信するたびに呼ばれ、相場が活発な時間帯には1秒間に複数回実行されます。「足が確定したときだけ判定したい」場合は、新しい足ができたかを自分で検出する必要があります(後述)。
OnTimer
EventSetTimer関数で指定した秒数ごとに呼ばれます。「1分ごとにポジションを確認する」「価格が動かない週末でも処理したい」といった定期処理に使います。
int OnInit()
{
EventSetTimer(60);
return(INIT_SUCCEEDED);
}
void OnTimer()
{
// ここに処理を記載
}
OnInitでEventSetTimerを呼んだら、OnDeinitで必ずEventKillTimerを呼んでタイマーを止めます。MQL4公式ドキュメントでも、EventSetTimerはOnInitで1回、EventKillTimerはOnDeinitで1回呼ぶことが推奨されています。
OnTester
ストラテジーテスターでのテストが完了したときに呼ばれ、戻り値が最適化の評価値(カスタム基準)として使われます。「プロフィットファクター×取引回数」のような独自の評価指標で最適化したいときに使います。
あわせて読む
MT4バックテストのやり方【初心者向け】EAの設定と結果の見方MT4でEAをバックテストするやり方を画像付きで解説。ヒストリカルデータの準備、ストラテジーテスターのモデル・スプレッド設定、モデリング品質90%の意味、PF・最大ドローダウンなど結果の見方までわかります。
double OnTester()
{
double result = 0.0;
// ここで評価値を計算してresultに入れる
return(result);
}
OnChartEvent
チャート上のマウスクリックやキーボード操作、オブジェクトの移動などのイベントを処理します(オブジェクトの作成・削除やマウス移動のイベントは、チャートのプロパティCHART_EVENT_OBJECT_CREATE等をtrueにしたときだけ届きます)。チャート上にボタンを置いて手動操作するEAで使います。
void OnChartEvent(
const int id, // イベントID
const long& lparam, // long型イベント
const double& dparam, // double型イベント
const string& sparam) // string型イベント
{
// ここに処理を記載
}
OnCalculate
カスタムインジケーターの値を計算するための関数です。ティックごとに呼ばれ、prev_calculatedを使うと未計算のバーだけを計算できます。
int OnCalculate(const int rates_total, // 入力された時系列のバー数
const int prev_calculated, // 計算済み(前回呼び出し時)のバー数
const datetime &time[], // 時間
const double &open[], // 始値
const double &high[], // 高値
const double &low[], // 安値
const double &close[], // 終値
const long &tick_volume[], // Tick出来高
const long &volume[], // Real出来高
const int &spread[]) // スプレッド
{
// ここに処理を記載
// 戻り値は次回呼び出し時のprev_calculatedになる
return(rates_total);
}
旧形式(init / start / deinit)との対応
ビルド600より前のMQL4では、関数名がinit・start・deinitでした。古いEAのソースコードを読むときはこの対応表で読み替えてください。
旧形式のままでもコンパイルはできますが、新規に書くなら新形式を使います。
あわせて読む
MT4(MQL4)EAソースコード公開サイト11選と動かし方MT4(MQL4)のEAソースコードを無料で公開しているサイト11選。付属のMACD Sample、日本語の学習サイト、MQL5コードベース、GitHubをレベル別に紹介し、コンパイルして動かす手順も解説します。
MQL4のイベント関数の応用例
応用例のポイントは、初期化はOnInit、後片付けはOnDeinit、売買判定はOnTick、時間ベースの処理はOnTimer、手動操作はOnChartEventと役割を分けて書くことです。以下では、それぞれの実践的な使い方をコード付きで紹介します。
EAのライフサイクルとイベント関数の役割
OnTimer=EventSetTimerで指定した間隔(ストラテジーテスターでは処理されない)
OnChartEvent=クリック・キー操作などチャートのイベント
売買判定はOnTick、時間ベースの処理はOnTimer、手動操作はOnChartEvent、後片付けはOnDeinitと役割を分けて書く。
OnInit()の活用例
OnInitは初期パラメータの設定やリソースの読み込みに使います。外部のCSVファイルからパラメータを読み込んだり、初期の取引戦略を設定したりします。
int OnInit()
{
// パラメータの読み込みや初期設定
return(INIT_SUCCEEDED);
}
OnDeinit()の活用例
OnDeinitではオブジェクトの解放やログの保存など、終了に関連するタスクを実行します。
void OnDeinit(const int reason)
{
// オブジェクトの解放やログの保存
}
OnTick()の活用例
OnTickには取引の主要な処理を書きます。
void OnTick()
{
double currentPrice = Close[0];
// 価格が特定の条件を満たす場合に取引を実行
if(currentPrice > SOME_THRESHOLD)
{
// ロングポジションをオープン
}
}
足の確定ごとに1回だけ判定したい場合は、次のように新しい足の開始を検出します。EA作成で最もよく使うパターンです。
datetime lastBarTime = 0;
void OnTick()
{
// 新しい足ができたときだけ処理する
if(Time[0] == lastBarTime) return;
lastBarTime = Time[0];
// ここに足の確定ごとの売買判定を書く(Close[1]など確定足を使う)
}
OnTimer()の活用例
OnTimerは特定の時間間隔で動作します。1時間ごとに何らかのアクションをトリガーしたい場合などに役立ちます。
void OnTimer()
{
// 1時間ごとに特定のアクションを実行
}
OnChartEvent()の活用例
ユーザーの操作やチャート上のイベントをトリガーとして処理を行いたい場合はOnChartEventを使います。
void OnChartEvent(const int id,
const long &lparam,
const double &dparam,
const string &sparam)
{
// ユーザーのアクションに応じた処理
}
イベント関数でつまずきやすいポイントは?
イベント関数のトラブルの多くは、関数が「いつ・何回」呼ばれるかの誤解から起きます。代表的な症状と対処を表にまとめました。
OnTick・新しい足の検出・OnTimerが呼ばれるタイミング
※ティックの届き方・足の長さ・タイマー間隔は説明用の架空の例です。ストラテジーテスターではTimerイベントは処理されません。
MQL4の基本から自作EAを作る手順は以下の記事で解説しています。
併せて読む
FX EAの自作・作り方|MQL4で始める初心者向けEA開発入門FXのEAはMT4付属のMetaEditorとMQL4で無料で自作できます。必要なもの・難しさ、ひな形作成からコンパイル・バックテストまでの手順と全コード、未経験者向けのノーコードツール・ChatGPT・作成代行も解説します。
MQL5(MT5)のOnTick・OnTimerはMQL4と何が違う?
OnTick・OnTimer・OnInit・OnDeinit・OnCalculate・OnChartEvent・OnTester・OnStartは、MQL5でも同じ名前・同じ役割です。OnTickがEA専用でティックごとに呼ばれる点、OnInitでEventSetTimerを呼びOnDeinitでEventKillTimerを呼ぶ流れも変わりません。違いは主に、ストラテジーテスターでのOnTimerの扱い、MQL5にしかないイベント関数、価格・時刻の取り方の3点です。
表のMQL5側は、MQL5公式リファレンス(イベント処理・OnTimer・OnInit・取引ストラテジーのテスト)の記載に基づいています。MQL5ではテスターでもOnTimerが呼ばれるため、MQL4で必要だった「OnTick内で時刻を判定する」回避策は必須ではありません。
MQL5だけにあるイベント関数
MQL5には、取引サーバーからの通知や最適化の進行を受け取るためのイベント関数が追加されています。
- OnTrade:注文・ポジション・取引履歴が変わったときに呼ばれる(EA専用)
- OnTradeTransaction:取引リクエストの実行結果を1件ずつ受け取る。引数のtrans・request・resultで約定や注文変更の中身を確認できる(EA専用)
- OnBookEvent:板情報が変わったときに呼ばれる。事前にMarketBookAddで銘柄の購読を始めておく必要がある
- OnTesterInit・OnTesterPass・OnTesterDeinit:ストラテジーテスターでの最適化の開始前・各パスの結果受信時・終了後に呼ばれる
OnTradeとOnTradeTransactionの呼び出し回数は1対1に対応しません。約定ごとに処理したい場合は、OnTradeTransactionで取引の種類(trans.type)を見て分岐させます。
MQL5で新しい足を検出するOnTick
MQL5にはTime[0]のような定義済み配列がないため、MQL4の「新しい足の検出」コードはそのままでは動きません。iTime()で現在の足の開始時刻を取って比較します。iTimeはエラー時に0を返すので、0のときは処理しないようにしています。
datetime lastBarTime = 0;
void OnTick()
{
// MQL5にはTime[]がないため、iTimeで現在の足の開始時刻を取る
datetime barTime = iTime(_Symbol, PERIOD_CURRENT, 0);
if(barTime == 0 || barTime == lastBarTime) return; // 取得失敗(0)か同じ足なら何もしない
lastBarTime = barTime;
// ここに足の確定ごとの売買判定を書く(確定足はiClose(_Symbol, PERIOD_CURRENT, 1)など)
}
よくある質問
Q1. OnTickとOnStartの違いは何ですか?
A1. OnTickはEA専用で、新しいティックを受信するたびに呼ばれます。OnStartはスクリプト専用で、起動時に1回だけ呼ばれます。MQL4公式ドキュメントでも、StartイベントはEAやカスタムインジケーターには送られないと明記されています。
Q2. OnTickの処理中に次のティックが届いたらどうなりますか?
A2. そのティックは無視されます。MQL4では、OnTickの処理中に届いた新しいティックはイベントキューに積まれないためです。OnTickに重い処理を書くとティックを取りこぼすので、処理は軽く保ちます。
Q3. OnInitでINIT_FAILEDを返すとどうなりますか?
A3. 初期化失敗として扱われ、Deinitイベントが発生してEAは停止します。このときOnDeinitの引数reasonにはREASON_INITFAILED(値は8)が渡されます。パラメータ不正時にEAを動かさない用途に使えます。MQL4では#property strictを付けてコンパイルしたときだけ戻り値が評価されます。
Q4. OnDeinitに時間のかかる処理を書いてもよいですか?
A4. 避けるべきです。公式ドキュメントでは、OnDeinitの実行は2.5秒に制限され、時間内に終わらなければ強制終了されると定められています。ファイル保存などは短時間で終わる処理にとどめます。
Q5. OnTimerの呼び出し間隔はどう指定しますか?
A5. OnInitでEventSetTimer(秒数)を呼んで指定します。タイマーは1つのプログラムにつき1つまでです。1秒未満の間隔が必要ならEventSetMillisecondTimer()を使い、OnDeinitでEventKillTimer()を呼んで止めます。
Q6. カスタムインジケーターでOnTickは使えますか?
A6. 使えません。OnTickはEA専用のイベント関数です。インジケーターではOnCalculateがティックごとの計算を担い、定期処理にはOnTimerを使えます。
Q7. OnTickで足の確定ごとに1回だけ処理するにはどうしますか?
A7. 現在の足の開始時刻Time[0]を変数に保存し、値が変わったときだけ処理します。判定には確定済みのClose[1]などを使うと、1本の足で何度もエントリーする問題を防げます。
Q8. MQL5でもOnTickやOnTimerの書き方は同じですか?
A8. 関数名と役割は同じです。OnTickはEA専用でティックごとに呼ばれ、OnTimerはOnInitでEventSetTimer()を呼んで動かし、OnDeinitでEventKillTimer()で止めます。違うのは、MQL5ではストラテジーテスターでもOnTimerが呼ばれること、Time[0]などの定義済み配列がなくiTime()等で価格・時刻を取ること、OnTradeTransactionなどMQL5固有のイベント関数があることです。
まとめ
- EAはOnInit(読み込み時)→ OnTick(ティックごと)→ OnDeinit(終了時)の順に呼ばれる。時間足やパラメータを変えるとOnDeinit→OnInitが再び呼ばれる
- 売買ロジックはOnTickに書く。足の確定ごとに判定するなら新しい足の検出が必要
- 定期処理はOnTimer、終了時の後片付けはOnDeinit、独自の最適化基準はOnTester
- 旧形式のinit/start/deinitは新形式のOnInit/OnTick/OnDeinitに対応
- MQL5でも主要なイベント関数は同名。テスターでOnTimerが呼ばれる点、Time[]がない点、OnTradeTransaction等の固有関数に注意


