Preise und Signale in der DoEasy-Bibliothek (Teil 65): Kollektion der Markttiefe und die Klasse für die Arbeit mit MQL5.com- Signalen

26 April 2021, 08:45
Artyom Trishkin
0
205

Inhalt


Konzept

Wir haben bereits die Funktionalität für die Arbeit mit einem DOM eines beliebigen Symbols — in den vorangegangenen Artikeln habe ich die Klassen der abstrakten Orderobjekte für DOM (Depth of Market, Markttiefe) und ihre Nachkommen, die Schnappschussklasse für DOM und die Reihenklasse der DOM-Schnappschüsse erstellt. Jetzt bleibt noch, einen gemeinsamen Speicher für DOM-Snapshot-Serien-Objekte zu schaffen — die Kollektionsklasse der Schnappschuss-Reihen, die alle diese Reihen mit einem bequemen Zugriff auf jeden DOM-Schnappschuss, der in den Kollektionslisten gespeichert ist, und mit automatischer Aktualisierung (Hinzufügen neuer und Entfernen alter Schnappschüsse) zur Unterstützung der angegebenen Reihengröße speichern soll.

Neben dem Erstellen der Kollektionsklasse für die DOM-Schnappschuss-Reihen werde ich auch den neuen Bibliotheksabschnitt — andere Bibliotheksklassen — beginnen.
Ich beginne mit der Funktion für die Arbeit mit dem MQL5.com-Signaldienst, und zwar erstelle ich die Signalobjektklasse, die alle Daten eines einzelnen Signals speichert, das vom MQL5.com-Signaldienst gesendet wird.


Verbesserung der Bibliothek der Klasse

Fügen wir gleich die neuen Nachrichten zur Bibliothek hinzu. In \MQL5\Include\DoEasy\Data.mqh fügen wir die neue Nachrichtenindizes hinzu:

//--- CMBookSeries
   MSG_MBOOK_SERIES_TEXT_MBOOKSERIES,                 // DOM snapshot series
   MSG_MBOOK_SERIES_ERR_ADD_TO_LIST,                  // Error. Failed to add DOM snapshot series to the list
   
//--- CMBookSeriesCollection
   MSG_MB_COLLECTION_TEXT_MBCOLLECTION,               // DOM snapshot series collection
 
//--- CMQLSignal
   MSG_SIGNAL_MQL5_TEXT_SIGNAL,                       // Signal
   MSG_SIGNAL_MQL5_TEXT_SIGNAL_MQL5,                  // MQL5.com Signals service signal
   MSG_SIGNAL_MQL5_TRADE_MODE,                        // Account type
   MSG_SIGNAL_MQL5_DATE_PUBLISHED,                    // Publication date
   MSG_SIGNAL_MQL5_DATE_STARTED,                      // Monitoring start date
   MSG_SIGNAL_MQL5_DATE_UPDATED,                      // Date of the latest update of the trading statistics 
   MSG_SIGNAL_MQL5_ID,                                // ID
   MSG_SIGNAL_MQL5_LEVERAGE,                          // Trading account leverage
   MSG_SIGNAL_MQL5_PIPS,                              // Trading result in pips
   MSG_SIGNAL_MQL5_RATING,                            // Position in the signal rating
   MSG_SIGNAL_MQL5_SUBSCRIBERS,                       // Number of subscribers
   MSG_SIGNAL_MQL5_TRADES,                            // Number of trades
   MSG_SIGNAL_MQL5_SUBSCRIPTION_STATUS,               // Status of account subscription to a signal
   
   MSG_SIGNAL_MQL5_EQUITY,                            // Account equity
   MSG_SIGNAL_MQL5_GAIN,                              // Account growth in %
   MSG_SIGNAL_MQL5_MAX_DRAWDOWN,                      // Maximum drawdown
   MSG_SIGNAL_MQL5_PRICE,                             // Signal subscription price
   MSG_SIGNAL_MQL5_ROI,                               // Signal ROI (Return on Investment) in %

   MSG_SIGNAL_MQL5_AUTHOR_LOGIN,                      // Author login
   MSG_SIGNAL_MQL5_BROKER,                            // Broker (company) name
   MSG_SIGNAL_MQL5_BROKER_SERVER,                     // Broker server
   MSG_SIGNAL_MQL5_NAME,                              // Name
   MSG_SIGNAL_MQL5_CURRENCY,                          // Account currency
   
   MSG_SIGNAL_MQL5_TEXT_GAIN,                         // Growth
   MSG_SIGNAL_MQL5_TEXT_DRAWDOWN,                     // Drawdown
   
  };
//+------------------------------------------------------------------+

und Nachrichtentexte, die den neu hinzugefügten Indizes entsprechen:

//--- CMBookSeries
   {"Серия снимков стакана цен","Series of shots of the Depth of Market"},
   {"Ошибка. Не удалось добавить серию снимков стакана цен в список","Error. Failed to add a shots series of the Depth of Market to the list"},
   
//--- CMBookSeriesCollection
   {"Коллекция серий снимков стакана цен","Collection of series of the Depth of Market shot"},   
   
//--- CMQLSignal
   {"Сигнал","Signal"},
   {"Сигнал сервиса сигналов MQL5.com","Signal from MQL5.com signal service"},
   {"Тип счета","Account type"},
   {"Дата публикации","Publication date"},
   {"Дата начала мониторинга","Monitoring starting date"},
   {"Дата последнего обновления торговой статистики","The date of the last update of the signal's trading statistics"},
   {"ID","ID"},
   {"Плечо торгового счета","Account leverage"},
   {"Результат торговли в пипсах","Profit in pips"},
   {"Позиция в рейтинге сигналов","Position in rating"},
   {"Количество подписчиков","Number of subscribers"},
   {"Количество трейдов","Number of trades"},
   {"Состояние подписки счёта на этот сигнал","Account subscription status for this signal"},

   {"Средства на счете","Account equity"},
   {"Прирост счета в процентах","Account gain"},
   {"Максимальная просадка","Account maximum drawdown"},
   {"Цена подписки на сигнал","Signal subscription price"},
   {"Значение ROI (Return on Investment) сигнала в %","Return on Investment (%)"},
   
   {"Логин автора","Author login"},
   {"Наименование брокера (компании)","Broker name (company)"},
   {"Сервер брокера","Broker server"},
   {"Имя","Name"},
   {"Валюта счета","Base currency"},
   
   {"Прирост","Gain"},
   {"Просадка","Drawdown"},
   
  };
//+---------------------------------------------------------------------+

Da ich heute eine neue Kollektion entwickeln werde, müssen wir ihre ID festlegen. Fügen wir sie im Abschnitt ID in \MQL5\Include\DoEasy\Defines.mqh die ID der Kollektion der DOM-Schnappschuss-Reihen ein:

//--- Collection list IDs
#define COLLECTION_HISTORY_ID          (0x777A)                   // Historical collection list ID
#define COLLECTION_MARKET_ID           (0x777B)                   // Market collection list ID
#define COLLECTION_EVENTS_ID           (0x777C)                   // Event collection list ID
#define COLLECTION_ACCOUNT_ID          (0x777D)                   // Account collection list ID
#define COLLECTION_SYMBOLS_ID          (0x777E)                   // Symbol collection list ID
#define COLLECTION_SERIES_ID           (0x777F)                   // Timeseries collection list ID
#define COLLECTION_BUFFERS_ID          (0x7780)                   // Indicator buffer collection list ID
#define COLLECTION_INDICATORS_ID       (0x7781)                   // Indicator collection list ID
#define COLLECTION_INDICATORS_DATA_ID  (0x7782)                   // Indicator data collection list ID
#define COLLECTION_TICKSERIES_ID       (0x7783)                   // Tick series collection list ID
#define COLLECTION_MBOOKSERIES_ID      (0x7784)                   // DOM series collection list ID
//--- Data parameters for file operations

Verbessern wir die Datei der Objektklasse "DOM Schnappschuss-Reihe". In manchen Fällen sollte die Objektbeschreibung nur einmal angezeigt werden, während wir manchmal die Beschreibungen aller DOM-Schnappschuss-Reihen auf einmal anzeigen müssen. In diesem Fall sieht die Liste optisch ansprechender aus, wenn vor der Beschreibung der einzelnen Reihen ein Bindestrich eingefügt wird. Fügen wir in der Klassendatei der DOM-Schnappschuss-Reihen \MQL5\Include\DoEasy\Objects\Book\MBookSeries.mqh die Änderungen in der Beschreibung der Methoden hinzu:

//--- Display (1) description and (2) short description of a DOM snapshot series
   void              Print(const bool dash=false);
   void              PrintShort(const bool dash=false);

//--- Constructors

Wir verwenden einfach das Flag, das die Notwendigkeit der Anzeige eines Bindestrichs vor der Objektbeschreibung anzeigt.

Fügen wir die gleichen Änderungen in der Implementierung der Methoden hinzu:

//+------------------------------------------------------------------+
//| Display the description of the DOM snapshot series in the journal|
//+------------------------------------------------------------------+
void CMBookSeries::Print(const bool dash=false)
  {
   string txt=
     (
      CMessage::Text(MSG_TICKSERIES_REQUIRED_HISTORY_DAYS)+(string)this.RequiredUsedDays()+", "+
      CMessage::Text(MSG_LIB_TEXT_TS_ACTUAL_DEPTH)+(string)this.DataTotal()
     );
   ::Print((dash ? "- " : ""),this.Header(),": ",txt);
  }
//+------------------------------------------------------------------+
//| Display a short description of a DOM snapshot series             |
//+------------------------------------------------------------------+
void CMBookSeries::PrintShort(const bool dash=false)
  {
   ::Print((dash ? "- " : ""),this.Header());
  }
//+------------------------------------------------------------------+

Standardmäßig ist das Flag auf false gesetzt, sodass kein Bindestrich vor der Objektbeschreibung angezeigt wird.


Die Kollektionsklasse für DOM

Wir haben alle notwendigen Objekte für die Erstellung der DOM Kollektion. Und zwar haben wir das DOM-Orderobjekt, das durch die Struktur MqlBookInfo im Terminal repräsentiert wird. Wenn ein Ereignis von BookEvent auftritt, wird der OnBookEvent() aufgerufen. Als dessen Parameter wird ein Symbol angegeben, für das DOM-Änderungsereignis eingetreten ist. Wir sind in der Lage, alle aktuellen DOM-Daten in das Array der Struktur MqlBookInfo zu übernehmen. Die Kollektion dieser Daten in der Bibliothek wird durch das DOM-Schnappschuss-Objekt mit den Orderobjekten beschrieben, die wir bei der Behandlung des DOM-Änderungsereignisses erhalten haben. Bei jeder DOM-Änderung erstellen wir ein neues Schnappschuss-Objekt, das wir der Liste hinzufügen. Eine solche Liste wird durch das DOM-Schnappschuss-Reihen-Objekt dargestellt. Wir erstellen solche Listen für jedes Symbol, das wir abonniert haben, um DOM-Ereignisse zu empfangen. Die Listen werden in Echtzeit erstellt (leider hat das Terminal keine DOM-Änderungshistorie für ein Symbol). Daher müssen wir nun alle vorhandenen Listen in einem einzigen DOM-Kollektionsobjekt zusammenfassen.

Die Symbol-DOM-Kollektion soll ständig aktualisierte DOM-Schnappschuss-Listen speichern, die es uns ermöglichen, die Historie der DOM-Änderungen für jedes Symbol zu erstellen, während das Programm läuft. Wir werden in der Lage sein, Daten über jeden Schnappschuss zu erhalten, der in den Listen der Kollektion vorhanden ist. Außerdem werden wir eine beliebige Reihenfolge aus jedem Schnappschuss abrufen können. Wir werden in der Lage sein, nach den benötigten Daten zu suchen, die Listen nach bestimmten Kriterien zu sortieren und statistische Studien mit den verfügbaren Kollektionen durchzuführen.

In \MQL5\Include\DoEasy\Collections\ legen wir die neue Klasse CMBookSeriesCollection in BookSeriesCollection.mqh an.

Als Basis sollte die Klasse des Basisobjekts aller CBaseObj-Bibliotheksobjekte verwendet werden, während alle notwendigen Dateien in das Klassenverzeichnis aufgenommen werden sollten:

//+------------------------------------------------------------------+
//|                                         BookSeriesCollection.mqh |
//|                        Copyright 2021, MetaQuotes Software Corp. |
//|                             https://MQL5.com/en/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2021, MetaQuotes Software Corp."
#property link      "https://MQL5.com/en/users/artmedia70"
#property version   "1.00"
//+------------------------------------------------------------------+
//| Include files                                                    |
//+------------------------------------------------------------------+
#include "ListObj.mqh"
#include "..\Objects\Book\MBookSeries.mqh"
#include "..\Objects\Symbols\Symbol.mqh"
//+------------------------------------------------------------------+
//| Collection of symbol DOM series                                  |
//+------------------------------------------------------------------+
class CMBookSeriesCollection : public CBaseObj
  {
  }

Schauen wir uns den Klassenkörper und seine Methoden an und analysieren wir die Implementierung der Methoden und ihren Zweck:

//+------------------------------------------------------------------+
//| Collection of symbol DOM series                                  |
//+------------------------------------------------------------------+
class CMBookSeriesCollection : public CBaseObj
  {
private:
   CListObj                m_list;                                   // List of used symbol DOM series
//--- Return the DOM series index by a symbol name
   int                     IndexMBookSeries(const string symbol);
public:
//--- Return (1) itself, (2) DOM series collection list and (3) the number of DOM series in the list
   CMBookSeriesCollection *GetObject(void)                              { return &this;               }
   CArrayObj              *GetList(void)                                { return &this.m_list;        }
   int                     DataTotal(void)                        const { return this.m_list.Total(); }
//--- Return the pointer to the DOM series object (1) by symbol and (2) by index in the list
   CMBookSeries           *GetMBookseries(const string symbol);
   CMBookSeries           *GetMBookseries(const int index)              { return this.m_list.At(index);}
//--- Create symbol DOM series collection list
   bool                    CreateCollection(const CArrayObj *list_symbols,const uint required=0);
//--- Set the flag of using the DOM series of (1) a specified symbol and (2) all symbols
   void                    SetAvailableMBookSeries(const string symbol,const bool flag=true);
   void                    SetAvailableMBookSeries(const bool flag=true);
//--- Return the flag of using the DOM series of (1) a specified symbol and (2) all symbols
   bool                    IsAvailableMBookSeries(const string symbol);
   bool                    IsAvailableMBookSeries(void);

//--- Set the number of DOM history days of (1) a specified symbol and (2) all symbols
   bool                    SetRequiredUsedDays(const string symbol,const uint required=0);
   bool                    SetRequiredUsedDays(const uint required=0);

//--- Return the DOM snapshot object of a specified symbol (1) by index and (2) by time in milliseconds
   CMBookSnapshot         *GetMBook(const string symbol,const int index);
   CMBookSnapshot         *GetMBook(const string symbol,const long time_msc);

//--- Update the DOM series of a specified symbol
   bool                    Refresh(const string symbol,const long time_msc);

//--- Display (1) the complete and (2) short collection description in the journal
   void                    Print(void);
   void                    PrintShort(void);
   
//--- Constructor
                           CMBookSeriesCollection();
  };
