
Trabajando con los precios en la biblioteca DoEasy (Parte 63): Profundidad del mercado, clase de orden abstracta de la Profundidad del mercado
Contenido
- Concepto
- Clase del objeto de orden abstracta en la Profundidad del mercado
- Clases herederas del objeto de orden abstracta
- Prueba
- ¿Qué es lo próximo?
Concepto
A partir de este artículo, empezaremos a desarrollar la funcionalidad para trabajar con la Profundidad del mercado (en inglés Depth of Market, o DOM). Las clases para trabajar con el DOM no van a diferenciarse conceptualmente de todas las demás clases de la biblioteca desarrolladas anteriormente. Al mismo tiempo, vamos a tener una plantilla del DOM que va a contener datos sobre las ordenes en el DOM que se obtienen por la función MarketBookGet() cuando se active el manejador OnBookEvent(). Ahí, cuando el DOM se cambie, se activa un evento para cada símbolo que tenga activada la suscripción a los eventos del DOM.
De esta forma, la estructura del DOM va a ser la siguiente:
- La clase del objeto de orden del DOM es un objeto que describe los datos de una orden entre varias ordenes que se obtienen del DOM, durante la activación unitaria del manejador OnBookEvent() para un símbolo;
- La clase del objeto de plantilla del DOM es un objeto que describe los datos de todas las órdenes que se obtienen del DOM al mismo tiempo, durante una activación del manejador OnBookEvent() para un símbolo. Se trata de un conjunto de objetos del punto 1 que forman parte de la plantilla actual del DOM;
- La clase de serie temporal compuesta de una secuencia de objetos del punto 2 que se introducen en la lista de serie temporal durante cada activación de OnBookEvent() para un símbolo;
- La clase de colección de las series de datos de los DOMs de todos los símbolos utilizados en el programa que tienen activada la suscripción a los eventos del DOM.
En este artículo, vamos a crear la clase del objeto de orden (1) y hacer la prueba de la obtención de datos del DOM cuando OnBookEvent() se active en el símbolo actual.
Las propiedades de cada orden están escritas en la estructura MqlBookInfo que facilita la información en el DOM:
- tipo de la orden desde la enumeración ENUM_BOOK_TYPE
- precio de la orden colocada
- volumen de la orden
- volumen de la orden con precisión aumentada
En el DOM puede haber cuatro tipos de órdenes (de la enumeración ENUM_BOOK_TYPE):
- Orden de venta
- Orden de venta por el precio de mercado
- Orden de compra
- Orden de compra por el precio de mercado
Como podemos observar, hay cuatros tipos de órdenes: dos en la dirección Buy, y otras dos en la dirección Sell. Por tanto, para dividir todos los tipos de las órdenes según estas dos direcciones, aparte de las propiedades existentes, vamos a añadir una más: el estatus de la orden que indica su dirección (solicitud en la dirección Buy o solicitud en la dirección Sell). En lo sucesivo, eso nos permitirá dividir todas las órdenes según sus direcciones (demanda y oferta).
El objeto de una orden del DOM será hecho a semejanza de los objetos de orden (y muchos otros objetos de la biblioteca): es decir, habrá un objeto básico de la orden abstracta del DOM y cuatro objetos herederos con precisión del tipo de la orden. El concepto de la construcción de estos objetos ya fue considerado al principio del desarrollo de la biblioteca, en el primero y en el segundo artículos.
Antes de empezar a crear las clases para trabajar con el DOM, añadiremos nuevos mensajes de la biblioteca y mejoraremos un poco las clases de los objetos de datos de tick. Añadimos los índices de nuevos mensajes al archivo \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 }; //+------------------------------------------------------------------+
y los textos de los mensajes que se corresponden con los índices nuevamente añadidos:
{"В окно \"Обзор рынка\" добавлен символ","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"}, }; //+---------------------------------------------------------------------+
En el archivo de la clase del objeto de símbolo \MQL5\Include\DoEasy\Objects\Symbols\Symbol.mqh añadimos la visualización de los mensajes sobre el error al realizar la suscripción al 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; } //+------------------------------------------------------------------+
hacemos lo mismo cuando intentamos dar de baja la suscripción:
//+------------------------------------------------------------------+ //| 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; } //+------------------------------------------------------------------+
En el método para actualizar la serie de tick de la clase de la serie de tick, en el archivo \MQL5\Include\DoEasy\Objects\Ticks\TickSeries.mqh, eliminamos la visualización de los comentarios de depuración en el gráfico del símbolo , la que dejamos en el artículo anterior para la simulación:
//+------------------------------------------------------------------+ //| 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); } } } } //+------------------------------------------------------------------+
Ahora, la hora del último tick va a registrarse directamente en la variable m_last_time que sirve precisamente para eso, porque en el artículo anterior, teníamos que visualizar los datos de prueba a través del comentario en el gráfico del símbolo, donde era necesario ver la hora del tick anterior y del tick actual. Ahora, no lo necesitamos, vamos a guardar la hora directamente en la variable:
//+------------------------------------------------------------------+ //| 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); } } } } //+------------------------------------------------------------------+
Clase del objeto de orden abstracta en la Profundidad del mercado
Al igual que para todos los objetos de la biblioteca que tienen sus propios conjuntos de enumeraciones para determinar constantes de las propiedades del objeto, es necesario crear enumeraciones de las propiedades de tipo entero, real y string del objeto para los objetos nuevos de las clases de objetos de orden del DOM.
Añadimos las enumeraciones de las propiedades y parámetros del objeto de orden del DOM al archivo \MQL5\Include\DoEasy\Defines.mqh. Como no vamos a hacer el modelo de eventos para trabajar con cada orden en el DOM (en un momento dado, el DOM muestra el estado actual de todas las órdenes, y su modificación lleva a su siguiente estado y se procesa durante la siguiente activación de OnBookEvent()), simplemente añadimos una constante que indica el código del siguiente evento después del último código del evento del DOM. Se hace para mantener la identidad de constantes de todos los objetos, es decir, reducirlas a una imagen común:
//+------------------------------------------------------------------+ //| 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 //+------------------------------------------------------------------+
Vamos a definir la enumeración en la que escribiremos dos posibles estatus de una orden en el DOM (Buy o Sell):
//+------------------------------------------------------------------+ //| Abstract DOM type (status) | //+------------------------------------------------------------------+ enum ENUM_MBOOK_ORD_STATUS { MBOOK_ORD_STATUS_BUY, // Buy side MBOOK_ORD_STATUS_SELL, // Sell side }; //+------------------------------------------------------------------+
La filtración de todas las órdenes en el DOM según estas propiedades permitirá formar una lista con todas las órdenes en el DOM que pertenecen a la demanda o a la oferta.
A continuación, añadiremos enumeraciones de las propiedades de tipo entero, real y string del objeto de orden del 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 //+------------------------------------------------------------------+
Por consiguiente, escribiremos para las propiedades creadas una enumeración de posibles criterios de ordenación de las órdenes en el 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 }; //+------------------------------------------------------------------+
Ahora, se puede crear la clase del objeto de orden abstracta en el DOM
En el catálogo de la biblioteca \MQL5\Include\DoEasy\Objects\ creamos la nueva carpeta Book\, y dentro de ella, el nuevo archivo MarketBookOrd.mqh de la clase CMarketBookOrd derivada del objeto básico de todos los objetos de la biblioteca CBaseObj:
//+------------------------------------------------------------------+ //| MarketBookOrd.mqh | //| Copyright 2021, MetaQuotes Software Corp. | //| https://mql5.com/es/users/artmedia70 | //+------------------------------------------------------------------+ #property copyright "Copyright 2021, MetaQuotes Software Corp." #property link "https://mql5.com/es/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; }; //+------------------------------------------------------------------+
La estructura de la clase es idéntica a otras clases de los objetos de la biblioteca. Ya las analizamos varias veces. Pueden refrescar la memoria y consultar las primeras y posteriores artículos donde todo se describe al detalle.
Vamos a analizar la implementación de los métodos de la clase.
En el constructor paramétrico cerrado de la clase, establecemos todas las propiedades del objeto desde la estructura de la orden de el DOM transmitida al constructor:
//+------------------------------------------------------------------+ //| 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)); } //+------------------------------------------------------------------+
Además al constructor se le transmite el estatus de la orden que vamos a indicar en los objetos herederos de esta clase durante la creación de un nuevo objeto de orden del DOM.
Método para comparar dos objetos CMarketBookOrd entre sí según la propiedad indicada para determinar la igualdad de propiedades indicadas de dos objetos:
//+------------------------------------------------------------------+ //| 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; } //+------------------------------------------------------------------+
El método recibe el objeto cuya propiedad debe ser comparada con la misma propiedad del objeto actual. Si la propiedad indicada del objeto comparado tiene el valor inferior al actual, se devuelve -1; si es superior, se devuelve +1; si las propiedades son iguales, se devuelve 0.
Método para comparar dos objetos CMarketBookOrd entre sí según todas las propiedades. Permite determinar la igualdad completa de dos objetos comparados:
//+------------------------------------------------------------------+ //| 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; } //+------------------------------------------------------------------+
Aquí, todas las propiedades de dos objetos se comparan una por una, y si las propiedades no son iguales, se devuelve false. Después de comprobar si todas las propiedades de dos objetos son iguales, y si false no ha sido devuelto, se devuelve true. Es decir, ambos objetos son absolutamente idénticos.
Método que muestra en el diario todas las propiedades del objeto:
//+------------------------------------------------------------------+ //| 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"); } //+------------------------------------------------------------------+
Vamos a iterar en tres ciclos por todas las propiedades de tipo entero, real y string, mostrando las descripciones string de cada siguiente propiedad en el diario.
Los métodos que retornan las descripciones de la propiedad especificada de tipo entero, real y string del objeto:
//+------------------------------------------------------------------+ //| 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)+"\"" : ""); } //+------------------------------------------------------------------+
A cada uno de los métodos se le transmite la propiedad cuya descripción debe ser devuelta. Dependiendo de la propiedad transmitida al método, se crea una cadena que al final se devuelve del método.
Método que retorna la denominación breve del objeto:
//+------------------------------------------------------------------+ //| Return the object short name | //+------------------------------------------------------------------+ string CMarketBookOrd::Header(void) { return this.TypeDescription()+" \""+this.Symbol()+"\""; } //+------------------------------------------------------------------+
El método devuelve una cadena compuesta de la descripción del tipo de la orden y de su símbolo.
Método que muestra en el diario la descripción breve del objeto:
//+------------------------------------------------------------------+ //| Display a short description of the object in the journal | //+------------------------------------------------------------------+ void CMarketBookOrd::PrintShort(void) { ::Print(this.Header()); } //+------------------------------------------------------------------+
El método simplemente visualiza en el diario la cadena creada por el método anterior.
Método que retorna la descripción del estatus de la orden en el 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) : "" ); } //+------------------------------------------------------------------+
Dependiendo de la propiedad «estatus» de la orden, se devuelve la cadena con la descripción de este estatus.
Esta es la clase completa del objeto de orden en la DOM.
Ahora, tenemos que crear cuatro clases herederas de este objeto de la orden abstracta. Precisamente estas clases herederas van a usarse para crear nuevos objetos de orden del DOM. Simplemente, en el constructor de la clase heredera, en su lista de inicalización, vamos a indicar el estatus del objeto de orden creado dependiendo del tipo de esta orden.
Clases herederas del objeto de orden abstracta
En la carpeta \MQL5\Include\DoEasy\Objects\Book\ creamos un archivo nuevo MarketBookBuy.mqh de la clase CMarketBookBuy. La clase de la orden abstracta CMarketBookOrd que acabamos de crear nos servirá de la clase padre:
//+------------------------------------------------------------------+ //| MarketBookBuy.mqh | //| Copyright 2021, MetaQuotes Software Corp. | //| https://mql5.com/es/users/artmedia70 | //+------------------------------------------------------------------+ #property copyright "Copyright 2021, MetaQuotes Software Corp." #property link "https://mql5.com/es/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); } //+------------------------------------------------------------------+
Al crear un nuevo objeto de orden del DOM, indicamos el estatus «Dirección Buy» en el constructor de la clase padre.
En los métodos virtuales que devuelven la bandera del soporte de la propiedad entera y real devolvemos true —el objeto soporta cada propiedad.
En el método virtual que devuelve el nombre breve del objeto de orden del DOM, devolvemos la cadena en el formato
Type "Symbol": Price [VolumeReal]
Por ejemplo:
"EURUSD" buy order: 1.20123 [10.00]
En el método virtual que devuelve la descripción del tipo del objeto de orden del DOM, devolvemos la cadena «Orden de compra»
Las demás tres clases derivadas de la clase padre de la orden abstracta del DOM son idénticas a la considerada, a excepción del estatus de la orden. En cada constructor de la clase, se especifica su estatus correspondiente al objeto de orden descrito y a sus métodos virtuales que devuelven las cadenas correspondientes al tipo de la orden del DOM descrito por cada uno de los objetos. Todas estas clases se encuentran en la misma carpeta que la clase considerada arriba. Simplemente, vamos a mostrar sus listados para que el lector pueda analizarlos y comparar sus métodos virtuales por sí mismo.
MarketBookBuyMarket.mqh:
//+------------------------------------------------------------------+ //| MarketBookBuyMarket.mqh | //| Copyright 2021, MetaQuotes Software Corp. | //| https://mql5.com/es/users/artmedia70 | //+------------------------------------------------------------------+ #property copyright "Copyright 2021, MetaQuotes Software Corp." #property link "https://mql5.com/es/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/es/users/artmedia70 | //+------------------------------------------------------------------+ #property copyright "Copyright 2021, MetaQuotes Software Corp." #property link "https://mql5.com/es/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/es/users/artmedia70 | //+------------------------------------------------------------------+ #property copyright "Copyright 2021, MetaQuotes Software Corp." #property link "https://mql5.com/es/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); } //+------------------------------------------------------------------+
Eso es todo por hoy.
Prueba
Para la simulación, vamos a usar el asesor del artículo anterior y guardarlo en la nueva carpeta
\MQL5\Experts\TestDoEasy\Part63\ con el nombre nuevo TestDoEasyPart63.mq5.
¿Qué es lo que vamos a hacer? Al ejecutar el EA, se realizará la suscripción a los DOMs de los símbolos establecidos en los ajustes para el trabajo. Todos los eventos con el DOM se registran en el manejador OnBookEvent(). Por tanto, vamos a verificar en este manejador que el evento ha ocurrido en el símbolo actual, obtener la captura de imagen del DOM y guardar todas las órdenes existentes en una lista ordenada según el valor del precio. Luego, mostraremos la primera y la última orden de esta lista en el comentario para el gráfico. Así, mostraremos dos órdenes extremas del DOM (una de venta y otra de compra). En el diario, se mostrará la lista de todas las órdenes del DOM obtenidas durante la primera activación de OnBookEvent().
Para que el EA pueda ver las clases nuevamente creadas, las incluimos en el archivo del EA (por ahora, no se puede acceder a ellas desde el objeto principal de la biblioteca CEngine):
//+------------------------------------------------------------------+ //| TestDoEasyPart63.mq5 | //| Copyright 2021, MetaQuotes Software Corp. | //| https://mql5.com/es/users/artmedia70 | //+------------------------------------------------------------------+ #property copyright "Copyright 2021, MetaQuotes Software Corp." #property link "https://mql5.com/es/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
Ahora, tenemos que crear el manejador OnBookEvent() en el EA, y escribir dentro el procesamiento del evento del 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; } //+------------------------------------------------------------------+
Aquí hemos descrito todo con detalle en los comentarios al código, así que esperamos que no surjan ningunas dudas. En cualquier caso, el lector podrá expresar cualquier duda en los comentarios al artículo.
Compilamos el EA y lo iniciamos en el gráfico del símbolo, seleccionando previamente en los ajustes el uso de dos símbolos especificados y el marco temporal actual.
Después de iniciar el EA y recibir el primer evento del cambio del DOM, en los comentarios del gráfico se mostrarán los parámetros de la lista de la captura actual del DOM y dos ordenes (la máxima de venta y la mínima de compra):
En el diario, se mostrará la lista de todas las órdenes de la captura de pantalla del 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]
¿Qué es lo próximo?
En el siguiente artículo, seguiremos desarrollando la funcionalidad para trabajar con la Profundidad del mercado.
Más abajo se adjuntan todos los archivos de la versión actual de la biblioteca y el archivo del asesor de prueba para MQL5. Puede descargarlo todo y ponerlo a prueba por sí mismo.
Cabe mencionar que las clases para trabajar con el DOM se encuentran en el proceso del desarrollo. Por tanto, no se recomienda usarlas en sus programas en esta fase.
Si tiene preguntas, observaciones o sugerencias, podrá concretarlas en los comentarios al artículo.
Artículos de esta serie:
Trabajando con los precios en la biblioteca DoEasy (Parte 59): Objeto para almacenar los datos de un tick
Trabajando con los precios en la biblioteca DoEasy (Parte 60): Lista de serie de datos de tick del símbolo
Trabajando con los precios en la biblioteca DoEasy (Parte 61): Colección de series de tick de los símbolos
Trabajando con los precios en la biblioteca DoEasy (Parte 61): Actualización de las series de tick en tiempo real, preparando para trabajar con la Profundidad del mercado
Traducción del ruso hecha por MetaQuotes Ltd.
Artículo original: https://www.mql5.com/ru/articles/9010





- Aplicaciones de trading gratuitas
- 8 000+ señales para copiar
- Noticias económicas para analizar los mercados financieros
Usted acepta la política del sitio web y las condiciones de uso