Biblioteca para criação simples e rápida de programas para MetaTrader (Parte XXIX): ordens de negociação pendentes, classes de objetos-ordens

Artyom Trishkin | 20 março, 2020

Sumário


Ideia

Nos três artigos anteriores, testamos o conceito de gerenciamento de métodos de negociação de uma classe de negociação com a ajuda ordens pendentes.
Uma ordem pendente é, em essência, uma ordem de negociação, mas, executada com base numa determinada condição. Verificamos a condição de atraso para o envio de uma ordem de negociação nos métodos de negociação ao receber um erro do servidor, erro esse cujo processamento requer alguma espera antes de enviar a ordem ao servidor novamente. Certamente, essa não é a única condição para usar ordens pendentes. O níveis de preços para envio de ordens de negociação também podem ser uma condição. Mesmo uma combinação de condições pode se tornar numa condição: alguns valores limite das propriedades do símbolo que ao serem atingidos podem desencadear o envio de uma ordem de negociação ao servidor (ordens stop-limit são um exemplo claro de ordens de negociação para posicionar uma ordem limite quando o preço atingir o nível de uma ordem stop).

Em geral, as ordens de negociação pendentes nos permitem criar um tipo de lógica de comportamento para o envio de ordens de negociação para o servidor.

Porém, para incluir tudo isso no código do objeto-ordem pendente, precisamos aplicar-lhe o conceito geral de objetos de biblioteca, fazendo com que tais objetos se tornem facilmente extensíveis para introduzir novas propriedades neles. Agora, nesta etapa de trabalho com ordens de negociação pendentes, nós, para verificar o conceito em questão, escreveremos o código para trabalhar com elas diretamente na listagem da ordem de negociação, o que não é algo conceitualmente verdadeiro se quisermos usá-las mais para frente (no entanto, foi planejado, primeiro, verificar rapidamente tudo e, em seguida, dar a formatação correta).
Hoje, criaremos uma classe base de um objeto abstrato-ordem de negociação pendente e classes de objetos-herdeiros do objeto-ordem base. O objeto base conterá propriedades comuns para todos os objetos-ordens, enquanto os objetos-herdeiros conterão propriedades individuais inerentes aos status de cada objeto filho - faremos isso para todos os objetos da biblioteca.

Mas, para começar, como habitual, criaremos as mensagens de biblioteca necessárias para trabalhar com objetos.

No arquivo Datas.mqh, inserimos os índices das novas mensagens de biblioteca:

...

   MSG_LIB_TEXT_AND_PAUSE,                             //  and pause 
   MSG_LIB_TEXT_ALREADY_EXISTS,                       // already exists
   MSG_LIB_TEXT_CREATED,                              // Created
   MSG_LIB_TEXT_ATTEMPTS,                             // Attempts
   MSG_LIB_TEXT_WAIT,                                 // Wait
   MSG_LIB_TEXT_END,                                  // End

...

   MSG_LIB_TEXT_REQUEST,                              // Pending request #
   MSG_LIB_TEXT_REQUEST_DATAS,                        // Trading request parameters
   MSG_LIB_TEXT_PEND_REQUEST_DATAS,                   // Pending trading request parameters

...

   MSG_LIB_TEXT_PEND_REQUEST_BY_ERROR,                // Pending request generated based on the server return code
   MSG_LIB_TEXT_PEND_REQUEST_BY_REQUEST,              // Pending request created by request
   MSG_LIB_TEXT_PEND_REQUEST_WAITING_ONSET,           // Wait for the first trading attempt
   
   MSG_LIB_TEXT_PEND_REQUEST_STATUS,                 // Pending request status
   MSG_LIB_TEXT_PEND_REQUEST_STATUS_OPEN,             // Pending request to open a position
   MSG_LIB_TEXT_PEND_REQUEST_STATUS_CLOSE,            // Pending request to close a position
   MSG_LIB_TEXT_PEND_REQUEST_STATUS_SLTP,             // Pending request to modify position stop orders
   MSG_LIB_TEXT_PEND_REQUEST_STATUS_PLACE,            // Pending request to place a pending order
   MSG_LIB_TEXT_PEND_REQUEST_STATUS_REMOVE,           // Pending request to delete a pending order
   MSG_LIB_TEXT_PEND_REQUEST_STATUS_MODIFY,           // Pending request to modify pending order parameters
  };

and the messages corresponding to the new indices:

   {" и паузой "," and pause "},
   {" уже существует"," already exists"},
   {"Создан","Created"},
   {"Попыток","Attempts"},
   {"Ожидание","Wait"},
   {"Окончание","End"},

...

   {"Отложенный запрос #","Pending request #"},
   {"Параметры торгового запроса","Trade request parameters"},
   {"Параметры отложенного торгового запроса","Pending trade request parameters"},

...

   {"Отложенный запрос, созданный по коду возврата сервера","Pending request created as a result of server code"},
   {"Отложенный запрос, созданный по запросу","Pending request created by request"},
   {"Ожидание наступления времени первой торговой попытки","Waiting for onset time of the first trading attempt"},
   
   {"Статус отложенного запроса","Pending request status"},
   {"Отложенный запрос на открытие позиции","Pending request to open position"},
   {"Отложенный запрос на закрытие позиции","Pending request to close position"},
   {"Отложенный запрос на модификацию стоп-приказов позиции","Pending request to modify position stop orders"},
   {"Отложенный запрос на установку отложенного ордера","Pending request to place pending order"},
   {"Отложенный запрос на удаление отложенного ордера","Pending request to remove pending order"},
   {"Отложенный запрос на модификацию параметров отложенного ордера","Pending request to modify pending order parameters"},
  };

Como já mencionado acima, o objeto base de uma ordem de negociação pendente é um tipo de ordem abstrata geral que contém as propriedades inerentes a todas as ordens de negociação, enquanto a especificação das propriedades é atribuída aos objeto-herdeiros do objeto base.
Assim, teremos um objeto-ordem base e seis objetos-herdeiros que especificam as propriedades da ordem pendente de acordo com o tipo de operação de negociação:

Objeto base de uma ordem de negociação pendente abstrata

Como para todos os objetos de biblioteca anteriores, criaremos enumerações das propriedades do objeto da ordem de negociação pendente.

No arquivo Defines.mqh inserimos enumerações de status, bem como propriedades de objeto inteiras, reais e de string:

//+------------------------------------------------------------------+
//| Data for working with pending trading requests                   |
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Pending request status                                           |
//+------------------------------------------------------------------+
enum ENUM_PEND_REQ_STATUS
  {
   PEND_REQ_STATUS_OPEN,                                    // Pending request to open a position
   PEND_REQ_STATUS_CLOSE,                                   // Pending request to close a position
   PEND_REQ_STATUS_SLTP,                                    // Pending request to modify open position stop orders
   PEND_REQ_STATUS_PLACE,                                   // Pending request to place a pending order
   PEND_REQ_STATUS_REMOVE,                                  // Pending request to delete a pending order
   PEND_REQ_STATUS_MODIFY                                   // Pending request to modify a placed pending order
  };
//+------------------------------------------------------------------+
//| Pending request type                                             |
//+------------------------------------------------------------------+
enum ENUM_PEND_REQ_TYPE
  {
   PEND_REQ_TYPE_ERROR=PENDING_REQUEST_ID_TYPE_ERR,         // Pending request created based on the return code or error
   PEND_REQ_TYPE_REQUEST=PENDING_REQUEST_ID_TYPE_REQ,       // Pending request created by request
  };
//+------------------------------------------------------------------+
//| Integer properties of a pending trading request                  |
//+------------------------------------------------------------------+
enum ENUM_PEND_REQ_PROP_INTEGER
  {
   PEND_REQ_PROP_STATUS = 0,                                // Trading request status (from the ENUM_PEND_REQ_STATUS enumeration)
   PEND_REQ_PROP_TYPE,                                      // Trading request type (from the ENUM_PEND_REQ_TYPE enumeration)
   PEND_REQ_PROP_ID,                                        // Trading request ID
   PEND_REQ_PROP_RETCODE,                                   // Result a request is based on
   PEND_REQ_PROP_TIME_CREATE,                               // Request creation time
   PEND_REQ_PROP_TIME_ACTIVATE,                             // Next attempt activation time
   PEND_REQ_PROP_WAITING,                                   // Waiting time between requests
   PEND_REQ_PROP_CURENT,                                    // Current attempt index
   PEND_REQ_PROP_TOTAL,                                     // Number of attempts
   //--- MqlTradeRequest
   PEND_REQ_PROP_MQL_REQ_ACTION,                            // Type of a performed action in the request structure
   PEND_REQ_PROP_MQL_REQ_TYPE,                              // Order type in the request structure
   PEND_REQ_PROP_MQL_REQ_MAGIC,                             // EA stamp (magic number ID) in the request structure
   PEND_REQ_PROP_MQL_REQ_ORDER,                             // Order ticket in the request structure
   PEND_REQ_PROP_MQL_REQ_POSITION,                          // Position ticket in the request structure
   PEND_REQ_PROP_MQL_REQ_POSITION_BY,                       // Opposite position ticket in the request structure
   PEND_REQ_PROP_MQL_REQ_DEVIATION,                         // Maximum acceptable deviation from a requested price in the request structure
   PEND_REQ_PROP_MQL_REQ_EXPIRATION,                        // Order expiration time (for ORDER_TIME_SPECIFIED type orders) in the request structure
   PEND_REQ_PROP_MQL_REQ_TYPE_FILLING,                      // Order filling type in the request structure
   PEND_REQ_PROP_MQL_REQ_TYPE_TIME,                         // Order lifetime type in the request structure
  }; 
#define PEND_REQ_PROP_INTEGER_TOTAL (19)                    // Total number of integer event properties
#define PEND_REQ_PROP_INTEGER_SKIP  (0)                     // Number of request properties not used in sorting
//+------------------------------------------------------------------+
//| Real properties of a pending trading request                     |
//+------------------------------------------------------------------+
enum ENUM_PEND_REQ_PROP_DOUBLE
  {
   PEND_REQ_PROP_PRICE_CREATE = PEND_REQ_PROP_INTEGER_TOTAL,// Price at the moment of a request generation
   //--- MqlTradeRequest
   PEND_REQ_PROP_MQL_REQ_VOLUME,                            // Requested volume of a deal in lots in the request structure
   PEND_REQ_PROP_MQL_REQ_PRICE,                             // Price in the request structure
   PEND_REQ_PROP_MQL_REQ_STOPLIMIT,                         // StopLimit level in the request structure
   PEND_REQ_PROP_MQL_REQ_SL,                                // Stop Loss level in the request structure
   PEND_REQ_PROP_MQL_REQ_TP,                                // Take Profit level in the request structure
  };
#define PEND_REQ_PROP_DOUBLE_TOTAL  (6)                     // Total number of event's real properties
#define PEND_REQ_PROP_DOUBLE_SKIP   (0)                     // Number of order properties not used in sorting
//+------------------------------------------------------------------+
//| String properties of a pending trading request                   |
//+------------------------------------------------------------------+
enum ENUM_PEND_REQ_PROP_STRING
  {
   //--- MqlTradeRequest
   PEND_REQ_PROP_MQL_REQ_SYMBOL = (PEND_REQ_PROP_INTEGER_TOTAL+PEND_REQ_PROP_DOUBLE_TOTAL),  // Trading instrument name in the request structure
   PEND_REQ_PROP_MQL_REQ_COMMENT                            // Order comment in the request structure
  };
#define PEND_REQ_PROP_STRING_TOTAL  (2)                     // Total number of event's string properties
//+------------------------------------------------------------------+

Para calcular a indexação de propriedades nas matrizes de propriedades do objeto, são usadas substituições de macro indicando a quantidade de cada tipo de propriedade.
Nós já estudamos isso no primeiro artigo que descreve a criação da biblioteca.

Como pode ser visto na lista, as propriedades do objeto são aquelas que pertencem aos parâmetros de criação da ordem pendente, bem como aquelas especificadas na estrutura da ordem de negociação MqlTradeRequest, na qual são registrados todos os parâmetros da solicitação enviada ao servidor.
Como queremos classificar e procurar objetos na lista de acordo com qualquer um de seus parâmetros (como todos os objetos anteriores da biblioteca), copiamos todo o conteúdo da estrutura da ordem de negociação nas propriedades correspondentes do objeto, que repetem a finalidade dos campos da estrutura, nesse caso, podemos pesquisar e classificar solicitações pendentes na lista para qualquer propriedade.

Para pesquisar e classificar objetos-ordens pendentes, listamos todos os critérios possíveis para classificar tais objetos:

//+------------------------------------------------------------------+
//| Possible pending request sorting criteria                        |
//+------------------------------------------------------------------+
#define FIRST_PREQ_DBL_PROP         (PEND_REQ_PROP_INTEGER_TOTAL-PEND_REQ_PROP_INTEGER_SKIP)
#define FIRST_PREQ_STR_PROP         (PEND_REQ_PROP_INTEGER_TOTAL-PEND_REQ_PROP_INTEGER_SKIP+PEND_REQ_PROP_DOUBLE_TOTAL-PEND_REQ_PROP_DOUBLE_SKIP)
enum ENUM_SORT_PEND_REQ_MODE
  {
//--- Sort by integer properties
   SORT_BY_PEND_REQ_STATUS = 0,                             // Sort by a trading request status (from the ENUM_PEND_REQ_STATUS enumeration)
   SORT_BY_PEND_REQ_TYPE,                                   // Sort by a trading request type (from the ENUM_PEND_REQ_TYPE enumeration)
   SORT_BY_PEND_REQ_ID,                                     // Sort by a trading request ID
   SORT_BY_PEND_REQ_RETCODE,                                // Sort by a result a request is based on
   SORT_BY_PEND_REQ_TIME_CREATE,                            // Sort by a request generation time
   SORT_BY_PEND_REQ_TIME_ACTIVATE,                          // Sort by next attempt activation time
   SORT_BY_PEND_REQ_WAITING,                                // Sort by a waiting time between requests
   SORT_BY_PEND_REQ_CURENT,                                 // Sort by the current attempt index
   SORT_BY_PEND_REQ_TOTAL,                                  // Sort by a number of attempts
   //--- MqlTradeRequest
   SORT_BY_PEND_REQ_MQL_REQ_ACTION,                         // Sort by a type of a performed action in the request structure
   SORT_BY_PEND_REQ_MQL_REQ_TYPE,                           // Sort by an order type in the request structure
   SORT_BY_PEND_REQ_MQL_REQ_MAGIC,                          // Sort by an EA stamp (magic number ID) in the request structure
   SORT_BY_PEND_REQ_MQL_REQ_ORDER,                          // Sort by an order ticket in the request structure
   SORT_BY_PEND_REQ_MQL_REQ_POSITION,                       // Sort by a position ticket in the request structure
   SORT_BY_PEND_REQ_MQL_REQ_POSITION_BY,                    // Sort by an opposite position ticket in the request structure
   SORT_BY_PEND_REQ_MQL_REQ_DEVIATION,                      // Sort by a maximum acceptable deviation from a requested price in the request structure
   SORT_BY_PEND_REQ_MQL_REQ_EXPIRATION,                     // Sort by an order expiration time (for ORDER_TIME_SPECIFIED type orders) in the request structure
   SORT_BY_PEND_REQ_MQL_REQ_TYPE_FILLING,                   // Sort by an order filling type in the request structure
   SORT_BY_PEND_REQ_MQL_REQ_TYPE_TIME,                      // Sort by order lifetime type in the request structure
//--- Sort by real properties
   SORT_BY_PEND_REQ_PRICE_CREATE = FIRST_PREQ_DBL_PROP,     // Sort by a price at the moment of a request generation
   //--- MqlTradeRequest
   SORT_BY_PEND_REQ_MQL_REQ_VOLUME,                         // Sort by a requested volume of a deal in lots in the request structure
   SORT_BY_PEND_REQ_MQL_REQ_PRICE,                          // Sort by a price in the request structure
   SORT_BY_PEND_REQ_MQL_REQ_STOPLIMIT,                      // Sort by StopLimit order level in the request structure
   SORT_BY_PEND_REQ_MQL_REQ_SL,                             // Sort by StopLoss order level in the request structure
   SORT_BY_PEND_REQ_MQL_REQ_TP,                             // Sort by TakeProfit order level in the request structure
//--- Sort by string properties
   //--- MqlTradeRequest
   SORT_BY_PEND_REQ_MQL_SYMBOL = FIRST_PREQ_STR_PROP,       // Sort by a trading instrument name in the request structure
   SORT_BY_PEND_REQ_MQL_COMMENT                             // Sort by an order comment in the request structure
  };
//+------------------------------------------------------------------+

Agora, num arquivo separado, criamos uma nova classe do objeto base da ordem pendente abstrata.

No diretório da biblioteca \MQL5\Include\DoEasy\Objects\ criamos uma nova subpasta PendRequest\, nela armazenaremos os arquivos das classes das ordens de negociação pendentes.

Na pasta PendRequest, criaremos uma nova classe do objeto base da ordem pendente abstrata no arquivo PendRequest.mqh:

//+------------------------------------------------------------------+
//|                                                  PendRequest.mqh |
//|                        Copyright 2019, MetaQuotes Software Corp. |
//|                             https://mql5.com/pt/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2019, MetaQuotes Software Corp."
#property link      "https://mql5.com/pt/users/artmedia70"
#property version   "1.00"
#property strict    // Necessary for mql4
//+------------------------------------------------------------------+
//| Include files                                                    |
//+------------------------------------------------------------------+
#include <Object.mqh>
#include "..\..\Services\DELib.mqh"
//+------------------------------------------------------------------+
//| Abstract pending trading request class                           |
//+------------------------------------------------------------------+
class CPendRequest : public CObject
  {
private:
   MqlTradeRequest   m_request;                                         // Trade request structure
//--- Copy trading request data
   void              CopyRequest(const MqlTradeRequest &request);
//--- Return the index of the array the request (1) double and (2) string properties are actually located at
   int               IndexProp(ENUM_PEND_REQ_PROP_DOUBLE property)const { return(int)property-PEND_REQ_PROP_INTEGER_TOTAL;                               }
   int               IndexProp(ENUM_PEND_REQ_PROP_STRING property)const { return(int)property-PEND_REQ_PROP_INTEGER_TOTAL-PEND_REQ_PROP_DOUBLE_TOTAL;    }
protected:
   int               m_digits;                                          // Number of decimal places in a quote
   int               m_digits_lot;                                      // Number of decimal places in the symbol lot value
   bool              m_is_hedge;                                        // Hedging account flag
   long              m_long_prop[PEND_REQ_PROP_INTEGER_TOTAL];          // Request integer properties
   double            m_double_prop[PEND_REQ_PROP_DOUBLE_TOTAL];         // Request real properties
   string            m_string_prop[PEND_REQ_PROP_STRING_TOTAL];         // Request string properties
//--- Protected parametric constructor
                     CPendRequest(const ENUM_PEND_REQ_STATUS status,
                                  const uchar id,
                                  const double price,
                                  const ulong time,
                                  const MqlTradeRequest &request,
                                  const int retcode);
//--- Return (1) the magic number specified in the settings, (2) hedging account flag
   ushort            GetMagicID(void)                                      const { return ushort(this.GetProperty(PEND_REQ_PROP_MQL_REQ_MAGIC) & 0xFFFF);}
   bool              IsHedge(void)                                         const { return this.m_is_hedge;                                               }
public:
//--- Default constructor
                     CPendRequest(){;}
//--- Set request (1) integer, (2) real and (3) string properties
   void              SetProperty(ENUM_PEND_REQ_PROP_INTEGER property,long value) { this.m_long_prop[property]=value;                                     }
   void              SetProperty(ENUM_PEND_REQ_PROP_DOUBLE property,double value){ this.m_double_prop[this.IndexProp(property)]=value;                   }
   void              SetProperty(ENUM_PEND_REQ_PROP_STRING property,string value){ this.m_string_prop[this.IndexProp(property)]=value;                   }
//--- Return (1) integer, (2) real and (3) string request properties from the properties array
   long              GetProperty(ENUM_PEND_REQ_PROP_INTEGER property)      const { return this.m_long_prop[property];                                    }
   double            GetProperty(ENUM_PEND_REQ_PROP_DOUBLE property)       const { return this.m_double_prop[this.IndexProp(property)];                  }
   string            GetProperty(ENUM_PEND_REQ_PROP_STRING property)       const { return this.m_string_prop[this.IndexProp(property)];                  }

//--- Return the flag of the request supporting the property
   virtual bool      SupportProperty(ENUM_PEND_REQ_PROP_INTEGER property)        { return true; }
   virtual bool      SupportProperty(ENUM_PEND_REQ_PROP_DOUBLE property)         { return true; }
   virtual bool      SupportProperty(ENUM_PEND_REQ_PROP_STRING property)         { return true; }

//--- Compare CPendRequest objects by a specified property (to sort the lists by a specified request object property)
   virtual int       Compare(const CObject *node,const int mode=0) const;
//--- Compare CPendRequest objects by all properties (to search for equal request objects)
   bool              IsEqual(CPendRequest* compared_obj);
   
//+------------------------------------------------------------------+
//| Methods of a simplified access to the request object properties  |
//+------------------------------------------------------------------+
//--- Return (1) request structure, (2) status, (3) type, (4) price at the moment of the request generation,
//--- (5) request generation time, (6) next attempt activation time,
//--- (7) waiting time between requests, (8) current attempt index,
//--- (9) number of attempts, (10) request ID
//--- (11) result a request is based on,
//--- (12) order ticket, (13) position ticket, (14) trading operation type
   MqlTradeRequest      MqlRequest(void)                                   const { return this.m_request;                                                }
   ENUM_PEND_REQ_STATUS Status(void)                                       const { return (ENUM_PEND_REQ_STATUS)this.GetProperty(PEND_REQ_PROP_STATUS);  }
   ENUM_PEND_REQ_TYPE   TypeRequest(void)                                  const { return (ENUM_PEND_REQ_TYPE)this.GetProperty(PEND_REQ_PROP_TYPE);      }
   double               PriceCreate(void)                                  const { return this.GetProperty(PEND_REQ_PROP_PRICE_CREATE);                  }
   ulong                TimeCreate(void)                                   const { return this.GetProperty(PEND_REQ_PROP_TIME_CREATE);                   }
   ulong                TimeActivate(void)                                 const { return this.GetProperty(PEND_REQ_PROP_TIME_ACTIVATE);                 }
   ulong                WaitingMSC(void)                                   const { return this.GetProperty(PEND_REQ_PROP_WAITING);                       }
   uchar                CurrentAttempt(void)                               const { return (uchar)this.GetProperty(PEND_REQ_PROP_CURENT);                 }
   uchar                TotalAttempts(void)                                const { return (uchar)this.GetProperty(PEND_REQ_PROP_TOTAL);                  }
   uchar                ID(void)                                           const { return (uchar)this.GetProperty(PEND_REQ_PROP_ID);                     }
   int                  Retcode(void)                                      const { return (int)this.GetProperty(PEND_REQ_PROP_RETCODE);                  }
   ulong                Order(void)                                        const { return this.GetProperty(PEND_REQ_PROP_MQL_REQ_ORDER);                 }
   ulong                Position(void)                                     const { return this.GetProperty(PEND_REQ_PROP_MQL_REQ_POSITION);              }
   ENUM_TRADE_REQUEST_ACTIONS Action(void)                                 const { return (ENUM_TRADE_REQUEST_ACTIONS)this.GetProperty(PEND_REQ_PROP_MQL_REQ_ACTION);}

//--- Set (1) the price when creating a request, (2) request creation time,
//--- (3) current attempt time, (4) waiting time between requests,
//--- (5) current attempt index, (6) number of attempts, (7) ID,
//--- (8) order ticket, (9) position ticket
   void                 SetPriceCreate(const double price)                       { this.SetProperty(PEND_REQ_PROP_PRICE_CREATE,price);                   }
   void                 SetTimeCreate(const ulong time)                          { this.SetProperty(PEND_REQ_PROP_TIME_CREATE,time);                     }
   void                 SetTimeActivate(const ulong time)                        { this.SetProperty(PEND_REQ_PROP_TIME_ACTIVATE,time);                   }
   void                 SetWaitingMSC(const ulong miliseconds)                   { this.SetProperty(PEND_REQ_PROP_WAITING,miliseconds);                  }
   void                 SetCurrentAttempt(const uchar number)                    { this.SetProperty(PEND_REQ_PROP_CURENT,number);                        }
   void                 SetTotalAttempts(const uchar number)                     { this.SetProperty(PEND_REQ_PROP_TOTAL,number);                         }
   void                 SetID(const uchar id)                                    { this.SetProperty(PEND_REQ_PROP_ID,id);                                }
   void                 SetOrder(const ulong ticket)                             { this.SetProperty(PEND_REQ_PROP_MQL_REQ_ORDER,ticket);                 }
   void                 SetPosition(const ulong ticket)                          { this.SetProperty(PEND_REQ_PROP_MQL_REQ_POSITION,ticket);              }
   
//+------------------------------------------------------------------+
//| Descriptions of request object properties                        |
//+------------------------------------------------------------------+
//--- Get description of a request (1) integer, (2) real and (3) string property
   string               GetPropertyDescription(ENUM_PEND_REQ_PROP_INTEGER property);
   string               GetPropertyDescription(ENUM_PEND_REQ_PROP_DOUBLE property);
   string               GetPropertyDescription(ENUM_PEND_REQ_PROP_STRING property);

//--- Return the names of pending request object parameters
   string               StatusDescription(void)                const;
   string               TypeRequestDescription(void)           const;
   string               IDDescription(void)                    const;
   string               RetcodeDescription(void)               const;
   string               TimeCreateDescription(void)            const;
   string               TimeActivateDescription(void)          const;
   string               TimeWaitingDescription(void)           const;
   string               CurrentAttemptDescription(void)        const;

   string               TotalAttemptsDescription(void)         const;
   string               PriceCreateDescription(void)           const;
   
//--- Return the names of trading request structures parameters in the request object
   string               MqlReqActionDescription(void)          const;
   string               MqlReqMagicDescription(void)           const;
   string               MqlReqOrderDescription(void)           const;
   string               MqlReqSymbolDescription(void)          const;
   string               MqlReqVolumeDescription(void)          const;
   string               MqlReqPriceDescription(void)           const;
   string               MqlReqStopLimitDescription(void)       const;
   string               MqlReqStopLossDescription(void)        const;
   string               MqlReqTakeProfitDescription(void)      const;
   string               MqlReqDeviationDescription(void)       const;
   string               MqlReqTypeOrderDescription(void)       const;
   string               MqlReqTypeFillingDescription(void)     const;
   string               MqlReqTypeTimeDescription(void)        const;
   string               MqlReqExpirationDescription(void)      const;
   string               MqlReqCommentDescription(void)         const;
   string               MqlReqPositionDescription(void)        const;
   string               MqlReqPositionByDescription(void)      const;

//--- Display (1) description of request properties (full_prop=true - all properties, false - only supported ones),
//--- (2) short event message (implementation in the class descendants) in the journal
   void                 Print(const bool full_prop=false);
   virtual void         PrintShort(void){;}
  };
//+------------------------------------------------------------------+

Já criamos objetos idênticos muitas vezes com uma descrição detalhada de suas estruturas. Penso que aqui não vamos nos debruçar sobre os princípios da estrutura do objeto, pois, nela, como em outros similares, existem três matrizes para armazenar propriedades inteiras, reais e de string. Além disso, existem métodos para acessar essas propriedades, especificando a constante da propriedade como GetProperty(), e há métodos simplificados que têm um nome "falante". Também existem métodos que exibem descrições de todas as propriedades do objeto. Em geral, tudo é padrão para objetos de biblioteca. No primeiro artigo podemos ler novamente sobre a estrutura dos objetos de biblioteca.

Fora do corpo da classe, escrevemos um construtor de classe privado:

//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CPendRequest::CPendRequest(const ENUM_PEND_REQ_STATUS status,
                           const uchar id,
                           const double price,
                           const ulong time,
                           const MqlTradeRequest &request,
                           const int retcode)
  {
   this.CopyRequest(request);
   this.m_is_hedge=#ifdef __MQL4__ true #else bool(::AccountInfoInteger(ACCOUNT_MARGIN_MODE)==ACCOUNT_MARGIN_MODE_RETAIL_HEDGING) #endif;
   this.m_digits=(int)::SymbolInfoInteger(this.GetProperty(PEND_REQ_PROP_MQL_REQ_SYMBOL),SYMBOL_DIGITS);
   int dg=(int)DigitsLots(this.GetProperty(PEND_REQ_PROP_MQL_REQ_SYMBOL));
   this.m_digits_lot=(dg==0 ? 1 : dg);
   this.SetProperty(PEND_REQ_PROP_STATUS,status);
   this.SetProperty(PEND_REQ_PROP_ID,id);
   this.SetProperty(PEND_REQ_PROP_RETCODE,retcode);
   this.SetProperty(PEND_REQ_PROP_TYPE,this.GetProperty(PEND_REQ_PROP_RETCODE)>0 ? PEND_REQ_TYPE_ERROR : PEND_REQ_TYPE_REQUEST);
   this.SetProperty(PEND_REQ_PROP_TIME_CREATE,time);
   this.SetProperty(PEND_REQ_PROP_PRICE_CREATE,price);
  }
//+------------------------------------------------------------------+

Bem, o que temos aqui:
Primeiro, copiamos os dados da estrutura da ordem de negociação para matrizes de propriedades inteiras, reais e de string usando o método CopyRequest(), que discutiremos abaixo.
Em seguida, definimos o sinalizador da conta de tipo 'hedge', definimos o número de casas decimais na cotação do símbolo e no valor do lote do símbolo (isso é necessário para a exibição correta das informações no log). Além disso, se no valor do lote o número de casas decimais for zero, o resultado será uma casa decimal. Assim, o valor do lote será mais claro: em vez de "1", será exibido "1,0".
Logo, simplesmente configuramos os valores transferidos de algumas propriedades ao construtor da classe quando criado o objeto da ordem com os valores das propriedades do objeto correspondentes.
Assim, preenchemos todas as propriedades do objeto-ordem pendente imediatamente após sua criação.

Método para comparar dois objetos-ordens de negociação de acordo com a propriedade especificada (mode):

//+------------------------------------------------------------------+
//| Compare CPendRequest objects by a specified property             |
//+------------------------------------------------------------------+
int CPendRequest::Compare(const CObject *node,const int mode=0) const
  {
   const CPendRequest *compared_obj=node;
//--- compare integer properties of two events
   if(mode<PEND_REQ_PROP_INTEGER_TOTAL)
     {
      long value_compared=compared_obj.GetProperty((ENUM_PEND_REQ_PROP_INTEGER)mode);
      long value_current=this.GetProperty((ENUM_PEND_REQ_PROP_INTEGER)mode);
      return(value_current>value_compared ? 1 : value_current<value_compared ? -1 : 0);
     }
//--- compare integer properties of two objects
   if(mode<PEND_REQ_PROP_DOUBLE_TOTAL+PEND_REQ_PROP_INTEGER_TOTAL)
     {
      double value_compared=compared_obj.GetProperty((ENUM_PEND_REQ_PROP_DOUBLE)mode);
      double value_current=this.GetProperty((ENUM_PEND_REQ_PROP_DOUBLE)mode);
      return(value_current>value_compared ? 1 : value_current<value_compared ? -1 : 0);
     }
//--- compare string properties of two objects
   else if(mode<PEND_REQ_PROP_DOUBLE_TOTAL+PEND_REQ_PROP_INTEGER_TOTAL+PEND_REQ_PROP_STRING_TOTAL)
     {
      string value_compared=compared_obj.GetProperty((ENUM_PEND_REQ_PROP_STRING)mode);
      string value_current=this.GetProperty((ENUM_PEND_REQ_PROP_STRING)mode);
      return(value_current>value_compared ? 1 : value_current<value_compared ? -1 : 0);
     }
   return 0;
  }
//+------------------------------------------------------------------+

Método para comparar completamente dois objetos-ordens pendentes de acordo com todas as suas propriedades:

//+------------------------------------------------------------------+
//| Compare CPendRequest objects by all properties                   |
//+------------------------------------------------------------------+
bool CPendRequest::IsEqual(CPendRequest *compared_obj)
  {
   int beg=0, end=PEND_REQ_PROP_INTEGER_TOTAL;
   for(int i=beg; i<end; i++)
     {
      ENUM_PEND_REQ_PROP_INTEGER prop=(ENUM_PEND_REQ_PROP_INTEGER)i;
      if(this.GetProperty(prop)!=compared_obj.GetProperty(prop)) return false; 
     }
   beg=end; end+=PEND_REQ_PROP_DOUBLE_TOTAL;
   for(int i=beg; i<end; i++)
     {
      ENUM_PEND_REQ_PROP_DOUBLE prop=(ENUM_PEND_REQ_PROP_DOUBLE)i;
      if(this.GetProperty(prop)!=compared_obj.GetProperty(prop)) return false; 
     }
   beg=end; end+=PEND_REQ_PROP_STRING_TOTAL;
   for(int i=beg; i<end; i++)
     {
      ENUM_PEND_REQ_PROP_STRING prop=(ENUM_PEND_REQ_PROP_STRING)i;
      if(this.GetProperty(prop)!=compared_obj.GetProperty(prop)) return false; 
     }
//--- All properties are equal
   return true;
  }
//+------------------------------------------------------------------+

Esses métodos também foram abordados mais de uma vez durante a criação de objetos de biblioteca anteriores.
Repito apenas que o método virtual Compare() do objeto-solicitação (que serve para comparar com base na propriedade especificada) compara as propriedades especificadas do objeto atual da classe CPendRequest e o objeto da mesma classe transferido ao método. Se o valor do objeto atual for maior que o valor do objeto comparado, o método retornará 1, se for menor, retornará -1, caso contrário, 0. Isso é necessário para trabalhar com listas de ponteiros para objetos, pois, com seu método Searsh(), que para comparação rápida, usa o método virtual Compare() do objeto base da biblioteca padrão. Como o método é virtual, ele deve ser redefinido nos descendentes da classe CObject, já fizemos isso aqui.
Já o método IsEqual() compara alternadamente cada propriedade de dois objetos comparados, e se algum objeto não for igual, retornará false. Concluídos três ciclos por todas as propriedades dos dois objetos comparados, será retornado true , indicando que todas as propriedades dos objetos são iguais.

Método para copiar a estrutura de uma ordem de negociação nas matrizes de propriedades de um objeto de ordem pendente:

//+------------------------------------------------------------------+
//| Copy trading request data                                        |
//+------------------------------------------------------------------+
void CPendRequest::CopyRequest(const MqlTradeRequest &request)
  {
//--- Copy a passed structure to an object structure
   this.m_request=request;

//--- Integer properties of a trading request structure
   this.SetProperty(PEND_REQ_PROP_MQL_REQ_ACTION,request.action);             // Type of a performed action in the request structure
   this.SetProperty(PEND_REQ_PROP_MQL_REQ_TYPE,request.type);                 // Order type in the request structure
   this.SetProperty(PEND_REQ_PROP_MQL_REQ_MAGIC,request.magic);               // EA stamp (magic number ID) in the request structure
   this.SetProperty(PEND_REQ_PROP_MQL_REQ_ORDER,request.order);               // Order ticket in the request structure
   this.SetProperty(PEND_REQ_PROP_MQL_REQ_POSITION,request.position);         // Position ticket in the request structure
   this.SetProperty(PEND_REQ_PROP_MQL_REQ_POSITION_BY,request.position_by);   // Opposite position ticket in the request structure
   this.SetProperty(PEND_REQ_PROP_MQL_REQ_DEVIATION,request.deviation);       // Maximum acceptable deviation from a requested price in the request structure
   this.SetProperty(PEND_REQ_PROP_MQL_REQ_EXPIRATION,request.expiration);     // Order expiration time (for ORDER_TIME_SPECIFIED type orders) in the request structure
   this.SetProperty(PEND_REQ_PROP_MQL_REQ_TYPE_FILLING,request.type_filling); // Order filling type in the request structure
   this.SetProperty(PEND_REQ_PROP_MQL_REQ_TYPE_TIME,request.type_time);       // Order lifetime type in the request structure
//--- Real properties of a trading request structure
   this.SetProperty(PEND_REQ_PROP_MQL_REQ_VOLUME,request.volume);             // Requested volume of a deal in lots in the request structure
   this.SetProperty(PEND_REQ_PROP_MQL_REQ_PRICE,request.price);               // Price in the request structure
   this.SetProperty(PEND_REQ_PROP_MQL_REQ_STOPLIMIT,request.stoplimit);       // StopLimit level in the request structure
   this.SetProperty(PEND_REQ_PROP_MQL_REQ_SL,request.sl);                     // Stop Loss level in the request structure
   this.SetProperty(PEND_REQ_PROP_MQL_REQ_TP,request.tp);                     // Take Profit level in the request structure
//--- String properties of a trading request structure
   this.SetProperty(PEND_REQ_PROP_MQL_REQ_SYMBOL,request.symbol);             // Trading instrument name in the request structure
   this.SetProperty(PEND_REQ_PROP_MQL_REQ_COMMENT,request.comment);           // Order comment in the request structure
  }
//+------------------------------------------------------------------+

Neste caso, primeiro copiamos os valores de todos os campos transferidos para o método da estrutura da ordem de negociação na mesma estrutura do objeto-ordem, e, em seguida, definimos os valores de todos os campos da estrutura para as propriedades do objeto usando os métodos de configuração de propriedades SetProperty().

Métodos que retornam descrições de propriedades inteiras, reais e de string do objeto-ordem pendente:

//+------------------------------------------------------------------+
//| Return the description of the request integer property           |
//+------------------------------------------------------------------+
string CPendRequest::GetPropertyDescription(ENUM_PEND_REQ_PROP_INTEGER property)
  {
   return
     (
      property==PEND_REQ_PROP_STATUS               ?  this.StatusDescription()            :
      property==PEND_REQ_PROP_TYPE                 ?  this.TypeRequestDescription()       :
      property==PEND_REQ_PROP_ID                   ?  this.IDDescription()                :
      property==PEND_REQ_PROP_RETCODE              ?  this.RetcodeDescription()           :
      property==PEND_REQ_PROP_TIME_CREATE          ?  this.TimeCreateDescription()        :
      property==PEND_REQ_PROP_TIME_ACTIVATE        ?  this.TimeActivateDescription()      :
      property==PEND_REQ_PROP_WAITING              ?  this.TimeWaitingDescription()       :
      property==PEND_REQ_PROP_CURENT               ?  this.CurrentAttemptDescription()    :

      property==PEND_REQ_PROP_TOTAL                ?  this.TotalAttemptsDescription()     :
      //--- MqlTradeRequest
      property==PEND_REQ_PROP_MQL_REQ_ACTION       ?  this.MqlReqActionDescription()      :
      property==PEND_REQ_PROP_MQL_REQ_TYPE         ?  this.MqlReqTypeOrderDescription()   :
      property==PEND_REQ_PROP_MQL_REQ_MAGIC        ?  this.MqlReqMagicDescription()       :
      property==PEND_REQ_PROP_MQL_REQ_ORDER        ?  this.MqlReqOrderDescription()       :
      property==PEND_REQ_PROP_MQL_REQ_POSITION     ?  this.MqlReqPositionDescription()    :
      property==PEND_REQ_PROP_MQL_REQ_POSITION_BY  ?  this.MqlReqPositionByDescription()  :
      property==PEND_REQ_PROP_MQL_REQ_DEVIATION    ?  this.MqlReqDeviationDescription()   :
      property==PEND_REQ_PROP_MQL_REQ_EXPIRATION   ?  this.MqlReqExpirationDescription()  :
      property==PEND_REQ_PROP_MQL_REQ_TYPE_FILLING ?  this.MqlReqTypeFillingDescription() :
      property==PEND_REQ_PROP_MQL_REQ_TYPE_TIME    ?  this.MqlReqTypeTimeDescription()    :
      ::EnumToString(property)
     );
  }
//+------------------------------------------------------------------+
//| Return the description of the request real property              |
//+------------------------------------------------------------------+
string CPendRequest::GetPropertyDescription(ENUM_PEND_REQ_PROP_DOUBLE property)
  {
   return
     (
      property==PEND_REQ_PROP_PRICE_CREATE      ?  this.PriceCreateDescription()          :
      //--- MqlTradeRequest
      property==PEND_REQ_PROP_MQL_REQ_VOLUME    ?  this.MqlReqVolumeDescription()         :
      property==PEND_REQ_PROP_MQL_REQ_PRICE     ?  this.MqlReqPriceDescription()          :
      property==PEND_REQ_PROP_MQL_REQ_STOPLIMIT ?  this.MqlReqStopLimitDescription()      :
      property==PEND_REQ_PROP_MQL_REQ_SL        ?  this.MqlReqStopLossDescription()       :
      property==PEND_REQ_PROP_MQL_REQ_TP        ?  this.MqlReqTakeProfitDescription()     :
      ::EnumToString(property)
     );
  }
