MQL5 イベントハンドラ完全ガイド|OnInit・OnTick・OnTimer・OnChartEvent全解説

MQL5のイベントハンドラ関数を完全解説。OnInit・OnDeinit・OnTick・OnTimer・OnChartEvent・OnTrade・OnTester・OnBookEventなど、EA・インジケーター・スクリプトの動作を制御するすべてのイベント関数をコード付きで解説します。

目次

MQL5のイベント駆動モデル

MQL5のプログラムはイベント駆動型です。特定のイベントが発生すると、対応するハンドラ関数が自動的に呼び出されます。C言語のmain()のような「最初から最後まで順に実行」するモデルとは異なります。

イベントハンドラ呼び出しタイミングEAインジスクリプト
OnInit()プログラム起動時×
OnDeinit()プログラム終了時×
OnTick()新しいティック受信時××
OnCalculate()価格データ更新時××
OnTimer()タイマーイベント発生時×
OnChartEvent()チャート操作時×
OnTrade()取引イベント発生時××
OnTradeTransaction()取引トランザクション時××
OnTester()バックテスト終了時××
OnTesterInit()最適化開始時××
OnTesterPass()最適化の各パス完了時××
OnTesterDeinit()最適化終了時××
OnBookEvent()板情報更新時×
OnStart()スクリプト実行時××

OnInit — 初期化

OnInit()はEA/インジケーターがチャートに適用されたとき、時間足が変更されたとき、inputパラメータが変更されたとき、リコンパイル時に呼び出されます。インジケーターハンドルの取得、変数の初期化、タイマー設定などを行います。

// 戻り値の型
int OnInit()
  {
   // INIT_SUCCEEDED (0) — 初期化成功
   // INIT_FAILED — 初期化失敗(EAがチャートから削除される)
   // INIT_PARAMETERS_INCORRECT — パラメータが不正
   // INIT_AGENT_NOT_SUITABLE — テストエージェントが不適合

   return INIT_SUCCEEDED;
  }

実践的なOnInit

#include <Trade\Trade.mqh>

CTrade trade;
int maHandle, rsiHandle;

input int    MA_Period   = 20;
input int    RSI_Period  = 14;
input double Lot         = 0.1;
input long   MagicNumber = 12345;

int OnInit()
  {
   // 1. パラメータの検証
   if(MA_Period < 1 || RSI_Period < 1)
     {
      Print("エラー: 期間は1以上を指定してください");
      return INIT_PARAMETERS_INCORRECT;
     }
   if(Lot < SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN))
     {
      Print("エラー: ロット数が最小ロット未満です");
      return INIT_PARAMETERS_INCORRECT;
     }

   // 2. インジケーターハンドルの取得
   maHandle  = iMA(_Symbol, PERIOD_CURRENT, MA_Period, 0, MODE_EMA, PRICE_CLOSE);
   rsiHandle = iRSI(_Symbol, PERIOD_CURRENT, RSI_Period, PRICE_CLOSE);

   if(maHandle == INVALID_HANDLE || rsiHandle == INVALID_HANDLE)
     {
      Print("インジケーター作成失敗");
      return INIT_FAILED;
     }

   // 3. トレードオブジェクトの設定
   trade.SetExpertMagicNumber(MagicNumber);
   trade.SetDeviationInPoints(10);

   // 4. タイマー設定(必要な場合)
   EventSetTimer(60);  // 60秒ごと

   Print("EA初期化完了: ", _Symbol, " ", EnumToString(_Period));
   return INIT_SUCCEEDED;
  }

OnInit()INIT_FAILEDを返すとEAはチャートから削除されます。致命的なエラー以外ではINIT_SUCCEEDEDを返し、OnTick()内でエラー処理するのが一般的です。

OnDeinit — 終了処理

OnDeinit()はEA/インジケーターが終了する直前に呼ばれます。リソースの解放、タイマーの停止、ファイルのクローズなどを行います。引数のreasonで終了理由がわかります。

