English Русский 中文 Español Deutsch Português
preview
取引トランザクション:リクエストとレスポンスの構造体、説明、ロギング

取引トランザクション:リクエストとレスポンスの構造体、説明、ロギング

MetaTrader 5 | 8 1月 2024, 14:10
316 0
Artyom Trishkin
Artyom Trishkin

内容


はじめに

MQL5には、未決注文を出し、ポジションを開き、注文やポジションを変更するためのOrderSend()関数があります。この関数の最初の入力は、MqlTradeRequest取引リクエストの構造体です。構造体のactionフィールドは、実行されるアクションのタイプを示し、残りのフィールドは、actionフィールドで選択されたアクションに応じて入力されます。こうして、取引リクエストに必要なパラメータを関数に渡すことで、サーバーにさまざまなリクエストを送ります。

取引リクエスト構造体(MqlTradeRequest)

発注操作におけるクライアント端末と取引サーバーのやり取りは、取引リクエストを通じておこなわれます。このリクエストは、特別に定義されたMqlTradeRequest構造体によって表現されます。この構造体には取引を実行するために必要なすべてのフィールドが含まれています。

struct MqlTradeRequest
  {
   ENUM_TRADE_REQUEST_ACTIONS    action;           // Type of a performed action
   ulong                         magic;            // EA stamp (magic number ID)
   ulong                         order;            // Order ticket
   string                        symbol;           // Symbol name
   double                        volume;           // Requested volume of a deal in lots
   double                        price;            // Price 
   double                        stoplimit;        // StopLimit order level
   double                        sl;               // Stop Loss order level
   double                        tp;               // Take Profit order level
   ulong                         deviation;        // Maximum acceptable deviation from the requested price
   ENUM_ORDER_TYPE               type;             // Order type
   ENUM_ORDER_TYPE_FILLING       type_filling;     // Order filling type
   ENUM_ORDER_TYPE_TIME          type_time;        // Order lifetime type
   datetime                      expiration;       // Order expiration time (for ORDER_TIME_SPECIFIED type orders)
   string                        comment;          // Order comment
   ulong                         position;         // Position ticket
   ulong                         position_by;      // Opposite position ticket
  };

最初のactionフィールドは、実行するアクションのタイプを指定します。

これは取引操作タイプで、値はENUM_TRADE_REQUEST_ACTIONS列挙値のいずれかです。

ID
詳細
TRADE_ACTION_DEAL
指定したパラメータで即時取引の注文を出す(成行注文を設定する)
TRADE_ACTION_PENDING
指定した条件で取引をおこなうための注文を出す(未決注文)
TRADE_ACTION_SLTP
ストップロスとテイクプロフィットを変更する
TRADE_ACTION_MODIFY
先に発注した取引注文のパラメータを変更する
TRADE_ACTION_REMOVE
以前に発注した未決注文を削除する
TRADE_ACTION_CLOSE_BY
反対側のポジションでポジションを閉じる

構造体フィールドは、アクションの種類ごとに個別に入力しなければなりません。

必要事項を入力したら、サーバーに取引注文を送信します。また、OrderCheck()関数を使用して、構造体が正しく入力されているかどうかを最初に確認することもできます。この関数では、確認対象のクエリとMqlTradeCheckResult構造体タイプの変数を送信します。確認の結果は変数に設定されます。

struct MqlTradeCheckResult
  {
   uint         retcode;             // Response code
   double       balance;             // Balance after performing a deal
   double       equity;              // Equity after performing a deal
   double       profit;              // Floating profit
   double       margin;              // Margin requirements
   double       margin_free;         // Free margin
   double       margin_level;        // Margin level
   string       comment;             // Comment on the response code (error description)
  };

注文を確認した結果、資金が不足していたり、パラメータが正しく入力されていなかったりした場合、この関数はfalseを返します。構造体(ポインタ)の基本的な確認が成功した場合、関数はtrueを返しますが、これは、要求された取引操作が正常に実行されることを意味するものではありません 。関数を実行した結果の詳細な説明を得るには、 上に示したresult構造体のフィールドを分析する必要があります。

取引注文構造体のフィールドの完了を正常に確認した後、サーバーに送信することができます。OrderSend()関数の実行が成功しても、注文が実行されたことにはなりません。注文が処理され、サーバーに受け入れられたことがわかるだけです。取引注文をサーバーに送信した結果は、MqlTradeResult構造体のフィールドに入力されたものになります。この構造体には、OrderSend()関数によって送信されたリクエストに対する取引サーバーの応答が含まれています。

取引操作の結果は、MqlTradeResult型の変数に返されます。これは、取引操作をおこなうために、OrderSend()関数の2番目のパラメータとして渡されます。

OrdersSend()およびOrderSendAsync()関数を使用して端末から取引サーバーにリクエストが送信される際、 request_idフィールドにはリクエストIDが設定されます。端末は実行された取引に関するメッセージを取引サーバーから受信し、以下のコンポーネントをパラメータとして含むOnTradeTransaction()関数による処理のために送信します。

  • MqlTradeTransaction構造体での取引トランザクションの説明
  • OrderSend()またはOrdersSendAsync()関数から送信された取引リクエストの説明(リクエストIDは端末から取引サーバーに送信され、リクエストそのものとそのrequest_idは端末のメモリに保存される)
  • このリクエストのIDを含むrequest_idフィールドを持つMqlTradeResult構造体としての取引リクエスト実行結果

OnTradeTransaction()関数は3つの入力パラメータを受け取りますが、最後の2つはTRADE_TRANSACTION_REQUEST型のトランザクションについてのみ分析する必要があります。それ以外の場合、取引リクエストとその約定結果に関するデータは入力されません。パラメータ分析の例は、取引リクエスト構造体セクションに記載されています。

サーバーへの送信時に端末が取引リクエストのrequest_idを設定するようにされたのは、主に OrderSendAsync()非同期関数と連携するためです。この識別子により、実行されたアクション(OrderSendまたはOrderSendAsync関数の呼び出し)とOnTradeTransaction()に送信されたアクションの結果を関連付けることができます。

したがって、OnTradeTransaction()関数の中で、サーバーによる取引注文の受理、取引システムへの配置と約定を制御することができます。今回は、取引注文の構造体への入力から始まり、OnTradeTransaction()のイベント分析まで、取引リクエストに関わるすべての構造体フィールドをログに表示する関数を書いていきます。意図した結果は、すべての取引イベントを操作ログに出力する小さな情報提供EAです。

取引注文の処理は、以下の点に集約されます。

  1. 取引リクエストの構造体に入力する
  2. 入力の正しさを確認し、このような注文が可能かどうかを確認する
  3. 取引注文をサーバーに送信する
  4. 必要に応じて、サーバーに注文を送信した結果の構造を分析する
  5. OnTradeTransaction()ハンドラからイベントを受け取り、ログのメッセージを分析する
構造体フィールドの説明をログに出力する関数を書き始める前に、列挙定数の形で示されるある種の注文の説明を返す補助関数や、その他の便利で必要な関数を書くことにしましょう。

補助関数

記事の最後に紹介するEAは、キーボードショートカットを押して操作します。CtrlキーとShiftキーの押下を判定する関数を2つ書いてみましょう。

//+------------------------------------------------------------------+
//| Return the state of the Ctrl key                                 |
//+------------------------------------------------------------------+
bool IsCtrlKeyPressed(void) 
  { 
   return(::TerminalInfoInteger(TERMINAL_KEYSTATE_CONTROL)<0);
  }
//+------------------------------------------------------------------+
//| Return the state of the Shift key                                |
//+------------------------------------------------------------------+
bool IsShiftKeyPressed(void) 
  { 
   return(::TerminalInfoInteger(TERMINAL_KEYSTATE_SHIFT)<0);
  }

これで、キーが押されたことを検出する際に、CtrlキーやShiftキーを押し続けているか、あるいは同時に押し続けているかのフラグを確認し、Ctrlキーと英数字キーの組み合わせに対応できるようになりました。


構造体フィールドの説明を返す場合、取引サーバーのリターンコードを出力する必要があります。サーバーの応答コードの説明を返す関数を作ってみましょう。

//+------------------------------------------------------------------+
//| Return a description of the trade server return code             |
//+------------------------------------------------------------------+
string RetcodeDescription(const uint retcode,bool ext_descr=false)
  {
   switch(retcode)
     {
      //--- Done
      case 0                                 :  return "OK (0)";
      //--- Requote
      case TRADE_RETCODE_REQUOTE             :  return "10004 REQUOTE"+(ext_descr ? " (Requote)" : "");
      //--- Request rejected
      case TRADE_RETCODE_REJECT              :  return "10006 REJECT"+(ext_descr ? " (Request rejected)" : "");
      //--- Request canceled by trader
      case TRADE_RETCODE_CANCEL              :  return "10007 CANCEL"+(ext_descr ? " (Request canceled by trader)" : "");
      //--- Order placed
      case TRADE_RETCODE_PLACED              :  return "10008 PLACED"+(ext_descr ? " (Order placed)" : "");
      //--- Request completed
      case TRADE_RETCODE_DONE                :  return "10009 DONE"+(ext_descr ? " (Request completed)" : "");
      //--- Request completed partially
      case TRADE_RETCODE_DONE_PARTIAL        :  return "10010 DONE_PARTIAL"+(ext_descr ? " (Only part of the request was completed)" : "");
      //--- Request processing error
      case TRADE_RETCODE_ERROR               :  return "10011 ERROR"+(ext_descr ? " (Request processing error)" : "");
      //--- Request canceled by timeout
      case TRADE_RETCODE_TIMEOUT             :  return "10012 TIMEOUT"+(ext_descr ? " (Request canceled by timeout)" : "");
      //--- Invalid request
      case TRADE_RETCODE_INVALID             :  return "10013 INVALID"+(ext_descr ? " (Invalid request)" : "");
      //--- Invalid volume in the request
      case TRADE_RETCODE_INVALID_VOLUME      :  return "10014 INVALID_VOLUME"+(ext_descr ? " (Invalid volume in the request)" : "");
      //--- Invalid price in the request
      case TRADE_RETCODE_INVALID_PRICE       :  return "10015 INVALID_PRICE"+(ext_descr ? " (Invalid price in the request)" : "");
      //--- Invalid stops in the request
      case TRADE_RETCODE_INVALID_STOPS       :  return "10016 INVALID_STOPS"+(ext_descr ? " (Invalid stops in the request)" : "");
      //--- Trading disabled
      case TRADE_RETCODE_TRADE_DISABLED      :  return "10017 TRADE_DISABLED"+(ext_descr ? " (Trade is disabled)" : "");
      //--- Market is closed
      case TRADE_RETCODE_MARKET_CLOSED       :  return "10018 MARKET_CLOSED"+(ext_descr ? " (Market is closed)" : "");
      //--- There is not enough money to complete the request
      case TRADE_RETCODE_NO_MONEY            :  return "10019 NO_MONEY"+(ext_descr ? " (There is not enough money to complete the request)" : "");
      //--- Prices changed
      case TRADE_RETCODE_PRICE_CHANGED       :  return "10020 PRICE_CHANGED"+(ext_descr ? " (Prices changed)" : "");
      //--- There are no quotes to process the request
      case TRADE_RETCODE_PRICE_OFF           :  return "10021 PRICE_OFF"+(ext_descr ? " (There are no quotes to process the request)" : "");
      //--- Invalid order expiration date in the request
      case TRADE_RETCODE_INVALID_EXPIRATION  :  return "10022 INVALID_EXPIRATION"+(ext_descr ? " (Invalid order expiration date in the request)" : "");
      //--- Order state changed
      case TRADE_RETCODE_ORDER_CHANGED       :  return "10023 ORDER_CHANGED"+(ext_descr ? " (Order state changed)" : "");
      //--- Too frequent requests
      case TRADE_RETCODE_TOO_MANY_REQUESTS   :  return "10024 TOO_MANY_REQUESTS"+(ext_descr ? " (Too frequent requests)" : "");
      //--- No changes in request
      case TRADE_RETCODE_NO_CHANGES          :  return "10025 NO_CHANGES"+(ext_descr ? " (No changes in request)" : "");
      //--- Autotrading disabled by server
      case TRADE_RETCODE_SERVER_DISABLES_AT  :  return "10026 SERVER_DISABLES_AT"+(ext_descr ? " (Autotrading disabled by server)" : "");
      //--- Autotrading disabled by client terminal
      case TRADE_RETCODE_CLIENT_DISABLES_AT  :  return "10027 CLIENT_DISABLES_AT"+(ext_descr ? " (Autotrading disabled by client terminal)" : "");
      //--- Request locked for processing
      case TRADE_RETCODE_LOCKED              :  return "10028 LOCKED"+(ext_descr ? " (Request locked for processing)" : "");
      //--- Order or position frozen
      case TRADE_RETCODE_FROZEN              :  return "10029 FROZEN"+(ext_descr ? " (Order or position frozen)" : "");
      //--- Invalid order filling type
      case TRADE_RETCODE_INVALID_FILL        :  return "10030 INVALID_FILL"+(ext_descr ? " (Invalid order filling type)" : "");
      //--- No connection with the trade server
      case TRADE_RETCODE_CONNECTION          :  return "10031 CONNECTION"+(ext_descr ? " (No connection with the trade server)" : "");
      //--- Operation allowed only for live accounts
      case TRADE_RETCODE_ONLY_REAL           :  return "10032 ONLY_REAL"+(ext_descr ? " (Operation is allowed only for live accounts)" : "");
      //--- Number of pending orders reached the limit
      case TRADE_RETCODE_LIMIT_ORDERS        :  return "10033 LIMIT_ORDERS"+(ext_descr ? " (The number of pending orders has reached the limit)" : "");
      //--- Volume of orders and positions for the symbol reached the limit
      case TRADE_RETCODE_LIMIT_VOLUME        :  return "10034 LIMIT_VOLUME"+(ext_descr ? " (The volume of orders and positions for the symbol has reached the limit)" : "");
      //--- Incorrect or prohibited order type
      case TRADE_RETCODE_INVALID_ORDER       :  return "10035 INVALID_ORDER"+(ext_descr ? " (Incorrect or prohibited order type)" : "");
      //--- Position with specified POSITION_IDENTIFIER already closed
      case TRADE_RETCODE_POSITION_CLOSED     :  return "10036 POSITION_CLOSED"+(ext_descr ? " (Position with the specified POSITION_IDENTIFIER has already been closed)" : "");
      //--- Close volume exceeds the current position volume
      case TRADE_RETCODE_INVALID_CLOSE_VOLUME:  return "10038 INVALID_CLOSE_VOLUME"+(ext_descr ? " (A close volume exceeds the current position volume)" : "");
      //--- Close order already exists for specified position
      case TRADE_RETCODE_CLOSE_ORDER_EXIST   :  return "10039 CLOSE_ORDER_EXIST"+(ext_descr ? " (A close order already exists for a specified position)" : "");
      //--- Number of positions reached the limit
      case TRADE_RETCODE_LIMIT_POSITIONS     :  return "10040 LIMIT_POSITIONS"+(ext_descr ? " (The number of positions has reached the limit)" : "");
      //--- Pending order activation request is rejected, order is canceled
      case TRADE_RETCODE_REJECT_CANCEL       :  return "10041 REJECT_CANCEL"+(ext_descr ? " (The pending order activation request is rejected, the order is canceled)" : "");
      //--- Request rejected, only long positions are allowed on symbol
      case TRADE_RETCODE_LONG_ONLY           :  return "10042 LONG_ONLY"+(ext_descr ? " (Only long positions are allowed)" : "");
      //--- Request rejected, only short positions are allowed on symbol
      case TRADE_RETCODE_SHORT_ONLY          :  return "10043 SHORT_ONLY"+(ext_descr ? " (Only short positions are allowed)" : "");
      //--- Request rejected, only position closing is allowed on symbol
      case TRADE_RETCODE_CLOSE_ONLY          :  return "10044 CLOSE_ONLY"+(ext_descr ? " (Only position closing is allowed)" : "");
      //--- Request rejected, position closing for trading account is allowed only by FIFO rule
      case TRADE_RETCODE_FIFO_CLOSE          :  return "10045 FIFO_CLOSE"+(ext_descr ? " (Position closing is allowed only by FIFO rule)" : "");
      //--- Request rejected, opposite positions on a single symbol are disabled for trading account
      case TRADE_RETCODE_HEDGE_PROHIBITED    :  return "10046 HEDGE_PROHIBITED"+(ext_descr ? " (Opposite positions on a single symbol are disabled)" : "");
      //--- Unknown return code 
      default                                :  return "Undefined ("+(string)retcode+")";
     }
  }

