技術辞典

MQL5 OnTradeTransactionで約定を追跡する方法

EAファンクラブ

MQL5でEAの注文、約定、決済、履歴追加を追跡したい場合は、OnTradeTransactionの確認が重要です。

OnTradeTransactionは、取引口座で発生した注文追加、注文更新、約定追加、履歴追加、ポジション変化などのトランザクションを受け取るイベント関数です。

OrderSendの戻り値だけを見ていると、注文要求を送った結果は確認できても、その後の約定、部分約定、決済、履歴反映、コピーEA同期用のイベントを追い切れない場合があります。

このページでは、MQL5のOnTradeTransactionで約定を追跡する方法を、注文・約定・ポジションの違い、transaction / request / resultの見方、約定ログ、決済イベント、コピーEAでの活用、重複記録防止の観点から整理します。

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

OnTradeTransactionとは何か

OnTradeTransactionは、取引トランザクションが発生した時にEA側で呼ばれるイベント関数です。

EAでは、注文を出した瞬間だけでなく、注文が追加された、約定が追加された、履歴に移動した、ポジションが変化した、といった複数の段階を確認する必要があります。

void OnTradeTransaction(const MqlTradeTransaction &trans,
                        const MqlTradeRequest &request,
                        const MqlTradeResult &result)
{
   PrintFormat("[TRADE_TRANSACTION] type=%d order=%I64u deal=%I64u position=%I64u symbol=%s price=%.5f volume=%.2f",
               trans.type,
               trans.order,
               trans.deal,
               trans.position,
               trans.symbol,
               trans.price,
               trans.volume);
}

OnTradeTransactionでは、まずtrans.typeを見て、どの種類の取引イベントなのかを分けます。

注文・約定・ポジションの違い

OnTradeTransactionを正しく使うには、Order、Deal、Positionの違いを分けて考える必要があります。

区分意味ログで確認すること
Order注文要求または未約定注文order ticket、注文種別、注文追加、注文削除、履歴移動
Deal実際に約定した取引deal ticket、約定価格、約定数量、エントリー種別、損益
Position現在保有している建玉position ticket、symbol、volume、price open、Magic Number
History履歴へ移動した注文・約定HistoryDealGetInteger、HistoryDealGetDouble、HistoryOrderGetInteger

EAの検証ログでは、「注文を出した」ことと「約定した」ことを混同しないようにしてください。

主なTrade Transactionタイプ

OnTradeTransactionでは、trans.typeに応じて処理を分けます。

すべてのtypeで同じ情報が入るわけではないため、約定追跡では、特にDEAL追加系、ORDER履歴移動系、REQUEST系を分けてログ化します。

type意味確認用途
TRADE_TRANSACTION_REQUEST取引リクエストの処理結果request、result、retcodeの確認
TRADE_TRANSACTION_ORDER_ADD注文追加注文ticket、注文発生の確認
TRADE_TRANSACTION_ORDER_UPDATE注文更新注文状態変更、部分約定前後の確認
TRADE_TRANSACTION_ORDER_DELETE注文削除注文取消、約定後の注文削除確認
TRADE_TRANSACTION_DEAL_ADD約定追加実際の約定、決済、損益、コピーEA同期の起点
TRADE_TRANSACTION_HISTORY_ADD履歴追加注文または取引が履歴へ反映された確認
TRADE_TRANSACTION_POSITIONポジション変化ポジション数量や価格の変化確認

約定ログやコピーEA同期では、TRADE_TRANSACTION_DEAL_ADDを中心に確認すると整理しやすくなります。

transaction / request / resultの見方

OnTradeTransactionには、trans、request、resultの3つが渡されます。

ただし、requestとresultは常に有効な情報として使えるわけではありません。取引リクエストの処理結果を見る場合はTRADE_TRANSACTION_REQUESTを確認し、約定そのものを見る場合はtrans.dealから履歴情報を取得する流れに分けます。

