Estendendo a biblioteca padrão do MQL5 e reutilizando o código

Jordi Bassaganas | 27 março, 2014

Introdução

A biblioteca padrão do MQL5 é uma estrutura baseada em objetos composta por um conjunto de classes prontas para uso, que tornam mais fácil a sua vida como desenvolvedor. No entanto, ela não implementa todas as necessidades de todos os desenvolvedores ao redor do mundo, então, se você achar que precisa de mais algum material de customização, você pode dar um passo a mais e estender. Este artigo o leva através da integração do indicador técnico Zig-Zag MetaQuotes' na biblioteca padrão. Seremos inspirados pela filosofia de design MetaQuotes' para alcançarmos o nosso objetivo.

Em poucas palavras, a IPA do MQL5 é destinada para que você se ​beneficie da reutilização, confiabilidade, flexibilidade e facilidade de manutenção do código. Isto é o que a teoria diz, mas, além de tudo isso, se você pretende continuar a avançar em MQL5 e desenvolver coisas mais sofisticadas, tais como Experts Advisors multi-moedas, em primeiro lugar você deve ser capaz de codificar no modo da biblioteca padrão, então seus aplicativos estão garantidos em uma vida bem sucedida.

Como seus EAs e indicadores tornam-se mais e mais complexos, é mais necessário dominar os conceitos envolvidos em uma estrutura de desenvolvimento. Como um exemplo da vida real, é minha necessidade pessoal desenvolver um EA multi-moeda complexo, que determina a necessidade de fortalecer a base do meu projeto a partir do zero.

Figura 1. Poliedros regulares são objetos perfeitos. Eles retratam bem a abordagem de criação de aplicativos em conceitos sólidos.

Figura 1. Poliedros regulares são objetos perfeitos. Eles retratam bem a abordagem de criação de aplicativos em conceitos sólidos

1. Download do ZigZag

Começamos baixando o indicador ZigZag MetaQuotes, que está disponível no Código Base, do nosso terminal MetaTrader 5. Isto criará os arquivos Indicators\zigzag.mq5 e Indicators\zigzag.ex5.

Figura 2. Começamos baixando o ZigZag MetaQuotes' a partir do nosso terminal MetaTrader 5

Figura 2. Começamos baixando o ZigZag MetaQuotes a partir do nosso terminal MetaTrader 5

Anexo aqui as linhas dos Indicators\zigzag.mq5 contendo os parâmetros de entrada do indicador, variáveis ​globais e o manipulador OnInit(). Eu coloco apenas essa parte porque o arquivo inteiro tem 298 linhas de código. Isto é simplesmente por conveniência e para a compreensão do panorama geral que estamos falando abaixo.

//+------------------------------------------------------------------+
//|                                                       ZigZag.mq5 |
//|                        Copyright 2009, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "2009, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property indicator_chart_window
#property indicator_buffers 3
#property indicator_plots   1
//---- plot Zigzag
#property indicator_label1  "Zigzag"
#property indicator_type1   DRAW_SECTION
#property indicator_color1  Red
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
//--- input parameters
input int      ExtDepth=12;
input int      ExtDeviation=5;
input int      ExtBackstep=3;
//--- indicator buffers
double         ZigzagBuffer[];      // main buffer
double         HighMapBuffer[];     // highs
double         LowMapBuffer[];      // lows
int            level=3;             // recounting depth
double         deviation;           // deviation in points
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,ZigzagBuffer,INDICATOR_DATA);
   SetIndexBuffer(1,HighMapBuffer,INDICATOR_CALCULATIONS);
   SetIndexBuffer(2,LowMapBuffer,INDICATOR_CALCULATIONS);

//--- set short name and digits   
   PlotIndexSetString(0,PLOT_LABEL,"ZigZag("+(string)ExtDepth+","+(string)ExtDeviation+","+(string)ExtBackstep+")");
   IndicatorSetInteger(INDICATOR_DIGITS,_Digits);
//--- set empty value
   PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0.0);
//--- to use in cycle
   deviation=ExtDeviation*_Point;
//---
   return(INIT_SUCCEEDED);
  }


2. Visão rápida de cima para baixo