void OnDeinit(const int reason)
  {
   // インジケーターハンドルの解放
   if(maHandle != INVALID_HANDLE)  IndicatorRelease(maHandle);
   if(rsiHandle != INVALID_HANDLE) IndicatorRelease(rsiHandle);

   // タイマー停止
   EventKillTimer();

   // チャートオブジェクト削除(必要な場合)
   ObjectsDeleteAll(0, "EA_");  // "EA_"で始まるオブジェクトを全削除

   // 終了理由をログに出力
   string reasons[] = {
      "プログラム削除",        // 0: REASON_PROGRAM
      "手動削除",              // 1: REASON_REMOVE
      "リコンパイル",          // 2: REASON_RECOMPILE
      "時間足/銘柄変更",       // 3: REASON_CHARTCHANGE
      "チャート閉鎖",          // 4: REASON_CHARTCLOSE
      "パラメータ変更",        // 5: REASON_PARAMETERS
      "別アカウント接続",      // 6: REASON_ACCOUNT
      "テンプレート適用",      // 7: REASON_TEMPLATE
      "OnInit失敗",            // 8: REASON_INITFAILED
      "ターミナル終了"         // 9: REASON_CLOSE
   };

   if(reason >= 0 && reason < ArraySize(reasons))
      Print("EA終了: ", reasons[reason]);
   else
      Print("EA終了: reason=", reason);
  }

OnDeinit reason定数一覧

定数意味
REASON_PROGRAM0ExpertRemove()で削除
REASON_REMOVE1チャートから手動削除
REASON_RECOMPILE2リコンパイル
REASON_CHARTCHANGE3時間足または銘柄の変更
REASON_CHARTCLOSE4チャートが閉じられた
REASON_PARAMETERS5inputパラメータの変更
REASON_ACCOUNT6別アカウントに接続
REASON_TEMPLATE7テンプレート適用
REASON_INITFAILED8OnInit()が0以外を返した
REASON_CLOSE9ターミナル終了

OnTick — ティックイベント

OnTick()はEA専用のイベントハンドラで、新しいティック(価格変動)が受信されるたびに呼び出されます。EAのメインロジック(エントリー判定、ポジション管理等)はすべてこの中に書きます。

void OnTick()
  {
   // 1. 新しいバーの検出(バー確定時のみ処理する場合)
   static datetime lastBarTime = 0;
   datetime currentBarTime = iTime(_Symbol, PERIOD_CURRENT, 0);

   if(currentBarTime == lastBarTime)
      return;  // 同じバー内の2回目以降のティックは無視

   lastBarTime = currentBarTime;

   // 2. インジケーター値の取得
   double ma[];
   ArraySetAsSeries(ma, true);
   if(CopyBuffer(maHandle, 0, 0, 3, ma) < 3) return;

   // 3. エントリー条件の判定
   // ...

   // 4. ポジション管理
   // ...
  }
重要

OnTick()はティックが来ない限り呼ばれません。週末やメンテナンス中は一切実行されません。時間に基づく処理が必要な場合はOnTimer()を併用してください。

新しいバーの検出パターン

// 方法1: iTime()で比較(シンプル)
bool IsNewBar()
  {
   static datetime lastBar = 0;
   datetime current = iTime(_Symbol, PERIOD_CURRENT, 0);

   if(current != lastBar)
     {
      lastBar = current;
      return true;
     }
   return false;
  }

// 方法2: iBars()で比較(より軽量)
bool IsNewBar2()
  {
   static int lastBars = 0;
   int current = iBars(_Symbol, PERIOD_CURRENT);

   if(current != lastBars)
     {
      lastBars = current;
      return true;
     }
   return false;
  }

// 使用例
void OnTick()
  {
   if(!IsNewBar()) return;

   // ここはバー確定時のみ実行される
   Print("新しいバー: ", iTime(_Symbol, PERIOD_CURRENT, 0));
  }