構造体主な役割確認例
MqlTradeTransaction trans発生した取引トランザクションの情報type、deal、order、position、symbol、price、volume
MqlTradeRequest request送信した取引リクエストの情報action、symbol、volume、price、magic、comment
MqlTradeResult result取引リクエスト処理結果retcode、deal、order、comment、request_id

ログでは、REQUEST結果とDEAL追加を別イベントとして記録してください。

約定追加を検出する基本コード

実際の約定を追跡する場合は、TRADE_TRANSACTION_DEAL_ADDを検出し、trans.dealを使って履歴からDeal情報を取得します。

void OnTradeTransaction(const MqlTradeTransaction &trans,
                        const MqlTradeRequest &request,
                        const MqlTradeResult &result)
{
   if(trans.type == TRADE_TRANSACTION_REQUEST)
   {
      PrintFormat("[TRADE_REQUEST_RESULT] retcode=%u deal=%I64u order=%I64u comment=%s request_id=%u",
                  result.retcode,
                  result.deal,
                  result.order,
                  result.comment,
                  result.request_id);
      return;
   }

   if(trans.type != TRADE_TRANSACTION_DEAL_ADD)
      return;

   ulong deal_ticket = trans.deal;

   if(deal_ticket == 0)
   {
      Print("[DEAL_ADD_SKIP] reason=deal_ticket_zero");
      return;
   }

   if(!HistoryDealSelect(deal_ticket))
   {
      PrintFormat("[DEAL_SELECT_NG] deal=%I64u last_error=%d",
                  deal_ticket,
                  GetLastError());
      return;
   }

   string symbol = HistoryDealGetString(deal_ticket, DEAL_SYMBOL);
   long magic    = HistoryDealGetInteger(deal_ticket, DEAL_MAGIC);
   long entry    = HistoryDealGetInteger(deal_ticket, DEAL_ENTRY);
   long type     = HistoryDealGetInteger(deal_ticket, DEAL_TYPE);
   double volume = HistoryDealGetDouble(deal_ticket, DEAL_VOLUME);
   double price  = HistoryDealGetDouble(deal_ticket, DEAL_PRICE);
   double profit = HistoryDealGetDouble(deal_ticket, DEAL_PROFIT);
   datetime time = (datetime)HistoryDealGetInteger(deal_ticket, DEAL_TIME);

   PrintFormat("[DEAL_ADD] deal=%I64u symbol=%s magic=%d entry=%d type=%d volume=%.2f price=%.5f profit=%.2f time=%s",
               deal_ticket,
               symbol,
               (int)magic,
               (int)entry,
               (int)type,
               volume,
               price,
               profit,
               TimeToString(time, TIME_DATE|TIME_SECONDS));
}

約定追跡では、trans.dealだけをログに出すのではなく、HistoryDealSelect後にDealの詳細を取得して記録します。

約定ログで残したい項目

約定ログは、あとから検証、コピーEA同期、決済漏れ調査、重複記録防止に使える形で残します。

ログ項目意味確認用途
deal約定ticket重複記録防止、履歴照合
order注文ticket注文と約定の対応確認
positionポジションticketポジション単位の追跡
symbol銘柄コピーEAやマルチシンボルEAでの振り分け
magicMagic NumberEA別、ロジック別、コピー対象の判定
entryIN / OUT / INOUTなどの約定種別新規約定、決済約定、反転の判定
typeBUY / SELLなどのDeal種別方向確認
volume約定数量ロット同期、部分約定確認
price約定価格約定価格確認、スリッページ確認
profit損益決済約定、履歴集計
time約定時刻イベント順、ログ照合、CSV記録

コピーEAや運用記録ツールでは、deal、symbol、magic、entry、type、volume、price、timeを必ず確認できる形にしておくと、あとから同期差分を追いやすくなります。

新規約定と決済約定を分ける

Dealには、エントリー種別があります。