この関数は、サーバーの応答コードと、拡張説明を返す必要性を示すフラグを受け取ります。この関数は、定数記述のデジタルコード

10034 LIMIT_VOLUME

またはサーバーの応答コードの詳細な説明のいずれかを返します。

10034 LIMIT_VOLUME (The volume of orders and positions for the symbol has reached the limit)


以下は、注文タイプの説明を返す関数です。

//+------------------------------------------------------------------+
//| Return the order type description                                |
//+------------------------------------------------------------------+
string OrderTypeDescription(const ENUM_ORDER_TYPE type,const bool ext_descr=false)
  {
//--- "Cut out" the order type from the string obtained from enum
   string res=StringSubstr(EnumToString(type),11);
//--- Convert all received characters to lowercase and
   if(res.Lower())
     {
      //--- replace the first letter from small to capital
      res.SetChar(0,ushort(res.GetChar(0)-0x20));
      int total=(int)res.Length();  // Text length
      int index=0;                  // index to start searching for "_" in a text
      //--- Search for underscores in a loop through all characters
      for(int i=0;i<total;i++)
        {
         int pos=StringFind(res,"_",index);
         //--- If an underscore is found,
         if(pos>0)
           {
            //--- replace it with space and convert the next letter to uppercase 
            res.SetChar(pos,' ');
            res.SetChar(pos+1,ushort(res.GetChar(pos+1)-0x20));
            //--- Set a new index for starting the search for "_"
            index=pos;
           }
        }
     }
   string descr="";
   switch(type)
     {
      case ORDER_TYPE_BUY              :  descr=" (Market Buy order)";                                                                          break;
      case ORDER_TYPE_SELL             :  descr=" (Market Sell order)";                                                                         break;
      case ORDER_TYPE_BUY_LIMIT        :  descr=" (Buy Limit pending order)";                                                                   break;
      case ORDER_TYPE_SELL_LIMIT       :  descr=" (Sell Limit pending order)";                                                                  break;
      case ORDER_TYPE_BUY_STOP         :  descr=" (Buy Stop pending order)";                                                                    break;
      case ORDER_TYPE_SELL_STOP        :  descr=" (Sell Stop pending order)";                                                                   break;
      case ORDER_TYPE_BUY_STOP_LIMIT   :  descr=" (Upon reaching the order price, a pending Buy Limit order is placed at the StopLimit price)"; break;
      case ORDER_TYPE_SELL_STOP_LIMIT  :  descr=" (Upon reaching the order price, a pending Sell Limit order is placed at the StopLimit price)";break;
      case ORDER_TYPE_CLOSE_BY         :  descr=" (Order to close a position by an opposite one)";                                              break;
      default: break;
     }
   return res+(!ext_descr ? "" : descr);
   /* Sample output:
      Sell Limit (Sell Limit pending order)
   */
  }

OrderSend()関数を使用して取引リクエストを送信する際、いくつかの操作では注文タイプを指定する必要があります。注文タイプはMqlTradeRequest構造体のtypeフィールドで指定され、 ENUM_ORDER_TYPE列挙から値を取ることができます。

ID
詳細
ORDER_TYPE_BUY
成行買い注文
ORDER_TYPE_SELL
成行売り注文
ORDER_TYPE_BUY_LIMIT
買い指値注文
ORDER_TYPE_SELL_LIMIT
売り指値注文
ORDER_TYPE_BUY_STOP
買い逆指値注文
ORDER_TYPE_SELL_STOP
売り逆指値注文
ORDER_TYPE_BUY_STOP_LIMIT
注文価格に達すると、買い指値注文が逆指値で出される
ORDER_TYPE_SELL_STOP_LIMIT
注文価格に達すると、売り指値注文が逆指値で出される
ORDER_TYPE_CLOSE_BY
反対ポジションによる決済の注文


以下は、実行による注文タイプの説明を返す関数です。

//+------------------------------------------------------------------+
//| Return the order type description by execution                   |
//+------------------------------------------------------------------+
string OrderTypeFillingDescription(const ENUM_ORDER_TYPE_FILLING type_filling,const bool ext_descr=false)
  {
   string res=StringSubstr(EnumToString(type_filling),14);
//--- Convert all obtained symbols to lower case and replace the first letter from small to capital (for ORDER_FILLING_RETURN)
   if(type_filling==ORDER_FILLING_RETURN && res.Lower())
      res.SetChar(0,ushort(res.GetChar(0)-0x20));
   string descr="";
   switch(type_filling)
     {
      case ORDER_FILLING_FOK     :  descr=" (Fill or Kill. An order can be executed in the specified volume only)";                                               break;
      case ORDER_FILLING_IOC     :  descr=" (Immediate or Cancel. A deal with the volume maximally available in the market within that indicated in the order)";  break;
      case ORDER_FILLING_BOC     :  descr=" (Passive (Book or Cancel). The order can only be placed in the Depth of Market and cannot be immediately executed)";  break;
      case ORDER_FILLING_RETURN  :  descr=" (In case of partial filling, an order with remaining volume is not canceled but processed further)";                  break;
      default: break;
     }
   return res+(!ext_descr ? "" : descr);
   /* Sample output:
      Type filling: Return (In case of partial filling, an order with remaining volume is not canceled but processed further)
   */
  }

OrderSend()関数を使用して取引リクエストを送信する際、必要な出来高執行方策は、特別なMqlTradeRequest構造体のtype_fillingフィールドで設定できます。ENUM_ORDER_TYPE_FILLING列挙体の値が使用できます。特定の有効/完了注文のプロパティ値を取得するには、OrderGetInteger()またはHistoryOrderGetInteger()関数をORDER_TYPE_FILLING修飾子と共に使用します。

ORDER_TYPE_FILLING値(出来高による執行タイプ)を正しく設定するために、現在時刻に執行する注文を送信する前に、各金融商品のSymbolInfoInteger()関数を使用してSYMBOL_FILLING_MODEプロパティの値を取得することができます。これは、この銘柄に許可されるボリューム処理タイプをフラグの組み合わせとして示しています。ORDER_FILLING_RETURN処理タイプは、「市場執行」モード(SYMBOL_TRADE_EXECUTION_MARKET)を除き、常に有効です。


以下は、取引トランザクションタイプの説明を返す関数です。

//+------------------------------------------------------------------+
//| Return a description of the trade transaction type               |
//+------------------------------------------------------------------+
string TradeTransactionTypeDescription(const ENUM_TRADE_TRANSACTION_TYPE transaction,const bool ext_descr=false)
  {
//--- "Cut out" the transaction type from the string obtained from enum
   string res=StringSubstr(EnumToString(transaction),18);
//--- Convert all obtained symbols to lower case and replace the first letter from small to capital
   if(res.Lower())
      res.SetChar(0,ushort(res.GetChar(0)-0x20));
//--- Replace all underscore characters with space in the resulting line
   StringReplace(res,"_"," ");
   string descr="";
   switch(transaction)
     {
      case TRADE_TRANSACTION_ORDER_ADD       :  descr=" (Adding a new open order)";                                                                   break;
      case TRADE_TRANSACTION_ORDER_UPDATE    :  descr=" (Updating an open order)";                                                                    break;
      case TRADE_TRANSACTION_ORDER_DELETE    :  descr=" (Removing an order from the list of the open ones)";                                          break;
      case TRADE_TRANSACTION_DEAL_ADD        :  descr=" (Adding a deal to the history)";                                                              break;
      case TRADE_TRANSACTION_DEAL_UPDATE     :  descr=" (Updating a deal in the history)";                                                            break;
      case TRADE_TRANSACTION_DEAL_DELETE     :  descr=" (Deleting a deal from the history)";                                                          break;
      case TRADE_TRANSACTION_HISTORY_ADD     :  descr=" (Adding an order to the history as a result of execution or cancellation)";                   break;
      case TRADE_TRANSACTION_HISTORY_UPDATE  :  descr=" (Changing an order located in the orders history)";                                           break;
      case TRADE_TRANSACTION_HISTORY_DELETE  :  descr=" (Deleting an order from the orders history)";                                                 break;
      case TRADE_TRANSACTION_POSITION        :  descr=" (Changing a position not related to a deal execution)";                                       break;
      case TRADE_TRANSACTION_REQUEST         :  descr=" (The trade request has been processed by a server and processing result has been received)";  break;
      default: break;
     }
   return res+(!ext_descr ? "" : descr);
   /* Sample output:
      Order add (Adding a new open order)
   */
  }

この関数は、口座で実行された取引トランザクションタイプの説明を返します。


以下は、注文ステータスの説明を返す関数です。

//+------------------------------------------------------------------+
//| Return an order state description                                |
//+------------------------------------------------------------------+
string OrderStateDescription(const ENUM_ORDER_STATE state,const bool ext_descr=false)
  {
//--- "Cut out" the order status from the string obtained from enum
   string res=StringSubstr(EnumToString(state),12);
//--- Convert all obtained symbols to lower case and replace the first letter from small to capital
   if(res.Lower())
      res.SetChar(0,ushort(res.GetChar(0)-0x20));
//--- Replace all underscore characters with space in the resulting line
   StringReplace(res,"_"," ");
   string descr="";
   switch(state)
     {
      case ORDER_STATE_STARTED         :  descr=" (Order checked, but not yet accepted by broker)";            break;
      case ORDER_STATE_PLACED          :  descr=" (Order accepted)";                                           break;
      case ORDER_STATE_CANCELED        :  descr=" (Order canceled by client)";                                 break;
      case ORDER_STATE_PARTIAL         :  descr=" (Order partially executed)";                                 break;
      case ORDER_STATE_FILLED          :  descr=" (Order fully executed)";                                     break;
      case ORDER_STATE_REJECTED        :  descr=" (Order rejected)";                                           break;
      case ORDER_STATE_EXPIRED         :  descr=" (Order expired)";                                            break;
      case ORDER_STATE_REQUEST_ADD     :  descr=" (Order is being registered (placing to the trading system))";break;
      case ORDER_STATE_REQUEST_MODIFY  :  descr=" (Order is being modified (changing its parameters))";        break;
      case ORDER_STATE_REQUEST_CANCEL  :  descr=" (Order is being deleted (deleting from the trading system))";break;
      default: break;
     }
   return res+(!ext_descr ? "" : descr);
   /* Sample output:
      Placed (Order accepted)
   */
  }

各注文には、その状態を表すステータスがあります。情報を取得するには、OrderGetInteger()またはHistoryOrderGetInteger()関数をORDER_STATE修飾子と共に使用します。有効な値はENUM_ORDER_STATE列挙体に格納されています。サーバーに取引リクエストを送信すると、注文のステータスが徐々に変化します。まず、サーバーによって確認され、次に取引システムに置かれ、そしてトリガーされ、取引が発生するか、キャンセルされます。このリストには、可能なすべての注文状態が含まれており、取引注文を扱う際には、それらを考慮する必要があります。


以下は、トランザクションタイプの説明を返す関数です。

//+------------------------------------------------------------------+
//| Return the deal type description                                 |
//+------------------------------------------------------------------+
string DealTypeDescription(const ENUM_DEAL_TYPE type,const bool ext_descr=false)
  {
//--- "Cut out" the deal type from the string obtained from enum
   string res=StringSubstr(EnumToString(type),(type==DEAL_DIVIDEND || type==DEAL_DIVIDEND_FRANKED || type==DEAL_TAX ? 5 : 10));
//--- Convert all obtained symbols to lower case and replace the first letter from small to capital
   if(res.Lower())
      res.SetChar(0,ushort(res.GetChar(0)-0x20));
//--- Replace all underscore characters with space in the resulting line
   StringReplace(res,"_"," ");
   string descr="";
//--- Extended descriptions are added only to the deals whose description obtained from enum does not match the extended one
   switch(type)
     {
      case DEAL_TYPE_CHARGE                  : descr=" (Additional charge)";                          break;
      case DEAL_TYPE_COMMISSION              : descr=" (Additional commission)";                      break;
      case DEAL_TYPE_COMMISSION_DAILY        : descr=" (Daily commission)";                           break;
      case DEAL_TYPE_COMMISSION_MONTHLY      : descr=" (Monthly commission)";                         break;
      case DEAL_TYPE_COMMISSION_AGENT_DAILY  : descr=" (Daily agent commission)";                     break;
      case DEAL_TYPE_COMMISSION_AGENT_MONTHLY: descr=" (Monthly agent commission)";                   break;
      case DEAL_TYPE_INTEREST                : descr=" (Interest rate)";                              break;
      case DEAL_TYPE_BUY_CANCELED            : descr=" (Canceled buy deal)";                          break;
      case DEAL_TYPE_SELL_CANCELED           : descr=" (Canceled sell deal)";                         break;
      case DEAL_DIVIDEND                     : descr=" (Dividend operations)";                        break;
      case DEAL_DIVIDEND_FRANKED             : descr=" (Franked (non-taxable) dividend operations)";  break;
      case DEAL_TAX                          : descr=" (Tax charges)";                                break;
      default: break;
     }
   return res+(!ext_descr ? "" : descr);
   /* Sample output:
      Comission (Additional commission)
   */
  }

各取引にはタイプがあります。取り得る値はENUM_DEAL_TYPEに記載されています。取引タイプに関するデータを取得するには、HistoryDealGetInteger()関数をDEAL_TYPE修飾子と共に使用します。


以下は、有効期限による注文タイプの説明を返す関数です。

//+------------------------------------------------------------------+
//| Return an order type description by expiration                   |
//+------------------------------------------------------------------+
string OrderTypeTimeDescription(const ENUM_ORDER_TYPE_TIME type_time,const bool ext_descr=false)
  {
//--- "Cut out" the order type by expiration from the string obtained from enum
   string res=StringSubstr(EnumToString(type_time),6);
//--- If the type by expiration is ORDER_TIME_GTC, add "Time GTC" to res
   if(type_time==ORDER_TIME_GTC)
      res="Time GTC";
//--- Otherwise, convert all obtained symbols to lower case and replace the first letter from small to capital
   else
     {
      if(res.Lower())
         res.SetChar(0,ushort(res.GetChar(0)-0x20));
      //--- Replace all underscore characters with space in the resulting line
      StringReplace(res,"_"," ");
     }
   string descr="";
   switch(type_time)
     {
      case ORDER_TIME_GTC           : descr=" (Good till cancel order)";                                          break;
      case ORDER_TIME_DAY           : descr=" (Good till current trade day order)";                               break;
      case ORDER_TIME_SPECIFIED     : descr=" (Good till expired order)";                                         break;
      case ORDER_TIME_SPECIFIED_DAY : descr=" (The order will be effective till 23:59:59 of the specified day)";  break;
      default: break;
     }
   return res+(!ext_descr ? "" : descr);
   /* Sample output:
      Time GTC (Good till cancel order)
   */
  }

注文の有効期限は OrderSend()関数を使用して取引リクエストを送信する際に、MqlTradeRequest構造体のtype_timeフィールドに設定することができますENUM_ORDER_TYPE_TIME列挙体の値が有効です。プロパティ値を取得するには、OrderGetInteger()またはHistoryOrderGetInteger()関数をORDER_TYPE_TIME修飾子とともに使用します。

取引トランザクションは、注文、取引、ポジションによって発生します。このようなトランザクションの各カテゴリには、追加、変更、削除という異なるタイプがあり得ます。ただし、注文、取引、ポジションなど、詳細を特定することなく、どのようなトランザクションがおこなわれたのかだけを知りたい場合もあります。これを実現するために、トランザクションの所属を返す関数を作ってみましょう。

//+------------------------------------------------------------------+
//| Define and set transaction affiliation values                    |
//+------------------------------------------------------------------+
void SetTransactionBelong(const ENUM_TRADE_TRANSACTION_TYPE type,bool &request_flag,bool &order_flag,bool &deal_flag,bool &position_flag)
  {
   switch(type)
     {
      //--- Request
      case TRADE_TRANSACTION_REQUEST         : request_flag=true; order_flag=false; deal_flag=false; position_flag=false; break;
      //--- Order
      case TRADE_TRANSACTION_ORDER_ADD       :
      case TRADE_TRANSACTION_ORDER_UPDATE    :
      case TRADE_TRANSACTION_ORDER_DELETE    :
      case TRADE_TRANSACTION_HISTORY_ADD     :
      case TRADE_TRANSACTION_HISTORY_UPDATE  :
      case TRADE_TRANSACTION_HISTORY_DELETE  : request_flag=false; order_flag=true; deal_flag=false; position_flag=false; break;
      //--- Deal
      case TRADE_TRANSACTION_DEAL_ADD        :
      case TRADE_TRANSACTION_DEAL_UPDATE     :
      case TRADE_TRANSACTION_DEAL_DELETE     : request_flag=false; order_flag=false; deal_flag=true; position_flag=false; break;
      //--- Position
      case TRADE_TRANSACTION_POSITION        : request_flag=false; order_flag=false; deal_flag=false; position_flag=true; break;
      //---
      default: break;
     }
  }

