Bibliothek für ein leichtes und schnelles Entwickeln vom Programmen für den MetaTrader (Teil XXIX): Schwebende Handelsanfrage - die Klasse der Anfrageobjekte
Inhalt
- Konzept
- Das Basisobjekt der abstrakten Handelsanfrage
- Abgeleitete Objekte des Objekts einer abstrakten Handelsanfrage
- Tests
- Was kommt als Nächstes?
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).
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:
- Eröffnung einer Position (eine neue Position auf einem Hedge-Konto, wobei das Volumen hinzugefügt und auf einem Netting-Konto rückgängig
gemacht wird);
- die Änderung von Stop-Orders einer offenen Position;
- Schließen einer Position — vollständiges und teilweises Schließen, sowie das Schließen durch eine entgegengesetzte Order (auf einem
Hedge-Konto);
- Platzierung einer Pending-Order;
- Änderung der Eigenschaften von Pending Orders — Preise für Stop-Order, Orderplatzierung, der StopLimit-Order, die Order-Laufzeit,
Ausfüllungsart und Verfallsart;
- Entfernen einer zuvor platzierten Pending-Order.
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:
- Öffnen einer Position
- Ändern der Stopp-Orders einer offenen Position
- Schließen einer Position
- Platzieren einer Pending-Order
- Ändern der Eigenschaften der Pending-Orders
- Entfernen einer zuvor platzierten Pending-Order
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.
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
Übersetzt aus dem Russischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/ru/articles/7454
- Freie Handelsapplikationen
- Über 8.000 Signale zum Kopieren
- Wirtschaftsnachrichten für die Lage an den Finanzmärkte
Sie stimmen der Website-Richtlinie und den Nutzungsbedingungen zu.