新規建てなのか、決済なのか、反転なのかを分けることで、EAの履歴集計やコピーEAの同期処理を整理できます。

string DealEntryToText(const long entry)
{
   if(entry == DEAL_ENTRY_IN)
      return "IN";

   if(entry == DEAL_ENTRY_OUT)
      return "OUT";

   if(entry == DEAL_ENTRY_INOUT)
      return "INOUT";

   if(entry == DEAL_ENTRY_OUT_BY)
      return "OUT_BY";

   return "UNKNOWN";
}

void PrintDealEntryLog(const ulong deal_ticket)
{
   if(!HistoryDealSelect(deal_ticket))
      return;

   long entry = HistoryDealGetInteger(deal_ticket, DEAL_ENTRY);
   string symbol = HistoryDealGetString(deal_ticket, DEAL_SYMBOL);
   double volume = HistoryDealGetDouble(deal_ticket, DEAL_VOLUME);
   double profit = HistoryDealGetDouble(deal_ticket, DEAL_PROFIT);

   PrintFormat("[DEAL_ENTRY] deal=%I64u symbol=%s entry=%s volume=%.2f profit=%.2f",
               deal_ticket,
               symbol,
               DealEntryToText(entry),
               volume,
               profit);
}

決済イベントだけを追跡したい場合は、DEAL_ENTRY_OUTやDEAL_ENTRY_INOUTを条件にして、決済ログ、履歴CSV、コピー先決済処理へつなげます。

決済イベント追跡の考え方

EAの決済を検証する時は、OrderSendで決済要求を送ったログだけでなく、実際に決済Dealが追加されたかを確認します。

決済要求を送ったが決済Dealが出ていない場合、約定拒否、価格変動、部分約定、サーバー側の処理待ちなどを切り分ける必要があります。

確認段階ログ例意味
決済要求CLOSE_REQUEST_SENDEAが決済要求を送った
リクエスト結果TRADE_REQUEST_RESULTサーバーがリクエストを処理した
決済Deal追加DEAL_ADD entry=OUT実際に決済約定が発生した
履歴記録HISTORY_DEAL_LOGGEDEA側のCSVや内部履歴へ記録した
重複防止DEAL_DUP_SKIP同じDealの二重記録を防止した

決済処理では、要求ログと約定ログを分けておくと、EAが要求を出していないのか、要求後に約定していないのか、約定後の記録だけが失敗したのかを確認できます。

コピーEAでの活用

コピーEAでは、コピー元口座で発生した約定イベントを検出し、コピー先へ反映する必要があります。

OnTradeTransactionのDEAL_ADDを使うと、コピー元で新規約定や決済約定が発生したタイミングを検出しやすくなります。

コピーEAで見る項目確認内容
deal ticketコピー元約定の一意識別
symbolコピー対象銘柄、シンボル名変換
magicコピー対象EAまたは対象ロジックの絞り込み
entry新規建て、決済、反転の判定
typeBUY / SELL方向の判定
volumeコピー先ロット換算の基準
price参考価格、許容スリッページ確認
time同期順序、遅延確認

コピーEAでは、約定イベントをそのまま注文処理へ直結せず、対象symbol、対象magic、対象entry、重複処理済みdealかどうかを確認してからコピー処理へ渡す設計が安全です。

重複記録防止

OnTradeTransactionでは、同じDealをCSV、履歴配列、外部ファイル、コピーキューへ記録する場合があります。

この時、同じdeal ticketを二重に処理しないように、処理済みDealを記録しておく必要があります。

ulong g_processed_deals[];

bool IsProcessedDeal(const ulong deal_ticket)
{
   for(int i = 0; i < ArraySize(g_processed_deals); i++)
   {
      if(g_processed_deals[i] == deal_ticket)
         return true;
   }

   return false;
}

void MarkProcessedDeal(const ulong deal_ticket)
{
   int size = ArraySize(g_processed_deals);
   ArrayResize(g_processed_deals, size + 1);
   g_processed_deals[size] = deal_ticket;
}

