取引処理構造体 (MqlTradeTransaction)

取引口座にいくつかの明確なアクションを実行すると、状態が変更されます。アクションの例は下記です。

  • クライアント端末内の任意の MQL5 アプリケーションから OrderSendOrderSendAsync 関数を使用して取引リクエストを送信し、取引が実行される。
  • 端末のグラフィカルインターフェースを使用して取引リクエストを送信し、取引が実行される。
  • サーバ上で未決注文と逆指値注文が執行される。
  • 取引サーバ側で操作を行う。

これらのアクションの結果として以下の取引トランザクションが実行されます。

  • 取引リクエストの処理
  • 未執行注文の変更
  • 注文履歴の変更
  • 約定履歴の変更
  • ポジションの変更

例えば、市場の買い注文を送信する際に、注文が処理され、買い注文が口座に記録されます。その後注文が実行されオープン注文の表から削除されて注文履歴に追加されます。約定履歴に追加され新しいポジションが作成されます。これらのアクションは全て取引トランザクションです。

取引処理の口座への適応のために、MQL5 では特別な OnTradeTransaction() ハンドラ—が提供されています。ハンドラ—の1 番目のパラメータは取引処理を記述する MqlTradeTransaction 構造体を取得します。

struct MqlTradeTransaction
 {
  ulong                         deal;             // 約定チケット
  ulong                         order;           // 注文チケット
  string                       symbol;           // 取引銘柄名
  ENUM_TRADE_TRANSACTION_TYPE   type;             // 取引トランザクションの種類
  ENUM_ORDER_TYPE               order_type;       // 注文の種類
  ENUM_ORDER_STATE             order_state;     // 注文状態
  ENUM_DEAL_TYPE               deal_type;       // 約定の種類
  ENUM_ORDER_TYPE_TIME       time_type;       // 作用時間の 注文種類
  datetime                     time_expiration; // 注文の期限
  double                       price;           // 価格
  double                       price_trigger;   // ストップリミット注文アクティベーションの価格
  double                       price_sl;         // 決済逆指値レベル
  double                       price_tp;         // 決済指値レベル
  double                       volume;           // ボリューム(ロット単位)
  ulong                         position;         // ポジションチケット
  ulong                         position_by;     // 反対ポジションのチケット
 };

フィールドの説明

フィールド

説明

deal

約定チケット。

order

注文チケット。

symbol

トランザクションが実行される、取引シンボルの名称。

type

取引トランザクションの種類。値は ENUM_TRADE_TRANSACTION_TYPE 列挙値のいずれかです。

order_type

取引注文の種類。値は ENUM_ORDER_TYPE 列挙値のいずれかです。

order_state

取引注文の状態。値は ENUM_ORDER_STATE 列挙値のいずれかです。

deal_type

約定の種類。値は ENUM_DEAL_TYPE 列挙値のいずれかです。

time_type

期限切れ後の注文の種類。値は ENUM_ORDER_TYPE_TIME 列挙値のいずれかです。

time_expiration

未決注 文の期限切れ日時 (ORDER_TIME_SPECIFIEDORDER_TIME_SPECIFIED_DAY 型の注文)。

price

価格。取引トランザクションの種類によって、注文価格、 約定またはポジションの価格。

price_trigger

指値つきストップ注文(活性化)価格(ORDER_TYPE_BUY_STOP_LIMITORDER_TYPE_SELL_STOP_LIMIT)。

price_sl

決済逆指値。取引トランザクションの種類によって、注文、 約定、またはポジション。

price_tp

決済指値。取引トランザクションの種類によって、注文、 約定、またはポジション。

ボリューム

ロットでのボリューム。取引トランザクションの種類によって、注文、 約定、またはポジションの現在のボリューム。

position

トランザクションが影響を与えたポジションチケット。

position_by

反対ポジションのチケット。反対ポジション(同じ商品であるが反対側に保有するポジション)の決済時に使用されます。

受信したトランザクション分析の必須パラメータはtype フィールドで指定された型です。例えば、トランザクションが TRADE_TRANSACTION_REQUEST タイプ(サーバによる取引リクエスト処理の結果が受信された)の場合、構造体のtypeフィールド のみが書き入れられています。他のフィールドは分析されません。この場合、下記のように、OnTradeTransaction() ハンドラ—に渡されたrequest 及び result 追加パラメータの分析が可能です。

