English Русский 中文 Español Deutsch 日本語
preview
Operações de negociação Estruturas das solicitações e das resposta, descrição e registro

Operações de negociação Estruturas das solicitações e das resposta, descrição e registro

MetaTrader 5Exemplos | 17 janeiro 2024, 05:24
203 0
Artyom Trishkin
Artyom Trishkin

Conteúdo


Introdução

O MQL5 possui a função OrderSend() para a colocação de ordens pendentes, abertura de posições, alteração de ordens e posições. O primeiro parâmetro de entrada dessa função é a estrutura de solicitação de negociação MqlTradeRequest. No campo 'action' de tal estrutura, deve ser especificado o tipo de ação a ser executada, e os outros campos são preenchidos dependendo da ação selecionada. Por isso, quando passamos os parâmetros necessários para a solicitação de negociação na função, estamos realizando o envio de diferentes solicitações ao servidor.

Estrutura da solicitação de negociação (MqlTradeRequest)

A interação entre o terminal de cliente e o servidor de negociação para a colocação de ordens é feita por meio de solicitações de negociação. A solicitação é representada por uma estrutura pré-definida especial, MqlTradeRequest, que contém todos os campos necessários para concluir esse tipo de operações:

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
  };

No primeiro campo 'action', justamente é indicado o tipo de ação a ser executada.

Tipo de operação de negociação. O valor pode ser um dos valores da enumeração ENUM_TRADE_REQUEST_ACTIONS:

Identificador
Descrição
TRADE_ACTION_DEAL
Define uma ordem de negociação para execução imediata de uma transação com os parâmetros especificados (colocar uma ordem a mercado)
TRADE_ACTION_PENDING
Define uma ordem de negociação para executar uma transação conforme as condições especificadas (ordem pendente)
TRADE_ACTION_SLTP
Altera os valores de Stop Loss e Take Profit de uma posição aberta
TRADE_ACTION_MODIFY
Altera os parâmetros de uma ordem de negociação definida anteriormente
TRADE_ACTION_REMOVE
Exclui uma ordem de negociação pendente colocada previamente
TRADE_ACTION_CLOSE_BY
Fecha a posição oposta

Os campos da estrutura devem ser preenchidos individualmente para cada tipo de ação.

Após preencher os campos necessários da estrutura, a ordem de negociação pode ser enviada ao servidor. No entanto, antes disso, é possível verificar o preenchimento da estrutura usando a função OrderCheck(), à qual a própria solicitação a ser verificada e uma variável do tipo da estrutura MqlTradeCheckResult são passadas. O resultado da verificação será registrado nessa variável:

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)
  };

No caso de falta de fundos após a verificação da ordem ou parâmetros incorretamente preenchidos, a função retorna false. No caso de uma verificação básica bem-sucedida das estruturas (verificação de ponteiros), retorna-se true - isso não é uma garantia de que a operação de negociação solicitada será necessariamente realizada com sucesso. Para obter uma descrição detalhada do resultado da execução da função, é necessário analisar os campos da estrutura 'result', apresentados anteriormente.

Após o preenchimento dos campos da estrutura da ordem de negociação ser verificado com sucesso, ela pode ser enviada ao servidor. Atenção, a execução bem-sucedida da função OrderSend() não garante que a ordem foi executada. Entendemos apenas que a ordem foi processada e aceita pelo servidor. O resultado do envio da ordem de negociação ao servidor será os campos preenchidos da estrutura MqlTradeResult, que contém a resposta do servidor de negociação à solicitação enviada pela função OrderSend().

O resultado da operação de negociação é retornado na variável do tipo MqlTradeResult, que é passada como segundo parâmetro na função OrderSend() usada para realizar operações de negociação.

O terminal registra o identificador da solicitação no campo 'request_id' quando a envia ao servidor de negociação mediante as funções OrdersSend() e OrderSendAsync(). Do servidor de negociação, o terminal recebe mensagens sobre as transações realizadas e as transmite para processamento na função OnTradeTransaction(), que contém como parâmetros:

  • descrição da própria transação na estrutura MqlTradeTransaction;
  • descrição da solicitação de negociação enviada a partir da função OrderSend() ou OrdersSendAsync(). O identificador da solicitação é enviado pelo terminal ao servidor de negociação, e a própria solicitação e seu request_id são armazenados na memória do terminal;
  • resultado da execução da solicitação de negociação na forma da estrutura MqlTradeResult, em que o campo request_id contém o identificador dessa mesma solicitação.

A função OnTradeTransaction() recebe três parâmetros de entrada, mas os dois últimos só fazem sentido serem analisados para transações do tipo TRADE_TRANSACTION_REQUEST. Em todos os outros casos, os dados da solicitação de negociação e o resultado de sua execução não são preenchidos. Um exemplo de análise dos parâmetros é apresentado na seção Estrutura da operação de negociação.

A configuração do identificador 'request_id' efetuada pelo terminal para a solicitação de negociação ao enviá-la ao servidor é primariamente destinada a trabalhar com a função assíncrona OrderSendAsync(). Esse identificador permite associar a ação realizada (chamada das funções OrderSend ou OrderSendAsync) com o resultado dessa ação, transmitido em OnTradeTransaction().