Vamos agora adotar uma abordagem de cima para baixo para pensar em nosso novo indicador ZigZag orientado em objetos o qual queremos integrar na biblioteca padrão do MQL5. Isso significa que, primeiro, temos de olhar para todo o sistema e, em seguida, analisar as partes menores do mesmo. Então por que não codificamos um par de EAs simbólicos, a fim de ver um panorama maior? Vamos escrever um Expert Advisor de estilo processual juntamente com a sua versão orientada a objetos.


2.1. ZigZag pronto para uso

Desenvolvedores do MQL5 intermediários provavelmente usariam o indicador ZigZag em seus EAs assim:

//+----------------------------------------------------------------------+
//|                                            ExpertOriginalZigZag.mq5  |
//|                   Copyright © 2013, Laplacianlab - Jordi Bassagañas  | 
//+----------------------------------------------------------------------+
//--- EA properties
#property copyright     "Copyright © 2013, Laplacianlab - Jordi Bassagañas"
#property link          "https://www.mql5.com/pt/articles"
#property version       "1.00"
#property description   "This dummy Expert Advisor is just for showing how to use the original MetaQuotes' ZigZag indicator."
//--- EA inputs
input ENUM_TIMEFRAMES   EAPeriod=PERIOD_H1;
input string            CurrencyPair="EURUSD";
//--- global variables
int      zigZagHandle;
double   zigZagBuffer[];
double   zigZagHigh[];
double   zigZagLow[];
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   zigZagHandle=iCustom(CurrencyPair,EAPeriod,"zigzag",12,5,3);
   ArraySetAsSeries(zigZagBuffer,true);
   ArraySetAsSeries(zigZagHigh,true);
   ArraySetAsSeries(zigZagLow,true);  
   return(0);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   IndicatorRelease(zigZagHandle);
   ArrayFree(zigZagBuffer);
   ArrayFree(zigZagHigh);
   ArrayFree(zigZagLow);
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   //--- refresh data   
   if(CopyBuffer(zigZagHandle,0,0,2,zigZagBuffer)<0)
   {
      Print("Can't copy ZigZag buffer 0!");
      return;
   }
   if(CopyBuffer(zigZagHandle,1,0,2,zigZagHigh)<0)
   {
      Print("Can't copy ZigZag buffer 1!");
      return;
   }
   if(CopyBuffer(zigZagHandle,2,0,2,zigZagLow)<0)
   {
      Print("Can't copy ZigZag buffer 2!");
      return;
   }
   //--- print values
   if(zigZagBuffer[0]!=0) Print("zigZagBuffer[0]: ", zigZagBuffer[0]);
   if(zigZagHigh[0]!=0) Print("zigZagHigh[0]: ", zigZagHigh[0]);
   if(zigZagLow[0]!=0) Print("zigZagLow[0]: ", zigZagLow[0]);
  }
//+------------------------------------------------------------------+


2.2. ZigZag integrado na biblioteca padrão

Por outro lado, os desenvolvedores do MQL5 avançados vão querer trabalhar com o indicador ZigZag assim como eles já fazem com os indicadores da biblioteca padrão, desta forma:

//+----------------------------------------------------------------------+
//|                                                  ExpertOOZigZag.mq5  |
//|                   Copyright © 2013, Laplacianlab - Jordi Bassagañas  | 
//+----------------------------------------------------------------------+
#include <..\Include\Indicators\Custom\Trend.mqh>
//--- EA properties
#property copyright     "Copyright © 2013, Laplacianlab - Jordi Bassagañas"
#property link          "https://www.mql5.com/pt/articles"
#property version       "1.00"
#property description   "This dummy Expert Advisor is just for showing how to use the object-oriented version of MetaQuotes' ZigZag indicator."
//--- EA inputs
input ENUM_TIMEFRAMES   EAPeriod=PERIOD_H1;
input string            CurrencyPair="EURUSD";
//--- global variables
CiZigZag *ciZigZag;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   ciZigZag=new CiZigZag;
   ciZigZag.Create(CurrencyPair,EAPeriod,12,5,3);
   return(0);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   delete(ciZigZag);
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {   
   //--- refresh data
   ciZigZag.Refresh();
   //--- print values
   if(ciZigZag.ZigZag(0)!=0) Print("OO ZigZag buffer: ", ciZigZag.ZigZag(0));
   if(ciZigZag.High(0)!=0) Print("OO ZigZag high: ", ciZigZag.High(0));
   if(ciZigZag.Low(0)!=0) Print("OO ZigZag low: ",ciZigZag.Low(0));
  }
//+------------------------------------------------------------------+


2.3. Conclusão

