Bibliothek für ein leichtes und schnelles Entwickeln vom Programmen für den MetaTrader (Teil XXIX): Schwebende Handelsanfrage - die Klasse der Anfrageobjekte

Artyom Trishkin | 16 März, 2020

Inhalt


Konzept

In den drei vorhergehenden Artikeln haben wir das Konzept der Verwaltung von Handelsmethoden der Handelsklasse anhand von schwebende Anfragen überprüft.
Eine schwebende Anfrage ist in der Tat ein gewöhnlicher Handelsauftrag, der unter einer bestimmten Bedingung ausgeführt wird. Wir haben die Bedingung der Verzögerung des Sendens einer Handelsorder bei den Handelsmethoden geprüft, wenn wir den Serverfehler erhalten, dessen Behandlung eine gewisse Wartezeit erfordert, bevor die Anfrage erneut an den Server gesendet wird. Dies sind natürlich nicht alle Bedingungen, unter denen schwebende Anfragen verwendet werden können. Zu den Bedingungen können auch Preisniveaus gehören, bei deren Erreichen ein Handelsauftrag gesendet wird. Es kann auch eine Kombination von Bedingungen sein, z.B. einige Schwellenwerte von Symboleigenschaften. Bei Erreichen dieser Werte wird eine Handelsorder an den Server gesendet (eine Stop-Limit-Order ist ein gutes Beispiel für eine schwebende Handelsanfrage zur Platzierung einer Limit-Order, wenn der Preis ein Stop-Order-Niveau erreicht).

Im Allgemeinen erlauben uns schwebende Handelsanfrage, eine Art Verhaltenslogik für das Senden von Handelsaufträgen an den Server zu erstellen.

Um all dies an den Objektcode der schwebenden Anfrage anzupassen, muss er jedoch dem Allgemeinen Konzept der Bibliotheksobjekte entsprechen. Dies macht Objekte leicht erweiterbar, um neue Eigenschaften in sie einzufügen. Zum gegenwärtigen Zeitpunkt befindet sich der Code für die Behandlung von schwebenden Handelsanfragen direkt im Code der Handelsklasse. Dies dient lediglich der Überprüfung des Konzepts und ist für die weitere Verwendung konzeptionell falsch. Ich habe dies absichtlich getan, um alles schnell zu überprüfen, bevor ich die Konstruktion in die richtige Form bringe.
Im aktuellen Artikel werden wir die Basisklasse des abstrakten Objekts einer schwebenden Handelsanfrage und die abgeleiteten Objektklassen des Objekts der Basisanfrage erstellen. Das Basisobjekt soll Eigenschaften enthalten, die für die Eigenschaften aller Anfrageobjekte gemeinsam sind, während die abgeleiteten Objekte individuelle Eigenschaften enthalten, die dem Status jedes abgeleiteten Objekts entsprechen. Dies geschieht für alle Bibliotheksobjekte, und der aktuelle Fall bildet keine Ausnahme.

Aber zuerst erstellen wir wie üblich die für die Handhabung der Objekte notwendigen Bibliotheksnachrichten.

Hier schreiben wir die Indizes der neuen Bibliotheksnachrichten in die Datei Datas.mqh:

...

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


und die den neuen Indices entsprechenden Nachrichten:

   {" и паузой "," 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"},
  };


Wie bereits oben erwähnt, ist das Basisobjekt einer anhängigen Handelsanfrage eine allgemeine abstrakte Anfrage, die die in allen Handelsanfragen vorhandenen Eigenschaften enthält, während die Aufgabe der Klärung der Eigenschaften den nachkommenden Objekten des Basisobjekts zugewiesen wird.
Wir werden also ein einziges Basisanfrageobjekt und sechs abgeleitete Objekte haben, die die Eigenschaften einer schwebenden Anfrage nach der Art der durchgeführten Handelsoperation klären:

Das Basisobjekt der abstrakten Handelsanfrage

Erstellen wir die Enumeration der Eigenschaften des Objekts der schwebenden Handelsanfrage, wie für alle vorherigen Bibliotheksobjekte.

In der Datei Defines.mqh fügen wir die Enumerationen der Objektzustände, sowie die Eigenschaften der Typen ganzzahlig, real und Zeichenketten hinzu:

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


Makro-Substitutionen, die die Anzahl der einzelnen Eigenschaftstypen angeben, werden zur Berechnung der Eigenschaftsindizierung in den Objekteigenschafts-Arrays verwendet.
Wir haben dies im ersten Artikel bei der Beschreibung der Bibliotheksgeneration berücksichtigt. Es hat keinen Sinn, hier darauf einzugehen.

Wie wir im Code sehen können, umfassen die Objekteigenschaften sowohl die Eigenschaften, die zu den Parametern für die Erstellung einer anstehenden Anfrage gehören, als auch die Eigenschaften, die in der Struktur MqlTradeRequest Handelsanfrage angegeben sind, in der alle Parameter einer an den Server gesendeten Anfrage festgelegt sind.
Da wir die Objekte in der Liste nach jedem ihrer Parameter sortieren und suchen wollen (genau wie alle vorherigen Bibliotheksobjekte), kopieren wir den gesamten Inhalt der Struktur der Handelsanfrage in die entsprechenden Objekteigenschaften und wiederholen dabei den Zweck der Strukturfelder. In diesem Fall können wir nach den schwebenden Anfragen in der Liste nach jeder beliebigen Eigenschaft suchen und sortieren.