//+------------------------------------------------------------------+

Die Methodenbeschreibungen machen deutlich, dass die Kollektion selbst durch m_list repräsentiert wird, die die Reihen-Objekte von DOM-Schnappschüssen für verschiedene Symbole speichern soll, die durch die Klasse CMBookSeries repräsentiert werden. Dies sind die Symbole mit DOM-Schnappschuss-Objekten, die durch die Klasse CMBookSnapshot repräsentiert werden.

Betrachten wir die Implementierung der Methoden der Klasse im Detail.

Im Klassenkonstruktor, löschen wir die Kollektionsliste, setzen das Flag für die sortierte Liste auf die Liste und weisen die ID der Kollektionsliste der DOM-Reihen zu:

//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CMBookSeriesCollection::CMBookSeriesCollection()
  {
   this.m_list.Clear();
   this.m_list.Sort();
   this.m_list.Type(COLLECTION_MBOOKSERIES_ID);
  }
//+------------------------------------------------------------------+

Standardmäßig werden alle Reihen in der Kollektionsliste nach dem Symbolnamen der DOM-Schnappschuss-Reihe sortiert.

Die Methode zum Erstellen der Kollektionsliste der Symbol-DOM-Reihen:

//+------------------------------------------------------------------+
//| Create symbol DOM series collection list                         |
//+------------------------------------------------------------------+
bool CMBookSeriesCollection::CreateCollection(const CArrayObj *list_symbols,const uint required=0)
  {
//--- If an empty list of symbol objects is passed, exit
   if(list_symbols==NULL)
      return false;
//--- Get the number of symbol objects in the passed list
   int total=list_symbols.Total();
//--- Clear the DOM series collection list
   this.m_list.Clear();
//--- In a loop by all symbol objects
   for(int i=0;i<total;i++)
     {
      //--- get the next symbol object
      CSymbol *symbol_obj=list_symbols.At(i);
      //--- if failed to get a symbol object, move on to the next one in the list
      if(symbol_obj==NULL)
         continue;
      //--- Create a new DOM series object
      CMBookSeries *bookseries=new CMBookSeries(symbol_obj.Name(),required);
      //--- If failed to create the DOM series object, move on to the next symbol in the list
      if(bookseries==NULL)
         continue;
      //--- Set the sorted list flag for the DOM series collection list
      this.m_list.Sort();
      //--- If the object with the same symbol name is already present in the DOM series collection list, remove the DOM series object
      if(this.m_list.Search(bookseries)>WRONG_VALUE)
         delete bookseries;
      //--- otherwise, there is no object with such a symbol name in the collection yet
      else
        {
         //--- if failed to add the DOM series object to the collection list, remove the series object,
         //--- inform of that and return 'false'
         if(!this.m_list.Add(bookseries))
           {
            delete bookseries;
            ::Print(DFUN,"\"",symbol_obj.Name(),"\": ",CMessage::Text(MSG_MBOOK_SERIES_ERR_ADD_TO_LIST));
            return false;
           }
        } 
     }
//--- Collection created successfully, return 'true'
   return true;
  }
//+------------------------------------------------------------------+

Die gesamte Logik der Methode ist in ihrem Listing detailliert beschrieben. Kurz gesagt, erhält die Methode die Liste aller im Programm verwendeten Symbole und die Anzahl der DOM-Schnappschüsse, die in den Kollektionslisten gespeichert werden können. In der Schleife durch die Liste an die Methode übergeben, erhalten wir das nächste Symbol-Objekt aus der Liste, erstellen ein neues DOM Schnappschuss-Reihen-Objekt durch das Symbol und fügen es in die Kollektionsliste. Als Ergebnis erhalten wir die Liste der Schnappschuss-Reihen-Objekte von DOMs für verschiedene Symbole — die in der an die Methode übergebenen Liste vorhanden sind. Jede erzeugte Liste von Schnappschuss-Reihen ist zunächst leer.
Die in der Kollektionsliste erstellten Listen werden in der Methode zum Aktualisieren der Schnappschuss-Reihen-Liste eines DOMs für ein bestimmtes Symbol gefüllt:

//+------------------------------------------------------------------+
//| Update the snapshot series list of a specified symbol DOM        |
//+------------------------------------------------------------------+
bool CMBookSeriesCollection::Refresh(const string symbol,const long time_msc)
  {
   CMBookSeries *bookseries=this.GetMBookseries(symbol);
   if(bookseries==NULL)
      return false;
   return bookseries.Refresh(time_msc);
  }
//+------------------------------------------------------------------+

Da OnBookEvent() für jedes Symbol aktiviert wird, wird die Aktualisierungsmethode nur für ein Symbol aus der Kollektion verwendet und nicht für die gesamte Kollektion. Die Methode erhält den Namen eines Symbols, das das DOM-Änderungsereignis hervorgerufen hat, und die Zeit der Registrierung eines DOM-Änderungsereignisses in Millisekunden. Weiterhin erhalten wir das DOM-Schnappschuss-Reihen-Objekt durch ein an die Methode übergebenes Symbol und geben das Ergebnis der Methode Refresh() des DOM-Schnappschuss-Reihen-Objekts zurück, das wir im vorherigen Artikel betrachtet haben.

Die Methode zur Rückgabe des DOM-Reihen-Index nach Symbolname:

//+------------------------------------------------------------------+
//| Return the DOM series index by a symbol name                     |
//+------------------------------------------------------------------+
int CMBookSeriesCollection::IndexMBookSeries(const string symbol)
  {
   const CMBookSeries *obj=new CMBookSeries(symbol==NULL || symbol=="" ? ::Symbol() : symbol);
   if(obj==NULL)
      return WRONG_VALUE;
   this.m_list.Sort();
   int index=this.m_list.Search(obj);
   delete obj;
   return index;
  }
//+------------------------------------------------------------------+

Hier erzeugen wir ein neues temporäres DOM-Schnappschuss-Reihen-Objekt mit einem in den Eingängen angegebenen Symbol. Wir setzen das Flag für eine sortierte Liste (die Suche wird nur in der sortierten Liste durchgeführt) und erhalten den Objektindex mit dem gleichen Symbol in der Liste. Achten Sie darauf, das temporäre Objekt zu entfernen und den erhaltenen Index zurückzugeben. Wenn das DOM Schnappschuss-Reihen-Objekt mit einem angegebenen Symbol in der Liste vorhanden ist, gibt die Methode Search() seinen Index zurück, andernfalls gibt die Methode -1 zurück.

Die Methode gibt das angegebene Symbol DOM-Reihen-Objekt zurück:

//+------------------------------------------------------------------+
//| Return the specified symbol DOM series object                    |
//+------------------------------------------------------------------+
CMBookSeries *CMBookSeriesCollection::GetMBookseries(const string symbol)
  {
   int index=this.IndexMBookSeries(symbol);
   return this.m_list.At(index);
  }
//+------------------------------------------------------------------+

Hier verwenden wir die oben angegebene Methode, um den Index des DOM-Schnappschuss-Reihen-Objekts in der Liste für das Symbol zu erhalten und um den Zeiger auf das Objekt in der Liste per angegebenem Index zurückzugeben. Wenn das Objekt mit dem angegebenen Symbol nicht in der Liste vorhanden ist (der Index ist -1), gibt die Methode NULL zurück.

Um die Funktionalität der Arbeit mit DOMs zu nutzen, müssen wir uns für jedes Symbol auf den Empfang von DOM-Änderungsereignissen abonnieren. Diese Funktion ist bereits in der Symbol-Objektklasse vorhanden. Außerdem verfügt das Objekt "DOM-Schnappschuss-Reihe" über ein Flag, das anzeigt, dass die Behandlung von DOM-Änderungsereignissen aktiviert/deaktiviert werden muss. Mit anderen Worten: Selbst wenn das Abonnement für BookEvent-Ereignisse aktiv ist, können wir die Arbeit mit dem DOM für dieses Symbol mithilfe des Flags vorübergehend deaktivieren. Wir verwenden die folgende Methode, um das Flag zu setzen, das die Notwendigkeit der Behandlung von BookEvent-Ereignissen des Symbols anzeigt:

//+------------------------------------------------------------------+
//| Set the flag of using a series                                   |
//| of a specified symbol's DOM                                      |
//+------------------------------------------------------------------+
void CMBookSeriesCollection::SetAvailableMBookSeries(const string symbol,const bool flag=true)
  {
   CMBookSeries *bookseries=this.GetMBookseries(symbol);
   if(bookseries==NULL)
      return;
   bookseries.SetAvailable(flag);
  }
//+------------------------------------------------------------------+

Hier erhalten wir das Reihen-Objekt eines DOMs für ein angegebenes Symbol und setzen das an die Methode übergebene Flag dafür.
Der Standardwert für das Flag ist true.

Wenn unser Programm mit mehreren Symbolen arbeitet, während wir die oben erwähnten DOM-Schnappschuss-Reihen-Flags verwalten müssen, dann kann die Methode, die den Flag-Wert für alle im Programm verwendeten Symbole auf einmal definiert, hilfreich sein:

//+------------------------------------------------------------------+
//|Set the flag of using the DOM series for all symbols              |
//+------------------------------------------------------------------+
void CMBookSeriesCollection::SetAvailableMBookSeries(const bool flag=true)
  {
   for(int i=0;i<this.m_list.Total();i++)
     {
      CMBookSeries *bookseries=this.m_list.At(i);
      if(bookseries==NULL)
         continue;
      bookseries.SetAvailable(flag);
     }
  }
//+------------------------------------------------------------------+

Hier wird in der Schleife durch die Gesamtzahl der DOM Schnappschuss-Serien-Objekte in der Kollektion, die nächste Reihen-Liste geholt und das dafür an die Methode übergebene Flag gesetzt. Der Standardwert für das Flag ist true.

Die Methoden, die den oben betrachteten gegenüberliegen, geben die Werte von Flags für die Arbeit mit der Reihen-Liste entweder eines bestimmten Symbols oder aller auf einmal zurück.

Die Methode, die das Flag für die Verwendung der DOM-Reihe eines bestimmten Symbols zurückgibt:

//+------------------------------------------------------------------+
//|Return the flag of using the DOM series of a specified symbol     |
//+------------------------------------------------------------------+
bool CMBookSeriesCollection::IsAvailableMBookSeries(const string symbol)
  {
   CMBookSeries *bookseries=this.GetMBookseries(symbol);
   if(bookseries==NULL)
      return false;
   return bookseries.IsAvailable();
  }
//+------------------------------------------------------------------+

Hier erhalten wir die Objektreihe der DOM-Schnappschüsse durch ein an die Methode übergebenes Symbol und geben den für das Objekt angegebenen Flag-Wert zurück.

Die Methode gibt das Flag der Verwendung der DOM-Reihe aller Symbole zurück:

//+------------------------------------------------------------------+
//| Return the flag of using the DOM series of all symbols           |
//+------------------------------------------------------------------+
bool CMBookSeriesCollection::IsAvailableMBookSeries(void)
  {
   bool res=true;
   int total=this.m_list.Total();
   for(int i=0;i<total;i++)
     {
      CMBookSeries *bookseries=this.m_list.At(i);
      if(bookseries==NULL)
         continue;
      res &=bookseries.IsAvailable();
     }
   return res;
  }
//+------------------------------------------------------------------+

Die Methode gibt true nur dann zurück, wenn das Flag, das die Notwendigkeit der Symbolverwendung anzeigt, für jedes der verwendeten Symbole in deren DOM-Reihe aktiviert ist. Hier, in der Schleife durch alle Objekte der Kollektion Reihen, erhalten wir die nächste Reihe und fügen den Wert des Reihen-Flags in die Variable ein. Wenn das Flag für mindestens eines der Symbole auf false gesetzt ist, gibt die Methode false zurück.

Die Methode setzt die Anzahl der Schnappschüsse in der DOM-Historie des angegebenen Symbols:

//+------------------------------------------------------------------+
//| Set the number of snapshots in history                           |
//| of a specified symbol's DOM                                      |
//+------------------------------------------------------------------+
bool CMBookSeriesCollection::SetRequiredUsedDays(const string symbol,const uint required=0)
  {
   CMBookSeries *bookseries=this.GetMBookseries(symbol);
   if(bookseries==NULL)
      return false;
   bookseries.SetRequiredUsedDays(required);
   return true;
  }
//+------------------------------------------------------------------+


Die Methode wird verwendet, um die Gesamtzahl der DOM-Schnappschüsse für jedes der Symbole zu begrenzen und zu vermeiden, dass zusätzlicher Speicher für veraltete Daten verwendet wird. Hier erhalten wir die Schnappschuss-Reihen-Liste eines angegebenen Symbols und setzen die maximale Anzahl von Schnappschüssen in der Liste für dieses Symbol. Wenn wir die Liste der Schnappschuss-Reihen nicht erhalten haben, wird false zurückgegeben. Wenn die angeforderte Zahl erfolgreich gesetzt wurde, wird true zurückgegeben.

Die Methode gibt die Anzahl der Schnappschüsse in der DOM-Historie aller Symbole zurück:

//+------------------------------------------------------------------+
//|Set the number of snapshots in the DOM history of all symbols     |
//+------------------------------------------------------------------+
bool CMBookSeriesCollection::SetRequiredUsedDays(const uint required=0)
  {
   bool res=true;
   for(int i=0;i<this.m_list.Total();i++)
     {
      CMBookSeries *bookseries=this.m_list.At(i);
      if(bookseries==NULL)
        {
         res &=false;
         continue;
        }
      bookseries.SetRequiredUsedDays(required);
     }
   return res;
  }
//+------------------------------------------------------------------+

Die Methode setzt eine vergleichbare Zahl für die benötigten DOM-Historiendaten für alle im Programm verwendeten Symbole auf einmal.

In der Schleife durch die Gesamtzahl der Reihen-Objekte in der Kollektion, erhalten wir das nächste DOM-Schnappschuss-Reihen-Objekt und setzen die angegebene Menge an Daten dafür. Wenn es nicht gelingt, die Reihe zu erhalten, wird false zum Ergebnis hinzugefügt. Wenn also für mindestens eine Reihe die erforderliche Menge nicht ermittelt werden konnte, gibt die Methode false zurück. Nach Beendigung der Schleife wird das erhaltene Ergebnis in der resVariablen zurückgegeben.

