Trabajando con las series temporales en la biblioteca DoEasy (Parte 54): Clases herederas del indicador abstracto básico

11 enero 2021, 15:45
Artyom Trishkin
0
129

Contenido


Concepto

En el artículo anterior, consideramos la creación de un objeto-indicador abstracto básico. Ahora vamos a crear sus objetos herederos que contienen la información más detallada sobre un determinado objeto de indicador creado. Colocaremos todos estos objetos en la colección de indicadores de la cual se podrá obtener los datos y propiedades de cada indicador creado.
El concepto de los objetos herederos corresponde por completo al concepto de la construcción de objetos en la biblioteca y sus interacciones. Pues, la colección de indicadores nos permitirá añadir rápidamente la funcionalidad de eventos a todos los objetos de indicador en el futuro, lo cual nos permitirá definir fácilmente los eventos investigados de los indicadores y usar estos eventos en nuestros programas.


Mejorando las clases de la biblioteca

Vamos a comenzar como siempre, añadiendo los mensajes de texto necesarios de la biblioteca.

En el archivo \MQL5\Include\DoEasy\Data.mqh escribimos los índices de nuevos mensajes:

//--- CIndicatorDE
   MSG_LIB_TEXT_IND_TEXT_STATUS,                      // Indicator status
   MSG_LIB_TEXT_IND_TEXT_STATUS_STANDART,             // Standard indicator
   MSG_LIB_TEXT_IND_TEXT_STATUS_CUSTOM,               // Custom indicator
   
   MSG_LIB_TEXT_IND_TEXT_TYPE,                        // Indicator type
   MSG_LIB_TEXT_IND_TEXT_TIMEFRAME,                   // Indicator timeframe
   MSG_LIB_TEXT_IND_TEXT_HANDLE,                      // Indicator handle

   MSG_LIB_TEXT_IND_TEXT_GROUP,                       // Indicator group
   MSG_LIB_TEXT_IND_TEXT_GROUP_TREND,                 // Trend indicator
   MSG_LIB_TEXT_IND_TEXT_GROUP_OSCILLATOR,            // Oscillator
   MSG_LIB_TEXT_IND_TEXT_GROUP_VOLUMES,               // Volumes
   MSG_LIB_TEXT_IND_TEXT_GROUP_ARROWS,                // Arrow indicator
   
   MSG_LIB_TEXT_IND_TEXT_EMPTY_VALUE,                 // Empty value for plotting where nothing will be drawn
   MSG_LIB_TEXT_IND_TEXT_SYMBOL,                      // Indicator symbol
   MSG_LIB_TEXT_IND_TEXT_NAME,                        // Indicator name
   MSG_LIB_TEXT_IND_TEXT_SHORTNAME,                   // Indicator short name
   
//--- CIndicatorsCollection
   MSG_LIB_SYS_FAILED_ADD_IND_TO_LIST,                // Error. Failed to add indicator object to list
   
  };
//+------------------------------------------------------------------+

y después añadimos los nuevos mensajes que se correspondan con los índices nuevamente creados:

   {"Статус индикатора","Indicator status"},
   {"Стандартный индикатор","Standard indicator"},
   {"Пользовательский индикатор","Custom indicator"},
   {"Тип индикатора","Indicator type"},
   {"Таймфрейм индикатора","Indicator timeframe"},
   {"Хэндл индикатора","Indicator handle"},
   {"Группа индикатора","Indicator group"},
   {"Трендовый индикатор","Trend indicator"},
   {"Осциллятор","Solid lineOscillator"},
   {"Объёмы","Volumes"},
   {"Стрелочный индикатор","Arrow indicator"},
   {"Пустое значение для построения, для которого нет отрисовки","Empty value for plotting, for which there is no drawing"},
   {"Символ индикатора","Indicator symbol"},
   {"Имя индикатора","Indicator name"},
   {"Короткое имя индикатора","Indicator shortname"},
   
   {"Ошибка. Не удалось добавить объект-индикатор в список","Error. Failed to add indicator object to list"},
   
  };
//+---------------------------------------------------------------------+

Al crear la clase del objeto del indicador abstracto en el artículo anterior, no añadimos una de las propiedades enteras (integer) del objeto: el tipo del indicador estándar. Este tipo va a corresponder a los tipos de la enumeración ENUM_INDICATOR, y lo necesitaremos para buscar un indicador concreto.
Si queremos encontrar todos los indicadores MACD almacenados en la colección, en primer lugar, tenemos que obtener la lista de todos los indicadores MACD que se encuentran en la colección. Para eso, necesitamos filtrar la lista completa de la colección de indicadores según el tipo IND_MACD, y luego hacer la selección según otras propiedades buscadas en la lista obtenida que va a contener sólo IND_MACD.

Añadimos la nueva propiedad del objeto de indicador al archivo \MQL5\Include\DoEasy\Defines.mqh:

//+------------------------------------------------------------------+
//| Indicator integer properties                                     |
//+------------------------------------------------------------------+
enum ENUM_INDICATOR_PROP_INTEGER
  {
   INDICATOR_PROP_STATUS = 0,                               // Indicator status (from enumeration ENUM_INDICATOR_STATUS)
   INDICATOR_PROP_TYPE,                                     // Indicator type (from enumeration ENUM_INDICATOR)
   INDICATOR_PROP_TIMEFRAME,                                // Indicator timeframe
   INDICATOR_PROP_HANDLE,                                   // Indicator handle
   INDICATOR_PROP_GROUP,                                    // Indicator group
  }; 
#define INDICATOR_PROP_INTEGER_TOTAL (5)                    // Total number of indicator integer properties
#define INDICATOR_PROP_INTEGER_SKIP  (0)                    // Number of indicator properties not used in sorting
//+------------------------------------------------------------------+

y aumentamos el número de propiedades enteras de 4 a 5.

Al añadir la nueva propiedad al objeto, tenemos que definir la posibilidad de la búsqueda y ordenación de objetos según esta propiedad.
Añadimos un criterio de ordenación nuevo a la enumeración:

//+------------------------------------------------------------------+
//| Possible indicator sorting criteria                              |
//+------------------------------------------------------------------+
#define FIRST_INDICATOR_DBL_PROP          (INDICATOR_PROP_INTEGER_TOTAL-INDICATOR_PROP_INTEGER_SKIP)
#define FIRST_INDICATOR_STR_PROP          (INDICATOR_PROP_INTEGER_TOTAL-INDICATOR_PROP_INTEGER_SKIP+INDICATOR_PROP_DOUBLE_TOTAL-INDICATOR_PROP_DOUBLE_SKIP)
enum ENUM_SORT_INDICATOR_MODE
  {
//--- Sort by integer properties
   SORT_BY_INDICATOR_INDEX_STATUS = 0,                      // Sort by indicator status
   SORT_BY_INDICATOR_TYPE,                                  // Sort by indicator type
   SORT_BY_INDICATOR_TIMEFRAME,                             // Sort by indicator timeframe
   SORT_BY_INDICATOR_HANDLE,                                // Sort by indicator handle
   SORT_BY_INDICATOR_GROUP,                                 // Sort by indicator group
//--- Sort by real properties
   SORT_BY_INDICATOR_EMPTY_VALUE = FIRST_INDICATOR_DBL_PROP,// Sort by the empty value for plotting where nothing will be drawn
//--- Sort by string properties
   SORT_BY_INDICATOR_SYMBOL = FIRST_INDICATOR_STR_PROP,     // Sort by indicator symbol
   SORT_BY_INDICATOR_NAME,                                  // Sort by indicator name
   SORT_BY_INDICATOR_SHORTNAME,                             // Sort by indicator short name
  };
//+------------------------------------------------------------------+

Vamos a mejorar la clase del objeto del indicador abstracto en el archivo \MQL5\Include\DoEasy\Objects\Indicators\IndicatorDE.mqh.

Trasladaremos la matriz de estructuras de los parámetros del indicador de la sección privada de la clase a la protegida (ahora esta matriz estará disponible para las clases heredadas), declararemos en la sección privada una variable para almacenar la descripción del tipo del indicador:

//+------------------------------------------------------------------+
//| Abstract indicator class                                         |
//+------------------------------------------------------------------+
class CIndicatorDE : public CBaseObj
  {
protected:
   MqlParam          m_mql_param[];                                              // Array of indicator parameters
private:
   long              m_long_prop[INDICATOR_PROP_INTEGER_TOTAL];                  // Integer properties
   double            m_double_prop[INDICATOR_PROP_DOUBLE_TOTAL];                 // Real properties
   string            m_string_prop[INDICATOR_PROP_STRING_TOTAL];                 // String properties
   string            m_ind_type;                                                 // Indicator type description
   

Añadimos dos métodos a la sección pública de la clase: para devolver el tipo del indicador y para devolver la descripción del tipo del indicador:

public:  
//--- Default constructor
                     CIndicatorDE(void){;}
//--- Destructor
                    ~CIndicatorDE(void);
                     
//--- Set buffer's (1) integer, (2) real and (3) string properties
   void              SetProperty(ENUM_INDICATOR_PROP_INTEGER property,long value)   { this.m_long_prop[property]=value;                                        }
   void              SetProperty(ENUM_INDICATOR_PROP_DOUBLE property,double value)  { this.m_double_prop[this.IndexProp(property)]=value;                      }
   void              SetProperty(ENUM_INDICATOR_PROP_STRING property,string value)  { this.m_string_prop[this.IndexProp(property)]=value;                      }
//--- Return (1) integer, (2) real and (3) string buffer properties from the properties array
   long              GetProperty(ENUM_INDICATOR_PROP_INTEGER property)        const { return this.m_long_prop[property];                                       }
   double            GetProperty(ENUM_INDICATOR_PROP_DOUBLE property)         const { return this.m_double_prop[this.IndexProp(property)];                     }
   string            GetProperty(ENUM_INDICATOR_PROP_STRING property)         const { return this.m_string_prop[this.IndexProp(property)];                     }
//--- Get description of buffer's (1) integer, (2) real and (3) string properties
   string            GetPropertyDescription(ENUM_INDICATOR_PROP_INTEGER property);
   string            GetPropertyDescription(ENUM_INDICATOR_PROP_DOUBLE property);
   string            GetPropertyDescription(ENUM_INDICATOR_PROP_STRING property);
//--- Return the flag of the buffer supporting the property
   virtual bool      SupportProperty(ENUM_INDICATOR_PROP_INTEGER property)          { return true;       }
   virtual bool      SupportProperty(ENUM_INDICATOR_PROP_DOUBLE property)           { return true;       }
   virtual bool      SupportProperty(ENUM_INDICATOR_PROP_STRING property)           { return true;       }

//--- Compare CIndicatorDE objects by all possible properties (for sorting the lists by a specified indicator object property)
   virtual int       Compare(const CObject *node,const int mode=0) const;
//--- Compare CIndicatorDE objects by all properties (to search for equal indicator objects)
   bool              IsEqual(CIndicatorDE* compared_obj) const;
                     
//--- Set indicator’s (1) group, (2) empty value of buffers, (3) name, (4) short name
   void              SetGroup(const ENUM_INDICATOR_GROUP group)      { this.SetProperty(INDICATOR_PROP_GROUP,group);                         }
   void              SetEmptyValue(const double value)               { this.SetProperty(INDICATOR_PROP_EMPTY_VALUE,value);                   }
   void              SetName(const string name)                      { this.SetProperty(INDICATOR_PROP_NAME,name);                           }
   void              SetShortName(const string shortname)            { this.SetProperty(INDICATOR_PROP_SHORTNAME,shortname);                 }
   
//--- Return indicator’s (1) status, (2) group, (3) timeframe, (4) handle, (5) empty value of buffers, (6) name, (7) short name, (8) symbol, (9) type
   ENUM_INDICATOR_STATUS Status(void)                          const { return (ENUM_INDICATOR_STATUS)this.GetProperty(INDICATOR_PROP_STATUS);}
   ENUM_INDICATOR_GROUP  Group(void)                           const { return (ENUM_INDICATOR_GROUP)this.GetProperty(INDICATOR_PROP_GROUP);  }
   ENUM_TIMEFRAMES   Timeframe(void)                           const { return (ENUM_TIMEFRAMES)this.GetProperty(INDICATOR_PROP_TIMEFRAME);   }
   ENUM_INDICATOR    TypeIndicator(void)                       const { return (ENUM_INDICATOR)this.GetProperty(INDICATOR_PROP_TYPE);         }
   int               Handle(void)                              const { return (int)this.GetProperty(INDICATOR_PROP_HANDLE);                  }
   double            EmptyValue(void)                          const { return this.GetProperty(INDICATOR_PROP_EMPTY_VALUE);                  }
   string            Name(void)                                const { return this.GetProperty(INDICATOR_PROP_NAME);                         }
   string            ShortName(void)                           const { return this.GetProperty(INDICATOR_PROP_SHORTNAME);                    }
   string            Symbol(void)                              const { return this.GetProperty(INDICATOR_PROP_SYMBOL);                       }
   
//--- Return description of indicator’s (1) type, (2) status, (3) group, (4) timeframe, (5) empty value
   string            GetTypeDescription(void)                  const { return m_ind_type;                                                    }
   string            GetStatusDescription(void)                const;
   string            GetGroupDescription(void)                 const;
   string            GetTimeframeDescription(void)             const;
   string            GetEmptyValueDescription(void)            const;
   
//--- Display the description of indicator 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 indicator object in the journal (implementation in the descendants)
   virtual void      PrintShort(void) {;}

  };
//+------------------------------------------------------------------+

En el constructor paramétrico cerrado, recuperaremos la subcadena del parámetro de entrada del tipo del indicador para dejar sólo el nombre del indicador (por ejemplo, de IND_MACD se queda sólo MACD, lo cual representará la descripción del tipo del indicador), y el propio tipo del indicador lo añadiremos a las propiedades del objeto:

//+------------------------------------------------------------------+
//| Closed parametric constructor                                    |
//+------------------------------------------------------------------+
CIndicatorDE::CIndicatorDE(ENUM_INDICATOR ind_type,
                           string symbol,
                           ENUM_TIMEFRAMES timeframe,
                           ENUM_INDICATOR_STATUS status,
                           ENUM_INDICATOR_GROUP group,
                           string name,
                           string shortname,
                           MqlParam &mql_params[])
  {
//--- Set collection ID to the object
   this.m_type=COLLECTION_INDICATORS_ID;
//--- Write description of indicator type
   this.m_ind_type=::StringSubstr(::EnumToString(ind_type),4);
//--- If parameter array value passed to constructor is more than zero
//--- fill in the array of object parameters with data from the array passed to constructor
   int count=::ArrayResize(m_mql_param,::ArraySize(mql_params));
   for(int i=0;i<count;i++)
     {
      this.m_mql_param[i].type=mql_params[i].type;
      this.m_mql_param[i].double_value=mql_params[i].double_value;
      this.m_mql_param[i].integer_value=mql_params[i].integer_value;
      this.m_mql_param[i].string_value=mql_params[i].string_value;
     }
//--- Create indicator handle
   int handle=::IndicatorCreate(symbol,timeframe,ind_type,count,this.m_mql_param);
   
//--- Save integer properties
   this.m_long_prop[INDICATOR_PROP_STATUS]                     = status;
   this.m_long_prop[INDICATOR_PROP_TYPE]                       = ind_type;
   this.m_long_prop[INDICATOR_PROP_GROUP]                      = group;
   this.m_long_prop[INDICATOR_PROP_TIMEFRAME]                  = timeframe;
   this.m_long_prop[INDICATOR_PROP_HANDLE]                     = handle;
   
//--- Save real properties
   this.m_double_prop[this.IndexProp(INDICATOR_PROP_EMPTY_VALUE)]=EMPTY_VALUE;
//--- Save string properties
   this.m_string_prop[this.IndexProp(INDICATOR_PROP_SYMBOL)]   = (symbol==NULL || symbol=="" ? ::Symbol() : symbol);
   this.m_string_prop[this.IndexProp(INDICATOR_PROP_NAME)]     = name;
   this.m_string_prop[this.IndexProp(INDICATOR_PROP_SHORTNAME)]= shortname;
  }
//+------------------------------------------------------------------+

Añadimos el bloque del código para devolver la descripción del tipo del indicador al método que devuelve la descripción de una propiedad entera del indicador:

//+------------------------------------------------------------------+
//| Return description of indicator's integer property               |
//+------------------------------------------------------------------+
string CIndicatorDE::GetPropertyDescription(ENUM_INDICATOR_PROP_INTEGER property)
  {
   return
     (
      property==INDICATOR_PROP_STATUS        ?  CMessage::Text(MSG_LIB_TEXT_IND_TEXT_STATUS)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+this.GetStatusDescription()
         )  :
      property==INDICATOR_PROP_TYPE        ?  CMessage::Text(MSG_LIB_TEXT_IND_TEXT_TYPE)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+this.GetTypeDescription()
         )  :
      property==INDICATOR_PROP_GROUP          ?  CMessage::Text(MSG_LIB_TEXT_IND_TEXT_GROUP)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+this.GetGroupDescription()
         )  :
      property==INDICATOR_PROP_TIMEFRAME     ?  CMessage::Text(MSG_LIB_TEXT_IND_TEXT_TIMEFRAME)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+this.GetTimeframeDescription()
         )  :
      property==INDICATOR_PROP_HANDLE        ?  CMessage::Text(MSG_LIB_TEXT_IND_TEXT_HANDLE)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(string)this.GetProperty(property)
         )  :
      ""
     );
  }
//+------------------------------------------------------------------+


Clase de objetos de indicador

Ahora, procedemos a desarrollar los objetos herederos del indicador abstracto básico que van a detallar toda la información sobre el objeto de indicador a crear. Precisamente estas clases serán usadas para crear indicadores de tipos diferentes y obtener datos sobre ellos.

En el directorio \MQL5\Include\DoEasy\Objects\Indicators\ creamos la carpeta nueva Standart, y dentro de ella, el archivo nuevo IndAC.mqh de la clase CIndAC del indicador estándar Accelerator Oscillator, heredada de la clase base del indicador abstracto cuyo archivo está conectado al listado de esta clase.
Dado que la clase no será grande, vamos a analizar su listado completo:

//+------------------------------------------------------------------+
//|                                                        IndAC.mqh |
//|                        Copyright 2020, MetaQuotes Software Corp. |
//|                             https://mql5.com/es/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2020, MetaQuotes Software Corp."
#property link      "https://mql5.com/es/users/artmedia70"
//+------------------------------------------------------------------+
//| Include files                                                    |
//+------------------------------------------------------------------+
#include "..\\IndicatorDE.mqh"
//+------------------------------------------------------------------+
//| Accelerator Oscillator standard indicator                        |
//+------------------------------------------------------------------+
class CIndAC : public CIndicatorDE
  {
private:

public:
   //--- Constructor
                     CIndAC(const string symbol,const ENUM_TIMEFRAMES timeframe,MqlParam &mql_param[]) : 
                        CIndicatorDE(IND_AC,symbol,timeframe,
                                     INDICATOR_STATUS_STANDART,
                                     INDICATOR_GROUP_OSCILLATOR,
                                     "Accelerator Oscillator",
                                     "AC("+symbol+","+TimeframeDescription(timeframe)+")",mql_param) {}
   //--- Supported indicator properties (1) real, (2) integer
   virtual bool      SupportProperty(ENUM_INDICATOR_PROP_DOUBLE property);
   virtual bool      SupportProperty(ENUM_INDICATOR_PROP_INTEGER property);
   
//--- Display a short description of indicator object in the journal
   virtual void      PrintShort(void);
  };
//+------------------------------------------------------------------+
//| Return 'true' if the indicator supports the passed               |
//| integer property, otherwise return 'false'                       |
//+------------------------------------------------------------------+
bool CIndAC::SupportProperty(ENUM_INDICATOR_PROP_INTEGER property)
  {
   return true;
  }
//+------------------------------------------------------------------+
//| Return 'true' if the indicator supports the passed               |
//| real property, otherwise return 'false'                          |
//+------------------------------------------------------------------+
bool CIndAC::SupportProperty(ENUM_INDICATOR_PROP_DOUBLE property)
  {
   return true;
  }
//+------------------------------------------------------------------+
//| Display a short description of indicator object in the journal   |
//+------------------------------------------------------------------+
void CIndAC::PrintShort(void)
  {
   ::Print(GetStatusDescription()," ",this.Name()," ",this.Symbol()," ",TimeframeDescription(this.Timeframe()));
  }
//+------------------------------------------------------------------+

En total, tendremos que hacer 38 clases —de acuerdo con el número de indicadores estándar (todavía no hacemos el indicador personalizado porque su implementación será algo diferente).
Todas estas clases van a tener los métodos iguales, diferenciándose sólo en sus parámetros que se transmiten a la clase padre de su constructor:

   //--- Constructor
                     CIndAC(const string symbol,const ENUM_TIMEFRAMES timeframe,MqlParam &mql_param[]) : 
                        CIndicatorDE(IND_AC,symbol,timeframe,
                                     INDICATOR_STATUS_STANDART,
                                     INDICATOR_GROUP_OSCILLATOR,
                                     "Accelerator Oscillator",
                                     "AC("+symbol+","+TimeframeDescription(timeframe)+")",mql_param) {}