//+------------------------------------------------------------------+
//| Return the description of the request string property            |
//+------------------------------------------------------------------+
string CPendRequest::GetPropertyDescription(ENUM_PEND_REQ_PROP_STRING property)
  {
   return
     (
      property==PEND_REQ_PROP_MQL_REQ_SYMBOL    ?  this.MqlReqSymbolDescription()         :
      property==PEND_REQ_PROP_MQL_REQ_COMMENT   ?  this.MqlReqCommentDescription()        :
      ::EnumToString(property)
     );
  }
//+------------------------------------------------------------------+

Ao método é transferida a propriedade, e, dependendo do seu valor, é retornada sua descrição de string
com a ajuda de métodos que retornam uma descrição desta propriedade:

//+------------------------------------------------------------------+
//| Return the pending request status name                           |
//+------------------------------------------------------------------+
string CPendRequest::StatusDescription(void) const
  {
   int code_descr=
     (
      this.GetProperty(PEND_REQ_PROP_STATUS)==PEND_REQ_STATUS_OPEN   ?  MSG_LIB_TEXT_PEND_REQUEST_STATUS_OPEN     :
      this.GetProperty(PEND_REQ_PROP_STATUS)==PEND_REQ_STATUS_CLOSE  ?  MSG_LIB_TEXT_PEND_REQUEST_STATUS_CLOSE    :
      this.GetProperty(PEND_REQ_PROP_STATUS)==PEND_REQ_STATUS_SLTP   ?  MSG_LIB_TEXT_PEND_REQUEST_STATUS_SLTP     :
      this.GetProperty(PEND_REQ_PROP_STATUS)==PEND_REQ_STATUS_PLACE  ?  MSG_LIB_TEXT_PEND_REQUEST_STATUS_PLACE    :
      this.GetProperty(PEND_REQ_PROP_STATUS)==PEND_REQ_STATUS_REMOVE ?  MSG_LIB_TEXT_PEND_REQUEST_STATUS_REMOVE   :
      this.GetProperty(PEND_REQ_PROP_STATUS)==PEND_REQ_STATUS_MODIFY ?  MSG_LIB_TEXT_PEND_REQUEST_STATUS_MODIFY   :
      MSG_EVN_STATUS_UNKNOWN
     );
   return CMessage::Text(MSG_LIB_TEXT_PEND_REQUEST_STATUS)+": "+CMessage::Text(code_descr);
  }
//+------------------------------------------------------------------+
//| Return the pending request type name                             |
//+------------------------------------------------------------------+
string CPendRequest::TypeRequestDescription(void) const
  {
   int code_descr=
     (
      this.GetProperty(PEND_REQ_PROP_TYPE)==PEND_REQ_TYPE_ERROR   ?  MSG_LIB_TEXT_PEND_REQUEST_BY_ERROR     :
      this.GetProperty(PEND_REQ_PROP_TYPE)==PEND_REQ_TYPE_REQUEST ?  MSG_LIB_TEXT_PEND_REQUEST_BY_REQUEST   :
      MSG_SYM_MODE_UNKNOWN
     );
   return CMessage::Text(MSG_LIB_TEXT_PEND_REQUEST_TYPE)+": "+CMessage::Text(code_descr);
  }
//+------------------------------------------------------------------+
//| Return the pending request ID description                        |
//+------------------------------------------------------------------+
string CPendRequest::IDDescription(void) const
  {
   return CMessage::Text(MSG_LIB_TEXT_PEND_REQUEST_ID)+": #"+(string)this.GetProperty(PEND_REQ_PROP_ID);
  }
//+------------------------------------------------------------------+
//| Return the description of an error code a request is based on    |
//+------------------------------------------------------------------+
string CPendRequest::RetcodeDescription(void) const
  {
   return CMessage::Text(MSG_LIB_TEXT_PEND_REQUEST_RETCODE)+": "+
          CMessage::Text((int)this.GetProperty(PEND_REQ_PROP_RETCODE))+
          " ("+(string)this.GetProperty(PEND_REQ_PROP_RETCODE)+")";
  }
//+------------------------------------------------------------------+
//| Return the description of a pending request creation time        |
//+------------------------------------------------------------------+
string CPendRequest::TimeCreateDescription(void) const
  {
   return CMessage::Text(MSG_LIB_TEXT_PEND_REQUEST_TIME_CREATE)+": "+::TimeMSCtoString(this.GetProperty(PEND_REQ_PROP_TIME_CREATE));
  }
//+------------------------------------------------------------------+
//| Return the description of a pending request activation time      |
//+------------------------------------------------------------------+
string CPendRequest::TimeActivateDescription(void) const
  {
   return CMessage::Text(MSG_LIB_TEXT_PEND_REQUEST_TIME_ACTIVATE)+": "+::TimeMSCtoString(this.GetProperty(PEND_REQ_PROP_TIME_ACTIVATE));
  }
//+----------------------------------------------------------------------+
//| Return the description of a time spent waiting for a pending request |
//+----------------------------------------------------------------------+
string CPendRequest::TimeWaitingDescription(void) const
  {
   return CMessage::Text(MSG_LIB_TEXT_PEND_REQUEST_WAITING)+": "+
          (string)this.GetProperty(PEND_REQ_PROP_WAITING)+
          " ("+::TimeToString(this.GetProperty(PEND_REQ_PROP_WAITING)/1000,TIME_MINUTES|TIME_SECONDS)+")";
  }
//+------------------------------------------------------------------+
//| Return the description of the current pending request attempt    |
//+------------------------------------------------------------------+
string CPendRequest::CurrentAttemptDescription(void) const
  {
   return CMessage::Text(MSG_LIB_TEXT_PEND_REQUEST_CURRENT_ATTEMPT)+": "+(string)this.GetProperty(PEND_REQ_PROP_CURENT);
  }
//+------------------------------------------------------------------+
//| Return the description of a number of pending request attempts   |
//+------------------------------------------------------------------+
string CPendRequest::TotalAttemptsDescription(void) const
  {
   return CMessage::Text(MSG_LIB_TEXT_PEND_REQUEST_TOTAL_ATTEMPTS)+": "+(string)this.GetProperty(PEND_REQ_PROP_TOTAL);
  }
//+------------------------------------------------------------------+
//| Return the description of a price when creating a request        |
//+------------------------------------------------------------------+
string CPendRequest::PriceCreateDescription(void) const
  {
   return CMessage::Text(MSG_LIB_TEXT_PEND_REQUEST_PRICE_CREATE)+": "+::DoubleToString(this.GetProperty(PEND_REQ_PROP_PRICE_CREATE),this.m_digits);
  }
//+------------------------------------------------------------------+
//| Return the executed action type description                      |
//+------------------------------------------------------------------+
string CPendRequest::MqlReqActionDescription(void) const
  {
   int code_descr=
     (
      this.GetProperty(PEND_REQ_PROP_MQL_REQ_ACTION)==TRADE_ACTION_DEAL       ?  MSG_LIB_TEXT_REQUEST_ACTION_DEAL       :
      this.GetProperty(PEND_REQ_PROP_MQL_REQ_ACTION)==TRADE_ACTION_PENDING    ?  MSG_LIB_TEXT_REQUEST_ACTION_PENDING    :
      this.GetProperty(PEND_REQ_PROP_MQL_REQ_ACTION)==TRADE_ACTION_SLTP       ?  MSG_LIB_TEXT_REQUEST_ACTION_SLTP       :
      this.GetProperty(PEND_REQ_PROP_MQL_REQ_ACTION)==TRADE_ACTION_MODIFY     ?  MSG_LIB_TEXT_REQUEST_ACTION_MODIFY     :
      this.GetProperty(PEND_REQ_PROP_MQL_REQ_ACTION)==TRADE_ACTION_REMOVE     ?  MSG_LIB_TEXT_REQUEST_ACTION_REMOVE     :
      this.GetProperty(PEND_REQ_PROP_MQL_REQ_ACTION)==TRADE_ACTION_CLOSE_BY   ?  MSG_LIB_TEXT_REQUEST_ACTION_CLOSE_BY   :
      MSG_LIB_TEXT_REQUEST_ACTION_UNCNOWN
     );
   return CMessage::Text(MSG_LIB_TEXT_REQUEST_ACTION)+": "+CMessage::Text(code_descr);
  }
//+------------------------------------------------------------------+
//| Return the magic number value description                        |
//+------------------------------------------------------------------+
string CPendRequest::MqlReqMagicDescription(void) const
  {
   return CMessage::Text(MSG_ORD_MAGIC)+": "+(string)this.GetProperty(PEND_REQ_PROP_MQL_REQ_MAGIC)+
          (this.GetMagicID()!=this.GetProperty(PEND_REQ_PROP_MQL_REQ_MAGIC) ? " ("+(string)this.GetMagicID()+")" : "");
  }
//+------------------------------------------------------------------+
//| Return the order ticket value description                        |
//+------------------------------------------------------------------+
string CPendRequest::MqlReqOrderDescription(void) const
  {
   return CMessage::Text(MSG_LIB_TEXT_REQUEST_ORDER)+": "+
          (this.GetProperty(PEND_REQ_PROP_MQL_REQ_ORDER)>0 ? 
           "#"+(string)this.GetProperty(PEND_REQ_PROP_MQL_REQ_ORDER) : 
           CMessage::Text(MSG_LIB_PROP_NOT_SET));
  }
//+------------------------------------------------------------------+
//| Return the request position ticket description                   |
//+------------------------------------------------------------------+
string CPendRequest::MqlReqPositionDescription(void) const
  {
   return CMessage::Text(MSG_LIB_TEXT_REQUEST_POSITION)+": "+
          (this.GetProperty(PEND_REQ_PROP_MQL_REQ_POSITION)>0 ? 
           (string)this.GetProperty(PEND_REQ_PROP_MQL_REQ_POSITION) : 
           CMessage::Text(MSG_LIB_PROP_NOT_SET));
  }
//+------------------------------------------------------------------+
//| Return the request opposite position ticket description          |
//+------------------------------------------------------------------+
string CPendRequest::MqlReqPositionByDescription(void) const
  {
   return CMessage::Text(MSG_LIB_TEXT_REQUEST_POSITION_BY)+": "+
          (this.GetProperty(PEND_REQ_PROP_MQL_REQ_POSITION_BY)>0 ? 
           (string)this.GetProperty(PEND_REQ_PROP_MQL_REQ_POSITION_BY) : 
           CMessage::Text(MSG_LIB_PROP_NOT_SET));
  }
//+------------------------------------------------------------------+
//| Return the request deviation size description                    |
//+------------------------------------------------------------------+
string CPendRequest::MqlReqDeviationDescription(void) const
  {
   return CMessage::Text(MSG_LIB_TEXT_REQUEST_DEVIATION)+": "+(string)this.GetProperty(PEND_REQ_PROP_MQL_REQ_DEVIATION);
  }
//+------------------------------------------------------------------+
//| Return the request order type description                        |
//+------------------------------------------------------------------+
string CPendRequest::MqlReqTypeOrderDescription(void) const
  {
   return CMessage::Text(MSG_LIB_TEXT_REQUEST_TYPE)+": "+OrderTypeDescription((ENUM_ORDER_TYPE)this.GetProperty(PEND_REQ_PROP_MQL_REQ_TYPE));
  }
//+------------------------------------------------------------------+
//| Return the request order filling mode description                |
//+------------------------------------------------------------------+
string CPendRequest::MqlReqTypeFillingDescription(void) const
  {
   return CMessage::Text(MSG_LIB_TEXT_REQUEST_TYPE_FILLING)+": "+OrderTypeFillingDescription((ENUM_ORDER_TYPE_FILLING)this.GetProperty(PEND_REQ_PROP_MQL_REQ_TYPE_FILLING));
  }
//+------------------------------------------------------------------+
//| Return the request order lifetime type description               |
//+------------------------------------------------------------------+
string CPendRequest::MqlReqTypeTimeDescription(void) const
  {
   return CMessage::Text(MSG_LIB_TEXT_REQUEST_TYPE_TIME)+": "+OrderTypeTimeDescription((ENUM_ORDER_TYPE_TIME)this.GetProperty(PEND_REQ_PROP_MQL_REQ_TYPE_TIME));
  }
//+------------------------------------------------------------------+
//| Return the request order expiration time description             |
//+------------------------------------------------------------------+
string CPendRequest::MqlReqExpirationDescription(void) const
  {
   return CMessage::Text(MSG_LIB_TEXT_REQUEST_EXPIRATION)+": "+
          (this.GetProperty(PEND_REQ_PROP_MQL_REQ_EXPIRATION)>0 ? 
           ::TimeToString(this.GetProperty(PEND_REQ_PROP_MQL_REQ_EXPIRATION)) : 
           CMessage::Text(MSG_LIB_PROP_NOT_SET));
  }
//+------------------------------------------------------------------+
//| Return the request volume description                            |
//+------------------------------------------------------------------+
string CPendRequest::MqlReqVolumeDescription(void) const
  {
   return CMessage::Text(MSG_LIB_TEXT_REQUEST_VOLUME)+": "+
          (this.GetProperty(PEND_REQ_PROP_MQL_REQ_VOLUME)>0 ? 
           ::DoubleToString(this.GetProperty(PEND_REQ_PROP_MQL_REQ_VOLUME),this.m_digits_lot) : 
           CMessage::Text(MSG_LIB_PROP_NOT_SET));
  }
//+------------------------------------------------------------------+
//| Return the request price value description                       |
//+------------------------------------------------------------------+
string CPendRequest::MqlReqPriceDescription(void) const
  {
   return CMessage::Text(MSG_LIB_TEXT_REQUEST_PRICE)+": "+
          (this.GetProperty(PEND_REQ_PROP_MQL_REQ_PRICE)>0 ? 
           ::DoubleToString(this.GetProperty(PEND_REQ_PROP_MQL_REQ_PRICE),this.m_digits) : 
           CMessage::Text(MSG_LIB_PROP_NOT_SET));
  }
//+------------------------------------------------------------------+
//| Return the request StopLimit order price description             |
//+------------------------------------------------------------------+
string CPendRequest::MqlReqStopLimitDescription(void) const
  {
   return CMessage::Text(MSG_LIB_TEXT_REQUEST_STOPLIMIT)+": "+
          (this.GetProperty(PEND_REQ_PROP_MQL_REQ_STOPLIMIT)>0 ? 
           ::DoubleToString(this.GetProperty(PEND_REQ_PROP_MQL_REQ_STOPLIMIT),this.m_digits) : 
           CMessage::Text(MSG_LIB_PROP_NOT_SET));
  }
//+------------------------------------------------------------------+
//| Return the request StopLoss order price description              |
//+------------------------------------------------------------------+
string CPendRequest::MqlReqStopLossDescription(void) const
  {
   return CMessage::Text(MSG_LIB_TEXT_REQUEST_SL)+": "+
          (this.GetProperty(PEND_REQ_PROP_MQL_REQ_SL)>0 ? 
           ::DoubleToString(this.GetProperty(PEND_REQ_PROP_MQL_REQ_SL),this.m_digits) : 
           CMessage::Text(MSG_LIB_PROP_NOT_SET));
  }
//+------------------------------------------------------------------+
//| Return the request TakeProfit order price description            |
//+------------------------------------------------------------------+
string CPendRequest::MqlReqTakeProfitDescription(void) const
  {
   return CMessage::Text(MSG_LIB_TEXT_REQUEST_TP)+": "+
          (this.GetProperty(PEND_REQ_PROP_MQL_REQ_TP)>0 ? 
           ::DoubleToString(this.GetProperty(PEND_REQ_PROP_MQL_REQ_TP),this.m_digits) : 
           CMessage::Text(MSG_LIB_PROP_NOT_SET));
  }
//+------------------------------------------------------------------+
//| Return the description of a trading instrument name in a request |
//+------------------------------------------------------------------+
string CPendRequest::MqlReqSymbolDescription(void) const
  {
   return CMessage::Text(MSG_LIB_TEXT_REQUEST_SYMBOL)+": "+this.GetProperty(PEND_REQ_PROP_MQL_REQ_SYMBOL);
  }
//+------------------------------------------------------------------+
//| Return the request order comment description                     |
//+------------------------------------------------------------------+
string CPendRequest::MqlReqCommentDescription(void) const
  {
   return CMessage::Text(MSG_LIB_TEXT_REQUEST_COMMENT)+": "+
          (this.GetProperty(PEND_REQ_PROP_MQL_REQ_COMMENT)!="" && this.GetProperty(PEND_REQ_PROP_MQL_REQ_COMMENT)!=NULL ? 
           "\""+this.GetProperty(PEND_REQ_PROP_MQL_REQ_COMMENT)+"\"" : 
           CMessage::Text(MSG_LIB_PROP_NOT_SET));
  }
//+------------------------------------------------------------------+

Nos métodos, é verificado o valor da propriedade transferida, é criada sua descrição de texto e é retornada a linha de texto criada.

O método Print() serve para exibir todas as propriedades do objeto no log:

//+------------------------------------------------------------------+
//| Display the pending request properties in the journal            |
//+------------------------------------------------------------------+
void CPendRequest::Print(const bool full_prop=false)
  {
   int header_code=
     (
      this.GetProperty(PEND_REQ_PROP_STATUS)==PEND_REQ_STATUS_OPEN   ? MSG_LIB_TEXT_PEND_REQUEST_STATUS_OPEN   :
      this.GetProperty(PEND_REQ_PROP_STATUS)==PEND_REQ_STATUS_CLOSE  ? MSG_LIB_TEXT_PEND_REQUEST_STATUS_CLOSE  :
      this.GetProperty(PEND_REQ_PROP_STATUS)==PEND_REQ_STATUS_SLTP   ? MSG_LIB_TEXT_PEND_REQUEST_STATUS_SLTP   :
      this.GetProperty(PEND_REQ_PROP_STATUS)==PEND_REQ_STATUS_PLACE  ? MSG_LIB_TEXT_PEND_REQUEST_STATUS_PLACE  :
      this.GetProperty(PEND_REQ_PROP_STATUS)==PEND_REQ_STATUS_REMOVE ? MSG_LIB_TEXT_PEND_REQUEST_STATUS_REMOVE :
      this.GetProperty(PEND_REQ_PROP_STATUS)==PEND_REQ_STATUS_MODIFY ? MSG_LIB_TEXT_PEND_REQUEST_STATUS_MODIFY :
      WRONG_VALUE
     );
   ::Print("============= \"",CMessage::Text(header_code),"\" =============");
   int beg=0, end=PEND_REQ_PROP_INTEGER_TOTAL;
   for(int i=beg; i<end; i++)
     {
      ENUM_PEND_REQ_PROP_INTEGER prop=(ENUM_PEND_REQ_PROP_INTEGER)i;
      if(!full_prop && !this.SupportProperty(prop)) continue;
      ::Print(this.GetPropertyDescription(prop));
     }
   ::Print("------");
   beg=end; end+=PEND_REQ_PROP_DOUBLE_TOTAL;
   for(int i=beg; i<end; i++)
     {
      ENUM_PEND_REQ_PROP_DOUBLE prop=(ENUM_PEND_REQ_PROP_DOUBLE)i;
      if(!full_prop && !this.SupportProperty(prop)) continue;
      ::Print(this.GetPropertyDescription(prop));
     }
   ::Print("------");
   beg=end; end+=PEND_REQ_PROP_STRING_TOTAL;
   for(int i=beg; i<end; i++)
     {
      ENUM_PEND_REQ_PROP_STRING prop=(ENUM_PEND_REQ_PROP_STRING)i;
      if(!full_prop && !this.SupportProperty(prop)) continue;
      ::Print(this.GetPropertyDescription(prop));
     }
   ::Print("================== ",CMessage::Text(MSG_LIB_PARAMS_LIST_END),": \"",CMessage::Text(header_code),"\" ==================\n");
  }
//+------------------------------------------------------------------+


Nós criamos tais métodos para todos os objetos anteriores da biblioteca e analisamos sua estrutura desde o início da descrição da biblioteca, por isso, aqui vamos nos restringir a uma breve descrição dele:
Realizamos três ciclos percorrendo as três matrizes das propriedades do objeto, obtemos cada propriedade do objeto e exibimos sua descrição no log, dependendo do sinalizador que exibe apenas as propriedades suportadas do objeto.

O método PrintShort(), projetado para exibir uma descrição breve do objeto-ordem, é feito como virtual. No objeto base, ele não faz nada, ele deve ser redefinido nos objetos-herdeiros para que cada objeto-herdeiro possa exibir no log exclusivamente suas propriedades pertencentes apenas a ele.