バー確定時のみ処理することで、EAの負荷を大幅に軽減できます。1時間足EAなら1時間に1回しか判定しないため、バックテストも高速化されます。トレーリングストップのようにティックごとに処理が必要な部分は、新バー判定の外に書きます。

OnTimer — タイマーイベント

OnTimer()はタイマーイベントで定期的に呼び出されます。ティックに依存しない定期処理(パネル更新、ログ記録、ニュース監視等)に使用します。

int OnInit()
  {
   // 秒単位でタイマー設定
   EventSetTimer(60);        // 60秒ごと

   // ミリ秒単位(より精密)
   // EventSetMillisecondTimer(500);  // 500msごと

   return INIT_SUCCEEDED;
  }

void OnTimer()
  {
   // 60秒ごとに呼ばれる
   Print("Timer: ", TimeCurrent());

   // ダッシュボード更新
   UpdateDashboard();

   // 日次レポート(特定時刻に処理)
   MqlDateTime dt;
   TimeCurrent(dt);
   if(dt.hour == 23 && dt.min == 59)
      GenerateDailyReport();
  }

void OnDeinit(const int reason)
  {
   EventKillTimer();  // タイマー停止(必須)
  }

EventSetMillisecondTimer()を短い間隔で設定するとCPU負荷が高くなります。100ms以下は避けてください。また、タイマーは1つのプログラムにつき1つだけです。2回目のEventSetTimer()は前の設定を上書きします。

OnChartEvent — チャートイベント

OnChartEvent()はチャート上でユーザーが操作を行ったときに呼ばれます。ボタンクリック、キーボード入力、マウス移動、オブジェクトのドラッグ等を検知できます。EA上にGUIパネルを作る場合に必須です。

void OnChartEvent(const int    id,
                  const long   &lparam,
                  const double &dparam,
                  const string &sparam)
  {
   // ボタンクリック
   if(id == CHARTEVENT_OBJECT_CLICK)
     {
      if(sparam == "btnBuy")
        {
         Print("買いボタンがクリックされました");
         // ボタン状態をリセット
         ObjectSetInteger(0, "btnBuy", OBJPROP_STATE, false);
        }
      if(sparam == "btnSell")
        {
         Print("売りボタンがクリックされました");
         ObjectSetInteger(0, "btnSell", OBJPROP_STATE, false);
        }
     }

   // キーボード入力
   if(id == CHARTEVENT_KEYDOWN)
     {
      // lparamにキーコードが入る
      if(lparam == 'B')
         Print("Bキーが押されました");
      if(lparam == 27)  // ESCキー
         Print("ESCキーが押されました");
     }

   // マウスクリック
   if(id == CHARTEVENT_CLICK)
     {
      int x = (int)lparam;
      int y = (int)dparam;
      Print("クリック位置: x=", x, " y=", y);

      // ピクセル座標を時間・価格に変換
      datetime time;
      double   price;
      int      window;
      if(ChartXYToTimePrice(0, x, y, window, time, price))
         Print("時間=", time, " 価格=", price);
     }

   // カスタムイベント(EventChartCustom()で送信)
   if(id >= CHARTEVENT_CUSTOM)
     {
      int customId = id - CHARTEVENT_CUSTOM;
      Print("カスタムイベント: id=", customId, " ", sparam);
     }
  }

CHARTEVENT定数一覧

