English Русский Español Deutsch 日本語 Português
DoEasy 函数库中的价格(第六十三部分):市场深度及其抽象请求类

DoEasy 函数库中的价格(第六十三部分):市场深度及其抽象请求类

MetaTrader 5示例 | 5 四月 2021, 08:22
3 218 0
Artyom Trishkin
Artyom Trishkin

内容


概述

在本文中,我将着手实现操控市场深度的功能。 从概念上讲,操控 DOM 的类与以前实现的所有函数库类都没啥区别。 与此同时,我们将拥有一个 DOM 特征数据的模型,其中包含 DOM 中存储的有关订单数据信息。激活 OnBookEvent() 处理程序时,可由 MarketBookGet() 函数获取数据。 在 DOM 发生任何变化的情况下,处理程序中会为订阅 DOM 事件的每个品种激活一个事件。

故此,DOM 类结构如下:

  1. DOM 订单对象类 — 当某个品种触发了 OnBookEvent() 处理程序,可从 DOM 获得多个订单,该对象描述的是其中一个订单的数据;
  2. DOM 模型对象类 — 在单次 OnBookEvent() 处理程序激活时,从 DOM 并发获得所有订单数据,该对象描述的是针对其中一个品种的所有订单数据 — 构成当前 DOM 模型的对象集合 p1;
  3. 时间序列类由单一品种的 p2 对象序列组成,它是在每次 OnBookEvent() 激活时输入到时间序列列表之中的;
  4. DOM 事件里可订阅的所有用到品种的 DOM 数据的时间序列集合类。

今天,我将实现订单对象类(1),并测试当前品种激活 OnBookEvent() 时获取 DOM 数据。

每个订单的属性都在 MqlBookInfo 结构中设置,提供 DOM 所含的数据:

  • 订单类型来自 ENUM_BOOK_TYPE 枚举
  • 订单价格
  • 订单交易量
  • 精度更高的订单交易量

DOM 可能有四种订单类型(来自 ENUM_BOOK_TYPE 枚举):

  • 卖单
  • 市价卖单
  • 买单
  • 市价买单

正如我们所见,有四种订单类型 — 两种买入,和两种卖出。 为了将所有类型的订单分为两部分,我们应该在现有的属性上再添加一个属性 — 指示其方向的订单状态 — 买单或卖单。 这能令我们迅速将所有订单划分为两部分 — 供给和需求。