Criamos o objeto base da ordem pendente abstrata.
Em seguida, para esclarecer qual ordem específica deve ser criada, precisamos criar seis objetos-herdeiros a partir do objeto-ordem abstrata. Eles serão criados nos métodos de negociação da classe de negociação ao processar erros que exigem espera. Além disso, eles serão gerados assim como ordens de negociação independentes ao criar a lógica de negociação com a ajuda de ordens de negociação pendentes.

Objetos-herdeiros do objeto base-ordem pendente

Em cada método de negociação da classe de negociação, temos blocos para criar ordens pendentes. Com base na operação realizada pelo método de negociação, criaremos as ordens pendentes correspondentes. Mas, por enquanto, só temos uma ordem pendente abstrata base. Para, com base nela, criar várias ordens de negociação segundo seu tipo de operação, precisamos criar seis de seus herdeiros, onde cada classe herdada enviará apenas sua própria operação de negociação para o servidor. Anteriormente, já dei uma lista desses objetos:

Como lembramos, no construtor protegido da ordem pendente abstrata base há um parâmetro que indica o status da ordem criada:

//--- Protected parametric constructor
                     CPendRequest(const ENUM_PEND_REQ_STATUS status,
                                  const uchar id,
                                  const double price,
                                  const ulong time,
                                  const MqlTradeRequest &request,
                                  const int retcode);

Indicaremos este status (transferiremos do construtor do objeto herdado ao construtor do objeto base) ao criar uma nova ordem pendente. Assim, indicaremos o tipo de ordem estamos criando com base na operação executada. Já analisamos esse comportamento no segundo artigo ao criar objetos de ordens e transações históricas. Por isso, em vez de falar disso, vamos considerar todos os seis objetos de ordens pendentes com base no tipo de operação de negociação.
Criaremos todas as classes de objetos-herdeiros da ordem de negociação base na mesma pasta em que está localizado o objeto base:
\MQL5\Include\DoEasy\Objects\ PendRequest\

Classe de objeto de uma ordem pendente para abrir uma posição (arquivo de classe PendReqOpen.mqh):

//+------------------------------------------------------------------+
//|                                                  PendReqOpen.mqh |
//|                        Copyright 2019, MetaQuotes Software Corp. |
//|                             https://mql5.com/pt/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2019, MetaQuotes Software Corp."
#property link      "https://mql5.com/pt/users/artmedia70"
#property version   "1.00"
//+------------------------------------------------------------------+
//| Include files                                                    |
//+------------------------------------------------------------------+
#include "PendRequest.mqh"
//+------------------------------------------------------------------+
//| Pending request for opening a position                           |
//+------------------------------------------------------------------+
class CPendReqOpen : public CPendRequest
  {
public:
//--- Constructor
                     CPendReqOpen(const uchar id,
                                  const double price,
                                  const ulong time,
                                  const MqlTradeRequest &request,
                                  const int retcode) : CPendRequest(PEND_REQ_STATUS_OPEN,id,price,time,request,retcode) {}
                                  
//--- Supported deal properties (1) real, (2) integer
   virtual bool      SupportProperty(ENUM_PEND_REQ_PROP_INTEGER property);
   virtual bool      SupportProperty(ENUM_PEND_REQ_PROP_DOUBLE property);
   virtual bool      SupportProperty(ENUM_PEND_REQ_PROP_STRING property);
//--- Display a brief message with request data in the journal
   virtual void      PrintShort(void);
  };
//+------------------------------------------------------------------+
//| Return 'true' if an order supports a passed                      |
//| inteira; caso contrário, retorna false                           |
//+------------------------------------------------------------------+
bool CPendReqOpen::SupportProperty(ENUM_PEND_REQ_PROP_INTEGER property)
  {
   if(property==PEND_REQ_PROP_MQL_REQ_ORDER        ||
      property==PEND_REQ_PROP_MQL_REQ_POSITION     ||
      property==PEND_REQ_PROP_MQL_REQ_POSITION_BY  ||
      property==PEND_REQ_PROP_MQL_REQ_EXPIRATION   ||
      property==PEND_REQ_PROP_MQL_REQ_TYPE_TIME
     ) return false;
   return true;
  }
//+------------------------------------------------------------------+
//| Return 'true' if an order supports a passed                      |
//| real; caso contrário, retorna false                              |
//+------------------------------------------------------------------+
bool CPendReqOpen::SupportProperty(ENUM_PEND_REQ_PROP_DOUBLE property)
  {
   return(property==PEND_REQ_PROP_MQL_REQ_STOPLIMIT ? false : true);
  }
//+------------------------------------------------------------------+
//| Return 'true' if an order supports a passed                      |
//| string; retorna false caso contrário                             |
//+------------------------------------------------------------------+
bool CPendReqOpen::SupportProperty(ENUM_PEND_REQ_PROP_STRING property)
  {
   return true;
  }
//+------------------------------------------------------------------+
//| Display a brief message with request data in the journal         |
//+------------------------------------------------------------------+
void CPendReqOpen::PrintShort(void)
  {
   string params=this.GetProperty(PEND_REQ_PROP_MQL_REQ_SYMBOL)+" "+::DoubleToString(this.GetProperty(PEND_REQ_PROP_MQL_REQ_VOLUME),this.m_digits_lot)+" "+
                 OrderTypeDescription((ENUM_ORDER_TYPE)this.GetProperty(PEND_REQ_PROP_MQL_REQ_TYPE));
   string price=CMessage::Text(MSG_LIB_TEXT_REQUEST_PRICE)+" "+::DoubleToString(this.GetProperty(PEND_REQ_PROP_MQL_REQ_PRICE),this.m_digits);
   string sl=this.GetProperty(PEND_REQ_PROP_MQL_REQ_SL)>0 ? ", "+CMessage::Text(MSG_LIB_TEXT_REQUEST_SL)+" "+::DoubleToString(this.GetProperty(PEND_REQ_PROP_MQL_REQ_SL),this.m_digits) : "";
   string tp=this.GetProperty(PEND_REQ_PROP_MQL_REQ_TP)>0 ? ", "+CMessage::Text(MSG_LIB_TEXT_REQUEST_TP)+" "+::DoubleToString(this.GetProperty(PEND_REQ_PROP_MQL_REQ_TP),this.m_digits) : "";
   string time=this.IDDescription()+", "+CMessage::Text(MSG_LIB_TEXT_CREATED)+" "+TimeMSCtoString(this.GetProperty(PEND_REQ_PROP_TIME_CREATE));
   string attempts=CMessage::Text(MSG_LIB_TEXT_ATTEMPTS)+" "+(string)this.GetProperty(PEND_REQ_PROP_TOTAL);
   string wait=CMessage::Text(MSG_LIB_TEXT_WAIT)+" "+::TimeToString(this.GetProperty(PEND_REQ_PROP_WAITING)/1000,TIME_SECONDS);
   string end=CMessage::Text(MSG_LIB_TEXT_END)+" "+
              TimeMSCtoString(this.GetProperty(PEND_REQ_PROP_TIME_CREATE)+this.GetProperty(PEND_REQ_PROP_WAITING)*this.GetProperty(PEND_REQ_PROP_TOTAL));
   //---
   string message=CMessage::Text(MSG_LIB_TEXT_PEND_REQUEST_STATUS_OPEN)+": "+
   "\n- "+params+", "+price+sl+tp+
   "\n- "+time+", "+attempts+", "+wait+", "+end+"\n";
   ::Print(message);
  }
//+------------------------------------------------------------------+

O método é bastante primitivo. Tudo o que ele faz é, no seu construtor na lista de inicialização, transferir ao construtor do objeto base o status do objeto criado (abertura de posição) e todos os parâmetros de entrada do seu construtor:

//--- Constructor
   CPendReqOpen(const uchar id,
                const double price,
                const ulong time,
                const MqlTradeRequest &request,
                const int retcode) : CPendRequest(PEND_REQ_STATUS_OPEN,id,price,time,request,retcode) {}

Métodos virtuais que retornam o sinalizador para suportar o objeto de algumas propriedades inteiras, reais e de string:

//+------------------------------------------------------------------+
//| Return 'true' if an order supports a passed                      |
//| inteira; caso contrário, retorna false                           |
//+------------------------------------------------------------------+
bool CPendReqOpen::SupportProperty(ENUM_PEND_REQ_PROP_INTEGER property)
  {
   if(property==PEND_REQ_PROP_MQL_REQ_ORDER        ||
      property==PEND_REQ_PROP_MQL_REQ_POSITION     ||
      property==PEND_REQ_PROP_MQL_REQ_POSITION_BY  ||
      property==PEND_REQ_PROP_MQL_REQ_EXPIRATION   ||
      property==PEND_REQ_PROP_MQL_REQ_TYPE_TIME
     ) return false;
   return true;
  }
//+------------------------------------------------------------------+
//| Return 'true' if an order supports a passed                      |
//| real; caso contrário, retorna false                              |
//+------------------------------------------------------------------+
bool CPendReqOpen::SupportProperty(ENUM_PEND_REQ_PROP_DOUBLE property)
  {
   return(property==PEND_REQ_PROP_MQL_REQ_STOPLIMIT ? false : true);
  }
//+------------------------------------------------------------------+
//| Return 'true' if an order supports a passed                      |
//| string; retorna false caso contrário                             |
//+------------------------------------------------------------------+
bool CPendReqOpen::SupportProperty(ENUM_PEND_REQ_PROP_STRING property)
  {
   return true;
  }
//+------------------------------------------------------------------+

Se alguma propriedade não for suportada pelo objeto-herdeiro da ordem de negociação abstrata base, o método retornará false, caso contrário, true. Vamos ver como funciona tudo isso no segundo artigo da descrição da biblioteca ao considerar a criação de objetos de ordens e transações históricas.

Método virtual para criar e exibir uma breve descrição de uma ordem:

//+------------------------------------------------------------------+
//| Display a brief message with request data in the journal         |
//+------------------------------------------------------------------+
void CPendReqOpen::PrintShort(void)
  {
   string params=this.GetProperty(PEND_REQ_PROP_MQL_REQ_SYMBOL)+" "+::DoubleToString(this.GetProperty(PEND_REQ_PROP_MQL_REQ_VOLUME),this.m_digits_lot)+" "+
                 OrderTypeDescription((ENUM_ORDER_TYPE)this.GetProperty(PEND_REQ_PROP_MQL_REQ_TYPE));
   string price=CMessage::Text(MSG_LIB_TEXT_REQUEST_PRICE)+" "+::DoubleToString(this.GetProperty(PEND_REQ_PROP_MQL_REQ_PRICE),this.m_digits);
   string sl=this.GetProperty(PEND_REQ_PROP_MQL_REQ_SL)>0 ? ", "+CMessage::Text(MSG_LIB_TEXT_REQUEST_SL)+" "+::DoubleToString(this.GetProperty(PEND_REQ_PROP_MQL_REQ_SL),this.m_digits) : "";
   string tp=this.GetProperty(PEND_REQ_PROP_MQL_REQ_TP)>0 ? ", "+CMessage::Text(MSG_LIB_TEXT_REQUEST_TP)+" "+::DoubleToString(this.GetProperty(PEND_REQ_PROP_MQL_REQ_TP),this.m_digits) : "";
   string time=this.IDDescription()+", "+CMessage::Text(MSG_LIB_TEXT_CREATED)+" "+TimeMSCtoString(this.GetProperty(PEND_REQ_PROP_TIME_CREATE));
   string attempts=CMessage::Text(MSG_LIB_TEXT_ATTEMPTS)+" "+(string)this.GetProperty(PEND_REQ_PROP_TOTAL);
   string wait=CMessage::Text(MSG_LIB_TEXT_WAIT)+" "+::TimeToString(this.GetProperty(PEND_REQ_PROP_WAITING)/1000,TIME_SECONDS);
   string end=CMessage::Text(MSG_LIB_TEXT_END)+" "+
              TimeMSCtoString(this.GetProperty(PEND_REQ_PROP_TIME_CREATE)+this.GetProperty(PEND_REQ_PROP_WAITING)*this.GetProperty(PEND_REQ_PROP_TOTAL));
   //---
   string message=CMessage::Text(MSG_LIB_TEXT_PEND_REQUEST_STATUS_OPEN)+": "+
   "\n- "+params+", "+price+sl+tp+
   "\n- "+time+", "+attempts+", "+wait+", "+end+"\n";
   ::Print(message);
  }
//+------------------------------------------------------------------+

No método, são criadas as linhas de descrição de alguns parâmetros usados pelo objeto e a partir deles é gerada uma mensagem final, que é exibida no log. O método é virtual é implementado de maneira própria em cada um dos objetos-herdeiros do objeto base da ordem pendente.

Classe de objeto de uma ordem pendente para modificar ordens stop de uma posição aberta (arquivo de classe PendReqSLTP.mqh):

//+------------------------------------------------------------------+
//|                                                  PendReqSLTP.mqh |
//|                        Copyright 2019, MetaQuotes Software Corp. |
//|                             https://mql5.com/pt/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2019, MetaQuotes Software Corp."
#property link      "https://mql5.com/pt/users/artmedia70"
#property version   "1.00"
//+------------------------------------------------------------------+
//| Include files                                                    |
//+------------------------------------------------------------------+
#include "PendRequest.mqh"
//+------------------------------------------------------------------+
//| Pending request to modify position stop orders                   |
//+------------------------------------------------------------------+
class CPendReqSLTP : public CPendRequest
  {
public:
//--- Constructor
                     CPendReqSLTP(const uchar id,
                                  const double price,
                                  const ulong time,
                                  const MqlTradeRequest &request,
                                  const int retcode) : CPendRequest(PEND_REQ_STATUS_SLTP,id,price,time,request,retcode) {}
                                  
//--- Supported deal properties (1) real, (2) integer
   virtual bool      SupportProperty(ENUM_PEND_REQ_PROP_INTEGER property);
   virtual bool      SupportProperty(ENUM_PEND_REQ_PROP_DOUBLE property);
   virtual bool      SupportProperty(ENUM_PEND_REQ_PROP_STRING property);
//--- Display a brief message with request data in the journal
   virtual void      PrintShort(void);
  };
//+------------------------------------------------------------------+
//| Return 'true' if an order supports a passed                      |
//| inteira; caso contrário, retorna false                           |
//+------------------------------------------------------------------+
bool CPendReqSLTP::SupportProperty(ENUM_PEND_REQ_PROP_INTEGER property)
  {
   if(property==PEND_REQ_PROP_MQL_REQ_POSITION_BY  ||
      property==PEND_REQ_PROP_MQL_REQ_ORDER        ||
      property==PEND_REQ_PROP_MQL_REQ_EXPIRATION   ||
      property==PEND_REQ_PROP_MQL_REQ_DEVIATION    ||
      property==PEND_REQ_PROP_MQL_REQ_TYPE_FILLING ||
      property==PEND_REQ_PROP_MQL_REQ_TYPE_TIME
     ) return false;
   return true;
  }
//+------------------------------------------------------------------+
//| Return 'true' if an order supports a passed                      |
//| real; caso contrário, retorna false                              |
//+------------------------------------------------------------------+
bool CPendReqSLTP::SupportProperty(ENUM_PEND_REQ_PROP_DOUBLE property)
  {
   if(property==PEND_REQ_PROP_PRICE_CREATE         ||
      property==PEND_REQ_PROP_MQL_REQ_SL           ||
      property==PEND_REQ_PROP_MQL_REQ_TP
     ) return true;
   return false;
  }
//+------------------------------------------------------------------+
//| Return 'true' if an order supports a passed                      |
//| string; retorna false caso contrário                             |
//+------------------------------------------------------------------+
bool CPendReqSLTP::SupportProperty(ENUM_PEND_REQ_PROP_STRING property)
  {
   return true;
  }
//+------------------------------------------------------------------+
//| Display a brief message with request data in the journal         |
//+------------------------------------------------------------------+
void CPendReqSLTP::PrintShort(void)
  {
   string params=this.GetProperty(PEND_REQ_PROP_MQL_REQ_SYMBOL)+" "+::DoubleToString(this.GetProperty(PEND_REQ_PROP_MQL_REQ_VOLUME),this.m_digits_lot)+" "+
                 PositionTypeDescription((ENUM_POSITION_TYPE)this.GetProperty(PEND_REQ_PROP_MQL_REQ_TYPE))+" #"+(string)this.GetProperty(PEND_REQ_PROP_MQL_REQ_POSITION);
   string sl=this.GetProperty(PEND_REQ_PROP_MQL_REQ_SL)>0 ? ", "+CMessage::Text(MSG_LIB_TEXT_REQUEST_SL)+" "+::DoubleToString(this.GetProperty(PEND_REQ_PROP_MQL_REQ_SL),this.m_digits) : "";
   string tp=this.GetProperty(PEND_REQ_PROP_MQL_REQ_TP)>0 ? ", "+CMessage::Text(MSG_LIB_TEXT_REQUEST_TP)+" "+::DoubleToString(this.GetProperty(PEND_REQ_PROP_MQL_REQ_TP),this.m_digits) : "";
   string time=this.IDDescription()+", "+CMessage::Text(MSG_LIB_TEXT_CREATED)+" "+TimeMSCtoString(this.GetProperty(PEND_REQ_PROP_TIME_CREATE));
   string attempts=CMessage::Text(MSG_LIB_TEXT_ATTEMPTS)+" "+(string)this.GetProperty(PEND_REQ_PROP_TOTAL);
   string wait=CMessage::Text(MSG_LIB_TEXT_WAIT)+" "+::TimeToString(this.GetProperty(PEND_REQ_PROP_WAITING)/1000,TIME_SECONDS);
   string end=CMessage::Text(MSG_LIB_TEXT_END)+" "+
              TimeMSCtoString(this.GetProperty(PEND_REQ_PROP_TIME_CREATE)+this.GetProperty(PEND_REQ_PROP_WAITING)*this.GetProperty(PEND_REQ_PROP_TOTAL));
   //---
   string message=CMessage::Text(MSG_LIB_TEXT_PEND_REQUEST_STATUS_SLTP)+": "+
   "\n- "+params+sl+tp+
   "\n- "+time+", "+attempts+", "+wait+", "+end+"\n";
   ::Print(message);
  }
//+------------------------------------------------------------------+

Classe de objeto de uma ordem pendente para fechar uma posição (arquivo de classe PendReqClose.mqh):

//+------------------------------------------------------------------+
//|                                                 PendReqClose.mqh |
//|                        Copyright 2019, MetaQuotes Software Corp. |
//|                             https://mql5.com/pt/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2019, MetaQuotes Software Corp."
#property link      "https://mql5.com/pt/users/artmedia70"
#property version   "1.00"
//+------------------------------------------------------------------+
//| Include files                                                    |
//+------------------------------------------------------------------+
#include "PendRequest.mqh"
//+------------------------------------------------------------------+
//| Pending request to close a position                              |
//+------------------------------------------------------------------+
class CPendReqClose : public CPendRequest
  {
public:
//--- Constructor
                     CPendReqClose(const uchar id,
                                   const double price,
                                   const ulong time,
                                   const MqlTradeRequest &request,
                                   const int retcode) : CPendRequest(PEND_REQ_STATUS_CLOSE,id,price,time,request,retcode) {}
                                  
//--- Supported deal properties (1) real, (2) integer
   virtual bool      SupportProperty(ENUM_PEND_REQ_PROP_INTEGER property);
   virtual bool      SupportProperty(ENUM_PEND_REQ_PROP_DOUBLE property);
   virtual bool      SupportProperty(ENUM_PEND_REQ_PROP_STRING property);
//--- Display a brief message with request data in the journal
   virtual void      PrintShort(void);
  };
//+------------------------------------------------------------------+
//| Return 'true' if an order supports a passed                      |
//| inteira; caso contrário, retorna false                           |
//+------------------------------------------------------------------+
bool CPendReqClose::SupportProperty(ENUM_PEND_REQ_PROP_INTEGER property)
  {
   if((
      property==PEND_REQ_PROP_MQL_REQ_POSITION_BY  && 
      this.GetProperty(property)==0)               ||
      property==PEND_REQ_PROP_MQL_REQ_ORDER        ||
      property==PEND_REQ_PROP_MQL_REQ_EXPIRATION   ||
      property==PEND_REQ_PROP_MQL_REQ_TYPE_TIME
     ) return false;
   return true;
  }
//+------------------------------------------------------------------+
//| Return 'true' if an order supports a passed                      |
//| real; caso contrário, retorna false                              |
//+------------------------------------------------------------------+
bool CPendReqClose::SupportProperty(ENUM_PEND_REQ_PROP_DOUBLE property)
  {
   if(property==PEND_REQ_PROP_MQL_REQ_STOPLIMIT    ||
      property==PEND_REQ_PROP_MQL_REQ_SL           ||
      property==PEND_REQ_PROP_MQL_REQ_TP
     ) return false;
   return true;
  }
