English Русский 中文 Español 日本語 Português
Bibliothek für ein leichtes und schnelles Entwickeln vom Programmen für den MetaTrader (Teil II). Erhebung (Collection) historischer Aufträge und Deals

Bibliothek für ein leichtes und schnelles Entwickeln vom Programmen für den MetaTrader (Teil II). Erhebung (Collection) historischer Aufträge und Deals

MetaTrader 5Beispiele | 7 Mai 2019, 08:48
695 3
Artyom Trishkin
Artyom Trishkin

Inhalt

Im vorherigen Artikel haben wir begonnen, eine große plattformübergreifende Bibliothek zu erstellen, die die Entwicklung von Programmen für MetaTrader 5 und MetaTrader 4 Plattformen vereinfacht. Wir haben das abstrakte Objekt COrder angelegt, das als Basisobjekt für die Speicherung von Daten zu historischen Aufträgen und Deals sowie zu Marktorders und Positionen dient.

In diesem Teil werden wir alle notwendigen Objekte entwickeln, um die Daten der Kontohistorie in "Collections" (Sammlungen bzw. Listen) zu speichern, die Collection der historischen Aufträge (Order) und Deals (Transaktionen) vorzubereiten sowie bereits erstellte Objekte und Enumerationen zu modifizieren und zu verbessern.

Objekte historischer Aufträge und Deals

Das Basisobjekt COrder enthält alle Daten zu einem beliebigen Kontoobjekt, sei es eine Marktorder (ein Auftrag zur Durchführung einer Aktion), eine Pending-Order, ein Deal (Transaktion) oder eine Position. Damit wir alle diese Objekte getrennt voneinander verwenden können, werden wir mehrere Klassen auf Basis der abstrakten COrder entwickeln. Diese Klassen zeigen die Zugehörigkeit des Objekts zu seinem Typ genau an.

Die Liste der historischen Aufträge und Deals kann mehrere Arten solcher Objekte enthalten: entfernte Pending-Orders, erteilte Marktorder und Deals (Ergebnisse der Auftragsausführung). Es gibt noch zwei weitere Objekttypen in MQL4: Saldo und Korrekturbuchungen (in MQL5 werden diese Daten in den Deal-Eigenschaften gespeichert).

Wir erstellen die neue Klasse CHistoryOrder im Ordner Objects der Bibliothek.
Dazu klicken wir mit der rechten Maustaste auf den Ordner Objekte und wählen den Menüpunkt "Neue Datei" (Strg+N). Im neu geöffneten MQL5-Assistenten wählen wir "Neue Klasse" und klicken auf "Weiter". Jetzt geben wir CHistoryOrder (1) in das Feld Klassenname ein, geben den Namen der abstrakten Klasse COrder (2) in das Feld der Basisklasse ein und klicken auf "Fertig stellen".


Danach wird die Datei HistoryOrder.mqh (3) im Ordner Objects erzeugt. Wir öffnen sie:

//+------------------------------------------------------------------+
//|                                                 HistoryOrder.mqh |
//|                        Copyright 2018, MetaQuotes Software Corp. |
//|                             https://mql5.com/en/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2018, MetaQuotes Software Corp."
#property link      "https://mql5.com/en/users/artmedia70"
#property version   "1.00"
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class CHistoryOrder : public COrder
  {
private:

public:
                     CHistoryOrder();
                    ~CHistoryOrder();
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
CHistoryOrder::CHistoryOrder()
  {
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
CHistoryOrder::~CHistoryOrder()
  {
  }
//+------------------------------------------------------------------+

Im Moment ist dies nur die Vorlage für eine Klasse. Wenn wir versuchen, sie zu kompilieren, werden wir die fünf bereits bekannten Fehler sehen — die neue Klasse, die von COrder abgeleitet wurde, weiß nichts von ihre übergeordnete Klasse. Einbinden der Datei Order.mqh:

//+------------------------------------------------------------------+
//|                                                 HistoryOrder.mqh |
//|                        Copyright 2018, MetaQuotes Software Corp. |
//|                             https://mql5.com/en/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2018, MetaQuotes Software Corp."
#property link      "https://mql5.com/en/users/artmedia70"
#property version   "1.00"
//+------------------------------------------------------------------+
//| Include-Dateien                                                  |
//+------------------------------------------------------------------+
#include "Order.mqh"
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class CHistoryOrder : public COrder
  {
private:

public:
                     CHistoryOrder();
                    ~CHistoryOrder();
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
CHistoryOrder::CHistoryOrder()
  {
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
CHistoryOrder::~CHistoryOrder()
  {
  }
//+------------------------------------------------------------------+

Jetzt kompiliert alles ohne Probleme.

Die Klasse wird ziemlich klein sein. Wir müssen die Methoden der übergeordneten Klasse COrder neu definieren, die das Flag der zurückgibt, sowie das Ticket des Auftrags an die Klasse im Konstruktor übergibt:

//+------------------------------------------------------------------+
//|                                                 HistoryOrder.mqh |
//|                        Copyright 2018, MetaQuotes Software Corp. |
//|                             https://mql5.com/en/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2018, MetaQuotes Software Corp."
#property link      "https://mql5.com/en/users/artmedia70"
#property version   "1.00"
//+------------------------------------------------------------------+
//| Include-Dateien                                                  |
//+------------------------------------------------------------------+
#include "Order.mqh"
//+------------------------------------------------------------------+
//| Historische Marktorder                                           |
//+------------------------------------------------------------------+
class CHistoryOrder : public COrder
  {
public:
   //--- Konstructor
                     CHistoryOrder(const ulong ticket) : COrder(ORDER_STATUS_HISTORY_ORDER,ticket) {}
   //--- Unterstützte Integer-Eigenschaften der Aufträge
   virtual bool      SupportProperty(ENUM_ORDER_PROP_INTEGER property);
  };
//+------------------------------------------------------------------+
//| Rückgabe von 'true', falls der Auftrag die übergebene            |
//| Eigenschaft unterstützt, sonst 'false'                           |
//+------------------------------------------------------------------+
bool CHistoryOrder::SupportProperty(ENUM_ORDER_PROP_INTEGER property)
  {
   if(property==ORDER_PROP_TIME_EXP       || 
      property==ORDER_PROP_DEAL_ENTRY     || 
      property==ORDER_PROP_TIME_UPDATE    || 
      property==ORDER_PROP_TIME_UPDATE_MSC
     ) return false;
   return true;
  }
//+------------------------------------------------------------------+

Somit wird das Ticket des ausgewählten Auftrags an den Klassenkonstruktor übergeben, während ein Order-Status (historischer Auftrag) und sein Ticket an den 'protected' Konstruktor des übergeordneten Objekts COrder übergeben werden.

Wir haben auch die virtuelle Methode der übergeordneten Klasse neu definiert, die die Unterstützung für die Integer-Eigenschaften der Aufträge zurückgibt. Die Methoden, die die Unterstützung für die Real- und String-Eigenschaften des Auftrags zurückgeben, wurden unverändert gelassen — diese Methoden der Elternklasse geben immer 'true' zurück, und wir werden davon ausgehen, dass ein historischer Auftrag alle Real- und String-Eigenschaften unterstützt, so dass wir sie noch nicht neu definieren werden.

Überprüfen wir der Eigenschaft in der Methode, die die Integer-Eigenschaften der Order unterstützt. Wenn es sich um eine Verfallszeit, eine Deal-Richtung oder eine Positionsänderungszeit handelt, wird 'false' zurückgegeben. Solche Eigenschaften werden nicht von eine Marktorder unterstützt. Alle anderen Eigenschaften werden unterstützt und 'true' wird zurückgegeben.

Erstellen wir in ähnlicher Weise die Klasse CHistoryPending des historischen (entfernten) ausstehenden Auftrags und die Klasse CHistoryDeal des historischen Geschäfts:

//+------------------------------------------------------------------+
//|                                               HistoryPending.mqh |
//|                        Copyright 2018, MetaQuotes Software Corp. |
//|                             https://mql5.com/en/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2018, MetaQuotes Software Corp."
#property link      "https://mql5.com/en/users/artmedia70"
#property version   "1.00"
//+------------------------------------------------------------------+
//| Include-Dateien                                                  |
//+------------------------------------------------------------------+
#include "Order.mqh"
//+------------------------------------------------------------------+
//| Entfernte Pending-Order                                          |
//+------------------------------------------------------------------+
class CHistoryPending : public COrder
  {
public:
   //--- Konstructor
                     CHistoryPending(const ulong ticket) : COrder(ORDER_STATUS_HISTORY_PENDING,ticket) {}
   //--- Unterstützte Order-Eigenschaften (1) real, (2) integer
   virtual bool      SupportProperty(ENUM_ORDER_PROP_DOUBLE property);
   virtual bool      SupportProperty(ENUM_ORDER_PROP_INTEGER property);
  };
//+------------------------------------------------------------------+
//| Rückgabe von 'true', falls der Auftrag die übergebene            |
//| Eigenschaft unterstützt, sonst 'false'                           |
//+------------------------------------------------------------------+
bool CHistoryPending::SupportProperty(ENUM_ORDER_PROP_INTEGER property)
  {
   if(property==ORDER_PROP_PROFIT_PT         ||
      property==ORDER_PROP_DEAL_ORDER        ||
      property==ORDER_PROP_DEAL_ENTRY        ||
      property==ORDER_PROP_TIME_UPDATE       ||
      property==ORDER_PROP_TIME_UPDATE_MSC   ||
      property==ORDER_PROP_TICKET_FROM       ||
      property==ORDER_PROP_TICKET_TO         ||
      property==ORDER_PROP_CLOSE_BY_SL       ||
      property==ORDER_PROP_CLOSE_BY_TP
     ) return false;
   return true;
  }
//+------------------------------------------------------------------+
//| Rückgabe von 'true', falls der Auftrag die übergebene            |
//| Eigenschaft unterstützt, sonst 'false'                           |
//+------------------------------------------------------------------+
bool CHistoryPending::SupportProperty(ENUM_ORDER_PROP_DOUBLE property)
  {
   if(property==ORDER_PROP_COMMISSION  ||
      property==ORDER_PROP_SWAP        ||
      property==ORDER_PROP_PROFIT      ||
      property==ORDER_PROP_PROFIT_FULL ||
      property==ORDER_PROP_PRICE_CLOSE
     ) return false;
   return true;
  }
//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
//|                                                  HistoryDeal.mqh |
//|                        Copyright 2018, MetaQuotes Software Corp. |
//|                             https://mql5.com/en/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2018, MetaQuotes Software Corp."
#property link      "https://mql5.com/en/users/artmedia70"
#property version   "1.00"
//+------------------------------------------------------------------+
//| Include-Dateien                                                  |
//+------------------------------------------------------------------+
#include "Order.mqh"
//+------------------------------------------------------------------+
//| Historische Deals                                                |
//+------------------------------------------------------------------+
class CHistoryDeal : public COrder
  {
public:
   //--- Konstructor
                     CHistoryDeal(const ulong ticket) : COrder(ORDER_STATUS_DEAL,ticket) {}
   //--- Unterstützte Deal-Eigenschaften (1) real, (2) integer
   virtual bool      SupportProperty(ENUM_ORDER_PROP_DOUBLE property);
   virtual bool      SupportProperty(ENUM_ORDER_PROP_INTEGER property);
  };
//+------------------------------------------------------------------+
//| Rückgabe von 'true', falls der Auftrag die übergebene            |
//| Eigenschaft unterstützt, sonst 'false'                           |
//+------------------------------------------------------------------+
bool CHistoryDeal::SupportProperty(ENUM_ORDER_PROP_INTEGER property)
  {
   if(property==ORDER_PROP_TIME_EXP          || 
      property==ORDER_PROP_PROFIT_PT         ||
      property==ORDER_PROP_POSITION_BY_ID    ||
      property==ORDER_PROP_TIME_UPDATE       ||
      property==ORDER_PROP_TIME_UPDATE_MSC   ||
      property==ORDER_PROP_STATE             ||
      (
       this.OrderType()==DEAL_TYPE_BALANCE &&
       (
        property==ORDER_PROP_POSITION_ID     ||
        property==ORDER_PROP_POSITION_BY_ID  ||
        property==ORDER_PROP_TICKET_FROM     ||
        property==ORDER_PROP_TICKET_TO       ||
        property==ORDER_PROP_DEAL_ORDER      ||
        property==ORDER_PROP_MAGIC           ||
        property==ORDER_PROP_TIME_CLOSE      ||
        property==ORDER_PROP_TIME_CLOSE_MSC  ||
        property==ORDER_PROP_CLOSE_BY_SL     ||
        property==ORDER_PROP_CLOSE_BY_TP
       )
      )
     ) return false;
   return true;
  }
//+------------------------------------------------------------------+
bool CHistoryDeal::SupportProperty(ENUM_ORDER_PROP_DOUBLE property)
  {
   if(property==ORDER_PROP_TP                || 
      property==ORDER_PROP_SL                || 
      property==ORDER_PROP_PRICE_CLOSE       ||
      property==ORDER_PROP_VOLUME_CURRENT    ||
      property==ORDER_PROP_PRICE_STOP_LIMIT  ||
      (
       this.OrderType()==DEAL_TYPE_BALANCE &&
       (
        property==ORDER_PROP_PRICE_OPEN      ||
        property==ORDER_PROP_COMMISSION      ||
        property==ORDER_PROP_SWAP            ||
        property==ORDER_PROP_VOLUME
       )
      )
     ) return false;
   return true;
  }
//+------------------------------------------------------------------+

Wir haben drei Objekte für die Aufträge angelegt, auf denen die Collection der historischen Aufträge basieren soll. Alle werden von der abstrakten Basisklasse COrder abgeleitet. Sie haben ihre Eigenschaften, erlauben aber nur die Rückgabe der von diesem Auftragstyp unterstützten Eigenschaften. Sie alle sollen in einer einzigen Collection (Sammlung historischer Aufträge) zusammengefasst werden, aus der wir alle notwendigen Daten zur Kontohistorie in beliebiger Zusammensetzung und Reihenfolge erhalten.

Nicht alle unterstützten oder nicht unterstützten Eigenschaften werden in den Methoden SupportProperty() zur Anzeige von Auftragseigenschaften im Journal berücksichtigt. Beispielsweise werden bei Deals nur drei Arten berücksichtigt: Kaufen, Verkaufen und Saldo-Operationen.

Eigenschaften, die noch nicht berücksichtigt und nicht explizit in den Methoden angegeben sind, die sie unterstützen, werden immer gedruckt. Dann können wir sie der Methode hinzufügen, um die Eigenschaften nicht zu drucken, die unabhängig von der Situation immer Nullwerte liefern (nicht unterstützte).

Erhebung (Collection) historischer Aufträge und Deals

Es ist immer hilfreich, die Kontohistorie zur Hand zu haben. Das Terminal stellt sie zur Verfügung und es hat die Werkzeuge, damit Programme sie abrufen können. Unsere aktuellen Aufgaben erfordern jedoch eine benutzerdefinierte Liste, die wir sortieren und neu anordnen können, um die notwendigen Daten an unsere Programme zurückzugeben. Das bedeutet, dass die Änderung des Status der vorherigen Kontohistorie bei jedem Tick überprüft werden sollte. Wird eine Änderung festgestellt, soll die Liste der historischen Aufträge und Deals neu berechnet werden. Aber das Sortieren der gesamten Historie bei jedem Tick ist zu ressourcenintensiv. Daher werden wir nur Ergänzungen zu unserer Liste der neuen Daten vornehmen, während frühere Daten bereits in der Liste gespeichert sind.

Erstellen wir die neue Klasse CHistoryCollection im Ordner Collections:

Dazu klicken wir mit der rechten Maustaste auf den Ordner Collections, wählen "Neue Datei", wählen "Neue Klasse" im Fenster des MQL Wizards und klicken auf "Weiter". Dann tragen wir den Klassenname CHistoryCollection ein, lassen das Feld Basisklasse leer und klicken auf "Fertig stellen".


Die neue Datei HistoryCollection wird im Ordner Collections erzeugt:

//+------------------------------------------------------------------+
//|                                            HistoryCollection.mqh |
//|                        Copyright 2018, MetaQuotes Software Corp. |
//|                             https://mql5.com/en/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2018, MetaQuotes Software Corp."
#property link      "https://mql5.com/en/users/artmedia70"
#property version   "1.00"
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class CHistoryCollection
  {
private:

public:
                     CHistoryCollection();
                    ~CHistoryCollection();
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
CHistoryCollection::CHistoryCollection()
  {
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
CHistoryCollection::~CHistoryCollection()
  {
  }
//+------------------------------------------------------------------+

Tragen wir das jetzt ein.

Wir werden die dynamische Liste der Zeiger auf Objektinstanzen der Standardbibliothek CArrayObj für die Liste verwenden. Fügen wir sie in die Datei ein und definieren sie sofort (dies kann über das Kontextmenü mit der rechten Maustaste gemacht werden):


Einbinden von CArrayObj und definieren der Liste der historischen Aufträge und Geschäfte im 'private' Bereich der Klasse:

//+------------------------------------------------------------------+
//|                                            HistoryCollection.mqh |
//|                        Copyright 2018, MetaQuotes Software Corp. |
//|                             https://mql5.com/en/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2018, MetaQuotes Software Corp."
#property link      "https://mql5.com/en/users/artmedia70"
#property version   "1.00"
//+------------------------------------------------------------------+
//| Include-Dateien                                                  |
//+------------------------------------------------------------------+
#include <Arrays\ArrayObj.mqh>
//+------------------------------------------------------------------+
//| Collection der historischen Aufträge und Deals                   |
//+------------------------------------------------------------------+
class CHistoryCollection
  {
private:
   CArrayObj         m_list_all_orders;      // Liste der historischen Aufträge und Deals

public:
                     CHistoryCollection();
                    ~CHistoryCollection();
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
CHistoryCollection::CHistoryCollection()
  {
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
CHistoryCollection::~CHistoryCollection()
  {
  }
//+------------------------------------------------------------------+

Wir müssen Indizes der letzten Bestellungen und Geschäfte speichern, die der Collection hinzugefügt wurden. Außerdem müssen wir den Unterschied zwischen der vergangenen und der aktuellen Anzahl von Aufträgen und Deals kennen, deshalb werden wir private Klassenmitglieder erstellen, um sie zu speichern:

//+------------------------------------------------------------------+
//|                                            HistoryCollection.mqh |
//|                        Copyright 2018, MetaQuotes Software Corp. |
//|                             https://mql5.com/en/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2018, MetaQuotes Software Corp."
#property link      "https://mql5.com/en/users/artmedia70"
#property version   "1.00"
//+------------------------------------------------------------------+
//| Include-Dateien                                                  |
//+------------------------------------------------------------------+
#include <Arrays\ArrayObj.mqh>
//+------------------------------------------------------------------+
//| Collection der historischen Aufträge und Deals                   |
//+------------------------------------------------------------------+
class CHistoryCollection
  {
private:
   CArrayObj         m_list_all_orders;      // Liste der historischen Aufträge und Deals
   int               m_index_order;          // Index des letzten zur Collection hinzugefügten Auftrags aus der Liste der Terminalhistorie (MQL4, MQL5)
   int               m_index_deal;           // Index des letzten zur Collection hinzugefügten Deals aus der Liste der Terminalhistorie (MQL5)
   int               m_delta_order;          // Differenz der Auftragsanzahl im Vergleich zur vorherigen Prüfung
   int               m_delta_deal;           // Differenz der Anzahl der Deals im Vergleich zur vorherigen Prüfung
public:
                     CHistoryCollection();
                    ~CHistoryCollection();
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
CHistoryCollection::CHistoryCollection()
  {
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
CHistoryCollection::~CHistoryCollection()
  {
  }
//+------------------------------------------------------------------+

Beim ersten Start werden alle 'private' Mitglieder der Klasse zurückgesetzt und der Verlauf erneut berechnet. Dazu fügen wir einfach die Liste der Klassenmitglieder Initialisierung im Klassenkonstruktor hinzu und setzen das Standardkriterium, nach dem die Collection sortiert werden soll.

Derzeit haben wir den Standardkonstruktor. Bevor wir die Implementierung schreiben, sollten wir eine Enumeration erstellen, die alle möglichen Kriterien für die Sortierung von Bestellungen und Deals in der Collection enthält.
Aber zuerst ordnen wir die Eigenschaften Integer-, Real- und String-Order für ihre logischere Darstellung im Journal an. Wir öffnen die Datei Defines.mqh aus dem Stammverzeichnis der Bibliothek und platzieren die Elemente der Enumeration in der gewünschten Reihenfolge:

//+------------------------------------------------------------------+
//| Order, Deal, Position, Integer-Eigenschaften                     |
//+------------------------------------------------------------------+
enum ENUM_ORDER_PROP_INTEGER
  {
   ORDER_PROP_TICKET = 0,                                   // Order-Ticket
   ORDER_PROP_MAGIC,                                        // Magicnummer des Auftrags
   ORDER_PROP_TIME_OPEN,                                    // Eröffnungszeit (MQL5 Deal-Zeit)
   ORDER_PROP_TIME_CLOSE,                                   // Schlusszeit (MQL5 Zeit der Ausführung oder Entfernung - ORDER_TIME_DONE)
   ORDER_PROP_TIME_OPEN_MSC,                                // Eröffnungszeit in Millisekunden (MQL5 Deal-Zeit in msc)
   ORDER_PROP_TIME_CLOSE_MSC,                               // Schlusszeit in Millisekunden  (MQL5 Zeit der Ausführung oder Entfernung - ORDER_TIME_DONE_MSC)
   ORDER_PROP_TIME_EXP,                                     // Verfallszeit der Order (für Pending-Orders)
   ORDER_PROP_STATUS,                                       // Order-Status (aus der Enumeration ENUM_ORDER_STATUS)
   ORDER_PROP_TYPE,                                         // Auftragstyp (MQL5 Deal-Typ)
   ORDER_PROP_DIRECTION,                                    // Richtung (Buy, Sell)
   ORDER_PROP_REASON,                                       // Deal/Order/Position Grund oder Quelle
   ORDER_PROP_POSITION_ID,                                  // Positions-ID
   ORDER_PROP_POSITION_BY_ID,                               // Entgegengesetzte Positions-ID
   ORDER_PROP_DEAL_ORDER,                                   // Basis des Auftrags oder Deals
   ORDER_PROP_DEAL_ENTRY,                                   // Deal-Richtung – IN, OUT oder IN/OUT
   ORDER_PROP_TIME_UPDATE,                                  // Zeit der Positionsänderung in Sekunden
   ORDER_PROP_TIME_UPDATE_MSC,                              // Zeit der Positionsänderung in Millisekunden
   ORDER_PROP_TICKET_FROM,                                  // Ticket der Ober-Order
   ORDER_PROP_TICKET_TO,                                    // Ticket der abgeleiteten Order
   ORDER_PROP_PROFIT_PT,                                    // Gewinn in Points
   ORDER_PROP_CLOSE_BY_SL,                                  // Flag für das Schließen durch StopLoss
   ORDER_PROP_CLOSE_BY_TP,                                  // Flag für das Schließen mit TakeProfit
  }; 
#define ORDER_PROP_INTEGER_TOTAL    (22)                    // Gesamtzahl der Integer-Eigenschaften
//+------------------------------------------------------------------+
//| Order, Deal, Position Real-Eigenschaften                         |
//+------------------------------------------------------------------+
enum ENUM_ORDER_PROP_DOUBLE
  {
   ORDER_PROP_PRICE_OPEN = ORDER_PROP_INTEGER_TOTAL,        // Eröffnungspreis (MQL5 Deal-Preis)
   ORDER_PROP_PRICE_CLOSE,                                  // Schlusskurs
   ORDER_PROP_SL,                                           // Preis des StopLoss'
   ORDER_PROP_TP,                                           // Preis des TakeProfits
   ORDER_PROP_PROFIT,                                       // Gewinn
   ORDER_PROP_COMMISSION,                                   // Kommission
   ORDER_PROP_SWAP,                                         // Swap
   ORDER_PROP_VOLUME,                                       // Volumen
   ORDER_PROP_VOLUME_CURRENT,                               // Nicht ausgeführtes Volumen
   ORDER_PROP_PROFIT_FULL,                                  // Gewinn+Kommission+Swap
   ORDER_PROP_PRICE_STOP_LIMIT,                             // Preis der Limit-Order, wenn eine StopLimit-Order aktiviert ist
  };
#define ORDER_PROP_DOUBLE_TOTAL     (11)                    // Gesamtzahl der Real-Eigenschaften
//+------------------------------------------------------------------+
//| Order, Deal, Position, String-Eigenschaften                      |
//+------------------------------------------------------------------+
enum ENUM_ORDER_PROP_STRING
  {
   ORDER_PROP_SYMBOL = (ORDER_PROP_INTEGER_TOTAL+ORDER_PROP_DOUBLE_TOTAL), // Order-Symbol
   ORDER_PROP_COMMENT,                                      // Order-Kommentar
   ORDER_PROP_EXT_ID                                        // Order-ID im externen Handelssystem
  };
#define ORDER_PROP_STRING_TOTAL     (3)                     // Gesamtzahl der String-Eigenschaften
//+------------------------------------------------------------------+

Fügen wir nun die Enumeration mit allen möglichen Arten von Aufträgen und Deal-Sortierung zur gleichen Datei hinzu:

//+------------------------------------------------------------------+
//| Mögliche Sortierkriterien von Aufträgen und Deals                |
//+------------------------------------------------------------------+
enum ENUM_SORT_ORDERS_MODE
  {
   //--- Sortieren nach den Integer-Eigenschaften
   SORT_BY_ORDER_TICKET          =  0,                      // Sortieren nach Auftrags-Ticket
   SORT_BY_ORDER_MAGIC           =  1,                      // Sortieren nach der Magicnummer
   SORT_BY_ORDER_TIME_OPEN       =  2,                      // Sortieren nach Eröffnungszeit
   SORT_BY_ORDER_TIME_CLOSE      =  3,                      // Sortieren nach Schlusszeit
   SORT_BY_ORDER_TIME_OPEN_MSC   =  4,                      // Sortieren nach Eröffnungszeit des Auftrags in Millisekunden
   SORT_BY_ORDER_TIME_CLOSE_MSC  =  5,                      // Sortieren nach der Schlusszeit des Auftrags in Millisekunden
   SORT_BY_ORDER_TIME_EXP        =  6,                      // Sortieren nach der Verfallszeit
   SORT_BY_ORDER_STATUS          =  7,                      // Sortieren nach dem Auftragsstatus (Marktorder/Pending-Order/Deal)
   SORT_BY_ORDER_TYPE            =  8,                      // Sortieren nach dem Auftragstyp
   SORT_BY_ORDER_REASON          =  10,                     // Sortieren nach Grund/Quelle von Auftrag/Deal/Position
   SORT_BY_ORDER_POSITION_ID     =  11,                     // Sortieren nach der Positions-ID
   SORT_BY_ORDER_POSITION_BY_ID  =  12,                     // Sortieren nach der ID der entgegengesetzten Position
   SORT_BY_ORDER_DEAL_ORDER      =  13,                     // Sortieren nach dem Auftrag als Basis des Deals
   SORT_BY_ORDER_DEAL_ENTRY      =  14,                     // Sortieren nach der Richtung der Deals – IN, OUT oder IN/OUT
   SORT_BY_ORDER_TIME_UPDATE     =  15,                     // Sortieren nach der Änderungszeit der Position in Sekunden
   SORT_BY_ORDER_TIME_UPDATE_MSC =  16,                     // Sortieren nach der Änderungszeit der Position in Millisekunden
   SORT_BY_ORDER_TICKET_FROM     =  17,                     // Sortieren nach dem Tickets der Ober-Order
   SORT_BY_ORDER_TICKET_TO       =  18,                     // Sortieren nach der Ticket der abgeleiteten Order
   SORT_BY_ORDER_PROFIT_PT       =  19,                     // Sortieren nach dem Auftragsgewinn in Points
   SORT_BY_ORDER_CLOSE_BY_SL     =  20,                     // Sortieren nach dem Flag für das Schließen durch StopLoss
   SORT_BY_ORDER_CLOSE_BY_TP     =  21,                     // Sortieren nach dem Flag für das Schließen durch TakeProfit
   //--- Sortieren nach den Real-Eigenschaften
   SORT_BY_ORDER_PRICE_OPEN      =  ORDER_PROP_INTEGER_TOTAL,// Sortieren nach dem Eröffnungspreis
   SORT_BY_ORDER_PRICE_CLOSE     =  23,                     // Sortieren nach dem Schlusskurs
   SORT_BY_ORDER_SL              =  24,                     // Sortieren nach StopLoss
   SORT_BY_ORDER_TP              =  25,                     // Sortieren nach TakeProfit
   SORT_BY_ORDER_PROFIT          =  26,                     // Sortieren nach dem Gewinn
   SORT_BY_ORDER_COMMISSION      =  27,                     // Sortieren nach der Kommission
   SORT_BY_ORDER_SWAP            =  28,                     // Sortieren nach dem Swap
   SORT_BY_ORDER_VOLUME          =  29,                     // Sortieren nach dem Volumen
   SORT_BY_ORDER_VOLUME_CURRENT  =  30,                     // Sortieren nach dem nicht ausgeführten Volumen
   SORT_BY_ORDER_PROFIT_FULL     =  31,                     // Sortieren nach dem Kriterium Gewinn+Kommission+Swap
   SORT_BY_ORDER_PRICE_STOP_LIMIT=  32,                     // Sortieren nach der Limit-Order nach dem die StopLimit-Order aktiviert worden war
   //--- Sortieren nach den String-Eigenschaften
   SORT_BY_ORDER_SYMBOL          =  ORDER_PROP_INTEGER_TOTAL+ORDER_PROP_DOUBLE_TOTAL,// Sort by symbol
   SORT_BY_ORDER_COMMENT         =  34,                     // Sortieren nach dem Kommentar
   SORT_BY_ORDER_EXT_ID          =  35                      // Sortieren nach der ID des externen Handelssystems
  };
//+------------------------------------------------------------------+

Hinweis: Die Indizes der sortierenden Elemente der Enumeration sollten mit denen der Eigenschaften der Elemente der Enumeration übereinstimmen, da die Liste nach dem gleichen Wert sortiert werden sollte, der für die Suche in dieser Liste verwendet wird.

Wie wir sehen können, wurde die Sortiereigenschaft ORDER_PROP_DIRECTION in dieser Liste übersprungen, da es sich um eine Serviceeigenschaft handelt, die für die Bibliotheksanforderungen verwendet wird, genau wie andere benutzerdefinierte Eigenschaften, die wir zuvor hinzugefügt haben. Aber sie müssen vielleicht sortiert werden. Deshalb wurden sie weggelassen.

Nun können wir den Konstruktor der Klasse CHistoryCollection implementieren:

//+------------------------------------------------------------------+
//|                                            HistoryCollection.mqh |
//|                        Copyright 2018, MetaQuotes Software Corp. |
//|                             https://mql5.com/en/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2018, MetaQuotes Software Corp."
#property link      "https://mql5.com/en/users/artmedia70"
#property version   "1.00"
//+------------------------------------------------------------------+
//| Include-Dateien                                                  |
//+------------------------------------------------------------------+
#include <Arrays\ArrayObj.mqh>
#include "..\DELib.mqh"
//+------------------------------------------------------------------+
//| Collection historischer Aufträge und Deals                       |
//+------------------------------------------------------------------+
class CHistoryCollection
  {
private:
   CArrayObj         m_list_all_orders;      // Liste der historischen Aufträge und Deals
   int               m_index_order;          // Index des letzten zur Collection hinzugefügten Auftrags aus der Liste der Terminalhistorie (MQL4, MQL5)
   int               m_index_deal;           // Index des letzten zur Collection hinzugefügten Deals aus der Liste der Terminalhistorie (MQL5)
   int               m_delta_order;          // Differenz der Auftragsanzahl im Vergleich zur vorherigen Prüfung
   int               m_delta_deal;           // Differenz der Anzahl der Deals im Vergleich zur vorherigen Prüfung
public:
                     CHistoryCollection();
                    ~CHistoryCollection();
  };
//+------------------------------------------------------------------+
//| Konstruktor                                                      |
//+------------------------------------------------------------------+
CHistoryCollection::CHistoryCollection(void) : m_index_deal(0), 
                                               m_delta_deal(0), 
                                               m_index_order(0),
                                               m_delta_order(0) 
  {
   m_list_all_orders.Sort(SORT_BY_ORDER_TIME_CLOSE);
  }
//+------------------------------------------------------------------+

Analysieren wir den Code.
Da der Klassenkonstruktor nur den Wert einer neu hinzugefügten Enumeration verwendet, sollten wir die Datei Defines.mqh in die Klassendatei einbinden.
Bei der Vorbereitung der Basisklasse der abstrakten Order im ersten Artikel haben wir die Bibliothek DELib.mqh mit den Servicefunktionen entwickelt und die Datei Defines.mqh mit allen notwendigen Enumerationen und Makroersetzungen hinzugefügt. Daher werden wir auch die Bibliothek der Servicefunktionen einbinden.
In der Initialisierungsliste des Konstruktors werden alle Indizes und Werte der Differenzen zwischen der aktuellen und der vorherigen Nummer zurückgesetzt, und die Standardsortierung nach Schlusszeit wird im Konstruktorkörper angegeben
.

Jetzt ist es an der Zeit, mit dem Erfassen von Informationen aus dem Konto zu beginnen und diese in der Collection zu speichern. Dafür gehen wir in Schleifen durch die Kontohistorie und geben jede Reihenfolge in der Liste an. Wenn sich die Anzahl der Orders oder Deals gegenüber der vorherigen Prüfung geändert hat, setzen wir das Flag des eingetretenen Handelsereignisses. Es müssen Nachrichten über das aufgetretene neue Ereignis in der Kontohistorie an ein externes Programm gesendet werden.
Wir deklarieren das Flag des Handelsereignisses im Abschnitt 'private' der Klasse und die Methode Refresh() zum Aktualisieren der historischen Collection im Bereich 'public':

//+------------------------------------------------------------------+
//| Collection der historischen Aufträge und Deals                   |
//+------------------------------------------------------------------+
class CHistoryCollection
  {
private:
   CArrayObj         m_list_all_orders;      // Liste aller historischen Aufträge und Deals
   bool              m_is_trade_event;       // Flag des Handelsereignisses
   int               m_index_order;          // Index des letzten zur Collection hinzugefügten Auftrags aus der Liste der Terminalhistorie (MQL4, MQL5)
   int               m_index_deal;           // Index des letzten zur Collection hinzugefügten Deals aus der Liste der Terminalhistorie (MQL5)
   int               m_delta_order;          // Differenz der Auftragsanzahl im Vergleich zur vorherigen Prüfung
   int               m_delta_deal;           // Differenz der Anzahl der Deals im Vergleich zur vorherigen Prüfung
public:
                     CHistoryCollection();
   //--- Aktualisieren der Liste der Aufträge, Eintragen der neuen Daten und setzten des Flags der Handelsereignisse
   void              Refresh(void);
  };
//+------------------------------------------------------------------+

Um die Aktualisierung der Liste der Abholaufträge zu implementieren, benötigen wir eine weitere Makro-Substitution, um die vollständigen Verlaufsdaten abzurufen. Dazu wird die Funktion HistorySelect() verwendet. Das Datum des Beginns und des Endes der benötigten Daten werden als Argumente übergeben. Um die vollständige Liste der Kontohistorie zu erhalten, sollte das Anfangsdatum mit 0 und das Enddatum mit TimeCurrent() übergeben werden. In diesem Fall können die zurückgegebenen Verlaufsdaten jedoch manchmal unvollständig sein. Um dies zu vermeiden, geben wir anstelle von TimeCurrent() ein Datum ein, das größer ist, als die aktuelle Serverzeit. Ich werde das maximal mögliche Datum eingeben: 31.12.3000 23:59:59:59. Ein weiterer Vorteil ist, dass nutzerspezifische Symbole ein solches Datum enthalten können und das Abrufen der Historie weiterhin funktioniert.

Fügen wir eine neue Makro-Substitution in die Datei Defines.mqh ein:

//+------------------------------------------------------------------+
//|                                                      Defines.mqh |
//|                        Copyright 2018, MetaQuotes Software Corp. |
//|                             https://mql5.com/en/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2018, MetaQuotes Software Corp."
#property link      "https://mql5.com/en/users/artmedia70"
//+------------------------------------------------------------------+
//| Macro-Substitution                                               |
//+------------------------------------------------------------------+
#define COUNTRY_LANG   ("Russian")              // Landessprache
#define DFUN           (__FUNCTION__+": ")      // "Funktionsberechnung"
#define END_TIME       (D'31.12.3000 23:59:59') // Endzeit für den Abruf der historischen Daten des Kontos
//+------------------------------------------------------------------+

Anstatt TimeCurrent() als Endzeit einzugeben, werden wir nun das Makro END_TIME eingeben.

Implementierung der Aktualisierung der Collection der Auftragsliste:

//+------------------------------------------------------------------+
//| Aktualisierung der Auftragsliste                                 |
//+------------------------------------------------------------------+
void CHistoryCollection::Refresh(void)
  {
#ifdef __MQL4__
   int total=::OrdersHistoryTotal(),i=m_index_order;
   for(; i<total; i++)
     {
      if(!::OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)) continue;
      ENUM_ORDER_TYPE order_type=(ENUM_ORDER_TYPE)::OrderType();
      //--- Geschlossenen Positionen und Salden-/Korrekturbuchungen
      if(order_type<ORDER_TYPE_BUY_LIMIT || order_type>ORDER_TYPE_SELL_STOP)
        {
         CHistoryOrder *order=new CHistoryOrder(::OrderTicket());
         if(order==NULL) continue;
         m_list_all_orders.InsertSort(order);
        }
      else
        {
         //--- Entfernte Pending-Order
         CHistoryPending *order=new CHistoryPending(::OrderTicket());
         if(order==NULL) continue;
         m_list_all_orders.InsertSort(order);
        }
     }
//---
   int delta_order=i-m_index_order;
   this.m_index_order=i;
   this.m_delta_order=delta_order;
   this.m_is_trade_event=(this.m_delta_order!=0 ? true : false);
//--- __MQL5__
#else 
   if(!::HistorySelect(0,END_TIME)) return;
//--- Aufträge
   int total_orders=::HistoryOrdersTotal(),i=m_index_order;
   for(; i<total_orders; i++)
     {
      ulong order_ticket=::HistoryOrderGetTicket(i);
      if(order_ticket==0) continue;
      ENUM_ORDER_TYPE type=(ENUM_ORDER_TYPE)::HistoryOrderGetInteger(order_ticket,ORDER_TYPE);
      if(type==ORDER_TYPE_BUY || type==ORDER_TYPE_SELL)
        {
         CHistoryOrder *order=new CHistoryOrder(order_ticket);
         if(order==NULL) continue;
         m_list_all_orders.InsertSort(order);
        }
      else
        {
         CHistoryPending *order=new CHistoryPending(order_ticket);
         if(order==NULL) continue;
         m_list_all_orders.InsertSort(order);
        }
     }
//--- Sichern des Index des zuletzt ergänzten Auftrags und der Änderung im Vergleich zur vorherigen Prüfung
   int delta_order=i-this.m_index_order;
   this.m_index_order=i;
   this.m_delta_order=delta_order;
   
//--- Deals
   int total_deals=::HistoryDealsTotal(),j=m_index_deal;
   for(; j<total_deals; j++)
     {
      ulong deal_ticket=::HistoryDealGetTicket(j);
      if(deal_ticket==0) continue;
      CHistoryDeal *deal=new CHistoryDeal(deal_ticket);
      if(deal==NULL) continue;
      m_list_all_orders.InsertSort(deal);
     }
//--- Sichern des Index des zuletzt ergänzten Deals und der Änderung im Vergleich zur vorherigen Prüfung
   int delta_deal=j-this.m_index_deal;
   this.m_index_deal=j;
   this.m_delta_deal=delta_deal;
//--- Setzen des Flags für neue Ereignisse in der Historie
   this.m_is_trade_event=(this.m_delta_order+this.m_delta_deal);
#endif 
  }
//+------------------------------------------------------------------+

Überprüfen wir die Zugehörigkeit zu MQL4 oder MQL5. Lassen Sie uns den Code am Beispiel von MQL5 analysieren, da er etwas komplizierter ist.

Zuerst fordern wir die vollständige Kontohistorie an. Wenn dies nicht möglich ist, verlassen wir das Programm bis zum nächsten Tick. Nach dem erfolgreichen Abruf der Historie werden zwei Listen erstellt — Liste der Aufträge und die der Deals.

Bewegen wir uns sich zunächst durch die Liste aller Aufträge in einer Schleife. Der Anfangsindex, dort, wo die Schleife beginnt, ist das Endresultat der vorherigen Schleifenoperation (beim ersten Start = 0). Dies ermöglicht es uns, nur durch neue Aufträge zu navigieren, die seit der letzten Prüfung in der Historie erschienen sind, anstatt ressourcenintensiv die Schleife immer wieder über die gesamte Historie zu abzuarbeiten.

Als Nächstes erhalten wir die Tickets der Aufträge und deren Typen. Erstellen wir jetzt ein neues Objekt entsprechend dem Ergebnis der Ordertypprüfung (entweder eine historische Marktorder oder eine gelöschte Pending-Order) und platzieren es sofort in der Collection in sortierter Form (wir haben bereits für die Sortierung die Schlusszeit festgelegt).

Speichern wir jetzt nach dem Ende der Schleife den neuen Index der Order, so dass eine neue Schleife ab da beginnt. Die Differenz zwischen den Operationsergebnissen der vorherigen und der aktuellen Schleife ist eine Anzahl von neu hinzugekommenen Aufträgen.
Die Schleife für die Arbeit mit Deals ist die gleiche, außer dass es keine Notwendigkeit gibt, Deals nach Typen zu unterteilen. Stattdessen können wir ein Deal-Objekt sofort zur Collection hinzufügen.

Die Schleife im MQL4-Code ist fast identisch, außer dass die Schleife über die gesamt möglichen Historie läuft, die für das Konto verfügbar ist. Der Umfang der Historie wird von einem Nutzer auf der Registerkarte Historie des Terminals festgelegt, d.h. es liegt in der Verantwortung des Benutzers, sicherzustellen, dass die gesamte Historie verfügbar ist, wenn das Programm sie benötigt. Eine weitere Möglichkeit ist die Verwendung von WinAPI, um die gesamte Historie zu erhalten, die über den Umfang der Artikel hinausgeht.

Nach dem Ende der Schleife wird die Anzahl der neuen Aufträge und Deals überprüft. Wenn die Zahl größer als Null ist, wird das Flag der aufgetretenen Handelsereignisse gesetzt.

Wir haben das Erheben der Daten in der Klasse der historischen Collection implementiert, ähnlich wie im Test-EA im ersten Teil, mit dem Unterschied, dass im aktuellen Fall, verschiedene Objekte der historischen Aufträge erstellt werden, getrennt durch ihren Status. Um zu überprüfen, wie alles funktioniert, müssen wir die erstellte Collection der historischen Aufträge von außen beziehen (von dem Programm, das diese Bibliothek verwenden soll; in unserem Fall ist dies ein Test-EA).

Ergänzen wir dafür die Methode GetList() ohne Parameter 'public' Teil der Klasse CHistoryCollection (im nächsten Artikel werde ich Methoden zum Abrufen der Liste mit Parametern hinzufügen):
//+------------------------------------------------------------------+
//| Collection historischer Aufträge und Deals                       |
//+------------------------------------------------------------------+
class CHistoryCollection
  {
private:
   CArrayObj         m_list_all_orders;      // Liste aller historischen Aufträge und Deals
   bool              m_is_trade_event;       // Flag des Handelsereignisses
   int               m_index_order;          // Index des letzten zur Collection hinzugefügten Auftrags aus der Liste der Terminalhistorie (MQL4, MQL5)
   int               m_index_deal;           // Index des letzten zur Collection hinzugefügten Deals aus der Liste der Terminalhistorie (MQL5)
   int               m_delta_order;          // Differenz der Auftragsanzahl im Vergleich zur vorherigen Prüfung
   int               m_delta_deal;           // Differenz der Anzahl der Deals im Vergleich zur vorherigen Prüfung
public:
   //--- Rückgabe der ganzen Collection 'wie besehen'
   CArrayObj*        GetList(void)           { return &m_list_all_orders;  }
//--- Konstructor
                     CHistoryCollection();
   //--- Aktualisieren der Liste der Aufträge, Eintragen der neuen Daten und setzten des Handelsereignisses
   void              Refresh(void);
  };
//+------------------------------------------------------------------+

Wie aus dem Code ersichtlich ist, wird der Zeiger auf die Liste (nicht das Objekt selbst) zurückgegeben. Dies ist ausreichend, um die Liste in den Programmen zu verwenden. Für eine schnelle und einfache Nutzung der Bibliothek reicht dies jedoch nicht aus. Im nächsten Artikel über die Bibliothek werde ich einen einfachen Zugriff auf die benötigten Daten implementieren. In den kommenden Artikeln werde ich den Zugriff noch weiter vereinfachen, indem ich spezielle Funktionen für die Arbeit mit der Bibliothek in benutzerdefinierten Programmen erstelle.

Mal sehen, wie die Liste befüllt wird. Dazu erstellen wir einen kleinen EA. Wir erzeugen im Ordner TestDoEasy (den wir bereits im ersten Teil erstellt haben) den Unterordner Part02. Er enthält die Datei des zweiten Test-EAs mit dem Namen TestDoEasyPart02 und verbindet die erstellte Collection mit ihr:

//+------------------------------------------------------------------+
//|                                             TestDoEasyPart02.mq5 |
//|                        Copyright 2018, MetaQuotes Software Corp. |
//|                             https://mql5.com/en/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2018, MetaQuotes Software Corp."
#property link      "https://mql5.com/en/users/artmedia70"
#property version   "1.00"
//--- includes
#include <DoEasy\Collections\HistoryCollection.mqh>
//+------------------------------------------------------------------+
//| Initialisierungsfunktion des Experten                            |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
   
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Deinitialisierungsfunktion des Experten                          |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
   
  }
//+------------------------------------------------------------------+
//| Experten Funktion OnTick                                         |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
   
  }
//+------------------------------------------------------------------+

Da die Liste nun die Objekte verschiedener Typen speichert, die von einem einzigen übergeordneten COrder geerbt wurden, implementieren wir die Anzeige der Beschreibungen der ausgewählten Auftragsobjekte im Journal. Dazu erstellen wir die Enumeration mit Auswahl der angezeigten Auftragsarten in den Eingaben, sowie ein Collection-Objekt zum Lesen der Kontodaten:

//+------------------------------------------------------------------+
//|                                             TestDoEasyPart02.mq5 |
//|                        Copyright 2018, MetaQuotes Software Corp. |
//|                             https://mql5.com/en/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2018, MetaQuotes Software Corp."
#property link      "https://mql5.com/en/users/artmedia70"
#property version   "1.00"
//--- includes
#include <DoEasy\Collections\HistoryCollection.mqh>
//--- Enumerationen
enum ENUM_TYPE_ORDERS
  {
   TYPE_ORDER_MARKET,   // Marktorder
   TYPE_ORDER_PENDING,  // Pending-Order
   TYPE_ORDER_DEAL      // Deals
  };
//--- Eingabeparameter
input ENUM_TYPE_ORDERS  InpOrderType   =  TYPE_ORDER_DEAL;  // Anzeige des Typs:
//--- Globale Variablen
CHistoryCollection history;
//+------------------------------------------------------------------+
//| Initialisierungsfunktion des Experten                            |
//+------------------------------------------------------------------+

Wie im vorherigen Test-EA aus dem ersten Teil der Bibliotheksbeschreibung, wird in OnInit() die Kontenhistorie gelesen und Informationen über die Aufträge an das Journal in einer Schleife angezeigt:

//+------------------------------------------------------------------+
//| Initialisierungsfunktion des Experten                            |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- Aktualisieren der Historie
   history.Refresh();
//--- Abrufen des Pointers auf die ganze Collection
   CArrayObj* list=history.GetList();
   if(list==NULL)
     {
      Print("Could not get collection list");
      return INIT_FAILED;
     }
   int total=list.Total();
   for(int i=0;i<total;i++)
     {
      //--- Abrufen des Auftrags aus der Liste
      COrder* order=list.At(i);
      if(order==NULL) continue;
      //--- Falls es ein Deal ist
      if(order.Status()==ORDER_STATUS_DEAL && InpOrderType==TYPE_ORDER_DEAL)
         order.Print();
      //--- Falls es eine historische Marktorder ist
      if(order.Status()==ORDER_STATUS_HISTORY_ORDER && InpOrderType==TYPE_ORDER_MARKET)
         order.Print();
      //--- Falles es eine entfernte Pending-Order ist
      if(order.Status()==ORDER_STATUS_HISTORY_PENDING && InpOrderType==TYPE_ORDER_PENDING)
         order.Print();
     }
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+

Erstellen wir hier einen Zeiger auf die Collection und empfangen sie von CHistoryCollection mit der dort erstellten Methode GetList().
Als Nächstes holen wir in einer Schleife das Objekt order aus der Liste, überprüfen dessen Status und die Berechtigung in den EA-Einstellungen, die Daten im Journal anzuzeigen.
Je nach Ergebnis werden die Daten im Journal angezeigt oder nicht.
Obwohl wir das Basisobjekt COrder aus der Liste erhalten, werden im Journal nur die Daten angezeigt, die den Nachkommen des Basisorders gehören — Market Orders, Pending-Order und Deals mit neu definierten virtuellen Methoden, die das Flag zurückgeben, das angibt, dass die Order nur ihre eigenen Eigenschaften unterstützt.

Kompilieren und starten wir den EA. Das Journal zeigt Daten zu ausgewählten Order- und Dealarten an:


Wenn wir uns die Arten der angezeigten Eigenschaften genauer ansehen, werden wir die Eigenschaften sehen, die für MQL5-Aufträge nicht typisch sind: Gewinn, Swap, Kommission und Gewinn in Punkten.

Machen wir noch einige Verbesserungen und Ergänzungen in den bereits erstellten Objekten.

Fügen wir die nicht unterstützte Eigenschaft MQL5 Gewinn in Punkten zur Methode SupportProperty(ENUM_ORDER_PROP_INTEGER property) der Klasse CHistoryOrder hinzu:

//+------------------------------------------------------------------+
//| Rückgabe von 'true' falls ein Auftrag die übergebenen            |
//| Eigenschaft unterstützt, sonst 'false'                           |
//+------------------------------------------------------------------+
bool CHistoryOrder::SupportProperty(ENUM_ORDER_PROP_INTEGER property)
  {
   if(property==ORDER_PROP_TIME_EXP       || 
      property==ORDER_PROP_DEAL_ENTRY     || 
      property==ORDER_PROP_TIME_UPDATE    || 
      property==ORDER_PROP_TIME_UPDATE_MSC
      #ifdef __MQL5__                     ||
      property==ORDER_PROP_PROFIT_PT
      #endif                        
     ) return false;
   return true;
  }
//+------------------------------------------------------------------+

und auch noch eine weitere virtuelle Methode, die die von den Aufträgen unterstützten Real-Eigenschaften zurückgibt:

//+------------------------------------------------------------------+
//| Historische Marktorder                                           |
//+------------------------------------------------------------------+
class CHistoryOrder : public COrder
  {
public:
   //--- Konstructor
                     CHistoryOrder(const ulong ticket) : COrder(ORDER_STATUS_HISTORY_ORDER,ticket) {}
   //--- Unterstützte Integer-Eigenschaften eines Auftrags
   virtual bool      SupportProperty(ENUM_ORDER_PROP_INTEGER property);
   //--- Unterstützte Real-Eigenschaften eines Auftrags
   virtual bool      SupportProperty(ENUM_ORDER_PROP_DOUBLE property);
  };
//+------------------------------------------------------------------+

sowie deren Umsetzung:

//+------------------------------------------------------------------+
//| Rückgabe von 'true' falls ein Auftrag die übergebenen            |
//| Eigenschaft unterstützt, sonst 'false'                           |
//+------------------------------------------------------------------+
bool CHistoryOrder::SupportProperty(ENUM_ORDER_PROP_DOUBLE property)
  {
#ifdef __MQL5__
   if(property==ORDER_PROP_PROFIT      || 
      property==ORDER_PROP_PROFIT_FULL || 
      property==ORDER_PROP_SWAP        || 
      property==ORDER_PROP_COMMISSION  ||
      property==ORDER_PROP_PRICE_STOP_LIMIT
     ) return false;
#endif 
   return true;
  }
//+------------------------------------------------------------------+

Wenn dies MQL5 ist, werden Gewinn, Swap, Provision, Gesamtgewinn und der Preis einer StopLimit-Order nicht unterstützt. Für MQL4 und andere Real-Eigenschaften in MQL5, wird das Flag der Unterstützung der Order für die Real-Eigenschaften zurück gegeben.

MQL5-Aufträge haben auch die Eigenschaft ORDER_STATE. Dies ist ein Auftragsstatus, der in der Enumeration ENUM_ORDER_STATE gesetzt wird.
Wir fügen das zur Liste der Integer-Eigenschaften der Aufträge (die Enumeration ENUM_ORDER_PROP_INTEGER in den Dateien Defines.mqh):

//+------------------------------------------------------------------+
//| Order, Deal, Position, Integer-Eigenschaften                     |
//+------------------------------------------------------------------+
enum ENUM_ORDER_PROP_INTEGER
  {
   ORDER_PROP_TICKET = 0,                                   // Order-Ticket
   ORDER_PROP_MAGIC,                                        // Magicnummer des Auftrags
   ORDER_PROP_TIME_OPEN,                                    // Eröffnungszeit (MQL5 Deal-Zeit)
   ORDER_PROP_TIME_CLOSE,                                   // Schlusszeit (MQL5 Zeit der Ausführung oder Entfernung - ORDER_TIME_DONE)
   ORDER_PROP_TIME_OPEN_MSC,                                // Eröffnungszeit in Millisekunden (MQL5 Deal-Zeit in msc)
   ORDER_PROP_TIME_CLOSE_MSC,                               // Schlusszeit in Millisekunden  (MQL5 Zeit der Ausführung oder Entfernung - ORDER_TIME_DONE_MSC)
   ORDER_PROP_TIME_EXP,                                     // Verfallszeit der Order (für Pending-Orders)
   ORDER_PROP_STATUS,                                       // Order-Status (aus der Enumeration ENUM_ORDER_STATUS)
   ORDER_PROP_TYPE,                                         // Auftragstyp (MQL5 Deal-Typ)
   ORDER_PROP_DIRECTION,                                    // Richtung (Buy, Sell)
   ORDER_PROP_REASON,                                       // Deal/Order/Position Grund oder Quelle
   ORDER_PROP_STATE,                                        // Auftragsstatus (aus der Enumeration ENUM_ORDER_STATE)
   ORDER_PROP_POSITION_ID,                                  // Positions-ID
   ORDER_PROP_POSITION_BY_ID,                               // Entgegengesetzte Positions-ID
   ORDER_PROP_DEAL_ORDER,                                   // Basis des Auftrags oder Deals
   ORDER_PROP_DEAL_ENTRY,                                   // Deal-Richtung – IN, OUT oder IN/OUT
   ORDER_PROP_TIME_UPDATE,                                  // Zeit der Positionsänderung in Sekunden
   ORDER_PROP_TIME_UPDATE_MSC,                              // Zeit der Positionsänderung in Millisekunden
   ORDER_PROP_TICKET_FROM,                                  // Ticket der Ober-Order
   ORDER_PROP_TICKET_TO,                                    // Ticket der abgeleiteten Order
   ORDER_PROP_PROFIT_PT,                                    // Gewinn in Points
   ORDER_PROP_CLOSE_BY_SL,                                  // Flag für das Schließen durch StopLoss
   ORDER_PROP_CLOSE_BY_TP,                                  // Flag für das Schließen mit TakeProfit
  }; 
#define ORDER_PROP_INTEGER_TOTAL    (23)                    // Gesamtzahl der Integer-Eigenschaften
//+------------------------------------------------------------------+

und wir stellen sicher, dass die Anzahl der Integer-Eigenschaften der Aufträge von 22 auf 23 in der Makro-Substitution ORDER_PROP_INTEGER_TOTAL ändern, die die Anzahl der Integer-Eigenschaften der Aufträge angibt und zur Berechnung einer genauen "Adresse" der notwendigen Order-Eigenschaft verwendet wird.
In der gleichen Datei fügen wir die neue Eigenschaft den möglichen Order-Kriterien hinzu, so dass wir in der Lage sind, Aufträge nach dieser neuen Eigenschaft zu sortieren und bequemere Berechnung von Indizes im Falle einer späteren Änderung der Enumerationen zu implementieren:

//+------------------------------------------------------------------+
//| Mögliche Sortierkriterien von Aufträgen und Deals                |
//+------------------------------------------------------------------+
#define FIRST_DBL_PROP              (ORDER_PROP_INTEGER_TOTAL)
#define FIRST_STR_PROP              (ORDER_PROP_INTEGER_TOTAL+ORDER_PROP_DOUBLE_TOTAL)
enum ENUM_SORT_ORDERS_MODE
  {
   //--- Sortieren nach den Integer-Eigenschaften
   SORT_BY_ORDER_TICKET          =  0,                      // Sortieren nach Auftrags-Ticket
   SORT_BY_ORDER_MAGIC           =  1,                      // Sortieren nach der Magicnummer
   SORT_BY_ORDER_TIME_OPEN       =  2,                      // Sortieren nach Eröffnungszeit
   SORT_BY_ORDER_TIME_CLOSE      =  3,                      // Sortieren nach Schlusszeit
   SORT_BY_ORDER_TIME_OPEN_MSC   =  4,                      // Sortieren nach Eröffnungszeit des Auftrags in Millisekunden
   SORT_BY_ORDER_TIME_CLOSE_MSC  =  5,                      // Sortieren nach der Schlusszeit des Auftrags in Millisekunden
   SORT_BY_ORDER_TIME_EXP        =  6,                      // Sortieren nach der Verfallszeit
   SORT_BY_ORDER_STATUS          =  7,                      // Sortieren nach dem Auftragsstatus (Marktorder/Pending-Order/Deal)
   SORT_BY_ORDER_TYPE            =  8,                      // Sortieren nach dem Auftragstyp
   SORT_BY_ORDER_REASON          =  10,                     // Sortieren nach Grund/Quelle von Auftrag/Deal/Position
   SORT_BY_ORDER_STATE           =  11,                     // Sortieren nach dem Auftragsstatus
   SORT_BY_ORDER_POSITION_ID     =  12,                     // Sortieren nach der Positions-ID
   SORT_BY_ORDER_POSITION_BY_ID  =  13,                     // Sortieren nach der ID der entgegengesetzten Position
   SORT_BY_ORDER_DEAL_ORDER      =  14,                     // Sortieren nach dem Auftrag als Basis des Deals
   SORT_BY_ORDER_DEAL_ENTRY      =  15,                     // Sortieren nach der Richtung der Deals – IN, OUT or IN/OUT
   SORT_BY_ORDER_TIME_UPDATE     =  16,                     // Sortieren nach der Änderungszeit der Position in Sekunden
   SORT_BY_ORDER_TIME_UPDATE_MSC =  17,                     // Sortieren nach der Änderungszeit der Position in Millisekunden
   SORT_BY_ORDER_TICKET_FROM     =  18,                     // Sortieren nach dem Tickets der Ober-Order
   SORT_BY_ORDER_TICKET_TO       =  19,                     // Sortieren nach der Ticket der abgeleiteten Order
   SORT_BY_ORDER_PROFIT_PT       =  20,                     // Sortieren nach dem Auftragsgewinn in Points
   SORT_BY_ORDER_CLOSE_BY_SL     =  21,                     // Sortieren nach dem Flag für das Schließen durch StopLoss
   SORT_BY_ORDER_CLOSE_BY_TP     =  22,                     // Sortieren nach dem Flag für das Schließen durch TakeProfit
   //--- Sortieren nach den Real-Eigenschaften
   SORT_BY_ORDER_PRICE_OPEN      =  FIRST_DBL_PROP,         // Sortieren nach dem Eröffnungspreis by open price
   SORT_BY_ORDER_PRICE_CLOSE     =  FIRST_DBL_PROP+1,       // Sortieren nach dem Schlusskurs
   SORT_BY_ORDER_SL              =  FIRST_DBL_PROP+2,       // Sortieren nach StopLoss
   SORT_BY_ORDER_TP              =  FIRST_DBL_PROP+3,       // Sortieren nach TakeProfit
   SORT_BY_ORDER_PROFIT          =  FIRST_DBL_PROP+4,       // Sortieren nach dem Gewinn
   SORT_BY_ORDER_COMMISSION      =  FIRST_DBL_PROP+5,       // Sortieren nach der Kommission
   SORT_BY_ORDER_SWAP            =  FIRST_DBL_PROP+6,       // Sortieren nach dem Swap
   SORT_BY_ORDER_VOLUME          =  FIRST_DBL_PROP+7,       // Sortieren nach dem Volumen
   SORT_BY_ORDER_VOLUME_CURRENT  =  FIRST_DBL_PROP+8,       // Sortieren nach dem nicht ausgeführten Volumen
   SORT_BY_ORDER_PROFIT_FULL     =  FIRST_DBL_PROP+9,       // Sortieren nach dem Kriterium Gewinn+Kommission+Swap
   SORT_BY_ORDER_PRICE_STOP_LIMIT=  FIRST_DBL_PROP+10,      // Sortieren nach der Limit-Order nach dem die StopLimit-Order aktiviert worden war
   //--- Sortieren nach den String-Eigenschaften
   SORT_BY_ORDER_SYMBOL          =  FIRST_STR_PROP,         // Sortieren nach dem Symbol
   SORT_BY_ORDER_COMMENT         =  FIRST_STR_PROP+1,       // Sortieren nach dem Kommentar
   SORT_BY_ORDER_EXT_ID          =  FIRST_STR_PROP+2        // Sortieren nach der ID des externen Handelssystems
  };
//+------------------------------------------------------------------+

Wir deklarieren im 'protected' Teile der abstrakten Auftragsklasse COrder der Datei Order.mqh die Methode OrderState(), die ihren Status aus der Enumeration ENUM_ORDER_STATE zu den Auftragseigenschaften schreibt:

protected:
   //--- 'Protected' Konstruktor
                     COrder(ENUM_ORDER_STATUS order_status,const ulong ticket);

   //--- Die Integer-Eigenschaften der ausgewählten Order aus den Parametern abrufen und zurückgeben
   long              OrderMagicNumber(void)        const;
   long              OrderTicket(void)             const;
   long              OrderTicketFrom(void)         const;
   long              OrderTicketTo(void)           const;
   long              OrderPositionID(void)         const;
   long              OrderPositionByID(void)       const;
   long              OrderOpenTimeMSC(void)        const;
   long              OrderCloseTimeMSC(void)       const;
   long              OrderType(void)               const;
   long              OrderState(void)              const;
   long              OrderTypeByDirection(void)    const;
   long              OrderTypeFilling(void)        const;
   long              OrderTypeTime(void)           const;
   long              OrderReason(void)             const;
   long              DealOrder(void)               const;
   long              DealEntry(void)               const;
   bool              OrderCloseByStopLoss(void)    const;
   bool              OrderCloseByTakeProfit(void)  const;
   datetime          OrderOpenTime(void)           const;
   datetime          OrderCloseTime(void)          const;
   datetime          OrderExpiration(void)         const;
   datetime          PositionTimeUpdate(void)      const;
   datetime          PositionTimeUpdateMSC(void)   const;

und fügen das zur Implementation hinzu:

//+------------------------------------------------------------------+
//| Rückgabe des des Auftragsstatus                                  |
//+------------------------------------------------------------------+
long COrder::OrderState(void) const
  {
#ifdef __MQL4__              
   return ORDER_STATE_FILLED;
#else
   long res=0;
   switch((ENUM_ORDER_STATUS)this.GetProperty(ORDER_PROP_STATUS))
     {
      case ORDER_STATUS_HISTORY_PENDING   :
      case ORDER_STATUS_HISTORY_ORDER     : res=::HistoryOrderGetInteger(m_ticket,ORDER_STATE); break;
      case ORDER_STATUS_MARKET_PENDING    : res=::OrderGetInteger(ORDER_STATE);                 break;
      case ORDER_STATUS_MARKET_ACTIVE     : 
      case ORDER_STATUS_DEAL              : 
      default                             : res=0;                                              break;
     }
   return res;
#endif
  }
//+------------------------------------------------------------------+

Im Falle von MQL4, geben wir vorerst die vollständige Ausführung des Auftrags zurück, im Falle von MQL5, entweder 0 (wenn dies ein Deal oder eine Position ist), oder den Orderstatus (wenn dies ein Markt- oder eine Pending-Order ist) abhängig vom Orderstatus.

Wir deklarieren im 'public' Teil der Klasse COrder die Methode, die die Beschreibung des Auftragsstatus zurückgibt:

//+------------------------------------------------------------------+
//| Beschreibung der Objekteigenschaften des Auftrags                |
//+------------------------------------------------------------------+
   //--- Abrufen der Beschreibung der Order (1) Integer-, (2) Double- und (3) String-Eigenschaft
   string            GetPropertyDescription(ENUM_ORDER_PROP_INTEGER property);
   string            GetPropertyDescription(ENUM_ORDER_PROP_DOUBLE property);
   string            GetPropertyDescription(ENUM_ORDER_PROP_STRING property);
   //--- Rückgabe des Namens des Order-Status
   string            StatusDescription(void)    const;
   //---  Rückgabe des namens des Auftrags oder Position
   string            TypeDescription(void)      const;
   //--- Rückgabe der Beschreibung des Auftragsstatus'
   string            StateDescription(void)     const;
   //--- Richtung des Namens des Deals
   string            DealEntryDescription(void) const;
   //--- Rückgabe des Richtungstyps des Auftrags/Position
   string            DirectionDescription(void) const;
   //--- Senden der Beschreibung der Auftragsbeschreibung an das Journal (full_prop=true - alle Eigenschaften, false - nur die unterstützten)
   void              Print(const bool full_prop=false);

sowie deren Umsetzung:

//+------------------------------------------------------------------+
//| Rückgabe der Statusbeschreibung                                  |
//+------------------------------------------------------------------+
string COrder::StateDescription(void) const
  {
   if(this.Status()==ORDER_STATUS_DEAL || this.Status()==ORDER_STATUS_MARKET_ACTIVE)
      return "";                       
   else switch(this.StateOrder())
     {
      case ORDER_STATE_STARTED         :  return TextByLanguage("Ордер проверен на корректность, но еще не принят брокером","Order checked for correctness, but not yet accepted by broker");
      case ORDER_STATE_PLACED          :  return TextByLanguage("Ордер принят","Order accepted");
      case ORDER_STATE_CANCELED        :  return TextByLanguage("Ордер снят клиентом","Order withdrawn by client");
      case ORDER_STATE_PARTIAL         :  return TextByLanguage("Ордер выполнен частично","Order filled partially");
      case ORDER_STATE_FILLED          :  return TextByLanguage("Ордер выполнен полностью","Order filled");
      case ORDER_STATE_REJECTED        :  return TextByLanguage("Ордер отклонен","Order rejected");
      case ORDER_STATE_EXPIRED         :  return TextByLanguage("Ордер снят по истечении срока его действия","Order withdrawn upon expiration");
      case ORDER_STATE_REQUEST_ADD     :  return TextByLanguage("Ордер в состоянии регистрации (выставление в торговую систему)","Order in state of registration (placing in trading system)");
      case ORDER_STATE_REQUEST_MODIFY  :  return TextByLanguage("Ордер в состоянии модификации","Order in state of modification.");
      case ORDER_STATE_REQUEST_CANCEL  :  return TextByLanguage("Ордер в состоянии удаления","Order in deletion state");
      default                          :  return TextByLanguage("Неизвестное состояние","Unknown state");
     }
  }
//+------------------------------------------------------------------+

Wenn dies ein Deal oder eine Position ist, geben wir eine leere Zeichenkette zurück, andernfalls überprüfen wir den Auftragsstatus und geben die Beschreibung zurück.

Fügen wir die Rückgabe der Auftragsstatusbeschreibung in die Methodenimplementierung GetPropertyDescription(ENUM_ORDER_PROP_INTEGER property) ein:

//+------------------------------------------------------------------+
//| Rückgabe der Beschreibung der Integer-Eigenschaft des Auftrags   |
//+------------------------------------------------------------------+
string COrder::GetPropertyDescription(ENUM_ORDER_PROP_INTEGER property)
  {
   return
     (
   //--- Allgemeine Eigenschaften
      property==ORDER_PROP_MAGIC             ?  TextByLanguage("Магик","Magic number")+
         (!this.SupportProperty(property)    ?  TextByLanguage(": Свойство не поддерживается",": Property not supported") :
          ": "+(string)this.GetProperty(property)
         )  :
      property==ORDER_PROP_TICKET            ?  TextByLanguage("Тикет","Ticket")+
         (!this.SupportProperty(property)    ?  TextByLanguage(": Свойство не поддерживается",": Property not supported") :
          " #"+(string)this.GetProperty(property)
         )  :
      property==ORDER_PROP_TICKET_FROM       ?  TextByLanguage("Тикет родительского ордера","Ticket of parent order")+
         (!this.SupportProperty(property)    ?  TextByLanguage(": Свойство не поддерживается",": Property not supported") :
          " #"+(string)this.GetProperty(property)
         )  :
      property==ORDER_PROP_TICKET_TO         ?  TextByLanguage("Тикет наследуемого ордера","Inherited order ticket")+
         (!this.SupportProperty(property)    ?  TextByLanguage(": Свойство не поддерживается",": Property not supported") :
          " #"+(string)this.GetProperty(property)
         )  :
      property==ORDER_PROP_TIME_OPEN         ?  TextByLanguage("Время открытия","Open time")+
         (!this.SupportProperty(property)    ?  TextByLanguage(": Свойство не поддерживается",": Property not supported") :
          ": "+::TimeToString(this.GetProperty(property),TIME_DATE|TIME_MINUTES|TIME_SECONDS)
         )  :
      property==ORDER_PROP_TIME_CLOSE        ?  TextByLanguage("Время закрытия","Close time")+
         (!this.SupportProperty(property)    ?  TextByLanguage(": Свойство не поддерживается",": Property not supported") :
          ": "+::TimeToString(this.GetProperty(property),TIME_DATE|TIME_MINUTES|TIME_SECONDS)
         )  :
      property==ORDER_PROP_TIME_EXP          ?  TextByLanguage("Дата экспирации","Expiration date")+
         (!this.SupportProperty(property)    ?  TextByLanguage(": Свойство не поддерживается",": Property not supported") :
          (this.GetProperty(property)==0     ?  TextByLanguage(": Не задана",": Not set") :
          ": "+::TimeToString(this.GetProperty(property),TIME_DATE|TIME_MINUTES|TIME_SECONDS))
         )  :
      property==ORDER_PROP_TYPE              ?  TextByLanguage("Тип","Type")+": "+this.TypeDescription()                   :
      property==ORDER_PROP_DIRECTION         ?  TextByLanguage("Тип по направлению","Type by direction")+": "+this.DirectionDescription() :
      
      property==ORDER_PROP_REASON            ?  TextByLanguage("Причина","Reason")+
         (!this.SupportProperty(property)    ?  TextByLanguage(": Свойство не поддерживается",": Property not supported") :
          ": "+this.GetReasonDescription(this.GetProperty(property))
         )  :
      property==ORDER_PROP_POSITION_ID       ?  TextByLanguage("Идентификатор позиции","Position ID")+
         (!this.SupportProperty(property)    ?  TextByLanguage(": Свойство не поддерживается",": Property not supported") :
          ": #"+(string)this.GetProperty(property)
         )  :
      property==ORDER_PROP_DEAL_ORDER        ?  TextByLanguage("Сделка на основании ордера","Deal by order")+
         (!this.SupportProperty(property)    ?  TextByLanguage(": Свойство не поддерживается",": Property not supported") :
          ": #"+(string)this.GetProperty(property)
         )  :
      property==ORDER_PROP_DEAL_ENTRY        ?  TextByLanguage("Направление сделки","Deal direction")+
         (!this.SupportProperty(property)    ?  TextByLanguage(": Свойство не поддерживается",": Property not supported") :
          ": "+this.GetEntryDescription(this.GetProperty(property))
         )  :
      property==ORDER_PROP_POSITION_BY_ID    ?  TextByLanguage("Идентификатор встречной позиции","Opposite position ID")+
         (!this.SupportProperty(property)    ?  TextByLanguage(": Свойство не поддерживается",": Property not supported") :
          ": "+(string)this.GetProperty(property)
         )  :
      property==ORDER_PROP_TIME_OPEN_MSC     ?  TextByLanguage("Время открытия в милисекундах","Open time in milliseconds")+
         (!this.SupportProperty(property)    ?  TextByLanguage(": Свойство не поддерживается",": Property not supported") :
          ": "+(string)this.GetProperty(property)+" > "+TimeMSCtoString(this.GetProperty(property))
         )  :
      property==ORDER_PROP_TIME_CLOSE_MSC    ?  TextByLanguage("Время закрытия в милисекундах","Close time in milliseconds")+
         (!this.SupportProperty(property)    ?  TextByLanguage(": Свойство не поддерживается",": Property not supported") :
          ": "+(string)this.GetProperty(property)+" > "+TimeMSCtoString(this.GetProperty(property))
         )  :
      property==ORDER_PROP_TIME_UPDATE       ?  TextByLanguage("Время изменения позиции","Position change time")+
         (!this.SupportProperty(property)    ?  TextByLanguage(": Свойство не поддерживается",": Property not supported") :
          ": "+(this.GetProperty(property)!=0 ? ::TimeToString(this.GetProperty(property),TIME_DATE|TIME_MINUTES|TIME_SECONDS) : "0")
         )  :
      property==ORDER_PROP_TIME_UPDATE_MSC   ?  TextByLanguage("Время изменения позиции в милисекундах","Position change time in milliseconds")+
         (!this.SupportProperty(property)    ?  TextByLanguage(": Свойство не поддерживается",": Property not supported") :
          ": "+(this.GetProperty(property)!=0 ? (string)this.GetProperty(property)+" > "+TimeMSCtoString(this.GetProperty(property)) : "0")
         )  :
      property==ORDER_PROP_STATE             ?  TextByLanguage("Состояние","Statе")+
         (!this.SupportProperty(property)    ?  TextByLanguage(": Свойство не поддерживается",": Property not supported") :
          ": \""+this.StateDescription()+"\""
         )  :
   //--- Zusätzliche Eigenschaften
      property==ORDER_PROP_STATUS            ?  TextByLanguage("Статус","Status")+
         (!this.SupportProperty(property)    ?  TextByLanguage(": Свойство не поддерживается",": Property not supported") :
          ": \""+this.StatusDescription()+"\""
         )  :
      property==ORDER_PROP_PROFIT_PT         ?  TextByLanguage("Прибыль в пунктах","Profit in points")+
         (!this.SupportProperty(property)    ?  TextByLanguage(": Свойство не поддерживается",": Property not supported") :
          ": "+(string)this.GetProperty(property)
         )  :
      property==ORDER_PROP_CLOSE_BY_SL       ?  TextByLanguage("Закрытие по StopLoss","Close by StopLoss")+
         (!this.SupportProperty(property)    ?  TextByLanguage(": Свойство не поддерживается",": Property not supported") :
          ": "+(this.GetProperty(property) ? TextByLanguage("Да","Yes") : TextByLanguage("Нет","No"))
         )  :
      property==ORDER_PROP_CLOSE_BY_TP       ?  TextByLanguage("Закрытие по TakeProfit","Close by TakeProfit")+
         (!this.SupportProperty(property)    ?  TextByLanguage(": Свойство не поддерживается",": Property not supported") :
          ": "+(this.GetProperty(property) ? TextByLanguage("Да","Yes") : TextByLanguage("Нет","No"))
         )  :
      ""
     );
  }
//+------------------------------------------------------------------+

Wir haben alle Verbesserungen fertiggestellt.

Es ist zu beachten, dass die Bibliothek "live" entwickelt wird und eine Beta-Version ist, so dass verschiedene Überarbeitungen, Änderungen und Ergänzungen später vorgenommen werden können.

Was kommt als Nächstes?

Im nächsten Artikel werde ich eine Klasse für eine komfortable Auswahl und Sortierung von Aufträgen, Deals und Positionen nach einem der unterstützten Kriterien entwickeln und eine Collection von Marktorders und Positionen erstellen.

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

Zurück zum Inhalt


Übersetzt aus dem Russischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/ru/articles/5669

Beigefügte Dateien |
MQL5.zip (22.89 KB)
Letzte Kommentare | Zur Diskussion im Händlerforum (3)
Christian
Christian | 7 Mai 2019 in 09:49

Glückwünsch .... die Qualität der Artikel steigt stetig.

Auch das es erwähnt wird das es noch den status BETA hat.


Wenn jetzt noch diese Teile korrekt übersetzt werden , darf man zufrieden sein.

Was nützt denn ein deutscher Artikel mit Code der noch Russisch enthält ?

case ORDER_STATE_STARTED         :  return TextByLanguage("Ордер проверен на корректность, но еще не принят брокером","Order checked for correctness, but not yet accepted by broker");
      case ORDER_STATE_PLACED          :  return TextByLanguage("Ордер принят","Order accepted");
      case ORDER_STATE_CANCELED        :  return TextByLanguage("Ордер снят клиентом","Order withdrawn by client");
      case ORDER_STATE_PARTIAL         :  return TextByLanguage("Ордер выполнен частично","Order filled partially");
      case ORDER_STATE_FILLED          :  return TextByLanguage("Ордер выполнен полностью","Order filled");
      case ORDER_STATE_REJECTED        :  return TextByLanguage("Ордер отклонен","Order rejected");
      case ORDER_STATE_EXPIRED         :  return TextByLanguage("Ордер снят по истечении срока его действия","Order withdrawn upon expiration");
      case ORDER_STATE_REQUEST_ADD     :  return TextByLanguage("Ордер в состоянии регистрации (выставление в торговую систему)","Order in state of registration (placing in trading system)");
      case ORDER_STATE_REQUEST_MODIFY  :  return TextByLanguage("Ордер в состоянии модификации","Order in state of modification.");
      case ORDER_STATE_REQUEST_CANCEL  :  return TextByLanguage("Ордер в состоянии удаления","Order in deletion state");
      default                          :  return TextByLanguage("Неизвестное состояние","Unknown state");


Daran müsst ihr noch arbeiten.


Freundlichste Grüße 

Artyom Trishkin
Artyom Trishkin | 7 Mai 2019 in 10:01
Christian:

Поздравляю .... качество статьи неуклонно растет.

Также упомянуто, что он все еще имеет статус BETA.


Если теперь эти части переведены правильно, вы можете быть удовлетворены.

Что хорошего в немецкой статье с кодом, который до сих пор содержит русский язык?


Вы все еще должны работать над этим.


С наилучшими пожеланиями

Статья изначально пишется на русском языке.
Поэтому в любом случае в коде будут присутствовать тексты на русском языке. Но в частях описания библиотеки (после статьи о создании торговых классов - это примерно статья 12), будет создан класс для создания и вывода пользовательских и системных сообщений библиотеки. Там будет возможность в специальном файле вписать свой текст сообщений на любом языке.


Google-Übersetzung:

Der Artikel ist ursprünglich in Russisch verfasst.
Daher enthält der Code in jedem Fall Texte in russischer Sprache. In Teilen der Beschreibung der Bibliothek (nach dem Artikel zur Erstellung von Handelsklassen - dies ist ungefähr Artikel 12) wird jedoch eine Klasse zum Erstellen und Anzeigen von Benutzer- und Systemnachrichten der Bibliothek erstellt. Es besteht die Möglichkeit, Ihren Nachrichtentext in einer beliebigen Datei in einer beliebigen Datei einzugeben.

Christian
Christian | 7 Mai 2019 in 12:19
Artyom Trishkin:

Статья изначально пишется на русском языке.
Поэтому в любом случае в коде будут присутствовать тексты на русском языке. Но в частях описания библиотеки (после статьи о создании торговых классов - это примерно статья 12), будет создан класс для создания и вывода пользовательских и системных сообщений библиотеки. Там будет возможность в специальном файле вписать свой текст сообщений на любом языке.


Google-Übersetzung:

Der Artikel ist ursprünglich in Russisch verfasst.
Daher enthält der Code in jedem Fall Texte in russischer Sprache. In Teilen der Beschreibung der Bibliothek (nach dem Artikel zur Erstellung von Handelsklassen - dies ist ungefähr Artikel 12) wird jedoch eine Klasse zum Erstellen und Anzeigen von Benutzer- und Systemnachrichten der Bibliothek erstellt. Es besteht die Möglichkeit, Ihren Nachrichtentext in einer beliebigen Datei in einer beliebigen Datei einzugeben.

Entschuldige meine schnelles Urteil.


Ich sehe jetzt erst das die Ausgabe des Textes über eine Funktion erfolgt.

Somit hat der benutzer die Wahl. Englisch oder Russisch.

Sehr gute Entwicklung. Was dem Problem der mehrsprachigkeit entgegenwirkt.

Obwohl ja eigentlich Englisch die Standardsprache ist.


Das ist natürlich die ideal Lösung. 

Weiter so !

Extrahieren von strukturierten Daten aus HTML-Seiten mit Hilfe von CSS-Selektoren Extrahieren von strukturierten Daten aus HTML-Seiten mit Hilfe von CSS-Selektoren
Der Artikel beschreibt eine universelle Methode zur Analyse und Konvertierung von Daten aus HTML-Dokumenten auf Basis von CSS-Selektoren. Handelsberichte, Testerberichte, Ihren bevorzugten Wirtschaftskalender, öffentliche Signale, Kontoüberwachung und zusätzliche Online-Kursquellen werden direkt mit MQL verfügbar gemacht.
Untersuchung von Techniken zur Analyse der Kerzen (Teil II): Automatische Suche nach den Mustern Untersuchung von Techniken zur Analyse der Kerzen (Teil II): Automatische Suche nach den Mustern
Im vorherigen Artikel haben wir 14 Muster analysiert, die aus einer Vielzahl von bestehenden Kerzenformationen ausgewählt wurden. Es ist unmöglich, alle Muster einzeln zu analysieren, deshalb wurde eine andere Lösung gefunden. Das neue System sucht und testet neue Kerzenmuster basierend auf bekannten den Kerzentypen.
Integration von MetaTrader 5 und Python: Daten senden und empfangen Integration von MetaTrader 5 und Python: Daten senden und empfangen
Eine umfassende Datenverarbeitung erfordert umfangreiche Werkzeuge und geht oft über den Sandkasten (Sandbox) einer einzigen Anwendung hinaus. Für die Verarbeitung und Analyse von Daten, Statistiken und maschinellem Lernen werden spezielle Programmiersprachen verwendet. Eine der führenden Programmiersprachen für die Datenverarbeitung ist Python. Der Artikel enthält eine Beschreibung, wie man MetaTrader 5 und Python über Sockets verbindet und wie man Kurse über die Terminal-API erhält.
Bibliothek für ein leichtes und schnelles Entwickeln vom Programmen für den MetaTrader (Teil I). Konzept, Datenverwaltung und erste Ergebnisse Bibliothek für ein leichtes und schnelles Entwickeln vom Programmen für den MetaTrader (Teil I). Konzept, Datenverwaltung und erste Ergebnisse
Bei der Analyse einer Vielzahl von Handelsstrategien, der Entwicklung von Anwendungen für MetaTrader 5 und MetaTrader 4 Terminals und verschiedenen MetaTrader Websites kam ich zu dem Schluss, dass diese ganze Vielfalt hauptsächlich auf den gleichen elementaren Funktionen, Aktionen und Werten basiert, die regelmäßig in verschiedenen Programmen wiederkehren. Daraus entstand die plattformübergreifende Bibliothek DoEasy für die einfache und schnelle Entwicklung von Anwendungen für МetaТrader 4 und 5.