定数意味lparamdparamsparam
CHARTEVENT_KEYDOWNキー押下キーコード繰り返し回数キー状態
CHARTEVENT_MOUSE_MOVEマウス移動X座標Y座標フラグ
CHARTEVENT_OBJECT_CREATEオブジェクト作成--オブジェクト名
CHARTEVENT_OBJECT_CHANGEオブジェクト変更--オブジェクト名
CHARTEVENT_OBJECT_DELETEオブジェクト削除--オブジェクト名
CHARTEVENT_CLICKチャートクリックX座標Y座標-
CHARTEVENT_OBJECT_CLICKオブジェクトクリックX座標Y座標オブジェクト名
CHARTEVENT_OBJECT_DRAGオブジェクト移動--オブジェクト名
CHARTEVENT_OBJECT_ENDEDITテキスト編集完了--オブジェクト名
CHARTEVENT_CHART_CHANGEチャートプロパティ変更---
CHARTEVENT_CUSTOMカスタムイベント任意任意任意

ボタン付きパネルの作成例

#include <Trade\Trade.mqh>
CTrade trade;

void CreatePanel()
  {
   // 買いボタン
   ObjectCreate(0, "btnBuy", OBJ_BUTTON, 0, 0, 0);
   ObjectSetInteger(0, "btnBuy", OBJPROP_XDISTANCE, 20);
   ObjectSetInteger(0, "btnBuy", OBJPROP_YDISTANCE, 30);
   ObjectSetInteger(0, "btnBuy", OBJPROP_XSIZE, 100);
   ObjectSetInteger(0, "btnBuy", OBJPROP_YSIZE, 30);
   ObjectSetString(0, "btnBuy", OBJPROP_TEXT, "BUY");
   ObjectSetInteger(0, "btnBuy", OBJPROP_COLOR, clrWhite);
   ObjectSetInteger(0, "btnBuy", OBJPROP_BGCOLOR, clrDodgerBlue);
   ObjectSetInteger(0, "btnBuy", OBJPROP_FONTSIZE, 10);

   // 売りボタン
   ObjectCreate(0, "btnSell", OBJ_BUTTON, 0, 0, 0);
   ObjectSetInteger(0, "btnSell", OBJPROP_XDISTANCE, 130);
   ObjectSetInteger(0, "btnSell", OBJPROP_YDISTANCE, 30);
   ObjectSetInteger(0, "btnSell", OBJPROP_XSIZE, 100);
   ObjectSetInteger(0, "btnSell", OBJPROP_YSIZE, 30);
   ObjectSetString(0, "btnSell", OBJPROP_TEXT, "SELL");
   ObjectSetInteger(0, "btnSell", OBJPROP_COLOR, clrWhite);
   ObjectSetInteger(0, "btnSell", OBJPROP_BGCOLOR, clrCrimson);
   ObjectSetInteger(0, "btnSell", OBJPROP_FONTSIZE, 10);

   // 全決済ボタン
   ObjectCreate(0, "btnCloseAll", OBJ_BUTTON, 0, 0, 0);
   ObjectSetInteger(0, "btnCloseAll", OBJPROP_XDISTANCE, 240);
   ObjectSetInteger(0, "btnCloseAll", OBJPROP_YDISTANCE, 30);
   ObjectSetInteger(0, "btnCloseAll", OBJPROP_XSIZE, 100);
   ObjectSetInteger(0, "btnCloseAll", OBJPROP_YSIZE, 30);
   ObjectSetString(0, "btnCloseAll", OBJPROP_TEXT, "CLOSE ALL");
   ObjectSetInteger(0, "btnCloseAll", OBJPROP_COLOR, clrWhite);
   ObjectSetInteger(0, "btnCloseAll", OBJPROP_BGCOLOR, clrDimGray);

   ChartRedraw();
  }

void OnChartEvent(const int id, const long &lparam,
                  const double &dparam, const string &sparam)
  {
   if(id != CHARTEVENT_OBJECT_CLICK) return;

   if(sparam == "btnBuy")
     {
      trade.Buy(0.1, _Symbol);
      ObjectSetInteger(0, "btnBuy", OBJPROP_STATE, false);
     }
   else if(sparam == "btnSell")
     {
      trade.Sell(0.1, _Symbol);
      ObjectSetInteger(0, "btnSell", OBJPROP_STATE, false);
     }
   else if(sparam == "btnCloseAll")
     {
      for(int i = PositionsTotal() - 1; i >= 0; i--)
        {
         ulong ticket = PositionGetTicket(i);
         if(PositionGetString(POSITION_SYMBOL) == _Symbol)
            trade.PositionClose(ticket);
        }
      ObjectSetInteger(0, "btnCloseAll", OBJPROP_STATE, false);
     }
  }

