English Русский 中文 Español Deutsch 日本語
preview
Trabalhando com séries temporais na biblioteca DoEasy (Parte 54): classes herdeiras do indicador base abstrato

Trabalhando com séries temporais na biblioteca DoEasy (Parte 54): classes herdeiras do indicador base abstrato

MetaTrader 5Sistemas de negociação | 14 janeiro 2021, 09:17
496 0
Artyom Trishkin
Artyom Trishkin

Sumário


Ideia

No último artigo analisados como criar um objeto-indicador base abstrato. Hoje vamos criar seus objetos herdeiros, neles serão especificadas informações sobre um objeto-indicador específico que está sendo criado. Colocaremos todos esses objetos na coleção de indicadores a partir da qual será possível obter os dados e propriedades de cada indicador criado.
O conceito de objetos herdeiros é totalmente consistente com o de construção de objetos na biblioteca e sua interligação. A coleção de indicadores nos permitirá adicionar rapidamente a funcionalidade de evento a todos os objetos-indicadores no futuro, o que nos permitirá definir facilmente eventos de indicadores rastreados e usar esses eventos em nossos programas.


Aprimorando as classes da biblioteca

Como de costume, vamos começar adicionando as mensagens de texto da biblioteca necessárias.

No arquivo \MQL5\Include\DoEasy\Data.mqh inserimos os índices das novas mensagens:

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

e em seguida inserimos as novas mensagens que correspondem aos índices recém-adicionados:

   {"Статус индикатора","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"},
   
  };
//+---------------------------------------------------------------------+

Ao criar a classe do objeto do indicador abstrato no último artigo, não inserimos uma das propriedades inteiras do objeto - o tipo do indicador padrão. Este tipo corresponderá aos tipos de enumeração ENUM_INDICATOR, e serão necessários para encontrar um indicador específico.
Se quisermos encontrar todos os indicadores MACD armazenados numa coleção, a primeira coisa que precisamos fazer é obter uma lista com todos os indicadores MACD localizados na coleção. Para isso, precisamos filtrar a lista completa da coleção de indicadores pelo tipo IND_MACD, e somente então na lista resultante, que conterá apenas IND_MACDs, faremos uma escolha por outras propriedades obrigatórias.

Vamos adicionar uma nova propriedade do objeto-indicador ao arquivo \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
//+------------------------------------------------------------------+

e aumentamos o número de propriedades inteiras de 4 para 5.

Ao adicionar uma nova propriedade a um objeto, precisamos definir a capacidade de pesquisar e classificar objetos com base nessa propriedade.
Adicionamos um novo critério de classificação à enumeração:

//+------------------------------------------------------------------+
//| 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 modificar a classe do objeto do indicador abstrato no arquivo \MQL5\Include\DoEasy\Objects\Indicators\IndicatorDE.mqh.

Vamos transferir a matriz de estruturas de parâmetros do indicador desde a seção privada da classe para a protegida (esta matriz agora estará disponível para classes herdeiras), e na seção privada declararemos a variável para armazenar a descrição do tipo de 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
   

Na seção pública da classe escrevemos dois métodos, um para retornar o tipo de indicador e outro para retornar uma descrição do tipo de 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) {;}

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

No construtor paramétrico privado extraímos a substring do parâmetro de entrada do tipo de indicador para deixar apenas o próprio nome do indicador (por exemplo, de IND_MACD permanecerá MACD, que será a descrição do tipo de indicador), e escrevemos o tipo de indicador nas propriedades do 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;
  }
//+------------------------------------------------------------------+

No método que retorna a descrição da propriedade inteira do indicador, adicionamos um bloco de código para retornar uma descrição do tipo de 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)
         )  :
      ""
     );
  }
//+------------------------------------------------------------------+


Classes de objetos de indicadores

Agora temos que criar objetos herdeiros do indicador abstrato básico, o que irá refinar todas as informações sobre o objeto-indicador criado. Essas classes servirão para criar diferentes indicadores e receber dados deles.

No diretório \MQL5\Include\DoEasy\Objects\Indicators\ criamos uma nova pasta Standart, e nela, um novo arquivo IndAC.mqh da classe CIndAC do indicador padrão Accelerator Oscillator herdado da classe base do indicador abstrato cujo arquivo é anexado à listagem desta classe.
Como a classe será pequena, veremos imediatamente sua lista completa:

//+------------------------------------------------------------------+
//|                                                        IndAC.mqh |
//|                        Copyright 2020, MetaQuotes Software Corp. |
//|                             https://mql5.com/en/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2020, MetaQuotes Software Corp."
#property link      "https://mql5.com/en/users/artmedia70"
//+------------------------------------------------------------------+
//| 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()));
  }
//+------------------------------------------------------------------+

Precisaremos fazer um total de 38 dessas classes - com base no número de indicadores padrão (não estamos fazendo um indicador personalizado ainda, pois sua implementação será um pouco diferente).
Todas essas classes terão os mesmos métodos e serão diferentes apenas nos parâmetros passados para a classe pai desde seu construtor:

   //--- 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) {}

Nos parâmetros de entrada da classe, passamos o nome do símbolo, período gráfico e estrutura já preenchida dos parâmetros do indicador (neste exemplo, Accelerator Oscillator).
Na lista de inicialização passamos para o construtor paramétrico privado da classe pai (em ordem):

  • tipo de indicador — IND_AC, nome do símbolo, período gráfico
  • status do indicador — padrão
  • grupo do indicador — osciladores
  • nome do indicador — Accelerator Oscillator
  • nome curto do indicador — AC (símbolo, período gráfico) e a estrutura preenchida dos parâmetros do indicador

Já estamos familiarizados com todos os outros métodos graças aos objetos de biblioteca que criamos anteriormente. Eles executam exatamente as mesmas tarefas.
Métodos que retornam um sinalizador indicando que o objeto suporta propriedades inteiras e reais retornam true - todas as propriedades são suportadas por objetos-indicadores.
O método que retorna uma breve descrição do indicador retorna uma string deste tipo:

Standard indicator Accelerator Oscillator EURUSD H4

Em todos os outros arquivos de classes semelhantes de objetos indicadores, a única diferença estará no construtor da classe - os parâmetros correspondentes ao indicador serão passados para o construtor da classe pai.

Por exemplo, para o indicador de Accumulation/Distribution, o construtor da classe ficará assim:

   //--- 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 podemos ver, aqui já são transferidos os parâmetros correspondentes ao indicador padrão AD:

  • tipo de indicador — IND_AD, nome do símbolo, período gráfico
  • status do indicador — padrão
  • grupo do indicador — volumes
  • nome do indicador — Accumulation/Distribution
  • nome curto do indicador — AD (símbolo, período gráfico) e estrutura preenchida dos parâmetros do indicador

Todos os arquivos das classes herdeiras da classe base do indicador abstrato já foram implementados e podem ser visualizados independentemente nos arquivos anexados ao artigo na pasta \MQL5\Include\DoEasy\Objects\Indicators\Standart.

Coleção de objetos de indicadores

De acordo com o conceito geral de construção e armazenamento de objetos de biblioteca, agora precisamos colocar todos os objetos indicadores criados numa lista-coleção. Dessa lista, sempre podemos obter um ponteiro para o indicador de que precisamos pelas propriedades especificadas ou uma lista de indicadores com as mesmas propriedades comuns. Com base no ponteiro recebido para o indicador, já podemos pegar todos os dados retornados pelo indicador para cálculos posteriores.

Na pasta \MQL5\Include\DoEasy\Collections\ criamos uma nova classe no arquivo IndicatorsCollection.mqh.

Além dos métodos padrão da biblioteca que retornam as listas necessárias de objetos desde a coleção, a classe conterá um método privado para criar um objeto-indicador e muitos métodos para criar objetos-indicadores específicos de acordo com seu tipo, bem como muitos métodos para obter ponteiros para objetos-indicadores criados também por seus tipos. Visto que todos os métodos de cada grupo são logicamente idênticos entre si, consideraremos apenas alguns deles como exemplos.

Para que a coleção de classes de indicadores tenha acesso às classes de indicadores criadas por nós acima, precisamos anexá-las à lista de arquivos:

//+------------------------------------------------------------------+
//|                                         IndicatorsCollection.mqh |
//|                        Copyright 2020, MetaQuotes Software Corp. |
//|                             https://mql5.com/en/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2020, MetaQuotes Software Corp."
#property link      "https://mql5.com/en/users/artmedia70"
#property version   "1.00"
//+------------------------------------------------------------------+
//| Include files                                                    |
//+------------------------------------------------------------------+
#include "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 seguir, vamos ver a listagem completa do corpo da classe e, em seguida, analisaremos dois métodos de cada um dos 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();

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

A lista parece inacabada, mas na realidade existem apenas alguns grupos do mesmo tipo de métodos que diferem uns dos outros no tipo de indicador exigido.

Os métodos que retornam listas com os tipos de indicadores necessários são padrão para a biblioteca, e já os consideramos várias vezes:

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

No construtor da classe redefinimos a matriz de estruturas de parâmetros do indicador, limpamos a lista-coleção, definimos para a lista o sinalizador de lista classificada e atribuímos a ele o identificador de coleção do indicador:

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

O método privado para criar um objeto indicador simplesmente cria um novo objeto-indicador dependendo do tipo de indicador criado passado para o método e retorna um ponteiro para o objeto criado:

//+------------------------------------------------------------------+
//| 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 padrão, bem como temporariamente e para um indicador personalizado (sua criação será implementada em artigos subsequentes) o método retorna NULL.

O método que cria o objeto 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;
  }
//+------------------------------------------------------------------+

A lógica do método está descrita em sua listagem e acho que não deve levantar dúvidas. Observe que o objeto indicador é criado no método CreateIndicator(), que discutimos acima. Ao método é transferido o tipo de indicador IND_AC. Visto que o indicador AC não tem parâmetros de entrada, a matriz de estruturas de parâmetros do indicador também não é necessária. Por isso, a matriz é redefinida, o que indica que não é necessário usá-la ao criar um indicador na classe CIndicatorDE que vimos no último artigo.

Os métodos restantes para a criação de outros indicadores padrão são logicamente idênticos ao que acabamos de analisar e diferem apenas na especificação do indicador e no preenchimento da matriz de estruturas de parâmetros do indicador quando necessário.

Como exemplo veremos o método de criação do indicador Alligator, que requer oito parâmetros de entrada, sendo que todos eles são gravados na matriz de parâmetros do indicador de acordo com a ordem desses parâmetros no indicador Alligator e para o método para criar o objeto-indicador é passado o tipo IND_ALLIGATOR:

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

Essas são todas as diferenças entre cada método. Não consideraremos outros métodos de criação de indicadores - eles estão nos arquivos anexados ao artigo.

Método, que retorna uma lista de todos os objetos-indicadores Accelerator Oscillator, localizados na lista de coleção, por símbolo e período gráfico:

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

Primeiro, obtemos uma lista com todos os objetos-indicadores do Accelerator Oscillator localizados na lista-coleção,
em seguida, filtramos a lista resultante por símbolo
e retornamos a lista resultante, mais uma vez filtrada pelo período gráfico.

Os métodos restantes são completamente idênticos aos anteriores, exceto que, primeiro, obtemos uma lista com todos os indicadores necessários de acordo com o propósito do método.

Por exemplo, para obter uma lista contendo todos os objetos-indicadores Accumulation/Distribution localizados na lista-coleção por símbolo e período gráfico, o método será o seguinte:

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

Primeiro, obtemos uma lista contendo todos os indicadores AD, localizados na coleção e, em seguida, filtramos a lista por símbolo e período gráfico como no método acima.

Hoje vamos implementar apenas um método que retorna um ponteiro para um objeto-indicador na coleção pelo tipo de indicador e seus parâmetros - para o 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));
  }
//+------------------------------------------------------------------+

Visto que este indicador (e alguns outros) não tem parâmetros de entrada, ao selecioná-lo a partir da lista-coleção por símbolo e período gráfico, a lista conterá apenas um objeto-indicador (de índice 0)correspondente ao tipo IND_AC e ao símbolo e período gráfico solicitados.
Os mesmos indicadores que possuem parâmetros de entrada requerem, para implementar sua pesquisa com base nos parâmetros especificados, métodos de pesquisa adicionais segundo a matriz de estruturas de parâmetros do indicador, e isso fica além deste artigo. Portanto, tais métodos serão discutidos a seguir.