この関数はトランザクションタイプを受け取り、参照により3つのフラグ変数を受け取ります。これらの変数は、トランザクションが正確に実行された内容に応じてセット/リセットされます。


以下は、取引リクエストタイプの説明を返す関数です。

//+------------------------------------------------------------------+
//| Return the trade request type description                        |
//+------------------------------------------------------------------+
string TradeActionDescription(const ENUM_TRADE_REQUEST_ACTIONS action,const bool ext_descr=false)
  {
//--- "Cut out" the operation type from the string obtained from enum
   string res=StringSubstr(EnumToString(action),13);
//--- Convert all obtained symbols to lower case and replace the first letter from small to capital (except for TRADE_ACTION_SLTP)
   if(action!=TRADE_ACTION_SLTP && res.Lower())
      res.SetChar(0,ushort(res.GetChar(0)-0x20));
   string descr="";
   switch(action)
     {
      case TRADE_ACTION_DEAL     : descr=" (Place a trade order for an immediate execution with the specified parameters (market order))";break;
      case TRADE_ACTION_PENDING  : descr=" (Place a trade order for the execution under specified conditions (pending order))";           break;
      case TRADE_ACTION_SLTP     : descr=" (Modify Stop Loss and Take Profit values of an opened position)";                              break;
      case TRADE_ACTION_MODIFY   : descr=" (Modify the parameters of the order placed previously)";                                       break;
      case TRADE_ACTION_REMOVE   : descr=" (Delete the pending order placed previously)";                                                 break;
      case TRADE_ACTION_CLOSE_BY : descr=" (Close a position by an opposite one)";                                                        break;
      default: break;
     }
   return res+(!ext_descr ? "" : descr);
   /* Sample output:
      Pending (Place a trade order for the execution under specified conditions (pending order)):
   */
  }


取引リクエストの構造体、そのフィールドの説明の出力を見て、この構造体でどのように動作するかを説明するいくつかの取引関数を作成しましょう。

取引操作の際にリクエストを作成するためのMqlTradeRequest構造体

発注操作におけるクライアント端末と取引サーバーのやり取りは、取引リクエストを通じておこなわれます。このリクエストは、特別に定義されたMqlTradeRequest構造体によって表現されます。この構造体には取引を実行するために必要なすべてのフィールドが含まれています。

struct MqlTradeRequest
  {
   ENUM_TRADE_REQUEST_ACTIONS    action;           // Type of a performed action
   ulong                         magic;            // EA stamp (magic number ID)
   ulong                         order;            // Order ticket
   string                        symbol;           // Symbol name
   double                        volume;           // Requested volume of a deal in lots
   double                        price;            // Price 
   double                        stoplimit;        // StopLimit order level
   double                        sl;               // Stop Loss order level
   double                        tp;               // Take Profit order level
   ulong                         deviation;        // Maximum acceptable deviation from the requested price
   ENUM_ORDER_TYPE               type;             // Order type
   ENUM_ORDER_TYPE_FILLING       type_filling;     // Order filling type
   ENUM_ORDER_TYPE_TIME          type_time;        // Order lifetime type
   datetime                      expiration;       // Order expiration time (for ORDER_TIME_SPECIFIED type orders)
   string                        comment;          // Order comment
   ulong                         position;         // Position ticket
   ulong                         position_by;      // Opposite position ticket
  };

取引注文をサーバーに送信するには、注文に適した方法で構造体フィールドに入力される必要があります。actionフィールドは入力されるべきです。このフィールドにどのようなアクションが書かれるかによって、そのアクションに必要な構造の他のフィールドも入力されます。従って、未使用のフィールドはゼロを含みます(ただし、構造体のフィールドは、入力前にゼロにリセットされます)。構造体フィールドの説明を表示する際、いくつかのフィールドは使用されておらず、ゼロが含まれています。これは、未使用のフィールドをログに送信するときに表示されるべきです。例えば、値(1.12345)の小数点以下の桁数を使用する代わりに、1つだけ(0.0)を使用します。これにより、このフィールドが単に入力されていないことが明確になります。

最終的にログに構造体を出力する際には、トランザクションに応じて未使用のフィールドを考慮し、単に表示しないようにします。


実行されたアクションのタイプ

これは取引操作タイプで、値は、ENUM_TRADE_REQUEST_ACTIONS列挙値のいずれかです。

//+------------------------------------------------------------------+
//| Return the type of a performed action as a string                |
//+------------------------------------------------------------------+
string MqlTradeRequestAction(const MqlTradeRequest &req,const uint header_width=0,const uint indent=0,const bool ext_descr=false)
  {
//--- Define the header text and the width of the header field
//--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
   string header="Action:";
   uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Return the property value with a header having the required width and indentation
   return StringFormat("%*s%-*s%-s",indent,"",w,header,TradeActionDescription(req.action,ext_descr));
   /* Sample output:
      Action: Pending (Place a trade order for the execution under specified conditions (pending order)):
   */
  }


エキスパートアドバイザー(EA)のスタンプ(マジックナンバー識別子)

これはEAのIDで、取引注文を分析的に処理できるようにします。各EAは、取引リクエストを送信する際に一意のIDを設定することができます
//+------------------------------------------------------------------+
//| Return the EA stamp (magic number) as a string                   |
//+------------------------------------------------------------------+
string MqlTradeRequestMagic(const MqlTradeRequest &req,const uint header_width=0,const uint indent=0)
  {
//--- Define the header text and the width of the header field
//--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
   string header="Magic:";
   uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Return the property value with a header having the required width and indentation
   return StringFormat("%*s%-*s%-llu",indent,"",w,header,req.magic);
   /* Sample output:
      Magic: 1024
   */
  }


注文チケット

これは注文チケットで、未決注文の修正に必要です。

//+------------------------------------------------------------------+
//| Return the order ticket as a string                              |
//+------------------------------------------------------------------+
string MqlTradeRequestOrder(const MqlTradeRequest &req,const uint header_width=0,const uint indent=0)
  {
//--- Define the header text and the width of the header field
//--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
   string header="Order:";
   uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Return the property value with a header having the required width and indentation
   return StringFormat("%*s%-*s%-llu",indent,"",w,header,req.order);
   /* Sample output:
      Order: 1835982676
   */
  }


取引商品名

これは注文の対象となる取引商品名ですが、注文の変更およびポジションの決済時には不要です。

//+------------------------------------------------------------------+
//| Return a trading instrument name                                 |
//+------------------------------------------------------------------+
string MqlTradeRequestSymbol(const MqlTradeRequest &req,const uint header_width=0,const uint indent=0)
  {
//--- Define the header text and the width of the header field
//--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
   string header="Symbol:";
   uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Return the property value with a header having the required width and indentation
   return StringFormat("%*s%-*s%-s",indent,"",w,header,req.symbol);
   /* Sample output:
      Symbol: EURUSD
   */
  }


ロット単位での取引希望数量

リクエストされたロット単位の取引量です。取引をおこなう際の実際の出来高は、注文執行タイプに依存します。

//+------------------------------------------------------------------+
//| Return the requested volume of a deal in lots as a string        |
//+------------------------------------------------------------------+
string MqlTradeRequestVolume(const MqlTradeRequest &req,const uint header_width=0,const uint indent=0)
  {
//--- Define the header text and the width of the header field
//--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
   string header="Volume:";
   uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Get the number of decimal places in the lot value. If the character is not specified, use 1
   int dg=(int)ceil(fabs(log10(SymbolInfoDouble(req.symbol,SYMBOL_VOLUME_STEP))));
//--- Return the property value with a header having the required width and indentation
   return StringFormat("%*s%-*s%-.*f",indent,"",w,header,dg,req.volume);
   /* Sample output:
      Volume: 0.10
   */
  }


価格

注文を執行する価格です。TRADE_ACTION_DEALを持つ「成行執行」(SYMBOL_TRADE_EXECUTION_MARKET)型の商品の成行注文の場合、価格は設定されません。

//+------------------------------------------------------------------+
//| Return the price as a string                                     |
//+------------------------------------------------------------------+
string MqlTradeRequestPrice(const MqlTradeRequest &req,const uint header_width=0,const uint indent=0)
  {
//--- Define the header text and the width of the header field
//--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
   string header="Price:";
   uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Get the number of decimal places
   int dg=(req.price!=0 ? (int)SymbolInfoInteger(req.symbol,SYMBOL_DIGITS) : 1);
//--- Return the property value with a header having the required width and indentation
   return StringFormat("%*s%-*s%-.*f",indent,"",w,header,dg,req.price);
   /* Sample output:
      Price: 1.09586
   */
  }


ストップリミット注文レベル

BuyStopLimitとSellStopLimitの未決注文用です。価格がprice値に達したときに、指値注文が発注される価格(この条件は必須)です。指値注文は、その瞬間まで取引システムに渡されません

//+------------------------------------------------------------------+
//| Return the StopLimit order level as a string                     |
//+------------------------------------------------------------------+
string MqlTradeRequestStopLimit(const MqlTradeRequest &req,const uint header_width=0,const uint indent=0)
  {
//--- Define the header text and the width of the header field
//--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
   string header="StopLimit:";
   uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Get the number of decimal places
   int dg=(req.stoplimit!=0 ? (int)SymbolInfoInteger(req.symbol,SYMBOL_DIGITS) : 1);
//--- Return the property value with a header having the required width and indentation
   return StringFormat("%*s%-*s%-.*f",indent,"",w,header,dg,req.stoplimit);
   /* Sample output:
      StopLimit: 0.0
   */
  }


ストップロス注文レベル

ストップロス注文は、価格が不利な方向に動いたときに発動される価格です

//+------------------------------------------------------------------+
//| Return the Stop Loss order level as a string                     |
//+------------------------------------------------------------------+
string MqlTradeRequestStopLoss(const MqlTradeRequest &req,const uint header_width=0,const uint indent=0)
  {
//--- Define the header text and the width of the header field
//--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
   string header="SL:";
   uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Get the number of decimal places
   int dg=(req.sl!=0 ? (int)SymbolInfoInteger(req.symbol,SYMBOL_DIGITS) : 1);
//--- Return the property value with a header having the required width and indentation
   return StringFormat("%*s%-*s%-.*f",indent,"",w,header,dg,req.sl);
   /* Sample output:
      SL: 0.0
   */
  }


テイクプロフィット注文レベル

価格が有利な方向に動いたときに、利食い注文が有効になる価格です

//+------------------------------------------------------------------+
//| Return the Take Profit order level as a string                   |
//+------------------------------------------------------------------+
string MqlTradeRequestTakeProfit(const MqlTradeRequest &req,const uint header_width=0,const uint indent=0)
  {
//--- Define the header text and the width of the header field
//--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
   string header="TP:";
   uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Get the number of decimal places
   int dg=(req.tp!=0 ? (int)SymbolInfoInteger(req.symbol,SYMBOL_DIGITS) : 1);
//--- Return the property value with a header having the required width and indentation
   return StringFormat("%*s%-*s%-.*f",indent,"",w,header,dg,req.tp);
   /* Sample output:
      TP: 0.0
   */
  }


リクエスト価格との乖離

ポイント単位で指定される、リクエスト価格からの許容可能な最大偏差です

//+------------------------------------------------------------------+
//| Return the maximum acceptable                                    |
//| deviation from the requested price                               |
//+------------------------------------------------------------------+
string MqlTradeRequestDeviation(const MqlTradeRequest &req,const uint header_width=0,const uint indent=0)
  {
//--- Define the header text and the width of the header field
//--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
   string header="Deviation:";
   uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Return the property value with a header having the required width and indentation
   return StringFormat("%*s%-*s%-llu",indent,"",w,header,req.deviation);
   /* Sample output:
      Deviation: 5
   */
  }


注文タイプ

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

//+------------------------------------------------------------------+
//| Return the order type as a string                                |
//+------------------------------------------------------------------+
string MqlTradeRequestType(const MqlTradeRequest &req,const uint header_width=0,const uint indent=0,bool ext_descr=false)
  {
//--- Define the header text and the width of the header field
//--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
   string header="Type:";
   uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Return the property value with a header having the required width and indentation
   return StringFormat("%*s%-*s%-s",indent,"",w,header,OrderTypeDescription(req.type,ext_descr));
   /* Sample output:
      Type: Buy Limit (Buy Limit pending order)
   */
  }


注文処理タイプ

これは注文処理のタイプで、値はENUM_ORDER_TYPE_FILLING値のいずれかです。

//+------------------------------------------------------------------+
//| Return the order type by execution as a string                   |
//+------------------------------------------------------------------+
string MqlTradeRequestTypeFilling(const MqlTradeRequest &req,const uint header_width=0,const uint indent=0,bool ext_descr=false)
  {
//--- Define the header text and the width of the header field
//--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
   string header="Type filling:";
   uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Return the property value with a header having the required width and indentation
   return StringFormat("%*s%-*s%-s",indent,"",w,header,OrderTypeFillingDescription(req.type_filling,ext_descr));
   /* Sample output:
      Type filling: Return (In case of partial filling, an order with remaining volume is not canceled but processed further)
   */
  }


注文寿命タイプ

有効期限別の注文タイプで、値は、ENUM_ORDER_TYPE_TIME値のいずれかです。

//+------------------------------------------------------------------+
//| Return the order type by expiration time as a string             |
//+------------------------------------------------------------------+
string MqlTradeRequestTypeTime(const MqlTradeRequest &req,const uint header_width=0,const uint indent=0,bool ext_descr=false)
  {
//--- Define the header text and the width of the header field
//--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
   string header="Type time:";
   uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Return the property value with a header having the required width and indentation
   return StringFormat("%*s%-*s%-s",indent,"",w,header,OrderTypeTimeDescription(req.type_time,ext_descr));
   /* Sample output:
      Type time: Time GTC (Good till cancel order)
   */
  }


注文有効期限

未決注文の有効期限 (ORDER_TIME_SPECIFIED型の注文用)。

//+------------------------------------------------------------------+
//| Return the order expiration time as a string                     |
//+------------------------------------------------------------------+
string MqlTradeRequestExpiration(const MqlTradeRequest &req,const uint header_width=0,const uint indent=0)
  {
//--- Define the header text and the width of the header field
//--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
   string header="Expiration:";
   uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Return the property value with a header having the required width and indentation
   return StringFormat("%*s%-*s%-s",indent,"",w,header,(req.type_time==ORDER_TIME_SPECIFIED || req.type_time==ORDER_TIME_SPECIFIED_DAY ? (string)req.expiration : "0"));
   /* Sample output:
      Expiration: 0
   */
  }


注文へのコメント

//+------------------------------------------------------------------+
//| Return the order comment                                         |
//+------------------------------------------------------------------+
string MqlTradeRequestComment(const MqlTradeRequest &req,const uint header_width=0,const uint indent=0)
  {
//--- Define the header text and the width of the header field
//--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
   string header="Comment:";
   uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Return the property value with a header having the required width and indentation
   return StringFormat("%*s%-*s%-s",indent,"",w,header,req.comment);
   /* Sample output:
      Comment: TestMqlTradeTransaction
   */
  }


ポジションチケット

ポジションチケットです。ポジションを変更したり、閉じたりする際に入力され、明確に識別できるようにします。通常、ポジションを開いた注文のチケットと同じです。

//+------------------------------------------------------------------+
//| Return the position ticket as a string                           |
//+------------------------------------------------------------------+
string MqlTradeRequestPosition(const MqlTradeRequest &req,const uint header_width=0,const uint indent=0)
  {
//--- Define the header text and the width of the header field
//--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
   string header="Position:";
   uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Return the property value with a header having the required width and indentation
   return StringFormat("%*s%-*s%-llu",indent,"",w,header,req.position);
   /* Sample output:
      Position: 1835982676
   */
  }


反対側ポジションのチケット

反対側のポジションのチケットです。ポジションを反対方向(同じ銘柄で建てたが反対方向)に決済するときに使用します。

//+------------------------------------------------------------------+
//| Return the opposite position ticket as a string                  |
//+------------------------------------------------------------------+
string MqlTradeRequestPositionBy(const MqlTradeRequest &req,const uint header_width=0,const uint indent=0)
  {
//--- Define the header text and the width of the header field
//--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
   string header="Position by:";
   uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Return the property value with a header having the required width and indentation
   return StringFormat("%*s%-*s%-llu",indent,"",w,header,req.position_by);
   /* Sample output:
      Position by: 1835987626
   */
  }


使用例

