Preise in der DoEasy-Bibliothek (Teil 63): Markttiefe und deren abstrakte Anforderungsklasse

Artyom Trishkin | 31 März, 2021

Inhalt


Konzept

In diesem Artikel beginne ich mit der Implementierung der Funktionen für die Arbeit mit der Markttiefe (Depth of Market, DOM). Konzeptionell werden sich die Klassen für die Arbeit mit dem DOM nicht von allen bisher implementierten Bibliotheksklassen unterscheiden. Gleichzeitig werden wir eine Form des DOM haben, die Daten über die im DOM gespeicherten Aufträge enthält. Die Daten werden von der Funktion MarketBookGet() bezogen, wenn der Handler OnBookEvent() aktiviert ist. Bei einer DOM-Änderung wird ein Ereignis für jedes der Symbole im Handler aktiviert, die das aktive Abonnement für DOM-Ereignisse haben.

Die Struktur der DOM-Klasse soll also wie folgt aussehen:

  1. Das Klassenobjekt der DOM-Aufträge — das Objekt, das die Daten eines Auftrags aus mehreren Aufträgen beschreibt, die vom DOM erhalten werden, wenn die Funktion OnBookEvent() für ein Symbol ausgelöst wird;
  2. Die Form der DOM-Objektklasse — das Objekt, das die Daten aller Aufträge beschreibt, die gleichzeitig aus dem DOM erhalten werden, wenn OnBookEvent() für ein einzelnes Symbol ausgelöst wird — p1 Menge der Objekte, die die aktuelle DOM-Form bilden;
  3. Zeitreihenklasse, bestehend aus der Objektfolge p2, die bei jeder Aktivierung von OnBookEvent() für ein einzelnes Symbol in die Zeitreihenliste eingetragen wird;
  4. Die Kollektionsklasse der Zeitreihen der DOM-Daten aller verwendeten Symbole mit aktiviertem Abonnement auf DOM-Ereignisse.

Heute werde ich die Order-Objektklasse (1) implementieren und das Abrufen von DOM-Daten bei der Aktivierung von OnBookEvent() für das aktuelle Symbol testen.

Die Eigenschaften jeder Order werden in der Struktur MqlBookInfo festgelegt, die Daten im DOM bereitstellt:

  • Auftragstyp aus der Enumeration ENUM_BOOK_TYPE
  • Auftragspreis
  • Auftragsvolumen
  • Erweiterte Genauigkeit des Auftragsvolumens

DOM kann vier Ordertypen (aus der Enumeration ENUM_BOOK_TYPE) aufweisen:

  • Verkaufsauftrag
  • Verkaufsauftrag als Marktorder
  • Kaufauftrag
  • Kaufauftrag als Marktorder

Wie wir sehen können, gibt es vier Ordertypen — zwei Kauf- und zwei Verkaufsarten. Um alle Auftragstypen in zwei Seiten aufzuteilen, sollten wir eine weitere Eigenschaft zu den bereits vorhandenen hinzufügen — den Auftragsstatus, der seine Richtung angibt — Kauf- oder Verkaufsauftrag. Dies wird uns erlauben, alle Aufträge schnell ihrer Seiten zuzuweisen — Angebot und Nachfrage.