bool CanProcessDealOnce(const ulong deal_ticket)
{
   if(deal_ticket == 0)
      return false;

   if(IsProcessedDeal(deal_ticket))
   {
      PrintFormat("[DEAL_DUP_SKIP] deal=%I64u reason=already_processed", deal_ticket);
      return false;
   }

   MarkProcessedDeal(deal_ticket);
   return true;
}

長時間稼働EAでは、処理済みDeal配列が増え続けないように、保持件数の上限、日付単位の整理、CSV記録済み判定などを設計してください。

履歴CSVへ記録する時の考え方

運用記録や検証補助では、約定DealをCSVへ記録することがあります。

CSV記録では、同じDealを二重に書かないこと、必要な項目を固定列で残すこと、機密情報や不要な個人情報を混ぜないことが重要です。

CSV列内容
time約定時刻
dealDeal ticket
orderOrder ticket
positionPosition ticket
symbol銘柄
magicMagic Number
entryIN / OUT / INOUT / OUT_BY
typeBUY / SELL
volume約定ロット
price約定価格
profit損益
commentDealコメント

CSVへ出力する場合は、Webhook URL、APIキー、認証トークン、口座番号などの実値を混入させないようにしてください。

ログ出力例

約定追跡のログは、REQUEST結果、DEAL追加、決済種別、重複防止を分けると確認しやすくなります。

[TRADE_REQUEST_RESULT] retcode=10009 deal=123456789 order=987654321 comment=Request executed request_id=15
[DEAL_ADD] deal=123456789 symbol=GOLD magic=24014 entry=IN type=BUY volume=0.10 price=2350.12 profit=0.00 time=2026.05.26 10:15:04
[DEAL_ADD] deal=123456790 symbol=GOLD magic=24014 entry=OUT type=SELL volume=0.10 price=2353.12 profit=30.00 time=2026.05.26 11:22:31
[HISTORY_DEAL_LOGGED] deal=123456790 entry=OUT profit=30.00
[DEAL_DUP_SKIP] deal=123456790 reason=already_processed

この形式でログを残すと、注文要求、実約定、決済、履歴記録、重複スキップを分けて確認できます。

OnTradeTransaction実装時の注意点

OnTradeTransactionは便利ですが、重い処理を直接詰め込みすぎると、ログ過多や処理遅延の原因になります。

注意点理由対応
全イベントを詳細ログ化しない約定が多いEAやコピーEAでログが膨らむDEAL_ADD、REQUEST、NG系を中心に記録する
重いファイル処理を直接連発しないイベント処理が遅くなる必要情報をキュー化し、OnTimer側で処理する
同じDealを二重記録しない履歴CSVやコピー処理が重複するdeal ticketで処理済み管理を行う
request / resultを常に信用しないtypeによって有効情報が異なるTRADE_TRANSACTION_REQUEST時に確認する
DealとPositionを混同しない決済、部分約定、反転で意味が変わるDEAL_ENTRY、DEAL_TYPE、positionを分けてログ化する
コピーEAで即時発注に直結しない対象外magicや重複dealまでコピーする恐れがあるsymbol、magic、entry、重複状態を確認してから処理する

OnTradeTransactionは、約定追跡の入口として使い、重い集計、外部送信、CSV整形、コピーキュー処理は必要に応じて別関数やOnTimerへ分けると安定しやすくなります。

OnTradeTransactionとあわせて確認したいイベント設計

OnTradeTransactionで約定や決済を追跡する場合は、イベント構造、OrderSend結果ログ、重複記録防止を分けて確認しておくと、約定後の状態反映を追いやすくなります。

確認したい内容関連ページ確認ポイント
EAイベント構造MQL5 EAの基本イベント構造を実コードで解説OnInit、OnTick、OnDeinitの責務分離とイベントごとの役割を確認します。
重複エントリー防止MQL5重複エントリー防止を実コードで解説Duplicate Gate、同一バー制御、in-flight lock、注文直後の状態反映遅延を確認します。