En los parámetros de entrada de la clase, transmitimos sólo el nombre del símbolo, marco temporal y la estructura de los parámetros del indicador ya rellenada (en este ejemplo es Accelerator Oscillator).
En la lista de inicialización, transmitimos al constructor paramétrico cerrado de la clase padre (por orden) lo siguiente:

  • tipo del indicador — IND_AC, nombre del símbolo, marco temporal
  • estatus del indicador — estándar
  • grupo del indicador — osciladores
  • nombre del indicador — Accelerator Oscillator
  • nombre breve del indicador — AC (símbolo, marco temporal) y estructura rellenada de parámetros del indicador

Ya conocemos los demás métodos por haber creado los objetos anteriores de la biblioteca. Ellos realizan las mismas tareas.
Los métodos que devuelven la bandera del soporte de las propiedades enteras y reales por el objeto devuelven true —todas las propiedades se soportan por los objetos de indicador.
El método que devuelve la descripción breve del indicador devuelve la cadena del tipo siguiente:

Standard indicator Accelerator Oscillator EURUSD H4

En todos los demás archivos de clases semejantes de los objetos de indicador, la diferencia será en el constructor de la clase, es decir, los parámetros correspondientes al indicador van a transmitirse al constructor de la clase padre.

Por ejemplo, para el indicador Accumulation/Distribution el constructor de la clase tendrá este aspecto:

   //--- Constructor
                     CIndAD(const string symbol,const ENUM_TIMEFRAMES timeframe,MqlParam &mql_param[]) :
                        CIndicatorDE(IND_AD,symbol,timeframe,
                                     INDICATOR_STATUS_STANDART,
                                     INDICATOR_GROUP_VOLUMES,
                                     "Accumulation/Distribution",
                                     "AD("+symbol+","+TimeframeDescription(timeframe)+")",mql_param) {}

Como vemos, aquí ya se transmiten los parámetros correspondientes al indicador estándar AD:

  • tipo del indicador — IND_AD, nombre del símbolo, marco temporal
  • estatus del indicador — estándar
  • grupo del indicador — volúmenes
  • nombre del indicador — Accumulation/Distribution
  • nombre breve del indicador — AD (símbolo, marco temporal) y estructura rellenada de parámetros del indicador

Todos los archivos de las clases herederas de la clase base del indicador abstracto ya están implementados. Puede analizarlas por sí mismo accediendo a los archivos adjuntos al artículo ubicados en la carpeta \MQL5\Include\DoEasy\Objects\Indicators\Standart.

Colección de objetos de indicador

Conforme al concepto general de la construcción y almacenamiento de objetos de la biblioteca, ahora tenemos que colocar todos los objetos creados de los indicadores en la lista de colección. A partir de esta lista, siempre podemos obtener el puntero al indicador necesario según las propiedades indicadas, o bien, una lista de indicadores que poseen propiedades generales iguales. Usando el puntero al indicador, podemos acceder a todos los datos devueltos por el indicador para los cálculos posteriores.

En la carpeta \MQL5\Include\DoEasy\Collections\ creamos una nueva clase en el archivo con el nombre IndicatorsCollection.mqh.

Aparte de los métodos estándar para la biblioteca que devuelven las listas de objetos solicitadas de la colección, la clase va a contener un método privado para crear el objeto de indicador y varios métodos para crear objetos de indicador concretos de acuerdo con su tipo, así como varios métodos para obtener punteros a los objetos de indicador, también según sus tipos. En cuanto a su lógica, todos los métodos de cada grupo son idénticos, por eso, vamos a analizar sólo algunos de ellos como ejemplo.

Para que la clase de colección de los indicadores tenga acceso a las clases de los indicadores creados más arriba, tenemos que incluirlas en el listado del archivo:

//+------------------------------------------------------------------+
//|                                         IndicatorsCollection.mqh |
//|                        Copyright 2020, MetaQuotes Software Corp. |
//|                             https://mql5.com/es/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2020, MetaQuotes Software Corp."
#property link      "https://mql5.com/es/users/artmedia70"
#property version   "1.00"
//+------------------------------------------------------------------+
//| Include files                                                    |
//+------------------------------------------------------------------+
#include "ListObj.mqh"
#include "..\Objects\Indicators\Standart\IndAC.mqh"
#include "..\Objects\Indicators\Standart\IndAD.mqh"
#include "..\Objects\Indicators\Standart\IndADX.mqh"
#include "..\Objects\Indicators\Standart\IndADXW.mqh"
#include "..\Objects\Indicators\Standart\IndAlligator.mqh"
#include "..\Objects\Indicators\Standart\IndAMA.mqh"
#include "..\Objects\Indicators\Standart\IndAO.mqh"
#include "..\Objects\Indicators\Standart\IndATR.mqh"
#include "..\Objects\Indicators\Standart\IndBands.mqh"
#include "..\Objects\Indicators\Standart\IndBears.mqh"
#include "..\Objects\Indicators\Standart\IndBulls.mqh"
#include "..\Objects\Indicators\Standart\IndBWMFI.mqh"
#include "..\Objects\Indicators\Standart\IndCCI.mqh"
#include "..\Objects\Indicators\Standart\IndChaikin.mqh"
#include "..\Objects\Indicators\Standart\IndDEMA.mqh"
#include "..\Objects\Indicators\Standart\IndDeMarker.mqh"
#include "..\Objects\Indicators\Standart\IndEnvelopes.mqh"
#include "..\Objects\Indicators\Standart\IndForce.mqh"
#include "..\Objects\Indicators\Standart\IndFractals.mqh"
#include "..\Objects\Indicators\Standart\IndFRAMA.mqh"
#include "..\Objects\Indicators\Standart\IndGator.mqh"
#include "..\Objects\Indicators\Standart\IndIchimoku.mqh"
#include "..\Objects\Indicators\Standart\IndMA.mqh"
#include "..\Objects\Indicators\Standart\IndMACD.mqh"
#include "..\Objects\Indicators\Standart\IndMFI.mqh"
#include "..\Objects\Indicators\Standart\IndMomentum.mqh"
#include "..\Objects\Indicators\Standart\IndOBV.mqh"
#include "..\Objects\Indicators\Standart\IndOsMA.mqh"
#include "..\Objects\Indicators\Standart\IndRSI.mqh"
#include "..\Objects\Indicators\Standart\IndRVI.mqh"
#include "..\Objects\Indicators\Standart\IndSAR.mqh"
#include "..\Objects\Indicators\Standart\IndStDev.mqh"
#include "..\Objects\Indicators\Standart\IndStoch.mqh"
#include "..\Objects\Indicators\Standart\IndTEMA.mqh"
#include "..\Objects\Indicators\Standart\IndTRIX.mqh"
#include "..\Objects\Indicators\Standart\IndVIDYA.mqh"
#include "..\Objects\Indicators\Standart\IndVolumes.mqh"
#include "..\Objects\Indicators\Standart\IndWPR.mqh"
//+------------------------------------------------------------------+

A continuación, vamos a ver el listado completo del cuerpo de la clase, y luego, analizaremos dos métodos en cada uno de los grupos.