OnTrade — 取引イベント

OnTrade()は注文の発注・変更・削除、ポジションのオープン・クローズ・変更など、取引に関するイベントが発生したときに呼ばれます。OnTradeTransaction()よりシンプルですが、詳細な情報は取得できません。

void OnTrade()
  {
   // ポジション数の変化を検知
   static int lastPositions = 0;
   int currentPositions = PositionsTotal();

   if(currentPositions > lastPositions)
      Print("新しいポジションがオープンしました 現在: ", currentPositions);
   else if(currentPositions < lastPositions)
      Print("ポジションがクローズされました 現在: ", currentPositions);

   lastPositions = currentPositions;

   // 待機注文の変化を検知
   static int lastOrders = 0;
   int currentOrders = OrdersTotal();

   if(currentOrders != lastOrders)
     {
      Print("待機注文数が変化: ", lastOrders, " → ", currentOrders);
      lastOrders = currentOrders;
     }
  }

OnTrade()OnTradeTransaction()は同じ取引イベントに対して両方呼ばれます。詳細な約定情報が必要ならOnTradeTransaction()、単にポジション数の変化だけを見るならOnTrade()が適しています。

OnCalculate — インジケーター計算

OnCalculate()はカスタムインジケーター専用のイベントハンドラです。価格データが更新されるたびに呼ばれ、インジケーターバッファに値を格納します。2つのオーバーロードがあります。

// 形式1: OHLCVデータを受け取る(一般的)
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[],
                const long &volume[],
                const int &spread[])
  {
   // 最初の呼び出しではprev_calculated=0(全バー計算)
   // 2回目以降はprev_calculated=rates_total-1(最新バーのみ再計算)
   int start = (prev_calculated == 0) ? 0 : prev_calculated - 1;

   for(int i = start; i < rates_total; i++)
     {
      // ここでインジケーターバッファに値をセット
      // Buffer[i] = ... ;
     }

   return rates_total;  // 次回のprev_calculatedに渡される
  }

// 形式2: 単一のデータ配列を受け取る(他のインジケーターに適用する場合)
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const int begin,            // 有効データの開始位置
                const double &price[])       // 適用価格データ
  {
   int start = (prev_calculated == 0) ? begin : prev_calculated - 1;

   for(int i = start; i < rates_total; i++)
     {
      // price[i] は選択された適用価格
      // Buffer[i] = ... ;
     }

   return rates_total;
  }

カスタムSMAインジケーターの完全例

#property indicator_chart_window
#property indicator_buffers 1
#property indicator_plots   1
#property indicator_label1  "My SMA"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrDodgerBlue
#property indicator_width1  2

input int Period = 20;

double SMA_Buffer[];

int OnInit()
  {
   SetIndexBuffer(0, SMA_Buffer, INDICATOR_DATA);
   PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, Period - 1);
   IndicatorSetString(INDICATOR_SHORTNAME, "MySMA(" + IntegerToString(Period) + ")");
   return INIT_SUCCEEDED;
  }

int OnCalculate(const int rates_total,
                const int prev_calculated,
                const int begin,
                const double &price[])
  {
   if(rates_total < Period) return 0;

   int start;
   if(prev_calculated == 0)
     {
      start = begin + Period - 1;
      // 最初のSMAを計算
      double sum = 0;
      for(int i = begin; i < start; i++)
         sum += price[i];
      sum += price[start];
      SMA_Buffer[start] = sum / Period;
      start++;
     }
   else
      start = prev_calculated - 1;

   // 逐次計算(前のSMAから差分で計算、高速)
   for(int i = start; i < rates_total; i++)
      SMA_Buffer[i] = SMA_Buffer[i - 1] + (price[i] - price[i - Period]) / Period;

   return rates_total;
  }