Dessa forma, podemos controlar o recebimento da ordem (ordem de negociação) pelo servidor, sua colocação no sistema de negociação e execução na função OnTradeTransaction(). Hoje escreveremos funções para registrar no log os campos de todas as estruturas envolvidas na solicitação de negociação, começando pelo preenchimento da estrutura da ordem de negociação e terminando com a análise dos eventos em OnTradeTransaction(). O resultado do artigo será um pequeno Expert Advisor informante, que imprime no log todos os eventos de negociação.

O procedimento para trabalhar com ordens de negociação é resumidamente o seguinte:

  1. Preenchemos a estrutura da solicitação de negociação,
  2. Verificamos se o preenchimento da estrutura está correto e se é possível fazer tal ordem,
  3. Enviamos a ordem de negociação para o servidor,
  4. Se necessário, analisamos a estrutura do resultado do envio da ordem ao servidor,
  5. Recebemos eventos e, se necessário, analisamos as mensagens no log do manipulador OnTradeTransaction().
Mas antes de começarmos a escrever funções para enviar a descrição dos campos da estrutura para o log, vamos escrever funções auxiliares que retornem descrições de alguns tipos de ordem representados como constantes de enumeração, bem como outras funções úteis e necessárias.

Funções auxiliares

O Expert Advisor, que será apresentado no final do artigo, será controlado pelo pressionamento de combinações de teclas. Para determinar os pressionamentos das teclas Ctrl e Shift, escreveremos duas funções:

//+------------------------------------------------------------------+
//| 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);
  }

Agora, ao detectar o pressionamento de uma tecla, poderemos verificar o flag de manter pressionada a tecla Ctrl ou Shift, ou mantê-las pressionadas simultaneamente para responder à combinação de teclas de controle e alfanuméricas.


Ao retornar a descrição dos campos das estruturas, será necessário imprimir os códigos de retorno do servidor de negociação. Faremos uma função que retorna a descrição do código de resposta do servidor:

//+------------------------------------------------------------------+
//| 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+")";
     }
  }

Na função, é passado o código de resposta do servidor e o flag para retorno da descrição expandida. A função retorna o código numérico com a descrição da constante:

10034 LIMIT_VOLUME

ou com uma descrição detalhada do código de resposta do servidor:Função que retorna a descrição do tipo de ordem:

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


Função que retorna uma descrição do tipo de ordem:

//+------------------------------------------------------------------+
//| 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)
   */
  }

Ao enviar uma solicitação de negociação usando a função OrderSend(), para algumas operações, é necessário especificar o tipo de ordem. O tipo de ordem é indicado no campo 'type' da estrutura MqlTradeRequest e pode assumir valores da enumeração ENUM_ORDER_TYPE:

Identificador
Descrição
ORDER_TYPE_BUY
Pedido de compra a mercado
ORDER_TYPE_SELL
Pedido de venda a mercado
ORDER_TYPE_BUY_LIMIT
Ordem pendente Buy Limit
ORDER_TYPE_SELL_LIMIT
Ordem pendente Sell Limit
ORDER_TYPE_BUY_STOP
Ordem pendente Buy Stop
ORDER_TYPE_SELL_STOP
Ordem pendente Sell Stop
ORDER_TYPE_BUY_STOP_LIMIT
Se o preço da ordem for atingido, uma ordem pendente Buy Limit será colocada ao preço StopLimit
ORDER_TYPE_SELL_STOP_LIMIT
Se o preço da ordem for atingido, uma ordem pendente Sell Limit será colocada ao preço StopLimit
ORDER_TYPE_CLOSE_BY
Ordem de fechamento da posição oposta


Função que retorna a descrição do tipo de ordem segundo sua execução:

//+------------------------------------------------------------------+
//| 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)
   */
  }

Ao enviar uma solicitação de negociação com a função OrderSend(), a política de execução exigida por volume pode ser definida no campo type_filling na estrutura MqlTradeRequest; são permitidos valores provenientes da enumeração ENUM_ORDER_TYPE_FILLING. Para obter o valor dessa propriedade em uma ordem ativa/executada específica, use a função OrderGetInteger() ou HistoryOrderGetInteger() com o modificador ORDER_TYPE_FILLING.

Antes de enviar uma ordem com execução no momento atual, para definir corretamente o valor de ORDER_TYPE_FILLING (tipo de execução por volume), para cada instrumento financeiro, é possível obter o valor da propriedade SYMBOL_FILLING_MODE usando a função SymbolInfoInteger(), que indica os tipos de preenchimento por volume permitidos para esse símbolo em forma de combinação de flags. Note-se que o tipo de preenchimento ORDER_FILLING_RETURN é sempre permitido, exceto no modo "Execução a Mercado" (SYMBOL_TRADE_EXECUTION_MARKET).


Função que retorna a descrição do tipo de transação:

//+------------------------------------------------------------------+
//| 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)
   */
  }

A função retorna as descrições dos tipos de transações executadas na conta.


Função que retorna a descrição do estado da ordem:

//+------------------------------------------------------------------+
//| 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)
   */
  }