A segunda solução é melhor porque é orientada a objetos. Uma vez que as classes OO foram desenvolvidas, é intuitivo observar que é muito mais fácil interagir com a funcionalidade orientada a objetos do ZigZag que trabalhar com a sua contraparte processual. Vamos recordar brevemente, de qualquer forma, as vantagens das quais nos beneficiamos ao trabalhar com uma biblioteca orientada a objetos:

Figura 3. Icosaedro regular. A construção de nossos aplicativos em conceitos sólidos é uma garantia de qualidade que faz com que nossos projetos persistam no tempo.

Figura 3. Icosaedro regular. A construção de nossos aplicativos em conceitos sólidos é uma garantia de qualidade que faz com que nossos projetos persistam no tempo


3. Integrando nosso novo ZigZag OO na biblioteca padrão do MQL5

Como eu disse na introdução deste artigo, estamos sendo inspirados no estilo orientado a objeto do MetaQuotes para construir o nosso novo conjunto de classes destinadas a envolver o ZigZag baixado antes. Isso é fácil, só temos que dar uma olhada nos arquivos dentro de Include\Indicators e estudar e compreender algumas das ideias que estão por trás da biblioteca padrão do MQL5. Quando você olha para o que há dentro do MetaQuotes logo perceberá que ele é cheio de classes representando alguns indicadores técnicos: ADX, Faixas de Bollinger, SAR, Médias móveis, etc. Todas essas classes herdam do CIndicator. Então vamos implementar este método. A propósito, a extensão do novo indicador OO de CiCustom da classe do MQL5 teria sido uma outra alternativa para implementar este exercício.

Vamos começar pela criação da nova pasta Include\Indicators\Custom e, logo depois, pela do novo arquivo Include\Indicators\Custom\Trend.mqh, para podermos codificar lá os nossos próprios indicadores técnicos, assim como MetaQuotes o faz em seu Include\Indicators\Trend.mqh. Aqui está o nosso arquivo de extensão já implementado Include\Indicators\Custom\Trend.mqh. Vou discutir abaixo alguns aspectos técnicos necessários para codificá-lo.

//+------------------------------------------------------------------+
//|                              Include\Indicators\Custom\Trend.mqh |
//|                  Copyright 2013, Laplacianlab - Jordi Bassagañas |
//|                     https://www.mql5.com/pt/users/laplacianlab |
//+------------------------------------------------------------------+
#include <..\Include\Indicators\Indicator.mqh>
//+------------------------------------------------------------------+
//| Class CiZigZag.                                                  |
//| Purpose: Class of the "ZigZag" indicator.                        |
//|          Derives from class CIndicator.                          |
//+------------------------------------------------------------------+
class CiZigZag : public CIndicator
  {
protected:
   int               m_depth;
   int               m_deviation;
   int               m_backstep;

public:
                     CiZigZag(void);
                    ~CiZigZag(void);
   //--- methods of access to protected data
   int               Depth(void)          const { return(m_depth);      }
   int               Deviation(void)      const { return(m_deviation);  }
   int               Backstep(void)       const { return(m_backstep);   }
   //--- method of creation
   bool              Create(const string symbol,const ENUM_TIMEFRAMES period,
                            const int depth,const int deviation_create,const int backstep);
   //--- methods of access to indicator data
   double            ZigZag(const int index) const;
   double            High(const int index) const;
   double            Low(const int index) const;
   //--- method of identifying
   virtual int       Type(void) const { return(IND_CUSTOM); }

protected:
   //--- methods of tuning
   virtual bool      Initialize(const string symbol,const ENUM_TIMEFRAMES period,const int num_params,const MqlParam &params[]);
   bool              Initialize(const string symbol,const ENUM_TIMEFRAMES period,
                                const int depth,const int deviation_init,const int backstep);
  };
//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CiZigZag::CiZigZag(void) : m_depth(-1),
                         m_deviation(-1),
                         m_backstep(-1)
  {
  }
//+------------------------------------------------------------------+
//| Destructor                                                       |
//+------------------------------------------------------------------+
CiZigZag::~CiZigZag(void)
  {
  }