OnTester — バックテスト終了時

OnTester()はストラテジーテスターでのバックテストが完了した直後に呼ばれます。カスタム最適化基準を返すことができます。

double OnTester()
  {
   // テスト結果の統計を取得
   double profit     = TesterStatistics(STAT_PROFIT);
   double maxDD      = TesterStatistics(STAT_EQUITY_DDREL_PERCENT);
   int    totalTrades = (int)TesterStatistics(STAT_TRADES);
   double profitFactor = TesterStatistics(STAT_PROFIT_FACTOR);
   double sharpe     = TesterStatistics(STAT_SHARPE_RATIO);

   Print("=== バックテスト結果 ===");
   Print("純利益: ", profit);
   Print("最大DD: ", maxDD, "%");
   Print("取引数: ", totalTrades);
   Print("PF: ", profitFactor);
   Print("シャープ: ", sharpe);

   // カスタム最適化基準を返す
   // 例: 利益をDDで割ったリカバリーファクター
   if(maxDD == 0) return 0;
   if(totalTrades < 30) return 0;  // 取引数が少なすぎる場合は0

   double recoveryFactor = profit / (maxDD / 100.0 * TesterStatistics(STAT_INITIAL_DEPOSIT));

   return recoveryFactor;  // この値が最大化される
  }

OnTester()の戻り値は、最適化で「カスタム最大」を選択した場合の最適化基準になります。リカバリーファクター、シャープレシオ、プロフィットファクターなど、自分にとって重要な指標を返してください。

OnTesterInit / OnTesterPass / OnTesterDeinit — 最適化制御

最適化の前後に呼ばれるイベントハンドラです。最適化の全体管理、各パスの結果収集、フレーム処理に使用します。

// 最適化開始前(メインチャートのEAで呼ばれる)
void OnTesterInit()
  {
   Print("最適化を開始します...");
  }

// 各最適化パスが完了するたびに呼ばれる
void OnTesterPass()
  {
   // FrameFirst() / FrameNext() でフレームデータを読み取る
   ulong  pass;
   string name;
   long   id;
   double value;

   if(FrameFirst())
     {
      FrameInputs(name, pass);
      FrameNext(pass, name, id, value);
      PrintFormat("パス #%d: %s = %.2f", pass, name, value);
     }
  }

// 最適化完了後
void OnTesterDeinit()
  {
   Print("最適化が完了しました");
  }

// テスターのOnTester()内でフレームを送信
double OnTester()
  {
   double result = TesterStatistics(STAT_PROFIT);

   // フレームとしてメインチャートに送信
   FrameAdd("Profit", 1, result, NULL);

   return result;
  }

OnBookEvent — 板情報イベント

OnBookEvent()は板情報(Depth of Market / DOM)が更新されたときに呼ばれます。事前にMarketBookAdd()で購読を開始する必要があります。

int OnInit()
  {
   // 板情報の購読を開始
   if(!MarketBookAdd(_Symbol))
      Print("板情報の購読に失敗: ", GetLastError());

   return INIT_SUCCEEDED;
  }

void OnBookEvent(const string &symbol)
  {
   if(symbol != _Symbol) return;

   MqlBookInfo book[];
   if(MarketBookGet(_Symbol, book))
     {
      for(int i = 0; i < ArraySize(book); i++)
        {
         PrintFormat("Type=%s Price=%.5f Volume=%d",
                     (book[i].type == BOOK_TYPE_SELL) ? "SELL" : "BUY",
                     book[i].price, (int)book[i].volume);
        }
     }
  }

void OnDeinit(const int reason)
  {
   MarketBookRelease(_Symbol);  // 購読解除
  }