Cada ordem tem um status que descreve seu estado. Para obter informações, use a função OrderGetInteger() ou HistoryOrderGetInteger() com o modificador ORDER_STATE. Os valores permitidos estão armazenados na enumeração ENUM_ORDER_STATE. Ao enviar uma solicitação de negociação ao servidor, o status da ordem muda gradualmente. Primeiro, é verificado pelo servidor, depois colocado no sistema de negociação, e então é acionado, gerando um negócio, ou pode ser cancelado. A enumeração lista todos os possíveis estados das ordens, e eles devem ser considerados ao trabalhar com ordens de negociação.


Função que retorna a descrição do tipo de operação:

//+------------------------------------------------------------------+
//| 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)
   */
  }

Cada operação é caracterizada por um tipo, os possíveis valores estão listados em ENUM_DEAL_TYPE. Para obter informações sobre o tipo de operação, use a função HistoryDealGetInteger() com o modificador DEAL_TYPE.


Função que retorna a descrição do tipo de ordem por expiração:

//+------------------------------------------------------------------+
//| 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)
   */
  }

O prazo de validade da ordem pode ser definido no campo 'type_time' da estrutura MqlTradeRequest ao enviar uma solicitação de negociação usando a função OrderSend(). Os valores permitidos são da enumeração ENUM_ORDER_TYPE_TIME. Para obter o valor desta propriedade, use a função OrderGetInteger() ou HistoryOrderGetInteger() com o modificador ORDER_TYPE_TIME.

As transações podem ocorrer com ordens, operações e posições. Em cada categoria dessas transações, podem existir diferentes tipos, como adição, modificação e remoção. Mas às vezes é necessário saber apenas com o que a transação foi realizada, sem detalhes específicos — seja com uma ordem, operação ou posição. Para isso, faremos uma função que retorna a categoria da transação:

//+------------------------------------------------------------------+
//| 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;
     }
  }

Na função, o tipo de transação é passado e, por referência, três variáveis-flags, que são definidas ou redefinidas dependendo do que exatamente a transação envolveu.


Função que retorna a descrição do tipo de solicitação de negociação:

//+------------------------------------------------------------------+
//| 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)):
   */
  }


Agora, vamos examinar a estrutura da solicitação de negociação, o output da descrição de seus campos e criar algumas funções de negociação que ilustram o trabalho com esta estrutura.

Estrutura MqlTradeRequest para criar uma solicitação ao realizar operações de negociação

A interação entre o terminal de cliente e o servidor de negociação para a colocação de ordens é feita por meio de solicitações de negociação. A solicitação é representada por uma estrutura pré-definida especial, MqlTradeRequest, que contém todos os campos necessários para concluir operações de negociação:

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
  };

Para enviar uma ordem de negociação ao servidor, é necessário preencher os campos da estrutura de acordo com a ordem. O campo 'action' deve ser preenchido obrigatoriamente, e dependendo da ação registrada neste campo, apenas os outros campos necessários para essa ação são preenchidos. Consequentemente, campos não utilizados conterão zeros (supondo que os campos da estrutura foram zerados antes de serem preenchidos). Ao exibir a descrição dos campos da estrutura, é preciso considerar que alguns campos não são utilizados e contêm zeros. Isso deve ser refletido ao exibir qualquer campo não utilizado no log, por exemplo, em vez de usar para o valor o número de casas decimais (1.12345), usar apenas um (0.0) - isso torna mais claro que este campo simplesmente não está preenchido.

No entanto, no output final da estrutura no log, consideraremos os campos não utilizados dependendo da transação e simplesmente não os exibiremos.


Tipo de ação a ser executada

Tipo de operação de negociação. O valor pode ser um dos valores da enumeração 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)):
   */
  }


Identificador do EA (magic number)

Identificador do EA. Permite que realizar o processamento analítico de ordens de negociação. Cada Expert Advisor pode exibir seu próprio identificador exclusivo ao enviar uma solicitação de negociação.
//+------------------------------------------------------------------+
//| 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
   */
  }


Ticket da ordem

Ticket da ordem Necessário para a modificação de ordens pendentes.

//+------------------------------------------------------------------+
//| 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
   */
  }


Nome do instrumento de negociação

Nome do instrumento de negociação para o qual a ordem é colocada. Não necessário para modificação de ordens e fechamento de posições.

//+------------------------------------------------------------------+
//| 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
   */
  }


Volume da operação solicitada em lotes

Volume da operação solicitada em lotes O valor real do volume ao abrir uma operação dependerá do tipo de ordem por execução.

//+------------------------------------------------------------------+
//| 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
   */
  }


Preço

Preço ao qual a ordem deve ser executada. Para ordens de mercado em instrumentos com tipo de execução "Execução a Mercado" (SYMBOL_TRADE_EXECUTION_MARKET), que têm o tipo TRADE_ACTION_DEAL, a indicação de preço não é necessária.

//+------------------------------------------------------------------+
//| 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
   */
  }


Nível da ordem StopLimit

Para ordens pendentes BuyStopLimit e SellStopLimit. É o preço ao qual a ordem Limit pendente será colocada, ao atingir o valor do preço (esta condição é obrigatória). Até esse momento, a ordem pendente não é exibida no sistema de negociação.

//+------------------------------------------------------------------+
//| 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
   */
  }


Nível da ordem Stop Loss

Preço ao qual a ordem Stop Loss será acionada quando o preço se mover em uma direção desfavorável.

//+------------------------------------------------------------------+
//| 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
   */
  }