//+------------------------------------------------------------------+
//| Create indicator "Zig Zag"                                       |
//+------------------------------------------------------------------+
bool CiZigZag::Create(const string symbol,const ENUM_TIMEFRAMES period,
                      const int depth,const int deviation_create,const int backstep)
  {
//--- check history
   if(!SetSymbolPeriod(symbol,period))
      return(false);
//--- create
   m_handle=iCustom(symbol,period,"zigzag",depth,deviation_create,backstep);
//--- check result
   if(m_handle==INVALID_HANDLE)
      return(false);
//--- indicator successfully created
   if(!Initialize(symbol,period,depth,deviation_create,backstep))
     {
      //--- initialization failed
      IndicatorRelease(m_handle);
      m_handle=INVALID_HANDLE;
      return(false);
     }
//--- ok
   return(true);
  }
//+------------------------------------------------------------------+
//| Initialize the indicator with universal parameters               |
//+------------------------------------------------------------------+
bool CiZigZag::Initialize(const string symbol,const ENUM_TIMEFRAMES period,const int num_params,const MqlParam &params[])
  {
   return(Initialize(symbol,period,(int)params[0].integer_value,(int)params[1].integer_value,(int)params[2].integer_value));
  }
//+------------------------------------------------------------------+
//| Initialize indicator with the special parameters                 |
//+------------------------------------------------------------------+
bool CiZigZag::Initialize(const string symbol,const ENUM_TIMEFRAMES period,
                        const int depth,const int deviation_init,const int backstep)
  {
   if(CreateBuffers(symbol,period,3))
     {
      //--- string of status of drawing
      m_name  ="ZigZag";
      m_status="("+symbol+","+PeriodDescription()+","+
               IntegerToString(depth)+","+IntegerToString(deviation_init)+","+
               IntegerToString(backstep)+") H="+IntegerToString(m_handle);
      //--- save settings
      m_depth=depth;
      m_deviation=deviation_init;
      m_backstep=backstep;       
      //--- create buffers
      ((CIndicatorBuffer*)At(0)).Name("ZIGZAG");
      ((CIndicatorBuffer*)At(1)).Name("HIGH");
      ((CIndicatorBuffer*)At(2)).Name("LOW");
      //--- ok
      return(true);
     }
//--- error
   return(false);
  }
//+------------------------------------------------------------------+
//| Access to ZigZag buffer of "Zig Zag"                             |
//+------------------------------------------------------------------+
double CiZigZag::ZigZag(const int index) const
  {
   CIndicatorBuffer *buffer=At(0);
//--- check
   if(buffer==NULL)
      return(EMPTY_VALUE);
//---
   return(buffer.At(index));
  }
//+------------------------------------------------------------------+
//| Access to High buffer of "Zig Zag"                               |
//+------------------------------------------------------------------+
double CiZigZag::High(const int index) const
  {
   CIndicatorBuffer *buffer=At(1);
//--- check
   if(buffer==NULL)
      return(EMPTY_VALUE);
//---
   return(buffer.At(index));
  }
//+------------------------------------------------------------------+
//| Access to Low buffer of "Zig Zag"                                |
//+------------------------------------------------------------------+
double CiZigZag::Low(const int index) const
  {
   CIndicatorBuffer *buffer=At(2);
//--- check
   if(buffer==NULL)
      return(EMPTY_VALUE);
//---
   return(buffer.At(index));
  }
//+------------------------------------------------------------------+


3.1. Encapsulação orientada a objeto

O encapsulamento OO é uma boa prática de programação que significa que membro de dados do objeto só pode ser modificado pelas operações definidas a eles. Todas as classes definidas no Trend.mqh do MetaQuotes implementam esta ideia, por isso estamos fazendo o mesmo.

Por um lado, existem propriedades protegidas específicas de CiZigZag:

protected:
   int               m_depth;
   int               m_deviation;
   int               m_backstep;

Subsequentemente, há interface pública CiZigZag para o acesso as propriedades protegidas definidas acima de fora de um determinado objeto do tipo CiZigZag:

public:
   //--- methods of access to protected data
   int               Depth(void)          const { return(m_depth);      }
   int               Deviation(void)      const { return(m_deviation);  }
   int               Backstep(void)       const { return(m_backstep);   }

Esta é uma medida de segurança para o isolamento de objetos. Este encapsulamento protege contra modificações arbitrárias realizadas por alguém ou algo que não tenha permissão para acessar os dados de objetos.


3.2. Acesso dos dados ZigZag

Como visto na primeira parte deste artigo, o arquivo de código­fonte chamado zigzag.mq5 cria três buffers:

//--- indicator buffers mapping
   SetIndexBuffer(0,ZigzagBuffer,INDICATOR_DATA);
   SetIndexBuffer(1,HighMapBuffer,INDICATOR_CALCULATIONS);
   SetIndexBuffer(2,LowMapBuffer,INDICATOR_CALCULATIONS);

Através de encapsulamento orientado a objetos, os métodos de CiZigZag, ZigZag (índice interno constante), de alta (índice interno constante) e de baixa (índice interno constante), retornam os buffers de indicadores que foram criados anteriormente no método de inicialização É importante notar que o wrapper orientado a objetos CIndicatorBuffer esteja definido na classe do MQL5 Include\Indicators\Indicator.mqh. CIndicatorBuffer é a peça central destes três métodos. Nós já estamos imersos na IPA do MQL5!

Como um exemplo aqui, este é o código para acessar o buffer máximo do CiZigZag:

//+------------------------------------------------------------------+
//| Access to High buffer of "Zig Zag"                               |
//+------------------------------------------------------------------+
double CiZigZag::High(const int index) const
  {
   CIndicatorBuffer *buffer=At(1);
//--- check
   if(buffer==NULL)
      return(EMPTY_VALUE);
//---
   return(buffer.At(index));
  }


3.3.
Polimorfismo, funções virtuais e de sobrecarga do método

Na seção anterior, brevemente discutimos o tópico de encapsulamento que é uma das características mais importantes da programação orientada a objeto. Bem, as classes contidas em Include\Indicators\Indicator.mqh e o arquivo Include\Indicators\Custom\Trend.mqh lidam com outros dois aspectos do paradigma da POO, polimorfismo e sobrecarregamento do método.

O polimorfismo tem a capacidade de acessar uma grande variedade de métodos através da mesma interface. Desta forma, um dado identificador pode assumir várias formas, dependendo do contexto no qual ele está situado. O polimorfismo requer o mecanismo hierárquico de modo que ele possa ser implementado. Por outro lado, a sobrecarga de método é uma outra característica da POO que permite a criação de vários métodos que compartilham o mesmo nome, mas com declarações de parâmetros diferentes.

Esta é uma introdução muito breve. Não há espaço suficiente neste artigo para discutir esses assuntos, então o aprofundamento neles é um exercício deixado para você. Por favor, leia as seções do MQL5 sobre Polimorfismo e sobrecarga. Em qualquer caso, vemos a biblioteca padrão implementar todos os recursos de POO, consequentemente, quanto melhor os conhecermos, melhor podemos estender a IPA para atender às nossas necessidades.

Com tudo o que foi dito, há apenas mais uma coisa a ser notada. O MQL5 implementa o polimorfismo através de um mecanismo chamado funções virtuais. Mais uma vez, por favor, leia a seção do MQL5 sobre as funções virtuais para entender como funciona.

É por isso que codificamos o método de inicialização do CiZigZag desta forma:

//+------------------------------------------------------------------+
//| Initialize the indicator with universal parameters               |
//+------------------------------------------------------------------+
bool CiZigZag::Initialize(const string symbol,const ENUM_TIMEFRAMES period,const int num_params,const MqlParam &params[])
  {
   return(Initialize(symbol,period,(int)params[0].integer_value,(int)params[1].integer_value,(int)params[2].integer_value));
  }
//+------------------------------------------------------------------+
//| Initialize indicator with the special parameters                 |
//+------------------------------------------------------------------+
bool CiZigZag::Initialize(const string symbol,const ENUM_TIMEFRAMES period,
                        const int depth,const int deviation_init,const int backstep)
  {
   if(CreateBuffers(symbol,period,3))
     {
      //--- string of status of drawing
      m_name  ="ZigZag";
      m_status="("+symbol+","+PeriodDescription()+","+
               IntegerToString(depth)+","+IntegerToString(deviation_init)+","+
               IntegerToString(backstep)+") H="+IntegerToString(m_handle);
      //--- save settings
      m_depth=depth;
      m_deviation=deviation_init;
      m_backstep=backstep;       
      //--- create buffers
      ((CIndicatorBuffer*)At(0)).Name("ZIGZAG");
      ((CIndicatorBuffer*)At(1)).Name("HIGH");
      ((CIndicatorBuffer*)At(2)).Name("LOW");
      //--- ok
      return(true);
     }
//--- error
   return(false);
  }

4. Testando o novo ZigZag OO, já disponível na biblioteca padrão