異なるタイプの取引注文の場合、構造体フィールドは注文に応じて個別に入力されます。実行されるアクションに応じて構造体フィールドの説明をログに記録する関数と、ポジションの開閉や未決注文の設定/削除をおこなう取引関数を作成します。

次は、取引リクエスト明細を操作ログに表示する関数です。

//+------------------------------------------------------------------+
//| Display the trading request description in the journal           |
//+------------------------------------------------------------------+
void TradeRequestPrint(const MqlTradeRequest &req,const uint header_width=0,const uint indent=0,bool ext_descr=false)
  {
//--- Get execution type by symbol
   ENUM_SYMBOL_TRADE_EXECUTION exemode=(ENUM_SYMBOL_TRADE_EXECUTION)SymbolInfoInteger(req.symbol,SYMBOL_TRADE_EXEMODE);
//--- Header
   PrintFormat("Request %s:",TradeActionDescription(req.action,ext_descr));
//--- Place an order for an instant deal with the specified parameters (set a market order)
   if(req.action==TRADE_ACTION_DEAL)
     {
      //--- Depending on the transaction mode 
      switch(exemode)
        {
         //--- Trade order to open a position in the Request Execution mode
         //--- Trade order to open a position in the Instant Execution mode
         case SYMBOL_TRADE_EXECUTION_REQUEST    :
         case SYMBOL_TRADE_EXECUTION_INSTANT    :
            Print(MqlTradeRequestSymbol(req,header_width,indent));
            Print(MqlTradeRequestVolume(req,header_width,indent));
            Print(MqlTradeRequestPrice(req,header_width,indent));
            if(req.position==0)  // Only for opening a position 
               Print(MqlTradeRequestStopLoss(req,header_width,indent));
            if(req.position==0)  // Only for opening a position 
               Print(MqlTradeRequestTakeProfit(req,header_width,indent));
            Print(MqlTradeRequestDeviation(req,header_width,indent));
            Print(MqlTradeRequestType(req,header_width,indent,ext_descr));
            Print(MqlTradeRequestTypeFilling(req,header_width,indent,ext_descr));
            Print(MqlTradeRequestMagic(req,header_width,indent));
            if(req.position==0)  // Only for opening a position 
               Print(MqlTradeRequestComment(req,header_width,indent));
            //--- Closing
            if(req.position!=0)
               Print(MqlTradeRequestPosition(req,header_width,indent));
           break;
         //--- Trade order to open a position in the Market Execution mode
         //--- Trade order to open a position in the Exchange Execution mode
         case SYMBOL_TRADE_EXECUTION_MARKET     :
         case SYMBOL_TRADE_EXECUTION_EXCHANGE   :
            Print(MqlTradeRequestSymbol(req,header_width,indent));
            Print(MqlTradeRequestVolume(req,header_width,indent));
            Print(MqlTradeRequestType(req,header_width,indent,ext_descr));
            Print(MqlTradeRequestTypeFilling(req,header_width,indent,ext_descr));
            Print(MqlTradeRequestMagic(req,header_width,indent));
            if(req.position==0)  // Only for opening a position 
               Print(MqlTradeRequestComment(req,header_width,indent));
            //--- Closing
            if(req.position!=0)
               Print(MqlTradeRequestPosition(req,header_width,indent));
           break;
         default:
           break;
        }
     }
//--- Trading order to close a position by an opposite one
   if(req.action==TRADE_ACTION_CLOSE_BY)
     {
      Print(MqlTradeRequestSymbol(req,header_width,indent));
      Print(MqlTradeRequestPosition(req,header_width,indent));
      Print(MqlTradeRequestMagic(req,header_width,indent));
      Print(MqlTradeRequestComment(req,header_width,indent));
      Print(MqlTradeRequestPositionBy(req,header_width,indent));
     }
//--- Trading order to modify StopLoss and/or TakeProfit levels
   if(req.action==TRADE_ACTION_SLTP)
     {
      Print(MqlTradeRequestSymbol(req,header_width,indent));
      Print(MqlTradeRequestStopLoss(req,header_width,indent));
      Print(MqlTradeRequestTakeProfit(req,header_width,indent));
      Print(MqlTradeRequestPosition(req,header_width,indent));
     }
//--- Trading order to place a pending order
   if(req.action==TRADE_ACTION_PENDING)
     {
      Print(MqlTradeRequestSymbol(req,header_width,indent));
      Print(MqlTradeRequestVolume(req,header_width,indent));
      Print(MqlTradeRequestPrice(req,header_width,indent));
      if(req.type==ORDER_TYPE_BUY_STOP_LIMIT || req.type==ORDER_TYPE_SELL_STOP_LIMIT)
         Print(MqlTradeRequestStopLimit(req,header_width,indent));
      Print(MqlTradeRequestStopLoss(req,header_width,indent));
      Print(MqlTradeRequestTakeProfit(req,header_width,indent));
      Print(MqlTradeRequestType(req,header_width,indent,ext_descr));
      Print(MqlTradeRequestTypeFilling(req,header_width,indent,ext_descr));
      Print(MqlTradeRequestTypeTime(req,header_width,indent,ext_descr));
      Print(MqlTradeRequestExpiration(req,header_width,indent));
      Print(MqlTradeRequestMagic(req,header_width,indent));
      Print(MqlTradeRequestComment(req,header_width,indent));
     }
//--- Trading order to modify the price levels of a pending order
   if(req.action==TRADE_ACTION_MODIFY)
     {
      Print(MqlTradeRequestOrder(req,header_width,indent));
      Print(MqlTradeRequestPrice(req,header_width,indent));
      if(req.stoplimit!=0)
         Print(MqlTradeRequestStopLimit(req,header_width,indent));
      Print(MqlTradeRequestStopLoss(req,header_width,indent));
      Print(MqlTradeRequestTakeProfit(req,header_width,indent));
      Print(MqlTradeRequestTypeTime(req,header_width,indent,ext_descr));
      Print(MqlTradeRequestExpiration(req,header_width,indent));
     }
//--- Trading order to remove a pending order
   if(req.action==TRADE_ACTION_REMOVE)
     {
      Print(MqlTradeRequestOrder(req,header_width,indent));
     }
   /* Sample output:
      Request Pending (Place a trade order for the execution under specified conditions (pending order)):
        Symbol: EURUSD
        Volume: 0.10
        Price: 1.09586
        SL: 0.0
        TP: 0.0
        Type: Buy Limit (Buy Limit pending order)
        Type filling: Return (In case of partial filling, an order with remaining volume is not canceled but processed further)
        Type time: Time GTC (Good till cancel order)
        Expiration: 0
        Magic: 1024
        Comment: TestMqlTradeTransaction
   */
  }


OpenBuyで買いポジションを建てる

//+------------------------------------------------------------------+
//| Open Buy position                                                |
//+------------------------------------------------------------------+
bool OpenBuy(const string symbol,const double lots,const uint magic,const ulong deviation=5,const string comment="")
  {
//--- Set a symbol for a request
   string symbol_name=(symbol==NULL ? Symbol() : symbol);
//--- Declare and initialize the request and result structures
   MqlTradeRequest request={};
   MqlTradeResult  result={};
//--- Get the normalized price
   double price=NormalizeDouble(SymbolInfoDouble(symbol_name,SYMBOL_ASK),(int)SymbolInfoInteger(symbol_name,SYMBOL_DIGITS));
//--- request parameters
   request.action    =  TRADE_ACTION_DEAL;                        // trading operation type
   request.symbol    =  symbol_name;                              // symbol
   request.volume    =  lots;                                     // position volume
   request.type      =  ORDER_TYPE_BUY;                           // order type
   request.price     =  price;                                    // open price
   request.deviation =  deviation;                                // allowed deviation from the price
   request.magic     =  magic;                                    // order MagicNumber
   request.comment   =  comment;                                  // Order comment
//--- If failed to send a request, inform of that and return 'false'
   if(!OrderSend(request,result))
     {
      PrintFormat("%s: OrderSend for %s %s error: %s",__FUNCTION__,
                  TradeActionDescription(request.action),OrderTypeDescription(request.type),RetcodeDescription(result.retcode,true)
                 );
      return false;
     }
//--- OrderSend OK, return 'true'
   return true;
  }


OpenSellで売りポジションを建てる

//+------------------------------------------------------------------+
//| Open a Sell position                                             |
//+------------------------------------------------------------------+
bool OpenSell(const string symbol,const double lots,const uint magic,const ulong deviation=5,const string comment="")
  {
//--- Set a symbol for a request
   string symbol_name=(symbol==NULL ? Symbol() : symbol);
//--- Declare and initialize the request and result structures
   MqlTradeRequest request={};
   MqlTradeResult  result={};
//--- Get the normalized price
   double price=NormalizeDouble(SymbolInfoDouble(symbol_name,SYMBOL_BID),(int)SymbolInfoInteger(symbol_name,SYMBOL_DIGITS));
//--- request parameters
   request.action    =  TRADE_ACTION_DEAL;                        // trading operation type
   request.symbol    =  symbol_name;                              // symbol
   request.volume    =  lots;                                     // position volume
   request.type      =  ORDER_TYPE_SELL;                          // order type
   request.price     =  price;                                    // open price
   request.deviation =  deviation;                                // allowed deviation from the price
   request.magic     =  magic;                                    // order MagicNumber
   request.comment   =  comment;                                  // Order comment
//--- If failed to send a request, inform of that and return 'false'
   if(!OrderSend(request,result))
     {
      PrintFormat("%s: OrderSend for %s %s error: %s",__FUNCTION__,
                  TradeActionDescription(request.action),OrderTypeDescription(request.type),RetcodeDescription(result.retcode,true)
                 );
      return false;
     }
//--- OrderSend OK, return 'true'
   return true;
  }


ClosePositionで指定したポジションを閉じる

//+------------------------------------------------------------------+
//| Close position by ticket                                         |
//+------------------------------------------------------------------+
bool ClosePosition(const ulong ticket,const ulong deviation=5)
  {
//--- Declare request and result structures
   MqlTradeRequest request;
   MqlTradeResult  result;
//--- If failed to select a position by ticket, inform of the error and leave
   ResetLastError();
   if(!PositionSelectByTicket(ticket))
     {
      Print("PositionSelectByTicket failed, error: ",(string)GetLastError());
      return false;
     }
//--- Get the data on the closed position
   string position_symbol=PositionGetString(POSITION_SYMBOL);                       // symbol 
   int    digits=(int)SymbolInfoInteger(position_symbol,SYMBOL_DIGITS);             // number of decimal places
   double volume=PositionGetDouble(POSITION_VOLUME);                                // position volume
   ENUM_POSITION_TYPE type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);   // position type
   ulong magic=PositionGetInteger(POSITION_MAGIC);                                  // position MagicNumber
//--- Set request and result values to zero
   ZeroMemory(request);
   ZeroMemory(result);
//--- Set operation parameters
   request.action    =  TRADE_ACTION_DEAL;   // trading operation type
   request.position  =  ticket;              // position ticket
   request.symbol    =  position_symbol;     // symbol 
   request.volume    =  volume;              // position volume
   request.deviation =  deviation;           // allowed deviation from the price
   request.magic     =  magic;               // position MagicNumber
//--- Set order price and type depending on the position type
   if(type==POSITION_TYPE_BUY)
     {
      request.price=NormalizeDouble(SymbolInfoDouble(position_symbol,SYMBOL_BID),digits);
      request.type =ORDER_TYPE_SELL;
     }
   else
     {
      request.price=NormalizeDouble(SymbolInfoDouble(position_symbol,SYMBOL_ASK),digits);
      request.type =ORDER_TYPE_BUY;
     }
//--- If failed to send a request, inform of that and return 'false'
   if(!OrderSend(request,result))
     {
      PrintFormat("%s: OrderSend for %s %s #%llu error: %s",__FUNCTION__,
                  TradeActionDescription(request.action),OrderTypeDescription(request.type),ticket,RetcodeDescription(result.retcode,true)
                 );
      return false;
     }
//--- OrderSend OK, return 'true'
   return true;
  }


ClosePositionsAllですべてのポジションを閉じる

//+------------------------------------------------------------------+
//| Close all positions on a symbol                                  |
//+------------------------------------------------------------------+
uint ClosePositionsAll(const string symbol,const ulong magic=0)
  {
//--- Declare the variable for storing the result and the number of closed positions
   bool res=true;
   uint num=0;
//--- iterate over open positions
   int total=PositionsTotal();                     // number of open positions
   for(int i=total-1; i>=0; i--)
     {
      ulong  position_ticket=PositionGetTicket(i); // position ticket
      if(position_ticket==0)
         continue;
      if(PositionGetInteger(POSITION_MAGIC)!=magic)
         continue;
      //--- If MagicNumber is not specified (zero) or position magic number matches the specified one
      if(magic==0 || PositionGetInteger(POSITION_MAGIC)==magic)
        {
         //--- if the position symbol matches the one passed or NULL is passed, close the position on the ticket 
         if(symbol==NULL || PositionGetString(POSITION_SYMBOL)==symbol)
           {
            //--- Get the result of closing a position on a ticket and increase the counter of closed positions if successful 
            res &=ClosePosition(position_ticket);
            if(res)
               num++;
           }
        }
     }
   if(!res)
      PrintFormat("%s: Not all positions were able to close without errors",__FUNCTION__);
   return num;
  }


SetPendingで指値注文を出す

//+------------------------------------------------------------------+
//| Place a specified pending order                                  |
//+------------------------------------------------------------------+
bool SetPending(const string symbol,const ENUM_ORDER_TYPE order_type,const double lots,const uint magic,const int distance,const int stoplimit=0,const string comment="")
  {
//--- Set a symbol for a request
   string symbol_name=(symbol==NULL ? Symbol() : symbol);
//--- Declare and initialize the request and result structures
   MqlTradeRequest request={};
   MqlTradeResult  result={};
//--- Set operation parameters
   request.action    =  TRADE_ACTION_PENDING;                     // trading operation type
   request.type      =  order_type;                               // order type
   request.symbol    =  symbol_name;                              // symbol
   request.volume    =  lots;                                     // volume
   request.magic     =  magic;                                    // order MagicNumber
   request.comment   =  comment;                                  // Order comment
//--- Get Point and Digits
   double point=SymbolInfoDouble(symbol_name,SYMBOL_POINT);
   int digits=(int)SymbolInfoInteger(symbol_name,SYMBOL_DIGITS);
//--- Calculate the distance from the price depending on the order type
//--- Buy order
   if(order_type==ORDER_TYPE_BUY_STOP)
      request.price=NormalizeDouble(SymbolInfoDouble(symbol_name,SYMBOL_ASK)+distance*point,digits);  // normalized setting price 
   if(order_type==ORDER_TYPE_BUY_LIMIT)
      request.price=NormalizeDouble(SymbolInfoDouble(symbol_name,SYMBOL_ASK)-distance*point,digits);  // normalized setting price 
   if(order_type==ORDER_TYPE_BUY_STOP_LIMIT)
     {
      request.price=NormalizeDouble(SymbolInfoDouble(symbol_name,SYMBOL_ASK)+distance*point,digits);  // normalized Stop order trigger price 
      request.stoplimit=NormalizeDouble(request.price-stoplimit*point,digits);                        // normalized Limit order setting price
     }
//--- Sell order
   if(order_type==ORDER_TYPE_SELL_STOP)
      request.price=NormalizeDouble(SymbolInfoDouble(symbol_name,SYMBOL_BID)-distance*point,digits);  // normalized setting price 
   if(order_type==ORDER_TYPE_SELL_LIMIT)
      request.price=NormalizeDouble(SymbolInfoDouble(symbol_name,SYMBOL_BID)+distance*point,digits);  // normalized setting price 
   if(order_type==ORDER_TYPE_SELL_STOP_LIMIT)
     {
      request.price=NormalizeDouble(SymbolInfoDouble(symbol_name,SYMBOL_BID)-distance*point,digits);  // normalized Stop order trigger price 
      request.stoplimit=NormalizeDouble(request.price+stoplimit*point,digits);                        // normalized Limit order setting price
     }
//--- If failed to send a request, inform of that and return 'false'
   if(!OrderSend(request,result))
     {
      PrintFormat("%s: OrderSend for %s %s error: %s",__FUNCTION__,
                  TradeActionDescription(request.action),OrderTypeDescription(request.type),RetcodeDescription(result.retcode,true)
                 );
      return false;
     }
//--- OrderSend OK, return 'true'
   return true;
  }


上記で紹介した関数を基に、未決注文の特定のタイプを設定する関数を作成することができます。

SetBuyStopで買い注文を設定する