//+------------------------------------------------------------------+
//| Indicator collection                                             |
//+------------------------------------------------------------------+
class CIndicatorsCollection : public CObject
  {
private:
   CListObj                m_list;                       // List of indicator objects
   MqlParam                m_mql_param[];                // Array of indicator parameters

//--- Create a new indicator object
   CIndicatorDE           *CreateIndicator(const ENUM_INDICATOR ind_type,MqlParam &mql_param[],const string symbol_name=NULL,const ENUM_TIMEFRAMES period=PERIOD_CURRENT);

public:
//--- Return (1) itself, (2) indicator list, (3) list of indicators by type
   CIndicatorsCollection  *GetObject(void)               { return &this;                                       }
   CArrayObj              *GetList(void)                 { return &this.m_list;                                }
//--- Return indicator list by (1) status, (2) type, (3) timeframe, (4) group, (5) symbol, (6) name, (7) short name
   CArrayObj              *GetListIndByStatus(const ENUM_INDICATOR_STATUS status)
                             { return CSelect::ByIndicatorProperty(this.GetList(),INDICATOR_PROP_STATUS,status,EQUAL);        }
   CArrayObj              *GetListIndByType(const ENUM_INDICATOR type)
                             { return CSelect::ByIndicatorProperty(this.GetList(),INDICATOR_PROP_TYPE,type,EQUAL);            }
   CArrayObj              *GetListIndByTimeframe(const ENUM_TIMEFRAMES timeframe)
                             { return CSelect::ByIndicatorProperty(this.GetList(),INDICATOR_PROP_TIMEFRAME,timeframe,EQUAL);  }
   CArrayObj              *GetListIndByGroup(const ENUM_INDICATOR_GROUP group)
                             { return CSelect::ByIndicatorProperty(this.GetList(),INDICATOR_PROP_GROUP,group,EQUAL);          }
   CArrayObj              *GetListIndBySymbol(const string symbol)
                             { return CSelect::ByIndicatorProperty(this.GetList(),INDICATOR_PROP_SYMBOL,symbol,EQUAL);        }
   CArrayObj              *GetListIndByName(const string name)
                             { return CSelect::ByIndicatorProperty(this.GetList(),INDICATOR_PROP_NAME,name,EQUAL);            }
   CArrayObj              *GetListIndByShortname(const string shortname)
                             { return CSelect::ByIndicatorProperty(this.GetList(),INDICATOR_PROP_SHORTNAME,shortname,EQUAL);  }
  
//--- Return the list of indicator objects by type of indicator, symbol and timeframe
   CArrayObj              *GetListAC(const string symbol,const ENUM_TIMEFRAMES timeframe);
   CArrayObj              *GetListAD(const string symbol,const ENUM_TIMEFRAMES timeframe);
   CArrayObj              *GetListADX(const string symbol,const ENUM_TIMEFRAMES timeframe);
   CArrayObj              *GetListADXWilder(const string symbol,const ENUM_TIMEFRAMES timeframe);
   CArrayObj              *GetListAlligator(const string symbol,const ENUM_TIMEFRAMES timeframe);
   CArrayObj              *GetListAMA(const string symbol,const ENUM_TIMEFRAMES timeframe);
   CArrayObj              *GetListAO(const string symbol,const ENUM_TIMEFRAMES timeframe);
   CArrayObj              *GetListATR(const string symbol,const ENUM_TIMEFRAMES timeframe);
   CArrayObj              *GetListBands(const string symbol,const ENUM_TIMEFRAMES timeframe);
   CArrayObj              *GetListBearsPower(const string symbol,const ENUM_TIMEFRAMES timeframe);
   CArrayObj              *GetListBullsPower(const string symbol,const ENUM_TIMEFRAMES timeframe);
   CArrayObj              *GetListChaikin(const string symbol,const ENUM_TIMEFRAMES timeframe);
   CArrayObj              *GetListCCI(const string symbol,const ENUM_TIMEFRAMES timeframe);
   CArrayObj              *GetListDEMA(const string symbol,const ENUM_TIMEFRAMES timeframe);
   CArrayObj              *GetListDeMarker(const string symbol,const ENUM_TIMEFRAMES timeframe);
   CArrayObj              *GetListEnvelopes(const string symbol,const ENUM_TIMEFRAMES timeframe);
   CArrayObj              *GetListForce(const string symbol,const ENUM_TIMEFRAMES timeframe);
   CArrayObj              *GetListFractals(const string symbol,const ENUM_TIMEFRAMES timeframe);
   CArrayObj              *GetListFrAMA(const string symbol,const ENUM_TIMEFRAMES timeframe);
   CArrayObj              *GetListGator(const string symbol,const ENUM_TIMEFRAMES timeframe);
   CArrayObj              *GetListIchimoku(const string symbol,const ENUM_TIMEFRAMES timeframe);
   CArrayObj              *GetListBWMFI(const string symbol,const ENUM_TIMEFRAMES timeframe);
   CArrayObj              *GetListMomentum(const string symbol,const ENUM_TIMEFRAMES timeframe);
   CArrayObj              *GetListMFI(const string symbol,const ENUM_TIMEFRAMES timeframe);
   CArrayObj              *GetListMA(const string symbol,const ENUM_TIMEFRAMES timeframe);
   CArrayObj              *GetListOsMA(const string symbol,const ENUM_TIMEFRAMES timeframe);
   CArrayObj              *GetListMACD(const string symbol,const ENUM_TIMEFRAMES timeframe);
   CArrayObj              *GetListOBV(const string symbol,const ENUM_TIMEFRAMES timeframe);
   CArrayObj              *GetListSAR(const string symbol,const ENUM_TIMEFRAMES timeframe);
   CArrayObj              *GetListRSI(const string symbol,const ENUM_TIMEFRAMES timeframe);
   CArrayObj              *GetListRVI(const string symbol,const ENUM_TIMEFRAMES timeframe);
   CArrayObj              *GetListStdDev(const string symbol,const ENUM_TIMEFRAMES timeframe);
   CArrayObj              *GetListStochastic(const string symbol,const ENUM_TIMEFRAMES timeframe);
   CArrayObj              *GetListTEMA(const string symbol,const ENUM_TIMEFRAMES timeframe);
   CArrayObj              *GetListTriX(const string symbol,const ENUM_TIMEFRAMES timeframe);
   CArrayObj              *GetListWPR(const string symbol,const ENUM_TIMEFRAMES timeframe);
   CArrayObj              *GetListVIDYA(const string symbol,const ENUM_TIMEFRAMES timeframe);
   CArrayObj              *GetListVolumes(const string symbol,const ENUM_TIMEFRAMES timeframe);
   
//--- Return the pointer to indicator object in the collection by indicator type and by its parameters
   CIndicatorDE           *GetIndAC(const string symbol,const ENUM_TIMEFRAMES timeframe);
   CIndicatorDE           *GetIndAD(const string symbol,const ENUM_TIMEFRAMES timeframe,const ENUM_APPLIED_VOLUME applied_volume);
   CIndicatorDE           *GetIndADX(const string symbol,const ENUM_TIMEFRAMES timeframe,const int adx_period);
   CIndicatorDE           *GetIndADXWilder(const string symbol,const ENUM_TIMEFRAMES timeframe,const int adx_period);
   CIndicatorDE           *GetIndAlligator(const string symbol,const ENUM_TIMEFRAMES timeframe,
                                       const int jaw_period,
                                       const int jaw_shift,
                                       const int teeth_period,
                                       const int teeth_shift,
                                       const int lips_period,
                                       const int lips_shift,
                                       const ENUM_MA_METHOD ma_method,
                                       const ENUM_APPLIED_PRICE applied_price);
   CIndicatorDE           *GetIndAMA(const string symbol,const ENUM_TIMEFRAMES timeframe,
                                       const int ama_period,
                                       const int fast_ema_period,
                                       const int slow_ema_period,
                                       const int ama_shift,
                                       const ENUM_APPLIED_PRICE applied_price);
   CIndicatorDE           *GetIndAO(const string symbol,const ENUM_TIMEFRAMES timeframe);
   CIndicatorDE           *GetIndATR(const string symbol,const ENUM_TIMEFRAMES timeframe,const int ma_period);
   CIndicatorDE           *GetIndBands(const string symbol,const ENUM_TIMEFRAMES timeframe,
                                       const int ma_period,
                                       const int ma_shift,
                                       const double deviation,
                                       const ENUM_APPLIED_PRICE applied_price);
   CIndicatorDE           *GetIndBearsPower(const string symbol,const ENUM_TIMEFRAMES timeframe,const int ma_period);
   CIndicatorDE           *GetIndBullsPower(const string symbol,const ENUM_TIMEFRAMES timeframe,const int ma_period);
   CIndicatorDE           *GetIndChaikin(const string symbol,const ENUM_TIMEFRAMES timeframe,
                                       const int fast_ma_period,
                                       const int slow_ma_period,
                                       const ENUM_MA_METHOD ma_method,
                                       const ENUM_APPLIED_VOLUME applied_volume);
   CIndicatorDE           *GetIndCCI(const string symbol,const ENUM_TIMEFRAMES timeframe,
                                       const int ma_period,
                                       const ENUM_APPLIED_PRICE applied_price);
   CIndicatorDE           *GetIndDEMA(const string symbol,const ENUM_TIMEFRAMES timeframe,
                                       const int ma_period,
                                       const int ma_shift,
                                       const ENUM_APPLIED_PRICE applied_price);
   CIndicatorDE           *GetIndDeMarker(const string symbol,const ENUM_TIMEFRAMES timeframe,const int ma_period);
   CIndicatorDE           *GetIndEnvelopes(const string symbol,const ENUM_TIMEFRAMES timeframe,
                                       const int ma_period,
                                       const int ma_shift,
                                       const ENUM_MA_METHOD ma_method,
                                       const ENUM_APPLIED_PRICE applied_price,
                                       const double deviation);
   CIndicatorDE           *GetIndForce(const string symbol,const ENUM_TIMEFRAMES timeframe,
                                       const int ma_period,
                                       const ENUM_MA_METHOD ma_method,
                                       const ENUM_APPLIED_VOLUME applied_volume);
   CIndicatorDE           *GetIndFractals(const string symbol,const ENUM_TIMEFRAMES timeframe);
   CIndicatorDE           *GetIndFrAMA(const string symbol,const ENUM_TIMEFRAMES timeframe,
                                       const int ma_period,
                                       const int ma_shift,
                                       const ENUM_APPLIED_PRICE applied_price);
   CIndicatorDE           *GetIndGator(const string symbol,const ENUM_TIMEFRAMES timeframe,
                                       const int jaw_period,
                                       const int jaw_shift,
                                       const int teeth_period,
                                       const int teeth_shift,
                                       const int lips_period,
                                       const int lips_shift,
                                       const ENUM_MA_METHOD ma_method,
                                       const ENUM_APPLIED_PRICE applied_price);
   CIndicatorDE           *GetIndIchimoku(const string symbol,const ENUM_TIMEFRAMES timeframe,
                                       const int tenkan_sen,
                                       const int kijun_sen,
                                       const int senkou_span_b);
   CIndicatorDE           *GetIndBWMFI(const string symbol,const ENUM_TIMEFRAMES timeframe,
                                       const ENUM_APPLIED_VOLUME applied_volume);
   CIndicatorDE           *GetIndMomentum(const string symbol,const ENUM_TIMEFRAMES timeframe,
                                       const int mom_period,
                                       const ENUM_APPLIED_PRICE applied_price);
   CIndicatorDE           *GetIndMFI(const string symbol,const ENUM_TIMEFRAMES timeframe,
                                       const int ma_period,
                                       const ENUM_APPLIED_VOLUME applied_volume);
   CIndicatorDE           *GetIndMA(const string symbol,const ENUM_TIMEFRAMES timeframe,
                                       const int ma_period,
                                       const int ma_shift,
                                       const ENUM_MA_METHOD ma_method,
                                       const ENUM_APPLIED_PRICE applied_price);
   CIndicatorDE           *GetIndOsMA(const string symbol,const ENUM_TIMEFRAMES timeframe,
                                       const int fast_ema_period,
                                       const int slow_ema_period,
                                       const int signal_period,
                                       const ENUM_APPLIED_PRICE applied_price);
   CIndicatorDE           *GetIndMACD(const string symbol,const ENUM_TIMEFRAMES timeframe,
                                       const int fast_ema_period,
                                       const int slow_ema_period,
                                       const int signal_period,
                                       const ENUM_APPLIED_PRICE applied_price);
   CIndicatorDE           *GetIndOBV(const string symbol,const ENUM_TIMEFRAMES timeframe,
                                       const ENUM_APPLIED_VOLUME applied_volume);
   CIndicatorDE           *GetIndSAR(const string symbol,const ENUM_TIMEFRAMES timeframe,
                                       const double step,
                                       const double maximum);
   CIndicatorDE           *GetIndRSI(const string symbol,const ENUM_TIMEFRAMES timeframe,
                                       const int ma_period,
                                       const ENUM_APPLIED_PRICE applied_price);
   CIndicatorDE           *GetIndRVI(const string symbol,const ENUM_TIMEFRAMES timeframe,const int ma_period);
   CIndicatorDE           *GetIndStdDev(const string symbol,const ENUM_TIMEFRAMES timeframe,
                                       const int ma_period,
                                       const int ma_shift,
                                       const ENUM_MA_METHOD ma_method,
                                       const ENUM_APPLIED_PRICE applied_price);
   CIndicatorDE           *GetIndStochastic(const string symbol,const ENUM_TIMEFRAMES timeframe,
                                       const int Kperiod,
                                       const int Dperiod,
                                       const int slowing,
                                       const ENUM_MA_METHOD ma_method,
                                       const ENUM_STO_PRICE price_field);
   CIndicatorDE           *GetIndTEMA(const string symbol,const ENUM_TIMEFRAMES timeframe,
                                       const int ma_period,
                                       const int ma_shift,
                                       const ENUM_APPLIED_PRICE applied_price);
   CIndicatorDE           *GetIndTriX(const string symbol,const ENUM_TIMEFRAMES timeframe,
                                       const int ma_period,
                                       const ENUM_APPLIED_PRICE applied_price);
   CIndicatorDE           *GetIndWPR(const string symbol,const ENUM_TIMEFRAMES timeframe,const int calc_period);
   CIndicatorDE           *GetIndVIDYA(const string symbol,const ENUM_TIMEFRAMES timeframe,
                                       const int cmo_period,
                                       const int ema_period,
                                       const int ma_shift,
                                       const ENUM_APPLIED_PRICE applied_price);
   CIndicatorDE           *GetIndVolumes(const string symbol,const ENUM_TIMEFRAMES timeframe,const ENUM_APPLIED_VOLUME applied_volume);
  
//--- Create a new indicator object by indicator type and places it to collection list
   int                     CreateAC(const string symbol,const ENUM_TIMEFRAMES timeframe);
   int                     CreateAD(const string symbol,const ENUM_TIMEFRAMES timeframe,const ENUM_APPLIED_VOLUME applied_volume);
   int                     CreateADX(const string symbol,const ENUM_TIMEFRAMES timeframe,const int adx_period);
   int                     CreateADXWilder(const string symbol,const ENUM_TIMEFRAMES timeframe,const int adx_period);
   int                     CreateAlligator(const string symbol,const ENUM_TIMEFRAMES timeframe,
                                       const int jaw_period,
                                       const int jaw_shift,
                                       const int teeth_period,
                                       const int teeth_shift,
                                       const int lips_period,
                                       const int lips_shift,
                                       const ENUM_MA_METHOD ma_method,
                                       const ENUM_APPLIED_PRICE applied_price);
   int                     CreateAMA(const string symbol,const ENUM_TIMEFRAMES timeframe,
                                       const int ama_period,
                                       const int fast_ema_period,
                                       const int slow_ema_period,
                                       const int ama_shift,
                                       const ENUM_APPLIED_PRICE applied_price);
   int                     CreateAO(const string symbol,const ENUM_TIMEFRAMES timeframe);
   int                     CreateATR(const string symbol,const ENUM_TIMEFRAMES timeframe,const int ma_period);
   int                     CreateBands(const string symbol,const ENUM_TIMEFRAMES timeframe,
                                       const int ma_period,
                                       const int ma_shift,
                                       const double deviation,
                                       const ENUM_APPLIED_PRICE applied_price);
   int                     CreateBearsPower(const string symbol,const ENUM_TIMEFRAMES timeframe,const int ma_period);
   int                     CreateBullsPower(const string symbol,const ENUM_TIMEFRAMES timeframe,const int ma_period);
   int                     CreateChaikin(const string symbol,const ENUM_TIMEFRAMES timeframe,
                                       const int fast_ma_period,
                                       const int slow_ma_period,
                                       const ENUM_MA_METHOD ma_method,
                                       const ENUM_APPLIED_VOLUME applied_volume);
   int                     CreateCCI(const string symbol,const ENUM_TIMEFRAMES timeframe,
                                       const int ma_period,
                                       const ENUM_APPLIED_PRICE applied_price);
   int                     CreateDEMA(const string symbol,const ENUM_TIMEFRAMES timeframe,
                                       const int ma_period,
                                       const int ma_shift,
                                       const ENUM_APPLIED_PRICE applied_price);
   int                     CreateDeMarker(const string symbol,const ENUM_TIMEFRAMES timeframe,const int ma_period);
   int                     CreateEnvelopes(const string symbol,const ENUM_TIMEFRAMES timeframe,
                                       const int ma_period,
                                       const int ma_shift,
                                       const ENUM_MA_METHOD ma_method,
                                       const ENUM_APPLIED_PRICE applied_price,
                                       const double deviation);
   int                     CreateForce(const string symbol,const ENUM_TIMEFRAMES timeframe,
                                       const int ma_period,
                                       const ENUM_MA_METHOD ma_method,
                                       const ENUM_APPLIED_VOLUME applied_volume);
   int                     CreateFractals(const string symbol,const ENUM_TIMEFRAMES timeframe);
   int                     CreateFrAMA(const string symbol,const ENUM_TIMEFRAMES timeframe,
                                       const int ma_period,
                                       const int ma_shift,
                                       const ENUM_APPLIED_PRICE applied_price);
   int                     CreateGator(const string symbol,const ENUM_TIMEFRAMES timeframe,
                                       const int jaw_period,
                                       const int jaw_shift,
                                       const int teeth_period,
                                       const int teeth_shift,
                                       const int lips_period,
                                       const int lips_shift,
                                       const ENUM_MA_METHOD ma_method,
                                       const ENUM_APPLIED_PRICE applied_price);
   int                     CreateIchimoku(const string symbol,const ENUM_TIMEFRAMES timeframe,
                                       const int tenkan_sen,
                                       const int kijun_sen,
                                       const int senkou_span_b);
   int                     CreateBWMFI(const string symbol,const ENUM_TIMEFRAMES timeframe,
                                       const ENUM_APPLIED_VOLUME applied_volume);
   int                     CreateMomentum(const string symbol,const ENUM_TIMEFRAMES timeframe,
                                       const int mom_period,
                                       const ENUM_APPLIED_PRICE applied_price);
   int                     CreateMFI(const string symbol,const ENUM_TIMEFRAMES timeframe,
                                       const int ma_period,
                                       const ENUM_APPLIED_VOLUME applied_volume);
   int                     CreateMA(const string symbol,const ENUM_TIMEFRAMES timeframe,
                                       const int ma_period,
                                       const int ma_shift,
                                       const ENUM_MA_METHOD ma_method,
                                       const ENUM_APPLIED_PRICE applied_price);
   int                     CreateOsMA(const string symbol,const ENUM_TIMEFRAMES timeframe,
                                       const int fast_ema_period,
                                       const int slow_ema_period,
                                       const int signal_period,
                                       const ENUM_APPLIED_PRICE applied_price);
   int                     CreateMACD(const string symbol,const ENUM_TIMEFRAMES timeframe,
                                       const int fast_ema_period,
                                       const int slow_ema_period,
                                       const int signal_period,
                                       const ENUM_APPLIED_PRICE applied_price);
   int                     CreateOBV(const string symbol,const ENUM_TIMEFRAMES timeframe,
                                       const ENUM_APPLIED_VOLUME applied_volume);
   int                     CreateSAR(const string symbol,const ENUM_TIMEFRAMES timeframe,
                                       const double step,
                                       const double maximum);
   int                     CreateRSI(const string symbol,const ENUM_TIMEFRAMES timeframe,
                                       const int ma_period,
                                       const ENUM_APPLIED_PRICE applied_price);
   int                     CreateRVI(const string symbol,const ENUM_TIMEFRAMES timeframe,const int ma_period);
   int                     CreateStdDev(const string symbol,const ENUM_TIMEFRAMES timeframe,
                                       const int ma_period,
                                       const int ma_shift,
                                       const ENUM_MA_METHOD ma_method,
                                       const ENUM_APPLIED_PRICE applied_price);
   int                     CreateStochastic(const string symbol,const ENUM_TIMEFRAMES timeframe,
                                       const int Kperiod,
                                       const int Dperiod,
                                       const int slowing,
                                       const ENUM_MA_METHOD ma_method,
                                       const ENUM_STO_PRICE price_field);
   int                     CreateTEMA(const string symbol,const ENUM_TIMEFRAMES timeframe,
                                       const int ma_period,
                                       const int ma_shift,
                                       const ENUM_APPLIED_PRICE applied_price);
   int                     CreateTriX(const string symbol,const ENUM_TIMEFRAMES timeframe,
                                       const int ma_period,
                                       const ENUM_APPLIED_PRICE applied_price);
   int                     CreateWPR(const string symbol,const ENUM_TIMEFRAMES timeframe,const int calc_period);
   int                     CreateVIDYA(const string symbol,const ENUM_TIMEFRAMES timeframe,
                                       const int cmo_period,
                                       const int ema_period,
                                       const int ma_shift,
                                       const ENUM_APPLIED_PRICE applied_price);
   int                     CreateVolumes(const string symbol,const ENUM_TIMEFRAMES timeframe,const ENUM_APPLIED_VOLUME applied_volume);

//--- Constructor
                           CIndicatorsCollection();

  };