Um nach Objekten der schwebenden Anfragen zu suchen und zu sortieren, listen wir alle möglichen Sortierkriterien der Objekte auf:

//+------------------------------------------------------------------+
//| 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
  {
//--- Sortieren nach den Integer-Eigenschaften
   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
//--- Sortieren nach den Double-Eigenschaften
   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
//--- Sortieren nach den Zeichenketten-Eigenschaften
   //--- 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
  };
//+------------------------------------------------------------------+

In einer separaten Datei erstellen wir eine neue Klasse des abstrakten Basisobjekts einer schwebenden Anfrage.

Wir erstellen auch im Bibliotheksverzeichnis \MQL5\Include\DoEasy\Objects\ einen neuen Unterordner PendRequest\ zur Speicherung von Dateien der Klassen der schwebenden Handelsanfragen.

Erstellen wir jetzt eine neue Klasse des abstrakten Basisobjekts für schwebende Anfragen in der Datei PendRequest.mqh des Verzeichnises PendRequest:

//+------------------------------------------------------------------+
//|                                                  PendRequest.mqh |
//|                        Copyright 2019, MetaQuotes Software Corp. |
//|                             https://mql5.com/de/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2019, MetaQuotes Software Corp."
#property link      "https://mql5.com/de/users/artmedia70"
#property version   "1.00"
#property strict    // Notwendig für mql4
//+------------------------------------------------------------------+
//| Include-Dateien                                                  |
//+------------------------------------------------------------------+
#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' Konstruktor
                     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:
//--- Standardmäßiger Konstruktor
                     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) kurze Ereignisnachrichten (implementiert in abgeleiteten Klassen) im Journal
   void                 Print(const bool full_prop=false);
   virtual void         PrintShort(void){;}
  };
//+------------------------------------------------------------------+


Wir haben bereits viele Male identische Objekte mit einer detaillierten Beschreibung ihrer Struktur erstellt. Ich denke, es hat keinen Sinn, hier die Prinzipien der Objektstruktur noch einmal zu erläutern. Genau wie alle anderen, ähnlichen Objekte verfügt es über drei Arrays zum Speichern von Integer-, Real- und Zeichenketten-Eigenschaften. Außerdem bietet es die Methoden für den Zugriff auf diese Eigenschaften durch Angabe der Eigenschaftskonstante — GetProperty(), sowie vereinfachte Methoden mit selbsterklärenden Methodennamen. Es gibt auch Methoden, die Beschreibungen aller Objekteigenschaften anzeigen. Im Allgemeinen ist alles Standard für Bibliotheksobjekte. Sie können die Struktur der Bibliotheksobjekte im allerersten Artikel untersuchen.

Schreiben wir den geschlossenen Klassenkonstruktor außerhalb des Klassenkörpers:

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



Zunächst kopieren wir die Strukturdaten der Handelsanfrage in die Arrays von Integer-, Real- und Zeichenketten-Eigenschaften unter Verwendung der Methode CopyRequest(), die wir unten betrachten sollen.
Als Nächstes setzen wir das Flag für das Hedging-Konto, setzen die Anzahl der Dezimalstellen des Symbolpreises und in einen Wert für die Losgröße des Symbols (dies ist für die korrekte Anzeige der Informationen im Journal erforderlich). Wenn die Anzahl der Dezimalstellen der Losgröße Null ist, wird aus Gründen der Bequemlichkeit nur eine Dezimalstelle angezeigt: Statt "1" wird "1.0" angezeigt.
Als Nächstes setzen Sie einfach die übergebenen Werte einiger Eigenschaften an den Klassenkonstruktor, wenn Sie ein Anfrageobjekt für die Werte der entsprechenden Objekteigenschaften erstellen.
Auf diese Weise füllen wir alle Eigenschaften eines schwebenden Anfrageobjekts unmittelbar nach seiner Erstellung.

Die Methode des Vergleichs zweier Objekte der schwebenden Anfrage durch eine bestimmte Eigenschaft (Modus):

//+------------------------------------------------------------------+
//| Compare CPendRequest objects by a specified property             |
//+------------------------------------------------------------------+
int CPendRequest::Compare(const CObject *node,const int mode=0) const
  {
   const CPendRequest *compared_obj=node;
//--- Vergleich der Integer-Eigenschaften von zwei Ereignissen
   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);
     }
//--- Vergleich der Integer-Eigenschaften von zwei Objekten
   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);
     }
//--- Vergleich der Zeichenketten-Eigenschaften von zwei Objekten
   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;
  }
//+------------------------------------------------------------------+


Die Methode eines vollständigen Vergleichs von zwei schwebenden Anfrageobjekten nach allen ihren Eigenschaften:

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