该对象将令单个 DOM 请求类似于订单对象(以及许多其他函数库对象)— 我们会有一个基准 DOM 抽象订单对象,和四个含有订单类型规则的衍生对象。 此类对象的构造概念,已在函数库开发之初的第一篇第二篇文章里就研究过了。

    在实现操控 DOM 的类之前,需添加新的函数库消息,并略微改进即时报价数据对象类。 并在 \MQL5\Include\DoEasy\Data.mqh 里加入新消息的索引:

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

    以及与新添加索引相对应的消息文本:

       {"В окно \"Обзор рынка\" добавлен символ","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"},
       
      };
    //+---------------------------------------------------------------------+
    
    

    在品种对象类的 \MQL5\Include\DoEasy\Objects\Symbols\Symbol.mqh 文件中添加与订阅 DOM 有关的错误显示消息:

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

    对于取消订阅时执行相同的操作:

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

    来自 \MQL5\Include\DoEasy\Objects\Ticks\TickSeries.mqh 中即时报价序列类的更新方法,从其中删除在品种图表上显示调试注释,我们在上一篇文章留作测试:

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

    最后的即时报价时间立即设置在 m_last_time 变量中,如此这般目的在于在上一篇文章里,我需要将验证数据显示在品种图表注释当中,其中包含的前一次和当前的即时报价时间。 现在我们不需要它了,时间会被立即保存在变量中:

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


    市场深度中的抽象订单对象类

    与所有函数库对象一样,定义对象属性常量均有相应的枚举集合,我们也需要为 DOM 订单创建整数型、实数型和字符串型对象属性的枚举。

    在 \MQL5\Include\DoEasy\Defines.mqh 以下位置添加 DOM 订单对象属性和参数的枚举。 鉴于我不打算实现处理每个 DOM 订单的事件模型(在某时刻,订单簿会显示所有订单的当前状态,它们的变化会引发下一个状态,并在下次激活 OnBookEvent() 时处理,只需在 DOM 事件的最后一个代码之后添加指定下一个事件的代码常量即可,如此只需维护所有对象的常量标识,令它们具有相同的形式即可:

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

    定义枚举指定单个 DOM 订单的两种可能状态 — 买方或卖方:

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

    依据这些属性针对 DOM 的所有订单进行分类,可令我们快速选择属于需求方或供应方的所有 DOM 订单。

    接下来,添加 DOM 订单对象的整数型实数型字符串型属性的枚举:

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

    我们根据创建的属性实现 DOM 订单的可能排序标准的枚举:

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

    现在可创建 DOM 抽象订单对象类。

    在 \MQL5\Include\DoEasy\Objects\ 里,创建一个新的 Book\ 文件夹,其下的 MarketBookOrd.mqh 文件包含 CMarketBookOrd 类,继承自所有 CBaseObj 函数库对象的基准对象

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

    该类的组成与函数库对象的其他类绝对相同。 我经常提到它们。 您可以在第一篇及后续文章中找到详细解说。

    我们来看一下类方法的实现。

    在类的封闭参数构造函数中所有对象属性的设置值均来自 DOM 传递给构造函数的订单结构参数:

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

    创建新的 DOM 订单对象时,构造函数还会接收该类衍生对象中指定的订单状态

    该方法依据指定属性比较两个 CMarketBookOrd 对象,可定义两个对象指定属性的相等性:

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

    该方法接收对象,并与当前对象的相同属性进行比较。 如果所比较对象的指定属性值小于当前对象的属性值,则返回 -1;如果较大,则返回 — +1,如果属性相等,则返回 0。

    该方法比较两个 CMarketBookOrd 对象的所有属性。 它能够判断两个所比较对象是否完全相等:

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

    在此,按顺序逐一比较两个对象的每个属性。 如果对象不等,则返回 false。 在两个对象所有属性的相等性检查完成后,若结果并非 false,则返回 true — 两个对象完全相同。

    该方法在日志中显示所有对象属性:

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

    在三个循环中显示后续每个属性的字符串说明按整数型、实数型和字符串型对象属性。

    该方法返回指定的整数型实数型字符串型对象属性说明的方法:

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

    每个方法都接收需返回其描述的属性。 取决于传递给该方法的属性,创建并最终返回说明字符串。

    该方法返回一个对象名称的简述:

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

    该方法返回由订单类型的描述、极其品种组成的字符串。

    该方法在日志中显示对象简述:

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

    该方法在日志中简单地显示由先前方法创建的字符串。

    该方法返回 DOM 中的订单状态描述:

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

    根据订单“状态”,返回含有状态描述的字符串。

    这就是 DOM 的完整订单对象类。

    现在,我们需要创建四个类,继承自该抽象订单对象。 衍生类将用于创建来自 DOM 的新订单对象。根据订单类型,将在衍生类构造函数的初始化列表中指定需创建的订单对象状态。


    抽象订单对象的衍生类

    在 \MQL5\Include\DoEasy\Objects\Book\ 里,创建包含 CMarketBookBuy 类的 MarketBookBuy.mqh 文件。 新创建的 CMarketBookOrd 抽象订单类将成为父类:

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

    创建新的 DOM 订单对象时,在父类构造函数中设置“买方”

    在虚拟方法中返回支持整数型实数型属性的标志,返回 true — 对象支持每个属性。

    在虚拟方法里返回 DOM 订单对象的简称,返回的字符串格式如下

    Type "Symbol": Price [VolumeReal]

    例如:

    "EURUSD" buy order: 1.20123 [10.00]

    在虚拟方法里返回 DOM 订单对象类型的描述,返回 “Buy order” 字符串。

    除了订单状态,继承自 DOM 抽象订单基类的其余三个类与已研究过的相同。 每个类的构造函数特征是与所描述订单对象的状态对应,其虚拟方法返回与每个对象所描述的 DOM 订单类型相对应的字符串。 所有这些类都与上述类位于同一文件夹当中。 我会在此展示它们的清单,让您分析和比较它们的虚拟方法。

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

    这些就是我在本文中想要做的所有事情。


    测试

    为了执行测试,我们借用上一篇文章中的 EA,并将其保存在 \MQL5\Experts\TestDoEasy\Part63\TestDoEasyPart63.mq5

    启动 EA 之后,按照设置中指定的操作品种,我们订阅 DOM。 所有 DOM 事件都在 OnBookEvent() 处理程序中注册。 相应地,在此处理程序中,我们确保事件已在当前品种上发生。 我们还得到 DOM 快照,并将所有现有订单保存到按价格值排序的列表当中。 接下来,在图表注释中显示列表中的第一笔和最后一笔订单。 因此,我们将显示两端的 DOM 订单 — 买单,卖单各一。 在日志中,首次激活 OnBookEvent() 时显示所有得到的 DOM 订单的列表。

    为了令 EA 能够查看新创建的类,将它们包括在 EA 文件里(当前,无法从 CEngine 函数库主对象访问它们):

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

    现在,我们需要在 EA 中创建 OnBookEvent() 处理程序,并在其中实现 DOM 事件的处理:

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

    代码注释包含所有详细信息。 如果您有任何疑问,请随时在评论中提问。

    编译 EA,在设置中初步定义的品种图表上启动它,它会使用两个指定品种和当前时间帧。


    启动 EA,且第一个 DOM 变化事件到达后,当前 DOM 快照列表的参数将与两笔订单一起显示在图表注释中,最高的出价(Buy)和最低的要价(Ask):


    日志显示当前 DOM 快照的所有订单的列表

    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]
    
    


    下一步是什么?

    在下一篇文章中,我们将继续创建操控 DOM 的功能。

    以下是该函数库当前版本的所有文件,以及 MQL5 的测试 EA 文件,供您测试和下载。
    操控 DOM 的类正在开发当中,因此,在现阶段强烈建议不要在自定义程序中使用它们。
    请您在评论中留下问题和建议。

    返回内容目录

    *该系列的前几篇文章:

    DoEasy 函数库中的价格(第五十九部分):存储一个即时报价数据的对象
    DoEasy 函数库中的价格(第六十部分):品种即时报价数据的序列列表
    DoEasy 函数库中的价格(第六十一部分):品种即时报价序列集合
    DoEasy 函数库中的价格(第六十二部分):实时更新即时报价序列,为操控市场深度做准备

    本文由MetaQuotes Ltd译自俄文
    原文地址: https://www.mql5.com/ru/articles/9010

    附加的文件 |
    MQL5.zip (3891.18 KB)
    神经网络变得轻松(第十一部分):自 GPT 获取 神经网络变得轻松(第十一部分):自 GPT 获取
    也许,GPT-3 是目前已有语言类神经网络中最先进的模型之一,它的最大变体可包含 1750 亿个参数。 当然,我们不打算在家用 PC 上创建如此庞然之物。 然而,我们可以看看在我们的操作中能够采用哪种体系解决方案,以及如何从中受益。
    DoEasy 函数库中的价格(第六十二部分):实时更新即时报价序列,为操控市场深度做准备 DoEasy 函数库中的价格(第六十二部分):实时更新即时报价序列,为操控市场深度做准备
    在本文中,我将实现即时报价数据的实时更新,并为操控市场深度的品种对象类(DOM 本身将在下一篇文章中实现)做准备。
    DoEasy 函数库中的价格(第六十四部分):市场深度,DOM 快照类和快照序列对象 DoEasy 函数库中的价格(第六十四部分):市场深度,DOM 快照类和快照序列对象
    在本文中,我将创建两个类(DOM 快照对象类,和 DOM 快照序列对象类),并测试 DOM 数据序列的创建。
    DoEasy 函数库中的时间序列(第六十一部分):品种即时报价序列集合 DoEasy 函数库中的时间序列(第六十一部分):品种即时报价序列集合
    鉴于程序在其运行时可能会用到不同的品种,因此应为每个品种创建一个单独的列表。 在本文中,我将把这些列表合并到一个即时报价数据集合。 实际上,这将是一个常规列表,基于指向标准库 CObject 类及其衍生类实例指针的动态数组。