Nível da ordem Take Profit

Preço ao qual a ordem Take Profit será acionada quando o preço se mover em uma direção favorável.

//+------------------------------------------------------------------+
//| 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
   */
  }


Desvio do preço solicitado

Desvio máximo aceitável do preço solicitado, estabelecido em pontos.

//+------------------------------------------------------------------+
//| 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
   */
  }


Tipo de ordem

Tipo de ordem. O valor pode ser um dos valores da enumeração 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)
   */
  }


Tipo de ordem por execução

Tipo de ordem por execução. O valor pode ser um dos valores do 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)
   */
  }


Tipo de ordem por tempo de execução

Tipo de ordem por expiração. O valor pode ser um dos valores do 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)
   */
  }


Tempo de expiração da ordem

Prazo de expiração da ordem pendente (para ordens do tipo 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
   */
  }


Comentário da ordem

//+------------------------------------------------------------------+
//| 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
   */
  }


Ticket da posição

Ticket da posição. Deve ser preenchido ao modificar e fechar uma posição para sua identificação inequívoca. Geralmente corresponde ao ticket da ordem que provocou a abertura da posição.

//+------------------------------------------------------------------+
//| 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
   */
  }


Ticket da posição oposta

Ticket da posição oposta. Utilizado ao fechar uma posição contrária, isto é, aberta com mesmo instrumento, mas em direção oposta.

//+------------------------------------------------------------------+
//| 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
   */
  }


Exemplos de uso

Para diferentes tipos de ordens de negociação, os campos da estrutura são preenchidos individualmente de acordo com a ordem. Vamos considerar exemplos práticos: criaremos uma função que registra no log as descrições dos campos da estrutura, dependendo da ação executada, e funções de negociação para abrir/fechar posições e para estabelecer/remover ordens pendentes.

Função que registra no log a descrição da solicitação de negociação:

//+------------------------------------------------------------------+
//| 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 para abrir uma posição de compra:

//+------------------------------------------------------------------+
//| 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 para abrir uma posição de venda:

//+------------------------------------------------------------------+
//| 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 para fechar uma posição especificada:

//+------------------------------------------------------------------+
//| 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 para fechar todas as posições:

//+------------------------------------------------------------------+
//| 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 para colocar uma ordem pendente:

//+------------------------------------------------------------------+
//| 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;
  }


Com base na função apresentada acima, é possível criar funções que definam tipos específicos de ordens pendentes:

SetBuyStop para definir uma ordem BuyStop pendente:

//+------------------------------------------------------------------+
//| 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 para definir uma ordem BuyLimit pendente:

//+------------------------------------------------------------------+
//| 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 para definir uma ordem BuyStopLimit pendente:

//+------------------------------------------------------------------+
//| 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 para definir uma ordem pendente SellStop:

//+------------------------------------------------------------------+
//| 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 para definir uma ordem pendente SellLimit:

//+------------------------------------------------------------------+
//| 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 para definir uma ordem pendente 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 para excluir a ordem pendente especificada:

//+------------------------------------------------------------------+
//| 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 para excluir todas as ordens pendentes:

//+------------------------------------------------------------------+
//| 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;
  }

Estas funções de negociação são exemplos simples e não incluem tratamento e ajuste de erros com base no código de erro e no código de resposta do servidor. Elas podem ser expandidas para incluir esses aspectos, mas isso vai além do escopo deste artigo.

Após preencher a estrutura da ordem de negociação, é possível verificar o preenchimento. Isso pode ser feito usando a função OrderCheck(), que verifica se há fundos suficientes para a operação de negociação desejada.

Se houver falta de fundos ou parâmetros preenchidos incorretamente, a função retorna false. No caso de uma verificação básica bem-sucedida das estruturas (verificação de ponteiros), retorna-se true - isso não é uma garantia de que a operação de negociação solicitada será necessariamente realizada com sucesso. Para obter uma descrição detalhada do resultado da execução da função, é necessário analisar os campos da estrutura 'result'.

Os resultados da verificação são colocados nos campos da estrutura MqlTradeCheckResult. Para registrar as descrições dos campos desta estrutura, escreveremos funções correspondentes.


Estrutura MqlTradeCheckResult para verificar a solicitação preparada antes de enviá-la

Antes de enviar ao servidor de negociação uma solicitação para uma operação de negociação, recomenda-se realizar sua verificação. A verificação é feita pela função OrderCheck(), que recebe a própria solicitação a ser verificada e uma variável do tipo da estrutura MqlTradeCheckResult. Nesta variável, o resultado da verificação será registrado.

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)
  };


Código de resposta

Código de retornoTodos os pedidos para realizar operações de negociação são enviados na forma da estrutura de solicitação de negociação MqlTradeRequest usando a função OrderSend(). O resultado da execução dessa função é colocado na estrutura MqlTradeResult, cujo campo 'retcode' contém o código de retorno do servidor de negociação. Da mesma forma, após a verificação da ordem de negociação, o código de resposta pode ser lido no campo 'retcode' da estrutura MqlTradeCheckResult.

//+------------------------------------------------------------------+
//| 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)
   */
  }


Saldo após a realização da operação

Valor do saldo que será após a execução da operação de negociação.