Das Objekt einer einzelnen DOM-Anfrage wird ähnlich wie Auftragsobjekte (sowie viele andere Bibliotheksobjekte) aufgebaut sein — wir werden ein Basisobjekt des abstrakten DOM-Auftrags und vier abhängige Objekte mit der Auftragstypangabe haben. Das Konzept, solche Objekte zu konstruieren, wurde bereits zu Beginn der Bibliotheksentwicklung in den ersten und zweiten Artikeln berücksichtigt.

    Bevor wir die Klassen für die Arbeit mit dem DOM implementieren, fügen wir neue Bibliotheksnachrichten hinzu und verbessern leicht die Tick-Daten-Objektklassen. Fügen wir neue Nachrichtenindizes in \MQL5\Include\DoEasy\Data.mqh hinzu:

       MSG_SYM_EVENT_SYMBOL_ADD,                          // Added symbol to Market Watch window
       MSG_SYM_EVENT_SYMBOL_DEL,                          // Symbol removed from Market Watch window
       MSG_SYM_EVENT_SYMBOL_SORT,                         // Changed location of symbols in Market Watch window
       MSG_SYM_SYMBOLS_MODE_CURRENT,                      // Work with current symbol only
       MSG_SYM_SYMBOLS_MODE_DEFINES,                      // Work with predefined symbol list
       MSG_SYM_SYMBOLS_MODE_MARKET_WATCH,                 // Work with Market Watch window symbols
       MSG_SYM_SYMBOLS_MODE_ALL,                          // Work with full list of all available symbols
       MSG_SYM_SYMBOLS_BOOK_ADD,                          // Subscribed to Depth of Market 
       MSG_SYM_SYMBOLS_BOOK_DEL,                          // Unsubscribed from Depth of Market 
       MSG_SYM_SYMBOLS_MODE_BOOK,                         // Subscription to Depth of Market
       MSG_SYM_SYMBOLS_ERR_BOOK_ADD,                      // Error subscribing to DOM
       MSG_SYM_SYMBOLS_ERR_BOOK_DEL,                      // Error unsubscribing from DOM
       
    //--- CAccount
    
    

    ...

    //--- CTickSeries
       MSG_TICKSERIES_TEXT_TICKSERIES,                    // Tick series
       MSG_TICKSERIES_ERR_GET_TICK_DATA,                  // Failed to get tick data
       MSG_TICKSERIES_FAILED_CREATE_TICK_DATA_OBJ,        // Failed to create tick data object
       MSG_TICKSERIES_FAILED_ADD_TO_LIST,                 // Failed to add tick data object to list
       MSG_TICKSERIES_TEXT_IS_NOT_USE,                    // Tick series not used. Set the flag using SetAvailable()
       MSG_TICKSERIES_REQUIRED_HISTORY_DAYS,              // Requested number of days
       
    //--- CMarketBookOrd
       MSG_MBOOK_ORD_TEXT_MBOOK_ORD,                      // Order in DOM
       MSG_MBOOK_ORD_VOLUME,                              // Volume
       MSG_MBOOK_ORD_VOLUME_REAL,                         // Extended accuracy volume
       MSG_MBOOK_ORD_STATUS_BUY,                          // Buy side
       MSG_MBOOK_ORD_STATUS_SELL,                         // Sell side
       MSG_MBOOK_ORD_TYPE_SELL,                           // Sell order
       MSG_MBOOK_ORD_TYPE_BUY,                            // Buy order 
       MSG_MBOOK_ORD_TYPE_SELL_MARKET,                    // Sell order by Market
       MSG_MBOOK_ORD_TYPE_BUY_MARKET,                     // Buy order by Market
    
      };
    //+------------------------------------------------------------------+
    
    

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

       {"В окно \"Обзор рынка\" добавлен символ","Added symbol to \"Market Watch\" window"},
       {"Из окна \"Обзор рынка\" удалён символ","Removed from \"Market Watch\" window"},
       {"Изменено расположение символов в окне \"Обзор рынка\"","Changed arrangement of symbols in \"Market Watch\" window"},
       {"Работа только с текущим символом","Work only with the current symbol"},
       {"Работа с предопределённым списком символов","Work with predefined list of symbols"},
       {"Работа с символами из окна \"Обзор рынка\"","Working with symbols from \"Market Watch\" window"},
       {"Работа с полным списком всех доступных символов","Work with full list of all available symbols"},
       {"Осуществлена подписка на стакан цен ","Subscribed to Depth of Market"},
       {"Осуществлена отписка от стакан цен ","Unsubscribed from Depth of Market"},
       {"Подписка на стакан цен","Subscription to Depth of Market"},
       {"Ошибка при подписке на стакан цен",""},
       {"Ошибка при отписке от стакан цен",""},
       
    //--- CAccount
    
    

    ...

    //--- CMarketBookOrd
       {"Заявка в стакане цен","Order in Depth of Market"},
       {"Объем","Volume"},
       {"Объем c повышенной точностью","Volume Real"},
       {"Сторона Buy","Buy side"},
       {"Сторона Sell","Sell side"},
       {"Заявка на продажу","Sell order"},
       {"Заявка на покупку","Buy order"},
       {"Заявка на продажу по рыночной цене","Sell order at market price"},
       {"Заявка на покупку по рыночной цене","Buy order at market price"},
       
      };
    //+---------------------------------------------------------------------+
    
    

    Hinzufügen der Anzeige von Meldungen über den Fehler beim Abonnieren des DOM in der Datei \MQL5\Include\DoEasy\Objects\Symbols\Symbol.mqh der Symbolobjektklasse:

    //+------------------------------------------------------------------+
    //| Subscribe to the Depth of Market                                 |
    //+------------------------------------------------------------------+
    bool CSymbol::BookAdd(void)
      {
       this.m_book_subscribed=(#ifdef __MQL5__ ::MarketBookAdd(this.m_name) #else false #endif);
       this.m_long_prop[SYMBOL_PROP_BOOKDEPTH_STATE]=this.m_book_subscribed;
       if(this.m_book_subscribed)
          ::Print(CMessage::Text(MSG_SYM_SYMBOLS_BOOK_ADD)+" "+this.m_name);
       else
          ::Print(CMessage::Text(MSG_SYM_SYMBOLS_ERR_BOOK_ADD)+": "+CMessage::Text(::GetLastError()));
       return this.m_book_subscribed;
      }
    //+------------------------------------------------------------------+
    
    

    und das Gleiche für das Storno des Abonnements

    //+------------------------------------------------------------------+
    //| Close the market depth                                           |
    //+------------------------------------------------------------------+
    bool CSymbol::BookClose(void)
      {
    //--- If the DOM subscription flag is off, subscription is disabled (or not enabled yet). Return 'true'
       if(!this.m_book_subscribed)
          return true;
    //--- Save the result of unsubscribing from the DOM
       bool res=( #ifdef __MQL5__ ::MarketBookRelease(this.m_name) #else true #endif );
    //--- If unsubscribed successfully, reset the DOM subscription flag and write the status to the object property
       if(res)
         {
          this.m_long_prop[SYMBOL_PROP_BOOKDEPTH_STATE]=this.m_book_subscribed=false;
          ::Print(CMessage::Text(MSG_SYM_SYMBOLS_BOOK_DEL)+" "+this.m_name);
         }
       else
         {
          this.m_long_prop[SYMBOL_PROP_BOOKDEPTH_STATE]=this.m_book_subscribed=true;
          ::Print(CMessage::Text(MSG_SYM_SYMBOLS_ERR_BOOK_DEL)+": "+CMessage::Text(::GetLastError()));
         }
    //--- Return the result of unsubscribing from DOM
       return res;
      }
    //+------------------------------------------------------------------+
    
    

    Aus der Methode für die Aktualisierung der Tick-Reihe der Klasse der Tick-Reihen in \MQL5\Include\DoEasy\Objects\Ticks\TickSeries.mqh, entfernen wir die Anzeige von Debugging-Kommentaren auf dem Symboldiagramm, die im vorherigen Artikel für Tests noch verblieben sind:

    //+------------------------------------------------------------------+
    //| Update the tick series list                                      |
    //+------------------------------------------------------------------+
    void CTickSeries::Refresh(void)
      {
       MqlTick ticks_array[];
       if(IsNewTick())
         {
          //--- Copy ticks from m_last_time time+1 ms to the end of history
          int err=ERR_SUCCESS;
          int total=::CopyTicksRange(this.Symbol(),ticks_array,COPY_TICKS_ALL,this.m_last_time+1,0);
          //--- If the ticks have been copied, create new tick data objects and add them to the list in the loop by their number
          if(total>0)
            {
             for(int i=0;i<total;i++)
               {
                //--- Create the tick object and add it to the list
                CDataTick *tick_obj=this.CreateNewTickObj(ticks_array[i]);
                if(tick_obj==NULL)
                   break;
                //--- Write the last tick time for subsequent copying of newly arrived ticks
                long end_time=ticks_array[::ArraySize(ticks_array)-1].time_msc;
                if(this.Symbol()=="AUDUSD")
                   Comment(DFUN,this.Symbol(),", copied=",total,", m_last_time=",TimeMSCtoString(m_last_time),", end_time=",TimeMSCtoString(end_time),", total=",DataTotal());
                this.m_last_time=end_time;
               }
             //--- If the number of ticks in the list exceeds the default maximum number,
             //--- remove the calculated number of tick objects from the end of the list
             if(this.DataTotal()>TICKSERIES_MAX_DATA_TOTAL)
               {
                int total_del=m_list_ticks.Total()-TICKSERIES_MAX_DATA_TOTAL;
                for(int j=0;j<total_del;j++)
                   this.m_list_ticks.Delete(j);
               }
            }
         }
      }
    //+------------------------------------------------------------------+
    
    

    Die letzte Tick-Zeit wird jetzt sofort in der dafür vorgesehenen Variablen m_last_time gesetzt, weil ich im vorigen Artikel die Verifikationsdaten als Symbolchart-Kommentar mit den vorherigen und aktuellen Tick-Zeiten anzeigen musste. Jetzt brauchen wir sie nicht mehr und die Zeit wird sofort in der Variablen gespeichert:

    //+------------------------------------------------------------------+
    //| Update the tick series list                                      |
    //+------------------------------------------------------------------+
    void CTickSeries::Refresh(void)
      {
       MqlTick ticks_array[];
       if(IsNewTick())
         {
          //--- Copy ticks from m_last_time time+1 ms to the end of history
          int err=ERR_SUCCESS;
          int total=::CopyTicksRange(this.Symbol(),ticks_array,COPY_TICKS_ALL,this.m_last_time+1,0);
          //--- If the ticks have been copied, create new tick data objects and add them to the list in the loop by their number
          if(total>0)
            {
             for(int i=0;i<total;i++)
               {
                //--- Create the tick object and add it to the list
                CDataTick *tick_obj=this.CreateNewTickObj(ticks_array[i]);
                if(tick_obj==NULL)
                   break;
                //--- Write the last tick time for subsequent copying of newly arrived ticks
                this.m_last_time=ticks_array[::ArraySize(ticks_array)-1].time_msc;
               }
             //--- If the number of ticks in the list exceeds the default maximum number,
             //--- remove the calculated number of tick objects from the end of the list
             if(this.DataTotal()>TICKSERIES_MAX_DATA_TOTAL)
               {
                int total_del=m_list_ticks.Total()-TICKSERIES_MAX_DATA_TOTAL;
                for(int j=0;j<total_del;j++)
                   this.m_list_ticks.Delete(j);
               }
            }
         }
      }
    //+------------------------------------------------------------------+
    
    


    Abstraktes Klasse des Auftragsobjekts der Markttiefe

    Wie bei allen Bibliotheksobjekten mit den Enumerationen zur Definition von Objekt-Eigenschaftskonstanten müssen wir auch für DOM-Aufträge Enumerationen von Integer-, Real- und String-Objekteigenschaften erstellen.

    Fügen wir die Enumerationen von DOM-Auftragsobjekteigenschaften und -parametern in \MQL5\Include\DoEasy\Defines.mqh hinzu. Da ich kein Ereignismodell für die Arbeit mit den einzelnen Aufträgen im DOM implementieren werde (zu einem Zeitpunkt zeigt das Auftragsbuch den aktuellen Zustand aller Aufträge an, und deren Änderung führt zu seinem nächsten Zustand und wird bei der nächsten Aktivierung von OnBookEvent() verarbeitet), fügen wir einfach die Konstante, die den Code des nächsten Ereignisses angibt, nach dem letzten Code des DOM-Ereignisses hinzu, um die Identität der Konstanten aller Objekte zu erhalten und sie auf die gleiche Form zu bringen:

    //+------------------------------------------------------------------+
    //| Data for working with DOM                                        |
    //+------------------------------------------------------------------+
    //+------------------------------------------------------------------+
    //| List of possible DOM events                                      |
    //+------------------------------------------------------------------+
    #define MBOOK_ORD_EVENTS_NEXT_CODE  (SERIES_EVENTS_NEXT_CODE+1)   // The code of the next event after the last DOM event code
    //+------------------------------------------------------------------+
    
    

    Definieren wir die Enumeration mit den zwei möglichen Zuständen eines einzelnen DOM-Auftrags — Kauf- oder Verkaufsseite:

    //+------------------------------------------------------------------+
    //| Abstract DOM type (status)                                       |
    //+------------------------------------------------------------------+
    enum ENUM_MBOOK_ORD_STATUS
      {
       MBOOK_ORD_STATUS_BUY,                              // Buy side
       MBOOK_ORD_STATUS_SELL,                             // Sell side
      };
    //+------------------------------------------------------------------+
    
    

    Wenn wir alle Aufträge im DOM nach diesen Eigenschaften sortieren, können wir alle Aufträge im DOM, die entweder zur Nachfrage oder zum Angebot gehören, schnell nach diesen Eigenschaften auswählen.

    Als Nächstes fügen wir Enumerationen der Eigenschaften integer, real und string von DOM-Auftragsobjekt-Eigenschaften hinzu:

    //+------------------------------------------------------------------+
    //| Integer properties of DOM order                                  |
    //+------------------------------------------------------------------+
    enum ENUM_MBOOK_ORD_PROP_INTEGER
      {
       MBOOK_ORD_PROP_STATUS = 0,                         // Order status
       MBOOK_ORD_PROP_TYPE,                               // Order type
       MBOOK_ORD_PROP_VOLUME,                             // Order volume
      }; 
    #define MBOOK_ORD_PROP_INTEGER_TOTAL (3)              // Total number of integer properties
    #define MBOOK_ORD_PROP_INTEGER_SKIP  (0)              // Number of integer DOM properties not used in sorting
    //+------------------------------------------------------------------+
    //| Real properties of DOM order                                     |
    //+------------------------------------------------------------------+
    enum ENUM_MBOOK_ORD_PROP_DOUBLE
      {
       MBOOK_ORD_PROP_PRICE = MBOOK_ORD_PROP_INTEGER_TOTAL, // Order price
       MBOOK_ORD_PROP_VOLUME_REAL,                        // Extended accuracy order volume
      };
    #define MBOOK_ORD_PROP_DOUBLE_TOTAL  (2)              // Total number of real properties
    #define MBOOK_ORD_PROP_DOUBLE_SKIP   (0)              // Number of real properties not used in sorting
    //+------------------------------------------------------------------+
    //| String properties of DOM order                                   |
    //+------------------------------------------------------------------+
    enum ENUM_MBOOK_ORD_PROP_STRING
      {
       MBOOK_ORD_PROP_SYMBOL = (MBOOK_ORD_PROP_INTEGER_TOTAL+MBOOK_ORD_PROP_DOUBLE_TOTAL), // Order symbol name
      };
    #define MBOOK_ORD_PROP_STRING_TOTAL  (1)              // Total number of string properties
    //+------------------------------------------------------------------+
    
    

    Implementieren wir die Enumeration möglicher Kriterien für die Sortierung von Aufträgen im DOM entsprechend der erstellten Eigenschaften:

    //+------------------------------------------------------------------+
    //| Possible sorting criteria of DOM orders                          |
    //+------------------------------------------------------------------+
    #define FIRST_MB_DBL_PROP  (MBOOK_ORD_PROP_INTEGER_TOTAL-MBOOK_ORD_PROP_INTEGER_SKIP)
    #define FIRST_MB_STR_PROP  (MBOOK_ORD_PROP_INTEGER_TOTAL-MBOOK_ORD_PROP_INTEGER_SKIP+MBOOK_ORD_PROP_DOUBLE_TOTAL-MBOOK_ORD_PROP_DOUBLE_SKIP)
    enum ENUM_SORT_MBOOK_ORD_MODE
      {
    //--- Sort by integer properties
       SORT_BY_MBOOK_ORD_STATUS = 0,                      // Sort by order status
       SORT_BY_MBOOK_ORD_TYPE,                            // Sort by order type
       SORT_BY_MBOOK_ORD_VOLUME,                          // Sort by order volume
    //--- Sort by real properties
       SORT_BY_MBOOK_ORD_PRICE = FIRST_MB_DBL_PROP,       // Sort by order price
       SORT_BY_MBOOK_ORD_VOLUME_REAL,                     // Sort by extended accuracy order volume
    //--- Sort by string properties
       SORT_BY_MBOOK_ORD_SYMBOL = FIRST_MB_STR_PROP,      // Sort by symbol name
      };
    //+------------------------------------------------------------------+
    
    

    Jetzt ist es möglich, die abstrakte Auftrags-Objektklasse im DOM zu erstellen.

    Legen wir in \MQL5\Include\DoEasy\Objects\ den neuen Ordner Book\ an, der die Datei MarketBookOrd.mqh der Klasse CMarketBookOrd abgeleitet vom Basisobjekt aller CBaseObj Bibliotheksobjekte enthält:

    //+------------------------------------------------------------------+
    //|                                                MarketBookOrd.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 "..\..\Services\DELib.mqh"
    #include "..\..\Objects\BaseObj.mqh"
    //+------------------------------------------------------------------+
    //| DOM abstract order class                                         |
    //+------------------------------------------------------------------+
    class CMarketBookOrd : public CBaseObj
      {
    private:
       int               m_digits;                                       // Number of decimal places
       long              m_long_prop[MBOOK_ORD_PROP_INTEGER_TOTAL];      // Integer properties
       double            m_double_prop[MBOOK_ORD_PROP_DOUBLE_TOTAL];     // Real properties
       string            m_string_prop[MBOOK_ORD_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_MBOOK_ORD_PROP_DOUBLE property)  const { return(int)property-MBOOK_ORD_PROP_INTEGER_TOTAL;                              }
       int               IndexProp(ENUM_MBOOK_ORD_PROP_STRING property)  const { return(int)property-MBOOK_ORD_PROP_INTEGER_TOTAL-MBOOK_ORD_PROP_DOUBLE_TOTAL;  }
    
    public:
    //--- Set object's (1) integer, (2) real and (3) string properties
       void              SetProperty(ENUM_MBOOK_ORD_PROP_INTEGER property,long value)   { this.m_long_prop[property]=value;                      }
       void              SetProperty(ENUM_MBOOK_ORD_PROP_DOUBLE property,double value)  { this.m_double_prop[this.IndexProp(property)]=value;    }
       void              SetProperty(ENUM_MBOOK_ORD_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_MBOOK_ORD_PROP_INTEGER property)        const { return this.m_long_prop[property];                     }
       double            GetProperty(ENUM_MBOOK_ORD_PROP_DOUBLE property)         const { return this.m_double_prop[this.IndexProp(property)];   }
       string            GetProperty(ENUM_MBOOK_ORD_PROP_STRING property)         const { return this.m_string_prop[this.IndexProp(property)];   }
    //--- Return itself
       CMarketBookOrd   *GetObject(void)                                                { return &this;}
    
    //--- Return the flag of the object supporting this property
       virtual bool      SupportProperty(ENUM_MBOOK_ORD_PROP_INTEGER property)          { return true; }
       virtual bool      SupportProperty(ENUM_MBOOK_ORD_PROP_DOUBLE property)           { return true; }
       virtual bool      SupportProperty(ENUM_MBOOK_ORD_PROP_STRING property)           { return true; }
    
    //--- Get description of (1) integer, (2) real and (3) string properties
       string            GetPropertyDescription(ENUM_MBOOK_ORD_PROP_INTEGER property);
       string            GetPropertyDescription(ENUM_MBOOK_ORD_PROP_DOUBLE property);
       string            GetPropertyDescription(ENUM_MBOOK_ORD_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(void);
       
    //--- Compare CMarketBookOrd objects by all possible properties (to sort the lists by a specified order object property)
       virtual int       Compare(const CObject *node,const int mode=0) const;
    //--- Compare CMarketBookOrd objects by all properties (to search for equal request objects)
       bool              IsEqual(CMarketBookOrd* compared_req) const;
       
    //--- Default constructor
                         CMarketBookOrd(){;}
    protected:
    //--- Protected parametric constructor
                         CMarketBookOrd(const ENUM_MBOOK_ORD_STATUS status,const MqlBookInfo &book_info,const string symbol);
                         
    public:
    //+-------------------------------------------------------------------+ 
    //|Methods of a simplified access to the DOM request object properties|
    //+-------------------------------------------------------------------+
    //--- Return order (1) status, (2) type and (3) order volume
       ENUM_MBOOK_ORD_STATUS Status(void)        const { return (ENUM_MBOOK_ORD_STATUS)this.GetProperty(MBOOK_ORD_PROP_STATUS);   }
       ENUM_BOOK_TYPE    TypeOrd(void)           const { return (ENUM_BOOK_TYPE)this.GetProperty(MBOOK_ORD_PROP_TYPE);            }
       long              Volume(void)            const { return this.GetProperty(MBOOK_ORD_PROP_VOLUME);                          }
    //--- Return (1) the price and (2) extended accuracy order volume
       double            Price(void)             const { return this.GetProperty(MBOOK_ORD_PROP_PRICE);                           }
       double            VolumeReal(void)        const { return this.GetProperty(MBOOK_ORD_PROP_VOLUME_REAL);                     }
    //--- Return (1) order symbol and (2) symbol's Digits
       string            Symbol(void)            const { return this.GetProperty(MBOOK_ORD_PROP_SYMBOL);                          }
       int               Digits()                const { return this.m_digits;                                                    }
       
    //--- Return the description of order  (1) type (ENUM_BOOK_TYPE) and (2) status (ENUM_MBOOK_ORD_STATUS)
       virtual string    TypeDescription(void)   const { return this.StatusDescription();                                         }
       string            StatusDescription(void) const;
    
      };
    //+------------------------------------------------------------------+
    
    

    Der Aufbau der Klasse ist absolut identisch mit anderen Klassen von Bibliotheksobjekten. Ich habe sie schon oft erwähnt. Die ausführlichen Beschreibungen finden Sie im ersten und nachfolgenden Artikel.

    Werfen wir einen Blick auf die Implementierung der Klassenmethoden.

    Im parametrischen Konstruktor der geschlossenen Klasse setzen wir alle Objekteigenschaften gemäß der vom DOM an den Konstruktor übergebenen Auftragsstruktur:

    //+------------------------------------------------------------------+
    //| Parametric constructor                                           |
    //+------------------------------------------------------------------+
    CMarketBookOrd::CMarketBookOrd(const ENUM_MBOOK_ORD_STATUS status,const MqlBookInfo &book_info,const string symbol)
      {
    //--- Save symbol’s Digits
       this.m_digits=(int)::SymbolInfoInteger(symbol,SYMBOL_DIGITS);
    //--- Save integer object properties
       this.SetProperty(MBOOK_ORD_PROP_STATUS,status);
       this.SetProperty(MBOOK_ORD_PROP_TYPE,book_info.type);
       this.SetProperty(MBOOK_ORD_PROP_VOLUME,book_info.volume);
    //--- Save real object properties
       this.SetProperty(MBOOK_ORD_PROP_PRICE,book_info.price);
       this.SetProperty(MBOOK_ORD_PROP_VOLUME_REAL,book_info.volume_real);
    //--- Save additional object properties
       this.SetProperty(MBOOK_ORD_PROP_SYMBOL,(symbol==NULL || symbol=="" ? ::Symbol() : symbol));
      }
    //+------------------------------------------------------------------+
    
    

    Der Konstruktor erhält beim Anlegen eines neuen DOM-Auftragsobjekts auch den in Nachfolgeobjekten der Klasse angegebenen Auftragsstatus.

    Die Methode des Vergleichs zweier CMarketBookOrd-Objekte anhand einer angegebenen Eigenschaft zur Definition der Gleichheit der angegebenen Eigenschaften zweier Objekte:

    //+------------------------------------------------------------------+
    //| Compare CMarketBookOrd objects                                   |
    //| by a specified property                                          |
    //+------------------------------------------------------------------+
    int CMarketBookOrd::Compare(const CObject *node,const int mode=0) const
      {
       const CMarketBookOrd *obj_compared=node;
    //--- compare integer properties of two objects
       if(mode<MBOOK_ORD_PROP_INTEGER_TOTAL)
         {
          long value_compared=obj_compared.GetProperty((ENUM_MBOOK_ORD_PROP_INTEGER)mode);
          long value_current=this.GetProperty((ENUM_MBOOK_ORD_PROP_INTEGER)mode);
          return(value_current>value_compared ? 1 : value_current<value_compared ? -1 : 0);
         }
    //--- compare real properties of two objects
       else if(mode<MBOOK_ORD_PROP_DOUBLE_TOTAL+MBOOK_ORD_PROP_INTEGER_TOTAL)
         {
          double value_compared=obj_compared.GetProperty((ENUM_MBOOK_ORD_PROP_DOUBLE)mode);
          double value_current=this.GetProperty((ENUM_MBOOK_ORD_PROP_DOUBLE)mode);
          return(value_current>value_compared ? 1 : value_current<value_compared ? -1 : 0);
         }
    //--- compare string properties of two objects
       else if(mode<MBOOK_ORD_PROP_DOUBLE_TOTAL+MBOOK_ORD_PROP_INTEGER_TOTAL+MBOOK_ORD_PROP_STRING_TOTAL)
         {
          string value_compared=obj_compared.GetProperty((ENUM_MBOOK_ORD_PROP_STRING)mode);
          string value_current=this.GetProperty((ENUM_MBOOK_ORD_PROP_STRING)mode);
          return(value_current>value_compared ? 1 : value_current<value_compared ? -1 : 0);
         }
       return 0;
      }
    //+------------------------------------------------------------------+
    
    

    Die Methode erhalten das Objekt, dessen Eigenschaft mit der gleichen Eigenschaft des aktuellen Objekts verglichen werden soll. Wenn der angegebene Eigenschaftswert des verglichenen Objekts kleiner als der aktuelle ist, wird -1 zurückgegeben, wenn größer +1, wenn die Eigenschaften gleich sind 0.

    Die Methode zum Vergleich zweier CMarketBookOrd-Objekte anhand aller Eigenschaften. Sie ermöglicht die Bestimmung der vollständigen Identität von zwei verglichenen Objekten:

    //+------------------------------------------------------------------+
    //| Compare CMarketBookOrd objects by all properties                 |
    //+------------------------------------------------------------------+
    bool CMarketBookOrd::IsEqual(CMarketBookOrd *compared_obj) const
      {
       int beg=0, end=MBOOK_ORD_PROP_INTEGER_TOTAL;
       for(int i=beg; i<end; i++)
         {
          ENUM_MBOOK_ORD_PROP_INTEGER prop=(ENUM_MBOOK_ORD_PROP_INTEGER)i;
          if(this.GetProperty(prop)!=compared_obj.GetProperty(prop)) return false; 
         }
       beg=end; end+=MBOOK_ORD_PROP_DOUBLE_TOTAL;
       for(int i=beg; i<end; i++)
         {
          ENUM_MBOOK_ORD_PROP_DOUBLE prop=(ENUM_MBOOK_ORD_PROP_DOUBLE)i;
          if(this.GetProperty(prop)!=compared_obj.GetProperty(prop)) return false; 
         }
       beg=end; end+=MBOOK_ORD_PROP_STRING_TOTAL;
       for(int i=beg; i<end; i++)
         {
          ENUM_MBOOK_ORD_PROP_STRING prop=(ENUM_MBOOK_ORD_PROP_STRING)i;
          if(this.GetProperty(prop)!=compared_obj.GetProperty(prop)) return false; 
         }
       return true;
      }
    //+------------------------------------------------------------------+
    
    

    Jede nachfolgende Eigenschaft von zwei Objekten wird hier einzeln verglichen. Wenn die Objekte nicht gleich sind, wird false zurückgegeben. Nachdem die Überprüfung der Gleichheit aller Eigenschaften zweier Objekte abgeschlossen ist und kein false erhalten wurde, wird true zurückgegeben — beide Objekte sind vollständig identisch.

    Die Methode, die alle Objekteigenschaften ins Journal schreibt:

    //+------------------------------------------------------------------+
    //| Display object properties in the journal                         |
    //+------------------------------------------------------------------+
    void CMarketBookOrd::Print(const bool full_prop=false)
      {
       ::Print("============= ",CMessage::Text(MSG_LIB_PARAMS_LIST_BEG)," (",this.Header(),") =============");
       int beg=0, end=MBOOK_ORD_PROP_INTEGER_TOTAL;
       for(int i=beg; i<end; i++)
         {
          ENUM_MBOOK_ORD_PROP_INTEGER prop=(ENUM_MBOOK_ORD_PROP_INTEGER)i;
          if(!full_prop && !this.SupportProperty(prop)) continue;
          ::Print(this.GetPropertyDescription(prop));
         }
       ::Print("------");
       beg=end; end+=MBOOK_ORD_PROP_DOUBLE_TOTAL;
       for(int i=beg; i<end; i++)
         {
          ENUM_MBOOK_ORD_PROP_DOUBLE prop=(ENUM_MBOOK_ORD_PROP_DOUBLE)i;
          if(!full_prop && !this.SupportProperty(prop)) continue;
          ::Print(this.GetPropertyDescription(prop));
         }
       ::Print("------");
       beg=end; end+=MBOOK_ORD_PROP_STRING_TOTAL;
       for(int i=beg; i<end; i++)
         {
          ENUM_MBOOK_ORD_PROP_STRING prop=(ENUM_MBOOK_ORD_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");
      }
    //+------------------------------------------------------------------+
    
    

    Text-Beschreibungen jeder nachfolgenden Eigenschaft werden in drei Schleifen nach Integer-, Real- und String-Objekteigenschaften angezeigt.

    Die Methoden geben die Beschreibungen der angegebenen Objekteigenschaften integer, real und string zurück:

    //+------------------------------------------------------------------+
    //| Return description of object's integer property                  |
    //+------------------------------------------------------------------+
    string CMarketBookOrd::GetPropertyDescription(ENUM_MBOOK_ORD_PROP_INTEGER property)
      {
       return
         (
          property==MBOOK_ORD_PROP_STATUS        ?  CMessage::Text(MSG_ORD_STATUS)+
             (!this.SupportProperty(property)    ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
              ": "+this.StatusDescription()
             )  :
          property==MBOOK_ORD_PROP_TYPE          ?  CMessage::Text(MSG_ORD_TYPE)+
             (!this.SupportProperty(property)    ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
              ": "+this.TypeDescription()
             )  :
          property==MBOOK_ORD_PROP_VOLUME        ?  CMessage::Text(MSG_MBOOK_ORD_VOLUME)+
             (!this.SupportProperty(property)    ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
              ": "+(string)this.GetProperty(property)
             )  :
          ""
         );
      }
    //+------------------------------------------------------------------+
    //| Return description of object's real property                     |
    //+------------------------------------------------------------------+
    string CMarketBookOrd::GetPropertyDescription(ENUM_MBOOK_ORD_PROP_DOUBLE property)
      {
       int dg=(this.m_digits>0 ? this.m_digits : 1);
       return
         (
          property==MBOOK_ORD_PROP_PRICE         ?  CMessage::Text(MSG_LIB_TEXT_REQUEST_PRICE)+
             (!this.SupportProperty(property)    ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
              ": "+::DoubleToString(this.GetProperty(property),dg)
             )  :
          property==MBOOK_ORD_PROP_VOLUME_REAL   ?  CMessage::Text(MSG_MBOOK_ORD_VOLUME_REAL)+
             (!this.SupportProperty(property)    ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
              ": "+::DoubleToString(this.GetProperty(property),dg)
             )  :
          ""
         );
      }
    //+------------------------------------------------------------------+
    //| Return description of object's string property                   |
    //+------------------------------------------------------------------+
    string CMarketBookOrd::GetPropertyDescription(ENUM_MBOOK_ORD_PROP_STRING property)
      {
       return(property==MBOOK_ORD_PROP_SYMBOL ? CMessage::Text(MSG_LIB_PROP_SYMBOL)+": \""+this.GetProperty(property)+"\"" : "");
      }
    //+------------------------------------------------------------------+
    
    

    Jede der Methoden erhält die Eigenschaft, deren Beschreibung zurückgegeben werden soll. Abhängig von der an die Methode übergebenen Eigenschaft wird eine Zeichenkette erstellt, die schließlich von der Methode zurückgegeben wird.

    Die Methode gibt einen kurzen Objektnamen zurück:

    //+------------------------------------------------------------------+
    //| Return the object short name                                     |
    //+------------------------------------------------------------------+
    string CMarketBookOrd::Header(void)
      {
       return this.TypeDescription()+" \""+this.Symbol()+"\"";
      }
    //+------------------------------------------------------------------+
    
    

    Die Methode gibt die Zeichenkette zurück, die aus der Beschreibung eines Auftragstyps und seinem Symbol besteht.

    Die Methode zeigt die kurze Objektbeschreibung im Journal an:

    //+------------------------------------------------------------------+
    //| Display a short description of the object in the journal         |
    //+------------------------------------------------------------------+
    void CMarketBookOrd::PrintShort(void)
      {
       ::Print(this.Header());
      }
    //+------------------------------------------------------------------+
    
    

    Die Methode zeigt einfach die von der vorherigen Methode erstellte Zeichenkette im Journal an.

    Die Methode gibt die Beschreibung des Auftragsstatus im DOM zurück:

    //+------------------------------------------------------------------+
    //| Return the order status description in DOM                       |
    //+------------------------------------------------------------------+
    string CMarketBookOrd::StatusDescription(void) const
      {
       return
         (
          Status()==MBOOK_ORD_STATUS_SELL  ?  CMessage::Text(MSG_MBOOK_ORD_STATUS_SELL) :
          Status()==MBOOK_ORD_STATUS_BUY   ?  CMessage::Text(MSG_MBOOK_ORD_STATUS_BUY)  :
          ""
         );
      }
    //+------------------------------------------------------------------+
    
    

    Abhängig vom Auftrag "Status" wird der Text mit der Statusbeschreibung zurückgegeben.

    Dies ist die gesamte Klasse des Auftragsobjekts im DOM.

    Nun müssen wir vier Klassen erstellen, die von diesem abstrakten Auftragsobjekt erben. Die Nachfolgeklassen werden verwendet, um neue Auftragsobjekte aus DOM zu erzeugen. Der Status des erzeugten Auftragsobjekts wird in der Initialisierungsliste des Konstruktors der Nachfolgeklasse abhängig vom Auftragstyp angegeben.


    Abgeleitete Klassen der abstrakten Klasse des Auftragsobjekts

    Wir erstellen in \MQL5\Include\DoEasy\Objects\Book\ die Datei MarketBookBuy.mqh für die Klasse CMarketBookBuy. Die neu erstellte abstrakte Auftragsklasse CMarketBookOrd soll eine übergeordnete Klasse sein:

    //+------------------------------------------------------------------+
    //|                                                MarketBookBuy.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 "MarketBookOrd.mqh"
    //+------------------------------------------------------------------+
    //| Buy order in DOM                                                 |
    //+------------------------------------------------------------------+
    class CMarketBookBuy : public CMarketBookOrd
      {
    private:
    
    public:
       //--- Constructor
                         CMarketBookBuy(const string symbol,const MqlBookInfo &book_info) :
                            CMarketBookOrd(MBOOK_ORD_STATUS_BUY,book_info,symbol) {}
       //--- Supported order properties (1) real, (2) integer
       virtual bool      SupportProperty(ENUM_MBOOK_ORD_PROP_DOUBLE property);
       virtual bool      SupportProperty(ENUM_MBOOK_ORD_PROP_INTEGER property);
    //--- Return the object short name
       virtual string    Header(void);
    //--- Return the description of order type (ENUM_BOOK_TYPE)
       virtual string    TypeDescription(void);
      };
    //+------------------------------------------------------------------+
    //| Return 'true' if an order supports a passed                      |
    //| integer property, otherwise return 'false'                       |
    //+------------------------------------------------------------------+
    bool CMarketBookBuy::SupportProperty(ENUM_MBOOK_ORD_PROP_INTEGER property)
      {
       return true;
      }
    //+------------------------------------------------------------------+
    //| Return 'true' if an order supports a passed                      |
    //| real property, otherwise return 'false'                          |
    //+------------------------------------------------------------------+
    bool CMarketBookBuy::SupportProperty(ENUM_MBOOK_ORD_PROP_DOUBLE property)
      {
       return true;
      }
    //+------------------------------------------------------------------+
    //| Return the object short name                                     |
    //+------------------------------------------------------------------+
    string CMarketBookBuy::Header(void)
      {
       return CMessage::Text(MSG_MBOOK_ORD_TYPE_BUY)+" \""+this.Symbol()+
              "\": "+::DoubleToString(this.Price(),this.Digits())+" ["+::DoubleToString(this.VolumeReal(),2)+"]";
      }
    //+------------------------------------------------------------------+
    //| Return the description of order type                             |
    //+------------------------------------------------------------------+
    string CMarketBookBuy::TypeDescription(void)
      {
       return CMessage::Text(MSG_MBOOK_ORD_TYPE_BUY);
      }
    //+------------------------------------------------------------------+
    
    

    Wenn wir ein neues DOM-Auftragsobjekt erstellen, setzen wir die "Kaufseite" im Konstruktor der übergeordneten Klasse.

    In den virtuellen Methoden Rückgabe des Flags der Unterstützung der Integer- und Real-Eigenschaften, Rückgabe true — jede Eigenschaft wird vom Objekt unterstützt.

    In der virtuellen Methode wird der Kurznamen des DOM-Auftragsobjekts als Zeichenkette in folgendem Format zurückgegeben

    Typ "Symbol": Preis [VolumeReal]

    Zum Beispiel:

    "EURUSD" buy order: 1.20123 [10.00]

    In der virtuellen Methode wird die Beschreibung des DOM-Auftragsobjekttyps die Zeichenkette "Buy order" (Kaufauftrag) zurückgegeben.

    Die übrigen drei von der abstrakten DOM-Basisklasse für Aufträge abgeleiteten Klassen sind bis auf den Auftragsstatus identisch mit der betrachteten Klasse. Jeder Klassenkonstruktor verfügt über den Status, der dem beschriebenen Auftragsobjekt entspricht, und über virtuelle Methoden, die die Zeichenketten zurückgeben, die dem Typ des DOM-Auftrags entsprechen, der von jedem der Objekte beschrieben wird. Alle diese Klassen befinden sich in demselben Ordner wie die oben beschriebene Klasse. Ich zeige hier ihre Auflistungen, damit Sie ihre virtuellen Methoden analysieren und vergleichen können.

    MarketBookBuyMarket.mqh:

    //+------------------------------------------------------------------+
    //|                                          MarketBookBuyMarket.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 "MarketBookOrd.mqh"
    //+------------------------------------------------------------------+
    //| Buy order by Market in DOM                                       |
    //+------------------------------------------------------------------+
    class CMarketBookBuyMarket : public CMarketBookOrd
      {
    private:
    
    public:
       //--- Constructor
                         CMarketBookBuyMarket(const string symbol,const MqlBookInfo &book_info) :
                            CMarketBookOrd(MBOOK_ORD_STATUS_BUY,book_info,symbol) {}
       //--- Supported order properties (1) real, (2) integer
       virtual bool      SupportProperty(ENUM_MBOOK_ORD_PROP_DOUBLE property);
       virtual bool      SupportProperty(ENUM_MBOOK_ORD_PROP_INTEGER property);
    //--- Return the object short name
       virtual string    Header(void);
    //--- Return the description of order type (ENUM_BOOK_TYPE)
       virtual string    TypeDescription(void);
      };
    //+------------------------------------------------------------------+
    //| Return 'true' if an order supports a passed                      |
    //| integer property, otherwise return 'false'                       |
    //+------------------------------------------------------------------+
    bool CMarketBookBuyMarket::SupportProperty(ENUM_MBOOK_ORD_PROP_INTEGER property)
      {
       return true;
      }
    //+------------------------------------------------------------------+
    //| Return 'true' if an order supports a passed                      |
    //| real property, otherwise return 'false'                          |
    //+------------------------------------------------------------------+
    bool CMarketBookBuyMarket::SupportProperty(ENUM_MBOOK_ORD_PROP_DOUBLE property)
      {
       return true;
      }
    //+------------------------------------------------------------------+
    //| Return the object short name                                     |
    //+------------------------------------------------------------------+
    string CMarketBookBuyMarket::Header(void)
      {
       return CMessage::Text(MSG_MBOOK_ORD_TYPE_BUY_MARKET)+" \""+this.Symbol()+
              "\": "+::DoubleToString(this.Price(),this.Digits())+" ["+::DoubleToString(this.VolumeReal(),2)+"]";
      }
    //+------------------------------------------------------------------+
    //| Return the description of order type                             |
    //+------------------------------------------------------------------+
    string CMarketBookBuyMarket::TypeDescription(void)
      {
       return CMessage::Text(MSG_MBOOK_ORD_TYPE_BUY_MARKET);
      }
    //+------------------------------------------------------------------+
    
    

    MarketBookSell.mqh:

    //+------------------------------------------------------------------+
    //|                                               MarketBookSell.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 "MarketBookOrd.mqh"
    //+------------------------------------------------------------------+
    //| Sell order in DOM                                                |
    //+------------------------------------------------------------------+
    class CMarketBookSell : public CMarketBookOrd
      {
    private:
    
    public:
       //--- Constructor
                         CMarketBookSell(const string symbol,const MqlBookInfo &book_info) :
                            CMarketBookOrd(MBOOK_ORD_STATUS_SELL,book_info,symbol) {}
       //--- Supported order properties (1) real, (2) integer
       virtual bool      SupportProperty(ENUM_MBOOK_ORD_PROP_DOUBLE property);
       virtual bool      SupportProperty(ENUM_MBOOK_ORD_PROP_INTEGER property);
    //--- Return the object short name
       virtual string    Header(void);
    //--- Return the description of order type (ENUM_BOOK_TYPE)
       virtual string    TypeDescription(void);
      };
    //+------------------------------------------------------------------+
    //| Return 'true' if an order supports a passed                      |
    //| integer property, otherwise return 'false'                       |
    //+------------------------------------------------------------------+
    bool CMarketBookSell::SupportProperty(ENUM_MBOOK_ORD_PROP_INTEGER property)
      {
       return true;
      }
    //+------------------------------------------------------------------+
    //| Return 'true' if an order supports a passed                      |
    //| real property, otherwise return 'false'                          |
    //+------------------------------------------------------------------+
    bool CMarketBookSell::SupportProperty(ENUM_MBOOK_ORD_PROP_DOUBLE property)
      {
       return true;
      }
    //+------------------------------------------------------------------+
    //| Return the object short name                                     |
    //+------------------------------------------------------------------+
    string CMarketBookSell::Header(void)
      {
       return CMessage::Text(MSG_MBOOK_ORD_TYPE_SELL)+" \""+this.Symbol()+
              "\": "+::DoubleToString(this.Price(),this.Digits())+" ["+::DoubleToString(this.VolumeReal(),2)+"]";
      }
    //+------------------------------------------------------------------+
    //| Return the description of order type                             |
    //+------------------------------------------------------------------+
    string CMarketBookSell::TypeDescription(void)
      {
       return CMessage::Text(MSG_MBOOK_ORD_TYPE_SELL);
      }
    //+------------------------------------------------------------------+
    
    

    MarketBookSellMarket.mqh:

    //+------------------------------------------------------------------+
    //|                                         MarketBookSellMarket.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 "MarketBookOrd.mqh"
    //+------------------------------------------------------------------+
    //| Sell order by Market in DOM                                      |
    //+------------------------------------------------------------------+
    class CMarketBookSellMarket : public CMarketBookOrd
      {
    private:
    
    public:
       //--- Constructor
                         CMarketBookSellMarket(const string symbol,const MqlBookInfo &book_info) :
                            CMarketBookOrd(MBOOK_ORD_STATUS_SELL,book_info,symbol) {}
       //--- Supported order properties (1) real, (2) integer
       virtual bool      SupportProperty(ENUM_MBOOK_ORD_PROP_DOUBLE property);
       virtual bool      SupportProperty(ENUM_MBOOK_ORD_PROP_INTEGER property);
    //--- Return the object short name
       virtual string    Header(void);
    //--- Return the description of order type (ENUM_BOOK_TYPE)
       virtual string    TypeDescription(void);
      };
    //+------------------------------------------------------------------+
    //| Return 'true' if an order supports a passed                      |
    //| integer property, otherwise return 'false'                       |
    //+------------------------------------------------------------------+
    bool CMarketBookSellMarket::SupportProperty(ENUM_MBOOK_ORD_PROP_INTEGER property)
      {
       return true;
      }
    //+------------------------------------------------------------------+
    //| Return 'true' if an order supports a passed                      |
    //| real property, otherwise return 'false'                          |
    //+------------------------------------------------------------------+
    bool CMarketBookSellMarket::SupportProperty(ENUM_MBOOK_ORD_PROP_DOUBLE property)
      {
       return true;
      }
    //+------------------------------------------------------------------+
    //| Return the object short name                                     |
    //+------------------------------------------------------------------+
    string CMarketBookSellMarket::Header(void)
      {
       return CMessage::Text(MSG_MBOOK_ORD_TYPE_SELL_MARKET)+" \""+this.Symbol()+
              "\": "+::DoubleToString(this.Price(),this.Digits())+" ["+::DoubleToString(this.VolumeReal(),2)+"]";
      }
    //+------------------------------------------------------------------+
    //| Return the description of order type                             |
    //+------------------------------------------------------------------+
    string CMarketBookSellMarket::TypeDescription(void)
      {
       return CMessage::Text(MSG_MBOOK_ORD_TYPE_SELL_MARKET);
      }
    //+------------------------------------------------------------------+
    
    

    Das ist alles, was ich im aktuellen Artikel tun wollte.


    Test

    Um den Test durchzuführen, verwende ich den EA aus dem vorherigen Artikel und speichere sie in \MQL5\Experts\TestDoEasy\Part63\ als TestDoEasyPart63.mq5.

    Nach dem Start des EA abonnieren wir DOMs von Symbolen, die in den Einstellungen für die Arbeit angegeben sind. Alle Ereignisse mit DOMs werden im OnBookEvent() registriert. Entsprechend stellen wir in dieser Funktion sicher, dass das Ereignis auf dem aktuellen Symbol aufgetreten ist. Außerdem holen wir uns den DOM-Snapshot und speichern alle vorhandenen Aufträge nach Preiswerten sortiert in der Liste ab. Als Nächstes zeigen wir den allerersten und den allerletzten Auftrag aus der Liste in den Chart-Kommentaren an. Wir werden also zwei extreme DOM-Aufträge anzeigen — einen Verkaufs- und einen Kaufauftrag. Im Journal zeigen wir die Liste aller erhaltenen DOM-Aufträge bei der allerersten OnBookEvent()-Aktivierung an.

    Damit der EA die neu erstellten Klassen sehen kann, binden wir sie in die EA-Datei ein (derzeit kann nicht auf sie vom Hauptobjekt der CEngine-Bibliothek zugegriffen werden):

    //+------------------------------------------------------------------+
    //|                                             TestDoEasyPart63.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\Book\MarketBookBuy.mqh>
    #include <DoEasy\Objects\Book\MarketBookSell.mqh>
    #include <DoEasy\Objects\Book\MarketBookBuyMarket.mqh>
    #include <DoEasy\Objects\Book\MarketBookSellMarket.mqh>
    //--- enums
    
    

    Nun müssen wir die Funktion OnBookEvent() im EA erstellen und die Behandlung eines DOM-Ereignisses darin implementieren:

    //+------------------------------------------------------------------+
    //| OnBookEvent function                                             |
    //+------------------------------------------------------------------+
    void OnBookEvent(const string& symbol)
      {
       static bool first=true;
       //--- Get a symbol object
       CSymbol *sym=engine.GetSymbolCurrent();
       //--- If failed to get a symbol object or it is not subscribed to DOM, exit
       if(sym==NULL || !sym.BookdepthSubscription()) return;
       //--- create the list for storing DOM order objects
       CArrayObj *list=new CArrayObj();
       if(list==NULL) return;
       //--- Work by the current symbol
       if(symbol==sym.Name())
         {
          //--- Declare the DOM structure array
          MqlBookInfo book_array[];
          //--- Get DOM entries to the structure array
          if(!MarketBookGet(sym.Name(),book_array))
             return;
          //--- clear the list
          list.Clear();
          //--- In the loop by the structure array
          int total=ArraySize(book_array);
          for(int i=0;i<total;i++)
            {
             //--- Create order objects of the current DOM snapshot depending on the order type
             CMarketBookOrd *mbook_ord=NULL;
             switch(book_array[i].type)
               {
                case BOOK_TYPE_BUY         : mbook_ord=new CMarketBookBuy(sym.Name(),book_array[i]);         break;
                case BOOK_TYPE_SELL        : mbook_ord=new CMarketBookSell(sym.Name(),book_array[i]);        break;
                case BOOK_TYPE_BUY_MARKET  : mbook_ord=new CMarketBookBuyMarket(sym.Name(),book_array[i]);   break;
                case BOOK_TYPE_SELL_MARKET : mbook_ord=new CMarketBookSellMarket(sym.Name(),book_array[i]);  break;
                default: break;
               }
             if(mbook_ord==NULL)
                continue;
             //--- Set the sorted list flag for the list (by the price value) and add the current order object to it
             list.Sort(SORT_BY_MBOOK_ORD_PRICE);
             if(!list.InsertSort(mbook_ord))
                delete mbook_ord;
            }
          //--- Get the very first and last DOM order objects from the list
          CMarketBookOrd *ord_0=list.At(0);
          CMarketBookOrd *ord_N=list.At(list.Total()-1);
          if(ord_0==NULL || ord_N==NULL) return;
          //--- Display the size of the current DOM snapshot in the chart comment, 
          //--- the maximum number of displayed orders in DOM for a symbol and
          //--- the highest and lowest orders of the current DOM snapshot
          Comment
            (
             DFUN,sym.Name(),": ",TimeMSCtoString(sym.Time()),", array total=",total,", book size=",sym.TicksBookdepth(),", list.Total: ",list.Total(),"\n",
             "Max: ",ord_N.Header(),"\nMin: ",ord_0.Header()
            );
          //--- Display the first DOM snapshot in the journal
          if(first)
            {
             for(int i=list.Total()-1;i>WRONG_VALUE;i--)
               {
                CMarketBookOrd *ord=list.At(i);
                ord.PrintShort();
               }
             first=false;
            }
         }
       //--- Delete the created list
       delete list;
      }
    //+------------------------------------------------------------------+
    
    

    Die Code-Kommentare enthalten alle Details. Wenn Sie Fragen haben, können Sie diese gerne in den Kommentaren stellen.

    Kompilieren Sie den EA und starten Sie ihn auf einem Symbolchart, nachdem Sie in den Einstellungen festgelegt haben, dass die beiden angegebenen Symbole und der aktuelle Zeitrahmen verwendet werden sollen.


    Nachdem der EA gestartet wurde und das erste DOM-Änderungsereignis eingetroffen ist, werden die Parameter der aktuellen DOM-Snapshot-Liste in den Chart-Kommentaren zusammen mit zwei Aufträgen angezeigt - dem höchsten Kauf- und dem niedrigsten Verkaufsauftrag:


    Das Journal zeigt die Liste aller Aufträge des aktuellen DOM-Snapshots an:

    Subscribed to Depth of Market  AUDUSD
    Subscribed to Depth of Market  EURUSD
    Library initialization time: 00:00:11.391
    "EURUSD" sell order: 1.20250 [250.00]
    "EURUSD" sell order: 1.20245 [100.00]
    "EURUSD" sell order: 1.20244 [50.00]
    "EURUSD" sell order: 1.20242 [36.00]
    "EURUSD" buy order: 1.20240 [16.00]
    "EURUSD" buy order: 1.20239 [20.00]
    "EURUSD" buy order: 1.20238 [50.00]
    "EURUSD" buy order: 1.20236 [100.00]
    "EURUSD" buy order: 1.20232 [250.00]
    
    


    Was kommt als Nächstes?

    Im nächsten Artikel werden wir damit fortfahren, die Funktionen für die Arbeit mit dem DOM zu 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.
    Die Klassen für die Arbeit mit dem DOM befinden sich in der Entwicklung, daher wird ihre Verwendung in benutzerdefinierten Programmen in diesem Stadium nicht empfohlen.
    Schreiben Sie Ihre Fragen und Vorschläge in den Kommentaren.

    Zurück zum Inhalt

    *Frühere Artikel dieser Serie:

    Zeitreihen in der Bibliothek DoEasy (Teil 59): Objekt zum Speichern der Daten eines Ticks
    Preise in der DoEasy-Bibliothek (Teil 60): Listen von Serien mit Symbol-Tickdaten
    Preise in der DoEasy-Bibliothek (Teil 61): Kollektion der Tickserien eines Symbols
    Preise in der DoEasy-Bibliothek (Teil 62): Aktualisieren der Tick-Serien in Echtzeit, Vorbereitung für die Arbeit mit Markttiefe