É claro que, antes de usar as extensões desenvolvidas por você em seus desenvolvimentos OO, você deve primeiro assegurar que eles funcionem como o esperado. Recomenda-se executar um conjunto compreensivo de testes em seus novos componentes personalizados. Por questões de simplicidade, no entanto, vamos agora executar um teste simples nos três métodos principais de CiZigZag, isto é, no ZigZag(índice interno constante), de alta(índice interno constante) e de baixa(índice interno constante).

Nós só imprimiremos os valores calculados por esses três métodos em cada tick dos EAs e, em seguida, compararemos a saída gerada pelo ExpertOriginalZigZag.ex5, o EA processual simbólico, com a saída gerada pelo ExpertOOZigZag.ex5, o EA orientado a objetos simbólico. Sempre que ambas as saídas obtidas forem as mesmas, podemos concluir que a nova extensão está OK, podemos tirar bom proveito do nosso ZigZag OO integrado na IPA do MQL5.

Figura 4. Estamos comparando a saída gerada pelo ExpertOriginalZigZag.ex5 com a gerada pelo ExpertOOZigZag.ex5

Figura 4. Estamos comparando a saída gerada pelo ExpertOriginalZigZag.ex5 com a gerada pelo ExpertOOZigZag.ex5

Consequentemente executamos tanto ExpertOriginalZigZag.ex5 quanto ExpertOOZigZag.ex5 e os dois EAs apresentados no início deste artigo no Strategy Tester com os seguintes parâmetros definidos:

Como ambos os robõs imprimem os mesmos resultados, concluímos que nosso CiZigZag está bem implementado, para que possamos usá-lo em nossos desenvolvimentos a partir de agora.

Log gerado pelo ExpertOriginalZigZag.ex5:

DE      0       18:45:39        ExpertOriginalZigZag (EURUSD,H1)        2013.08.01 08:50:40   zigZagBuffer[0]: 1.32657
ML      0       18:45:39        ExpertOriginalZigZag (EURUSD,H1)        2013.08.01 08:50:40   zigZagLow[0]: 1.32657
FL      0       18:45:39        ExpertOriginalZigZag (EURUSD,H1)        2013.08.01 08:50:59   zigZagBuffer[0]: 1.32657
GE      0       18:45:39        ExpertOriginalZigZag (EURUSD,H1)        2013.08.01 08:50:59   zigZagLow[0]: 1.32657
KS      0       18:45:39        ExpertOriginalZigZag (EURUSD,H1)        2013.08.01 08:51:00   zigZagBuffer[0]: 1.32657
FR      0       18:45:39        ExpertOriginalZigZag (EURUSD,H1)        2013.08.01 08:51:00   zigZagLow[0]: 1.32657
GK      0       18:45:39        ExpertOriginalZigZag (EURUSD,H1)        2013.08.01 08:51:20   zigZagBuffer[0]: 1.32653
RJ      0       18:45:39        ExpertOriginalZigZag (EURUSD,H1)        2013.08.01 08:51:20   zigZagLow[0]: 1.32653
OR      0       18:45:39        ExpertOriginalZigZag (EURUSD,H1)        2013.08.01 08:51:40   zigZagBuffer[0]: 1.32653
FS      0       18:45:39        ExpertOriginalZigZag (EURUSD,H1)        2013.08.01 08:51:40   zigZagLow[0]: 1.32653
QJ      0       18:45:39        ExpertOriginalZigZag (EURUSD,H1)        2013.08.01 08:51:59   zigZagBuffer[0]: 1.32653
PH      0       18:45:39        ExpertOriginalZigZag (EURUSD,H1)        2013.08.01 08:51:59   zigZagLow[0]: 1.32653
JQ      0       18:45:39        ExpertOriginalZigZag (EURUSD,H1)        2013.08.01 08:52:00   zigZagBuffer[0]: 1.32653
KP      0       18:45:39        ExpertOriginalZigZag (EURUSD,H1)        2013.08.01 08:52:00   zigZagLow[0]: 1.32653
RH      0       18:45:39        ExpertOriginalZigZag (EURUSD,H1)        2013.08.01 08:52:20   zigZagBuffer[0]: 1.32653
GI      0       18:45:39        ExpertOriginalZigZag (EURUSD,H1)        2013.08.01 08:52:20   zigZagLow[0]: 1.32653
GP      0       18:45:39        ExpertOriginalZigZag (EURUSD,H1)        2013.08.01 08:52:40   zigZagBuffer[0]: 1.32614
// More data here!..