//+------------------------------------------------------------------+
//| Place BuyStop pending order                                      |
//+------------------------------------------------------------------+
bool SetBuyStop(const string symbol,const double lots,const uint magic,const int distance,const string comment="")
  {
//--- Call the SetPending function with BuyStop parameters
   return SetPending(symbol,ORDER_TYPE_BUY_STOP,lots,magic,distance,0,comment);
  }


SetBuyLimitで買い指値注文を設定する

//+------------------------------------------------------------------+
//| Place BuyLimit pending order                                     |
//+------------------------------------------------------------------+
bool SetBuyLimit(const string symbol,const double lots,const uint magic,const int distance,const string comment="")
  {
//--- Call the SetPending function with BuyLimit parameters
   return SetPending(symbol,ORDER_TYPE_BUY_LIMIT,lots,magic,distance,0,comment);
  }


SetBuyStopLimitでBuyStopLimit注文を設定する

//+------------------------------------------------------------------+
//| Place BuyStopLimit pending order                                 |
//+------------------------------------------------------------------+
bool SetBuyStopLimit(const string symbol,const double lots,const uint magic,const int distance,const int stoplimit,const string comment="")
  {
//--- Call the SetPending function with BuyStopLimit parameters
   return SetPending(symbol,ORDER_TYPE_BUY_STOP_LIMIT,lots,magic,distance,stoplimit,comment);
  }


SetSellStopで売り逆指値注文を設定する

//+------------------------------------------------------------------+
//| Place SellStop pending order                                     |
//+------------------------------------------------------------------+
bool SetSellSellStop(const string symbol,const double lots,const uint magic,const int distance,const string comment="")
  {
//--- Call the SetPending function with SellStop parameters
   return SetPending(symbol,ORDER_TYPE_SELL_STOP,lots,magic,distance,0,comment);
  }


SetSellLimitで売り指値注文を設定する

//+------------------------------------------------------------------+
//| Place SellLimit pending order                                    |
//+------------------------------------------------------------------+
bool SetSellLimit(const string symbol,const double lots,const uint magic,const int distance,const string comment="")
  {
//--- Call the SetPending function with SellLimit parameters
   return SetPending(symbol,ORDER_TYPE_SELL_LIMIT,lots,magic,distance,0,comment);
  }


SetSellStopLimitでSellStopLimit注文を設定する

//+------------------------------------------------------------------+
//| Place SellStopLimit pending order                                |
//+------------------------------------------------------------------+
bool SetSellStopLimit(const string symbol,const double lots,const uint magic,const int distance,const int stoplimit,const string comment="")
  {
//--- Call the SetPending function with SellStopLimit parameters
   return SetPending(symbol,ORDER_TYPE_SELL_STOP_LIMIT,lots,magic,distance,stoplimit,comment);
  }


DeleteOrderで指定した未決注文を削除する

//+------------------------------------------------------------------+
//| Delete a pending order by ticket                                 |
//+------------------------------------------------------------------+
bool DeleteOrder(const ulong ticket)
  {
//--- declare and initialize the trade request and result
   MqlTradeRequest request={};
   MqlTradeResult  result={};
   ResetLastError();
//--- If failed to select an order by ticket, inform of the error and leave
   if(!OrderSelect(ticket))
     {
      PrintFormat("%s: OrderSelect failed, error: %d",__FUNCTION__,GetLastError());
      return false;
     }
//--- Set request and result values to zero
   ZeroMemory(request);
   ZeroMemory(result);
//--- Set operation parameters
   request.action=TRADE_ACTION_REMOVE;                   // trading operation type
   request.order = ticket;                               // order ticket
//--- If failed to send a request, inform of that and return 'false'
   if(!OrderSend(request,result))
     {
      PrintFormat("%s: OrderSend for %s %s #%llu error: %s",__FUNCTION__,
                  TradeActionDescription(request.action),OrderTypeDescription((ENUM_ORDER_TYPE)OrderGetInteger(ORDER_TYPE)),ticket,RetcodeDescription(result.retcode,true)
                 );
      return false;
     }
//--- OrderSend OK, return 'true'
   return true;
  }


DeleteOrdersAllで未決注文をすべて削除する

//+------------------------------------------------------------------+
//| Delete all pending orders by symbol                              |
//+------------------------------------------------------------------+
uint DeleteOrdersAll(const string symbol,const long magic=WRONG_VALUE)
  {
//--- Declare the variable for storing the result and the number of removed orders
   bool res=true;
   uint num=0;
//--- iterate over all placed pending orders
   int total=OrdersTotal(); // number of pending orders
   for(int i=total-1; i>=0; i--)
     {
      ulong  order_ticket=OrderGetTicket(i);             // order ticket
      if(order_ticket==0)
         continue;
      //--- If MagicNumber is not specified (zero) or order magic number matches the specified one
      if(magic==WRONG_VALUE || OrderGetInteger(ORDER_MAGIC)==magic)
        {
         //--- if the order symbol matches the one passed or NULL is passed, remove order by ticket
         if(symbol==NULL || OrderGetString(ORDER_SYMBOL)==symbol)
           {
            res &=DeleteOrder(order_ticket);
            if(res)
               num++;
           }
        }
     }
   if(!res)
      PrintFormat("%s: Not all orders were able to close without errors",__FUNCTION__);
   return num;
  }

上記で紹介した取引関数はすべて単純な例関数です。エラーコードやサーバーのリターンコードによってエラーを処理したり修正したりすることはありません。これらに基づいてこのような関数を実装することもできますが、この記事の範囲外です。

取引注文の構造体に入力した後、その有効性を確認することができます。これは、OrderCheck()関数を使用しておこなうことができます。この関数は、必要な取引操作を完了するのに十分な資金を確認します。

資金が不足していたり、パラメータが正しく入力されていなかったりした場合、この関数はfalseを返します。構造体(ポインタ)の基本的な確認が成功した場合はtrueを返しますが、これは、要求された取引操作が正常に実行されることを意味するものではありません 。関数実行結果の詳細な説明を得るためには、結果 構造体フィールドを分析する必要があります。

確認結果はMqlTradeCheckResult構造体のフィールドに配置されます。構造体フィールドの説明を表示するために必要な関数を実装しましょう。


準備されたリクエストを送信前に確認するためのMqlTradeCheckResult構造体

取引サーバーにリクエストを送る前に、取引操作を確認することをお勧めします。確認は、確認されるリクエストとMqlTradeCheckResult構造型の変数を受け取るOrderCheck()関数によって実行されます。確認の結果は変数に設定されます。

struct MqlTradeCheckResult
  {
   uint         retcode;             // Response code
   double       balance;             // Balance after performing a deal
   double       equity;              // Equity after performing a deal
   double       profit;              // Floating profit
   double       margin;              // Margin requirements
   double       margin_free;         // Free margin
   double       margin_level;        // Margin level
   string       comment;             // Comment on the response code (error description)
  };


応答コード

リターンコード 取引操作を実行するすべての注文は、OrderSend()関数を使用してMqlTradeRequest取引リクエスト構造体として送信されます。関数の実行結果はMqlTradeResult構造体に格納されます。retcode フィールドには取引サーバーのリターンコードが含まれています。取引注文を確認した後、応答コードをMqlTradeCheckResult構造体のretcodeフィールドで読み取ることができます。

//+------------------------------------------------------------------+
//| Return the response code as a string                             |
//+------------------------------------------------------------------+
string MqlTradeCheckResultRetcode(const MqlTradeCheckResult &result,const uint header_width=0,const uint indent=0,const bool ext_descr=false)
  {
//--- Define the header text and the width of the header field
//--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
   string header="Retcode:";
   uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Return the property value with a header having the required width and indentation
   return StringFormat("%*s%-*s%-s",indent,"",w,header,RetcodeDescription(result.retcode,ext_descr));
   /* Sample output:
      Retcode: OK (0)
   */
  }


取引実行後の残高

取引操作を実行した後の残高です

//+----------------------------------------------------------------------+
//| Returns the balance as a string after a trade operation is performed |
//+----------------------------------------------------------------------+
string MqlTradeCheckResultBalance(const MqlTradeCheckResult &result,const uint header_width=0,const uint indent=0)
  {
//--- Define the header text and the width of the header field
//--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
   string header="Balance:";
   uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Get the account currency
   string currency=AccountInfoString(ACCOUNT_CURRENCY);
//--- Get the number of decimal places
   int dg=(int)AccountInfoInteger(ACCOUNT_CURRENCY_DIGITS);
//--- Return the property value with a header having the required width and indentation
   return StringFormat("%*s%-*s%-.*f %s",indent,"",w,header,dg,result.balance,currency);
   /* Sample output:
      Balance: 10016.80 USD
   */
  }


取引実行後のエクイティ

取引操作を実行した後の株式価値です

//+--------------------------------------------------------------------+
//| Return the equity as a string after a trade operation is performed |
//+--------------------------------------------------------------------+
string MqlTradeCheckResultEquity(const MqlTradeCheckResult &result,const uint header_width=0,const uint indent=0)
  {
//--- Define the header text and the width of the header field
//--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
   string header="Equity:";
   uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Get the account currency
   string currency=AccountInfoString(ACCOUNT_CURRENCY);
//--- Get the number of decimal places
   int dg=(int)AccountInfoInteger(ACCOUNT_CURRENCY_DIGITS);
//--- Return the property value with a header having the required width and indentation
   return StringFormat("%*s%-*s%-.*f %s",indent,"",w,header,dg,result.equity,currency);
   /* Sample output:
      Equity: 10016.80 USD
   */
  }


浮動利益

取引操作を実行した後の浮動利益です

//+---------------------------------------------------------------------------+
//|Return the floating profit as a string after a trade operation is performed|
//+---------------------------------------------------------------------------+
string MqlTradeCheckResultProfit(const MqlTradeCheckResult &result,const uint header_width=0,const uint indent=0)
  {
//--- Define the header text and the width of the header field
//--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
   string header="Profit:";
   uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Get the account currency
   string currency=AccountInfoString(ACCOUNT_CURRENCY);
//--- Get the number of decimal places
   int dg=(int)AccountInfoInteger(ACCOUNT_CURRENCY_DIGITS);
//--- Return the property value with a header having the required width and indentation
   return StringFormat("%*s%-*s%-.*f %s",indent,"",w,header,dg,result.profit,currency);
   /* Sample output:
      Profit: 0.00 USD
   */
  }


必要証拠金

必要な取引操作に必要な証拠金の額.です。

//+------------------------------------------------------------------+
//| Return the margin,                                               |
//| required for the necessary trading operation, as a string        |
//+------------------------------------------------------------------+
string MqlTradeCheckResultMargin(const MqlTradeCheckResult &result,const uint header_width=0,const uint indent=0)
  {
//--- Define the header text and the width of the header field
//--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
   string header="Margin:";
   uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Get the account currency
   string currency=AccountInfoString(ACCOUNT_CURRENCY);
//--- Get the number of decimal places
   int dg=(int)AccountInfoInteger(ACCOUNT_CURRENCY_DIGITS);
//--- Return the property value with a header having the required width and indentation
   return StringFormat("%*s%-*s%-.*f %s",indent,"",w,header,dg,result.margin,currency);
   /* Sample output:
      Margin: 128.66 USD
   */
  }


余剰証拠金

取引をおこなった後に残る資本の価値です。

//+------------------------------------------------------------------+
//| Return the value of equity                                       |
//| to be left after conducting a trading operation as a string      |
//+------------------------------------------------------------------+
string MqlTradeCheckResultMarginFree(const MqlTradeCheckResult &result,const uint header_width=0,const uint indent=0)
  {
//--- Define the header text and the width of the header field
//--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
   string header="Margin free:";
   uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Get the account currency
   string currency=AccountInfoString(ACCOUNT_CURRENCY);
//--- Get the number of decimal places
   int dg=(int)AccountInfoInteger(ACCOUNT_CURRENCY_DIGITS);
//--- Return the property value with a header having the required width and indentation
   return StringFormat("%*s%-*s%-.*f %s",indent,"",w,header,dg,result.margin_free,currency);
   /* Sample output:
      Margin free: 9888.14 USD
   */
  }


証拠金レベル

必要な取引操作を完了した後に設定される証拠金レベルです。

//+-----------------------------------------------------------------------+
//| Return the margin level                                               |
//| to be set after completing the required trading operation as a string |
//+-----------------------------------------------------------------------+
string MqlTradeCheckResultMarginLevel(const MqlTradeCheckResult &result,const uint header_width=0,const uint indent=0)
  {
//--- Define the header text and the width of the header field
//--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
   string header="Margin level:";
   uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Return the property value with a header having the required width and indentation
   return StringFormat("%*s%-*s%-.2f %%",indent,"",w,header,result.margin_level);
   /* Sample output:
      Margin level: 7785.48 %
   */
  }


応答コードへのコメント

応答コード、エラーの説明についてのコメントです。

//+------------------------------------------------------------------+
//| Return comment on the response code, error description           |
//+------------------------------------------------------------------+
string MqlTradeCheckResultComment(const MqlTradeCheckResult &result,const uint header_width=0,const uint indent=0)
  {
//--- Define the header text and the width of the header field
//--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
   string header="Comment:";
   uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Return the property value with a header having the required width and indentation
   return StringFormat("%*s%-*s%-s",indent,"",w,header,result.comment);
   /* Sample output:
      Comment: Done
   */
  }


使用例

以下は、操作ログ内のすべての MqlTradeCheckResult構造体フィールドを表示する関数です。

//+------------------------------------------------------------------+
//| Display the MqlTradeCheckResult structure fields in the journal  |
//| as a result of OrderCheck                                        |
//+------------------------------------------------------------------+
void OrderCheckResultPrint(const MqlTradeCheckResult &result,const uint header_width=0,const uint indent=0,bool ext_descr=false)
  {
   Print("OrderCheck result:");
   Print(MqlTradeCheckResultRetcode(result,header_width,indent,ext_descr));
   Print(MqlTradeCheckResultBalance(result,header_width,indent));
   Print(MqlTradeCheckResultEquity(result,header_width,indent));
   Print(MqlTradeCheckResultProfit(result,header_width,indent));
   Print(MqlTradeCheckResultMargin(result,header_width,indent));
   Print(MqlTradeCheckResultMarginFree(result,header_width,indent));
   Print(MqlTradeCheckResultMarginLevel(result,header_width,indent));
   Print(MqlTradeCheckResultComment(result,header_width,indent));
   /* Sample output:
      OrderCheck result:
        Retcode:      Undefined (0)
        Balance:      10016.80 USD
        Equity:       10016.80 USD
        Profit:       0.00 USD
        Margin:       128.66 USD
        Margin free:  9888.14 USD
        Margin level: 7785.48 %
        Comment:      Done
   */
  }

完了した取引注文を確認し、エラーを受信した場合は、完了したMqlTradeCheckResult構造体を操作ログに送信してエラーを分析できます。


OrderSend()関数によって送信されたリクエストに対するサーバーの応答を持つMqlTradeResult構造体

取引システムに注文を出すための取引リクエストに応答して、取引サーバーは、特別なMqlTradeResult構造体の形で取引リクエストの処理結果に関する情報を含むデータを返します。

struct MqlTradeResult
  {
   uint     retcode;          // Operation result code
   ulong    deal;             // Deal ticket if executed
   ulong    order;            // Order ticket if placed
   double   volume;           // Deal volume confirmed by a broker
   double   price;            // Deal price confirmed by a broker
   double   bid;              // The current market Bid price (requote price)
   double   ask;              // The current market Ask price (requote price)
   string   comment;          // Broker comment to operation (by default, it is filled by the trade server return code description)
   uint     request_id;       // Request ID set by the terminal when sending 
   int      retcode_external; // Response code of an external trading system
  };

取引操作の結果は、MqlTradeResult型の変数に返され、これは、取引操作をおこなうためのOrderSend()関数の2番目のパラメータとして渡されます。

構造体フィールドの説明を表示するために、以下の関数を実装します。

動作結果コード

取引サーバーのリターンコードです。
//+------------------------------------------------------------------+
//| Return the operation result code as a string                     |
//+------------------------------------------------------------------+
string MqlTradeResultRetcode(const MqlTradeResult &result,const uint header_width=0,const uint indent=0,const bool ext_descr=false)
  {
//--- Define the header text and the width of the header field
//--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
   string header="Retcode:";
   uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Return the property value with a header having the required width and indentation
   return StringFormat("%*s%-*s%-s",indent,"",w,header,RetcodeDescription(result.retcode,ext_descr));
   /* Sample output:
      Retcode: 10009 DONE (Request completed)
   */
  }


取引チケット