Wir haben solche Methoden auch bei der Erstellung der früheren Bibliotheksobjekte berücksichtigt.
Wie Sie sich vielleicht erinnern, vergleicht die Methode Compare() eines Anfrageobjekts, das zum Vergleich nach einer bestimmten Eigenschaft verwendet wird, die angegebenen Eigenschaften des aktuellen Objekts der Klasse CPendRequest mit dem Objekt derselben Klasse, das an die Methode übergeben wurde. Wenn der aktuelle Objektwert den Wert eines verglichenen Objekts überschreitet, gibt die Methode 1 zurück, wenn er kleiner als der Wert eines verglichenen Objekts ist, gibt die Methode -1 zurück, andernfalls 0. Dies ist notwendig, um mit Listen von Zeigern auf Objekte zu arbeiten — mit seiner Methode Search(), die die virtuelle Methode Compare() des Standard-Basisobjekts der Bibliothek verwendet, für einen schnellen Vergleich. Da die Methode virtuell ist, sollte sie in den Nachkommen der Klasse CObject neu definiert werden. Genau das habe ich hier getan.
Die Methode IsEqual() vergleicht jede Eigenschaft von zwei verglichenen Objekten nacheinander und liefert false, sobald eine Ungleichheit festgestellt wird — die Objekte sind nicht gleich. Nach Abschluss von drei Schleifen durch alle Eigenschaften der beiden verglichenen Objekte wird true zurückgegeben — alle Objekteigenschaften sind gleich.

Die Methode zum Kopieren der Struktur der Handelsanfrage in die Arrays der Objekteigenschaften der schwebenden Anfrage:

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


Hier kopieren wir zunächst die Werte aller Felder der Struktur der Handelsanfrage, die an die Methode übergeben wurden, in dieselbe Struktur des Anfrageobjekts. Dann werden die Werte aller Strukturfelder für Objekteigenschaften mit den Methoden SetProperty() zur Platzierung von Eigenschaften gesetzt.

Die Methoden, die Beschreibungen von ganzzahligen, realen und Zeichenketten-Eigenschaften eines schwebenden Anfrageobjekts zurückgeben:

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


Die Methode erhält die Eigenschaft und ihre Zeichenkettenbeschreibung wird abhängig vom Eigenschaftswert unter Verwendung der Methoden, die die Eigenschaftsbeschreibung zurückgeben, zurückgegeben:

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


Der Wert der übergebenen Eigenschaft wird in den Methoden überprüft, ihre Textbeschreibung wird erstellt und die generierte Textzeile wird zurückgegeben.

Die Methode Print() wird verwendet, um alle Objekteigenschaften in das Journal zu schreiben:

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



Wir haben solche Methoden für alle früheren Bibliotheksobjekte erstellt und ihre Struktur von Anfang an analysiert, daher werde ich hier nur eine kurze Beschreibung geben:
Drei Schleifen der drei Arrays mit den Objekteigenschaften durchlaufen, jede aufeinander folgende Objekteigenschaft holen und ihre Beschreibung im Journal anzeigen, je nachdem, ob nur unterstützte Objekteigenschaften angezeigt werden sollen oder nicht.

Die Methode PrintShort() ist für die Anzeige einer kurzen Objektbeschreibung der Anfrage gedacht und wird virtuell gemacht. Sie bewirkt nichts im Basisobjekt und sollte in den Nachfolgeobjekten neu definiert werden, so dass jeder Nachkomme nur seine eigenen Eigenschaften im Journal anzeigen kann.

Wir haben das Basisobjekt der abstrakten Anfrage erstellt.
Um zu klären, welche Anfragen erzeugt werden soll, müssen wir sechs Nachfolgeobjekte auf der Grundlage des abstrakten Anfrageobjekts erstellen. Sie werden in den Handelsmethoden der Handelsklasse bei der Behandlung von Fehlern, die ein Warten erfordern, angelegt. Außerdem werden sie als unabhängige Handelsanfragen erstellt, wenn eine Handelslogik mit schwebenden Handelsanfragen erstellt wird.

Abgeleitete Objekte des Objekts einer abstrakten Handelsanfrage

Jede Handelsmethode der Handelsklasse verfügt über die Blöcke zur Erstellung von schwebenden Anfragen. Wir werden die entsprechenden schwebenden Anfragen auf der Grundlage der von der Handelsmethode durchgeführten Operation erstellen. Aber im Moment haben wir nur eine abstrakte Basis für die schwebenden Anfragen. Um verschiedene Handelsanfragen nach der Art der ausgeführten Operation zu erzeugen, müssen wir sechs Nachkommen erstellen, wobei jede Nachkommenklasse nur ihre eigene Handelsoperation an den Server sendet. Die Liste derartiger Objekte habe ich oben bereits bereitgestellt:

Wie Sie sich vielleicht erinnern, enthält der geschützte Konstruktor der abstrakten Basisanfrage den Parameter, der den Status der generierten Anfrage angibt:

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


Wir werden diesen Status (Übergang vom geerbten Objektkonstruktor zum Basisobjekt) anzeigen, wenn wir eine neue schwebende Anfrage erstellen. Dadurch können wir festlegen, welchen Anfragetyp wir durch eine ausgeführte Operation erzeugen. Wir haben dieses Verhalten im zweiten Artikel analysiert, wenn Objekte historischer Orders und Deals erzeugt werden. Daher werden wir an dieser Stelle nicht aufhören, sondern alle sechs Objekte der schwebenden Anfragen nach der Art der ausgeführten Handelsoperationen betrachten.
Alle Klassen der Nachfolgeobjekte des Basishandelsauftrags werden in demselben Ordner angelegt, in dem sich das Basisobjekt befindet:
\MQL5\Include\DoEasy\Objects\ PendRequest\