//+----------------------------------------------------------------------+
//| 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
   */
  }


Patrimônio líquido após a realização da operação

Valor do patrimônio líquido que será após a execução da operação de negociação.

//+--------------------------------------------------------------------+
//| 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
   */
  }


Lucro flutuante

Valor do lucro flutuante que será após a execução da operação de negociação.

//+---------------------------------------------------------------------------+
//|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
   */
  }


Requisitos de margem

Tamanho da margem necessária para a operação de negociação desejada.

//+------------------------------------------------------------------+
//| 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
   */
  }


Margem livre

Tamanho dos fundos livres que restarão após a execução da operação de negociação desejada.

//+------------------------------------------------------------------+
//| 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
   */
  }


Nível de margem

Nível de margem que será estabelecido após a execução da operação de negociação desejada.

//+-----------------------------------------------------------------------+
//| 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 %
   */
  }


Comentário sobre o código de resposta

Comentário sobre o código de resposta, descrição do erro.

//+------------------------------------------------------------------+
//| 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
   */
  }


Exemplos de uso

Função que registra no log todos os campos da estrutura 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
   */
  }

Após a verificação da ordem de negociação preenchido e, em caso de erro, pode-se imprimir no log a estrutura MqlTradeCheckResult preenchida para análise do erro ocorrido.


Estrutura MqlTradeResult com a resposta do servidor à solicitação enviada pela função OrderSend()

Em resposta à solicitação de negociação para colocação de uma ordem no sistema de negociação, o servidor de negociação retorna dados contendo informações sobre o resultado do processamento da solicitação de negociação na forma da estrutura especial 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
  };

O resultado da operação de negociação é retornado em uma variável do tipo MqlTradeResult, que é passada como segundo parâmetro na função OrderSend() para realizar operações de negociação.

Para imprimir a descrição dos campos da estrutura, escreveremos funções:

Código do resultado da operação

Código do resultado da operação
//+------------------------------------------------------------------+
//| 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)
   */
  }


Ticket da operação

Ticket da transação, se confirmada. Informado durante uma operação de negociação 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
   */
  }


Ticket da ordem

Ticket da ordem, se colocada. Informado na operação de negociação 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
   */
  }


Volume da operação

Volume da transação confirmado pela corretora. Depende do tipo de ordem de execução.
//+------------------------------------------------------------------+
//| 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
   */
  }


Preço da operação

Preço da operação, confirmado pela corretora. Depende do campo 'deviation' na solicitação de negociação e/ou do tipo da operação de negociação.

//+------------------------------------------------------------------+
//| 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
   */
  }


Preço de mercado atual Bid

Atual preço de mercado da oferta (preços de re-cotação).
//+------------------------------------------------------------------+
//| 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
   */
  }


Preço de mercado atual Ask

Atual preço de mercado da demanda (preços de re-cotação).
//+------------------------------------------------------------------+
//| 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
   */
  }

Ao definir uma ordem pendente, os preços Bid e Ask na estrutura permanecem não preenchidos. Se a ordem não foi aceita devido a uma re-cotação, nos campos Bid e Ask, é possível ver os preços existentes no momento em que a colocação da ordem é rejeitada.


Comentário da corretora sobre a operação

Comentário da corretora sobre a operação (por padrão, ele é preenchido pela decodificação do código de retorno do servidor de negociação).
//+------------------------------------------------------------------+
//| 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
   */
  }


Identificador da solicitação

Identificador da solicitação definido pelo terminal durante o envio ao servidor de negociação.
//+------------------------------------------------------------------+
//| 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
   */
  }

A configuração do identificador 'request_id' feita pelo terminal para a solicitação de negociação ao enviá-la ao servidor é, principalmente, destinada para uso com a função assíncrona OrderSendAsync(). Este identificador permite associar a ação realizada (chamada das funções OrderSend ou OrderSendAsync) com o resultado dessa ação, transmitido no manipulador OnTradeTransaction().


Código de resposta do sistema de negociação externo

Código de erro retornado pelo sistema de negociação externo. A colocação e os tipos desses erros dependem da corretora e do sistema de negociação externo para o qual as operações de negociação são enviadas.
//+--------------------------------------------------------------------+
//| 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
   */
  }


Exemplos de uso

Função que registra no log todos os campos da estrutura do resultado da solicitação de negociação:

//+------------------------------------------------------------------+
//| 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
   */
  }


Estrutura MqlTradeTransaction com descrição da operação de negociação

Como resultado de certas ações na conta de negociação, o seu estado muda. Essas ações incluem:

  • Envio da solicitação de negociação com qualquer aplicativo MQL5 no terminal do cliente usando as funções OrderSend e OrderSendAsync e sua execução subsequente;
  • Envio da solicitação de negociação por meio da GUI do terminal e sua execução subsequente;
  • Acionamento de ordens pendentes e ordens de stop no servidor;
  • Execução de operações no lado do servidor de negociação.

Como resultado dessas ações, na conta acontece:

  • processamento da solicitação de negociação;
  • alteração de ordens abertas;
  • alteração do histórico de ordens;
  • alteração do histórico de operações;
  • alteração de posições.