取引操作タイプのデータによってで、取引口座の注文、ポジションや 約定の現在の状態を分析することが出来ます。サーバに送信された 1 つの取引リクエストが複数の新しいトランザクションを生成することがあることは、留意されるべきです。端末におけるこれらのトランザクションの到着の優先順位は保証されません。

MqlTradeTransaction 構造は、取引トランザクションの種類に応じて異なる方法で書き入れられています(ENUM_TRADE_TRANSACTION_TYPE)。

TRADE_TRANSACTION_ORDER_* 及び TRADE_TRANSACTION_HISTORY_*

MqlTradeTransaction 構造内の次のフィールドは、オープン注文の処理に関連する取引(TRADE_TRANSACTION_ORDER_ADD、TRADE_TRANSACTION_ORDER_UPDATE 及び TRADE_TRANSACTION_ORDER_DELETE)と注文履歴(TRADE_TRANSACTION_HISTORY_ADD、TRADE_TRANSACTION_HISTORY_UPDATE、TRADE_TRANSACTION_HISTORY_DELETE)のために書き入れられています。

  • order - 注文チケット。
  • symbol - 注文銘柄名。
  • type - 取引トランザクションの種類。
  • order_type - 注文の種類。
  • orders_state - 注文の現状態。
  • time_type - 注文期限切れの種類。
  • time_expiration - 注文期限切れの時刻 ORDER_TIME_SPECIFIED 及び ORDER_TIME_SPECIFIED_DAY 期限切れ型を持つ注文)。
  • price - クライアントによって指定された注文価格。
  • price_trigger - 指値つきストップ注文のストップ価格(ORDER_TYPE_BUY_STOP_LIMIT 及び ORDER_TYPE_SELL_STOP_LIMIT のみ)。
  • price_sl - 決済逆指値(注文で指定されている場合)。
  • price_tp - 決済指値(注文で指定されている場合)。
  • volume - 現在の注文のボリューム。初回注文ボリュームは、HistoryOrders* 関数を使用して注文履歴で見つけることが出来ます。
  • position - 注文実行の結果として保有、変更、決済されたポジションのチケット。成行注文の為にのみ記入されます。TRADE_TRANSACTION_ORDER_ADDの為には記入されません。
  • position_by - 反対ポジションのチケット。反対ポジションを決済する注文(close by)の為にのみ記入されます。

TRADE_TRANSACTION_DEAL_*

MqlTradeTransaction 構造内の次のフィールドは取引ハンドルに関するトランザクションのために書き入れられています(TRADE_TRANSACTION_DEAL_ADD、TRADE_TRANSACTION_DEAL_UPDATE 及び TRADE_TRANSACTION_DEAL_DELETE)。

  • deal - 約定チケット
  • order - 約定が基づいている注文チケット
  • symbol - 約定銘柄名
  • type - 取引トランザクションの種類。
  • deal_type - 約定の種類
  • price - 約定価格
  • price_sl - 決済逆指値(約定が基づいている注文で指定された場合に書き入れられる)
  • price_tp - 決済指値(約定が基づいている注文で指定された場合に書き入れられる)
  • volume - 約定ボリューム(ロット単位)
  • position - 取引実行の結果、保有、変更、決済されたポジションのチケット。
  • position_by - 反対ポジションのチケット。反対ポジション決済の取引(out by)の為にのみ記入されます。

TRADE_TRANSACTION_POSITION