Die Klasse des Objekts der schwebende Anfrage zum Öffnen einer Position (PendReqOpen.mqh-Klassendatei):

//+------------------------------------------------------------------+
//|                                                  PendReqOpen.mqh |
//|                        Copyright 2019, MetaQuotes Software Corp. |
//|                             https://mql5.com/de/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2019, MetaQuotes Software Corp."
#property link      "https://mql5.com/de/users/artmedia70"
#property version   "1.00"
//+------------------------------------------------------------------+
//| Include-Dateien                                                  |
//+------------------------------------------------------------------+
#include "PendRequest.mqh"
//+------------------------------------------------------------------+
//| Pending request for opening a position                           |
//+------------------------------------------------------------------+
class CPendReqOpen : public CPendRequest
  {
public:
//--- Konstructor
                     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) {}
                                  
//--- Unterstützte Deal-Eigenschaften (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                      |
//| Integer-Eigenschaft unterstützt, sonst '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                      |
//| Double-Eigenschaft, sonst '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-Eigenschaft, sonst 'false'                                |
//+------------------------------------------------------------------+
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);
  }
//+------------------------------------------------------------------+


Die Methode ist recht einfach. Ihre einzige Funktion besteht darin, den Status eines erzeugten Objekts (Eröffnung einer Position) und alle Eingaben seines Konstruktors an den Basisobjektkonstruktor in der Initialisierungsliste zu übergeben:

//--- Konstructor
   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) {}


Die virtuellen Methoden geben die Flags der Unterstützung einiger ganzzahliger, realer und Zeichenketten-Eigenschaften durch das Objekt zurück:

//+------------------------------------------------------------------+
//| Return 'true' if an order supports a passed                      |
//| Integer-Eigenschaft unterstützt, sonst '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                      |
//| Double-Eigenschaft, sonst '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-Eigenschaft, sonst 'false'                                |
//+------------------------------------------------------------------+
bool CPendReqOpen::SupportProperty(ENUM_PEND_REQ_PROP_STRING property)
  {
   return true;
  }
//+------------------------------------------------------------------+


Wenn ein abgeleitetes Objekt der absrakten Basis einer schwebenden Anfrage keine Eigenschaft unterstützt, gibt die Methode 'false' zurück, andernfalls — 'true'. Wir haben dies bereits im zweiten Artikel berücksichtigt, wenn es darum geht, Objekte historischer Orders und Deals zu generieren.

Die virtuelle Methode zum Erstellen und Darstellung einer kurzen Anfragebeschreibung:

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


Die Zeilen, die einige vom Objekt verwendete Parameter beschreiben, werden in der Methode erstellt. Die abschließende Nachricht wird daraus zusammengestellt und im Journal angezeigt. Die Methode ist virtuell und auf ihre eigene Art und Weise in jedem der Nachfolgeobjekte des abstrakten Anfrage-Basisobjekts implementiert.

Die Klasse des schwebenden Anfrageobjekts zur Änderung von Stop-Orders einer offenen Position (PendReqSLTP.mqh Klassendatei):

//+------------------------------------------------------------------+
//|                                                  PendReqSLTP.mqh |
//|                        Copyright 2019, MetaQuotes Software Corp. |
//|                             https://mql5.com/de/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2019, MetaQuotes Software Corp."
#property link      "https://mql5.com/de/users/artmedia70"
#property version   "1.00"
//+------------------------------------------------------------------+
//| Include-Dateien                                                  |
//+------------------------------------------------------------------+
#include "PendRequest.mqh"
//+------------------------------------------------------------------+
//| Pending request to modify position stop orders                   |
//+------------------------------------------------------------------+
class CPendReqSLTP : public CPendRequest
  {
public:
//--- Konstructor
                     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) {}
                                  
//--- Unterstützte Deal-Eigenschaften (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                      |
//| Integer-Eigenschaft unterstützt, sonst '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                      |
//| Double-Eigenschaft, sonst '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-Eigenschaft, sonst 'false'                                |
//+------------------------------------------------------------------+
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);
  }
//+------------------------------------------------------------------+


Die Klasse des Objekts der schwebenden Anfrage zum Schließen einer Position (Datei der Klasse PendReqClose.mqh):

//+------------------------------------------------------------------+
//|                                                 PendReqClose.mqh |
//|                        Copyright 2019, MetaQuotes Software Corp. |
//|                             https://mql5.com/de/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2019, MetaQuotes Software Corp."
#property link      "https://mql5.com/de/users/artmedia70"
#property version   "1.00"
//+------------------------------------------------------------------+
//| Include-Dateien                                                  |
//+------------------------------------------------------------------+
#include "PendRequest.mqh"
//+------------------------------------------------------------------+
//| Pending request to close a position                              |
//+------------------------------------------------------------------+
class CPendReqClose : public CPendRequest
  {
public:
//--- Konstructor
                     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) {}
                                  