Die Methode gibt das DOM-Schnappschuss-Objekt eines angegebenen Symbols per Index zurück:

//+------------------------------------------------------------------+
//|Return the DOM snapshot object of a specified symbol by index     |
//+------------------------------------------------------------------+
CMBookSnapshot *CMBookSeriesCollection::GetMBook(const string symbol,const int index)
  {
   CMBookSeries *bookseries=this.GetMBookseries(symbol);
   if(bookseries==NULL)
      return NULL;
   return bookseries.GetMBookByListIndex(index);
  }
//+------------------------------------------------------------------+

Hier erhalten wir das DOM-Schnappschuss-Reihen-Objekt eines angegebenen Symbols und geben den Zeiger auf das DOM-Schnappschuss-Objekt mit einem angegebenen Index zurück, indem wir die Methode GetMBookByListIndex() der Klasse CMBookSeries verwenden, die im vorherigen Artikel beschrieben wurde.

Die Methode gibt das DOM-Schnappschuss-Objekt eines angegebenen Symbols nach Zeit in Millisekunden zurück:

//+------------------------------------------------------------------+
//| Return the DOM snapshot object of a specified symbol             |
//| by time in milliseconds                                          |
//+------------------------------------------------------------------+
CMBookSnapshot *CMBookSeriesCollection::GetMBook(const string symbol,const long time_msc)
  {
   CMBookSeries *bookseries=this.GetMBookseries(symbol);
   if(bookseries==NULL)
      return NULL;
   return bookseries.GetMBook(time_msc);
  }
//+------------------------------------------------------------------+

Hier erhalten wir das DOM-Schnappschuss-Reihen-Objekt eines angegebenen Symbols und geben den Zeiger auf das DOM-Schnappschuss-Objekt mit einem angegebenen Index zurück, indem wir die Methode GetMBook() der Klasse CMBookSeries verwenden, die im vorherigen Artikel beschrieben wurde.

Die Besonderheit der Methode besteht darin, dass wir, um den Zeiger auf das DOM-Schnappschuss-Objekt zu erhalten, seine genaue Zeit in Millisekunden kennen müssen.

Die Methode, die die vollständige Beschreibung der DOM Schnappschuss Reihen Kollektion in der Zeitschrift anzeigt:

//+------------------------------------------------------------------+
//| Display complete collection description to the journal           |
//+------------------------------------------------------------------+
void CMBookSeriesCollection::Print(void)
  {
   ::Print(CMessage::Text(MSG_MB_COLLECTION_TEXT_MBCOLLECTION),":");
   for(int i=0;i<this.m_list.Total();i++)
     {
      CMBookSeries *bookseries=this.m_list.At(i);
      if(bookseries==NULL)
         continue;
      bookseries.Print(true);
     }
  }
//+------------------------------------------------------------------+

Zuerst die Kopfzeile anzeigen, dann in der Schleife, jedes nachfolgende DOM-Serien-Objekt der Kollektion abrufen und die vollständige Beschreibung anzeigen. In der Methode Print() des Schnappschuss-Reihen-Objekts übergeben wir true, damit die Methode einen Bindestrich vor die Beschreibung setzt.

Die Methode, die die kurze Kollektionsliste in das Journal schreibt:

//+------------------------------------------------------------------+
//| Display the short collection description in the journal          |
//+------------------------------------------------------------------+
void CMBookSeriesCollection::PrintShort(void)
  {
   ::Print(CMessage::Text(MSG_MB_COLLECTION_TEXT_MBCOLLECTION),":");
   for(int i=0;i<this.m_list.Total();i++)
     {
      CMBookSeries *bookseries=this.m_list.At(i);
      if(bookseries==NULL)
         continue;
      bookseries.PrintShort(true);
     }
  }
//+------------------------------------------------------------------+

Die Methode ist identisch mit der oben beschriebenen, mit dem Unterschied, dass die Methode der Anzeige einer Kurzbeschreibung des DOM-Serien-Objekts zur Anzeige der Beschreibung der Kollektion-Reihe verwendet wird.

Verbessern wir nun die Klasse des Hauptobjekts der Bibliothek CEngine in \MQL5\Include\DoEasy\Engine.mqh.

Wir binden die Klasse des DOM-Schnappschuss-Reihen-Kollektion in die Datei ein:

//+------------------------------------------------------------------+
//|                                                       Engine.mqh |
//|                        Copyright 2020, MetaQuotes Software Corp. |
//|                             https://MQL5.com/en/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2020, MetaQuotes Software Corp."
#property link      "https://MQL5.com/en/users/artmedia70"
#property version   "1.00"
//+------------------------------------------------------------------+
//| Include files                                                    |
//+------------------------------------------------------------------+
#include "Services\TimerCounter.mqh"
#include "Collections\HistoryCollection.mqh"
#include "Collections\MarketCollection.mqh"
#include "Collections\EventsCollection.mqh"
#include "Collections\AccountsCollection.mqh"
#include "Collections\SymbolsCollection.mqh"
#include "Collections\ResourceCollection.mqh"
#include "Collections\TimeSeriesCollection.mqh"
#include "Collections\BuffersCollection.mqh"
#include "Collections\IndicatorsCollection.mqh"
#include "Collections\TickSeriesCollection.mqh"
#include "Collections\BookSeriesCollection.mqh"
#include "TradingControl.mqh"
//+------------------------------------------------------------------+

In die Objektliste der Klasse fügen wir ein neues Objekt hinzu — die DOM-Schnappschuss-Reihen-Kollektion-Klasse:

//+------------------------------------------------------------------+
//| Library basis class                                              |
//+------------------------------------------------------------------+
class CEngine
  {
private:
   CHistoryCollection   m_history;                       // Collection of historical orders and deals
   CMarketCollection    m_market;                        // Collection of market orders and deals
   CEventsCollection    m_events;                        // Event collection
   CAccountsCollection  m_accounts;                      // Account collection
   CSymbolsCollection   m_symbols;                       // Symbol collection
   CTimeSeriesCollection m_time_series;                  // Timeseries collection
   CBuffersCollection   m_buffers;                       // Collection of indicator buffers
   CIndicatorsCollection m_indicators;                   // Indicator collection
   CTickSeriesCollection m_tick_series;                  // Collection of tick series
   CMBookSeriesCollection m_book_series;                 // Collection of DOM series
   CResourceCollection  m_resource;                      // Resource list
   CTradingControl      m_trading;                       // Trading management object
   CPause               m_pause;                         // Pause object
   CArrayObj            m_list_counters;                 // List of timer counters
   int                  m_global_error;                  // Global error code
   bool                 m_first_start;                   // First launch flag
   bool                 m_is_hedge;                      // Hedge account flag
   bool                 m_is_tester;                     // Flag of working in the tester
   bool                 m_is_market_trade_event;         // Account trading event flag
   bool                 m_is_history_trade_event;        // Account history trading event flag
   bool                 m_is_account_event;              // Account change event flag
   bool                 m_is_symbol_event;               // Symbol change event flag
   ENUM_TRADE_EVENT     m_last_trade_event;              // Last account trading event
   int                  m_last_account_event;            // Last event in the account properties
   int                  m_last_symbol_event;             // Last event in the symbol properties
   ENUM_PROGRAM_TYPE    m_program;                       // Program type
   string               m_name;                          // Program name

Fügen wir die neue Ereignisbehandlung von BookEvent hinzu. In der Methode, die die Liste der verwendeten Symbole in der Symbol-Kollektion setzt, neben der Übergabe der Anzahl der Tage für die Tick-Reihe, hinzufügen, dass die maximale Anzahl der DOM Schnappschüsse übergeben wird:

//--- (1) Timer, event handler (2) NewTick, (3) Calculate, (4) BookEvent, (4) Deinit
   void                 OnTimer(SDataCalculate &data_calculate);
   void                 OnTick(SDataCalculate &data_calculate,const uint required=0);
   int                  OnCalculate(SDataCalculate &data_calculate,const uint required=0);
   bool                 OnBookEvent(const string &symbol);
   void                 OnDeinit(void);
   
//--- Set the list of used symbols in the symbol collection and create the collection of symbol timeseries
   bool                 SetUsedSymbols(const string &array_symbols[],const uint required_ticks=0,const uint required_books=0);

Fügen wir in der Liste der Methoden für die Arbeit mit der Sammlung von Tick-Serien die neuen Methoden zur Vereinfachung der Arbeit mit der Sammlung von Tick-Serien hinzu und schreiben die Methoden für die Arbeit mit der Sammlung von DOM-Serien:

//--- Return (1) the tick series collection, (2) the list of tick series from the tick series collection
   CTickSeriesCollection *GetTickSeriesCollection(void)                                { return &this.m_tick_series;                                  }
   CArrayObj           *GetListTickSeries(void)                                        { return this.m_tick_series.GetList();                         }

//--- Create (1) a specified tick series and (2) all tick series
   bool                 TickSeriesCreate(const string symbol,const uint required=0)    { return this.m_tick_series.CreateTickSeries(symbol,required); }
   bool                 TickSeriesCreateAll(const uint required=0)                     { return this.m_tick_series.CreateTickSeriesAll(required);     }

//--- Update (1) a tick series of a specified symbol, (2) all symbols and (3) all symbols except the current one
   void                 TickSeriesRefresh(const string symbol)                         { this.m_tick_series.Refresh(symbol);                          }
   void                 TickSeriesRefreshAll(void)                                     { this.m_tick_series.Refresh();                                }
   void                 TickSeriesRefreshAllExceptCurrent(void)                        { this.m_tick_series.RefreshExpectCurrent();                   }

//--- Return (1) the DOM series collection and (2) the list of DOM series from the DOM series collection
   CMBookSeriesCollection *GetMBookSeriesCollection(void)                              { return &this.m_book_series;                         }
   CArrayObj           *GetListMBookSeries(void)                                       { return this.m_book_series.GetList();                }

//--- Update the DOM series of a specified symbol
   void                 MBookSeriesRefresh(const string symbol,const long time_msc)    { this.m_book_series.Refresh(symbol,time_msc);        }

//--- Return the DOM series of a specified symbol
   CMBookSeries        *GetMBookSeries(const string symbol)                            { return this.m_book_series.GetMBookseries(symbol);   }

Alle diese Methoden rufen einfach die Methoden der entsprechenden gleichnamigen Kollektionen auf.

Implementieren wir OnBookEvent() der Bibliothek außerhalb des Klassenkörpers:

//+------------------------------------------------------------------+
//| BookEvent event handler                                          |
//+------------------------------------------------------------------+
bool CEngine::OnBookEvent(const string &symbol)
  {
   CSymbol *sym=this.m_symbols.GetSymbolObjByName(symbol);
   if(sym==NULL || !sym.BookdepthSubscription())
      return false;
   return this.m_book_series.Refresh(sym.Name(),sym.Time());
  }
//+------------------------------------------------------------------+

Da der OnBookEvent() immer nur während des DOM-Änderungsereignisses auf einem einzelnen Symbol aktiviert wird, können wir das Symbol innerhalb des Handlers selbst definieren.
Die Methode erhält den Namen eines Symbols, bei dem das DOM-Änderungsereignis aufgetreten ist. Als Nächstes erhalten wir das entsprechende Symbol-Objekt aus der Klasse der Symbol-Kollektion und geben das Ergebnis der Methode zum Aktualisieren der entsprechenden Reihe von DOM-Schnappschüssen zurück. Außerdem geben wir in der Methode Refresh() die Zeit in Millisekunden an, die für einen neu erzeugten DOM-Schnappschuss gesetzt werden soll.

Verbessern wir nun die Methode, die die Liste der verwendeten Symbole in der Kollektion setzt:

//+------------------------------------------------------------------+
//| Set the list of used symbols in the symbol collection            |
//| and create the collections of timeseries, tick series            |
//| and symbol DOM series                                            |
//+------------------------------------------------------------------+
bool CEngine::SetUsedSymbols(const string &array_symbols[],const uint required_ticks=0,const uint required_books=0)
  {
   bool res=this.m_symbols.SetUsedSymbols(array_symbols);
   CArrayObj *list=this.GetListAllUsedSymbols();
   if(list==NULL)
      return false;
   res&=this.m_time_series.CreateCollection(list);
   res&=this.m_tick_series.CreateCollection(list,required_ticks);
   res&=this.m_book_series.CreateCollection(list,required_books);
   return res;
  }
//+------------------------------------------------------------------+

Nun erhält die Methode die Anzahl der Tage der Tick-Reihe und die maximale Anzahl der DOM-Schnappschüsse in ihrer Reihe.
Hier haben wir die Erstellung der DOM-Schnappschuss-Reihen-Kollektion für alle Symbole hinzugefügt.

Damit ist die Verbesserung der Klassen für die Arbeit mit DOM-Reihen abgeschlossen.
In der Zukunft werde ich vielleicht auf dieses Thema zurückkommen, um weitere Verbesserungen vorzunehmen, aber jetzt wollen wir uns mit anderen notwendigen Bibliotheksfunktionen beschäftigen.

MQL5.com Signals Service ist ein Kopierhandelsdienst, der es Ihnen ermöglicht, den Handel des Anbieters automatisch auf Ihrem Handelskonto zu kopieren.
Dabei ist das MQL5-Signalobjekt das Handelskonto, auf dem der Handel kontrolliert wird, um sie öffentlich zu übertragen — eine Signalquelle.
Eine Signalquelle hat ihre eigenen Parameter, die mit den Funktionen SignalBaseGetInteger(), SignalBaseGetDouble() und SignalBaseGetString() ermittelt werden können. Außerdem gibt es Abonnement-Parameter — das Kopieren von Signalen für ein bestimmtes Konto. Diese Parameter können mit den Funktionen SignalInfoGetDouble(), SignalInfoGetInteger() und SignalInfoGetString() ermittelt werden.

Ein MQL5-Signalobjekt soll eine Signalquelle beschreiben, die im Terminal zum Abonnieren verfügbar ist. Es ist möglich, nur ein Signal von einem Konto zu abonnieren, aber wir können trotzdem die vollständige Liste aller Signale (MQL5-Signalobjekte) haben, die für die Subskription verfügbar sind, mit der Möglichkeit, sie nach jeder Eigenschaft zu sortieren, zu vergleichen und ein ausgewähltes Signal zu abonnieren. Dies ist eine sehr bequeme und nützliche Funktionalität für diejenigen, die vom MQL5.com Signalservice profitieren möchten.

Die Objektklasse für MQL5-Signale

In \MQL5\Include\DoEasy\Defines.mqh fügen wir die Enumeration der Eigenschaften integer, real und string des MQL5-Signal-Objekts hinzu:

//+------------------------------------------------------------------+
//| Data for working with MQL5.com signals                           |
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| The list of possible signal events                               |
//+------------------------------------------------------------------+
#define SIGNAL_MQL5_EVENTS_NEXT_CODE  (MBOOK_ORD_EVENTS_NEXT_CODE+1)   // The code of the next event after the last signal event code
//+------------------------------------------------------------------+
//| MQL5 signal integer properties                                   |
//+------------------------------------------------------------------+
enum ENUM_SIGNAL_MQL5_PROP_INTEGER
  {
   SIGNAL_MQL5_PROP_TRADE_MODE = 0,                   // Account type
   SIGNAL_MQL5_PROP_DATE_PUBLISHED,                   // Signal publication date 
   SIGNAL_MQL5_PROP_DATE_STARTED,                     // Start date of signal monitoring
   SIGNAL_MQL5_PROP_DATE_UPDATED,                     // Date of the latest update of the signal trading statistics
   SIGNAL_MQL5_PROP_ID,                               // Signal ID
   SIGNAL_MQL5_PROP_LEVERAGE,                         // Trading account leverage
   SIGNAL_MQL5_PROP_PIPS,                             // Trading result in pips
   SIGNAL_MQL5_PROP_RATING,                           // Position in the signal rating
   SIGNAL_MQL5_PROP_SUBSCRIBERS,                      // Number of subscribers
   SIGNAL_MQL5_PROP_TRADES,                           // Number of trades
   SIGNAL_MQL5_PROP_SUBSCRIPTION_STATUS,              // Status of account subscription to a signal
  };
#define SIGNAL_MQL5_PROP_INTEGER_TOTAL (11)           // Total number of integer properties
#define SIGNAL_MQL5_PROP_INTEGER_SKIP  (0)            // Number of integer DOM properties not used in sorting
//+------------------------------------------------------------------+
//| MQL5 signal real properties                                      |
//+------------------------------------------------------------------+
enum ENUM_SIGNAL_MQL5_PROP_DOUBLE
  {
   SIGNAL_MQL5_PROP_BALANCE = SIGNAL_MQL5_PROP_INTEGER_TOTAL, // Account balance
   SIGNAL_MQL5_PROP_EQUITY,                           // Account equity
   SIGNAL_MQL5_PROP_GAIN,                             // Account growth in %
   SIGNAL_MQL5_PROP_MAX_DRAWDOWN,                     // Maximum drawdown
   SIGNAL_MQL5_PROP_PRICE,                            // Signal subscription price
   SIGNAL_MQL5_PROP_ROI,                              // Signal's ROI (Return on Investment) in %
  };
#define SIGNAL_MQL5_PROP_DOUBLE_TOTAL  (6)            // Total number of real properties
#define SIGNAL_MQL5_PROP_DOUBLE_SKIP   (0)            // Number of real properties not used in sorting
//+------------------------------------------------------------------+
//| MQL5 signal string properties                                    |
//+------------------------------------------------------------------+
enum ENUM_SIGNAL_MQL5_PROP_STRING
  {
   SIGNAL_MQL5_PROP_AUTHOR_LOGIN = (SIGNAL_MQL5_PROP_INTEGER_TOTAL+SIGNAL_MQL5_PROP_DOUBLE_TOTAL), // Signal author's login
   SIGNAL_MQL5_PROP_BROKER,                           // Broker (company) name
   SIGNAL_MQL5_PROP_BROKER_SERVER,                    // Broker server
   SIGNAL_MQL5_PROP_NAME,                             // Signal name
   SIGNAL_MQL5_PROP_CURRENCY,                         // Signal account currency
  };
#define SIGNAL_MQL5_PROP_STRING_TOTAL  (5)            // Total number of string properties
//+------------------------------------------------------------------+

Wir werden jetzt keine Liste der möglichen mql5-Signal-Ereignisse erstellen, sondern uns auf die Konstante beschränken, die den Code des nächsten Ereignisses nach den Ereigniscodes von mql5-Signalen angibt, aber das werden wir höchstwahrscheinlich im weiteren Verlauf noch ändern.

Um nach Eigenschaften von mql5-Signalen suchen und sortieren zu können, definieren wir die Enumeration aller möglichen Sortierkriterien:

//+------------------------------------------------------------------+
//| Possible sorting criteria of MQL5 signals                        |
//+------------------------------------------------------------------+
#define FIRST_SIGNAL_MQL5_DBL_PROP  (SIGNAL_MQL5_PROP_INTEGER_TOTAL-SIGNAL_MQL5_PROP_INTEGER_SKIP)
#define FIRST_SIGNAL_MQL5_STR_PROP  (SIGNAL_MQL5_PROP_INTEGER_TOTAL-SIGNAL_MQL5_PROP_INTEGER_SKIP+SIGNAL_MQL5_PROP_DOUBLE_TOTAL-SIGNAL_MQL5_PROP_DOUBLE_SKIP)
enum ENUM_SORT_SIGNAL_MQL5_MODE
  {
//--- Sort by integer properties
   SORT_BY_SIGNAL_MQL5_TRADE_MODE = 0,                // Sort by signal type
   SORT_BY_SIGNAL_MQL5_DATE_PUBLISHED,                // Sort by signal publication date 
   SORT_BY_SIGNAL_MQL5_DATE_STARTED,                  // Sort by signal monitoring start date
   SORT_BY_SIGNAL_MQL5_DATE_UPDATED,                  // Sort by date of the latest update of the signal trading statistics
   SORT_BY_SIGNAL_MQL5_ID,                            // Sort by signal ID
   SORT_BY_SIGNAL_MQL5_LEVERAGE,                      // Sort by trading account leverage
   SORT_BY_SIGNAL_MQL5_PIPS,                          // Sort by trading result in pips
   SORT_BY_SIGNAL_MQL5_RATING,                        // Sort by a position in the signal rating
   SORT_BY_SIGNAL_MQL5_SUBSCRIBERS,                   // Sort by the number of subscribers
   SORT_BY_SIGNAL_MQL5_TRADES,                        // Sort by the number of trades
   SORT_BY_SIGNAL_MQL5_SUBSCRIPTION_STATUS,           // Sort by the status of account subscription to a signal
//--- Sort by real properties
   SORT_BY_SIGNAL_MQL5_BALANCE = FIRST_SIGNAL_MQL5_DBL_PROP, // Sort by account balance
   SORT_BY_SIGNAL_MQL5_EQUITY,                        // Sort by account equity
   SORT_BY_SIGNAL_MQL5_GAIN,                          // Sort by account growth in %
   SORT_BY_SIGNAL_MQL5_MAX_DRAWDOWN,                  // Sort by maximum drawdown
   SORT_BY_SIGNAL_MQL5_PRICE,                         // Sort by signal subscription price
   SORT_BY_SIGNAL_MQL5_ROI,                           // Sort by ROI
//--- Sort by string properties
   SORT_BY_SIGNAL_MQL5_AUTHOR_LOGIN = FIRST_SIGNAL_MQL5_STR_PROP, // Sort by signal author login
   SORT_BY_SIGNAL_MQL5_BROKER,                        // Sort by Broker (company) name
   SORT_BY_SIGNAL_MQL5_BROKER_SERVER,                 // Sort by broker server
   SORT_BY_SIGNAL_MQL5_NAME,                          // Sort by signal name
   SORT_BY_SIGNAL_MQL5_CURRENCY,                      // Sort by signal account currency
  };
//+------------------------------------------------------------------+

Dies ist ein Satz der notwendigsten Parameter für die Erstellung einer neuen Klasse des neuen Bibliotheksobjekts.

Wir kreieren in \MQL5\Include\DoEasy\Objects\ einen neuen Ordner MQLSignalBase\ mit einer neuen Datei MQLSignal.mqh der Klasse CMQLSignal.

Als Basisklasse soll die Klasse des Basisobjekts aller CBaseObj-Bibliotheksobjekte verwendet werden:

//+------------------------------------------------------------------+
//|                                                    MQLSignal.mqh |
//|                        Copyright 2021, MetaQuotes Software Corp. |
//|                             https://MQL5.com/en/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2021, MetaQuotes Software Corp."
#property link      "https://MQL5.com/en/users/artmedia70"
#property version   "1.00"
#property strict    // Necessary for mql4
//+------------------------------------------------------------------+
//| Include files                                                    |
//+------------------------------------------------------------------+
#include "..\..\Objects\BaseObj.mqh"
//+------------------------------------------------------------------+
//| Abstract MQL5 signal class                                       |
//+------------------------------------------------------------------+
class CMQLSignal : public CBaseObj
  {
  }

Betrachten wir nun die Zusammensetzung der Klasse und die Implementierung ihrer Methoden:

//+------------------------------------------------------------------+
//|                                                    MQLSignal.mqh |
//|                        Copyright 2021, MetaQuotes Software Corp. |
//|                             https://MQL5.com/en/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2021, MetaQuotes Software Corp."
#property link      "https://MQL5.com/en/users/artmedia70"
#property version   "1.00"
#property strict    // Necessary for mql4
//+------------------------------------------------------------------+
//| Include files                                                    |
//+------------------------------------------------------------------+
#include "..\..\Objects\BaseObj.mqh"
//+------------------------------------------------------------------+
//| Abstract MQL5 signal class                                       |
//+------------------------------------------------------------------+
class CMQLSignal : public CBaseObj
  {
private:
   long              m_long_prop[SIGNAL_MQL5_PROP_INTEGER_TOTAL];       // Integer properties
   double            m_double_prop[SIGNAL_MQL5_PROP_DOUBLE_TOTAL];      // Real properties
   string            m_string_prop[SIGNAL_MQL5_PROP_STRING_TOTAL];      // String properties

//--- Return the index of the array the (1) double and (2) string properties are actually located at
   int               IndexProp(ENUM_SIGNAL_MQL5_PROP_DOUBLE property)   const { return(int)property-SIGNAL_MQL5_PROP_INTEGER_TOTAL;                               }
   int               IndexProp(ENUM_SIGNAL_MQL5_PROP_STRING property)   const { return(int)property-SIGNAL_MQL5_PROP_INTEGER_TOTAL-SIGNAL_MQL5_PROP_DOUBLE_TOTAL; }

public:
//--- Set object's (1) integer, (2) real and (3) string properties
   void              SetProperty(ENUM_SIGNAL_MQL5_PROP_INTEGER property,long value)    { this.m_long_prop[property]=value;                      }
   void              SetProperty(ENUM_SIGNAL_MQL5_PROP_DOUBLE property,double value)   { this.m_double_prop[this.IndexProp(property)]=value;    }
   void              SetProperty(ENUM_SIGNAL_MQL5_PROP_STRING property,string value)   { this.m_string_prop[this.IndexProp(property)]=value;    }
//--- Return object’s (1) integer, (2) real and (3) string property from the properties array
   long              GetProperty(ENUM_SIGNAL_MQL5_PROP_INTEGER property)         const { return this.m_long_prop[property];                     }
   double            GetProperty(ENUM_SIGNAL_MQL5_PROP_DOUBLE property)          const { return this.m_double_prop[this.IndexProp(property)];   }
   string            GetProperty(ENUM_SIGNAL_MQL5_PROP_STRING property)          const { return this.m_string_prop[this.IndexProp(property)];   }
//--- Return itself
   CMQLSignal       *GetObject(void)                                                   { return &this;}

//--- Return the flag of the object supporting this property
   virtual bool      SupportProperty(ENUM_SIGNAL_MQL5_PROP_INTEGER property)           { return true; }
   virtual bool      SupportProperty(ENUM_SIGNAL_MQL5_PROP_DOUBLE property)            { return true; }
   virtual bool      SupportProperty(ENUM_SIGNAL_MQL5_PROP_STRING property)            { return true; }

//--- Get description of (1) integer, (2) real and (3) string properties
   string            GetPropertyDescription(ENUM_SIGNAL_MQL5_PROP_INTEGER property);
   string            GetPropertyDescription(ENUM_SIGNAL_MQL5_PROP_DOUBLE property);
   string            GetPropertyDescription(ENUM_SIGNAL_MQL5_PROP_STRING property);

//--- Display the description of object properties in the journal (full_prop=true - all properties, false - supported ones only)
   void              Print(const bool full_prop=false);
//--- Display a short description of the object in the journal
   virtual void      PrintShort(void);
//--- Return the object short name
   virtual string    Header(const bool shrt=false);
   
//--- Compare CMQLSignal objects by a specified property (to sort the list by an MQL5 signal object)
   virtual int       Compare(const CObject *node,const int mode=0) const;
//--- Compare CMQLSignal objects by all properties (to search for equal MQL5 signal objects)
   bool              IsEqual(CMQLSignal* compared_obj) const;
   
//--- Constructors
                     CMQLSignal(){;}
                     CMQLSignal(const long signal_id);
                     
public:
//+------------------------------------------------------------------+ 
//| Methods of simplified access to MQL5 signal object               |
//+------------------------------------------------------------------+
//--- Returns the dates of (1) publication, (2) monitoring start, (3) trading statistics last update,
//--- (4) ID, (5) trading account leverage, (6) trading result in pips, (7) position in the signal rating,
//--- (8) number of subscribers, (9) number of trades, (10) account type, (11) flag of the current account subscription to a signal
   datetime          DatePublished(void)     const { return (datetime)this.GetProperty(SIGNAL_MQL5_PROP_DATE_PUBLISHED);         }
   datetime          DateStarted(void)       const { return (datetime)this.GetProperty(SIGNAL_MQL5_PROP_DATE_STARTED);           }
   datetime          DateUpdated(void)       const { return (datetime)this.GetProperty(SIGNAL_MQL5_PROP_DATE_UPDATED);           }
   long              ID(void)                const { return this.GetProperty(SIGNAL_MQL5_PROP_ID);                               }
   long              Leverage(void)          const { return this.GetProperty(SIGNAL_MQL5_PROP_LEVERAGE);                         }
   long              Pips(void)              const { return this.GetProperty(SIGNAL_MQL5_PROP_PIPS);                             }
   long              Rating(void)            const { return this.GetProperty(SIGNAL_MQL5_PROP_RATING);                           }
   long              Subscribers(void)       const { return this.GetProperty(SIGNAL_MQL5_PROP_SUBSCRIBERS);                      }
   long              Trades(void)            const { return this.GetProperty(SIGNAL_MQL5_PROP_TRADES);                           }
   long              TradeMode(void)         const { return (long)this.GetProperty(SIGNAL_MQL5_PROP_TRADE_MODE);                 }
   bool              SubscriptionStatus(void)const { return (bool)this.GetProperty(SIGNAL_MQL5_PROP_SUBSCRIPTION_STATUS);        }
//--- Return (1) the account balance, (2) account funds, (3) account growth in %,
//--- (4) maximum drawdown, (5) subscription price and (6) signal ROI value (Return on Investment) in %
   double            Balance(void)           const { return this.GetProperty(SIGNAL_MQL5_PROP_BALANCE);                          }
   double            Equity(void)            const { return this.GetProperty(SIGNAL_MQL5_PROP_EQUITY);                           }
   double            Gain(void)              const { return this.GetProperty(SIGNAL_MQL5_PROP_GAIN);                             }
   double            MaxDrawdown(void)       const { return this.GetProperty(SIGNAL_MQL5_PROP_MAX_DRAWDOWN);                     }
   double            Price(void)             const { return this.GetProperty(SIGNAL_MQL5_PROP_PRICE);                            }
   double            ROI(void)               const { return this.GetProperty(SIGNAL_MQL5_PROP_ROI);                              }
//--- Return (1) signal author's login, (2) broker (company) name,
//--- (3) broker server, (4) signal name and (5) signal account currency
   string            AuthorLogin(void)       const { return this.GetProperty(SIGNAL_MQL5_PROP_AUTHOR_LOGIN);                     }
   string            Broker(void)            const { return this.GetProperty(SIGNAL_MQL5_PROP_BROKER);                           }
   string            BrokerServer(void)      const { return this.GetProperty(SIGNAL_MQL5_PROP_BROKER_SERVER);                    }
   string            Name(void)              const { return this.GetProperty(SIGNAL_MQL5_PROP_NAME);                             }
   string            Currency(void)          const { return this.GetProperty(SIGNAL_MQL5_PROP_CURRENCY);                         }

//--- Set the dates of (1) publication, (2) monitoring start, (3) trading statistics last update,
//--- (4) ID, (5) trading account leverage, (6) trading result in pips, (7) position in the signal rating,
//--- (8) number of subscribers, (9) number of trades, (10) account type, (11) flag of the current account subscription to a signal
   void              SetDatePublished(const datetime date)  { this.SetProperty(SIGNAL_MQL5_PROP_DATE_PUBLISHED,date);            }
   void              SetDateStarted(const datetime date)    { this.SetProperty(SIGNAL_MQL5_PROP_DATE_STARTED,date);              }
   void              SetDateUpdated(const datetime date)    { this.SetProperty(SIGNAL_MQL5_PROP_DATE_UPDATED,date);              }
   void              SetID(const long id)                   { this.SetProperty(SIGNAL_MQL5_PROP_ID,id);                          }
   void              SetLeverage(const long value)          { this.SetProperty(SIGNAL_MQL5_PROP_LEVERAGE,value);                 }
   void              SetPips(const long value)              { this.SetProperty(SIGNAL_MQL5_PROP_PIPS,value);                     }
   void              SetRating(const long value)            { this.SetProperty(SIGNAL_MQL5_PROP_RATING,value);                   }
   void              SetSubscribers(const long value)       { this.SetProperty(SIGNAL_MQL5_PROP_SUBSCRIBERS,value);              }
   void              SetTrades(const long value)            { this.SetProperty(SIGNAL_MQL5_PROP_TRADES,value);                   }
   void              SetTradeMode(const long mode)          { this.SetProperty(SIGNAL_MQL5_PROP_TRADE_MODE,mode);                }
   void              SetSubscriptionStatus(const bool flag) { this.SetProperty(SIGNAL_MQL5_PROP_SUBSCRIPTION_STATUS,flag);       }
//--- Set (1) the account balance, (2) account funds, (3) account growth in %,
//--- (4) maximum drawdown, (5) subscription price and (6) signal ROI value (Return on Investment) in %
   void              SetBalance(const double value)         { this.SetProperty(SIGNAL_MQL5_PROP_BALANCE,value);                  }
   void              SetEquity(const double value)          { this.SetProperty(SIGNAL_MQL5_PROP_EQUITY,value);                   }
   void              SetGain(const double value)            { this.SetProperty(SIGNAL_MQL5_PROP_GAIN,value);                     }
   void              SetMaxDrawdown(const double value)     { this.SetProperty(SIGNAL_MQL5_PROP_MAX_DRAWDOWN,value);             }
   void              SetPrice(const double value)           { this.SetProperty(SIGNAL_MQL5_PROP_PRICE,value);                    }
   void              SetROI(const double value)             { this.SetProperty(SIGNAL_MQL5_PROP_ROI,value);                      }
//--- Set (1) signal author's login, (2) broker (company) name,
//--- (3) broker server, (4) signal name and (5) signal account currency
   void              SetAuthorLogin(const string value)     { this.SetProperty(SIGNAL_MQL5_PROP_AUTHOR_LOGIN,value);             }
   void              SetBroker(const string value)          { this.SetProperty(SIGNAL_MQL5_PROP_BROKER,value);                   }
   void              SetBrokerServer(const string value)    { this.SetProperty(SIGNAL_MQL5_PROP_BROKER_SERVER,value);            }
   void              SetName(const string value)            { this.SetProperty(SIGNAL_MQL5_PROP_NAME,value);                     }
   void              SetCurrency(const string value)        { this.SetProperty(SIGNAL_MQL5_PROP_CURRENCY,value);                 }

//--- Return the account type name
   string            TradeModeDescription(void);
   
  };
//+------------------------------------------------------------------+

Die Arrays zum Speichern von integer-, real- und string-Objekteigenschaften und Methoden, die den Real-Index der Objekt-Real- und String-Eigenschaften zurückgeben, werden im privaten Abschnitt deklariert.

Im öffentlichen Abschnitt der Klasse sehen wir die Standardmethoden zum Setzen und Empfangen von Objekteigenschaften, Suchen und Sortieren, Anzeigen von Objektbeschreibungen und Klassenkonstruktoren.

Im öffentlichen Abschnitt befinden sich auch die Methoden für einen vereinfachten Zugriff auf Objekteigenschaften — die Methoden haben einfach selbsterklärende Namen, so dass Bibliotheksbenutzer in der Lage sind, auf jede Eigenschaft zuzugreifen, ohne sich die Namen aller Objektenumerationen merken zu müssen.

Die Zusammensetzung der Objektklassen wurde im ersten Teil der Bibliotheksbeschreibung ausführlich betrachtet. Werfen wir einen Blick auf die Implementierung der Klassenmethoden.

Der parametrische Klassenkonstruktor erhält die Signal-ID. Alle Objekteigenschaften werden dann mit Werten gefüllt, die von den entsprechenden Funktionen bezogen werden (unter Berücksichtigung, dass dieses Signal ausgewählt ist):

//+------------------------------------------------------------------+
//| Parametric constructor                                           |
//+------------------------------------------------------------------+
CMQLSignal::CMQLSignal(const long signal_id)
  {
   this.m_long_prop[SIGNAL_MQL5_PROP_ID]                             = signal_id;
   this.m_long_prop[SIGNAL_MQL5_PROP_SUBSCRIPTION_STATUS]            = false;
   this.m_long_prop[SIGNAL_MQL5_PROP_TRADE_MODE]                     = ::SignalBaseGetInteger(SIGNAL_BASE_TRADE_MODE);
   this.m_long_prop[SIGNAL_MQL5_PROP_DATE_PUBLISHED]                 = ::SignalBaseGetInteger(SIGNAL_BASE_DATE_PUBLISHED);
   this.m_long_prop[SIGNAL_MQL5_PROP_DATE_STARTED]                   = ::SignalBaseGetInteger(SIGNAL_BASE_DATE_STARTED);
   this.m_long_prop[SIGNAL_MQL5_PROP_DATE_UPDATED]                   = ::SignalBaseGetInteger(SIGNAL_BASE_DATE_UPDATED);
   this.m_long_prop[SIGNAL_MQL5_PROP_LEVERAGE]                       = ::SignalBaseGetInteger(SIGNAL_BASE_LEVERAGE);
   this.m_long_prop[SIGNAL_MQL5_PROP_PIPS]                           = ::SignalBaseGetInteger(SIGNAL_BASE_PIPS);
   this.m_long_prop[SIGNAL_MQL5_PROP_RATING]                         = ::SignalBaseGetInteger(SIGNAL_BASE_RATING);
   this.m_long_prop[SIGNAL_MQL5_PROP_SUBSCRIBERS]                    = ::SignalBaseGetInteger(SIGNAL_BASE_SUBSCRIBERS);
   this.m_long_prop[SIGNAL_MQL5_PROP_TRADES]                         = ::SignalBaseGetInteger(SIGNAL_BASE_TRADES);
   
   this.m_double_prop[this.IndexProp(SIGNAL_MQL5_PROP_BALANCE)]      = ::SignalBaseGetDouble(SIGNAL_BASE_BALANCE);
   this.m_double_prop[this.IndexProp(SIGNAL_MQL5_PROP_EQUITY)]       = ::SignalBaseGetDouble(SIGNAL_BASE_EQUITY);
   this.m_double_prop[this.IndexProp(SIGNAL_MQL5_PROP_GAIN)]         = ::SignalBaseGetDouble(SIGNAL_BASE_GAIN);
   this.m_double_prop[this.IndexProp(SIGNAL_MQL5_PROP_MAX_DRAWDOWN)] = ::SignalBaseGetDouble(SIGNAL_BASE_MAX_DRAWDOWN);
   this.m_double_prop[this.IndexProp(SIGNAL_MQL5_PROP_PRICE)]        = ::SignalBaseGetDouble(SIGNAL_BASE_PRICE);
   this.m_double_prop[this.IndexProp(SIGNAL_MQL5_PROP_ROI)]          = ::SignalBaseGetDouble(SIGNAL_BASE_ROI);
   
   this.m_string_prop[this.IndexProp(SIGNAL_MQL5_PROP_AUTHOR_LOGIN)] = ::SignalBaseGetString(SIGNAL_BASE_AUTHOR_LOGIN);
   this.m_string_prop[this.IndexProp(SIGNAL_MQL5_PROP_BROKER)]       = ::SignalBaseGetString(SIGNAL_BASE_BROKER);
   this.m_string_prop[this.IndexProp(SIGNAL_MQL5_PROP_BROKER_SERVER)]= ::SignalBaseGetString(SIGNAL_BASE_BROKER_SERVER);
   this.m_string_prop[this.IndexProp(SIGNAL_MQL5_PROP_NAME)]         = ::SignalBaseGetString(SIGNAL_BASE_NAME);
   this.m_string_prop[this.IndexProp(SIGNAL_MQL5_PROP_CURRENCY)]     = ::SignalBaseGetString(SIGNAL_BASE_CURRENCY);
  }
//+------------------------------------------------------------------+

Das Signalabonnement-Flag ist auf false gesetzt — das Abonnement eines ausgewählten Signals wird von einer anderen Klasse durchgeführt.

Die Methode zum Vergleichen von MQL5-Signalobjekten anhand einer angegebenen Eigenschaft:

//+----------------------------------------------------------------------+
//| Compare CMQLSignal objects with each other by the specified property |
//+----------------------------------------------------------------------+
int CMQLSignal::Compare(const CObject *node,const int mode=0) const
  {
   const CMQLSignal *obj_compared=node;
//--- compare integer properties of two objects
   if(mode<SIGNAL_MQL5_PROP_INTEGER_TOTAL)
     {
      long value_compared=obj_compared.GetProperty((ENUM_SIGNAL_MQL5_PROP_INTEGER)mode);
      long value_current=this.GetProperty((ENUM_SIGNAL_MQL5_PROP_INTEGER)mode);
      return(value_current>value_compared ? 1 : value_current<value_compared ? -1 : 0);
     }
//--- compare real properties of two objects
   else if(mode<SIGNAL_MQL5_PROP_DOUBLE_TOTAL+SIGNAL_MQL5_PROP_INTEGER_TOTAL)
     {
      double value_compared=obj_compared.GetProperty((ENUM_SIGNAL_MQL5_PROP_DOUBLE)mode);
      double value_current=this.GetProperty((ENUM_SIGNAL_MQL5_PROP_DOUBLE)mode);
      return(value_current>value_compared ? 1 : value_current<value_compared ? -1 : 0);
     }
//--- compare string properties of two objects
   else if(mode<SIGNAL_MQL5_PROP_DOUBLE_TOTAL+SIGNAL_MQL5_PROP_INTEGER_TOTAL+SIGNAL_MQL5_PROP_STRING_TOTAL)
     {
      string value_compared=obj_compared.GetProperty((ENUM_SIGNAL_MQL5_PROP_STRING)mode);
      string value_current=this.GetProperty((ENUM_SIGNAL_MQL5_PROP_STRING)mode);
      return(value_current>value_compared ? 1 : value_current<value_compared ? -1 : 0);
     }
   return 0;
  }
//+------------------------------------------------------------------+

Kurz gesagt, die Methode empfängt ein zu vergleichendes Objekt sowie eine Eigenschaft, mit der zwei Objekte verglichen werden sollen. Je nach übergebener Eigenschaft werden integer-, real- oder string-Eigenschaften von zwei Objekten verglichen. Zurückgegeben wird das Vergleichsergebnis -1, 1 oder 0 (kleiner als, größer als, gleich).

Die Methode zum Vergleich von MQL5-Signalobjekten anhand aller Eigenschaften:

//+------------------------------------------------------------------+
//| Compare CMQLSignal objects by all properties                     |
//+------------------------------------------------------------------+
bool CMQLSignal::IsEqual(CMQLSignal *compared_obj) const
  {
   int beg=0, end=SIGNAL_MQL5_PROP_INTEGER_TOTAL;
   for(int i=beg; i<end; i++)
     {
      ENUM_SIGNAL_MQL5_PROP_INTEGER prop=(ENUM_SIGNAL_MQL5_PROP_INTEGER)i;
      if(this.GetProperty(prop)!=compared_obj.GetProperty(prop)) return false; 
     }
   beg=end; end+=SIGNAL_MQL5_PROP_DOUBLE_TOTAL;
   for(int i=beg; i<end; i++)
     {
      ENUM_SIGNAL_MQL5_PROP_DOUBLE prop=(ENUM_SIGNAL_MQL5_PROP_DOUBLE)i;
      if(this.GetProperty(prop)!=compared_obj.GetProperty(prop)) return false; 
     }
   beg=end; end+=SIGNAL_MQL5_PROP_STRING_TOTAL;
   for(int i=beg; i<end; i++)
     {
      ENUM_SIGNAL_MQL5_PROP_STRING prop=(ENUM_SIGNAL_MQL5_PROP_STRING)i;
      if(this.GetProperty(prop)!=compared_obj.GetProperty(prop)) return false; 
     }
   return true;
  }
//+------------------------------------------------------------------+

Vergleichen wir in drei Schleifen durch drei Objekteigenschaften jede nachfolgende Eigenschaft von zwei Objekten und geben Sie false zurück, wenn die Eigenschaften von zwei Objekten nicht gleich sind. Nach dem Vergleich aller Eigenschaften von zwei Objekten in drei Arrays wird true zurückgegeben, wenn keine nicht übereinstimmende Eigenschaften gefunden werden.

Die Methoden geben die Beschreibung der angegebenen integer-, real- und string-Objekteigenschaft zurück:

//+------------------------------------------------------------------+
//| Return description of object's integer property                  |
//+------------------------------------------------------------------+
string CMQLSignal::GetPropertyDescription(ENUM_SIGNAL_MQL5_PROP_INTEGER property)
  {
   return
     (
      property==SIGNAL_MQL5_PROP_TRADE_MODE     ?  CMessage::Text(MSG_SIGNAL_MQL5_TRADE_MODE)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+this.TradeModeDescription()
         )  :
      property==SIGNAL_MQL5_PROP_DATE_PUBLISHED ?  CMessage::Text(MSG_SIGNAL_MQL5_DATE_PUBLISHED)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+::TimeToString(this.DatePublished())
         )  :
      property==SIGNAL_MQL5_PROP_DATE_STARTED   ?  CMessage::Text(MSG_SIGNAL_MQL5_DATE_STARTED)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+::TimeToString(this.DateStarted())
         )  :
      property==SIGNAL_MQL5_PROP_DATE_UPDATED   ?  CMessage::Text(MSG_SIGNAL_MQL5_DATE_UPDATED)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+::TimeToString(this.DateUpdated())
         )  :
      property==SIGNAL_MQL5_PROP_ID             ?  CMessage::Text(MSG_SIGNAL_MQL5_ID)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(string)this.GetProperty(property)
         )  :
      property==SIGNAL_MQL5_PROP_LEVERAGE       ?  CMessage::Text(MSG_SIGNAL_MQL5_LEVERAGE)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(string)this.GetProperty(property)
         )  :
      property==SIGNAL_MQL5_PROP_PIPS           ?  CMessage::Text(MSG_SIGNAL_MQL5_PIPS)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(string)this.GetProperty(property)
         )  :
      property==SIGNAL_MQL5_PROP_RATING         ?  CMessage::Text(MSG_SIGNAL_MQL5_RATING)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(string)this.GetProperty(property)
         )  :
      property==SIGNAL_MQL5_PROP_SUBSCRIBERS    ?  CMessage::Text(MSG_SIGNAL_MQL5_SUBSCRIBERS)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(string)this.GetProperty(property)
         )  :
      property==SIGNAL_MQL5_PROP_TRADES        ?  CMessage::Text(MSG_SIGNAL_MQL5_TRADES)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(string)this.GetProperty(property)
         )  :
      property==SIGNAL_MQL5_PROP_SUBSCRIPTION_STATUS  ?  CMessage::Text(MSG_SIGNAL_MQL5_SUBSCRIPTION_STATUS)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(this.GetProperty(property) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO))
         )  :
      ""
     );
  }