Por exemplo, ao enviar uma ordem a mercado para compra, ela é processada, um pedido de compra correspondente é criado para a conta, a ordem é executado, removido da lista de abertos, adicionado ao histórico de ordens, a transação correspondente é adicionada ao histórico e uma nova posição é criada. Todas essas ações são transações.

Para obter transações em relação à conta, no MQL5 é fornecido o manipulador especial OnTradeTransaction(). No primeiro parâmetro deste manipulador, é passada a estrutura MqlTradeTransaction, que descreve as transações.

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
  };


Para retornar descrições de todos os campos da estrutura, escreveremos funções.

Ticket da operação

//+------------------------------------------------------------------+
//| 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
   */
  }


Ticket da ordem

//+------------------------------------------------------------------+
//| 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
   */
  }


Nome do instrumento de negociação

Nome do instrumento de negociação para o qual a operação foi feita.

//+------------------------------------------------------------------+
//| 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
   */
  }


Tipo de operação de negociação

Tipo de operação de negociação. O valor pode ser um dos valores da enumeração 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)
   */
  }


Tipo de ordem

Tipo da ordem de negociação. O valor pode ser um dos valores da enumeração ENUM_ORDER_TYPE.

//+------------------------------------------------------------------+
//| 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)
   */
  }

A função determina a origem da transação e, se a transação foi realizada com uma ordem, retorna seu tipo, caso contrário, retorna '0'.


Estado da ordem

Estado da ordem de negociação. O valor pode ser um dos valores da enumeração 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)
   */
  }

A função determina a origem da transação e, se a transação foi realizada com uma ordem, retorna seu estado, caso contrário, retorna '0'.


Tipo de operação

Tipo da operação. O valor pode ser um dos valores da enumeração 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
   */
  }

Na função, é determinada a origem da transação e, se a transação foi realizada com uma operação (deal), então seu tipo é retornado, caso contrário, retorna '0'.


Tipo de ordem por tempo de execução

Tipo de ordem segundo vencimento. O valor pode ser um dos valores do 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)
   */
  }

Na função, é determinada a origem da transação e, se a transação foi realizada com uma ordem, então seu tipo por tempo de expiração é retornado, caso contrário, retorna '0'.


Tempo de expiração da ordem

Prazo de expiração da ordem pendente (para ordens do tipo ORDER_TIME_SPECIFIED e 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
   */
  }

Se o tempo de expiração no campo da estrutura estiver registrado como zero, então '0' é exibido, caso contrário, o tempo de expiração no formato de data. Se não verificar o valor do campo para zero, o valor zero será exibido como a data 01.01.1970 00:00:00, o que não é esteticamente agradável para um tempo de expiração de ordem ausente.


Preço

Preço. Dependendo do tipo de transação, pode ser o preço da ordem, operação ou posição.

//+------------------------------------------------------------------+
//| 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
   */
  }


Preço de acionamento da ordem stop-limit

Preço de acionamento da ordem stop-limitPreço de acionamento (stop price) da ordem stop-limit (ORDER_TYPE_BUY_STOP_LIMIT e 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
   */
  }

Se o preço da ordem stop-limit não for definido, '0.0' será exibido, caso contrário, o preço da ordem.


Nível de stop loss

Preço Stop Loss. Dependendo do tipo de transação, pode se referir à ordem, operação ou posição.

//+------------------------------------------------------------------+
//| 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
   */
  }

Se o preço Stop Loss não for definido, '0.0' será exibido, caso contrário, o preço Stop Loss.


Nível de Take Profit

Preço Take Profit. Dependendo do tipo de transação, pode se referir à ordem, operação ou posição.

//+------------------------------------------------------------------+
//| 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
   */
  }

Se o preço Take Profit não for definido, '0.0' será exibido, caso contrário, o preço Take Profit.


Volume em lotes

Volume em lotes. Dependendo do tipo de transação, pode indicar o volume atual da ordem, o volume da operação ou o volume da posição.

//+------------------------------------------------------------------+
//| 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
   */
  }


Ticket da posição

Ticket da posição que foi afetada pela transação.

//+------------------------------------------------------------------+
//| 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
   */
  }


Ticket da posição oposta

Ticket da posição oposta. Usado ao fechar uma posição contrária - aberta pelo mesmo instrumento, mas em direção oposta.

//+------------------------------------------------------------------+
//| 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
   */
  }


Exemplos de uso

Usando as funções apresentadas acima, podemos registrar todos os campos da estrutura 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
   */
  }

A função apresentada registra no log todos os campos da estrutura MqlTradeTransaction. No entanto, se nos referirmos ao manual, veremos que para diferentes eventos de negociação, os campos da estrutura são preenchidos de maneiras diferentes:

O parâmetro determinante para a análise de uma transação recebida é o seu tipo, que é passado no campo 'type'. Por exemplo, se a transação for do tipo TRADE_TRANSACTION_REQUEST (resultado do processamento da solicitação de negociação pelo servidor), a estrutura terá apenas um campo preenchido, 'type', e os outros campos não precisam ser analisados. Neste caso, pode-se realizar a análise de dois parâmetros adicionais, 'request' e 'result', que são passados para o manipulador OnTradeTransaction(), como mostrado no exemplo abaixo.

Conhecendo o tipo da operação de negociação, pode-se tomar uma decisão sobre a análise do estado atual das ordens, posições e operações na conta de negociação. É importante ter em mente que uma solicitação de negociação enviada do terminal para o servidor pode gerar várias transações, e a ordem de recebimento dessas transações no terminal não é garantida.