//+------------------------------------------------------------------+

El listado parece bastante grande pero, en realidad, tenemos sólo varios grupos de los métodos del mismo tipo que se diferencian según el tipo del indicador requerido.

Los métodos que devuelven las listas con tipos necesarios de los indicadores son estandarizados para la biblioteca, y ya han sido considerados varias veces:

//--- Return (1) itself, (2) indicator list, (3) list of indicators by type
   CIndicatorsCollection  *GetObject(void)               { return &this;                                       }
   CArrayObj              *GetList(void)                 { return &this.m_list;                                }
//--- Return indicator list by (1) status, (2) type, (3) timeframe, (4) group, (5) symbol, (6) name, (7) short name
   CArrayObj              *GetListIndByStatus(const ENUM_INDICATOR_STATUS status)
                             { return CSelect::ByIndicatorProperty(this.GetList(),INDICATOR_PROP_STATUS,status,EQUAL);        }
   CArrayObj              *GetListIndByType(const ENUM_INDICATOR type)
                             { return CSelect::ByIndicatorProperty(this.GetList(),INDICATOR_PROP_TYPE,type,EQUAL);            }
   CArrayObj              *GetListIndByTimeframe(const ENUM_TIMEFRAMES timeframe)
                             { return CSelect::ByIndicatorProperty(this.GetList(),INDICATOR_PROP_TIMEFRAME,timeframe,EQUAL);  }
   CArrayObj              *GetListIndByGroup(const ENUM_INDICATOR_GROUP group)
                             { return CSelect::ByIndicatorProperty(this.GetList(),INDICATOR_PROP_GROUP,group,EQUAL);          }
   CArrayObj              *GetListIndBySymbol(const string symbol)
                             { return CSelect::ByIndicatorProperty(this.GetList(),INDICATOR_PROP_SYMBOL,symbol,EQUAL);        }
   CArrayObj              *GetListIndByName(const string name)
                             { return CSelect::ByIndicatorProperty(this.GetList(),INDICATOR_PROP_NAME,name,EQUAL);            }
   CArrayObj              *GetListIndByShortname(const string shortname)
                             { return CSelect::ByIndicatorProperty(this.GetList(),INDICATOR_PROP_SHORTNAME,shortname,EQUAL);  }

En el constructor de la clase, reseteamos la matriz de estructuras de los parámetros del indicador, limpiamos la lista de colección, establecemos la bandera de la lista ordenada para la lista y le asignamos un identificador de la colección de indicadores:

//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CIndicatorsCollection::CIndicatorsCollection()
  {
   ::ArrayResize(this.m_mql_param,0);
   this.m_list.Clear();
   this.m_list.Sort();
   this.m_list.Type(COLLECTION_INDICATORS_ID);
  }
//+------------------------------------------------------------------+

El método privado para crear el objeto de indicador simplemente crea un nuevo objeto de indicador dependiendo del tipo del indicador a crear transmitido al método y devuelve el puntero al objeto creado:

//+------------------------------------------------------------------+
//| Create a new indicator object                                    |
//+------------------------------------------------------------------+
CIndicatorDE *CIndicatorsCollection::CreateIndicator(const ENUM_INDICATOR ind_type,MqlParam &mql_param[],const string symbol_name=NULL,const ENUM_TIMEFRAMES period=PERIOD_CURRENT)
  {
   string symbol=(symbol_name==NULL || symbol_name=="" ? ::Symbol() : symbol_name);
   ENUM_TIMEFRAMES timeframe=(period==PERIOD_CURRENT ? ::Period() : period);
   CIndicatorDE *indicator=NULL;
   switch(ind_type)
     {
      case IND_AC          : indicator=new CIndAC(symbol,timeframe,mql_param);         break;
      case IND_AD          : indicator=new CIndAD(symbol,timeframe,mql_param);         break;
      case IND_ADX         : indicator=new CIndADX(symbol,timeframe,mql_param);        break;
      case IND_ADXW        : indicator=new CIndADXW(symbol,timeframe,mql_param);       break;
      case IND_ALLIGATOR   : indicator=new CIndAlligator(symbol,timeframe,mql_param);  break;
      case IND_AMA         : indicator=new CIndAMA(symbol,timeframe,mql_param);        break;
      case IND_AO          : indicator=new CIndAO(symbol,timeframe,mql_param);         break;
      case IND_ATR         : indicator=new CIndATR(symbol,timeframe,mql_param);        break;
      case IND_BANDS       : indicator=new CIndBands(symbol,timeframe,mql_param);      break;
      case IND_BEARS       : indicator=new CIndBears(symbol,timeframe,mql_param);      break;
      case IND_BULLS       : indicator=new CIndBulls(symbol,timeframe,mql_param);      break;
      case IND_BWMFI       : indicator=new CIndBWMFI(symbol,timeframe,mql_param);      break;
      case IND_CCI         : indicator=new CIndCCI(symbol,timeframe,mql_param);        break;
      case IND_CHAIKIN     : indicator=new CIndCHO(symbol,timeframe,mql_param);        break;
      case IND_DEMA        : indicator=new CIndDEMA(symbol,timeframe,mql_param);       break;
      case IND_DEMARKER    : indicator=new CIndDeMarker(symbol,timeframe,mql_param);   break;
      case IND_ENVELOPES   : indicator=new CIndEnvelopes(symbol,timeframe,mql_param);  break;
      case IND_FORCE       : indicator=new CIndForce(symbol,timeframe,mql_param);      break;
      case IND_FRACTALS    : indicator=new CIndFractals(symbol,timeframe,mql_param);   break;
      case IND_FRAMA       : indicator=new CIndFRAMA(symbol,timeframe,mql_param);      break;
      case IND_GATOR       : indicator=new CIndGator(symbol,timeframe,mql_param);      break;
      case IND_ICHIMOKU    : indicator=new CIndIchimoku(symbol,timeframe,mql_param);   break;
      case IND_MA          : indicator=new CIndMA(symbol,timeframe,mql_param);         break;
      case IND_MACD        : indicator=new CIndMACD(symbol,timeframe,mql_param);       break;
      case IND_MFI         : indicator=new CIndMFI(symbol,timeframe,mql_param);        break;
      case IND_MOMENTUM    : indicator=new CIndMomentum(symbol,timeframe,mql_param);   break;
      case IND_OBV         : indicator=new CIndOBV(symbol,timeframe,mql_param);        break;
      case IND_OSMA        : indicator=new CIndOsMA(symbol,timeframe,mql_param);       break;
      case IND_RSI         : indicator=new CIndRSI(symbol,timeframe,mql_param);        break;
      case IND_RVI         : indicator=new CIndRVI(symbol,timeframe,mql_param);        break;
      case IND_SAR         : indicator=new CIndSAR(symbol,timeframe,mql_param);        break;
      case IND_STDDEV      : indicator=new CIndStDev(symbol,timeframe,mql_param);      break;
      case IND_STOCHASTIC  : indicator=new CIndStoch(symbol,timeframe,mql_param);      break;
      case IND_TEMA        : indicator=new CIndTEMA(symbol,timeframe,mql_param);       break;
      case IND_TRIX        : indicator=new CIndTRIX(symbol,timeframe,mql_param);       break;
      case IND_VIDYA       : indicator=new CIndVIDYA(symbol,timeframe,mql_param);      break;
      case IND_VOLUMES     : indicator=new CIndVolumes(symbol,timeframe,mql_param);    break;
      case IND_WPR         : indicator=new CIndWPR(symbol,timeframe,mql_param);        break;
      
      case IND_CUSTOM : break;
      default: break;
     }
   return indicator;
  }
//+------------------------------------------------------------------+

Por defecto, así como de forma temporal para el indicador personalizado también (su creación será implementada en los siguientes artículos), el método devuelve NULL.

El método para crear el objeto de indicador Accelerator Oscillator:

//+------------------------------------------------------------------+
//| Create a new indicator object Accelerator Oscillator             |
//| and place it to the collection list                              |
//+------------------------------------------------------------------+
int CIndicatorsCollection::CreateAC(const string symbol,const ENUM_TIMEFRAMES timeframe)
  {
//--- AC indicator possesses no parameters - resize the array of parameter structures
   ::ArrayResize(this.m_mql_param,0);
//--- Create indicator object
   CIndicatorDE *indicator=this.CreateIndicator(IND_AC,this.m_mql_param,symbol,timeframe);
   if(indicator==NULL)
      return INVALID_HANDLE;
   int index=this.m_list.Search(indicator);
//--- If such indicator is already in the list
   if(index!=WRONG_VALUE)
     {
      //--- Get indicator object from the list and return indicator handle
      indicator=this.m_list.At(index);
      return indicator.Handle();
     }
//--- If such indicator is not in the list
   else
     {
      //--- If failed to add indicator object to the list
      //--- display the appropriate message and return INVALID_HANDLE
      if(!this.m_list.Add(indicator))
        {
         Print(CMessage::Text(MSG_LIB_SYS_FAILED_ADD_IND_TO_LIST));
         return INVALID_HANDLE;
        }
      //--- Return the handle of a new indicator added to the list
      return indicator.Handle();
     }
//--- Return INVALID_HANDLE
   return INVALID_HANDLE;
  }
//+------------------------------------------------------------------+

La lógica del método está descrita en su listado, y creo que no debe provocar dudas. Cabe notar que el objeto de indicador se crea en el método de su creación CreateIndicator() considerado anteriormente. El método recibe el tipo del indicador IND_AC. Como indicador AC no tiene parámetros de entrada, pues, la matriz de estructuras de los parámetros del indicador tampoco es necesaria. Por esa razón, la matriz se resetea, lo cual indica en la inutilidad de su uso durante la creación del indicador en la clase CIndicatorDE considerada en el artículo anterior.

Los demás métodos de la creación de otros indicadores estándar son idénticos en su lógica al método que acabamos de analizar, diferenciándose sólo en la especificación del indicador necesario y el relleno de la matriz de estructuras de los parámetros del indicador donde sea necesario.

Como ejemplo, vamos a analizar el método de la creación del indicador Alligator que requiere ocho parámetros de entrada. Todos ellos se añaden a la matriz de parámetros del indicador de acuerdo con el orden de secuencia de estos parámetros para el indicador Alligator, y el tipo IND_ALLIGATOR se transmite al método de la creación del objeto de indicador:

//+------------------------------------------------------------------+
//| Create new indicator object Alligator                            |
//| and place it to the collection list                              |
//+------------------------------------------------------------------+
int CIndicatorsCollection::CreateAlligator(const string symbol,const ENUM_TIMEFRAMES timeframe,
                                           const int jaw_period,
                                           const int jaw_shift,
                                           const int teeth_period,
                                           const int teeth_shift,
                                           const int lips_period,
                                           const int lips_shift,
                                           const ENUM_MA_METHOD ma_method,
                                           const ENUM_APPLIED_PRICE applied_price)
  {
//--- Add required indicator parameters to the array of parameter structures
   ::ArrayResize(this.m_mql_param,8);
   this.m_mql_param[0].type=TYPE_INT;
   this.m_mql_param[0].integer_value=jaw_period;
   this.m_mql_param[1].type=TYPE_INT;
   this.m_mql_param[1].integer_value=jaw_shift;
   this.m_mql_param[2].type=TYPE_INT;
   this.m_mql_param[2].integer_value=teeth_period;
   this.m_mql_param[3].type=TYPE_INT;
   this.m_mql_param[3].integer_value=teeth_shift;
   this.m_mql_param[4].type=TYPE_INT;
   this.m_mql_param[4].integer_value=lips_period;
   this.m_mql_param[5].type=TYPE_INT;
   this.m_mql_param[5].integer_value=lips_shift;
   this.m_mql_param[6].type=TYPE_INT;
   this.m_mql_param[6].integer_value=ma_method;
   this.m_mql_param[7].type=TYPE_INT;
   this.m_mql_param[7].integer_value=applied_price;
//--- Create indicator object
   CIndicatorDE *indicator=this.CreateIndicator(IND_ALLIGATOR,this.m_mql_param,symbol,timeframe);
   if(indicator==NULL)
      return INVALID_HANDLE;
   int index=this.m_list.Search(indicator);
//--- If such indicator is already in the list
   if(index!=WRONG_VALUE)
     {
      //--- Get indicator object from the list and return indicator handle
      indicator=this.m_list.At(index);
      return indicator.Handle();
     }
//--- If such indicator is not in the list
   else
     {
      //--- If failed to add indicator object to the list
      //--- display the appropriate message and return INVALID_HANDLE
      if(!this.m_list.Add(indicator))
        {
         Print(CMessage::Text(MSG_LIB_SYS_FAILED_ADD_IND_TO_LIST));
         return INVALID_HANDLE;
        }
      //--- Return the handle of a new indicator added to the list
      return indicator.Handle();
     }
//--- Return INVALID_HANDLE
   return INVALID_HANDLE;
  }
//+------------------------------------------------------------------+

Estas son todas las diferencias entre los métodos. No vamos a analizar los demás métodos de la creación de indicadores. Están disponibles en los archivos adjuntos al artículo.

El método que devuelve la lista de todos los objetos de indicador Accelerator Oscillator ubicados en la lista de colección, según el símbolo y marco temporal:

//+------------------------------------------------------------------+
//| Return the list of Accelerator Oscillator indicator objects      |
//| by symbol and timeframe                                          |
//+------------------------------------------------------------------+
CArrayObj *CIndicatorsCollection::GetListAC(const string symbol,const ENUM_TIMEFRAMES timeframe)
  {
   CArrayObj *list=GetListIndByType(IND_AC);
   list=CSelect::ByIndicatorProperty(list,INDICATOR_PROP_SYMBOL,symbol,EQUAL);
   return CSelect::ByIndicatorProperty(list,INDICATOR_PROP_TIMEFRAME,timeframe,EQUAL);
  }