以下の MqlTradeTransaction 構造内の次のフィールドは、取引の実行に関連しないポジション変更に関連する取引トランザクションのために満たされています(TRADE_TRANSACTION_POSITION)

  • symbol - ポジション銘柄名
  • type - 取引トランザクションの種類。
  • deal_type - ポジションの種類(DEAL_TYPE_BUY または DEAL_TYPE_SELL
  • price - 加重平均ポジションの始値
  • price_sl - 決済逆指値
  • price_tp - 決済指値
  • volume - 変更された場合のポジションボリューム(ロット単位)
  • position - ポジションチケット。

約定実行の結果としてのポジション変更(追加、変更または閉鎖)は、TRADE_TRANSACTION_POSITION トランザクションの発生にはつながりません。

TRADE_TRANSACTION_REQUEST

取引トランザクションの場合、取引リクエストがサーバに処理され結果が受け取られたという事実を説明するために、MqlTradeTransaction の 1 つのフィールド (TRADE_TRANSACTION_REQUEST)のみが書き込まれます。

  • type - 取引トランザクションの種類。

この様なトランザクションでは type フィールド(取引トランザクションの種類)のみを分析する必要があります。OnTradeTransaction 関数の第 2 また第 3 パラメータ(request と result)も追加データのために分析する必要があります。

例:

input int MagicNumber=1234567;
 
//--- CTrade 取引クラスを有効にしてクラス変数を宣言する
#include <Trade\Trade.mqh>
CTrade trade;
//--- 未決注文インストールと削除のフラグ
bool pending_done=false;
bool pending_deleted=false;
//--- 未決注文チケットはここに保存される
ulong order_ticket;
//+------------------------------------------------------------------+
//| エキスパート初期化に使用される関数                                        |
//+------------------------------------------------------------------+
int OnInit()
 {
//--- MagicNumber を設定して全ての注文をマークする
  trade.SetExpertMagicNumber(MagicNumber);
//--- 取引リクエストは OrderSendAsync() 関数を使用して非同期モードで送信される
  trade.SetAsyncMode(true);
//--- 変数をゼロで初期化する
  order_ticket=0;
//---
  return(INIT_SUCCEEDED);
 }
//+------------------------------------------------------------------+
//| エキスパートティック関数                                                 |
//+------------------------------------------------------------------+
void OnTick()
 {
//---未決注文のインストール
  if(!pending_done)
    {
    double ask=SymbolInfoDouble(_Symbol,SYMBOL_ASK);
    double buy_stop_price=NormalizeDouble(ask+1000*_Point,(int)SymbolInfoInteger(_Symbol,SYMBOL_DIGITS));
    bool res=trade.BuyStop(0.1,buy_stop_price,_Symbol);
    //--- BuyStop() 関数が成功
    if(res)
       {
        pending_done=true;
        //--- ctrade から送信リクエストした結果の取得
        MqlTradeResult trade_result;
        trade.Result(trade_result);
        //--- 送信されたリクエストの request_id を取得
        uint request_id=trade_result.request_id;
        Print("Request has been sent to set a pending order. Request_ID=",request_id);
        //--- 注文チケットを保存する(CTrade への送信に非同期モードを使用する場合はゼロ)
        order_ticket=trade_result.order;
        //--- 完成。 OnTick() ハンドラ—を早期終了する。
        return;
       }
    }
//--- 未決注文の削除
  if(!pending_deleted)
    //--- 追加のチェック
    if(pending_done && (order_ticket!=0))
       {
        //--- 未決注文の削除を試みる
        bool res=trade.OrderDelete(order_ticket);
        Print("OrderDelete=",res);
        //--- 削除リクエスト送信に成功
        if(res)
          {
           pending_deleted=true;
          //--- リクエストの実行結果を取得
          MqlTradeResult trade_result;
           trade.Result(trade_result);
          //--- 結果から request ID と取得
          uint request_id=trade_result.request_id;
          //--- 操作ログに表示
          Print("The request has been sent to delete a pending order #",order_ticket,
                ". Request_ID=",request_id,
                "\r\n");
          //--- リクエスト結果から注文チケットを修正
           order_ticket=trade_result.order;
          }
       }
//---        
 }
//+------------------------------------------------------------------+
//| TradeTransaction 関数                                             |
//+------------------------------------------------------------------+
void OnTradeTransaction(const MqlTradeTransaction &trans,
                      const MqlTradeRequest &request,
                      const MqlTradeResult &result)
 {
//--- トランザクション型を列挙値として取得する
  ENUM_TRADE_TRANSACTION_TYPE type=(ENUM_TRADE_TRANSACTION_TYPE)trans.type;
//--- トランザクションが結果処理のリクエストの場合は、名称のみを表示する
  if(type==TRADE_TRANSACTION_REQUEST)
    {
    Print(EnumToString(type));
    //--- 取り扱つかわれたリクエストの文字列名を表示する
    Print("------------RequestDescription\r\n",RequestDescription(request));
    //--- リクエスト結果の記述を表示する
    Print("------------ResultDescription\r\n",TradeResultDescription(result));
    //--- OnTick() の次のハンドルで削除されるよう、チケットを保存する
    if(result.order!=0)
       {
        //--- 次の OnTick() の呼び出しでこの注文をチケットによって削除する
        order_ticket=result.order;
        Print(" Pending order ticket ",order_ticket,"\r\n");
       }
    }
  else // 別の種類のトランザクションの完全記述を表示する
//--- 受け取ったトランザクションの記述を操作ログに表示する
    Print("------------TransactionDescription\r\n",TransactionDescription(trans));
 
//---    
 }
//+------------------------------------------------------------------+
//| トランザクションのテキスト形式の記述を返す                                    |
//+------------------------------------------------------------------+
string TransactionDescription(const MqlTradeTransaction &trans)
 {
//---
  string desc=EnumToString(trans.type)+"\r\n";
  desc+="Symbol: "+trans.symbol+"\r\n";
  desc+="Deal ticket: "+(string)trans.deal+"\r\n";
  desc+="Deal type: "+EnumToString(trans.deal_type)+"\r\n";
  desc+="Order ticket: "+(string)trans.order+"\r\n";
  desc+="Order type: "+EnumToString(trans.order_type)+"\r\n";
  desc+="Order state: "+EnumToString(trans.order_state)+"\r\n";
  desc+="Order time type: "+EnumToString(trans.time_type)+"\r\n";
  desc+="Order expiration: "+TimeToString(trans.time_expiration)+"\r\n";
  desc+="Price: "+StringFormat("%G",trans.price)+"\r\n";
  desc+="Price trigger: "+StringFormat("%G",trans.price_trigger)+"\r\n";
  desc+="Stop Loss: "+StringFormat("%G",trans.price_sl)+"\r\n";
  desc+="Take Profit: "+StringFormat("%G",trans.price_tp)+"\r\n";
  desc+="Volume: "+StringFormat("%G",trans.volume)+"\r\n";
//--- 取得した文字列を返す
  return desc;
 }
//+------------------------------------------------------------------+
//| 取引リクエストのテキスト形式の記述を返す                                    |
//+------------------------------------------------------------------+
string RequestDescription(const MqlTradeRequest &request)
 {
//---
  string desc=EnumToString(request.action)+"\r\n";
  desc+="Symbol: "+request.symbol+"\r\n";
  desc+="Magic Number: "+StringFormat("%d",request.magic)+"\r\n";
  desc+="Order ticket: "+(string)request.order+"\r\n";
  desc+="Order type: "+EnumToString(request.type)+"\r\n";
  desc+="Order filling: "+EnumToString(request.type_filling)+"\r\n";
  desc+="Order time type: "+EnumToString(request.type_time)+"\r\n";
  desc+="Order expiration: "+TimeToString(request.expiration)+"\r\n";
  desc+="Price: "+StringFormat("%G",request.price)+"\r\n";
  desc+="Deviation points: "+StringFormat("%G",request.deviation)+"\r\n";
  desc+="Stop Loss: "+StringFormat("%G",request.sl)+"\r\n";
  desc+="Take Profit: "+StringFormat("%G",request.tp)+"\r\n";
  desc+="Stop Limit: "+StringFormat("%G",request.stoplimit)+"\r\n";
  desc+="Volume: "+StringFormat("%G",request.volume)+"\r\n";
  desc+="Comment: "+request.comment+"\r\n";
//--- 取得した文字列を返す
  return desc;
 }
//+------------------------------------------------------------------+
//| リクエスト処理結果の記述ををテキスト形式で返す                               |
//+------------------------------------------------------------------+
string TradeResultDescription(const MqlTradeResult &result)
 {
//---
  string desc="Retcode "+(string)result.retcode+"\r\n";
  desc+="Request ID: "+StringFormat("%d",result.request_id)+"\r\n";
  desc+="Order ticket: "+(string)result.order+"\r\n";
  desc+="Deal ticket: "+(string)result.deal+"\r\n";
  desc+="Volume: "+StringFormat("%G",result.volume)+"\r\n";
  desc+="Price: "+StringFormat("%G",result.price)+"\r\n";
  desc+="Ask: "+StringFormat("%G",result.ask)+"\r\n";
  desc+="Bid: "+StringFormat("%G",result.bid)+"\r\n";
  desc+="Comment: "+result.comment+"\r\n";
//--- 取得した文字列を返す
  return desc;
 }

参照

取引処理の種類OnTradeTransaction()