A estrutura MqlTradeTransaction é preenchida de maneira diferente dependendo do tipo da transação (ENUM_TRADE_TRANSACTION_TYPE):

TRADE_TRANSACTION_ORDER_* e TRADE_TRANSACTION_HISTORY_*

Para transações relacionadas ao processamento de ordens abertas (TRADE_TRANSACTION_ORDER_ADD, TRADE_TRANSACTION_ORDER_UPDATE e TRADE_TRANSACTION_ORDER_DELETE) e histórico de ordens (TRADE_TRANSACTION_HISTORY_ADD, TRADE_TRANSACTION_HISTORY_UPDATE, TRADE_TRANSACTION_HISTORY_DELETE), os seguintes campos na estrutura MqlTradeTransaction são preenchidos:

  • order — ticket da ordem;
  • symbol — nome do instrumento financeiro na ordem;
  • type — tipo de transação;
  • order_type — tipo de ordem;
  • order_state — estado atual da ordem;
  • time_type — tipo de expiração da ordem;
  • time_expiration — tempo de expiração da ordem (para ordens com os tipos de expiração ORDER_TIME_SPECIFIED e ORDER_TIME_SPECIFIED_DAY);
  • price — preço na ordem especificado pelo cliente;
  • price_trigger — preço de parada para acionar uma ordem de Stop Loss (somente para ORDER_TYPE_BUY_STOP_LIMIT e ORDER_TYPE_SELL_STOP_LIMIT);
  • price_sl — preço Stop Loss da ordem (preenchido se especificado na ordem);
  • price_tp — preço Take Profit da ordem (preenchido, se especificado na ordem);
  • volume — volume atual da ordem (não executado). O volume inicial da ordem pode ser encontrado no histórico de ordens usando as funções HistoryOrders*.
  • position — ticket da posição aberta, alterada ou fechada como resultado da execução da ordem. É preenchido somente para ordens a mercado. Não é preenchido para TRADE_TRANSACTION_ORDER_ADD.
  • position_by — ticket da posição oposta. Preenchido somente para ordens de fechamento de uma posição oposta (close by).

TRADE_TRANSACTION_DEAL_*

TRADE_TRANSACTION_DEAL_*Para transações relacionadas ao processamento de operações (TRADE_TRANSACTION_DEAL_ADD, TRADE_TRANSACTION_DEAL_UPDATE e TRADE_TRANSACTION_DEAL_DELETE), os seguintes campos na estrutura MqlTradeTransaction são preenchidos:

  • deal — ticket da operação;
  • order — ticket da ordem com a qual a transação foi executada;
  • symbol — nome do instrumento financeiro na transação;
  • type — tipo de transação;
  • deal_type — tipo de operação;
  • price — preço da transação;
  • price_sl — preço Stop Loss (deve ser preenchido se estiver especificado na ordem com a qual a transação foi feita);
  • price_tp — preço Take Profit (deve ser preenchido se estiver especificado na ordem com a qual a transação foi feita);
  • volume — volume da operação em lotes.
  • position — ticket da posição aberta, alterada ou fechada como resultado da execução da transação.
  • position_by — ticket da posição oposta. Deve ser preenchido apenas para operações de fechamento de uma posição oposta (out by).

TRADE_TRANSACTION_POSITION

Para transações relacionadas a mudanças nas posições, não associadas à execução de operações (TRADE_TRANSACTION_POSITION), os seguintes campos na estrutura MqlTradeTransaction são preenchidos:

  • symbol — nome do instrumento financeiro da posição;
  • type — tipo de transação;
  • deal_type — tipo de posição (DEAL_TYPE_BUY ou DEAL_TYPE_SELL);
  • price — preço médio ponderado de abertura da posição;
  • price_sl — preço Stop Loss;
  • price_tp — preço Take Profit;
  • volume — volume da posição em lotes, se tiver sido alterado.
  • position — ticket da posição.

Mudanças na posição (adição, alteração ou liquidação) como resultado da execução de uma operação não resultam em uma transação TRADE_TRANSACTION_POSITION.

TRADE_TRANSACTION_REQUEST

Para transações que descrevem o fato de a solicitação de negociação ser processada pelo servidor e o resultado de seu processamento ser recebido (TRADE_TRANSACTION_REQUEST), apenas um campo é preenchido na estrutura MqlTradeTransaction:

  • type — tipo de transação;
Para transações desse tipo, é necessário analisar apenas um campo - 'type' (tipo de transação). Para obter mais informações, é necessário analisar o segundo e o terceiro parâmetros da função OnTradeTransaction (request e result).

Consequentemente, podemos criar uma função que leva em conta os eventos de negociação recebidos e registra no log apenas aqueles campos da estrutura MqlTradeTransaction que são necessários para cada tipo de transação:

//+------------------------------------------------------------------+
//| 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/en/docs/event_handlers/ontradetransaction.
   */
  }


Expert Advisor informante de operações de negociação