//+------------------------------------------------------------------+

Primero, obtenemos la lista de todos los objetos de indicador de Accelerator Oscillator que se encuentran en la lista de colección.
Luego, filtramos las lista obtenida según el símbolo
y devolvemos la lista obtenida que ha sido filtrada de nuevo, ya según el marco temporal.

Los demás métodos son absolutamente idénticos al método analizado antes. La única diferencia es que primero obtenemos la lista de todos los indicadores necesarios de acuerdo con el cometido del método.

Por ejemplo, para obtener la lista de todos los objetos de indicador Accumulation/Distribution ubicados en la lista de colección, según el símbolo y marco temporal, el método será el siguiente:

//+------------------------------------------------------------------+
//| Return the list of indicator objects  Accumulation/Distribution  |
//| by symbol and timeframe                                          |
//+------------------------------------------------------------------+
CArrayObj *CIndicatorsCollection::GetListAD(const string symbol,const ENUM_TIMEFRAMES timeframe)
  {
   CArrayObj *list=GetListIndByType(IND_AD);
   list=CSelect::ByIndicatorProperty(list,INDICATOR_PROP_SYMBOL,symbol,EQUAL);
   return CSelect::ByIndicatorProperty(list,INDICATOR_PROP_TIMEFRAME,timeframe,EQUAL);
  }
//+------------------------------------------------------------------+

Aquí, primero, obtenemos la lista de todos los indicadores AD ubicados en la colección. Luego, filtramos la lista según el símbolo y el marco temporal como en el método analizado más arriba.

Hoy, implementamos sólo un método que devuelve el puntero al objeto de indicador en la colección según el tipo del indicador y sus parámetros (para el indicador Accelerator Oscillator):

//+------------------------------------------------------------------+
//| Return the pointer to Accelerator Oscillator indicator object    |
//+------------------------------------------------------------------+
CIndicatorDE *CIndicatorsCollection::GetIndAC(const string symbol,const ENUM_TIMEFRAMES timeframe)
  {
   CArrayObj *list=GetListAC(symbol,timeframe);
   return(list==NULL || list.Total()==0 ? NULL : list.At(0));
  }
//+------------------------------------------------------------------+

Puesto que este indicador (y algunos otros) no tiene parámetros de entrada, al seleccionarlo de la lista de colección según el símbolo y marco temporal, la lista va a contener sólo un objeto de indicador (por el índice 0) que corresponda al tipo IND_AC y al símbolo y marco temporal solicitados.
Mientras que los indicadores que poseen parámetros de entrada requieren los métodos adicionales de búsqueda en la matriz de estructuras de los parámetros del indicador para realizar su búsqueda según los parámetros especificados. Y eso ya excede de los límites del presente artículo. Por eso, analizaremos estos métodos en el siguiente artículo.

Como este artículo tiene una orientación más bien educativa y no pretende a estar completada, pues, vamos a simular solamente la creación de un objeto de indicador Accelerator Oscillator. En el artículo anterior, ya simulamos la creación de un objeto-indicador AC en la clase de colección de los búferes:

//+------------------------------------------------------------------+
//| Create multi-symbol multi-period AC                              |
//+------------------------------------------------------------------+
int CBuffersCollection::CreateAC(const string symbol,const ENUM_TIMEFRAMES timeframe,const int id=WRONG_VALUE)
  {
//--- To check it, create indicator object, print its data and remove it at once
   ::ArrayResize(this.m_mql_param,0);
   CIndicatorDE *indicator=new CIndicatorDE(IND_AC,symbol,timeframe,INDICATOR_STATUS_STANDART,INDICATOR_GROUP_OSCILLATOR,"Accelerator Oscillator","AC("+symbol+","+TimeframeDescription(timeframe)+")",this.m_mql_param);
   indicator.Print();
   delete indicator;

//--- Create the indicator handle and set the default ID

Hoy, hacemos la misma cosa. Es decir, en el mismo método, vamos a crear un objeto del indicador Accelerator Oscillator, pero en este caso, usando las clases nuevamente escritas.

Adelantándonos un poco, diremos que vamos a necesitar «ver» la lista de colección en la clase de colección de series temporales para que se nos abra la posibilidad de almacenar datos de todos los indicadores creados en los objetos de barras que «se encuentran» en las listas de series temporales.
Por eso, tenemos que incluir previamente la clase de colección de indicadores en la clase de colección de series temporales en el archivo \MQL5\Include\DoEasy\Collections\TimeSeriesCollection.mqh:

//+------------------------------------------------------------------+
//|                                         TimeSeriesCollection.mqh |
//|                        Copyright 2020, MetaQuotes Software Corp. |
//|                             https://mql5.com/es/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2020, MetaQuotes Software Corp."
#property link      "https://mql5.com/es/users/artmedia70"
#property version   "1.00"
//+------------------------------------------------------------------+
//| Include files                                                    |
//+------------------------------------------------------------------+
#include "ListObj.mqh"
#include "..\Objects\Series\TimeSeriesDE.mqh"
#include "..\Objects\Symbols\Symbol.mqh"
#include "IndicatorsCollection.mqh"
//+------------------------------------------------------------------+

Luego, declaramos el puntero a la clase de colección de indicadores en la sección privada de la clase:

//+------------------------------------------------------------------+
//| Symbol timeseries collection                                     |
//+------------------------------------------------------------------+
class CTimeSeriesCollection : public CBaseObjExt
  {
private:
   CListObj                m_list;                    // List of applied symbol timeseries
   CIndicatorsCollection  *m_indicators;              // Pointer to collection object of indicators
//--- Return the timeseries index by symbol name
   int                     IndexTimeSeries(const string symbol);
public:

Al final del listado de la clase, creamos el método de inicialización a través del cual vamos a transmitir el puntero al objeto de la colección de indicadores a la clase en el objeto principal de la biblioteca CEngine:

//--- Constructor
                           CTimeSeriesCollection();
//--- Get pointers to the indicator collection (the method is called in CollectionOnInit() method of the CEngine object)
   void                    OnInit(CIndicatorsCollection *indicators) { this.m_indicators=indicators;  }
  };
//+------------------------------------------------------------------+

En el archivo de la clase de colección de los búferes \MQL5\Include\DoEasy\Collections\BuffersCollection.mqh también declaramos el puntero al objeto de la colección de los indicadores:

//+------------------------------------------------------------------+
//| Collection of indicator buffers                                  |
//+------------------------------------------------------------------+
class CBuffersCollection : public CObject
  {
private:
   CListObj                m_list;                       // Buffer object list
   CTimeSeriesCollection  *m_timeseries;                 // Pointer to the timeseries collection object
   CIndicatorsCollection  *m_indicators;                 // Pointer to collection object of indicators
   MqlParam                m_mql_param[];                // Array of indicator parameters
//--- Return the index of the (1) last, (2) next drawn and (3) basic buffer
   int                     GetIndexLastPlot(void);
   int                     GetIndexNextPlot(void);
   int                     GetIndexNextBase(void);
//--- Create a new buffer object and place it to the collection list
   bool                    CreateBuffer(ENUM_BUFFER_STATUS status);
//--- Get data of the necessary timeseries and bars for working with a single buffer bar, and return the number of bars
   int                     GetBarsData(CBuffer *buffer,const int series_index,int &index_bar_period);

public:

Al método de la clase OnInit() le añadimos la asignación a este puntero de un valor que se transmite por el parámetro de entrada:

//--- Constructor
                           CBuffersCollection();
//--- Get pointers to collections of timeseries and indicators (the method is called in CollectionOnInit() method of the CEngine object)
   void                    OnInit(CTimeSeriesCollection *timeseries,CIndicatorsCollection *indicators)
                             { this.m_timeseries=timeseries; this.m_indicators=indicators;   }
  };
//+------------------------------------------------------------------+

En el método de la creación del indicador AC, cambiamos la creación del objeto de indicador realizada en el artículo anterior por su creación y obtención a través de la clase de colección de los indicadores:

//+------------------------------------------------------------------+
//| Create multi-symbol multi-period AC                              |
//+------------------------------------------------------------------+
int CBuffersCollection::CreateAC(const string symbol,const ENUM_TIMEFRAMES timeframe,const int id=WRONG_VALUE)
  {
//--- To check it, create indicator object, print its data and remove it at once
//--- Parameters are not needed for AC, therefore, reset the array of indicator parameter structures
   ::ArrayResize(this.m_mql_param,0);
//--- Create AC indicator and add it to collection
   this.m_indicators.CreateAC(symbol,timeframe);
//--- Get from collection of AC indicator object
   CIndicatorDE *indicator=this.m_indicators.GetIndAC(symbol,timeframe);
//--- Display all data of the created indicator in the journal, display its short description and remove indicator object
   indicator.Print();
   indicator.PrintShort();
   delete indicator;

//--- Create the indicator handle and set the default ID

Ahora, vamos a mejorar la clase del objeto principal de la biblioteca CEngine.
En el archivo \MQL5\Include\DoEasy\Engine.mqh escribimos la inclusión del archivo de la colección de los indicadores en el listado de la clase:

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

Declaramos el objeto de la clase de colección de los indicadores en la sección privada de la clase:

//+------------------------------------------------------------------+
//| Library basis class                                              |
//+------------------------------------------------------------------+
class CEngine
  {
private:
   CHistoryCollection   m_history;                       // Collection of historical orders and deals
   CMarketCollection    m_market;                        // Collection of market orders and deals
   CEventsCollection    m_events;                        // Event collection
   CAccountsCollection  m_accounts;                      // Account collection
   CSymbolsCollection   m_symbols;                       // Symbol collection
   CTimeSeriesCollection m_time_series;                  // Timeseries collection
   CBuffersCollection   m_buffers;                       // Collection of indicator buffers
   CIndicatorsCollection m_indicators;                   // Indicator collection
   CResourceCollection  m_resource;                      // Resource list
   CTradingControl      m_trading;                       // Trading management object
   CPause               m_pause;                         // Pause object
   CArrayObj            m_list_counters;                 // List of timer counters
   int                  m_global_error;                  // Global error code
   bool                 m_first_start;                   // First launch flag
   bool                 m_is_hedge;                      // Hedge account flag
   bool                 m_is_tester;                     // Flag of working in the tester
   bool                 m_is_market_trade_event;         // Account trading event flag
   bool                 m_is_history_trade_event;        // Account history trading event flag
   bool                 m_is_account_event;              // Account change event flag
   bool                 m_is_symbol_event;               // Symbol change event flag
   ENUM_TRADE_EVENT     m_last_trade_event;              // Last account trading event
   int                  m_last_account_event;            // Last event in the account properties
   int                  m_last_symbol_event;             // Last event in the symbol properties
   ENUM_PROGRAM_TYPE    m_program;                       // Program type
   string               m_name;                          // Program name
//--- Return the counter index by id
   int                  CounterIndex(const int id) const;
//--- Return the first launch flag
   bool                 IsFirstStart(void);
//--- Work with (1) order, deal and position, (2) account events
   void                 TradeEventsControl(void);
   void                 AccountEventsControl(void);
//--- (1) Working with a symbol collection and (2) symbol list events in the market watch window
   void                 SymbolEventsControl(void);
   void                 MarketWatchEventsControl(void);
//--- Return the last (1) market pending order, (2) market order, (3) last position, (4) position by ticket
   COrder              *GetLastMarketPending(void);
   COrder              *GetLastMarketOrder(void);
   COrder              *GetLastPosition(void);
   COrder              *GetPosition(const ulong ticket);
//--- Return the last (1) removed pending order, (2) historical market order, (3) historical order (market or pending one) by its ticket
   COrder              *GetLastHistoryPending(void);
   COrder              *GetLastHistoryOrder(void);
   COrder              *GetHistoryOrder(const ulong ticket);
//--- Return the (1) first and the (2) last historical market orders from the list of all position orders, (3) the last deal
   COrder              *GetFirstOrderPosition(const ulong position_id);
   COrder              *GetLastOrderPosition(const ulong position_id);
   COrder              *GetLastDeal(void);
//--- Retrieve a necessary 'ushort' number from the packed 'long' value
   ushort               LongToUshortFromByte(const long source_value,const uchar index) const;
   
public:

En la sección pública, vamos a escribir dos métodos para devolver el puntero al objeto de colección de los indicadores y puntero a la lista de indicadores de esta colección:

//--- Return the bar index on the specified timeframe chart by the current chart's bar index
   int                  IndexBarPeriodByBarCurrent(const int series_index,const string symbol,const ENUM_TIMEFRAMES timeframe)
                          { return this.m_time_series.IndexBarPeriodByBarCurrent(series_index,symbol,timeframe);  }
                          
//--- Return (1) the indicator collection, (2) the indicator list from the collection 
   CIndicatorsCollection *GetIndicatorsCollection(void)                                { return &this.m_indicators;           }
   CArrayObj           *GetListIndicators(void)                                        { return this.m_indicators.GetList();  }


Estos métodos nos serán útiles para invocar la colección de los indicadores desde nuestros programas.

Añadimos al método CollectionOnInit() la transmisión del puntero a la colección de los indicadores a las clases de colección de los búferes y series temporales:

//--- Pass the pointers to all the necessary collections to the trading class and the indicator buffer collection class
   void                 CollectionOnInit(void)
                          {
                           this.m_trading.OnInit(this.GetAccountCurrent(),m_symbols.GetObject(),m_market.GetObject(),m_history.GetObject(),m_events.GetObject());
                           this.m_buffers.OnInit(this.m_time_series.GetObject(),this.m_indicators.GetObject());
                           this.m_time_series.OnInit(this.m_indicators.GetObject());
                          }

Ahora, al inicializar la biblioteca, el puntero al objeto de colección de los indicadores será transmitido a todas las clases donde se requiere el acceso a la colección de los indicadores. Por tanto, ellas podrán trabajar con esta colección.

De momento, éstas son todas las mejoras necesarias para crear la clase de colección de los indicadores.

Prueba

Para la prueba, necesitaremos el indicador del artículo anterior sin ningunas alteraciones.
Simplemente, lo guardamos en la carpeta nueva \MQL5\Indicators\TestDoEasy\Part54\ con el nombre nuevo TestDoEasyPart54.mq5.

Compilamos el indicador y lo iniciamos en el gráfico.
En el diario, se mostrarán todos los parámetros del indicador creado Accelerator Oscillator y su descripción breve:

Account 8550475: Artyom Trishkin (MetaQuotes Software Corp.) 10425.23 USD, 1:100, Hedge, MetaTrader 5 demo
--- Initializing "DoEasy" library ---
Working with the current symbol only. The number of used symbols: 1
"EURUSD"
Working with the specified timeframe list:
"H4" "H1"
EURUSD symbol timeseries: 
- Timeseries "EURUSD" H1: Requested: 1000, Actual: 0, Created: 0, On the server: 0
- Timeseries "EURUSD" H4: Requested: 1000, Actual: 1000, Created: 1000, On the server: 6231
Library initialization time: 00:00:00.156
 
============= Parameter list start: "Standard indicator" =============
Indicator status: Standard indicator
Type of indicator: AC
Indicator timeframe: H4
Indicator handle: 10
Indicator group: Oscillator
------
Empty value for plotting where nothing will be drawn: EMPTY_VALUE
------
Indicator symbol: EURUSD
Indicator name: "Accelerator Oscillator"
Indicator short name: "AC(EURUSD,H4)"
================== Parameter list end: "Standard indicator" ==================
 
Standard indicator Accelerator Oscillator EURUSD H4
Buffer(P0/B0/C1): Histogram from the zero line EURUSD H4
Buffer[P0/B2/C2]: Calculated buffer
"EURUSD" H1 timeseries created successfully:
- Timeseries "EURUSD" H1: Requested: 1000, Actual: 1000, Created: 1000, On the server: 6256


¿Qué es lo próximo?

En el próximo artículo, continuaremos trabajando con la clase de colección de los indicadores.
.

Más abajo se adjuntan todos los archivos de la versión actual de la biblioteca y el archivo del indicador de prueba para MQL5. Puede descargarlo todo y ponerlo a prueba por sí mismo.
Nótese que, por el momento, la clase de colección de los indicadores se encuentra en el proceso del desarrollo. Por tanto, se recomienda estrictamente no usarla en sus programas.
Si tiene preguntas, observaciones o sugerencias, podrá concretarlas en los comentarios al artículo.

Volver al contenido

Artículos de esta serie:

Trabajando con las series temporales en la biblioteca DoEasy (Parte 35): El objeto "Barra" y la lista de serie temporal del símbolo
Trabajando con las series temporales en la biblioteca DoEasy (Parte 36): El objeto de series temporales de todos los periodos utilizados del símbolo
Trabajando con las series temporales en la biblioteca DoEasy (Parte 37): Colección de series temporales - Base de datos de series temporales según el símbolo y el periodo
Trabajando con las series temporales en la biblioteca DoEasy (Parte 38): Colección de series temporales - Actualización en tiempo real y acceso a los datos desde el programa
Trabajando con las series temporales en la biblioteca DoEasy (Parte 39): Indicadores basados en la biblioteca - Preparación de datos y eventos de la series temporales
Trabajando con las series temporales en la biblioteca DoEasy (Parte 40): Indicadores basados en la biblioteca - actualización de datos en tiempo real
Trabajando con las series temporales en la biblioteca DoEasy (Parte 41): Ejemplo de indicador de símbolo y periodo múltiples
Trabajando con las series temporales en la biblioteca DoEasy (Parte 42): La clase del objeto de búfer de indicador abstracto
Trabajando con las series temporales en la biblioteca DoEasy (Parte 43): Las clases de los objetos de búferes de indicador
Trabajando con las series temporales en la biblioteca DoEasy (Parte 44): Las clases de colección de los objetos de búferes de indicador
Trabajando con las series temporales en la biblioteca DoEasy (Parte 45): Búferes de indicador de periodo múltiple
Trabajando con las series temporales en la biblioteca DoEasy (Parte 46): Búferes de indicador de periodo y símbolos múltiples
Trabajando con las series temporales en la biblioteca DoEasy (Parte 47): Indicadores estándar de periodo y símbolo múltiples
Trabajando con las series temporales en la biblioteca DoEasy (Parte 48): Indicadores de periodo y símbolo múltiples en un búfer en una subventana
Trabajando con las series temporales en la biblioteca DoEasy (Parte 49): Indicadores estándar de periodo, símbolo y búfer múltiples
Trabajando con las series temporales en la biblioteca DoEasy (Parte 50): Indicadores estándar de periodo y símbolo múltiples con desplazamiento
Trabajando con las series temporales en la biblioteca DoEasy (Parte 51): Indicadores estándar compuestos de período y símbolo múltiples
Trabajando con las series temporales en la biblioteca DoEasy (Parte 52): Concepto multiplataforma de indicadores estándar de periodo y símbolo múltiples de búfer único
Trabajando con las series temporales en la biblioteca DoEasy (Parte 53): Clase del indicador abstracto básico

Traducción del ruso hecha por MetaQuotes Software Corp.
Artículo original: https://www.mql5.com/ru/articles/8508

Archivos adjuntos |
MQL5.zip (3831.26 KB)
Trabajando con las series temporales en la biblioteca DoEasy (Parte 53): Clase del indicador abstracto básico Trabajando con las series temporales en la biblioteca DoEasy (Parte 53): Clase del indicador abstracto básico

En este artículo, vamos a analizar la creación de la clase del indicador abstracto que a continuación va a usarse como una clase básica para crear objetos de los indicadores estándar y personalizados de la biblioteca.

Trabajando con las series temporales en la biblioteca DoEasy (Parte 52): Concepto multiplataforma de indicadores estándar de período y símbolo múltiples de búfer único Trabajando con las series temporales en la biblioteca DoEasy (Parte 52): Concepto multiplataforma de indicadores estándar de período y símbolo múltiples de búfer único

En el presente artículo, vamos a considerar la creación del indicador estándar de período y símbolo múltiples Accumulation/Distribution. Vamos a mejorar un poco las clases de la biblioteca en cuanto a los indicadores para que los programas escritos para la plataforma obsoleta MetaTrader 4 y basados en la biblioteca en cuestión puedan funcionar sin problema cuando los usamos en MetaTrader 5.

Optimización móvil continua (Parte 8): Mejorando el programa y corrigiendo los errores encontrados Optimización móvil continua (Parte 8): Mejorando el programa y corrigiendo los errores encontrados

A petición de los usuarios y lectores del presente ciclo de artículos, el programa ha sido modificado, y ahora podemos decir que el este artículo contiene la nueva versión del autooptimizador. Asimismo, hemos introducido en el autooptimizador tanto las mejoras solicitadas, como algunas nuevas cuya idea surgió durante la corrección del programa.

Redes neuronales: así de sencillo (Parte 3): Redes convolucionales Redes neuronales: así de sencillo (Parte 3): Redes convolucionales

Continuando el tema de la redes neuronales, proponemos al lector analizar las redes neuronales convolucionales. Este tipo de redes neuronales ha sido desarrollado para buscar objetos en una imagen. Asimismo, analizaremos cómo nos pueden ayudar al operar en los mercados financieros.