//--- Unterstützte Deal-Eigenschaften (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                      |
//| Integer-Eigenschaft unterstützt, sonst '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                      |
//| Double-Eigenschaft, sonst '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-Eigenschaft, sonst 'false'                                |
//+------------------------------------------------------------------+
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);
  }
//+------------------------------------------------------------------+


Die Klasse des Objekts der schwebenden Anfrage für das Erteilen einer Pending-Order (Datei der Klasse PendReqPlace.mqh):

//+------------------------------------------------------------------+
//|                                                 PendReqPlace.mqh |
//|                        Copyright 2019, MetaQuotes Software Corp. |
//|                             https://mql5.com/de/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2019, MetaQuotes Software Corp."
#property link      "https://mql5.com/de/users/artmedia70"
#property version   "1.00"
//+------------------------------------------------------------------+
//| Include-Dateien                                                  |
//+------------------------------------------------------------------+
#include "PendRequest.mqh"
//+------------------------------------------------------------------+
//| Pending request to place a pending order                         |
//+------------------------------------------------------------------+
class CPendReqPlace : public CPendRequest
  {
public:
//--- Konstructor
                     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) {}
                                  
//--- Unterstützte Deal-Eigenschaften (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                      |
//| Integer-Eigenschaft unterstützt, sonst '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                      |
//| Double-Eigenschaft, sonst 'false'                                |
//+------------------------------------------------------------------+
bool CPendReqPlace::SupportProperty(ENUM_PEND_REQ_PROP_DOUBLE property)
  {
   return true;
  }
//+------------------------------------------------------------------+
//| Return 'true' if an order supports a passed                      |
//| String-Eigenschaft, sonst 'false'                                |
//+------------------------------------------------------------------+
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);
  }
//+------------------------------------------------------------------+


Die Klasse des Objekts der schwebenden Anfrage zum Ändern der Parameter einer platzierten Pending-Order (Klassendatei PendReqModify.mqh):

//+------------------------------------------------------------------+
//|                                                PendReqModify.mqh |
//|                        Copyright 2019, MetaQuotes Software Corp. |
//|                             https://mql5.com/de/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2019, MetaQuotes Software Corp."
#property link      "https://mql5.com/de/users/artmedia70"
#property version   "1.00"
//+------------------------------------------------------------------+
//| Include-Dateien                                                  |
//+------------------------------------------------------------------+
#include "PendRequest.mqh"
//+------------------------------------------------------------------+
//| Pending request to modify pending order parameters               |
//+------------------------------------------------------------------+
class CPendReqModify : public CPendRequest
  {
public:
//--- Konstructor
                     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) {}
                                  
//--- Unterstützte Deal-Eigenschaften (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                      |
//| Integer-Eigenschaft unterstützt, sonst '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                      |
//| Double-Eigenschaft, sonst '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-Eigenschaft, sonst 'false'                                |
//+------------------------------------------------------------------+
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);
  }
//+------------------------------------------------------------------+


Die Klasse des Objekts der schwebenden Anfrage zum Entfernen einer Pending-Order (Datei der Klasse PendReqRemove.mqh):

//+------------------------------------------------------------------+
//|                                                PendReqRemove.mqh |
//|                        Copyright 2019, MetaQuotes Software Corp. |
//|                             https://mql5.com/de/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2019, MetaQuotes Software Corp."
#property link      "https://mql5.com/de/users/artmedia70"
#property version   "1.00"
//+------------------------------------------------------------------+
//| Include-Dateien                                                  |
//+------------------------------------------------------------------+
#include "PendRequest.mqh"
//+------------------------------------------------------------------+
//| Pending request to remove a pending order                        |
//+------------------------------------------------------------------+
class CPendReqRemove : public CPendRequest
  {
public:
//--- Konstructor
                     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) {}
                                  
//--- Unterstützte Deal-Eigenschaften (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                      |
//| Integer-Eigenschaft unterstützt, sonst '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                      |
//| Double-Eigenschaft, sonst '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-Eigenschaft, sonst 'false'                                |
//+------------------------------------------------------------------+
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);
  }
//+------------------------------------------------------------------+


Das wichtigste Unterscheidungsmerkmal all dieser Klassen ist das Übertragen des Status einer schwebenden Anfrage an den übergeordneten Objektkonstruktor - der Status bestimmt, welche Art von ausgeführter Handelsoperation jedes dieser Objekte durchzuführen ist. Die übrigen Klassenmethoden dienen nur zu Hilfszwecken und haben keinen Einfluss auf das Handelsergebnis.

Damit ist die Erstellung neuer Klassen von schwebenden Handelsanfragen abgeschlossen.
Jetzt müssen wir die Klasse der vorübergehend existierenden schwebenden Anfragen aus der Handelsklassen-Datei entfernen und zusätzliche Änderungen vornehmen, um mit neuen Objekten der schwebenden Handelsanfragen arbeiten zu können.

Wir öffnen Trading.mqh und entfernen die vorherige Klasse vollständig aus dem Code der schwebenden Anfragen:

//+------------------------------------------------------------------+
//|                                                      Trading.mqh |
//|                        Copyright 2019, MetaQuotes Software Corp. |
//|                             https://mql5.com/de/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2019, MetaQuotes Software Corp."
#property link      "https://mql5.com/de/users/artmedia70"
#property version   "1.00"
//+------------------------------------------------------------------+
//| Include-Dateien                                                  |
//+------------------------------------------------------------------+
#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
  {


Damit die Handelsklasse die Objekte der neuen Klassen der schwebenden Anfragen sehen kann, binden wir sie in die Datei der Handelsklassen ein:

//+------------------------------------------------------------------+
//|                                                      Trading.mqh |
//|                        Copyright 2019, MetaQuotes Software Corp. |
//|                             https://mql5.com/de/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2019, MetaQuotes Software Corp."
#property link      "https://mql5.com/de/users/artmedia70"
#property version   "1.00"
//+------------------------------------------------------------------+
//| Include-Dateien                                                  |
//+------------------------------------------------------------------+
#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"
//+------------------------------------------------------------------+


Die Methode zur Erstellung einer neuen schwebenden Anfrage übergibt nun zusätzlich den Status eines erstellten Handelsauftrags.
Fügen wir den Status zur Methodendeklaration hinzu:

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


Wir legen auch die Methode zur Implementierung einer neuen schwebenden Anfrage fest:

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


Nun erhält die Methode zusätzlich den Status des angelegten Objektes einer schwebenden Anfrage.
Zuvor war das Objekt einer schwebenden Anfrage vom Klassentyp CPendingReq. Jetzt wurde die Klasse vollständig entfernt, so dass wir derzeit eine neue Objektklasse CPendRequest der schwebenden Anfragen und seiner Nachkommen haben.
Daher verwenden wir beim Erstellen eines leeren Objekts das neue Basisobjekt einer abstrakten Abfrage CPendRequest.
Als Nächstes erstellen wir in Abhängigkeit von einem an die Methode übergebenen Status das entsprechende neue schwebende Anfrageobjekt.
Wenn das Objekt erfolgreich erstellt wurde, zeigt das Journal eine kurze Nachricht mit den Parametern einer erstellten schwebenden Handelsanfrage an.

Da wir nun ein neues Objekt der Klasse einer schwebenden Anfrage haben, ersetzen wir alle Vorkommnisse der vorherigen CPendingReq-Klasse durch CPendRequest im Code der Handelsklasse. Dies kann bequem mit Ctrl+H (Suchen und Ersetzen) erfolgen.

Bei der Erstellung neuer Objekte der schwebenden Anfragen sollen sie etwas mehr Daten über eine durchgeführte Handelsoperation erhalten. Grundsätzlich ist dies für die Anzeige im Journal notwendig. Die Daten werden durch das Schreiben zusätzlicher Daten in die Struktur der Handelsanfrage beim Erstellen eines neuen Objekts einer schwebenden Anfrage übergeben.

Wir setzen den Status der erstellten Anfragen in den Erstellungsblock der schwebenden Anfragen der Positionseröffnungsmethode:

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


In der Methode, die Stop-Orders einer offenen Position modifiziert, nämlich dort, wo die schwebenden Anfragen erstellt werden, übergeben wir jetzt dem Anfrageobjekt auch über die Struktur einen Ordertyp und ein Positionsvolumen und setzen den Status der erzeugten Order:

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


In der Methode zum Schließen der Position, nämlich in ihrem Block der Erstellung einer schwebenden Anfrage, übergeben wir dem Anfrageobjekt über die Struktur jetzt auch ein Ordertyp und ein Positionsvolumen hinzu und setzen den Status der angelegten Anfrage:

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


Ein Positionsvolumen kann bei der Methode (-1) negativ sein, was bedeutet, dass die Position vollständig geschlossen ist. Wenn das Volumen als ein bestimmter Wert angegeben wird, wird die Position teilweise geschlossen. All dies wird im Basis-Handelsobjekt eines Symbols behandelt, wenn eine Handelsanfrage an den Server gesendet wird.
Hier überprüfen wir sofort das an die Methode übergebene Volumen und tragen das erforderliche Volumen in die Struktur der Handelsanfrage ein.

In der Methode zum Schließen einer Position durch eine entgegengesetzte, fügen wir in ihrem Block zum Erstellen einer schwebenden Anfrage über die Struktur ein Ordertyp und ein Positionsvolumen hinzu und setzen den Status der erstellten Anfrage:

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


Angabe des Status der erstellten Anfrage im Erstellungsblock für schwebende Anfragen der Methode dafür:

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


In der Methode, die die Parameter der schwebenden Anfrage ändert, d.h. in seinem Erstellungsblock der schwebenden Anfrage, fügen wir die Übergabe eines Ordertyps an das Anfrageobjekt über die Struktur hinzu und setzen den Status der erstellten Anfrage:

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


In der Methode, die einen schwebende Anfrage entfernt, nämlich im Erstellungsblock der schwebenden Anfrage, fügen wir die Übergabe eines Ordertyps und eines Volumens seines Preises hinzu und setzen den Status der schwebenden Anfrage:

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


Wir haben zwei solcher Blöcke pro Handelsmethode. Daher müssen wir die Änderungen in beide einfügen.

Einstellen des Sortiertyps in den Methoden, die nach einer freien ID suchen und die Indizes der Anfrageobjekte zurückgeben:

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

Um ein Objekt anhand einer bestimmten Eigenschaft in der Liste mit der Methode Search() der Klasse der dynamischen Zeiger auf die Instanzen der Klasse CObject zu suchen, müssen wir die Methode Sort() der Basisklasse des dynamischen Variablenarrays CArray anwenden , um den Sortiertyp der Liste, in der die Suche durchgeführt wird, zu spezifizieren, da die Suche nur in sortierten Arrays durchgeführt wird. Genau das machen wir hier.

Verbessern wir nun die Anzeige von Nachrichten mit einer Handelsversuchsnummer im Journal im Timer der Klasse.
Ersetzen wir diesen Code:

      //--- 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)
        {


mit dem Folgendem:

      //--- 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)
        {


Dadurch erhalten wir eine informativere Journalmeldung über ein schwebendes Anfrageobjekt, für das der nächste Handelsversuch durchgeführt wird.

Damit sind alle notwendigen Änderungen abgeschlossen, die Bibliothek mit den schwebenden Handelsanfrageobjekten kann jetzt arbeiten.

Tests

Um die neue schwebenden Anfrageobjekte zu testen, verwenden wir den EA aus dem vorherigen Artikel und speichern ihn in \MQL5\Experts\TestDoEasy\ Part29\ unter dem Namen TestDoEasyPart29.mq5.

Wir müssen nur eine überflüssige Prüfung in den Blöcken der Schließung der Hälfte der Kauf- und Verkaufspositionen entfernen, da alles in den Handelsmethoden der Handelsklasse passiert.

In dem Block des teilweisen Schließens einer Kaufposition ersetzen wir den Code:

      //--- Wenn die Schaltfläche BUTT_CLOSE_BUY2 geklickt wurde: Schließen der Hälfte der Kaufposition mit Maximalgewinn
      else if(button==EnumToString(BUTT_CLOSE_BUY2))
        {
         //--- Abrufen der Liste aller offenen Positionen
         CArrayObj* list=engine.GetListMarketPosition();
         //--- Auswählen von nur Kaufpositionen aus der Liste
         list=CSelect::ByOrderProperty(list,ORDER_PROP_TYPE,POSITION_TYPE_BUY,EQUAL);
         //--- Sortieren der Liste nach Gewinn unter Berücksichtigung von Kommission und Swap
         list.Sort(SORT_BY_ORDER_PROFIT_FULL);
         //--- Abrufen des Index der Kaufposition mit Maximalgewinn
         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());
              }
           }
        }