取引がおこなわれた場合の取引チケットです。TRADE_ACTION_DEAL型の取引操作で使用できます。
//+------------------------------------------------------------------+
//| Return the deal ticket if it is completed                        |
//+------------------------------------------------------------------+
string MqlTradeResultDeal(const MqlTradeResult &result,const uint header_width=0,const uint indent=0)
  {
//--- Define the header text and the width of the header field
//--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
   string header="Deal:";
   uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Return the property value with a header having the required width and indentation
   return StringFormat("%*s%-*s%-llu",indent,"",w,header,result.deal);
   /* Sample output:
      Deal: 0
   */
  }


注文チケット

注文が設定されていた場合の注文チケットです。TRADE_ACTION_PENDING取引操作で利用可能です。
//+------------------------------------------------------------------+
//| Return the order ticket as a string if the order is set          |
//+------------------------------------------------------------------+
string MqlTradeResultOrder(const MqlTradeResult &result,const uint header_width=0,const uint indent=0)
  {
//--- Define the header text and the width of the header field
//--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
   string header="Order:";
   uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Return the property value with a header having the required width and indentation
   return StringFormat("%*s%-*s%-llu",indent,"",w,header,result.order);
   /* Sample output:
      Order: 1821552382
   */
  }


取引量

ブローカーが確認した取引量です。注文処理タイプに依存します
//+------------------------------------------------------------------+
//| Return the deal volume confirmed by a broker as a string         |
//+------------------------------------------------------------------+
string MqlTradeResultVolume(const string symbol,const MqlTradeResult &result,const uint header_width=0,const uint indent=0)
  {
//--- Define the header text and the width of the header field
//--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
   string header="Volume:";
   uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Get the number of decimal places in the lot value
   int dg=(int)ceil(fabs(log10(SymbolInfoDouble(symbol,SYMBOL_VOLUME_STEP))));
//--- Return the property value with a header having the required width and indentation
   return StringFormat("%*s%-*s%-.*f",indent,"",w,header,dg,result.volume);
   /* Sample output:
      Volume: 0.10
   */
  }


取引価格

ブローカーが確認した取引価格です。取引リクエストのdeviationフィールドおよび/または取引操作タイプに依存します。

//+------------------------------------------------------------------+
//| Return a deal price, confirmed by a broker, as a string          |
//+------------------------------------------------------------------+
string MqlTradeResultPrice(const string symbol,const MqlTradeResult &result,const uint header_width=0,const uint indent=0)
  {
//--- Define the header text and the width of the header field
//--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
   string header="Price:";
   uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Get the number of decimal places
   int dg=(result.price!=0 ? (int)SymbolInfoInteger(symbol,SYMBOL_DIGITS) : 1);
//--- Return the property value with a header having the required width and indentation
   return StringFormat("%*s%-*s%-.*f",indent,"",w,header,dg,result.price);
   /* Sample output:
      Price: 0.0
   */
  }


現在のBid市場価格

現在の市場のBid価格(リクオート価格)です
//+------------------------------------------------------------------+
//| Return the current market Bid price as a string                  |
//+------------------------------------------------------------------+
string MqlTradeResultBid(const string symbol,const MqlTradeResult &result,const uint header_width=0,const uint indent=0)
  {
//--- Define the header text and the width of the header field
//--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
   string header="Bid:";
   uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Get the number of decimal places
   int dg=(result.bid!=0 ? (int)SymbolInfoInteger(symbol,SYMBOL_DIGITS) : 1);
//--- Return the property value with a header having the required width and indentation
   return StringFormat("%*s%-*s%-.*f",indent,"",w,header,dg,result.bid);
   /* Sample output:
      Bid: 0.0
   */
  }


現在のAsk市場価格

現在の市場のAsk価格(リクオート価格)です
//+------------------------------------------------------------------+
//| Return the current market Ask price as a string                  |
//+------------------------------------------------------------------+
string MqlTradeResultAsk(const string symbol,const MqlTradeResult &result,const uint header_width=0,const uint indent=0)
  {
//--- Define the header text and the width of the header field
//--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
   string header="Ask:";
   uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Get the number of decimal places
   int dg=(result.ask!=0 ? (int)SymbolInfoInteger(symbol,SYMBOL_DIGITS) : 1);
//--- Return the property value with a header having the required width and indentation
   return StringFormat("%*s%-*s%-.*f",indent,"",w,header,dg,result.ask);
   /* Sample output:
      Ask: 0.0
   */
  }

未決済注文を発注する際、構造内のBidとAskの価格は空のままです。注文がリクオートによって受理されなかった場合、注文が発注を拒否された時点の価格をBidとAskのフィールドで見ることができます。


ブローカーの取引コメント

操作に対するブローカーのコメント(デフォルトでは、取引サーバーのリターンコードの説明が入力)です
//+------------------------------------------------------------------+
//| Return broker's comment on a deal                                |
//+------------------------------------------------------------------+
string MqlTradeResultComment(const MqlTradeResult &result,const uint header_width=0,const uint indent=0)
  {
//--- Define the header text and the width of the header field
//--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
   string header="Comment:";
   uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Return the property value with a header having the required width and indentation
   return StringFormat("%*s%-*s%-s",indent,"",w,header,result.comment);
   /* Sample output:
      Comment: Request executed
   */
  }


リクエストID

端末が取引サーバーに送信する際に設定するリクエストIDです
//+------------------------------------------------------------------+
//| Return request ID as a string                                    |
//+------------------------------------------------------------------+
string MqlTradeResultRequestID(const MqlTradeResult &result,const uint header_width=0,const uint indent=0)
  {
//--- Define the header text and the width of the header field
//--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
   string header="Request ID:";
   uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Return the property value with a header having the required width and indentation
   return StringFormat("%*s%-*s%-lu",indent,"",w,header,result.request_id);
   /* Sample output:
      Request ID: 3768213261
   */
  }

サーバーへの送信時に取引端末がrequest_id を設定するのは、主にOrderSendAsync()非同期関数と連携するためです。この識別子により、実行されたアクション(OrderSendまたはOrderSendAsync関数の呼び出し)とOnTradeTransaction()に送信されたアクションの結果を関連付けることができます。


外部取引システム応答コード

外部取引システムから返されたエラーコードです。これらのエラーの用途と種類は、ブローカーと、取引操作が送信される外部取引システムに依存します。
//+-------------------------------------------------------------------+
//| Return the response code of an external trading system as a string|
//+-------------------------------------------------------------------+
string MqlTradeResultRetcodeExternal(const MqlTradeResult &result,const uint header_width=0,const uint indent=0)
  {
//--- Define the header text and the width of the header field
//--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
   string header="Retcode External:";
   uint w=(header_width==0 ? header.Length()+1 : header_width-1);
//--- Return the property value with a header having the required width and indentation
   return StringFormat("%*s%-*s%- ld",indent,"",w,header,result.retcode_external);
   /* Sample output:
      Retcode External:  0
   */
  }


使用例

以下は、取引リクエスト結果構造のすべてのフィールドを操作ログに表示する関数です。

//+------------------------------------------------------------------+
//| Display MqlTradeResult structure fields in the journal           |
//| as a result of a trade request                                   |
//+------------------------------------------------------------------+
void TradeResultPrint(const string symbol,const MqlTradeResult &result,const uint header_width=0,const uint indent=0,bool ext_descr=false)
  {
   string symbol_name=(symbol==NULL ? Symbol() : symbol);
   Print("OrderSend result:");
   Print(MqlTradeResultRetcode(result,header_width,indent,ext_descr));
   Print(MqlTradeResultDeal(result,header_width,indent));
   Print(MqlTradeResultOrder(result,header_width,indent));
   Print(MqlTradeResultVolume(symbol_name,result,header_width,indent));
   Print(MqlTradeResultPrice(symbol_name,result,header_width,indent));
   Print(MqlTradeResultBid(symbol_name,result,header_width,indent));
   Print(MqlTradeResultAsk(symbol_name,result,header_width,indent));
   Print(MqlTradeResultComment(result,header_width,indent));
   Print(MqlTradeResultRequestID(result,header_width,indent));
   Print(MqlTradeResultRetcodeExternal(result,header_width,indent));
   /* Sample output:
      OrderSend result:
        Retcode:          10009 DONE (Request completed)
        Deal:             0
        Order:            1821671230
        Volume:           0.10
        Price:            0.0
        Bid:              0.0
        Ask:              0.0
        Comment:          Request executed
        Request ID:       3768213265
        Retcode External: 0
   */
  }


MqlTradeTransaction構造体と取引トランザクションの説明

取引口座で特定のアクションを実行した結果、その状態が変化します。これらのアクションには以下が含まれます。

  • OrderSend関数およびOrderSendAsync関数を使用した、クライアント端末の任意のMQL5アプリケーションによる取引リクエストの送信とその後の実行
  • 端末のグラフィカルインターフェースを通じた取引リクエストの送信とその後の実行
  • サーバー上での未決注文と逆指値注文のトリガー
  • 取引サーバー側での操作の実行

これらの行動の結果、口座に対して以下の取引トランザクションがおこなわれます。

  • 取引リクエストの処理
  • 未決済注文の変更
  • 注文履歴の変更
  • 取引履歴の変更
  • ポジションの変更

例えば、成行買い注文を送信すると、それが処理され、対応する買い注文が口座に作成され、注文が執行され、未決済の注文リストから削除され、注文履歴に追加されます。その後、対応する取引が履歴に追加され、新しいポジションが作成されます。これらの行為はすべて取引トランザクションです。

MQL5は、口座に適用された取引トランザクションを受信するOnTradeTransaction()ハンドラを備えています。このハンドラの最初のパラメータは、取引トランザクションを記述するMqlTradeTransaction構造体を受け取ります。

struct MqlTradeTransaction
  {
   ulong                         deal;             // Deal ticket
   ulong                         order;            // Order ticket
   string                        symbol;           // Symbol name
   ENUM_TRADE_TRANSACTION_TYPE   type;             // Trading transaction type
   ENUM_ORDER_TYPE               order_type;       // Order type
   ENUM_ORDER_STATE              order_state;      // Order state
   ENUM_DEAL_TYPE                deal_type;        // Deal type
   ENUM_ORDER_TYPE_TIME          time_type;        // Order lifetime type
   datetime                      time_expiration;  // Order expiration time
   double                        price;            // Price 
   double                        price_trigger;    // Stop limit order trigger price
   double                        price_sl;         // Stop Loss level
   double                        price_tp;         // Take Profit level
   double                        volume;           // Volume in lots
   ulong                         position;         // Position ticket
   ulong                         position_by;      // Opposite position ticket
  };


すべての構造体フィールドの説明を返すために、以下の関数を実装してみましょう。

取引チケット

//+------------------------------------------------------------------+
//| Return the deal ticket as a string                               |
//+------------------------------------------------------------------+
string MqlTradeTransactionDeal(const MqlTradeTransaction &trans,const uint header_width=0,const uint indent=0)
  {
//--- Define the header text and the width of the header field
//--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
   string header="Deal:";
   uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Return the property value with a header having the required width and indentation
   return StringFormat("%*s%-*s%-llu",indent,"",w,header,trans.deal);
   /* Sample output:
      Deal: 0
   */
  }


注文チケット

//+------------------------------------------------------------------+
//| Return the order ticket as a string                              |
//+------------------------------------------------------------------+
string MqlTradeTransactionOrder(const MqlTradeTransaction &trans,const uint header_width=0,const uint indent=0)
  {
//--- Define the header text and the width of the header field
//--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
   string header="Order:";
   uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Return the property value with a header having the required width and indentation
   return StringFormat("%*s%-*s%-llu",indent,"",w,header,trans.order);
   /* Sample output:
      Order: 1825990224
   */
  }


取引商品名

取引が実行された取引銘柄の名前です。

//+------------------------------------------------------------------+
//| Return an order symbol as a string                               |
//+------------------------------------------------------------------+
string MqlTradeTransactionSymbol(const MqlTradeTransaction &trans,const uint header_width=0,const uint indent=0)
  {
//--- Define the header text and the width of the header field
//--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
   string header="Symbol:";
   uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Return the property value with a header having the required width and indentation
   return StringFormat("%*s%-*s%-s",indent,"",w,header,trans.symbol);
   /* Sample output:
      Symbol: EURUSD
   */
  }


取引トランザクションタイプ

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

//+------------------------------------------------------------------+
//| Return the trading transaction type as a string                  |
//+------------------------------------------------------------------+
string MqlTradeTransactionType(const MqlTradeTransaction &trans,const uint header_width=0,const uint indent=0,const bool ext_descr=false)
  {
//--- Define the header text and the width of the header field
//--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
   string header="Type:";
   uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Return the property value with a header having the required width and indentation
   return StringFormat("%*s%-*s%-s",indent,"",w,header,TradeTransactionTypeDescription(trans.type,ext_descr));
   /* Sample output:
      Type: Order delete (Removing an order from the list of the open ones)
   */
  }


注文タイプ

取引注文の種類です。値は、ENUM_ORDER_TYPE列挙値の1つです。

//+------------------------------------------------------------------+
//| Return the order type as a string                                |
//+------------------------------------------------------------------+
string MqlTradeTransactionOrderType(const MqlTradeTransaction &trans,const uint header_width=0,const uint indent=0,const bool ext_descr=false)
  {
//--- Declare variables to indicate transaction affiliation
   bool trans_req=false;   // Request
   bool trans_order=false; // Order
   bool trans_deal=false;  // Deal
   bool trans_pos=false;   // Position
//--- Set transaction affiliation
   SetTransactionBelong(trans.type,trans_req,trans_order,trans_deal,trans_pos);
//--- Define the header text and the width of the header field
//--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
   string header="Order type:";
   uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Return the property value with a header having the required width and indentation
   return StringFormat("%*s%-*s%-s",indent,"",w,header,(trans_order ? OrderTypeDescription(trans.order_type,ext_descr) : "0"));
   /* Sample output:
      Order type: Sell Limit (Sell Limit pending order)
   */
  }

この関数は、取引トランザクションの所属を決定します。トランザクションが注文で実行された場合は、そのタイプが返され、そうでない場合は0が返されます。


注文状況

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

//+------------------------------------------------------------------+
//| Return the order status as a string                              |
//+------------------------------------------------------------------+
string MqlTradeTransactionOrderState(const MqlTradeTransaction &trans,const uint header_width=0,const uint indent=0,const bool ext_descr=false)
  {
//--- Declare variables to indicate transaction affiliation
   bool trans_req=false;   // Request
   bool trans_order=false; // Order
   bool trans_deal=false;  // Deal
   bool trans_pos=false;   // Position
//--- Set transaction affiliation
   SetTransactionBelong(trans.type,trans_req,trans_order,trans_deal,trans_pos);
//--- Define the header text and the width of the header field
//--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
   string header="Order state:";
   uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Return the property value with a header having the required width and indentation
   return StringFormat("%*s%-*s%-s",indent,"",w,header,(trans_order ? OrderStateDescription(trans.order_state,ext_descr) : "0"));
   /* Sample output:
      Order state: Started (Order checked, but not yet accepted by broker)
   */
  }

この関数は、取引トランザクションの所属を決定します。トランザクションが注文で実行された場合は、そのステータスが返され、そうでない場合は0が返されます。


取引タイプ

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

//+------------------------------------------------------------------+
//| Return the deal type as a string                                 |
//+------------------------------------------------------------------+
string MqlTradeTransactionDealType(const MqlTradeTransaction &trans,const uint header_width=0,const uint indent=0,const bool ext_descr=false)
  {
//--- Declare variables to indicate transaction affiliation
   bool trans_req=false;   // Request
   bool trans_order=false; // Order
   bool trans_deal=false;  // Deal
   bool trans_pos=false;   // Position
//--- Set transaction affiliation
   SetTransactionBelong(trans.type,trans_req,trans_order,trans_deal,trans_pos);
//--- Define the header text and the width of the header field
//--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
   string header="Deal type:";
   uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Return the property value with a header having the required width and indentation
   return StringFormat("%*s%-*s%-s",indent,"",w,header,(trans_deal || trans_pos ? DealTypeDescription(trans.deal_type,ext_descr) : "0"));
   /* Sample output:
      Deal type: Buy
   */
  }

この関数は、取引トランザクションの所属を決定します。トランザクションが取引で実行された場合はそのタイプが返され、そうでない場合は0が返されます。


注文寿命タイプ

執行による注文の種類です。値は、ENUM_ORDER_TYPE_TIME値のいずれかです。