//+------------------------------------------------------------------+
//| Return description of object's real property                     |
//+------------------------------------------------------------------+
string CMQLSignal::GetPropertyDescription(ENUM_SIGNAL_MQL5_PROP_DOUBLE property)
  {
   return
     (
      property==SIGNAL_MQL5_PROP_BALANCE         ?  CMessage::Text(MSG_ACC_PROP_BALANCE)+
         (!this.SupportProperty(property)    ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+::DoubleToString(this.GetProperty(property),2)
         )  :
      property==SIGNAL_MQL5_PROP_EQUITY   ?  CMessage::Text(MSG_SIGNAL_MQL5_EQUITY)+
         (!this.SupportProperty(property)    ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+::DoubleToString(this.GetProperty(property),2)
         )  :
         
      property==SIGNAL_MQL5_PROP_GAIN   ?  CMessage::Text(MSG_SIGNAL_MQL5_GAIN)+
         (!this.SupportProperty(property)    ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+::DoubleToString(this.GetProperty(property),2)
         )  :
      property==SIGNAL_MQL5_PROP_MAX_DRAWDOWN   ?  CMessage::Text(MSG_SIGNAL_MQL5_MAX_DRAWDOWN)+
         (!this.SupportProperty(property)    ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+::DoubleToString(this.GetProperty(property),2)
         )  :
      property==SIGNAL_MQL5_PROP_PRICE   ?  CMessage::Text(MSG_SIGNAL_MQL5_PRICE)+
         (!this.SupportProperty(property)    ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+::DoubleToString(this.GetProperty(property),2)
         )  :
      property==SIGNAL_MQL5_PROP_ROI   ?  CMessage::Text(MSG_SIGNAL_MQL5_ROI)+
         (!this.SupportProperty(property)    ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+::DoubleToString(this.GetProperty(property),2)
         )  :
      ""
     );
  }