//+------------------------------------------------------------------+
//| Return 'true' if an order supports a passed                      |
//| string; retorna false caso contrário                             |
//+------------------------------------------------------------------+
bool CPendReqClose::SupportProperty(ENUM_PEND_REQ_PROP_STRING property)
  {
   return true;
  }
//+------------------------------------------------------------------+
//| Display a brief message with request data in the journal         |
//+------------------------------------------------------------------+
void CPendReqClose::PrintShort(void)
  {
   string params=this.GetProperty(PEND_REQ_PROP_MQL_REQ_SYMBOL)+" "+::DoubleToString(this.GetProperty(PEND_REQ_PROP_MQL_REQ_VOLUME),this.m_digits_lot)+" "+
                 PositionTypeDescription((ENUM_POSITION_TYPE)this.GetProperty(PEND_REQ_PROP_MQL_REQ_TYPE))+" #"+(string)this.GetProperty(PEND_REQ_PROP_MQL_REQ_POSITION);
   string pos_by=(this.GetProperty(PEND_REQ_PROP_MQL_REQ_POSITION_BY)>0 ? ", "+CMessage::Text(MSG_ORD_DEAL_OUT_BY)+" #"+(string)this.GetProperty(PEND_REQ_PROP_MQL_REQ_POSITION_BY) : "");
   string price=CMessage::Text(MSG_LIB_TEXT_REQUEST_PRICE)+" "+::DoubleToString(this.GetProperty(PEND_REQ_PROP_PRICE_CREATE),this.m_digits);
   string time=this.IDDescription()+", "+CMessage::Text(MSG_LIB_TEXT_CREATED)+" "+TimeMSCtoString(this.GetProperty(PEND_REQ_PROP_TIME_CREATE));
   string attempts=CMessage::Text(MSG_LIB_TEXT_ATTEMPTS)+" "+(string)this.GetProperty(PEND_REQ_PROP_TOTAL);
   string wait=CMessage::Text(MSG_LIB_TEXT_WAIT)+" "+::TimeToString(this.GetProperty(PEND_REQ_PROP_WAITING)/1000,TIME_SECONDS);
   string end=CMessage::Text(MSG_LIB_TEXT_END)+" "+
              TimeMSCtoString(this.GetProperty(PEND_REQ_PROP_TIME_CREATE)+this.GetProperty(PEND_REQ_PROP_WAITING)*this.GetProperty(PEND_REQ_PROP_TOTAL));
   //---
   string message=CMessage::Text(MSG_LIB_TEXT_PEND_REQUEST_STATUS_CLOSE)+": "+
   "\n- "+params+", "+price+pos_by+
   "\n- "+time+", "+attempts+", "+wait+", "+end+"\n";
   ::Print(message);
  }
//+------------------------------------------------------------------+

Classe de objeto de uma ordem pendente para colocar uma ordem pendente (arquivo de classe PendReqPlace.mqh):

//+------------------------------------------------------------------+
//|                                                 PendReqPlace.mqh |
//|                        Copyright 2019, MetaQuotes Software Corp. |
//|                             https://mql5.com/pt/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2019, MetaQuotes Software Corp."
#property link      "https://mql5.com/pt/users/artmedia70"
#property version   "1.00"
//+------------------------------------------------------------------+
//| Include files                                                    |
//+------------------------------------------------------------------+
#include "PendRequest.mqh"
//+------------------------------------------------------------------+
//| Pending request to place a pending order                         |
//+------------------------------------------------------------------+
class CPendReqPlace : public CPendRequest
  {
public:
//--- Constructor
                     CPendReqPlace(const uchar id,
                                   const double price,
                                   const ulong time,
                                   const MqlTradeRequest &request,
                                   const int retcode) : CPendRequest(PEND_REQ_STATUS_PLACE,id,price,time,request,retcode) {}
                                  
//--- Supported deal properties (1) real, (2) integer
   virtual bool      SupportProperty(ENUM_PEND_REQ_PROP_INTEGER property);
   virtual bool      SupportProperty(ENUM_PEND_REQ_PROP_DOUBLE property);
   virtual bool      SupportProperty(ENUM_PEND_REQ_PROP_STRING property);
//--- Display a brief message with request data in the journal
   virtual void      PrintShort(void);
  };
//+------------------------------------------------------------------+
//| Return 'true' if an order supports a passed                      |
//| inteira; caso contrário, retorna false                           |
//+------------------------------------------------------------------+
bool CPendReqPlace::SupportProperty(ENUM_PEND_REQ_PROP_INTEGER property)
  {
   if(property==PEND_REQ_PROP_MQL_REQ_ORDER        ||
      property==PEND_REQ_PROP_MQL_REQ_POSITION     ||
      property==PEND_REQ_PROP_MQL_REQ_POSITION_BY  ||
      property==PEND_REQ_PROP_MQL_REQ_DEVIATION
     ) return false;
   return true;
  }
//+------------------------------------------------------------------+
//| Return 'true' if an order supports a passed                      |
//| real; caso contrário, retorna false                              |
//+------------------------------------------------------------------+
bool CPendReqPlace::SupportProperty(ENUM_PEND_REQ_PROP_DOUBLE property)
  {
   return true;
  }
//+------------------------------------------------------------------+
//| Return 'true' if an order supports a passed                      |
//| string; retorna false caso contrário                             |
//+------------------------------------------------------------------+
bool CPendReqPlace::SupportProperty(ENUM_PEND_REQ_PROP_STRING property)
  {
   return true;
  }
//+------------------------------------------------------------------+
//| Display a brief message with request data in the journal         |
//+------------------------------------------------------------------+
void CPendReqPlace::PrintShort(void)
  {
   string params=this.GetProperty(PEND_REQ_PROP_MQL_REQ_SYMBOL)+" "+::DoubleToString(this.GetProperty(PEND_REQ_PROP_MQL_REQ_VOLUME),this.m_digits_lot)+" "+
                 OrderTypeDescription((ENUM_ORDER_TYPE)this.GetProperty(PEND_REQ_PROP_MQL_REQ_TYPE));
   string price=CMessage::Text(MSG_LIB_TEXT_REQUEST_PRICE)+" "+::DoubleToString(this.GetProperty(PEND_REQ_PROP_MQL_REQ_PRICE),this.m_digits);
   string stoplimit=this.GetProperty(PEND_REQ_PROP_MQL_REQ_STOPLIMIT)>0 ? ", "+CMessage::Text(MSG_LIB_TEXT_REQUEST_STOPLIMIT)+" "+::DoubleToString(this.GetProperty(PEND_REQ_PROP_MQL_REQ_STOPLIMIT),this.m_digits) : "";
   string sl=this.GetProperty(PEND_REQ_PROP_MQL_REQ_SL)>0 ? ", "+CMessage::Text(MSG_LIB_TEXT_REQUEST_SL)+" "+::DoubleToString(this.GetProperty(PEND_REQ_PROP_MQL_REQ_SL),this.m_digits) : "";
   string tp=this.GetProperty(PEND_REQ_PROP_MQL_REQ_TP)>0 ? ", "+CMessage::Text(MSG_LIB_TEXT_REQUEST_TP)+" "+::DoubleToString(this.GetProperty(PEND_REQ_PROP_MQL_REQ_TP),this.m_digits) : "";
   string time=this.IDDescription()+", "+CMessage::Text(MSG_LIB_TEXT_CREATED)+" "+TimeMSCtoString(this.GetProperty(PEND_REQ_PROP_TIME_CREATE));
   string attempts=CMessage::Text(MSG_LIB_TEXT_ATTEMPTS)+" "+(string)this.GetProperty(PEND_REQ_PROP_TOTAL);
   string wait=CMessage::Text(MSG_LIB_TEXT_WAIT)+" "+::TimeToString(this.GetProperty(PEND_REQ_PROP_WAITING)/1000,TIME_SECONDS);
   string end=CMessage::Text(MSG_LIB_TEXT_END)+" "+
              TimeMSCtoString(this.GetProperty(PEND_REQ_PROP_TIME_CREATE)+this.GetProperty(PEND_REQ_PROP_WAITING)*this.GetProperty(PEND_REQ_PROP_TOTAL));
   //---
   string message=CMessage::Text(MSG_LIB_TEXT_PEND_REQUEST_STATUS_PLACE)+": "+
   "\n- "+params+", "+price+stoplimit+sl+tp+
   "\n- "+time+", "+attempts+", "+wait+", "+end+"\n";
   ::Print(message);
  }
//+------------------------------------------------------------------+

Classe de objeto de ordem pendente para modificar os parâmetros de uma ordem pendente colocada (arquivo de classe PendReqModify.mqh):

//+------------------------------------------------------------------+
//|                                                PendReqModify.mqh |
//|                        Copyright 2019, MetaQuotes Software Corp. |
//|                             https://mql5.com/pt/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2019, MetaQuotes Software Corp."
#property link      "https://mql5.com/pt/users/artmedia70"
#property version   "1.00"
//+------------------------------------------------------------------+
//| Include files                                                    |
//+------------------------------------------------------------------+
#include "PendRequest.mqh"
//+------------------------------------------------------------------+
//| Pending request to modify pending order parameters               |
//+------------------------------------------------------------------+
class CPendReqModify : public CPendRequest
  {
public:
//--- Constructor
                     CPendReqModify(const uchar id,
                                    const double price,
                                    const ulong time,
                                    const MqlTradeRequest &request,
                                    const int retcode) : CPendRequest(PEND_REQ_STATUS_MODIFY,id,price,time,request,retcode) {}
                                  
//--- Supported deal properties (1) real, (2) integer
   virtual bool      SupportProperty(ENUM_PEND_REQ_PROP_INTEGER property);
   virtual bool      SupportProperty(ENUM_PEND_REQ_PROP_DOUBLE property);
   virtual bool      SupportProperty(ENUM_PEND_REQ_PROP_STRING property);
//--- Display a brief message with request data in the journal
   virtual void      PrintShort(void);
  };
//+------------------------------------------------------------------+
//| Return 'true' if an order supports a passed                      |
//| inteira; caso contrário, retorna false                           |
//+------------------------------------------------------------------+
bool CPendReqModify::SupportProperty(ENUM_PEND_REQ_PROP_INTEGER property)
  {
   if(property==PEND_REQ_PROP_MQL_REQ_POSITION     ||
      property==PEND_REQ_PROP_MQL_REQ_POSITION_BY  ||
      property==PEND_REQ_PROP_MQL_REQ_DEVIATION
     ) return false;
   return true;
  }
//+------------------------------------------------------------------+
//| Return 'true' if an order supports a passed                      |
//| real; caso contrário, retorna false                              |
//+------------------------------------------------------------------+
bool CPendReqModify::SupportProperty(ENUM_PEND_REQ_PROP_DOUBLE property)
  {
   return(property==PEND_REQ_PROP_MQL_REQ_VOLUME ? false : true);
  }
//+------------------------------------------------------------------+
//| Return 'true' if an order supports a passed                      |
//| string; retorna false caso contrário                             |
//+------------------------------------------------------------------+
bool CPendReqModify::SupportProperty(ENUM_PEND_REQ_PROP_STRING property)
  {
   return true;
  }
//+------------------------------------------------------------------+
//| Display a brief message with request data in the journal         |
//+------------------------------------------------------------------+
void CPendReqModify::PrintShort(void)
  {
   string params=this.GetProperty(PEND_REQ_PROP_MQL_REQ_SYMBOL)+" "+::DoubleToString(this.GetProperty(PEND_REQ_PROP_MQL_REQ_VOLUME),this.m_digits_lot)+" "+
                 OrderTypeDescription((ENUM_ORDER_TYPE)this.GetProperty(PEND_REQ_PROP_MQL_REQ_TYPE))+" #"+(string)this.GetProperty(PEND_REQ_PROP_MQL_REQ_ORDER);
   string price=CMessage::Text(MSG_LIB_TEXT_REQUEST_PRICE)+" "+::DoubleToString(this.GetProperty(PEND_REQ_PROP_MQL_REQ_PRICE),this.m_digits);
   string stoplimit=this.GetProperty(PEND_REQ_PROP_MQL_REQ_STOPLIMIT)>0 ? ", "+CMessage::Text(MSG_LIB_TEXT_REQUEST_STOPLIMIT)+" "+::DoubleToString(this.GetProperty(PEND_REQ_PROP_MQL_REQ_STOPLIMIT),this.m_digits) : "";
   string sl=this.GetProperty(PEND_REQ_PROP_MQL_REQ_SL)>0 ? ", "+CMessage::Text(MSG_LIB_TEXT_REQUEST_SL)+" "+::DoubleToString(this.GetProperty(PEND_REQ_PROP_MQL_REQ_SL),this.m_digits) : "";
   string tp=this.GetProperty(PEND_REQ_PROP_MQL_REQ_TP)>0 ? ", "+CMessage::Text(MSG_LIB_TEXT_REQUEST_TP)+" "+::DoubleToString(this.GetProperty(PEND_REQ_PROP_MQL_REQ_TP),this.m_digits) : "";
   string expiration=this.GetProperty(PEND_REQ_PROP_MQL_REQ_EXPIRATION)>0 ? this.MqlReqExpirationDescription() : "";
   string type_filling=this.GetProperty(PEND_REQ_PROP_MQL_REQ_TYPE_FILLING)>WRONG_VALUE ? "\n- "+this.MqlReqTypeFillingDescription() : "";
   string type_time=this.GetProperty(PEND_REQ_PROP_MQL_REQ_TYPE_TIME)>WRONG_VALUE ? "\n- "+this.MqlReqTypeTimeDescription() : "";
   string time=this.IDDescription()+", "+CMessage::Text(MSG_LIB_TEXT_CREATED)+" "+TimeMSCtoString(this.GetProperty(PEND_REQ_PROP_TIME_CREATE));
   string attempts=CMessage::Text(MSG_LIB_TEXT_ATTEMPTS)+" "+(string)this.GetProperty(PEND_REQ_PROP_TOTAL);
   string wait=CMessage::Text(MSG_LIB_TEXT_WAIT)+" "+::TimeToString(this.GetProperty(PEND_REQ_PROP_WAITING)/1000,TIME_SECONDS);
   string end=CMessage::Text(MSG_LIB_TEXT_END)+" "+
              TimeMSCtoString(this.GetProperty(PEND_REQ_PROP_TIME_CREATE)+this.GetProperty(PEND_REQ_PROP_WAITING)*this.GetProperty(PEND_REQ_PROP_TOTAL));
   //---
   string message=CMessage::Text(MSG_LIB_TEXT_PEND_REQUEST_STATUS_MODIFY)+": "+
   "\n- "+params+", "+price+stoplimit+sl+tp+expiration+type_filling+type_time+
   "\n- "+time+", "+attempts+", "+wait+", "+end+"\n";
   ::Print(message);
  }
//+------------------------------------------------------------------+

Classe de objeto de uma ordem pendente para excluir uma ordem pendente (arquivo de classe PendReqRemove.mqh):

//+------------------------------------------------------------------+
//|                                                PendReqRemove.mqh |
//|                        Copyright 2019, MetaQuotes Software Corp. |
//|                             https://mql5.com/pt/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2019, MetaQuotes Software Corp."
#property link      "https://mql5.com/pt/users/artmedia70"
#property version   "1.00"
//+------------------------------------------------------------------+
//| Include files                                                    |
//+------------------------------------------------------------------+
#include "PendRequest.mqh"
//+------------------------------------------------------------------+
//| Pending request to remove a pending order                        |
//+------------------------------------------------------------------+
class CPendReqRemove : public CPendRequest
  {
public:
//--- Constructor
                     CPendReqRemove(const uchar id,
                                    const double price,
                                    const ulong time,
                                    const MqlTradeRequest &request,
                                    const int retcode) : CPendRequest(PEND_REQ_STATUS_REMOVE,id,price,time,request,retcode) {}
                                  
//--- Supported deal properties (1) real, (2) integer
   virtual bool      SupportProperty(ENUM_PEND_REQ_PROP_INTEGER property);
   virtual bool      SupportProperty(ENUM_PEND_REQ_PROP_DOUBLE property);
   virtual bool      SupportProperty(ENUM_PEND_REQ_PROP_STRING property);
//--- Display a brief message with request data in the journal
   virtual void      PrintShort(void);
  };
//+------------------------------------------------------------------+
//| Return 'true' if an order supports a passed                      |
//| inteira; caso contrário, retorna false                           |
//+------------------------------------------------------------------+
bool CPendReqRemove::SupportProperty(ENUM_PEND_REQ_PROP_INTEGER property)
  {
   return(property>PEND_REQ_PROP_MQL_REQ_ORDER ? false : true);
  }
//+------------------------------------------------------------------+
//| Return 'true' if an order supports a passed                      |
//| real; caso contrário, retorna false                              |
//+------------------------------------------------------------------+
bool CPendReqRemove::SupportProperty(ENUM_PEND_REQ_PROP_DOUBLE property)
  {
   return(property==PEND_REQ_PROP_PRICE_CREATE || property==PEND_REQ_PROP_MQL_REQ_PRICE ? true : false);
  }
//+------------------------------------------------------------------+
//| Return 'true' if an order supports a passed                      |
//| string; retorna false caso contrário                             |
//+------------------------------------------------------------------+
bool CPendReqRemove::SupportProperty(ENUM_PEND_REQ_PROP_STRING property)
  {
   return true;
  }
//+------------------------------------------------------------------+
//| Display a brief message with request data in the journal         |
//+------------------------------------------------------------------+
void CPendReqRemove::PrintShort(void)
  {
   string params=this.GetProperty(PEND_REQ_PROP_MQL_REQ_SYMBOL)+" "+::DoubleToString(this.GetProperty(PEND_REQ_PROP_MQL_REQ_VOLUME),this.m_digits_lot)+" "+
                 OrderTypeDescription((ENUM_ORDER_TYPE)this.GetProperty(PEND_REQ_PROP_MQL_REQ_TYPE))+" #"+(string)this.GetProperty(PEND_REQ_PROP_MQL_REQ_ORDER);
   string price=CMessage::Text(MSG_LIB_TEXT_REQUEST_PRICE)+" "+::DoubleToString(this.GetProperty(PEND_REQ_PROP_MQL_REQ_PRICE),this.m_digits);
   string stoplimit=this.GetProperty(PEND_REQ_PROP_MQL_REQ_STOPLIMIT)>0 ? ", "+CMessage::Text(MSG_LIB_TEXT_REQUEST_STOPLIMIT)+" "+::DoubleToString(this.GetProperty(PEND_REQ_PROP_MQL_REQ_STOPLIMIT),this.m_digits) : "";
   string time=this.IDDescription()+", "+CMessage::Text(MSG_LIB_TEXT_CREATED)+" "+TimeMSCtoString(this.GetProperty(PEND_REQ_PROP_TIME_CREATE));
   string attempts=CMessage::Text(MSG_LIB_TEXT_ATTEMPTS)+" "+(string)this.GetProperty(PEND_REQ_PROP_TOTAL);
   string wait=CMessage::Text(MSG_LIB_TEXT_WAIT)+" "+::TimeToString(this.GetProperty(PEND_REQ_PROP_WAITING)/1000,TIME_SECONDS);
   string end=CMessage::Text(MSG_LIB_TEXT_END)+" "+
              TimeMSCtoString(this.GetProperty(PEND_REQ_PROP_TIME_CREATE)+this.GetProperty(PEND_REQ_PROP_WAITING)*this.GetProperty(PEND_REQ_PROP_TOTAL));
   //---
   string message=CMessage::Text(MSG_LIB_TEXT_PEND_REQUEST_STATUS_REMOVE)+": "+
   "\n- "+params+", "+price+stoplimit+
   "\n- "+time+", "+attempts+", "+wait+", "+end+"\n";
   ::Print(message);
  }
//+------------------------------------------------------------------+

A característica distintiva mais importante de todas essas classes é a transferência do status da ordem pendente para o construtor do objeto pai. É esse status que determina que tipo de operação de negociação realizará cada um desses objetos. Os métodos de classe restantes servem apenas para fins auxiliares e não afetam o resultado da negociação.

Terminamos aqui a criação de novas de ordens de negociação pendentes.
Agora é preciso remover a classe de ordem pendente que criamos temporariamente do arquivo da classe de negociação e fazer correções adicionais para trabalhar com novos objetos de ordens de negociação pendentes.

Abrimos o arquivo Trading.mqh e removemos de sua listagem a classe completamente antiga da ordem pendente:

//+------------------------------------------------------------------+
//|                                                      Trading.mqh |
//|                        Copyright 2019, MetaQuotes Software Corp. |
//|                             https://mql5.com/pt/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2019, MetaQuotes Software Corp."
#property link      "https://mql5.com/pt/users/artmedia70"
#property version   "1.00"
//+------------------------------------------------------------------+
//| Include files                                                    |
//+------------------------------------------------------------------+
#include <Arrays\ArrayInt.mqh>
#include "Objects\Trade\TradeObj.mqh"
#include "Collections\AccountsCollection.mqh"
#include "Collections\SymbolsCollection.mqh"
#include "Collections\MarketCollection.mqh"
#include "Collections\HistoryCollection.mqh"
#include "Collections\EventsCollection.mqh"
//+-----------------------------------------------------------------+
//| Pending request object class                                     |
//+------------------------------------------------------------------+
class CPendingReq : public CObject
  {
private:
   MqlTradeRequest      m_request;                       // Trade request structure
   uchar                m_id;                            // Trading request ID
   int                  m_type;                          // Pending request type
   int                  m_retcode;                       // Result a request is based on
   double               m_price_create;                  // Price at the moment of a request generation
   ulong                m_time_create;                   // Request generation time
   ulong                m_time_activate;                 // Next attempt activation time
   ulong                m_waiting_msc;                   // Waiting time between requests
   uchar                m_current_attempt;               // Current attempt index
   uchar                m_total_attempts;                // Number of attempts
//--- Copy trading request data
   void                 CopyRequest(const MqlTradeRequest &request)  { this.m_request=request;        }
//--- Compare CPendingReq objects by IDs
   virtual int          Compare(const CObject *node,const int mode=0) const;

public:
//--- Return (1) the request structure, (2) the price at the moment of the request generation,
//--- (3) request generation time, (4) next attempt activation time,
//--- (5) waiting time between requests, (6) current attempt index,
//--- (7) number of attempts, (8) request ID
//--- (9) result a request is based on,
//--- (10) order ticket, (11) position ticket, (12) trading operation type
   MqlTradeRequest      MqlRequest(void)                       const { return this.m_request;         }
   double               PriceCreate(void)                      const { return this.m_price_create;    }
   ulong                TimeCreate(void)                       const { return this.m_time_create;     }
   ulong                TimeActivate(void)                     const { return this.m_time_activate;   }
   ulong                WaitingMSC(void)                       const { return this.m_waiting_msc;     }
   uchar                CurrentAttempt(void)                   const { return this.m_current_attempt; }
   uchar                TotalAttempts(void)                    const { return this.m_total_attempts;  }
   uchar                ID(void)                               const { return this.m_id;              }
   int                  Retcode(void)                          const { return this.m_retcode;         }
   ulong                Order(void)                            const { return this.m_request.order;   }
   ulong                Position(void)                         const { return this.m_request.position;}
   ENUM_TRADE_REQUEST_ACTIONS Action(void)                     const { return this.m_request.action;  }

//--- Set (1) the price when creating a request, (2) request creation time,
//--- (3) current attempt time, (4) waiting time between requests,
//--- (5) current attempt index, (6) number of attempts, (7) ID,
//--- (8) order ticket, (9) position ticket
   void                 SetPriceCreate(const double price)           { this.m_price_create=price;     }
   void                 SetTimeCreate(const ulong time)              { this.m_time_create=time;       }
   void                 SetTimeActivate(const ulong time)            { this.m_time_activate=time;     }
   void                 SetWaitingMSC(const ulong miliseconds)       { this.m_waiting_msc=miliseconds;}
   void                 SetCurrentAttempt(const uchar number)        { this.m_current_attempt=number; }
   void                 SetTotalAttempts(const uchar number)         { this.m_total_attempts=number;  }
   void                 SetID(const uchar id)                        { this.m_id=id;                  }
   void                 SetOrder(const ulong ticket)                 { this.m_request.order=ticket;   }
   void                 SetPosition(const ulong ticket)              { this.m_request.position=ticket;}
   
//--- Return the description of the (1) request structure, (2) the price at the moment of the request generation,
//--- (3) request generation time, (4) current attempt time,
//--- (5) waiting time between requests, (6) current attempt index,
//--- (7) number of attempts, (8) request ID
   string               MqlRequestDescription(void)            const { return RequestActionDescription(this.m_request); }
   string               TypeDescription(void)                  const
                          { 
                           return CMessage::Text(MSG_LIB_TEXT_PEND_REQUEST_TYPE) +
                             (this.Type()==PENDING_REQUEST_ID_TYPE_ERR           ?
                              CMessage::Text(MSG_LIB_TEXT_PEND_REQUEST_BY_ERROR) :
                              CMessage::Text(MSG_LIB_TEXT_PEND_REQUEST_BY_REQUEST)
                             );
                          }
   string               PriceCreateDescription(void)           const 
                          {
                           return CMessage::Text(MSG_LIB_TEXT_PEND_REQUEST_PRICE_CREATE)+": "+
                                  ::DoubleToString(this.PriceCreate(),(int)::SymbolInfoInteger(this.m_request.symbol,SYMBOL_DIGITS));
                          }
   string               TimeCreateDescription(void)            const { return CMessage::Text(MSG_LIB_TEXT_PEND_REQUEST_TIME_CREATE)+TimeMSCtoString(this.TimeCreate());    }
   string               TimeActivateDescription(void)          const { return CMessage::Text(MSG_LIB_TEXT_PEND_REQUEST_TIME_ACTIVATE)+TimeMSCtoString(this.TimeActivate());}
   string               WaitingMSCDescription(void)            const { return CMessage::Text(MSG_LIB_TEXT_PEND_REQUEST_WAITING)+(string)this.WaitingMSC();                 }
   string               CurrentAttemptDescription(void)        const 
                          {
                           return
                             (CMessage::Text(MSG_LIB_TEXT_PEND_REQUEST_CURRENT_ATTEMPT)+
                              (this.CurrentAttempt()==0 ? CMessage::Text(MSG_LIB_TEXT_PEND_REQUEST_WAITING_ONSET) : (string)this.CurrentAttempt())
                             );
                          }
   string               TotalAttemptsDescription(void)         const { return CMessage::Text(MSG_LIB_TEXT_PEND_REQUEST_TOTAL_ATTEMPTS)+(string)this.TotalAttempts();       }
   string               IdDescription(void)                    const { return CMessage::Text(MSG_LIB_TEXT_PEND_REQUEST_ID)+"#"+(string)this.ID();                          }
   string               RetcodeDescription(void)               const { return CMessage::Text(MSG_LIB_TEXT_PEND_REQUEST_RETCODE)+(string)this.Retcode();                    }
   string               ReasonDescription(void)                const { return CMessage::Text(this.m_retcode);  }

//--- Return a request type
   virtual int          Type(void)                             const { return this.m_type;   }
//--- Display request data in the journal
   void                 Print(void);
//--- Constructors
                        CPendingReq(void){;}
                        CPendingReq(const uchar id,const double price,const ulong time,const MqlTradeRequest &request,const int retcode);
  };
//+------------------------------------------------------------------+
//| Parametric constructor                                           |
//+------------------------------------------------------------------+
CPendingReq::CPendingReq(const uchar id,const double price,const ulong time,const MqlTradeRequest &request,const int retcode) : m_price_create(price),
                                                                                                                                m_time_create(time),
                                                                                                                                m_id(id),
                                                                                                                                m_retcode(retcode)
  {
   this.CopyRequest(request);
   this.m_type=(retcode>0 ? PENDING_REQUEST_ID_TYPE_ERR : PENDING_REQUEST_ID_TYPE_REQ);
  }
//+------------------------------------------------------------------+
//| Compare CPendingReq objects by properties                        |
//+------------------------------------------------------------------+
int CPendingReq::Compare(const CObject *node,const int mode=0) const
  {
   const CPendingReq *compared_req=node;
   return
     (
      //--- Compare by ID
      mode==SORT_BY_PEND_REQ_ID        ?  
      (this.ID()>compared_req.ID()     ? 1 : this.ID()<compared_req.ID() ? -1 : 0)     :
      //--- Compare by type
      mode==SORT_BY_PEND_REQ_TYPE      ?  
      (this.Type()>compared_req.Type() ? 1 : this.Type()<compared_req.Type() ? -1 : 0) :
      //--- Compare by ticket
      (
       //--- modifying position sl, tp, opening/closing a position or closing by an opposite one
       this.m_request.action==TRADE_ACTION_SLTP    || this.m_request.action==TRADE_ACTION_DEAL     || this.m_request.action==TRADE_ACTION_CLOSE_BY ?
       (this.m_request.position>compared_req.m_request.position ? 1 : this.m_request.position<compared_req.m_request.position ? -1 : 0)            :
       //--- modifying parameters, placing/removing a pending order
       this.m_request.action==TRADE_ACTION_MODIFY  || this.m_request.action==TRADE_ACTION_PENDING  || this.m_request.action==TRADE_ACTION_REMOVE   ?
       (this.m_request.order>compared_req.m_request.order ? 1 : this.m_request.order<compared_req.m_request.order ? -1 : 0)                        : 
       //--- otherwise
       0
      )
     );
  }