//+------------------------------------------------------------------+
//| Return the order type by expiration time as a string             |
//+------------------------------------------------------------------+
string MqlTradeTransactionTimeType(const MqlTradeTransaction &trans,const uint header_width=0,const uint indent=0,const bool ext_descr=false)
  {
//--- Declare variables to indicate transaction affiliation
   bool trans_req=false;   // Request
   bool trans_order=false; // Order
   bool trans_deal=false;  // Deal
   bool trans_pos=false;   // Position
//--- Set transaction affiliation
   SetTransactionBelong(trans.type,trans_req,trans_order,trans_deal,trans_pos);
//--- Define the header text and the width of the header field
//--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
   string header="Time type:";
   uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Return the property value with a header having the required width and indentation
   return StringFormat("%*s%-*s%-s",indent,"",w,header,(trans_order ? OrderTypeTimeDescription(trans.time_type,ext_descr) : "0"));
   /* Sample output:
      Order type time: Time GTC (Good till cancel order)
   */
  }

この関数は、取引トランザクションの所属を決定します。トランザクションが注文で実行された場合は、その期限によるタイプが返され、そうでない場合は0が返されます。


注文有効期限

未決注文の有効期限です(ORDER_TIME_SPECIFIEDおよびORDER_TIME_SPECIFIED_DAY型の注文用)。

//+------------------------------------------------------------------+
//| Return the order expiration time as a string                     |
//+------------------------------------------------------------------+
string MqlTradeTransactionTimeExpiration(const MqlTradeTransaction &trans,const uint header_width=0,const uint indent=0)
  {
//--- Define the header text and the width of the header field
//--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
   string header="Time expiration:";
   uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Set the expiration time as a string. If 0, then set 0
   string tm=(trans.time_expiration==0 ? "0" : (string)trans.time_expiration);
//--- Return the property value with a header having the required width and indentation
   return StringFormat("%*s%-*s%-s",indent,"",w,header,tm);
   /* Sample output:
      Time expiration: 0
   */
  }

構造体フィールドの有効期限がゼロに設定されている場合は「0」を表示し、そうでない場合は有効期限を日付形式で表示します。もしフィールドの値がゼロかどうかを確認しなければ、ゼロの値は1970年01月01日00:00:00と表示され、注文の有効期限切れの美観を損ねます。


価格

価格です。取引トランザクションのタイプに応じて、注文、取引、ポジションとなります。

//+------------------------------------------------------------------+
//| Return the order/deal/position price as a string                 |
//+------------------------------------------------------------------+
string MqlTradeTransactionPrice(const MqlTradeTransaction &trans,const uint header_width=0,const uint indent=0)
  {
//--- Define the header text and the width of the header field
//--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
   string header="Price:";
   uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Receive symbol's Digits. If the character is not specified, use 1
   int dg=(trans.symbol!="" ? (int)SymbolInfoInteger(trans.symbol,SYMBOL_DIGITS) : 1);
//--- Return the property value with a header having the required width and indentation
   return StringFormat("%*s%-*s%-.*f",indent,"",w,header,dg,trans.price);
   /* Sample output:
      Price: 1.10331
   */
  }


逆指値注文のトリガー価格

逆指値注文(ORDER_TYPE_BUY_STOP_LIMITおよびORDER_TYPE_SELL_STOP_LIMIT)の逆指値(トリガー価格)です。

//+------------------------------------------------------------------+
//| Return the stop limit order trigger price as a string            |
//+------------------------------------------------------------------+
string MqlTradeTransactionPriceTrigger(const MqlTradeTransaction &trans,const uint header_width=0,const uint indent=0)
  {
//--- Define the header text and the width of the header field
//--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
   string header="Price trigger:";
   uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Receive symbol's Digits. If a symbol is not specified or there is no stop price, use 1
   int dg=(trans.symbol!="" ? (int)SymbolInfoInteger(trans.symbol,SYMBOL_DIGITS) : 1);
   if(trans.price_trigger==0)
      dg=1;
//--- Return the property value with a header having the required width and indentation
   return StringFormat("%*s%-*s%-.*f",indent,"",w,header,dg,trans.price_trigger);
   /* Sample output:
      Price trigger: 0.0
   */
  }

逆指値注文価格が指定されていない場合は「0.0」、指定されていない場合は注文価格が表示されます。


ストップロスレベル

損切りの価格です。取引トランザクションのタイプに応じて、注文、取引、ポジションを指すことがあります。

//+------------------------------------------------------------------+
//| Return Stop Loss price as a string                               |
//+------------------------------------------------------------------+
string MqlTradeTransactionPriceSL(const MqlTradeTransaction &trans,const uint header_width=0,const uint indent=0)
  {
//--- Define the header text and the width of the header field
//--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
   string header="Price SL:";
   uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Receive symbol's Digits. If a symbol is not specified or a Stop Loss price is absent, use 1
   int dg=(trans.symbol!="" ? (int)SymbolInfoInteger(trans.symbol,SYMBOL_DIGITS) : 1);
   if(trans.price_sl==0)
      dg=1;
//--- Return the property value with a header having the required width and indentation
   return StringFormat("%*s%-*s%-.*f",indent,"",w,header,dg,trans.price_sl);
   /* Sample output:
      Price SL: 0.0
   */
  }

損切りが設定されていない場合、「0.0」と表示されます。


テイクプロフィットレベル

利食い価格です。取引トランザクションのタイプに応じて、注文、取引、ポジションを指すことがあります。

//+------------------------------------------------------------------+
//| Return a Take Profit price as a string                           |
//+------------------------------------------------------------------+
string MqlTradeTransactionPriceTP(const MqlTradeTransaction &trans,const uint header_width=0,const uint indent=0)
  {
//--- Define the header text and the width of the header field
//--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
   string header="Price TP:";
   uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Receive symbol's Digits. If a symbol is not specified or a Take Profit price is absent, use 1
   int dg=(trans.symbol!="" ? (int)SymbolInfoInteger(trans.symbol,SYMBOL_DIGITS) : 1);
   if(trans.price_tp==0)
      dg=1;
//--- Return the property value with a header having the required width and indentation
   return StringFormat("%*s%-*s%-.*f",indent,"",w,header,dg,trans.price_tp);
   /* Sample output:
      Price TP: 0.0
   */
  }

利食い価格が設定されていない場合は、「0.0」を表示し、そうでない場合は、利食い価格を表示します。


ロット数

ロット数です。取引トランザクションのタイプに応じて、現在の注文量、取引量、ポジション量を定義することができます。

//+------------------------------------------------------------------+
//| Return volume in lots as a string                                |
//+------------------------------------------------------------------+
string MqlTradeTransactionVolume(const MqlTradeTransaction &trans,const uint header_width=0,const uint indent=0)
  {
//--- Define the header text and the width of the header field
//--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
   string header="Volume:";
   uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Get the number of decimal places in the lot value. If the character is not specified, use 1
   int dg=(trans.symbol!="" ? (int)ceil(fabs(log10(SymbolInfoDouble(trans.symbol,SYMBOL_VOLUME_STEP)))) : 1);
//--- Return the property value with a header having the required width and indentation
   return StringFormat("%*s%-*s%-.*f",indent,"",w,header,dg,trans.volume);
   /* Sample output:
      Volume: 0.10
   */
  }


ポジションチケット

トランザクションによって影響を受けるポジションのチケットです。

//+------------------------------------------------------------------+
//| Return the position ticket as a string                           |
//+------------------------------------------------------------------+
string MqlTradeTransactionPosition(const MqlTradeTransaction &trans,const uint header_width=0,const uint indent=0)
  {
//--- Define the header text and the width of the header field
//--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
   string header="Position:";
   uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Return the property value with a header having the required width and indentation
   return StringFormat("%*s%-*s%-llu",indent,"",w,header,trans.position);
   /* Sample output:
      Position: 0
   */
  }


反対側ポジションのチケット

反対側のポジションのチケットです。ポジションを反対方向(同じ銘柄で建てたが反対方向)に決済するときに使用します。

//+------------------------------------------------------------------+
//| Return the opposite position ticket as a string                  |
//+------------------------------------------------------------------+
string MqlTradeTransactionPositionBy(const MqlTradeTransaction &trans,const uint header_width=0,const uint indent=0)
  {
//--- Define the header text and the width of the header field
//--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
   string header="Position by:";
   uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Return the property value with a header having the required width and indentation
   return StringFormat("%*s%-*s%-llu",indent,"",w,header,trans.position_by);
   /* Sample output:
      Position by: 0
   */
  }


使用例

上記の関数を使用すると、操作ログ内のMqlTradeTransaction構造体のすべてのフィールドを表示できます。

//+------------------------------------------------------------------+
//| Display the MqlTradeTransaction structure fields in the journal  |
//+------------------------------------------------------------------+
void MqlTradeTransactionPrint(const MqlTradeTransaction &trans,const uint header_width=0,const uint indent=0,const bool ext_descr=false)
  {
   Print(MqlTradeTransactionDeal(trans,header_width,indent));
   Print(MqlTradeTransactionOrder(trans,header_width,indent));
   Print(MqlTradeTransactionSymbol(trans,header_width,indent));
   Print(MqlTradeTransactionType(trans,header_width,indent,ext_descr));
   Print(MqlTradeTransactionOrderType(trans,header_width,indent,ext_descr));
   Print(MqlTradeTransactionOrderState(trans,header_width,indent,ext_descr));
   Print(MqlTradeTransactionDealType(trans,header_width,indent,ext_descr));
   Print(MqlTradeTransactionTimeType(trans,header_width,indent,ext_descr));
   Print(MqlTradeTransactionTimeExpiration(trans,header_width,indent));
   Print(MqlTradeTransactionPrice(trans,header_width,indent));
   Print(MqlTradeTransactionPriceTrigger(trans,header_width,indent));
   Print(MqlTradeTransactionPriceSL(trans,header_width,indent));
   Print(MqlTradeTransactionPriceTP(trans,header_width,indent));
   Print(MqlTradeTransactionVolume(trans,header_width,indent));
   Print(MqlTradeTransactionPosition(trans,header_width,indent));
   Print(MqlTradeTransactionPositionBy(trans,header_width,indent));
   /* Sample output:
      Deal:             0
      Order:            1829189788
      Symbol:           EURUSD
      Type:             Order add
      Order type:       Buy Limit
      Order state:      Started
      Deal type:        0
      Time type:        Time GTC
      Time expiration:  0
      Price:            1.09861
      Price trigger:    0.0
      Price SL:         0.0
      Price TP:         0.0
      Volume:           0.10
      Position:         0
      Position by:      0
   */
  }

この関数は、操作ログ内のMqlTradeTransaction構造体のすべてのフィールドを表示します。構造体フィールドは、取引イベントごとに異なって入力されます。

受信したトランザクションの分析に不可欠なパラメータは、typeフィールドで指定されたそのタイプです。例えば、TRADE_TRANSACTION_REQUEST型のトランザクション(サーバーによる取引リクエストの処理結果が受信された)の場合、構造体にはタイプのフィールドしかありません。それ以外の分野は分析していません。この場合、 OnTradeTransaction()ハンドラに送信された requestパラメータとresultパラメータの2つを分析することができます。

取引操作のタイプを知ることで、取引口座の注文、ポジション、取引の現状を分析することを決定できます。端末からサーバーに送信される1つの取引リクエストは、複数の取引トランザクションを生成できることに留意してください。端末への到着順は保証されていません。

MqlTradeTransaction構造体は、取引トランザクションの型(ENUM_TRADE_TRANSACTION_TYPE)に応じて異なる方法で入力されます。

TRADE_TRANSACTION_ORDER_*およびTRADE_TRANSACTION_HISTORY_*