OnStart — スクリプト実行

OnStart()はスクリプト専用のイベントハンドラです。スクリプトはチャートに適用されるとOnStart()が1回だけ実行され、完了後に自動的に削除されます。

// 全ポジション一括決済スクリプト
#include <Trade\Trade.mqh>

void OnStart()
  {
   CTrade trade;
   int closed = 0;

   for(int i = PositionsTotal() - 1; i >= 0; i--)
     {
      ulong ticket = PositionGetTicket(i);
      if(ticket == 0) continue;

      if(trade.PositionClose(ticket))
         closed++;
      else
         Print("決済失敗: #", ticket, " Error=", GetLastError());
     }

   Print("決済完了: ", closed, "ポジション");
   // スクリプトはここで自動的に終了・削除される
  }

カスタムイベント(EventChartCustom)

EventChartCustom()を使うと、自分でイベントを発生させてOnChartEvent()で受け取ることができます。EAの異なるモジュール間の通信や、非同期処理の通知に使えます。

// カスタムイベントIDの定義
#define EVENT_TRADE_OPENED   0
#define EVENT_TRADE_CLOSED   1
#define EVENT_SL_HIT         2

// イベントを発火
void NotifyTradeOpened(ulong ticket, double price)
  {
   EventChartCustom(0,                    // チャートID(0=自分のチャート)
                    EVENT_TRADE_OPENED,    // カスタムイベントID
                    (long)ticket,          // lparam
                    price,                 // dparam
                    "Trade Opened"         // sparam
                    );
  }

// イベントを受信
void OnChartEvent(const int id, const long &lparam,
                  const double &dparam, const string &sparam)
  {
   if(id == CHARTEVENT_CUSTOM + EVENT_TRADE_OPENED)
     {
      Print("取引オープン通知: ticket=", lparam, " price=", dparam);
      // ここでGUI更新、ログ記録等を行う
     }
   else if(id == CHARTEVENT_CUSTOM + EVENT_TRADE_CLOSED)
     {
      Print("取引クローズ通知: ticket=", lparam, " PL=", dparam);
     }
  }

イベントの実行順序

MQL5のイベントハンドラは以下の優先順位で実行されます。同時に複数のイベントがキューに入った場合、この順序で処理されます。

  1. OnInit() — 最初に1回だけ
  2. OnTick() / OnCalculate() — 最優先で処理
  3. OnTimer() — ティックイベントの次
  4. OnTrade() / OnTradeTransaction() — 取引イベント
  5. OnChartEvent() — ユーザー操作イベント
  6. OnBookEvent() — 板情報イベント
  7. OnDeinit() — 最後に1回だけ

すべてのイベントハンドラはシングルスレッドで実行されます。OnTick()の処理中にOnTimer()が呼ばれることはありません。OnTick()の処理に時間がかかると、その間に発生したタイマーイベントやチャートイベントはキューに溜まり、順番に処理されます。

プロが開発したEAをお探しの方は → シストレ.COM EA一覧

シストレ.COMで実績のあるEAが使い放題!/
無料会員登録はこちら
FX自動売買でEAを探すなら
シストレ.COM
実績あるEAが無料
厳格な審査を乗り越えた実績のあるEAが無料で使えます!
自由な口座選び
有料版を購入し柔軟な口座選びが可能!
フォワードテスト公開
全EAのフォワードテスト結果を公開中!
FX初心者も安心
初心者の方も安心して取引を始められます。
多様なEA選択肢
様々な種別のEAをご用意!自分の手法にあった取引が可能です。
信頼のFX会社と提携
人気のFX会社と提携中!様々なFX会社から選べます。
1分で登録完了!EA探すならシストレ.COM!/
無料会員登録はこちら
【FX自動売買】システムトレード完全ガイド|Forex Guide

この記事が気に入ったら
フォローしてね!

お役立ち情報をシェアする
  • URLをコピーしました!
目次