//+------------------------------------------------------------------+
//| Return description of object's string property                   |
//+------------------------------------------------------------------+
string CMQLSignal::GetPropertyDescription(ENUM_SIGNAL_MQL5_PROP_STRING property)
  {
   return
     (
      property==SIGNAL_MQL5_PROP_AUTHOR_LOGIN   ?  CMessage::Text(MSG_SIGNAL_MQL5_AUTHOR_LOGIN)+": \""+this.GetProperty(property)+"\""    :
      property==SIGNAL_MQL5_PROP_BROKER         ?  CMessage::Text(MSG_SIGNAL_MQL5_BROKER)+": \""+this.GetProperty(property)+"\""          :
      property==SIGNAL_MQL5_PROP_BROKER_SERVER  ?  CMessage::Text(MSG_SIGNAL_MQL5_BROKER_SERVER)+": \""+this.GetProperty(property)+"\""   :
      property==SIGNAL_MQL5_PROP_NAME           ?  CMessage::Text(MSG_SIGNAL_MQL5_NAME)+": \""+this.GetProperty(property)+"\""            :
      property==SIGNAL_MQL5_PROP_CURRENCY       ?  CMessage::Text(MSG_SIGNAL_MQL5_CURRENCY)+": \""+this.GetProperty(property)+"\""        :
      ""
     );
  }
//+------------------------------------------------------------------+

Abhängig von der an die Methode übergebenen Eigenschaft wird die Zeichenkette mit ihrer Beschreibung und ihrem Wert erstellt und zurückgegeben.

Die Methode zeigt alle MQL5-Signalobjekteigenschaften im Journal an:

//+------------------------------------------------------------------+
//| Display object properties in the journal                         |
//+------------------------------------------------------------------+
void CMQLSignal::Print(const bool full_prop=false)
  {
   ::Print("============= ",CMessage::Text(MSG_LIB_PARAMS_LIST_BEG)," (",this.Header(),") =============");
   int beg=0, end=SIGNAL_MQL5_PROP_INTEGER_TOTAL;
   for(int i=beg; i<end; i++)
     {
      ENUM_SIGNAL_MQL5_PROP_INTEGER prop=(ENUM_SIGNAL_MQL5_PROP_INTEGER)i;
      if(!full_prop && !this.SupportProperty(prop)) continue;
      ::Print(this.GetPropertyDescription(prop));
     }
   ::Print("------");
   beg=end; end+=SIGNAL_MQL5_PROP_DOUBLE_TOTAL;
   for(int i=beg; i<end; i++)
     {
      ENUM_SIGNAL_MQL5_PROP_DOUBLE prop=(ENUM_SIGNAL_MQL5_PROP_DOUBLE)i;
      if(!full_prop && !this.SupportProperty(prop)) continue;
      ::Print(this.GetPropertyDescription(prop));
     }
   ::Print("------");
   beg=end; end+=SIGNAL_MQL5_PROP_STRING_TOTAL;
   for(int i=beg; i<end; i++)
     {
      ENUM_SIGNAL_MQL5_PROP_STRING prop=(ENUM_SIGNAL_MQL5_PROP_STRING)i;
      if(!full_prop && !this.SupportProperty(prop)) continue;
      ::Print(this.GetPropertyDescription(prop));
     }
   ::Print("============= ",CMessage::Text(MSG_LIB_PARAMS_LIST_END)," (",this.Header(),") =============\n");
  }
//+------------------------------------------------------------------+

Eine Beschreibung jeder nachfolgenden Objekteigenschaft wird in drei Schleifen nach integer-, real- und string-Eigenschaften mit der entsprechenden Methode GetPropertyDescription() angezeigt.

Die Methode gibt den Kurznamen des MQL5-Signalobjekts zurück:

//+------------------------------------------------------------------+
//| Return the object short name                                     |
//+------------------------------------------------------------------+
string CMQLSignal::Header(const bool shrt=false)
  {
   return(shrt ? CMessage::Text(MSG_SIGNAL_MQL5_TEXT_SIGNAL) : CMessage::Text(MSG_SIGNAL_MQL5_TEXT_SIGNAL_MQL5));
  }
//+------------------------------------------------------------------+

Die Methode erhält das Flag, das entweder die kurze oder die lange Beschreibung angibt. Die lange Beschreibung wird standardmäßig angezeigt:

The signal of the MQL5.com Signal service

Wenn das Flag true ist, wird eine kurze Beschreibung angezeigt:

Signal

Die Methode zeigt die kurze Objektbeschreibung im Journal an:

//+------------------------------------------------------------------+
//| Display a short description of the object in the journal         |
//+------------------------------------------------------------------+
void CMQLSignal::PrintShort(void)
  {
   ::Print
     (
      this.Header(true),
      " \"",this.Name(),"\". ",
      CMessage::Text(MSG_SIGNAL_MQL5_AUTHOR_LOGIN),": ",this.AuthorLogin(),
      ", ID ",this.ID(),
      ", ",CMessage::Text(MSG_SIGNAL_MQL5_TEXT_GAIN),": ",::DoubleToString(this.Gain(),2),
      ", ",CMessage::Text(MSG_SIGNAL_MQL5_TEXT_DRAWDOWN),": ",::DoubleToString(this.MaxDrawdown(),2),
      ", ",CMessage::Text(MSG_LIB_TEXT_REQUEST_PRICE),": ",::DoubleToString(this.Price(),2)
     );
  }
//+------------------------------------------------------------------+

Der Kurzname des Signals wird zuerst erstellt. Ihm werden einige im Journal des Terminal angezeigte Parameter hinzugefügt.
Er könnte zum Beispiel so aussehen:

Signal "DemoForArticle". Author login: login, ID XXXXXX, Growth: XX.XX, Drawdown: XX.XX, Price: XX.XX

Die Methode gibt den Namen des Kontotyps zurück:

//+------------------------------------------------------------------+
//| Return the account type name                                     |
//+------------------------------------------------------------------+
string CMQLSignal::TradeModeDescription(void)
  {
   return
     (
      this.TradeMode()==0 ? CMessage::Text(MSG_ACC_TRADE_MODE_REAL)     :
      this.TradeMode()==1 ? CMessage::Text(MSG_ACC_TRADE_MODE_DEMO)     :
      this.TradeMode()==2 ? CMessage::Text(MSG_ACC_TRADE_MODE_CONTEST)  :
      CMessage::Text(MSG_ACC_TRADE_MODE_UNKNOWN)
     );
  }
//+------------------------------------------------------------------+

Abhängig vom Konto einer Signalquelle wird eine Zeichenkette mit einem Kontotyp (Real, Demo oder Wettbewerb) zurückgegeben.

Damit ist die Erstellung des MQL5-Signalobjekts abgeschlossen.


Test

Um den Test durchzuführen, verwenden wir den EA aus dem vorherigen Artikel und speichern ihn in \MQL5\Experts\TestDoEasy\Part65\ als TestDoEasyPart65.mq5.

Die Klasse der DOM Schnappschuss Reihen Kollektion ist jetzt vom Hauptbibliotheksobjekt verfügbar, während das MQL5 Signalobjekt noch nicht mit CEngine verbunden ist. Ersetzen wir daher die Einschlusszeichenfolge der Objektklasse DOM-Schnappschuss-Reihe

#include <DoEasy\Objects\Book\MBookSeries.mqh>

mit der für die Einbeziehung des MQL5-Signalobjekts:

//+------------------------------------------------------------------+
//|                                             TestDoEasyPart65.mq5 |
//|                        Copyright 2021, MetaQuotes Software Corp. |
//|                             https://MQL5.com/en/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2021, MetaQuotes Software Corp."
#property link      "https://MQL5.com/en/users/artmedia70"
#property version   "1.00"
//--- includes
#include <DoEasy\Engine.mqh>
#include <DoEasy\Objects\MQLSignalBase\MQLSignal.mqh>
//--- enums

Entfernen wir die Deklaration des Objekts der DOM-Schnappschuss-Reihe aus der Liste der globalen EA-Variablen:

//--- global variables
CEngine        engine;
SDataButt      butt_data[TOTAL_BUTT];
string         prefix;
double         lot;
double         withdrawal=(InpWithdrawal<0.1 ? 0.1 : InpWithdrawal);
ushort         magic_number;
uint           stoploss;
uint           takeprofit;
uint           distance_pending;
uint           distance_stoplimit;
uint           distance_pending_request;
uint           bars_delay_pending_request;
uint           slippage;
bool           trailing_on;
bool           pressed_pending_buy;
bool           pressed_pending_buy_limit;
bool           pressed_pending_buy_stop;
bool           pressed_pending_buy_stoplimit;
bool           pressed_pending_close_buy;
bool           pressed_pending_close_buy2;
bool           pressed_pending_close_buy_by_sell;
bool           pressed_pending_sell;
bool           pressed_pending_sell_limit;
bool           pressed_pending_sell_stop;
bool           pressed_pending_sell_stoplimit;
bool           pressed_pending_close_sell;
bool           pressed_pending_close_sell2;
bool           pressed_pending_close_sell_by_buy;
bool           pressed_pending_delete_all;
bool           pressed_pending_close_all;
bool           pressed_pending_sl;
bool           pressed_pending_tp;
double         trailing_stop;
double         trailing_step;
uint           trailing_start;
uint           stoploss_to_modify;
uint           takeprofit_to_modify;
int            used_symbols_mode;
string         array_used_symbols[];
string         array_used_periods[];
bool           testing;
uchar          group1;
uchar          group2;
double         g_point;
int            g_digits;
//---
CMBookSeries   book_series;
//+------------------------------------------------------------------+

In der MQL5-Hilfe finden Sie ein Beispiel für den Empfang der Liste der profitablen kostenlosen Signale mit einer Anzahl von Abonnenten, die nicht Null ist:

void OnStart()
  {
//--- request the total number of signals in the signal database
   int total=SignalBaseTotal();
//--- loop through all signals
   for(int i=0;i<total;i++)
     {
      //--- select a signal for further operation
      if(SignalBaseSelect(i))
        {
         //--- receive signal properties
         long   id    =SignalBaseGetInteger(SIGNAL_BASE_ID);          // signal ID
         long   pips  =SignalBaseGetInteger(SIGNAL_BASE_PIPS);        // trading result in pips
         long   subscr=SignalBaseGetInteger(SIGNAL_BASE_SUBSCRIBERS); // number of subscribers
         string name  =SignalBaseGetString(SIGNAL_BASE_NAME);         // signal name
         double price =SignalBaseGetDouble(SIGNAL_BASE_PRICE);        // signal subscription price
         string curr  =SignalBaseGetString(SIGNAL_BASE_CURRENCY);     // signal currency
         //--- display all profitable free signals with a non-zero number of subscribers
         if(price==0.0 && pips>0 && subscr>0)
            PrintFormat("id=%d, name=\"%s\", currency=%s, pips=%d, subscribers=%d",id,name,curr,pips,subscr);
        }
      else PrintFormat("Signal selection error. Error code=%d",GetLastError());
     }
  }

Machen wir das Gleiche mit Hilfe des neuen MQL5-Signalobjekts. Wir schreiben den folgenden Codeblock in OnInit() des EA:

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- Calling the function displays the list of enumeration constants in the journal 
//--- (the list is set in the strings 22 and 25 of the DELib.mqh file) for checking the constants validity
   //EnumNumbersTest();

//--- Set EA global variables
   prefix=MQLInfoString(MQL_PROGRAM_NAME)+"_";
   testing=engine.IsTester();
   for(int i=0;i<TOTAL_BUTT;i++)
     {
      butt_data[i].name=prefix+EnumToString((ENUM_BUTTONS)i);
      butt_data[i].text=EnumToButtText((ENUM_BUTTONS)i);
     }
   lot=NormalizeLot(Symbol(),fmax(InpLots,MinimumLots(Symbol())*2.0));
   magic_number=InpMagic;
   stoploss=InpStopLoss;
   takeprofit=InpTakeProfit;
   distance_pending=InpDistance;
   distance_stoplimit=InpDistanceSL;
   slippage=InpSlippage;
   trailing_stop=InpTrailingStop*Point();
   trailing_step=InpTrailingStep*Point();
   trailing_start=InpTrailingStart;
   stoploss_to_modify=InpStopLossModify;
   takeprofit_to_modify=InpTakeProfitModify;
   distance_pending_request=(InpDistancePReq<5 ? 5 : InpDistancePReq);
   bars_delay_pending_request=(InpBarsDelayPReq<1 ? 1 : InpBarsDelayPReq);
   g_point=SymbolInfoDouble(NULL,SYMBOL_POINT);
   g_digits=(int)SymbolInfoInteger(NULL,SYMBOL_DIGITS);
//--- Initialize random group numbers
   group1=0;
   group2=0;
   srand(GetTickCount());
   
//--- Initialize DoEasy library
   OnInitDoEasy();
   
//--- Check and remove remaining EA graphical objects
   if(IsPresentObectByPrefix(prefix))
      ObjectsDeleteAll(0,prefix);

//--- Create the button panel
   if(!CreateButtons(InpButtShiftX,InpButtShiftY))
      return INIT_FAILED;
//--- Set trailing activation button status
   ButtonState(butt_data[TOTAL_BUTT-1].name,trailing_on);
//--- Reset states of the buttons for working using pending requests
   for(int i=0;i<14;i++)
     {
      ButtonState(butt_data[i].name+"_PRICE",false);
      ButtonState(butt_data[i].name+"_TIME",false);
     }

//--- Check playing a standard sound by macro substitution and a custom sound by description
   engine.PlaySoundByDescription(SND_OK);
//--- Wait for 600 milliseconds
   engine.Pause(600);
   engine.PlaySoundByDescription(TextByLanguage("Звук упавшей монетки 2","Falling coin 2"));

   CArrayObj *list=new CArrayObj();
   if(list!=NULL)
     {
      //--- request the total number of signals in the signal database 
      int total=SignalBaseTotal(); 
      //--- loop through all signals 
      for(int i=0;i<total;i++) 
        { 
         //--- select a signal for further operation 
         if(!SignalBaseSelect(i))
            continue;
         long id=SignalBaseGetInteger(SIGNAL_BASE_ID);
         CMQLSignal *signal=new CMQLSignal(id);
         if(signal==NULL)
            continue;
         if(!list.Add(signal))
           {
            delete signal;
            continue;
           }
        } 
      //--- display all profitable free signals with a non-zero number of subscribers
      Print("");
      static bool done=false;
      for(int i=0;i<list.Total();i++)
        {
         CMQLSignal *signal=list.At(i);
         if(signal==NULL)
            continue;
         if(signal.Price()>0 || signal.Subscribers()==0)
            continue;
         //--- The very first suitable signal is fully displayed in the journal
         if(!done)
           {
            signal.Print();
            done=true;
           }
         //--- Short descriptions are displayed for the rest
         else
            signal.PrintShort();
        }
      delete list;
     }
     
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+

Auf den ersten Blick ist der resultierende Umfang des Codes größer als der Code aus der Hilfe. Aber das ist eine vorübergehende Erscheinung... Sobald die Klasse der Signalkollektion fertig ist, wird sie viel prägnanter sein. In der Zwischenzeit werde ich den Code verwenden, um zu prüfen, ob das MQL5-Signalobjekt korrekt funktioniert.

Da wir jetzt vom Hauptbibliotheksobjekt aus Zugriff auf die Klasse der Schnappschuss-Reihe der DOM-Kollektion haben, hat OnBookEvent() einige Änderungen erfahren. Jetzt sieht er wie folgt aus:

//+------------------------------------------------------------------+
//| OnBookEvent function                                             |
//+------------------------------------------------------------------+
void OnBookEvent(const string& symbol)
  {
   static bool first=true;
   //--- Leave if failed to update the symbol snapshot series
   if(!engine.OnBookEvent(symbol))
      return;
   //--- Work by the current symbol
   if(symbol==Symbol())
     {
      //--- Get the DOM snapshot series of the current symbol
      CMBookSeries *book_series=engine.GetMBookSeries(symbol);
      if(book_series==NULL)
         return;
      //--- Get the last DOM snapshot object from the DOM snapshot series object
      CMBookSnapshot *book=book_series.GetLastMBook();
      if(book==NULL)
         return;
      //--- Get the very first and last DOM order objects from the DOM snapshot object
      CMarketBookOrd *ord_0=book.GetMBookByListIndex(0);
      CMarketBookOrd *ord_N=book.GetMBookByListIndex(book.DataTotal()-1);
      if(ord_0==NULL || ord_N==NULL) return;
      //--- Display the time of the current DOM snapshot in the chart comment,
      //--- the maximum number of displayed orders in DOM for a symbol,
      //--- the obtained number of orders in the current DOM snapshot,
      //--- the total number of DOM snapshots set in the series list and
      //--- the highest and lowest orders of the current DOM snapshot
      Comment
        (
         DFUN,book.Symbol(),": ",TimeMSCtoString(book.Time()),
         //", symbol book size=",sym.TicksBookdepth(),
         ", last book data total: ",book.DataTotal(),
         ", series books total: ",book_series.DataTotal(),
         "\nMax: ",ord_N.Header(),"\nMin: ",ord_0.Header()
        );
      //--- Display the first DOM snapshot in the journal
      if(first)
        {
         //--- series description
         book_series.Print();
         //--- snapshot description
         book.Print();
         first=false;
        }
     }
  }
//+------------------------------------------------------------------+

Nehmen wir auch in der Funktion OnInitDoEasy() einige Korrekturen vor. Die Erzeugung der Tick-Reihen aller verwendeten Symbole ist jetzt als direkter Zugriff auf die entsprechende Methode des Hauptobjekts der Bibliothek implementiert. Außerdem habe ich die Überprüfung der erstellten DOM-Reihen hinzugefügt:

//--- Check created timeseries - display descriptions of all created timeseries in the journal
//--- (true - only created ones, false - created and declared ones)
   engine.GetTimeSeriesCollection().PrintShort(false); // Short descriptions

//--- Create tick series of all used symbols
   engine.TickSeriesCreateAll();

//--- Check created tick series - display descriptions of all created tick series in the journal
   engine.GetTickSeriesCollection().Print();

//--- Check created DOM series - display descriptions of all created DOM series in the journal
   engine.GetMBookSeriesCollection().Print();


Kompilieren Sie den EA und starten Sie ihn, nachdem Sie zuvor in den Einstellungen die Verwendung von zwei Symbolen und der aktuellen Chartperiode festgelegt haben:


Im Journal sollen die Daten der erstellten DOM-Schnappschuss-Kollektion, die gesamten Daten zum ersten passenden Signal und die Kurzdaten zu allen profitablen freien Signalen angezeigt werden. Am Ende der Liste stehen die Daten der Schnappschuss-Reihe und der erste erhaltene DOM-Schnappschuss des aktuellen Charts:

Account 8550475: Artyom Trishkin (MetaQuotes Software Corp.) 10428.13 USD, 1:100, Hedge, MetaTrader 5 demo
--- Initializing "DoEasy" library ---
Working with predefined symbol list. The number of used symbols: 2
"AUDUSD" "EURUSD"
Working with the current timeframe only: H1
AUDUSD symbol timeseries: 
- Timeseries "AUDUSD" H1: Requested: 1000, Actual: 1000, Created: 1000, On the server: 5385
EURUSD symbol timeseries: 
- Timeseries "EURUSD" H1: Requested: 1000, Actual: 1000, Created: 1000, On the server: 6310
Tick series "AUDUSD": Requested number of days: 1, Historical data created: 294221
Tick series "EURUSD": Requested number of days: 1, Historical data created: 216048
DOM snapshot series collection:
- "AUDUSD" DOM snapshot series: Requested number of days: 1, Actual history depth: 0
"EURUSD" DOM snapshot series: Requested number of days: 1, Actual history depth: 0
Subscribed to Depth of Market  AUDUSD
Subscribed to Depth of Market  EURUSD
Library initialization time: 00:00:25.015
 
============= Beginning of parameter list (Signal from the MQL5.com Signal service) =============
Account type: Demo
Publication date: 2018.06.04 16:45
Monitoring start date: 2018.06.04 16:45
Date of the latest update of the trading statistics: 2021.02.20 02:01
ID: 435626
Trading account leverage: 200
Trading result in pips: -72124
Position in the Rating of Signals: 12
Number of subscribers: 132
Number of trades: 7866
Status of account subscription to a signal: No
------
Account balance: 43144.27
Account equity: 43150.55
Account growth in %: 331.44
Maximum drawdown: 43.93
Signal subscription price: 0.00
Signal ROI (Return on Investment) in %: 331.51
------
Author login: "robots4forex"
Broker (company) name: "MetaQuotes Software Corp."
Broker server: "MetaQuotes-Demo"
Name: "Prospector Scalper EA"
Account currency: "GBP"
============= End of parameter list (Signal from the MQL5.com Signal service) =============
 