Para testar o funcionamento das funções discutidas acima, escreveremos um Expert Advisor que monitora todas as transações, respostas do servidor e registra no log as descrições das transações recebidas. Vamos configurá-lo para que seja possível colocar ordens pendentes (BuyStop, SellStop, BuyLimit e SellLimit) e abrir posições (Buy, Sell) pressionando as teclas selecionadas nas configurações. Por padrão, as seguintes teclas serão atribuídas para gerenciar a negociação:

Tipo de ordem
Combinações de teclas para abertura/definição
Combinações de teclas para fechamento/exclusão
 Buy
 B
 X
 Sell
 S
 X
 Buy Stop
 Shift+B
 Shift+X, Ctrl+Shift+X
 Buy Limit
 Ctrl+Shift+B
 Shift+X, Ctrl+Shift+X
 Sell Stop
 Shift+S
 Shift+X, Ctrl+Shift+X
 Sell Limit
 Ctrl+Shift+S
 Shift+X, Ctrl+Shift+X

As teclas podem ser atribuídas em qualquer registro nas configurações, o Expert Advisor as converterá automaticamente para maiúsculas. Três teclas podem ser definidas - para compras, vendas e para fechar posições/excluir ordens. As teclas de controle Ctrl e Shift para alterar o tipo de ordens pendentes na solicitação são atribuídas por padrão e não são alteradas. Ao pressionar a tecla 'B', uma posição de Buy será aberta, ao segurar Shift e pressionar 'B', uma ordem pendente de Buy Stop será colocada, e ao segurar simultaneamente Ctrl e Shift e pressionar 'B', uma ordem pendente de Buy Limit será colocada. O mesmo se aplica às vendas - pressionar 'S' abrirá uma posição de Sell, e segurar as teclas de controle levará à colocação de Sell Stop e Sell Limit. O fechamento de todas as posições abertas é realizado pressionando a tecla 'X', e segurar Shift ou Ctrl+Shift (não importa) e pressionar 'X' levará à exclusão de todas as ordens pendentes colocadas.

//+------------------------------------------------------------------+
//|                                      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);
  }

A colocação de ordens e abertura de posições é realizada no manipulador OnChartEvent() do Expert Advisor. No manipulador OnTradeTransaction(), a função TradeTransactionInformer() discutida acima é chamada, que registrará cada transação recebida no log. O Expert Advisor usa todas as funções discutidas no artigo em seu funcionamento, portanto, elas devem ser inseridas no arquivo do Expert Advisor para sua compilação sem erros.

Ao estabelecer uma ordem BuyLimit, tais registros sobre todas as transações processadas serão exibidos no log:

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

Quando a ordem estabelecida for posteriormente excluída, obteremos os seguintes registros no log do terminal:

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


Considerações finais

Examinamos todas as estruturas para criar, verificar e enviar um pedido de negociação ao servidor, bem como para obter uma descrição completa de todas as transações que ocorrem na conta como resultado de operações de negociação.

Todas as funções propostas podem ser usadas "como estão", ou podem ser adaptadas e modificadas de acordo com sua própria visão de aplicação e uso.

O arquivo do Expert Advisor com todas as funções discutidas no artigo está disponível como um anexo. Ele pode ser baixado e testado independentemente.

Traduzido do russo pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/ru/articles/13052

Arquivos anexados |
Estratégia de negociação RSI Deep Three Move Estratégia de negociação RSI Deep Three Move
Este artigo apresenta a estratégia de negociação RSI Deep Three Move no MetaTrader 5. O artigo é baseado em uma nova série de pesquisas que demonstram vários métodos de negociação com base no RSI, que é um indicador técnico para medir a força e o impulso de ativos financeiros, incluindo ações, moedas e commodities.
Desenvolvendo um sistema de Replay (Parte 40): Iniciando a segunda fase (I) Desenvolvendo um sistema de Replay (Parte 40): Iniciando a segunda fase (I)
Esta é a nova fase do sistema de replay / simulação. Nesta fase a conversa de fato irá ser seria. E o conteúdo irá ser tornar bastante denso. Peço que você leia com calma o artigo e sempre procure usar as referencias que possivelmente estarão sendo indicadas nos artigos. Isto para lhe ajudar a compreender melhor o que estará sendo explicado.
Desenvolvendo um agente de Aprendizado por Reforço em MQL5 com Integração RestAPI (Parte 4): Organizando Funções em Classes no MQL5 Desenvolvendo um agente de Aprendizado por Reforço em MQL5 com Integração RestAPI (Parte 4): Organizando Funções em Classes no MQL5
Este artigo examina a transição da codificação procedural para a Programação Orientada a Objetos (POO) no MQL5, com foco na integração com REST APIs. Discutimos como organizar funções de requisições HTTP (GET e POST) em classes, ressaltando vantagens como encapsulamento, modularidade e facilidade de manutenção. A refatoração de código é detalhada, mostrando a substituição de funções isoladas por métodos de classes. O artigo inclui exemplos práticos e testes.
Tudo o que você precisa saber sobre a estrutura de um programa MQL5 Tudo o que você precisa saber sobre a estrutura de um programa MQL5
Qualquer programa em qualquer linguagem de programação possui uma estrutura específica. Neste artigo, você aprenderá os componentes básicos da estrutura de um programa na linguagem MQL5, o que pode ser extremamente útil ao criar um sistema de negociação ou uma ferramenta de negociação para o MetaTrader 5.