【MQL5】OnTradeTransaction関数の使い方と自動売買実装コード

1. OnTradeTransaction関数の概要と実務での活用法

MQL5におけるOnTradeTransactionは、取引口座で発生した「あらゆる変化(トランザクション)」をリアルタイムで検知するためのイベントハンドラです。注文の発注、約定、指値の変更、ストップロスの発動など、サーバー側で取引状態が更新されるたびにこの関数が呼び出されます。

多くの開発者が、注文の成否を確認するためにOnTick内でループを回して履歴をチェックしたり、OnTrade関数(詳細な情報を持たない古いイベント)を使おうとして挫折します。しかし、実務レベルのEA開発において、約定後のチケット番号取得や決済の正確な検知には、このOnTradeTransactionの活用が不可欠です。

特に「エントリー直後に決済逆指値(SL)が正しく設定されたか」や「部分約定が発生したか」といった、ミリ秒単位の正確性が求められるロジックを実装する場合、この関数を使いこなすことで、堅牢で信頼性の高いシステムを構築できます。

2. 構文と戻り値

OnTradeTransactionは戻り値を持たないvoid型の関数です。以下の3つの引数を通じて、取引の詳細情報を受け取ります。

void OnTradeTransaction(
   const MqlTradeTransaction&    trans,     // 取引トランザクションの構造体
   const MqlTradeRequest&        request,   // リクエストの詳細(自分のEAが送った場合など)
   const MqlTradeResult&         result     // リクエストの結果
);
  • trans (MqlTradeTransaction): 発生したイベントの種類(新規注文、履歴への追加など)や、対象のチケット番号、価格、数量などの詳細が含まれます。
  • request (MqlTradeRequest): OrderSendなどで送信したリクエスト内容が含まれます。
  • result (MqlTradeResult): サーバーからの応答(リターンコードなど)が含まれます。

この関数は、1つの注文に対して複数回呼び出されるのが特徴です(例:注文受付時、約定時、履歴追加時の計3回など)。そのため、trans.typeを確認して必要なタイミングだけを抽出する処理が基本となります。

3. 具体的な使い方・実践サンプルコード

以下のコードは、自身のEAによって「約定(売買の成立)」が発生したタイミングを正確に捉え、その詳細をログに出力する実践的なテンプレートです。

//+------------------------------------------------------------------+
//| 取引トランザクションの検知イベント                                     |
//+------------------------------------------------------------------+
void OnTradeTransaction(const MqlTradeTransaction& trans,
                        const MqlTradeRequest& request,
                        const MqlTradeResult& result)
{
   // 1. トランザクションの種類を確認
   // TRADE_TRANSACTION_DEAL_ADD は「履歴に約定が追加された」ことを意味します
   if(trans.type == TRADE_TRANSACTION_DEAL_ADD)
   {
      // 2. 約定(Deal)のチケット番号を取得
      ulong deal_ticket = trans.deal;

      // 3. 約定履歴を選択して詳細を取得
      if(HistoryDealSelect(deal_ticket))
      {
         long   deal_type   = HistoryDealGetInteger(deal_ticket, DEAL_TYPE);
         double deal_volume = HistoryDealGetDouble(deal_ticket, DEAL_VOLUME);
         string deal_symbol = HistoryDealGetString(deal_ticket, DEAL_SYMBOL);
         double deal_price  = HistoryDealGetDouble(deal_ticket, DEAL_PRICE);
         long   deal_magic  = HistoryDealGetInteger(deal_ticket, DEAL_MAGIC);

         // 4. 自身のEAによる取引(Magic Numberの一致)かどうかを判定
         if(deal_magic == 123456) // 123456は仮のマジックナンバー
         {
            Print("【約定検知】シンボル:", deal_symbol, 
                  " タイプ:", EnumToString((ENUM_DEAL_TYPE)deal_type), 
                  " 数量:", deal_volume, 
                  " 価格:", deal_price);

            // ここに約定後の後続処理(LINE通知やリスク管理計算など)を記述
         }
      }
   }

   // 参考:注文がサーバーに受け付けられた瞬間の検知
   if(trans.type == TRADE_TRANSACTION_ORDER_ADD)
   {
      // 待機注文などがセットされた際の処理が必要な場合はここに記述
   }
}

4. 使用上の注意点とよくあるエラー

  1. イベントの「連打」に注意:
    一つの取引で複数回のイベントが発生するため、trans.typeによるフィルタリングを行わないと、同じ処理が何度も実行されてしまいます。例えば、決済処理を重複して行わないよう、必ずTRADE_TRANSACTION_DEAL_ADDなどで「確定した瞬間」を狙い撃ちしてください。

  2. マジックナンバーの確認を忘れない:
    OnTradeTransactionは、手動取引や他のEAによる取引にも反応します。自身のEAのロジックだけを動かしたい場合は、必ずHistoryDealGetInteger等でマジックナンバーを確認する条件分岐を入れてください。

  3. 非同期性の理解:
    この関数はサーバーから非同期で通知されます。稀に、OnTradeTransactionが届く順番が、内部の履歴更新と前後するケース(極めて稀ですが)や、ネットワーク状況により遅延するケースがあります。「通知が来る=100%成功」と過信せず、必要に応じて口座状態を再チェックする慎重さが中級者への一歩です。

5. 【重要】自動売買における約定スピードと環境の罠

自動売買プログラムを開発するエンジニアにとって、コードの最適化以上に重要なのが「物理的な実行環境」です。自宅のデスクトップPCや一般的なノートPCでEAを稼働させることは、ネットワークの遅延(レイテンシ)という致命的なハンデを背負うことを意味します。家庭用回線では、取引サーバーとの往復に数十ミリ秒から数百ミリ秒を要し、その間に価格が変動してスリッページが発生、本来得られるはずだった利益を削り取られてしまいます。

プロレベルの自動売買を実現するには、取引サーバーが設置されているデータセンターに近い場所に位置する、専用のFX用VPS(仮想専用サーバー)の使用が必須です。VPSを利用することで、レイテンシを1〜2ミリ秒以下にまで抑えることが可能となり、OnTradeTransactionで検知したチャンスを逃さず、極限のスピードで約定させることができます。ネットワーク遅延による損失は、VPSの月額コストを遥かに上回るため、システムトレーダーにとって環境への投資は最も効率的なリスク管理と言えるでしょう。

💡 この記事の内容を実運用で活かすには?

この記事の内容を実運用で活かすには、正しい環境が必要です。
特にVPSを使わないと、このロジックは再現できません。

コメント

タイトルとURLをコピーしました