mit den Folgenden:

      //--- Wenn die Schaltfläche BUTT_CLOSE_BUY2 geklickt wurde: Schließen der Hälfte der Kaufposition mit Maximalgewinn
      else if(button==EnumToString(BUTT_CLOSE_BUY2))
        {
         //--- Abrufen der Liste aller offenen Positionen
         CArrayObj* list=engine.GetListMarketPosition();
         //--- Auswählen von nur Kaufpositionen aus der Liste
         list=CSelect::ByOrderProperty(list,ORDER_PROP_TYPE,POSITION_TYPE_BUY,EQUAL);
         //--- Sortieren der Liste nach Gewinn unter Berücksichtigung von Kommission und Swap
         list.Sort(SORT_BY_ORDER_PROFIT_FULL);
         //--- Abrufen des Index der Kaufposition mit Maximalgewinn
         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);
           }
        }

Wir schreiben auch das teilweise Schließen der Verkaufsposition auf die gleiche Weise um:

      //--- Wenn die Schaltfläche BUTT_CLOSE_SELL2 geklickt wurde: Schließen der Hälfte der Verkaufsposition mit Maximalgewinn
      else if(button==EnumToString(BUTT_CLOSE_SELL2))
        {
         //--- Abrufen der Liste aller offenen Positionen
         CArrayObj* list=engine.GetListMarketPosition();
         //--- Auswählen von nur Verkaufspositionen aus der Liste
         list=CSelect::ByOrderProperty(list,ORDER_PROP_TYPE,POSITION_TYPE_SELL,EQUAL);
         //--- Sortieren der Liste nach Gewinn unter Berücksichtigung von Kommission und Swap
         list.Sort(SORT_BY_ORDER_PROFIT_FULL);
         //--- Abrufen des Index der Verkaufsposition mit Maximalgewinn
         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);
           }
        }

Kompilieren und starten wir den EA.

Derzeit habe ich vier aktive Pending-Orders. Deaktivieren wir die Schaltfläche "AutoTrading" und klicken auf die Schaltfläche "Delete pending" des Test-EAs, um alle Pending-Orders zu entfernen. Die folgenden Meldungen werden im Journal angezeigt:

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 


Wie wir sehen können, hat der EA vier Versuche unternommen, die vier Pending-Orders zu entfernen. Nachdem er sich dem Fehler des deaktivierten Handels von der Terminalseite aus gestellt hatte, hat er vier schwebende Anfragen erstellt, die von Kurznachrichten mit ihren Parametern begleitet wurden.

Dann ist es Zeit zu warten.
Nach einiger Zeit (20 Sekunden, obwohl das vom Eintreffen neuer Ticks abhängt) werden die Nachrichten von schwebende Anfrageobjekten über wiederholte Versuche, die vier Aufträge zu entfernen, im Journal angezeigt:

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