関連ページ

OnTradeTransactionは、注文・ポジション・履歴、標準ライブラリ、注文関数、コピーEA、ログ確認と合わせて確認すると理解しやすくなります。

関連ページ確認できること
MQL5ポジション・注文・約定・履歴用語辞典Order、Position、Deal、Historyの違い
MQL5注文・ポジション・履歴管理完全ガイドOrderSend、Position、Deal、History管理の全体像
MQL5注文関数・取引構造体辞典OrderSend、MqlTradeRequest、MqlTradeResultの基本
MQL5標準ライブラリ辞典CTrade、CPositionInfo、COrderInfo、CDealInfoの概要
MT5コピーEA完全ガイドコピー元、コピー先、Magic Number、ロット同期の確認
MT5のログ確認方法ExpertsログとJournalログの確認方法

イベント処理と注文結果ログを確認する場合

OnTradeTransactionは、注文送信後のorder、deal、position、決済、部分約定、注文変更などを追跡するために使うイベント関数です。イベント処理全体の役割分担や、OrderSend直後の結果ログとあわせて確認したい場合は、関連する親記事も確認してください。

確認したいこと確認するページ主な確認内容
MQL5イベント処理の全体を確認したいMQL5イベント処理完全ガイドOnInit、OnTick、OnTimer、OnTradeTransaction、OnChartEventの使い分け
OrderSend直後の結果ログを確認したいMQL5 OrderSend結果ログを実コードで解説retcode、deal、order、comment、GetLastError、MqlTradeResultの確認

注文処理の確認では、OrderSendの戻り値だけで完了判定せず、OrderSend結果、OnTradeTransaction、HistoryDeal、Position情報を分けて確認してください。コピーEAや複数ロジックEAでは、Magic Number、symbol、ticket、deal、positionの対応関係もログで追跡できるようにします。

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

OnTradeTransactionを使った約定追跡、履歴CSV、コピーEA同期、決済ログを相談する場合は、次の情報を整理しておくと確認が進めやすくなります。

整理する情報確認内容
対象EA新規EA、既存EA改修、コピーEA、運用記録ツールのどれか
追跡したいイベント新規約定、決済約定、部分約定、履歴追加、ポジション変化など
対象Magic Number全EA対象か、特定EA・特定ロジックのみか
対象銘柄単一銘柄か、複数銘柄か、シンボル名変換が必要か
記録方法Expertsログ、CSV、Commonフォルダ、コピーキュー、外部連携など
重複防止条件deal ticket、position ticket、basket idなど
コピーEA同期新規建てだけか、決済同期も含めるか
ログOrderSend結果、OnTradeTransactionログ、HistoryDealログ、Journalログ

約定追跡の不具合を相談する場合は、OrderSendログだけでなく、OnTradeTransactionで出ているDEAL_ADD、REQUEST、HistoryDealGet系のログも合わせて確認してください。

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

まとめ

OnTradeTransactionは、MQL5 EAで注文、約定、決済、履歴追加、ポジション変化を追跡するための重要なイベント関数です。

約定追跡では、TRADE_TRANSACTION_DEAL_ADDを検出し、trans.dealからHistoryDealSelect、HistoryDealGetInteger、HistoryDealGetDouble、HistoryDealGetStringを使ってDeal情報を取得します。

REQUEST結果、注文ticket、Deal ticket、Position ticket、Magic Number、DEAL_ENTRY、DEAL_TYPE、volume、price、profitを分けてログ化すると、EA検証、決済ログ、コピーEA同期、履歴CSV、重複記録防止に使いやすくなります。

OnTradeTransactionには重い処理を詰め込みすぎず、約定検出、重複確認、必要情報の記録に役割を絞ると、長時間稼働やコピーEA同期でも確認しやすい構造になります。

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