Signal "ADS MT5". Author login: vluxus, ID 478235, Growth: 251.84, Drawdown: 40.26, Price: 0.00
Signal "Sparrow USD ForexClub c 01012019". Author login: Tradotrade, ID 519975, Growth: 12.45, Drawdown: 14.98, Price: 0.00
Signal "RAZRED v03". Author login: joaoluiz_sa, ID 545382, Growth: 96.17, Drawdown: 28.18, Price: 0.00
Signal "NRDemo". Author login: v3sare, ID 655353, Growth: 2.94, Drawdown: 25.37, Price: 0.00
Signal "Amega 1000085182". Author login: AmegaTrust, ID 722001, Growth: 1.92, Drawdown: 5.13, Price: 0.00
Signal "Wns My strategy". Author login: WaldeliN, ID 727851, Growth: 103.69, Drawdown: 47.01, Price: 0.00
Signal "Bk EA". Author login: worknet, ID 749557, Growth: 506.88, Drawdown: 59.78, Price: 0.00
Signal "ROBIN 24". Author login: juanca034, ID 752873, Growth: 926.29, Drawdown: 30.25, Price: 0.00
Signal "Deny Forex". Author login: deny.mendonca, ID 759729, Growth: 149.06, Drawdown: 39.24, Price: 0.00
Signal "T Strategy". Author login: tonarino210, ID 760343, Growth: 28.87, Drawdown: 20.37, Price: 0.00
Signal "IC MT5 Demo". Author login: InvestForce, ID 760539, Growth: 67.01, Drawdown: 35.99, Price: 0.00
Signal "Gridingale". Author login: Myxx, ID 766073, Growth: 21.10, Drawdown: 15.55, Price: 0.00
Signal "Marcos Monteiro". Author login: slovenwill, ID 783988, Growth: 85.08, Drawdown: 17.59, Price: 0.00
Signal "Multi currency trend". Author login: mj2019, ID 785447, Growth: 54.42, Drawdown: 18.52, Price: 0.00
Signal "W7 901074879 Campeonato MT5". Author login: dramos236, ID 787269, Growth: 91.99, Drawdown: 21.20, Price: 0.00
Signal "Ramon Fx". Author login: viniciusramon18, ID 788732, Growth: 54.31, Drawdown: 9.46, Price: 0.00
Signal "Douglas demo w7". Author login: douglas.o.carne, ID 792392, Growth: 219.94, Drawdown: 43.61, Price: 0.00
"Suelen" signal. Author login: suelenacca, ID 794655, Growth: 67.40, Drawdown: 20.97, Price: 0.00
Signal "Conquers". Author login: borgesti, ID 795133, Growth: 37.23, Drawdown: 11.09, Price: 0.00
Signal "Conta demo torneio". Author login: Tiagoximenes, ID 798798, Growth: 42.36, Drawdown: 17.94, Price: 0.00
Signal "Conta demo de mil". Author login: Tiagoximenes, ID 798802, Growth: 132.02, Drawdown: 27.87, Price: 0.00
Signal "The art of Forex". Author login: Myxx, ID 801685, Growth: 170.29, Drawdown: 40.95, Price: 0.00
Signal "BB29 ICM". Author login: desmondpylow, ID 806971, Growth: 2.28, Drawdown: 41.60, Price: 0.00
Signal "Prometheus". Author login: g0079, ID 808538, Growth: 91.44, Drawdown: 22.98, Price: 0.00
Signal "Prueba robot 2 0 automatico". Author login: richwolfcompany, ID 809986, Growth: 76.76, Drawdown: 44.45, Price: 0.00
Signal "Deep Takeover Hedge StressTest 5M Candle". Author login: johnnypasado, ID 811819, Growth: 10.08, Drawdown: 13.58, Price: 0.00
Signal "Campeonato". Author login: AndreAutotecnic, ID 812233, Growth: 87.47, Drawdown: 13.79, Price: 0.00
Signal "OPM PRO". Author login: herinata, ID 812856, Growth: 38.55, Drawdown: 32.35, Price: 0.00
Signal "Slowly but surely 2". Author login: gyurmanz, ID 815467, Growth: 53.73, Drawdown: 13.08, Price: 0.00
Signal "Beef Waves". Author login: vladimir0005, ID 819055, Growth: 50.46, Drawdown: 32.69, Price: 0.00
Signal "Adriano Garcia". Author login: agarcia_ag, ID 823082, Growth: 111.62, Drawdown: 36.00, Price: 0.00
Signal "Max ScalperSpeed MT5". Author login: paran1615, ID 824333, Growth: 74.51, Drawdown: 40.62, Price: 0.00
Signal "SyH". Author login: gtrader2017, ID 826520, Growth: 42.78, Drawdown: 36.81, Price: 0.00
Signal "ECmp5s free". Author login: VallaLorenzo, ID 830456, Growth: 146.90, Drawdown: 27.64, Price: 0.00
Signal "MaxScalperSpeed MT5". Author login: paran1615, ID 835890, Growth: 64.33, Drawdown: 35.14, Price: 0.00
Signal "YEARNSIGNALS". Author login: yearnsignal2k19, ID 837512, Growth: 11.10, Drawdown: 2.54, Price: 0.00
Signal "AGS test 2". Author login: alireza.akbari, ID 838427, Growth: 7.93, Drawdown: 10.89, Price: 0.00
Signal "Waldeli003". Author login: WaldeliN, ID 838605, Growth: 32.98, Drawdown: 5.54, Price: 0.00
Signal "Michele". Author login: michele-m-r, ID 843351, Growth: 49.27, Drawdown: 13.90, Price: 0.00
Signal "SNAILER". Author login: 8F117EE2, ID 843458, Growth: 83.65, Drawdown: 11.86, Price: 0.00
Signal "Juniornicks". Author login: juniornicks, ID 845611, Growth: 100.25, Drawdown: 43.93, Price: 0.00
Signal "Black Hunter". Author login: christianlara, ID 845761, Growth: 51.94, Drawdown: 24.44, Price: 0.00
Signal "Master dizicheh1". Author login: awdtghuoilp, ID 857594, Growth: 5.04, Drawdown: 37.93, Price: 0.00
Signal "EUROS". Author login: Marketsystem, ID 858449, Growth: 5.31, Drawdown: 2.94, Price: 0.00
Signal "Scalpers risk10 pairs7 leverage100". Author login: leron34, ID 861750, Growth: 27.98, Drawdown: 20.53, Price: 0.00
Signal "EUREKA". Author login: Edmed933, ID 861927, Growth: 59.89, Drawdown: 7.32, Price: 0.00
Signal "Nadando Com Tubaroes". Author login: jun152, ID 862191, Growth: 21.18, Drawdown: 5.45, Price: 0.00
Signal "Demo using a grid system". Author login: RyanAfriansyah, ID 865900, Growth: 20.56, Drawdown: 8.38, Price: 0.00
Signal "Pilares". Author login: ValterCezar, ID 866672, Growth: 29.87, Drawdown: 18.96, Price: 0.00
Signal "EUROUSD". Author login: fxtrader036, ID 866719, Growth: 303.28, Drawdown: 40.70, Price: 0.00
Signal "LanzPower 25 S". Author login: sirlanz, ID 868027, Growth: 36.64, Drawdown: 45.53, Price: 0.00
Signal "Amadeu Volpato Desafio Internacional". Author login: Amadeu1971, ID 868928, Growth: 19.79, Drawdown: 12.57, Price: 0.00
Signal "Fernando correia W7". Author login: nandooo_123-hotmail, ID 870169, Growth: 41.70, Drawdown: 25.16, Price: 0.00
Signal "MAK GO". Author login: 9489631, ID 870413, Growth: 469.22, Drawdown: 36.31, Price: 0.00
Signal "Adriano Garcia W7bt 4 Pilares". Author login: agarcia_ag, ID 871868, Growth: 42.84, Drawdown: 13.19, Price: 0.00
Signal "Albertofxsemstop". Author login: albertosuga, ID 871969, Growth: 27.84, Drawdown: 19.36, Price: 0.00
Signal "BetoSTCDemo". Author login: betoabcsp, ID 872141, Growth: 29.03, Drawdown: 18.07, Price: 0.00
Signal "DESAFIOSEMSTOPLOSSCDS". Author login: cdsantos42, ID 873575, Growth: 19.47, Drawdown: 13.24, Price: 0.00
Signal "MrGeek7421". Author login: KamranAhmadi, ID 873583, Growth: 86.74, Drawdown: 16.33, Price: 0.00
Signal "Douglastorneio2w7". Author login: douglas.o.carne, ID 876302, Growth: 18.13, Drawdown: 15.34, Price: 0.00
Signal "Douglasw7demo1". Author login: douglas.o.carne, ID 876303, Growth: 148.80, Drawdown: 26.47, Price: 0.00
Signal "Douglastorneio1w7". Author login: douglas.o.carne, ID 876932, Growth: 136.86, Drawdown: 41.86, Price: 0.00
Signal "Campeonato mundial sem stop". Author login: Lpontes835, ID 878082, Growth: 23.52, Drawdown: 14.93, Price: 0.00
Signal "ALPHA IA v3". Author login: avaalpha, ID 878517, Growth: 2.77, Drawdown: 0.77, Price: 0.00
Signal "Gold x10". Author login: DynamixFX, ID 878540, Growth: 6.47, Drawdown: 8.87, Price: 0.00
Signal "MultiBolbandsRealM5". Author login: 11BREATH11, ID 879072, Growth: 83.18, Drawdown: 20.09, Price: 0.00
Signal "Ticols Stable profit". Author login: ticols, ID 879609, Growth: -56.37, Drawdown: 68.68, Price: 0.00
Signal "EA SkyBot MultiPares CENT". Author login: 4PerformanceFx, ID 882222, Growth: 248.38, Drawdown: 41.29, Price: 0.00
Signal "Trader Unity M15 100 rec". Author login: crifalo, ID 882268, Growth: 24.36, Drawdown: 26.11, Price: 0.00
Signal "Mad Piper Bill Millin". Author login: DiXOVERS, ID 882495, Growth: 251.06, Drawdown: 38.78, Price: 0.00
Signal "ProfitGuy STAR M Demo". Author login: justbond, ID 882847, Growth: 27.45, Drawdown: 24.89, Price: 0.00
Signal "EA GrayRock". Author login: serggray, ID 883235, Growth: 49.42, Drawdown: 28.68, Price: 0.00
Signal "FX FLASH". Author login: tradedeal, ID 883322, Growth: 9.17, Drawdown: 2.88, Price: 0.00
Signal "Optimizer". Author login: alama1, ID 884765, Growth: 73.53, Drawdown: 28.58, Price: 0.00
Signal "NnaFX Demo 02". Author login: 12259468, ID 886070, Growth: 136.64, Drawdown: 30.54, Pric: 0.00
Signal "Phantom5000 DEMO". Author login: JosephSmith, ID 887046, Growth: 43.41, Drawdown: 17.73, Price: 0.00
Signal "Art of Forex MadCat The G". Author login: The_G, ID 888018, Growth: 215.67, Drawdown: 40.86, Price: 0.00
Signal "ICMarkets MT5 AK 05". Author login: A.Klimkovsky, ID 889370, Growth: 13.03, Drawdown: 8.55, Price: 0.00
Signal "ProfitGuy STAR G Demo". Author login: justbond, ID 890551, Growth: 58.84, Drawdown: 58.80, Price: 0.00
Signal "BetoSemStopDM". Author login: betoabcsp, ID 892251, Growth: 94.96, Drawdown: 6.30, Price: 0.00
Signal "Smart Grid 26980 Demo". Author login: tm3912, ID 892313, Growth: 86.30, Drawdown: 37.19, Price: 0.00
Signal "Rel Vigor PSar n Red Dragon n mad max". Author login: DynamixFX, ID 892523, Growth: 73.74, Drawdown: 38.55, Price: 0.00
Signal "SolangeL". Author login: Mulherdeletras1, ID 894019, Growth: 108.40, Drawdown: 20.84, Price: 0.00
Signal "Paulotbone 1". Author login: paulotbone, ID 894062, Growth: 35.14, Drawdown: 23.93, Price: 0.00
Signal "GOLD MASTER". Author login: THEICD, ID 894983, Growth: 218.90, Drawdown: 22.80, Price: 0.00
Signal "Fxfrance". Author login: fxfrance, ID 895838, Growth: 369.48, Drawdown: 41.48, Price: 0.00
Signal "Marcos Paulo Serigatti". Author login: mpm4rcos, ID 895960, Growth: 45.62, Drawdown: 18.21, Price: 0.00
Signal "Roma Forex Desafio 4 Pilares". Author login: Jhonesroma, ID 896016, Growth: 29.60, Drawdown: 43.45, Price: 0.00
Signal "BOSBM OTC Test 5W". Author login: houli, ID 896563, Growth: 144.65, Drawdown: 22.94, Price: 0.00
Signal "FSTickTrade". Author login: onlyforsignup, ID 897751, Growth: 24.68, Drawdown: 16.20, Price: 0.00
Signal "Sun AI". Author login: Myxx, ID 899179, Growth: 16.82, Drawdown: 21.07, Price: 0.00
Signal "Equinox Demo". Author login: Kratoner, ID 905773, Growth: 44.46, Drawdown: 20.55, Price: 0.00
Signal "STRAGA Tornado VM1". Author login: stragapede, ID 906398, Growth: 36.70, Drawdown: 26.00, Price: 0.00
Signal "DiegoT". Author login: DiegoTT, ID 910230, Growth: 28.20, Drawdown: 11.49, Price: 0.00
Signal "Breaking Bad". Author login: Myxx, ID 911569, Growth: 7.63, Drawdown: 8.42, Price: 0.00
Signal "TradesaovivoBr". Author login: dhyegorodrigo1988, ID 913924, Growth: 16.77, Drawdown: 5.60, Price: 0.00
Signal "VantageFX Sunphone Dragon". Author login: sunphone, ID 916421, Growth: 345.56, Drawdown: 36.04, Price: 0.00
Signal "BYQS121". Author login: kadirryildiz, ID 916600, Growth: 32.85, Drawdown: 4.18, Price: 0.00
Signal "FBSLevelUP". Author login: manoj, ID 919106, Growth: 15.29, Drawdown: 10.49, Price: 0.00
Signal "Omega". Author login: zyntherius74, ID 922043, Growth: 70.18, Drawdown: 25.42, Price: 0.00
Signal "Best Bingo". Author login: kalnov-an, ID 926010, Growth: 59.90, Drawdown: 20.63, Price: 0.00
Signal "LCF 1". Author login: yosuf, ID 931735, Growth: 22.42, Drawdown: 36.26, Price: 0.00
Signal "Bao365". Author login: bao365, ID 933208, Growth: 28.41, Drawdown: 11.49, Price: 0.00
The "EURUSD" DOM snapshot series: Requested number of days: 1, Actual history depth: 1
"EURUSD" DOM snapshot (2021.02.24 22:22:54.654):
 - Sell order: 1.21576 [250.00]
 - Sell order: 1.21567 [100.00]
 - Sell order: 1.21566 [50.00]
 - Sell order: 1.21565 [36.00]
 - Buy order: 1.21563 [36.00]
 - Buy order: 1.21561 [50.00]
 - Buy order: 1.21559 [100.00]
 - Buy order: 1.21555 [250.00]


Was kommt als Nächstes?

Im nächsten Artikel werde ich eine Kollektion von MQL5-Signalen erstellen.

Alle Dateien der aktuellen Version der Bibliothek sind unten zusammen mit der Test-EA-Datei für MQL5 zum Testen und Herunterladen angehängt.
Schreiben Sie Ihre Fragen und Vorschläge in den Kommentaren.

Zurück zum Inhalt

*Frühere Artikel dieser Serie:

Preise in der DoEasy-Bibliothek (Teil 62): Aktualisieren der Tick-Serien in Echtzeit, Vorbereitung für die Arbeit mit Markttiefe
Preise in der DoEasy-Bibliothek (Teil 63): Markttiefe und deren abstrakte Anforderungsklasse
Preise in der DoEasy-Bibliothek (Teil 64): Markttiefe, Klassenobjekte für Schnappschüsse der Markttiefe und der Schnappschuss-Reihen


Übersetzt aus dem Russischen von MetaQuotes Software Corp.
Originalartikel: https://www.mql5.com/ru/articles/9095

Beigefügte Dateien |
MQL5.zip (3903.29 KB)
Neuronale Netze leicht gemacht (Teil 12): Dropout Neuronale Netze leicht gemacht (Teil 12): Dropout
Als nächsten Schritt beim Studium von neuronalen Netzwerken schlage ich vor, die Methoden zur Erhöhung der Konvergenz beim Training von neuronalen Netzwerken zu besprechen. Es gibt mehrere solcher Methoden. In diesem Artikel werden wir uns einer von ihnen mit dem Namen Dropout zuwenden.
Maschinelles Lernen für Grid- und Martingale-Handelssysteme. Würden Sie darauf wetten? Maschinelles Lernen für Grid- und Martingale-Handelssysteme. Würden Sie darauf wetten?
Dieser Artikel beschreibt die Technik des maschinellen Lernens, die auf den Grid- und Martingale-Handel angewendet wird. Überraschenderweise hat dieser Ansatz wenig bis gar keine Verbreitung im globalen Netzwerk. Nachdem Sie den Artikel gelesen haben, werden Sie in der Lage sein, Ihre eigenen Trading Bots zu erstellen.
Andere Klassen in der Bibliothek DoEasy (Teil 66): MQL5.com die Kollektionsklasse der Signale Andere Klassen in der Bibliothek DoEasy (Teil 66): MQL5.com die Kollektionsklasse der Signale
In diesem Artikel werde ich die Kollektionsklasse der Signale des MQL5.com Signals-Dienstes mit den Funktionen zur Verwaltung von Signalen erstellen. Außerdem werde ich die Schnappschuss-Objektklasse der Markttiefe (Depth of Market, DOM) verbessern, um das gesamte Kauf- und Verkaufsvolumen im DOM anzuzeigen.
Preise in der DoEasy-Bibliothek (Teil 64): Markttiefe, Klassenobjekte für Schnappschüsse der Markttiefe und der Schnappschuss-Reihen Preise in der DoEasy-Bibliothek (Teil 64): Markttiefe, Klassenobjekte für Schnappschüsse der Markttiefe und der Schnappschuss-Reihen
In diesem Artikel werde ich zwei Klassen erstellen (die Klassenobjekte des DOM-Schnappschusses und die der DOM-Schnappschuss-Reihe) und die Erstellung der DOM-Datenreihe testen.