未決済注文(TRADE_TRANSACTION_ORDER_ADD、TRADE_TRANSACTION_ORDER_UPDATE、TRADE_TRANSACTION_ORDER_DELETE)および注文履歴(TRADE_TRANSACTION_HISTORY_ADD、TRADE_TRANSACTION_HISTORY_UPDATE、TRADE_TRANSACTION_HISTORY_DELETE)の処理に関連する取引トランザクションでは、MqlTradeTransaction 構造体に以下のフィールドが入力されます。

  • 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_LIMITORDER_TYPE_SELL_STOP_LIMITのみ)
  • price_sl:ストップロス注文価格(注文で指定された場合に入力)
  • price_tp:テイクプロフィット注文価格(注文で指定された場合に入力)
  • volume :現在の注文数量(未約定)(初期注文量はHistoryOrders*関数を使用して注文履歴から求められる
  • position:注文執行の結果、オープン、変更、クローズされたポジションのチケット(成行注文のみで入力、TRADE_TRANSACTION_ORDER_ADDでは未入力)
  • position_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:反対ポジションのチケット(取引のみで入力)

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:取引トランザクションの種類
このタイプの取引について分析すべきフィールドは1つだけです。OnTradeTransaction関数の2番目と3番目のパラメータ(リクエストと結果)を分析し、追加情報を受け取る必要があります。

したがって、入ってくる取引イベントを考慮し、MqlTradeTransaction構造体の各トランザクションのタイプに必要なフィールドのみをログに記録する関数を作成することができます。

//+------------------------------------------------------------------+
//| Trading transaction informer                                     |
//+------------------------------------------------------------------+
void TradeTransactionInformer(const MqlTradeTransaction &trans,const MqlTradeRequest& request,const MqlTradeResult& result,
                              const uint header_width=0,const uint indent=0,const bool ext_descr=false)
  {
//--- Declare variables to indicate transaction affiliation
   bool trans_req=false;   // Request
   bool trans_order=false; // Order
   bool trans_deal=false;  // Deal
   bool trans_pos=false;   // Position
//--- Set transaction affiliation
   SetTransactionBelong(trans.type,trans_req,trans_order,trans_deal,trans_pos);
//--- Depending on the transaction affiliation, display descriptions of the corresponding structure fields
   //--- Trading request
   if(trans_req)
     {
      //--- Inform of the "trading request" transaction type and indicate that it is necessary to analyze the fields of the trading request and server response structure
      PrintFormat("Transaction %s\n%*sThe second and third parameters of OnTradeTransaction function (request and result) must be analyzed for additional data:",
         MqlTradeTransactionType(trans,0,0,true),indent,"");
      //--- Display the description of the trade request and the request result received from the server
      TradeRequestPrint(request,header_width,indent,ext_descr);
      TradeResultPrint(trans.symbol,result,header_width,indent,ext_descr);
     }
   //--- Otherwise, if the order/deal/position 
   else
     {
      //--- Display the transaction type in the journal
      PrintFormat("Transaction %s",MqlTradeTransactionType(trans,0,0,true));
      //--- Order
      if(trans_order)
        {
         Print(MqlTradeTransactionOrder(trans,header_width,indent));
         Print(MqlTradeTransactionSymbol(trans,header_width,indent));
         Print(MqlTradeTransactionOrderType(trans,header_width,indent,ext_descr));
         Print(MqlTradeTransactionOrderState(trans,header_width,indent,ext_descr));
         Print(MqlTradeTransactionTimeType(trans,header_width,indent,ext_descr));
         if(trans.time_type==ORDER_TIME_SPECIFIED || trans.time_type==ORDER_TIME_SPECIFIED_DAY)
            Print(MqlTradeTransactionTimeExpiration(trans,header_width,indent));
         Print(MqlTradeTransactionPrice(trans,header_width,indent));
         if(trans.order_type==ORDER_TYPE_BUY_STOP_LIMIT || trans.order_type==ORDER_TYPE_SELL_STOP_LIMIT)
            Print(MqlTradeTransactionPriceTrigger(trans,header_width,indent));
         Print(MqlTradeTransactionPriceSL(trans,header_width,indent));
         Print(MqlTradeTransactionPriceTP(trans,header_width,indent));
         Print(MqlTradeTransactionVolume(trans,header_width,indent));
         if(trans.type!=TRADE_TRANSACTION_ORDER_ADD && (trans.order_type==ORDER_TYPE_BUY || trans.order_type==ORDER_TYPE_SELL))
            Print(MqlTradeTransactionPosition(trans,header_width,indent));
         if(trans.order_type==ORDER_TYPE_CLOSE_BY)
            Print(MqlTradeTransactionPositionBy(trans,header_width,indent));
        }
      //--- Deal
      if(trans_deal)
        {
         Print(MqlTradeTransactionDeal(trans,header_width,indent));
         Print(MqlTradeTransactionOrder(trans,header_width,indent));
         Print(MqlTradeTransactionSymbol(trans,header_width,indent));
         Print(MqlTradeTransactionDealType(trans,header_width,indent,ext_descr));
         Print(MqlTradeTransactionPrice(trans,header_width,indent));
         Print(MqlTradeTransactionPriceSL(trans,header_width,indent));
         Print(MqlTradeTransactionPriceTP(trans,header_width,indent));
         Print(MqlTradeTransactionVolume(trans,header_width,indent));
         Print(MqlTradeTransactionPosition(trans,header_width,indent));
        }
      //--- Position
      if(trans_pos)
        {
         Print(MqlTradeTransactionSymbol(trans,header_width,indent));
         Print(MqlTradeTransactionDealType(trans,header_width,indent,ext_descr));
         Print(MqlTradeTransactionPrice(trans,header_width,indent));
         Print(MqlTradeTransactionPriceSL(trans,header_width,indent));
         Print(MqlTradeTransactionPriceTP(trans,header_width,indent));
         Print(MqlTradeTransactionVolume(trans,header_width,indent));
         Print(MqlTradeTransactionPosition(trans,header_width,indent));
        }
     }
   /* Sample output when setting the Sell Limit order:
      Transaction Type: Order add (Adding a new open order)
        Order: 1833072954
        Symbol: EURUSD
        Order type: Sell Limit (Sell Limit pending order)
        Order state: Started (Order checked, but not yet accepted by broker)
        Time type: Time GTC (Good till cancel order)
        Price: 1.10516
        Price SL: 0.0
        Price TP: 0.0
        Volume: 0.10
      Transaction Type: Order update (Updating an open order)
        Order: 1833072954
        Symbol: EURUSD
        Order type: Sell Limit (Sell Limit pending order)
        Order state: Placed (Order accepted)
        Time type: Time GTC (Good till cancel order)
        Price: 1.10516
        Price SL: 0.0
        Price TP: 0.0
        Volume: 0.10
      Transaction Type: Request (The trade request has been processed by a server and processing result has been received)
        The second and third parameters of OnTradeTransaction function (request and result) must be analyzed for additional data:
      Request Pending (Place a trade order for the execution under specified conditions (pending order)):
        Symbol: EURUSD
        Volume: 0.10
        Price: 1.10516
        SL: 0.0
        TP: 0.0
        Type: Sell Limit (Sell Limit pending order)
        Type filling: Return (In case of partial filling, an order with remaining volume is not canceled but processed further)
        Type time: Time GTC (Good till cancel order)
        Expiration: 0
        Magic: 1024
        Comment: TestMqlTradeTransaction
      OrderSend result:
        Retcode: 10009 DONE (Request completed)
        Deal: 0
        Order: 1833072954
        Volume: 0.10
        Price: 0.0
        Bid: 0.0
        Ask: 0.0
        Comment: 
        Request ID: 3768213464
        Retcode External:  0
      //---
      Here, when placing a Buy Limit pending order, we received three transactions:
         1. Request - a request to place a pending order was accepted by the server and a response was received. 
            To clarify information, it is necessary to analyze the fields of the MqlTradeRequest trade request structure 
            and the MqlTradeResult server response – 'request' and 'result', respectively.
         2. Adding a new pending order with the ticket #1829788294. Its status - Started.
         3. Changing an open order with the ticket #1829788294. Its status changed from Started to Placed.
      The order of transactions is not respected, but this is clearly indicated in the Help section concerning the OnTradeTransaction handler: 
      https://www.mql5.com/ja/docs/event_handlers/ontradetransaction.
   */
  }


取引情報提供EA

上述した機能の動作を確認するために、すべての取引トランザクションとサーバーの応答を追跡し、受信した取引トランザクションの説明を操作ログに表示するEAを作成してみましょう。設定で選択したキーを押すことで、未決注文(BuyStop、SellStop、BuyLimit、SellLimit)や建玉(ポジション)(Buy、Sell)を設定できるように実装してみましょう。デフォルトでは、以下のキーが取引管理に割り当てられます。

注文タイプ
開く/インストールするためのキーボードショートカット
閉じる/削除ためのキーボードショートカット
 買い
 B
 X
 売り
 S
 X
 買い逆指値
 Shift+B
 Shift+X、Ctrl+Shift+X
 買い指値
 Ctrl+Shift+B
 Shift+X、Ctrl+Shift+X
 売りストップ
 Shift+S
 Shift+X、Ctrl+Shift+X
 売り指値
 Ctrl+Shift+S
 Shift+X、Ctrl+Shift+X

キーは設定で自由に割り当てることができます。EAは自動的に大文字に変換します。買い、売り、手仕舞い(ポジション決済)/注文削除の3つのキーを設定できます。リクエスト内の未決注文のタイプを変更するための CtrlとShift Ctrlキーは、デフォルトで割り当てられており、変更することはできません。B'を押すと買いポジションが開き、シフトを押しながら'B'を押すと買い逆指値注文が設定されます。CtrlとShiftを同時に押しながら'B'を押すと、買い指値の未決注文が設定されます。S」を押すだけで売りポジションがオープンし、Ctrlキーを押し続けると売りストップと売りリミットが設定されます。すべての未決済ポジションを閉じるには、「X」ボタンを押します。シフトまたはCtrl+シフト(関係ありません)を押しながら「X」を押すと、すべての未決済注文が削除されます。

//+------------------------------------------------------------------+
//|                                      TestMqlTradeTransaction.mq5 |
//|                                  Copyright 2023, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
//--- input parameters
input double   InpLots        =  0.1;     /* Lots                       */ // Requested volume
input int      InpMagic       =  1024;    /* Magic number               */ // EA ID
input int      InpDistance    =  300;     /* Orders placement distance  */ // Distance for setting pending orders
input uint     InpDeviation   =  5;       /* Price deviation            */ // Allowed deviation from the price
input string   InpKeyBuy      =  "B";     /* Key to open Buy            */ // Key to open a Buy position (with Shift - Stop, with Ctrl+Shift - Limit)
input string   InpKeySell     =  "S";     /* Key to open Sell           */ // Key to open Sell (with Shift - Stop, with Ctrl+Shift - Limit)
input string   InpKeyClose    =  "X";     /* Key to close/delete        */ // Key for closing a position (without control keys) or deleting an order (with Shift or Shift+Ctrl)
//--- Global variables
ushort         key_buy;                   // Key to send a buy order 
ushort         key_sell;                  // Key to send a sell order
ushort         key_close;                 // Key to close or delete
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- Convert the text assigned to Buy to uppercase and get the code of the first character
   string tmp=InpKeyBuy;
   tmp.Upper();
   key_buy=StringGetCharacter(tmp,0);
//--- Convert the text assigned to Sell to uppercase and get the code of the first character
   tmp=InpKeySell;
   tmp.Upper();
   key_sell=StringGetCharacter(tmp,0);
//--- Convert the text assigned to Close to uppercase and get the code of the first character
   tmp=InpKeyClose;
   tmp.Upper();
   key_close=StringGetCharacter(tmp,0);

//--- If the keys assigned to Buy and Sell match, report this and exit with an error
   if(key_sell==key_buy)
     {
      PrintFormat("The key assigned to Sell ('%c') is the same as the key assigned to Buy ('%c')",key_sell,key_buy);
      return INIT_PARAMETERS_INCORRECT;
     }
//--- If the keys assigned to Close and Buy match, report this and exit with an error
   if(key_close==key_buy)
     {
      PrintFormat("The key assigned to Close ('%c') is the same as the key assigned to Buy ('%c')",key_close,key_buy);
      return INIT_PARAMETERS_INCORRECT;
     }
//--- If the keys assigned to Close and Sell match, report this and exit with an error
   if(key_close==key_sell)
     {
      PrintFormat("The key assigned to Close ('%c') is the same as the key assigned to Sell ('%c')",key_close,key_sell);
      return INIT_PARAMETERS_INCORRECT;
     }
//--- Successful initialization. Display the assigned keys in the journal and return successful execution
   string kb="Key assigned to Buy: ";
   string ks="Key assigned to Sell: ";
   string kc="Key assigned to Close: ";
   PrintFormat("%-23s%c (key code %lu)\n%-23s%c (key code %lu)\n%-23s%c (key code %lu)",kb,key_buy,key_buy,ks,key_sell,key_sell,kc,key_close,key_close);
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
   
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
   
  }
//+------------------------------------------------------------------+
//| ChartEvent function                                              |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
  {
//--- If a key is pressed
   if(id==CHARTEVENT_KEYDOWN)
     {
      //--- If neither Ctrl nor Shift are held 
      if(!IsCtrlKeyPressed() && !IsShiftKeyPressed())
        {
         //--- If the button is assigned to the Buy position, open Buy
         if(lparam==key_buy)
            OpenBuy(NULL,InpLots,InpMagic,InpDeviation,"TestMqlTradeTransaction");
         //--- If the button is assigned to the Sell position, open Sell
         if(lparam==key_sell)
            OpenSell(NULL,InpLots,InpMagic,InpDeviation,"TestMqlTradeTransaction");
         //--- If the button is assigned to closing positions, close all positions 
         if(lparam==key_close)
            ClosePositionsAll(Symbol());
        }
      //--- If only Shift is held 
      if(IsShiftKeyPressed() && !IsCtrlKeyPressed())
        {
         //--- If the button is assigned to Buy order, open Buy Stop order
         if(lparam==key_buy)
            SetBuyStop(NULL,InpLots,InpMagic,InpDistance,"TestMqlTradeTransaction");
         //--- If the button is assigned to Sell order, open Sell Stop order
         if(lparam==key_sell)
            SetSellSellStop(NULL,InpLots,InpMagic,InpDistance,"TestMqlTradeTransaction");
         //--- If the button is assigned to delete orders, delete all orders 
         if(lparam==key_close)
            DeleteOrdersAll(NULL);
        }
         //--- If Shift is held together with Ctrl
      if(IsShiftKeyPressed() && IsCtrlKeyPressed())
        {
         //--- If the button is assigned to Buy order, open Buy Limit order
         if(lparam==key_buy)
            SetBuyLimit(NULL,InpLots,InpMagic,InpDistance,"TestMqlTradeTransaction");
         //--- If the button is assigned to Sell order, open Sell Limit order
         if(lparam==key_sell)
            SetSellLimit(NULL,InpLots,InpMagic,InpDistance,"TestMqlTradeTransaction");
         //--- If the button is assigned to delete orders, delete all orders 
         if(lparam==key_close)
            DeleteOrdersAll(Symbol());
        }
     }
  }
//+------------------------------------------------------------------+
//| TradeTransaction function                                        |
//+------------------------------------------------------------------+
void OnTradeTransaction(const MqlTradeTransaction& trans,
                        const MqlTradeRequest& request,
                        const MqlTradeResult& result)
  {
//--- Set all incoming trade transactions to the journal
   TradeTransactionInformer(trans,request,result,18,2,true);
  }

注文の発注とポジションのオープンは、EAのOnChartEvent()ハンドラで実装されます。OnTradeTransaction()ハンドラで、上で説明したTradeTransactionInformer()関数を呼び出します。操作ログの各入力トランザクションが表示されます。EAはその作業において、記事で取り上げたすべての関数を使用するので、エラーなくコンパイルするためには、EAファイルにそれらを含める必要があります。

BuyLimit注文を発注すると、処理されたすべてのトランザクションの以下の項目が操作ログに表示されます。

Transaction Type: Order add (Adding a new open order)
  Order:            1838106218
  Symbol:           EURUSD
  Order type:       Buy Limit (Buy Limit pending order)
  Order state:      Started (Order checked, but not yet accepted by broker)
  Time type:        Time GTC (Good till cancel order)
  Price:            1.09449
  Price SL:         0.0
  Price TP:         0.0
  Volume:           0.10
Transaction Type: Order update (Updating an open order)
  Order:            1838106218
  Symbol:           EURUSD
  Order type:       Buy Limit (Buy Limit pending order)
  Order state:      Placed (Order accepted)
  Time type:        Time GTC (Good till cancel order)
  Price:            1.09449
  Price SL:         0.0
  Price TP:         0.0
  Volume:           0.10
Transaction Type: Request (The trade request has been processed by a server and processing result has been received)
  The second and third parameters of OnTradeTransaction function (request and result) must be analyzed for additional data:
Request Pending (Place a trade order for the execution under specified conditions (pending order)):
  Symbol:           EURUSD
  Volume:           0.10
  Price:            1.09449
  SL:               0.0
  TP:               0.0
  Type:             Buy Limit (Buy Limit pending order)
  Type filling:     Return (In case of partial filling, an order with remaining volume is not canceled but processed further)
  Type time:        Time GTC (Good till cancel order)
  Expiration:       0
  Magic:            1024
  Comment:          TestMqlTradeTransaction
OrderSend result:
  Retcode:          10009 DONE (Request completed)
  Deal:             0
  Order:            1838106218
  Volume:           0.10
  Price:            0.0
  Bid:              0.0
  Ask:              0.0
  Comment:          
  Request ID:       930808478
  Retcode External: 0

その後、発注した注文を削除する場合、端末操作ログに次のようなエントリが表示されます。

Transaction Type: Order update (Updating an open order)
  Order:            1838106218
  Symbol:           EURUSD
  Order type:       Buy Limit (Buy Limit pending order)
  Order state:      Request cancel (Order is being deleted (deleting from the trading system))
  Time type:        Time GTC (Good till cancel order)
  Price:            1.09449
  Price SL:         0.0
  Price TP:         0.0
  Volume:           0.10
Transaction Type: Order delete (Removing an order from the list of the open ones)
  Order:            1838106218
  Symbol:           EURUSD
  Order type:       Buy Limit (Buy Limit pending order)
  Order state:      Canceled (Order canceled by client)
  Time type:        Time GTC (Good till cancel order)
  Price:            1.09449
  Price SL:         0.0
  Price TP:         0.0
  Volume:           0.10
Transaction Type: History add (Adding an order to the history as a result of execution or cancellation)
  Order:            1838106218
  Symbol:           EURUSD
  Order type:       Buy Limit (Buy Limit pending order)
  Order state:      Canceled (Order canceled by client)
  Time type:        Time GTC (Good till cancel order)
  Price:            1.09449
  Price SL:         0.0
  Price TP:         0.0
  Volume:           0.10
Transaction Type: Request (The trade request has been processed by a server and processing result has been received)
  The second and third parameters of OnTradeTransaction function (request and result) must be analyzed for additional data:
Request Remove (Delete the pending order placed previously):
  Order:            1838106218
OrderSend result:
  Retcode:          10009 DONE (Request completed)
  Deal:             0
  Order:            1838106218
  Volume:           0.00
  Price:            0.0
  Bid:              0.0
  Ask:              0.0
  Comment:          
  Request ID:       930808479
  Retcode External: 0


結論

取引注文を作成し、それを確認し、サーバーに送信し、さらに取引操作の結果として口座で発生したすべての取引トランザクションの完全な説明を取得するためのすべての構造体を検討しました。

提案された関数はすべて「そのまま」使用できます。あるいは、読者の使用イメージに合わせて変更することもできます。

この記事で考慮されているすべての機能を含むEAファイルは添付ファイルに含まれています。ダウンロードして、自分ですべてをテストすることができます。

MetaQuotes Ltdによってロシア語から翻訳されました。
元の記事: https://www.mql5.com/ru/articles/13052

添付されたファイル |
時系列マイニングのためのデータラベル(第1回):EA操作チャートでトレンドマーカー付きデータセットを作成する 時系列マイニングのためのデータラベル(第1回):EA操作チャートでトレンドマーカー付きデータセットを作成する
この連載では、ほとんどの人工知能モデルに適合するデータを作成できる、いくつかの時系列のラベル付け方法を紹介します。ニーズに応じて的を絞ったデータのラベル付けをおこなうことで、訓練済みの人工知能モデルをより期待通りの設計に近づけ、モデルの精度を向上させ、さらにはモデルの質的飛躍を助けることができます。
ニューラルネットワークが簡単に(第51回):Behavior-Guided Actor-Critic (BAC) ニューラルネットワークが簡単に(第51回):Behavior-Guided Actor-Critic (BAC)
最後の2つの記事では、エントロピー正則化を報酬関数に組み込んだSoft Actor-Criticアルゴリズムについて検討しました。このアプローチは環境探索とモデル活用のバランスをとりますが、適用できるのは確率モデルのみです。今回の記事では、確率モデルと確定モデルの両方に適用できる代替アプローチを提案します。
MQL5の圏論(第19回):自然性の正方形の帰納法 MQL5の圏論(第19回):自然性の正方形の帰納法
自然性の正方形の帰納法を考えることで、自然変換について考察を続けます。MQL5ウィザードで組み立てられたエキスパートアドバイザー(EA)の多通貨の実装には若干の制約があるため、スクリプトでデータ分類能力を紹介しています。主な用途は、価格変動の分類とその予測です。
ニューラルネットワークが簡単に(第50回):Soft Actor-Critic(モデルの最適化) ニューラルネットワークが簡単に(第50回):Soft Actor-Critic(モデルの最適化)
前回の記事では、Soft Actor-Criticアルゴリズムを実装しましたが、有益なモデルを訓練することはできませんでした。今回は、先に作成したモデルを最適化し、望ましい結果を得ます。