//+------------------------------------------------------------------+
//| Display request data in the journal                              |
//+------------------------------------------------------------------+
void CPendingReq::Print(void)
  {
   string action=" - "+RequestActionDescription(this.m_request)+"\n";
   string symbol="",order="",volume="",price="",stoplimit="",sl="",tp="",deviation="",type="",type_filling="";
   string type_time="",expiration="",position="",position_by="",magic="",comment="",request_data="";
   string type_req=" - "+this.TypeDescription()+"\n";
   
   if(this.m_request.action==TRADE_ACTION_DEAL)
     {
      symbol=" - "+RequestSymbolDescription(this.m_request)+"\n";
      volume=" - "+RequestVolumeDescription(this.m_request)+"\n";
      price=" - "+RequestPriceDescription(this.m_request)+"\n";
      sl=" - "+RequestStopLossDescription(this.m_request)+"\n";
      tp=" - "+RequestTakeProfitDescription(this.m_request)+"\n";
      deviation=" - "+RequestDeviationDescription(this.m_request)+"\n";
      type=" - "+RequestTypeDescription(this.m_request)+"\n";
      type_filling=" - "+RequestTypeFillingDescription(this.m_request)+"\n";
      magic=" - "+RequestMagicDescription(this.m_request)+"\n";
      comment=" - "+RequestCommentDescription(this.m_request)+"\n";
      request_data=
        ("================== "+
         CMessage::Text(MSG_LIB_TEXT_REQUEST_DATAS)+" ==================\n"+
         action+symbol+volume+price+sl+tp+deviation+type+type_filling+magic+comment+
         " ==================\n"
        );
     }
   else if(this.m_request.action==TRADE_ACTION_SLTP)
     {
      symbol=" - "+RequestSymbolDescription(this.m_request)+"\n";
      sl=" - "+RequestStopLossDescription(this.m_request)+"\n";
      tp=" - "+RequestTakeProfitDescription(this.m_request)+"\n";
      position=" - "+RequestPositionDescription(this.m_request)+"\n";
      request_data=
        ("================== "+
         CMessage::Text(MSG_LIB_TEXT_REQUEST_DATAS)+" ==================\n"+
         action+symbol+sl+tp+position+
         " ==================\n"
        );
     }
   else if(this.m_request.action==TRADE_ACTION_PENDING)
     {
      symbol=" - "+RequestSymbolDescription(this.m_request)+"\n";
      volume=" - "+RequestVolumeDescription(this.m_request)+"\n";
      price=" - "+RequestPriceDescription(this.m_request)+"\n";
      stoplimit=" - "+RequestStopLimitDescription(this.m_request)+"\n";
      sl=" - "+RequestStopLossDescription(this.m_request)+"\n";
      tp=" - "+RequestTakeProfitDescription(this.m_request)+"\n";
      type=" - "+RequestTypeDescription(this.m_request)+"\n";
      type_filling=" - "+RequestTypeFillingDescription(this.m_request)+"\n";
      type_time=" - "+RequestTypeTimeDescription(this.m_request)+"\n";
      expiration=" - "+RequestExpirationDescription(this.m_request)+"\n";
      magic=" - "+RequestMagicDescription(this.m_request)+"\n";
      comment=" - "+RequestCommentDescription(this.m_request)+"\n";
      request_data=
        ("================== "+
         CMessage::Text(MSG_LIB_TEXT_REQUEST_DATAS)+" ==================\n"+
         action+symbol+volume+price+stoplimit+sl+tp+type+type_filling+type_time+expiration+magic+comment+
         " ==================\n"
        );
     }
   else if(this.m_request.action==TRADE_ACTION_MODIFY)
     {
      order=" - "+RequestOrderDescription(this.m_request)+"\n";
      price=" - "+RequestPriceDescription(this.m_request)+"\n";
      sl=" - "+RequestStopLossDescription(this.m_request)+"\n";
      tp=" - "+RequestTakeProfitDescription(this.m_request)+"\n";
      type_time=" - "+RequestTypeTimeDescription(this.m_request)+"\n";
      expiration=" - "+RequestExpirationDescription(this.m_request)+"\n";
      request_data=
        ("================== "+
         CMessage::Text(MSG_LIB_TEXT_REQUEST_DATAS)+" ==================\n"+
         action+order+price+sl+tp+type_time+expiration+
         " ==================\n"
        );
     }
   else if(this.m_request.action==TRADE_ACTION_REMOVE)
     {
      order=" - "+RequestOrderDescription(this.m_request)+"\n";
      request_data=
        ("================== "+
         CMessage::Text(MSG_LIB_TEXT_REQUEST_DATAS)+" ==================\n"+
         action+order+
         " ==================\n"
        );
     }
   else if(this.m_request.action==TRADE_ACTION_CLOSE_BY)
     {
      position=" - "+RequestPositionDescription(this.m_request)+"\n";
      position_by=" - "+RequestPositionByDescription(this.m_request)+"\n";
      magic=" - "+RequestMagicDescription(this.m_request)+"\n";
      request_data=
        ("================== "+
         CMessage::Text(MSG_LIB_TEXT_REQUEST_DATAS)+" ==================\n"+
         action+position+position_by+magic+
         " ==================\n"
        );
     }
   string datas=
     (
      " - "+this.TypeDescription()+"\n"+
      " - "+this.IdDescription()+"\n"+
      " - "+this.RetcodeDescription()+" \""+this.ReasonDescription()+"\"\n"+
      " - "+this.TimeCreateDescription()+"\n"+
      " - "+this.PriceCreateDescription()+"\n"+
      " - "+this.TimeActivateDescription()+"\n"+
      " - "+this.WaitingMSCDescription()+" ("+TimeToString(this.WaitingMSC()/1000,TIME_MINUTES|TIME_SECONDS)+")"+"\n"+
      " - "+this.CurrentAttemptDescription()+"\n"+
      " - "+this.TotalAttemptsDescription()+"\n"
     );
   ::Print("================== ",CMessage::Text(MSG_LIB_TEXT_PEND_REQUEST_DATAS)," ==================\n",datas,request_data);
  }
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Trading class                                                    |
//+------------------------------------------------------------------+
class CTrading
  {

Para que a classe de negociação veja objetos das novas classes de ordens pendentes, vamos anexá-los à listagem do arquivo da classe de negociação:

//+------------------------------------------------------------------+
//|                                                      Trading.mqh |
//|                        Copyright 2019, MetaQuotes Software Corp. |
//|                             https://mql5.com/pt/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2019, MetaQuotes Software Corp."
#property link      "https://mql5.com/pt/users/artmedia70"
#property version   "1.00"
//+------------------------------------------------------------------+
//| Include files                                                    |
//+------------------------------------------------------------------+
#include <Arrays\ArrayInt.mqh>
#include "Objects\Trade\TradeObj.mqh"
#include "Objects\PendRequest\PendReqOpen.mqh"
#include "Objects\PendRequest\PendReqSLTP.mqh"
#include "Objects\PendRequest\PendReqClose.mqh"
#include "Objects\PendRequest\PendReqPlace.mqh"
#include "Objects\PendRequest\PendReqModify.mqh"
#include "Objects\PendRequest\PendReqRemove.mqh"
#include "Collections\AccountsCollection.mqh"
#include "Collections\SymbolsCollection.mqh"
#include "Collections\MarketCollection.mqh"
#include "Collections\HistoryCollection.mqh"
#include "Collections\EventsCollection.mqh"
//+------------------------------------------------------------------+

Agora, ao método de criação de uma nova ordem pendente transferimos adicionalmente o status da ordem de negociação criada.
Inserimos o status na declaração do método:

//--- Create a pending request
   bool                 CreatePendingRequest(const ENUM_PEND_REQ_STATUS status,
                                             const uchar id,
                                             const uchar attempts,
                                             const ulong wait,
                                             const MqlTradeRequest &request,
                                             const int retcode,
                                             CSymbol *symbol_obj);

Ajustamos a implementação do método para criar uma nova ordem pendente:

//+------------------------------------------------------------------+
//| Create a pending request                                         |
//+------------------------------------------------------------------+
bool CTrading::CreatePendingRequest(const ENUM_PEND_REQ_STATUS status,
                                    const uchar id,
                                    const uchar attempts,
                                    const ulong wait,
                                    const MqlTradeRequest &request,
                                    const int retcode,
                                    CSymbol *symbol_obj)
  {
   //--- Create a new pending request object depending on a request status
   CPendRequest *req_obj=NULL;
   switch(status)
     {
      case PEND_REQ_STATUS_OPEN     : req_obj=new CPendReqOpen(id,symbol_obj.BidLast(),symbol_obj.Time(),request,retcode);    break;
      case PEND_REQ_STATUS_CLOSE    : req_obj=new CPendReqClose(id,symbol_obj.BidLast(),symbol_obj.Time(),request,retcode);   break;
      case PEND_REQ_STATUS_SLTP     : req_obj=new CPendReqSLTP(id,symbol_obj.BidLast(),symbol_obj.Time(),request,retcode);    break;
      case PEND_REQ_STATUS_PLACE    : req_obj=new CPendReqPlace(id,symbol_obj.BidLast(),symbol_obj.Time(),request,retcode);   break;
      case PEND_REQ_STATUS_REMOVE   : req_obj=new CPendReqRemove(id,symbol_obj.BidLast(),symbol_obj.Time(),request,retcode);  break;
      case PEND_REQ_STATUS_MODIFY   : req_obj=new CPendReqModify(id,symbol_obj.BidLast(),symbol_obj.Time(),request,retcode);  break;
      default: req_obj=NULL;
        break;
     }
   if(req_obj==NULL)
     {
      if(this.m_log_level>LOG_LEVEL_NO_MSG)
         ::Print(DFUN,CMessage::Text(MSG_LIB_TEXT_FAILING_CREATE_PENDING_REQ));
      return false;
     }
   //--- If failed to add the request to the list, display the appropriate message,
   //--- remove the created object and return 'false'
   if(!this.m_list_request.Add(req_obj))
     {
      if(this.m_log_level>LOG_LEVEL_NO_MSG)
         ::Print(DFUN,CMessage::Text(MSG_LIB_TEXT_FAILING_CREATE_PENDING_REQ));
      delete req_obj;
      return false;
     }
   //--- Filled in the fields of a successfully created object by the values passed to the method
   req_obj.SetTimeActivate(symbol_obj.Time()+wait);
   req_obj.SetWaitingMSC(wait);
   req_obj.SetCurrentAttempt(0);
   req_obj.SetTotalAttempts(attempts);
   
   //--- Display a brief description of a created pending request
   if(this.m_log_level>LOG_LEVEL_NO_MSG)
     {
      ::Print(CMessage::Text(MSG_LIB_TEXT_PEND_REQUEST_CREATED)," #",req_obj.ID(),":");
      req_obj.PrintShort();
     }
   //--- successful
   return true;
  }
//+------------------------------------------------------------------+

Agora ao método adicionalmente é transferido o status do objeto de ordem pendente a ser criado.
Anteriormente, nosso objeto de ordem pendente tinha o tipo de classe CPendingReq. Agora, excluímos completamente esta classe e agora ficamos com uma nova classe de objeto de ordem pendente CPendRequest e seus herdeiros.
Por isso, neste caso, ao criar um objeto vazio, usamos o novo objeto de ordem abstrata base CPendRequest.
Em seguida, dependendo do status transferido ao método, criamos o novo objeto de ordem pendente correspondente a ele.
Após a criação bem-sucedida do objeto, no logo é exibida uma pequena mensagem contendo os parâmetros da ordem de negociação pendente criada.

Como agora temos um novo objeto da classe de ordem pendente, na listagem da classe de negociação substituiremos todas as ocorrências da classe CPendingReq anterior por CPendRequest. Isso é simples de fazer usando "search by" e Ctrl+H.

Durante a criação de novos objetos de ordens pendentes, aos eles transferiremos um pouco mais de informações sobre a operação de negociação a ser realizada. Basicamente, isso é necessário para exibição correta no log. Transferiremos escrevendo dados adicionais na estrutura da ordem de negociação ao criar um novo objeto de ordem pendente.

No método de abertura de posição no bloco para criar uma ordem pendente indicamos o status da ordem criada:

      //--- If the check result is "waiting" - set the last error code to the return structure and display the message in the journal,
      //--- create a pending request and return 'false'
      if(method>ERROR_CODE_PROCESSING_METHOD_REFRESH)
        {
         //--- If the trading request magic number, has no pending request ID
         if(this.GetPendReqID((uint)magic)==0)
           {
            //--- Play the error sound
            if(this.IsUseSounds())
               trade_obj.PlaySoundError(action,order_type);
            //--- set the last error code to the return structure
            int code=this.m_list_errors.At(this.m_list_errors.Total()-1);
            if(code!=NULL)
              {
               if(code==MSG_LIB_TEXT_TERMINAL_NOT_TRADE_ENABLED || code==MSG_LIB_TEXT_EA_NOT_TRADE_ENABLED)
                  code=10027;
               trade_obj.SetResultRetcode(code);
               trade_obj.SetResultComment(CMessage::Text(trade_obj.GetResultRetcode()));
              }
            //--- Waiting time in milliseconds:
            //--- for the "Wait and repeat" handling method, the waiting value corresponds to the 'method' value,
            ulong wait=method;
            //--- Look for the least of the possible IDs. If failed to find
            //--- or in case of an error while updating the current symbol data, return 'false'
            int id=this.GetFreeID();
            if(id<1 || !symbol_obj.RefreshRates())
               return false;
            //--- Write the pending request object ID to the magic number and fill in the remaining unfilled fields of the trading request structure
            uint mn=(magic==ULONG_MAX ? (uint)trade_obj.GetMagic() : (uint)magic);
            this.SetPendReqID((uchar)id,mn);
            this.m_request.magic=mn;
            this.m_request.action=TRADE_ACTION_DEAL;
            this.m_request.symbol=symbol_obj.Name();
            this.m_request.type=order_type;
            //--- Set the number of trading attempts and create a pending request
            uchar attempts=(this.m_total_try < 1 ? 1 : this.m_total_try);
            this.CreatePendingRequest(PEND_REQ_STATUS_OPEN,(uchar)id,attempts,wait,this.m_request,trade_obj.GetResultRetcode(),symbol_obj);
           }
         return false;
        }

No método de modificação de ordens stop de uma posição aberta no bloco para criar uma solicitação pendente
adicionamos a transferência
através da estrutura ao objeto-ordem do tipo de solicitação, o volume da posição, e especificamos o status da ordem a ser criada:

      //--- If the check result is "waiting" - set the last error code to the return structure and display the message in the journal,
      //--- create a pending request and return 'false'
      if(method>ERROR_CODE_PROCESSING_METHOD_REFRESH)
        {
         //--- If the pending request object with the position ticket is not present in the list
         if(this.GetIndexPendingRequestByPosition(ticket)==WRONG_VALUE)
           {
            //--- Play the error sound
            if(this.IsUseSounds())
               trade_obj.PlaySoundError(action,order_type,(sl<0 ? false : true),(tp<0 ? false : true));
            //--- set the last error code to the return structure
            int code=this.m_list_errors.At(this.m_list_errors.Total()-1);
            if(code!=NULL)
              {
               if(code==MSG_LIB_TEXT_TERMINAL_NOT_TRADE_ENABLED || code==MSG_LIB_TEXT_EA_NOT_TRADE_ENABLED)
                  code=10027;
               trade_obj.SetResultRetcode(code);
               trade_obj.SetResultComment(CMessage::Text(trade_obj.GetResultRetcode()));
              }
            //--- Waiting time in milliseconds:
            //--- for the "Wait and repeat" handling method, the waiting value corresponds to the 'method' value,
            //--- for the "Create a pending request" handling method - till there is a zero waiting time
            ulong wait=method;
            //--- Look for the least of the possible IDs. If failed to find
            //--- or in case of an error while updating the current symbol data, return 'false'
            int id=this.GetFreeID();
            if(id<1 || !symbol_obj.RefreshRates())
               return false;
            //--- Write a type of a conducted operation, as well as a symbol and a ticket of a modified position to the request structure
            this.m_request.action=TRADE_ACTION_SLTP;
            this.m_request.symbol=symbol_obj.Name();
            this.m_request.position=ticket;
            this.m_request.type=order_type;
            this.m_request.volume=order.Volume();
            //--- Set the number of trading attempts and create a pending request
            uchar attempts=(this.m_total_try < 1 ? 1 : this.m_total_try);
            this.CreatePendingRequest(PEND_REQ_STATUS_SLTP,(uchar)id,attempts,wait,this.m_request,trade_obj.GetResultRetcode(),symbol_obj);
           }
         return false;
        }

No método de fechamento de posição ao seu bloco de criação de ordem pendente
adicionamos a transferência
através da estrutura ao objeto
-ordem do tipo de ordem, o volume da posição, e especificamos o status da ordem a ser criada:

      //--- If the check result is "waiting" - set the last error code to the return structure and display the message in the journal,
      //--- create a pending request and return 'false'
      if(method>ERROR_CODE_PROCESSING_METHOD_REFRESH)
        {
         //--- If the pending request object with the position ticket is not present in the list
         if(this.GetIndexPendingRequestByPosition(ticket)==WRONG_VALUE)
           {
            //--- Play the error sound
            if(this.IsUseSounds())
               trade_obj.PlaySoundError(action,order_type);
            //--- set the last error code to the return structure
            int code=this.m_list_errors.At(this.m_list_errors.Total()-1);
            if(code!=NULL)
              {
               if(code==MSG_LIB_TEXT_TERMINAL_NOT_TRADE_ENABLED || code==MSG_LIB_TEXT_EA_NOT_TRADE_ENABLED)
                  code=10027;
               trade_obj.SetResultRetcode(code);
               trade_obj.SetResultComment(CMessage::Text(trade_obj.GetResultRetcode()));
              }
            //--- Waiting time in milliseconds:
            //--- for the "Wait and repeat" handling method, the waiting value corresponds to the 'method' value,
            ulong wait=method;
            //--- Look for the least of the possible IDs. If failed to find
            //--- or in case of an error while updating the current symbol data, return 'false'
            int id=this.GetFreeID();
            if(id<1 || !symbol_obj.RefreshRates())
               return false;
            //--- Write the trading operation type, symbol, ticket and volume to the request structure
            this.m_request.action=TRADE_ACTION_DEAL;
            this.m_request.symbol=symbol_obj.Name();
            this.m_request.position=ticket;
            this.m_request.volume=(volume==WRONG_VALUE || volume>order.Volume() ? order.Volume() : volume);
            this.m_request.type=order_type;
            //--- Set the number of trading attempts and create a pending request
            uchar attempts=(this.m_total_try < 1 ? 1 : this.m_total_try);
            this.CreatePendingRequest(PEND_REQ_STATUS_CLOSE,(uchar)id,attempts,wait,this.m_request,trade_obj.GetResultRetcode(),symbol_obj);
           }
         return false;

O volume da posição pode ser especificado no método como negativo (-1), o que indica o completo fechamento da posição, ou pode ser especificado com um valor, o que indica o fechamento parcial da posição. Tudo isso é processado no objeto de negociação base do símbolo ao enviar uma ordem de negociação para o servidor.
Aqui, verificamos imediatamente o valor do volume transferido ao método e configuramos o volume necessário na estrutura da ordem de negociação.

No método de fechamento da posição com a ajuda de uma posição oposta no seu bloco de criação de ordem pendente
adicionamos a transferência
através da estrutura ao objeto
-ordem do tipo de ordem, o volume da posição, e especificamos o status da ordem a ser criada:

      //--- If the check result is "waiting" - set the last error code to the return structure and display the message in the journal,
      //--- create a pending request and return 'false'
      if(method>ERROR_CODE_PROCESSING_METHOD_REFRESH)
        {
         //--- If the pending request object with the position ticket is not present in the list
         if(this.GetIndexPendingRequestByPosition(ticket)==WRONG_VALUE)
           {
            //--- Play the error sound
            if(this.IsUseSounds())
               trade_obj_pos.PlaySoundError(action,order_type);
            //--- set the last error code to the return structure
            int code=this.m_list_errors.At(this.m_list_errors.Total()-1);
            if(code!=NULL)
              {
               if(code==MSG_LIB_TEXT_TERMINAL_NOT_TRADE_ENABLED || code==MSG_LIB_TEXT_EA_NOT_TRADE_ENABLED)
                  code=10027;
               trade_obj_pos.SetResultRetcode(code);
               trade_obj_pos.SetResultComment(CMessage::Text(trade_obj_pos.GetResultRetcode()));
              }
            //--- Waiting time in milliseconds:
            //--- for the "Wait and repeat" handling method, the waiting value corresponds to the 'method' value,
            ulong wait=method;
            //--- Look for the least of the possible IDs. If failed to find
            //--- or in case of an error while updating the current symbol data, return 'false'
            int id=this.GetFreeID();
            if(id<1 || !symbol_obj.RefreshRates())
               return false;
            //--- Write the trading operation type, symbol and tickets of two positions to the request structure
            this.m_request.action=TRADE_ACTION_CLOSE_BY;
            this.m_request.symbol=symbol_obj.Name();
            this.m_request.position=ticket;
            this.m_request.position_by=ticket_by;
            this.m_request.type=order_type;
            this.m_request.volume=order.Volume();
            //--- Set the number of trading attempts and create a pending request
            uchar attempts=(this.m_total_try < 1 ? 1 : this.m_total_try);
            this.CreatePendingRequest(PEND_REQ_STATUS_CLOSE,(uchar)id,attempts,wait,this.m_request,trade_obj_pos.GetResultRetcode(),symbol_obj);
           }
         return false;
        }

No método de definição de ordem pendente no bloco para criar uma ordem pendente indicamos o status da ordem criada:

      //--- If the check result is "waiting" - set the last error code to the return structure and display the message in the journal,
      //--- create a pending request and return 'false'
      if(method>ERROR_CODE_PROCESSING_METHOD_REFRESH)
        {
         //--- If the trading request magic number, has no pending request ID
         if(this.GetPendReqID((uint)magic)==0)
           {
            //--- Play the error sound
            if(this.IsUseSounds())
               trade_obj.PlaySoundError(action,order_type);
            //--- set the last error code to the return structure
            int code=this.m_list_errors.At(this.m_list_errors.Total()-1);
            if(code!=NULL)
              {
               if(code==MSG_LIB_TEXT_TERMINAL_NOT_TRADE_ENABLED || code==MSG_LIB_TEXT_EA_NOT_TRADE_ENABLED)
                  code=10027;
               trade_obj.SetResultRetcode(code);
               trade_obj.SetResultComment(CMessage::Text(trade_obj.GetResultRetcode()));
              }
            //--- Waiting time in milliseconds:
            //--- for the "Wait and repeat" handling method, the waiting value corresponds to the 'method' value,
            //--- for the "Create a pending request" handling method - till there is a zero waiting time
            ulong wait=method;
            //--- Look for the least of the possible IDs. If failed to find
            //--- or in case of an error while updating the current symbol data, return 'false'
            int id=this.GetFreeID();
            if(id<1 || !symbol_obj.RefreshRates())
               return false;
            //--- Write the request ID to the magic number, while a symbol name is set in the request structure,
            //--- trading operation and order types
            uint mn=(magic==ULONG_MAX ? (uint)trade_obj.GetMagic() : (uint)magic);
            this.SetPendReqID((uchar)id,mn);
            this.m_request.magic=mn;
            this.m_request.symbol=symbol_obj.Name();
            this.m_request.action=TRADE_ACTION_PENDING;
            this.m_request.type=order_type;
               //--- Set the number of trading attempts and create a pending request
            uchar attempts=(this.m_total_try < 1 ? 1 : this.m_total_try);
            this.CreatePendingRequest(PEND_REQ_STATUS_PLACE,(uchar)id,attempts,wait,this.m_request,trade_obj.GetResultRetcode(),symbol_obj);
           }
         return false;
        }

No método de modificação de parâmetros da ordem pendente no bloco para criar uma ordem pendente
adicionamos a transferência através da estrutura ao objeto-ordem do tipo de ordem, e especificamos o status da ordem a ser criada:

      //--- If the check result is "waiting" - set the last error code to the return structure and display the message in the journal,
      //--- create a pending request and return 'false'
      if(method>ERROR_CODE_PROCESSING_METHOD_REFRESH)
        {
         //--- If the pending request object with the order ticket is not present in the list
         if(this.GetIndexPendingRequestByOrder(ticket)==WRONG_VALUE)
           {
            //--- Play the error sound
            if(this.IsUseSounds())
               trade_obj.PlaySoundError(action,order_type,(sl<0 ? false : true),(tp<0 ? false : true),(price>0 || limit>0 ? true : false));
            //--- set the last error code to the return structure
            int code=this.m_list_errors.At(this.m_list_errors.Total()-1);
            if(code!=NULL)
              {
               if(code==MSG_LIB_TEXT_TERMINAL_NOT_TRADE_ENABLED || code==MSG_LIB_TEXT_EA_NOT_TRADE_ENABLED)
                  code=10027;
               trade_obj.SetResultRetcode(code);
               trade_obj.SetResultComment(CMessage::Text(trade_obj.GetResultRetcode()));
              }
            //--- Waiting time in milliseconds:
            //--- for the "Wait and repeat" handling method, the waiting value corresponds to the 'method' value,
            //--- for the "Create a pending request" handling method - till there is a zero waiting time
            ulong wait=method;
            //--- Look for the least of the possible IDs. If failed to find
            //--- or in case of an error while updating the current symbol data, return 'false'
            int id=this.GetFreeID();
            if(id<1 || !symbol_obj.RefreshRates())
               return false;
            //--- Set the trading operation type, as well as modified order's symbol and ticket in the request structure
            this.m_request.action=TRADE_ACTION_MODIFY;
            this.m_request.symbol=symbol_obj.Name();
            this.m_request.order=ticket;
            this.m_request.type=order_type;
            //--- Set the number of trading attempts and create a pending request
            uchar attempts=(this.m_total_try < 1 ? 1 : this.m_total_try);
            this.CreatePendingRequest(PEND_REQ_STATUS_MODIFY,(uchar)id,attempts,wait,this.m_request,trade_obj.GetResultRetcode(),symbol_obj);
           }
         return false;
        }

No método de exclusão da ordem pendente no bloco para criar uma ordem pendente
adicionamos a transferência
através da estrutura ao objeto
-ordem do tipo , o volume da ordem, o seu preço de posicionamento, e especificamos o status da ordem a ser criada:

      //--- If the check result is "waiting" - set the last error code to the return structure and display the message in the journal,
      //--- create a pending request and return 'false'
      if(method>ERROR_CODE_PROCESSING_METHOD_REFRESH)
        {
         //--- If the pending request object with the order ticket is not present in the list
         if(this.GetIndexPendingRequestByOrder(ticket)==WRONG_VALUE)
           {
            //--- Play the error sound
            if(this.IsUseSounds())
               trade_obj.PlaySoundError(action,order_type);
            //--- set the last error code to the return structure
            int code=this.m_list_errors.At(this.m_list_errors.Total()-1);
            if(code!=NULL)
              {
               if(code==MSG_LIB_TEXT_TERMINAL_NOT_TRADE_ENABLED || code==MSG_LIB_TEXT_EA_NOT_TRADE_ENABLED)
                  code=10027;
               trade_obj.SetResultRetcode(code);
               trade_obj.SetResultComment(CMessage::Text(trade_obj.GetResultRetcode()));
              }
            //--- Waiting time in milliseconds:
            //--- for the "Wait and repeat" handling method, the waiting value corresponds to the 'method' value,
            //--- for the "Create a pending request" handling method - till there is a zero waiting time
            ulong wait=method;
            //--- Look for the least of the possible IDs. If failed to find
            //--- or in case of an error while updating the current symbol data, return 'false'
            int id=this.GetFreeID();
            if(id<1 || !symbol_obj.RefreshRates())
               return false;
            //--- Set the trading operation type, as well as deleted order's symbol and ticket in the request structure
            this.m_request.action=TRADE_ACTION_REMOVE;
            this.m_request.symbol=symbol_obj.Name();
            this.m_request.order=ticket;
            this.m_request.type=order_type;
            this.m_request.volume=order.Volume();
            this.m_request.price=order.PriceOpen();
            //--- Set the number of trading attempts and create a pending request
            uchar attempts=(this.m_total_try < 1 ? 1 : this.m_total_try);
            this.CreatePendingRequest(PEND_REQ_STATUS_REMOVE,(uchar)id,attempts,wait,this.m_request,trade_obj.GetResultRetcode(),symbol_obj);
           }
         return false;
        }

Temos dois desses blocos em cada método de negociação. Por isso, precisamos fazer alterações em cada um deles.

Nos métodos para localizar um identificador livre e retornar índices de objetos-ordens especificamos os tipos de classificação:

//+------------------------------------------------------------------+
//| Look for the first free pending request ID                       |
//+------------------------------------------------------------------+
int CTrading::GetFreeID(void)
  {
   int id=WRONG_VALUE;
   CPendRequest *element=new CPendRequest();
   if(element==NULL)
      return 0;
   for(int i=1;i<256;i++)
     {
      element.SetID((uchar)i);
      this.m_list_request.Sort(SORT_BY_PEND_REQ_ID);
      if(this.m_list_request.Search(element)==WRONG_VALUE)
        {
         id=i;
         break;
        }
     }
   delete element;
   return id;
  }
//+------------------------------------------------------------------+
//| Return the request object index in the list by ID                |
//+------------------------------------------------------------------+
int CTrading::GetIndexPendingRequestByID(const uchar id)
  {
   CPendRequest *req=new CPendRequest();
   if(req==NULL)
      return WRONG_VALUE;
   req.SetID(id);
   this.m_list_request.Sort(SORT_BY_PEND_REQ_ID);
   int index=this.m_list_request.Search(req);
   delete req;
   return index;
  }
//+------------------------------------------------------------------+
//| Return the request object index in the list by the order ticket  |
//+------------------------------------------------------------------+
int CTrading::GetIndexPendingRequestByOrder(const ulong ticket)
  {
   CPendRequest *req=new CPendRequest();
   if(req==NULL)
      return WRONG_VALUE;
   req.SetOrder(ticket);
   this.m_list_request.Sort(SORT_BY_PEND_REQ_MQL_REQ_ORDER);
   int index=this.m_list_request.Search(req);
   delete req;
   return index;
  }
//+-------------------------------------------------------------------+
//| Return the request object index in the list by the position ticket|
//+-------------------------------------------------------------------+
int CTrading::GetIndexPendingRequestByPosition(const ulong ticket)
  {
   CPendRequest *req=new CPendRequest();
   if(req==NULL)
      return WRONG_VALUE;
   req.SetPosition(ticket);
   this.m_list_request.Sort(SORT_BY_PEND_REQ_MQL_REQ_POSITION);
   int index=this.m_list_request.Search(req);
   delete req;
   return index;
  }
//+------------------------------------------------------------------+

Para pesquisa do objeto, nas lista, segundo a propriedade especificada, com a ajuda do método Searsh() da classe de uma matriz dinâmica de ponteiros para instâncias da classe CObject, primeiro é necessário, com a ajuda do método Sort() da classe base de uma matriz dinâmica de variáveis CArray, especificar o tipo de classificação de lista na qual é realizada a lista, uma vez que a pesquisa é realizada apenas em matrizes classificadas. É o que estamos fazendo aqui.

Agora, no temporizador da classe, corrigiremos a exibição de mensagens sobre o número da tentativa de negociação no log.
Devemos substituir este código

      //--- Set the attempt number in the request object
      req_obj.SetCurrentAttempt(uchar(req_obj.CurrentAttempt()+1));
      
      //--- Display the number of a trading attempt in the journal

      if(this.m_log_level>LOG_LEVEL_NO_MSG)
         ::Print(CMessage::Text(MSG_LIB_TEXT_REQUEST)+(string)req_obj.GetProperty(PEND_REQ_PROP_ID)+" "+CMessage::Text(MSG_LIB_TEXT_RE_TRY_N)+(string)req_obj.CurrentAttempt());
      
      //--- Depending on the type of action performed in the trading request 
      switch(request.action)
        {

por este:

      //--- Set the attempt number in the request object
      req_obj.SetCurrentAttempt(uchar(req_obj.CurrentAttempt()+1));
      
      //--- Display the number of a trading attempt in the journal

      if(this.m_log_level>LOG_LEVEL_NO_MSG)
        {
         ::Print(CMessage::Text(MSG_LIB_TEXT_RE_TRY_N)+(string)req_obj.CurrentAttempt()+":");
         req_obj.PrintShort();
        }
      
      //--- Depending on the type of action performed in the trading request 
      switch(request.action)
        {

Isso nos dará uma mensagem mais informativa no log sobre qual objeto da ordem pendente é a próxima tentativa de negociação.

Essas são todas as alterações necessárias para a biblioteca trabalhar com objetos-ordens de negociação pendentes.

Teste

Para testar novos objetos-ordens pendentes, usamos o EA do artigo anterior
e o salvamos na nova pasta \MQL5\Experts\TestDoEasy\ Part29\ usando o novo nome TestDoEasyPart29.mq5.

Todas as alterações que precisam ser feitas dizem respeito a remover verificações desnecessárias nos blocos para fechar metade da posição Buy e metade da posição Sell, uma vez que já tudo é feito nos métodos de negociação da classe de negociação.

No bloco para fechamento parcial da posição Buy em vez deste código:

      //--- If the BUTT_CLOSE_BUY2 button is pressed: Close the half of the Buy with the maximum profit
      else if(button==EnumToString(BUTT_CLOSE_BUY2))
        {
         //--- Get the list of all open positions
         CArrayObj* list=engine.GetListMarketPosition();
         //--- Select only Buy positions from the list
         list=CSelect::ByOrderProperty(list,ORDER_PROP_TYPE,POSITION_TYPE_BUY,EQUAL);
         //--- Sort the list by profit considering commission and swap
         list.Sort(SORT_BY_ORDER_PROFIT_FULL);
         //--- Get the index of the Buy position with the maximum profit
         int index=CSelect::FindOrderMax(list,ORDER_PROP_PROFIT_FULL);
         if(index>WRONG_VALUE)
           {
            COrder* position=list.At(index);
            if(position!=NULL)
              {
               //--- If this is a hedge account, close the half of the Buy position by the ticket
               if(engine.IsHedge())
                  engine.ClosePositionPartially((ulong)position.Ticket(),position.Volume()/2.0);
               //--- If this is a netting account, open a Sell position with the half of the Buy position volume
               else
                  engine.OpenSell(NormalizeLot(position.Symbol(),position.Volume()/2.0),position.Symbol(),position.Magic(),position.StopLoss(),position.TakeProfit(),"Частичное закрытие Buy #"+(string)position.Ticket());
              }
           }
        }

escrevemos este:

      //--- If the BUTT_CLOSE_BUY2 button is pressed: Close the half of the Buy with the maximum profit
      else if(button==EnumToString(BUTT_CLOSE_BUY2))
        {
         //--- Get the list of all open positions
         CArrayObj* list=engine.GetListMarketPosition();
         //--- Select only Buy positions from the list
         list=CSelect::ByOrderProperty(list,ORDER_PROP_TYPE,POSITION_TYPE_BUY,EQUAL);
         //--- Sort the list by profit considering commission and swap
         list.Sort(SORT_BY_ORDER_PROFIT_FULL);
         //--- Get the index of the Buy position with the maximum profit
         int index=CSelect::FindOrderMax(list,ORDER_PROP_PROFIT_FULL);
         if(index>WRONG_VALUE)
           {
            COrder* position=list.At(index);
            //--- Close the Buy position partially
            if(position!=NULL)
               engine.ClosePositionPartially((ulong)position.Ticket(),position.Volume()/2.0);
           }
        }

Da mesma maneira, reescrevemos o fechamento parcial da posição Sell:

      //--- If the BUTT_CLOSE_SELL2 button is pressed: Close the half of the Sell with the maximum profit
      else if(button==EnumToString(BUTT_CLOSE_SELL2))
        {
         //--- Get the list of all open positions
         CArrayObj* list=engine.GetListMarketPosition();
         //--- Select only Sell positions from the list
         list=CSelect::ByOrderProperty(list,ORDER_PROP_TYPE,POSITION_TYPE_SELL,EQUAL);
         //--- Sort the list by profit considering commission and swap
         list.Sort(SORT_BY_ORDER_PROFIT_FULL);
         //--- Get the index of the Sell position with the maximum profit
         int index=CSelect::FindOrderMax(list,ORDER_PROP_PROFIT_FULL);
         if(index>WRONG_VALUE)
           {
            COrder* position=list.At(index);
            //--- Close the Sell position partially
            if(position!=NULL)
               engine.ClosePositionPartially((ulong)position.Ticket(),position.Volume()/2.0);
           }
        }

Compilamos e iniciamos o EA.

No momento, tenho quatro ordens pendentes posicionadas. Desativo a botão "Autotrading" e clico no botão do EA de teste "Delete pending" para excluir todas as ordens pendentes. No log são exibidas as mensagens:

2019.12.19 04:25:04.385 CTrading::DeleteOrder: Invalid request:
2019.12.19 04:25:04.385 There is no permission to conduct trading operations in the terminal (the "AutoTrading" button is disabled)
2019.12.19 04:25:04.385 Correction of trade request parameters ...
2019.12.19 04:25:04.385 Pending request created #1:
2019.12.19 04:25:04.385 Pending request to remove a pending order: 
2019.12.19 04:25:04.385 - EURUSD 0.10 Pending order Buy Limit #497568391, Price 1.11076
2019.12.19 04:25:04.385 - Pending request ID: #1, Created 2019.12.18 23:25:01.920, Attempts 5, Wait 00:00:20, End 2019.12.18 23:26:41.920
2019.12.19 04:25:04.385 
2019.12.19 04:25:04.386 CTrading::DeleteOrder: Invalid request:
2019.12.19 04:25:04.386 There is no permission to conduct trading operations in the terminal (the "AutoTrading" button is disabled)
2019.12.19 04:25:04.386 Correction of trade request parameters ...
2019.12.19 04:25:04.386 Pending request created #2:
2019.12.19 04:25:04.386 Pending request to remove a pending order: 
2019.12.19 04:25:04.386 - EURUSD 0.10 Pending order Buy Limit #497563913, Price 1.11099
2019.12.19 04:25:04.386 - Pending request ID: #2, Created 2019.12.18 23:25:01.920, Attempts 5, Wait 00:00:20, End 2019.12.18 23:26:41.920
2019.12.19 04:25:04.386 
2019.12.19 04:25:04.386 CTrading::DeleteOrder: Invalid request:
2019.12.19 04:25:04.386 There is no permission to conduct trading operations in the terminal (the "AutoTrading" button is disabled)
2019.12.19 04:25:04.386 Correction of trade request parameters ...
2019.12.19 04:25:04.386 Pending request created #3:
2019.12.19 04:25:04.386 Pending request to remove a pending order: 
2019.12.19 04:25:04.386 - EURUSD 0.10 Pending order Sell Limit #496816788, Price 1.11829
2019.12.19 04:25:04.386 - Pending request ID: #3, Created 2019.12.18 23:25:01.920, Attempts 5, Wait 00:00:20, End 2019.12.18 23:26:41.920
2019.12.19 04:25:04.386 
2019.12.19 04:25:04.386 CTrading::DeleteOrder: Invalid request:
2019.12.19 04:25:04.386 There is no permission to conduct trading operations in the terminal (the "AutoTrading" button is disabled)
2019.12.19 04:25:04.386 Correction of trade request parameters ...
2019.12.19 04:25:04.387 Pending request created #4:
2019.12.19 04:25:04.387 Pending request to remove a pending order: 
2019.12.19 04:25:04.387 - EURUSD 0.10 Pending order Sell Limit #496816707, Price 1.11784
2019.12.19 04:25:04.387 - Pending request ID: #4, Created 2019.12.18 23:25:01.920, Attempts 5, Wait 00:00:20, End 2019.12.18 23:26:41.920
2019.12.19 04:25:04.387 

Aqui pode ser visto que o EA fez quatro tentativas para excluir quatro ordens pendentes e, ao encontrar um erro de proibição de negociação da parte do terminal, criou quatro ordens pendentes sobre as quais exibia mensagens curtas com seus parâmetros.

Em seguida, não fazemos nada, apenas aguardamos.
Após algum tempo (20 segundos de espera, mas depende da chegada de ticks), são exibidas no log as mensagens de objetos-ordens pendentes sobre tentativas repetidas de excluir quatro ordens:

2019.12.19 04:25:38.780 Retry trading attempt #1:
2019.12.19 04:25:38.780 Pending request to remove a pending order: 
2019.12.19 04:25:38.780 - EURUSD 0.10 Pending order Sell Limit #496816707, Price 1.11784
2019.12.19 04:25:38.780 - Pending request ID: #4, Created 2019.12.18 23:25:01.920, Attempts 5, Wait 00:00:20, End 2019.12.18 23:26:41.920
2019.12.19 04:25:38.780 
2019.12.19 04:25:38.780 Retry trading attempt #1:
2019.12.19 04:25:38.780 Pending request to remove a pending order: 
2019.12.19 04:25:38.780 - EURUSD 0.10 Pending order Buy Limit #497563913, Price 1.11099
2019.12.19 04:25:38.780 - Pending request ID: #2, Created 2019.12.18 23:25:01.920, Attempts 5, Wait 00:00:20, End 2019.12.18 23:26:41.920
2019.12.19 04:25:38.780 
2019.12.19 04:25:38.781 Retry trading attempt #1:
2019.12.19 04:25:38.781 Pending request to remove a pending order: 
2019.12.19 04:25:38.781 - EURUSD 0.10 Pending order Sell Limit #496816788, Price 1.11829
2019.12.19 04:25:38.781 - Pending request ID: #3, Created 2019.12.18 23:25:01.920, Attempts 5, Wait 00:00:20, End 2019.12.18 23:26:41.920
2019.12.19 04:25:38.781 
2019.12.19 04:25:39.103 Retry trading attempt #1:
2019.12.19 04:25:39.103 Pending request to remove a pending order: 
2019.12.19 04:25:39.103 - EURUSD 0.10 Pending order Buy Limit #497568391, Price 1.11076
2019.12.19 04:25:39.103 - Pending request ID: #1, Created 2019.12.18 23:25:01.920, Attempts 5, Wait 00:00:20, End 2019.12.18 23:26:41.920
2019.12.19 04:25:39.103 
2019.12.19 04:25:42.006 Retry trading attempt #2:
2019.12.19 04:25:42.006 Pending request to remove a pending order: 
2019.12.19 04:25:42.006 - EURUSD 0.10 Pending order Buy Limit #497568391, Price 1.11076
2019.12.19 04:25:42.006 - Pending request ID: #1, Created 2019.12.18 23:25:01.920, Attempts 5, Wait 00:00:20, End 2019.12.18 23:26:41.920
2019.12.19 04:25:42.006 
2019.12.19 04:25:42.007 Retry trading attempt #2:
2019.12.19 04:25:42.007 Pending request to remove a pending order: 
2019.12.19 04:25:42.007 - EURUSD 0.10 Pending order Buy Limit #497563913, Price 1.11099
2019.12.19 04:25:42.007 - Pending request ID: #2, Created 2019.12.18 23:25:01.920, Attempts 5, Wait 00:00:20, End 2019.12.18 23:26:41.920
2019.12.19 04:25:42.007 
2019.12.19 04:25:42.007 Retry trading attempt #2:
2019.12.19 04:25:42.007 Pending request to remove a pending order: 
2019.12.19 04:25:42.007 - EURUSD 0.10 Pending order Sell Limit #496816788, Price 1.11829
2019.12.19 04:25:42.007 - Pending request ID: #3, Created 2019.12.18 23:25:01.920, Attempts 5, Wait 00:00:20, End 2019.12.18 23:26:41.920
2019.12.19 04:25:42.007 
2019.12.19 04:25:42.008 Retry trading attempt #2:
2019.12.19 04:25:42.008 Pending request to remove a pending order: 
2019.12.19 04:25:42.008 - EURUSD 0.10 Pending order Sell Limit #496816707, Price 1.11784
2019.12.19 04:25:42.008 - Pending request ID: #4, Created 2019.12.18 23:25:01.920, Attempts 5, Wait 00:00:20, End 2019.12.18 23:26:41.920
2019.12.19 04:25:42.008 
2019.12.19 04:26:03.026 Retry trading attempt #3:
2019.12.19 04:26:03.026 Pending request to remove a pending order: 
2019.12.19 04:26:03.026 - EURUSD 0.10 Pending order Buy Limit #497568391, Price 1.11076
2019.12.19 04:26:03.026 - Pending request ID: #1, Created 2019.12.18 23:25:01.920, Attempts 5, Wait 00:00:20, End 2019.12.18 23:26:41.920
2019.12.19 04:26:03.026 
2019.12.19 04:26:03.027 Retry trading attempt #3:
2019.12.19 04:26:03.027 Pending request to remove a pending order: 
2019.12.19 04:26:03.027 - EURUSD 0.10 Pending order Buy Limit #497563913, Price 1.11099
2019.12.19 04:26:03.027 - Pending request ID: #2, Created 2019.12.18 23:25:01.920, Attempts 5, Wait 00:00:20, End 2019.12.18 23:26:41.920
2019.12.19 04:26:03.027 
2019.12.19 04:26:03.027 Retry trading attempt #3:
2019.12.19 04:26:03.028 Pending request to remove a pending order: 
2019.12.19 04:26:03.028 - EURUSD 0.10 Pending order Sell Limit #496816788, Price 1.11829
2019.12.19 04:26:03.028 - Pending request ID: #3, Created 2019.12.18 23:25:01.920, Attempts 5, Wait 00:00:20, End 2019.12.18 23:26:41.920
2019.12.19 04:26:03.028 
2019.12.19 04:26:03.028 Retry trading attempt #3:
2019.12.19 04:26:03.028 Pending request to remove a pending order: 
2019.12.19 04:26:03.028 - EURUSD 0.10 Pending order Sell Limit #496816707, Price 1.11784
2019.12.19 04:26:03.028 - Pending request ID: #4, Created 2019.12.18 23:25:01.920, Attempts 5, Wait 00:00:20, End 2019.12.18 23:26:41.920
2019.12.19 04:26:03.028 
2019.12.19 04:26:22.357 Retry trading attempt #4:
2019.12.19 04:26:22.357 Pending request to remove a pending order: 
2019.12.19 04:26:22.357 - EURUSD 0.10 Pending order Buy Limit #497568391, Price 1.11076
2019.12.19 04:26:22.357 - Pending request ID: #1, Created 2019.12.18 23:25:01.920, Attempts 5, Wait 00:00:20, End 2019.12.18 23:26:41.920
2019.12.19 04:26:22.357 
2019.12.19 04:26:22.358 Retry trading attempt #4:
2019.12.19 04:26:22.358 Pending request to remove a pending order: 
2019.12.19 04:26:22.358 - EURUSD 0.10 Pending order Buy Limit #497563913, Price 1.11099
2019.12.19 04:26:22.358 - Pending request ID: #2, Created 2019.12.18 23:25:01.920, Attempts 5, Wait 00:00:20, End 2019.12.18 23:26:41.920
2019.12.19 04:26:22.358 
2019.12.19 04:26:22.358 Retry trading attempt #4:
2019.12.19 04:26:22.358 Pending request to remove a pending order: 
2019.12.19 04:26:22.358 - EURUSD 0.10 Pending order Sell Limit #496816788, Price 1.11829
2019.12.19 04:26:22.358 - Pending request ID: #3, Created 2019.12.18 23:25:01.920, Attempts 5, Wait 00:00:20, End 2019.12.18 23:26:41.920
2019.12.19 04:26:22.358 
2019.12.19 04:26:22.359 Retry trading attempt #4:
2019.12.19 04:26:22.359 Pending request to remove a pending order: 
2019.12.19 04:26:22.359 - EURUSD 0.10 Pending order Sell Limit #496816707, Price 1.11784
2019.12.19 04:26:22.359 - Pending request ID: #4, Created 2019.12.18 23:25:01.920, Attempts 5, Wait 00:00:20, End 2019.12.18 23:26:41.920

E, novamente, esperamos a próxima tentativa de negociação. Quando chegar a hora, os objetos-ordens pendentes serão excluídas devido à expiração do tempo alocado para todas as tentativas de negociação:

2019.12.19 04:26:44.004 Pending request ID: #1: Deleted due to expiration
2019.12.19 04:26:44.004 Pending request ID: #2: Deleted due to expiration
2019.12.19 04:26:44.004 Pending request ID: #3: Deleted due to expiration
2019.12.19 04:26:44.004 Pending request ID: #4: Deleted due to expiration

Se o botão "Autotrading" for pressionado para todas as tentativas de negociação no tempo previsto, os objetos de ordens pendentes enviarão uma ordem ao servidor para excluir as ordens pendentes e elas serão removidas.

Exatamente da mesma maneira, verifiquei o funcionamento de objetos de ordens de negociação pendentes para abrir/fechar posições, colocar ordens, modificar ordens stop e parâmetros de ordens pendentes; bem como para o fechamento de posições usando uma posição oposta. E como resultado notei que as ordens de negociação pendentes funcionam corretamente na maioria dos casos. Porém, há um 'mas': se, primeiro, modificarmos, por exemplo, uma ordem pendente e, em seguida, tentarmos novamente fazer alguma modificação, já não será possível fazer isso. É como criar duas ou mais operações de negociação com o mesmo ticket. As ordens pendentes serão simplesmente excluídas imediatamente após serem criadas com a causa "Concluídas". Acontece que, nos artigos anteriores, as verificações de processamento de solicitações pendentes eram realizadas apenas por ticket no temporizador da classe de negociação. E o método de verificação descobriu que no histórico da conta uma operação com certo ticket havia acabado de ser realizada. Dessa forma, acreditava-se que tudo funcionou bem e valia a pena excluir esse objeto-ordem. Vamos corrigir essa situação em seguida.

Lembre-se:

Chamo bastante a atenção para o fato de que trabalho com a classe de objeto-ordem pendente ainda não está totalmente concluído, por isso, os resultados descritos neste artigo e no EA de teste anexado ao artigo não devem, em caso algum, ser usados para negociação real!
Este artigo, seus materiais e o resultado, nesta apresentação, não são um produto acabado para uso em contas reais
, mas, sim, para uso somente em modo de demonstração ou no testador.

O que vem agora?

No próximo artigo, criaremos uma classe para gerenciar ordens de negociação pendentes e nos livraremos da incapacidade de executar a mesma operação de negociação com a mesma ordem ou posição várias vezes seguidas.

Abaixo estão anexados todos os arquivos da versão atual da biblioteca e os arquivos do EA de teste. Você pode baixá-los e testar tudo sozinho.
Se você tiver perguntas, comentários e sugestões, poderá expressá-los nos comentários do artigo.

Complementos

Artigos desta série:

Parte 1. Conceito, gerenciamento de dados e primeiros resultados
Parte 2. Coleção do histórico de ordens e negócios
Parte 3. Coleção de ordens e posições de mercado, busca e ordenação
Parte 4. Eventos de Negociação. Conceito
Parte 5. Classes e coleções de eventos de negociação. Envio de eventos para o programa
Parte 6. Eventos da conta netting
Parte 7. Eventos de ativação da ordem stoplimit, preparação da funcionalidade para os eventos de modificação de ordens e posições
Parte 8. Eventos de modificação de ordens e posições
Parte 9. Compatibilidade com a MQL4 — preparação dos dados
Parte 10. Compatibilidade com a MQL4 — eventos de abertura de posição e ativação de ordens pendentes
Parte 11. Compatibilidade com a MQL4 — eventos de encerramento de posição
Parte 12. Implementação da classe de objeto "conta" e da coleção de objetos da conta
Parte 13. Eventos do objeto conta
Parte 14. O objeto símbolo
Parte 15. Coleção de objetos-símbolos
Parte 16. Eventos de coleção de símbolos
Parte 17. Interatividade de objetos de biblioteca
Parte 18. Interatividade do objeto-conta e quaisquer de outros objetos da biblioteca
Parte 19. Classe de mensagens de biblioteca
Parte 20. Criação e armazenamento de recursos de programas
Parte 21 Classes de negociação - objeto base de negociação multiplataforma
Parte 22. Classes de negociação - classe básica de negociação, controle de restrições
Parte 23. Classes de negociação - classe básica de negociação, controle de parâmetros válidos
Parte 24. Classes de negociação - classe básica de negociação, correção automática de parâmetros errados
Parte 25. Classes de negociação - classe básica de negociação, processamento de erros retornados pelo servidor de negociação
Parte 26. Trabalho com ordens pendentes, primeira implementação (abertura de posições)
Parte 27. Trabalho com ordens pendentes, posicionamento de ordens pendentes Parte 28. Trabalho com ordens pendentes de negociação - fechamento, exclusão, modificações