Warten Sie wieder auf den nächsten Handelsversuch. Wenn die Zeit gekommen ist, werden schwebende Anfrageobjekte aufgrund des Ablaufs der für alle Handelsversuche vorgesehenen Zeit entfernt:

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


Wenn die Schaltfläche AutoTrading innerhalb der für alle Handelsversuche vorgesehenen Zeit angeklickt wurde, würden die schwebenden Anfrageobjekte einen Befehl an den Server senden, um die Pending-Orders zu entfernen, und sie würden entfernt werden.

Auf genau die gleiche Weise habe ich die schwebenden Anfrageobjekte für das Schließen/Eröffnen von Positionen, das Platzieren von Orders, das Ändern von Positions-Stop-Orders und den Parametern von Pending-Order und das Schließen einer Position durch eine entgegengesetzte Position überprüft. Es stellte sich heraus, dass schwebenden Handelsanfragen in den meisten Fällen korrekt funktionieren. Wenn wir jedoch zuerst versuchen, eine Pending-Order zu modifizieren und sie dann erneut zu ändern, wird ein solcher Versuch scheitern. Dasselbe gilt für die Durchführung von zwei und mehr Handelsoperationen unter Verwendung desselben Tickets. Schwebende Anfragen werden einfach sofort nach der Erstellung mit dem Grund "Ausgeführt" entfernt. In den vorhergehenden Artikeln wurde die Überprüfung der Aktivierung von schwebenden Anfragen nur durch ein Ticket im Timer der Handelsklassen vorgenommen. Die Prüfmethode erkannte in der Konto-Historie, dass eine Operation mit einem bestimmten Ticket gerade ausgeführt wurde. Dementsprechend nahm das System an, dass alles funktionierte, und es war an der Zeit, dieses Anfrageobjekt zu entfernen. Wir werden das später korrigieren.

Bitte beachten Sie:

Die Entwicklung der Klasse der schwebenden Anfrageobjekte ist derzeit in Arbeit. Verwenden Sie daher die im Artikel beschriebenen Ergebnisse und den beigefügten Test EA nicht im realen Handel!
Der Artikel und seine Begleitmaterialien sind kein fertiges Produkt und sind in keiner Weise für den realen Handel bestimmt.
Stattdessen sind sie nur für den Demomodus oder den Tester bestimmt.

Was kommt als Nächstes?

Im nächsten Artikel werden wir die Klasse der Verwaltung von schwebenden Handelsanfragen schaffen und die Unfähigkeit beseitigen, die gleiche Handelsoperation mit der gleichen Order oder Position mehrmals hintereinander durchzuführen.

Alle Dateien der aktuellen Version der Bibliothek sind unten zusammen mit den Dateien der Test-EAs angehängt, die Sie testen und herunterladen können.
Stellen Sie Ihre Fragen, Kommentare und Vorschläge in den Kommentaren.

Zurück zum Inhalt

Frühere Artikel dieser Serie:

Teil 1. Konzept, Datenverwaltung.
Teil 2. Erhebung (Collection) historischer Aufträge und Deals.
Teil 3. Erhebung (Collection) von Marktorders und Positionen, Organisieren der Suche
Teil 4. Handelsereignisse. Konzept
Teil 5. Klassen und Kollektionen von Handelsereignissen. Senden von Ereignissen an das Programm
Teil 6. Ereignisse auf Netting-Konten
Teil 7. Ereignis der Aktivierung einer StopLimit-Order, Vorbereiten der Funktionsweise bei Änderungen von Orders und Positionen
Teil 8. Ereignisse von Änderungen von Orders und Positionen
Teil 9. Kompatibilität mit MQL4 — Datenvorbereitung
Teil 10. Kompatibilität mit MQL4 - Ereignisse der Positionseröffnung und Aktivierung von Pending-Orders
Teil 11. Kompatibilität mit MQL4 - Ereignisse des Schließens von Positionen
Teil 12. Objektklasse "Account" und die Kollektion von Konto-Objekten
Teil 13. Das Objekt der Kontoereignisse
Teil 14. Das Symbolobjekt
Teil 15. Die Kollektion der Symbolobjekte
Teil 16. Ereignisse der Kollektionssymbole
Teil 17. Interaktivität von Bibliotheksobjekten
Teil 18. Interaktivität des Kontos und aller anderen Bibliotheksobjekt
Teil 19. Klassenbibliothek für Nachrichten
Teil 20. Erstellen und Speichern von Programmressourcen
Teil 21. Handelsklassen - Plattformübergreifendes Basis-Handelsobjekt
Teil 22. Handelsklassen - Basisklasse des Handels, Verifikation der Einschränkungen
Teil 23. Handelsklasse - Basisklasse des Handels, Verifikation der Parameter
Teil 24. Trading classes - Handelsklassen, automatische Korrektur ungültiger Parametern
Teil 25. Handelsklassen - Basisklasse des Handels, Behandlung der Fehlermeldungen vom Server
Teil 26. Arbeiten mit schwebenden Handelsanfragen - Erste Implementation (Öffnen von Positionen)
Teil 27. Arbeiten mit schwebenden Handelsanfragen - Platzieren von Pending-Orders
Teil 28. Arbeiten mit schwebenden Handelsanfragen - Schließen, Entfernen und Ändern