Como este artigo tem mais um propósito educativo e não pretende ser completo, testaremos apenas a criação de um objeto-indicador Accelerator Oscillator. No último artigo, já tínhamos esses teste para a criação de um indicador de objeto AC na classe-coleção de buffers:

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

Hoje faremos exatamente o mesmo. No mesmo método, criaremos um objeto do indicador Accelerator Oscillator, mas usando as classes recém-escritas.

Olhando para o futuro, direi que precisaremos "ver" a lista-coleção na classe de coleção da série temporal para que possamos armazenar os dados de todos os indicadores criados nos objetos-barras que "estão" nas listas da série temporal.
Por isso, primeiro precisamos anexar a classe-coleção de indicadores à classe de coleção da série temporal no arquivo \MQL5\Include\DoEasy\Collections\TimeSeriesCollection.mqh:

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

Mais adiante na seção privada da classe declaramos um ponteiro para uma classe-coleção de indicadores:

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

No final da listagem da classe criamos um método de inicialização através do qual passaremos para a classe um ponteiro para o objeto da coleção de indicadores no objeto principal da 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;  }
  };
//+------------------------------------------------------------------+

No arquivo da classe-coleção de buffers \MQL5\Include\DoEasy\Collections\BuffersCollection.mqh também declaramos um ponteiro para o objeto da coleção de 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:

Ao método da classe OnInit() adicionamos a atribuição a este ponteiro do valor passado pelo 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;   }
  };
//+------------------------------------------------------------------+

No método de criação do indicador AC, vamos mudar a criação do objeto-indicador que fizemos no último artigo para criá-lo e recebê-lo usando a classe-coleção de 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

Agora vamos modificar a classe do objeto principal da biblioteca CEngine.
No arquivo \MQL5\Include\DoEasy\Engine.mqh escrevemos a conexão à listagem da classe do arquivo da coleção de indicadores:

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

Na seção privada da classe declaramos um objeto da classe-coleção de indicadores:

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

Na seção pública, escreveremos dois métodos para retornar um ponteiro para o objeto-coleção de indicadores e um ponteiro para a lista de indicadores desta coleção:

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


Esses métodos serão úteis para acessarmos a coleção de indicadores a partir de nossos programas.

No método CollectionOnInit() adicionamos a transferência de um ponteiro para a coleção de indicadores para as classes-coleções de buffers e séries de tempo:

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

Agora, ao inicializar a biblioteca, um ponteiro para o objeto da coleção de indicadores será transferido a todas as classes que requerem acesso à coleção dos indicadores, e elas poderão trabalhar com esta coleção.

Hoje, essas são todas as melhorias necessárias para criar uma classe-coleção de indicadores.

Teste

Para o teste, precisamos um indicador do último artigo sem quaisquer alterações.
Simplemente, vamos salvá-lo numa nova pasta \MQL5\Indicators\TestDoEasy\Part54\ com o novo nome TestDoEasyPart54.mq5.

Vamos compilar o indicador e executá-lo no gráfico.
No log serão mostrados completamente todos os parâmetros do indicador Accelerator Oscillator criado e, depois, sua breve descrição:

Conta 8550475: Artyom Trishkin (MetaQuotes Software Corp.) 10425.23 USD, 1:100, Hedge, Conta de demonstração MetaTrader 5
--- Inicialização da biblioteca "DoEasy" ---
Trabalho apenas com o símbolo atual. 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


O que vem agora?

No próximo artigo, continuaremos trabalhando com a classe-coleção dos indicadores.

Todos os arquivos da versão atual da biblioteca e o arquivo do indicador de teste para MQL5 estão anexados abaixo. Você pode baixá-los e testar tudo sozinho.
Quero ressaltar que a classe-coleção de indicadores está atualmente em desenvolvimento, portanto, não é recomendável usá-la em nossos programas.
Se você tiver perguntas, comentários e sugestões, poderá expressá-los nos comentários do artigo.

Complementos

Artigos desta série:

Trabalhando com séries temporais na biblioteca DoEasy (Parte 35): Objeto "Barra" e lista-série temporal do símbolo
Trabalhando com séries temporais na biblioteca DoEasy (Parte 36): objeto das séries temporais de todos os períodos usados do símbolo
Trabalhando com séries temporais na biblioteca DoEasy (Parte 37): coleção de séries temporais - banco de dados de séries temporais para símbolos e períodos
Trabalhando com séries temporais na biblioteca DoEasy (Parte 38): coleção de séries temporais - atualização em tempo real e acesso aos dados do programa
Trabalhando com séries temporais na biblioteca DoEasy (Parte 39): indicadores com base na biblioteca - preparação de dados e eventos das séries temporais
Trabalhando com séries temporais na biblioteca DoEasy (Parte 40): indicadores com base na biblioteca - atualização de dados em tempo real
Trabalhando com séries temporais na biblioteca DoEasy (Parte 41): exemplo de indicador multissímbolo multiperíodo
Trabalhando com séries temporais na biblioteca DoEasy (Parte 42): classe de um objeto de buffer abstrato de indicador
Trabalhando com séries temporais na biblioteca DoEasy (Parte 43): classes de objetos de buffers de indicador
Trabalhando com séries temporais na biblioteca DoEasy (Parte 44): classe-coleção de objetos de buffers de indicador
Trabalhando com séries temporais na biblioteca DoEasy (Parte 45): buffers de indicador multiperíodo
Trabalhando com séries temporais na biblioteca DoEasy (Parte 46): buffers de indicador multiperíodos multissímbolos
Trabalhando com séries temporais na biblioteca DoEasy (Parte 47): indicadores padrão multiperíodos multissímbolos
Trabalhando com séries temporais na biblioteca DoEasy (Parte 48): indicadores multissímbolos multiperíodos num buffer de uma subjanela
Trabalhando com séries temporais na biblioteca DoEasy (Parte 49): indicadores padrão multiperíodos multissímbolos multibuffer
Trabalhando com séries temporais na biblioteca DoEasy (Parte 50): indicadores padrão multiperíodos multissímbolos com deslocamento
Trabalhando com séries temporais na biblioteca DoEasy (Parte 51): indicadores padrão multiperíodos multissímbolos compostos
Trabalhando com séries temporais na biblioteca DoEasy (Parte 52): natureza multiplataforma de indicadores padrão multiperíodos multissímbolos de buffer único
Trabalhando com séries temporais na biblioteca DoEasy (Parte 53): classe do indicador base abstrato

Traduzido do russo pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/ru/articles/8508

Arquivos anexados |
MQL5.zip (3835.27 KB)
Trabalhando com séries temporais na biblioteca DoEasy (Parte 55): classe-coleção de indicadores Trabalhando com séries temporais na biblioteca DoEasy (Parte 55): classe-coleção de indicadores
Neste artigo, continuaremos a desenvolver as classes de objetos-indicadores e suas coleções. Para cada objeto-indicador vamos criar uma descrição e ajustar a classe-coleção para armazenamento sem erros e recuperação de objetos-indicadores a partir da lista-coleção.
Trabalhando com séries temporais na biblioteca DoEasy (Parte 53): classe do indicador base abstrato Trabalhando com séries temporais na biblioteca DoEasy (Parte 53): classe do indicador base abstrato
Neste artigo, veremos a criação de uma classe de indicador abstrato que será posteriormente usada como uma classe base para a criação de objetos de indicadores padrão e personalizados da biblioteca.
Redes Neurais de Maneira Fácil (Parte 3): Redes Convolucionais Redes Neurais de Maneira Fácil (Parte 3): Redes Convolucionais
Como uma continuação do tópico das redes neurais, eu proponho ao leitor a análise das redes neurais convolucionais. Esse tipo de rede neural geralmente é aplicado para analisar imagens visuais. Neste artigo, nós consideraremos a aplicação dessas redes no mercado financeiro.
Otimização Walk Forward contínua (Parte 8): Melhorias e correções do programa Otimização Walk Forward contínua (Parte 8): Melhorias e correções do programa
O programa foi modificado com base nos comentários e solicitações dos usuários e leitores desta série de artigos. Este artigo contém uma nova versão do otimizador automático. Esta versão implementa os recursos solicitados e fornece outras melhorias, que eu descobri ao trabalhar com o programa.