Log gerado pelo ExpertOOZigZag.ex5:

RP      0       18:48:02        ExpertOOZigZag (EURUSD,H1)      2013.08.01 08:50:40   OO ZigZag buffer(0): 1.32657
HQ      0       18:48:02        ExpertOOZigZag (EURUSD,H1)      2013.08.01 08:50:40   OO ZigZag low(0): 1.32657
DI      0       18:48:02        ExpertOOZigZag (EURUSD,H1)      2013.08.01 08:50:59   OO ZigZag buffer(0): 1.32657
RH      0       18:48:02        ExpertOOZigZag (EURUSD,H1)      2013.08.01 08:50:59   OO ZigZag low(0): 1.32657
QR      0       18:48:02        ExpertOOZigZag (EURUSD,H1)      2013.08.01 08:51:00   OO ZigZag buffer(0): 1.32657
GS      0       18:48:02        ExpertOOZigZag (EURUSD,H1)      2013.08.01 08:51:00   OO ZigZag low(0): 1.32657
IK      0       18:48:02        ExpertOOZigZag (EURUSD,H1)      2013.08.01 08:51:20   OO ZigZag buffer(0): 1.32653
GJ      0       18:48:02        ExpertOOZigZag (EURUSD,H1)      2013.08.01 08:51:20   OO ZigZag low(0): 1.32653
EL      0       18:48:02        ExpertOOZigZag (EURUSD,H1)      2013.08.01 08:51:40   OO ZigZag buffer(0): 1.32653
OD      0       18:48:02        ExpertOOZigZag (EURUSD,H1)      2013.08.01 08:51:40   OO ZigZag low(0): 1.32653
OE      0       18:48:02        ExpertOOZigZag (EURUSD,H1)      2013.08.01 08:51:59   OO ZigZag buffer(0): 1.32653
IO      0       18:48:02        ExpertOOZigZag (EURUSD,H1)      2013.08.01 08:51:59   OO ZigZag low(0): 1.32653
DN      0       18:48:02        ExpertOOZigZag (EURUSD,H1)      2013.08.01 08:52:00   OO ZigZag buffer(0): 1.32653
RF      0       18:48:02        ExpertOOZigZag (EURUSD,H1)      2013.08.01 08:52:00   OO ZigZag low(0): 1.32653
PP      0       18:48:02        ExpertOOZigZag (EURUSD,H1)      2013.08.01 08:52:20   OO ZigZag buffer(0): 1.32653
RQ      0       18:48:02        ExpertOOZigZag (EURUSD,H1)      2013.08.01 08:52:20   OO ZigZag low(0): 1.32653
MI      0       18:48:02        ExpertOOZigZag (EURUSD,H1)      2013.08.01 08:52:40   OO ZigZag buffer(0): 1.32614
// More data here!..

Conclusão

A biblioteca padrão do MQL5 facilita a sua vida como desenvolvedor. No entanto, ela não implementa todas as necessidades de todos os desenvolvedores ao redor do mundo, então, sempre haverá algum ponto onde você precisará criar seu material de customização. À medida que seus EAs e indicadores tornam-se mais e mais complexos, é de maior necessidade dominar os conceitos envolvidos em uma estrutura de desenvolvimento. A extensão da biblioteca padrão do MQL5 é uma garantia de qualidade para que seus aplicativos tenham uma vida bem-sucedida.

Tiramos vantagem da reutilização do código fazendo primeiramente o download do indicador ZigZag do código base. Uma vez disponível em nosso terminal MetaTrader 5, fizemos uma abordagem de cima para baixo a fim de começar a pensar em nosso novo indicador ZigZag orientado a objetos. Realizamos um panorama geral em todo o sistema e em seguida continuamos a análise. Na primeira fase do desenvolvimento comparamos um EA simbólico usando o indicador Expert Advisor de estilo processual com a sua contraparte orientada a objetos.

Nós envolvemos o indicador ZigZag em uma classe orientada a objeto, que foi concebida de acordo com a filosofia de design MetaQuotes, a mesma aplicada à construção da biblioteca padrão. E, finalmente, executamos alguns testes simples concluindo que, o nosso novo invólucro CiZigZag, já integrado na IPA do MQL5, está bem implementado.