Você está na página 1de 42

01/01/2021 O poder do ZigZag (parte I).

Desenvolvimento da classe base do indicador - Artigos MQL5

Novo artigo
METATRADER 5 — EXEMPLOS

O PODER DO ZIGZAG (PARTE I). DESENVOLVIMENTO


DA CLASSE BASE DO INDICADOR
8 março 2019, 07:22

0 3 944
ANATOLI KAZHARSKI

Conteúdo
Introdução
Versão estendida do indicador ZigZag
Classe para obter os dados do indicador ZigZag
Visualização do conjunto de dados obtidos
EA para testar os resultados obtidos
Retomando o desenvolvimento da classe CZigZagModule
Conclusão

Introdução
Em um dos artigos anteriores, eu mostrei como um indicador como o Índice de Força Relativa (RSI) pode ser
apresentado. Em uma de suas versões, o resultado obtido pode ser usado para receber simultaneamente os sinais para
as condições de tendência e lateralizada. O indicador provavelmente carece de apenas uma coisa — a capacidade de
definir o comportamento dos preços, o que também pode ser muito importante para decidir quando negociar e quando
parar de negociar. 
Muitos pesquisadores simplesmente ignoram ou não prestam atenção o suficiente para determinar o comportamento do
preço. Ao mesmo tempo, são usados métodos complexos, que muitas vezes são “caixas pretas”, como aprendizado de
máquina ou redes neurais. A questão mais importante que surge nesse caso é quais dados enviar para o treinamento de
https://www.mql5.com/pt/articles/5543 1/42
01/01/2021 O poder do ZigZag (parte I). Desenvolvimento da classe base do indicador - Artigos MQL5

um determinado modelo. Neste artigo, nós vamos expandir as ferramentas para esses estudos. Você descobrirá como
selecionar os símbolos mais apropriados para negociação antes de procurar os parâmetros ideais. Para conseguir isso,
nós usaremos uma versão modificada do indicador ZigZag e o código da classe que simplifica significativamente a
obtenção e o trabalho com dados de indicadores pertencentes a esse tipo.
Nesta série de artigos, nós vamos implementar:

uma versão modificada do indicador ZigZag


uma classe para obter os dados do ZigZag
um EA para testar o processo de obtenção dos dados
indicadores que definem o comportamento do preço
um EA com uma interface gráfica para coletar as estatísticas de comportamento do preço
um EA seguidor dos sinais do ZigZag

Versão estendida do indicador ZigZag


Geralmente, os indicadores do tipo ZigZag são construídos com base nas máximas e mínimas das barras, sem considerar
o spread. Este artigo apresenta uma versão modificada, na qual um spread é considerado na construção dos segmentos
para os pontos extremos do ZigZag inferior. Supõe-se que os negócios devem ser realizados dentro do canal de preços
no sistema de negociação. Isso é importante, pois muitas vezes acontece do preço de compra (ask) ser
significativamente maior do que o de venda (bid). Por exemplo, isso pode acontecer durante a noite. Por isso, seria
errado construir um indicador apenas com base nos preços de venda (bid). Afinal de contas, não faz sentido construir os
pontos extremos inferiores do indicador baseados na mínima das barras se não houver a possibilidade de comprar a
esses preços. É claro que o spread pode ser levado em conta nas condições de negociação, mas é melhor quando tudo é
imediatamente visível no gráfico. Isso simplifica o desenvolvimento da estratégia de negociação, já que tudo é
inicialmente mais plausível.
Além disso, você também pode querer ver todos os pontos em que os valores extremos do ZigZag foram atualizados.
Neste caso, a imagem fica ainda mais completa. Agora vamos considerar o código do indicador. Nós vamos nos deter
apenas nos recursos e funções básicas.
Nós vamos precisar de dois buffers do indicador para construir os segmentos. Uma é para as máximas (maior máxima),
enquanto a outra é para mínimas (maior mínima). Eles devem ser exibidos como uma única linha no gráfico. Portanto,
nós vamos precisar de seis buffers do indicador, cinco dos quais serão exibidos no gráfico.

Vamos listar todos os buffers do indicador:

Preço de Ask mínimo. Os valores mínimos do ZigZag devem ser baseados neles
Preço de Bid máximo. Os valores máximos do ZigZag devem ser baseados neles
Máximas
Mínimas
Todos as máximas detectadas de um segmento ascendente
Todas as mínimas detectadas de um segmento descendente

https://www.mql5.com/pt/articles/5543 2/42
01/01/2021 O poder do ZigZag (parte I). Desenvolvimento da classe base do indicador - Artigos MQL5

#property indicator_chart_window
#property indicator_buffers 6
#property indicator_plots 5
//---
#property indicator_color1 clrRed
#property indicator_color2 clrCornflowerBlue
#property indicator_color3 clrGold
#property indicator_color4 clrOrangeRed
#property indicator_color5 clrSkyBlue

//--- buffers do indicador:


double low_ask_buffer[]; // Preço mínimo de Ask
double high_bid_buffer[]; // Preço máximo de Bid
double zz_H_buffer[]; // Máximas
double zz_L_buffer[]; // Mínmias
double total_zz_h_buffer[]; // Todas as máximas
double total_zz_l_buffer[]; // Todas as mínimas

Vamos adicionar a capacidade de definir o número de barras (NumberOfBars) nos parâmetros de entrada, a fim de
construir as linhas do indicador. Zero significa que todos os dados presentes no gráfico devem ser usados. O parâmetro
MinImpulseSize define o número de pontos, pelo qual o preço deve desviar do último valor extremo para começar a
construir um segmento direcionado de forma oposta. Além disso, vamos adicionar a capacidade de definir quais buffers
do indicador devem ser exibidos no gráfico, bem como a cor dos segmentos do ZigZag, como parâmetros adicionais.

//--- Parâmetros de entrada


input int NumberOfBars =0; // Número de barras
input int MinImpulseSize =100; // Pontos mínimos em um raio
input bool ShowAskBid =false; // Exibir ask/bid
input bool ShowAllPoints =false; // Exibir todos os pontos
input color RayColor =clrGold; // Cor do raio

No nível global, declare as variáveis auxiliares necessárias para calcular os valores extremos. Nós precisamos salvar os
índices dos pontos extremos calculados anteriormente, rastrear a direção do segmento atual, bem como salvar os
preços mínimos de compra (ask) e o máximo de venda (bid).

//--- Variáveis ZZ
int last_zz_max =0;
int last_zz_min =0;
int direction_zz =0;
double min_low_ask =0;
double max_high_bid =0;

A função FillAskBidBuffers() é usada para preencher os buffers do indicador para a mínima do preço de ask e a máxima
do preço de bid. Para o buffer de bid, salve os valores do array High, enquanto que para o buffer de ask, salve os
https://www.mql5.com/pt/articles/5543 3/42
01/01/2021 O poder do ZigZag (parte I). Desenvolvimento da classe base do indicador - Artigos MQL5

valores do array Low considerando o spread.

//+-------------------------------------------------------------------+
//| Preencher os buffers da Máxima de Bid e mínima de Ask do indicador|
//+-------------------------------------------------------------------+
void FillAskBidBuffers(const int i,const datetime &time[],const double &high[],const double &lo
{
//--- Sai se a data inicial não for atingida
if(time[i]<first_date)
return;
//---
high_bid_buffer[i] =high[i];
low_ask_buffer[i] =low[i]+(spread[i]*_Point);
}

A função FillIndicatorBuffers() serve para definir os pontos extremos do ZigZag. Os cálculos são realizados somente a
partir da data especificada dependendo do número de barras definidas no parâmetro de entrada MinImpulseSize. O
programa insere o bloco de código apropriado de acordo com a direção do segmento definida durante a chamada de
função anterior.

As seguintes condições são verificadas para definir a direção:

A direção atual do segmento ascendente


O Bid máximo atual excede a última máximo:
Se essa condição for atendida, (1) reconfigure a máxima anterior, (2) lembre-se do índice do array
de dados atual e (3) atribua o valor atual do Bid máximo aos elementos atuais dos buffers do
indicador.
Se essa condição não for atendida, a direção do segmento mudou e está na hora de verificar as
condições de formação do valor extremo inferior:
O Ask mínimo atual é menor que a última máxima
A distância entre o Ask mínimo atual e a última máxima do ZigZag excede o limite
especificado (MinImpulseSize).
Se essas condições forem atendidas, (1) lembre-se do índice atual do array de dados,
(2) salve a nova direção do segmento (descendente) na variável e (3) atribua o valor
atual do Ask mínimo aos elementos atuais dos buffers do indicador.
A direção atual do segmento é para baixo
O Ask mínimo atual é menor que a última mínima:
Se esta condição for satisfeita, (1) resete a mínima anterior, (2) lembre-se do índice atual do array
de dados e (3) atribua o valor atual de Ask mínimo aos elementos atuais dos buffers do indicador.
Se esta condição não for atendida, a direção do segmento mudou e é hora de verificar as condições
de formação do valor extremo superior:
O Bid máximo atual excede a última mínima
A distância entre o Bid máximo atual e a última mínima do ZigZag excede o limite
especificado (MinImpulseSize).
https://www.mql5.com/pt/articles/5543 4/42
01/01/2021 O poder do ZigZag (parte I). Desenvolvimento da classe base do indicador - Artigos MQL5

Se essas condições forem atendidas, (1) lembre-se do índice atual do array de dados,
(2) salve a nova direção do segmento (ascendente) na variável e (3) atribua o valor
atual de Bid máximo aos elementos atuais dos buffers do indicador.

O código da função FillIndicatorBuffers() pode ser visto em detalhes abaixo:

//+------------------------------------------------------------------+
//| Preenche os buffers do indicador ZZ |
//+------------------------------------------------------------------+
void FillIndicatorBuffers(const int i,const datetime &time[])
{
if(time[i]<first_date)
return;
//--- Se ZZ se move para cima
if(direction_zz>0)
{
//--- No caso de uma nova alta
if(high_bid_buffer[i]>=max_high_bid)
{
zz_H_buffer[last_zz_max] =0;
last_zz_max =i;
max_high_bid =high_bid_buffer[i];
zz_H_buffer[i] =high_bid_buffer[i];
total_zz_h_buffer[i] =high_bid_buffer[i];
}
//--- Se a direção mudou (para baixo)
else
{
if(low_ask_buffer[i]<max_high_bid &&
fabs(low_ask_buffer[i]-zz_H_buffer[last_zz_max])>MinImpulseSize*_Point)
{
last_zz_min =i;
direction_zz =-1;
min_low_ask =low_ask_buffer[i];
zz_L_buffer[i] =low_ask_buffer[i];
total_zz_l_buffer[i] =low_ask_buffer[i];
}
}
}
//--- Se ZZ se move para baixo
else
{
//--- No caso de uma nova baixa
if(low_ask_buffer[i]<=min_low_ask)
{
zz_L_buffer[last_zz_min] =0;
last_zz_min =i;
https://www.mql5.com/pt/articles/5543 5/42
01/01/2021 O poder do ZigZag (parte I). Desenvolvimento da classe base do indicador - Artigos MQL5
min_low_ask =low_ask_buffer[i];
zz_L_buffer[i] =low_ask_buffer[i];
total_zz_l_buffer[i] =low_ask_buffer[i];
}
//--- Se a direção mudou (para cima)
else
{
if(high_bid_buffer[i]>min_low_ask &&
fabs(high_bid_buffer[i]-zz_L_buffer[last_zz_min])>MinImpulseSize*_Point)
{
last_zz_max =i;
direction_zz =1;
max_high_bid =high_bid_buffer[i];
zz_H_buffer[i] =high_bid_buffer[i];
total_zz_h_buffer[i] =high_bid_buffer[i];
}
}
}
}

O código da função principal do indicador é exibido abaixo. O indicador é calculado apenas pelas barras formadas.
Depois disso, são definidos (1) os arrays e as variáveis como zero, (2) o número de barras para cálculo e o índice inicial.
Inicialmente, os dados de todos os elementos dos buffers do indicador são calculados e, após isso, são calculados
somente os dados da última barra. Depois de realizar os cálculos e verificações preliminares, os buffers do indicador
são calculados e preenchidos.

//+------------------------------------------------------------------+
//| Função de iteração do indicador personalizado |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,const int prev_calculated,const datetime &time[],
const double &open[],const double &high[],const double &low[],const double &clo
const long &tick_volume[],const long &volume[],const int &spread[])
{
//--- Evitar o cálculo a cada tick
if(prev_calculated==rates_total)
return(rates_total);
//--- Se este é o primeiro cálculo
if(prev_calculated==0)
{
//--- Define os buffers do indicador para zero
ZeroIndicatorBuffers();
//--- Define as variáveis para zero
ZeroIndicatorData();
//--- Verifica a quantidade de dados disponíveis
if(!CheckDataAvailable())
return(0);
https://www.mql5.com/pt/articles/5543 6/42
01/01/2021 O poder do ZigZag (parte I). Desenvolvimento da classe base do indicador - Artigos MQL5
//--- Se forem especificados mais dados para copiar, o valor atual é usado
DetermineNumberData();
//--- Define a plotagem de barras para cada símbolo a partir de
DetermineBeginForCalculate(rates_total);
}
else
{
//--- Calcula o último valor apenas
start=prev_calculated-1;
}
//--- Preenche os buffers do indicador High Bid e Low Ask
for(int i=start; i<rates_total; i++)
FillAskBidBuffers(i,time,high,low,spread);
//--- Preenche os buffers do indicador com dados
for(int i=start; i<rates_total-1; i++)
FillIndicatorBuffers(i,time);
//--- Retorna o tamanho do array de dados
return(rates_total);
}

O indicador no EURUSD D1 é exibido abaixo:

https://www.mql5.com/pt/articles/5543 7/42
01/01/2021 O poder do ZigZag (parte I). Desenvolvimento da classe base do indicador - Artigos MQL5

Fig. 1. Indicador ZigZag modificado no EURUSD D1

A próxima captura de tela exibe o indicador no EURMXN M5. Aqui nós podemos ver o spread crescendo
significativamente à noite. No entanto, o indicador é calculado considerando o spread.

https://www.mql5.com/pt/articles/5543 8/42
01/01/2021 O poder do ZigZag (parte I). Desenvolvimento da classe base do indicador - Artigos MQL5

Fig. 2. Indicador ZigZag modificado no EURMXN M5

Na próxima seção, nós consideraremos um código da classe com métodos que nos ajudam a obter todos os dados
necessários para definir o comportamento atual do preço.

Classe para obter os dados do indicador ZigZag


O preço se move de forma caótica e imprevisível. Movimentos lateralizados, quando o preço muda frequentemente de
direção, podem ser repentinamente substituídos por longas tendências unidirecionais, sem retrocessos. É necessário
monitorar sempre o estado atual, mas também é importante ter ferramentas para uma interpretação correta do
comportamento do preço. Isto pode ser alcançado pelo código da classe CZigZagModule com todos os métodos
necessários para trabalhar com os dados do ZigZag. Vamos ver como isso funciona.

https://www.mql5.com/pt/articles/5543 9/42
01/01/2021 O poder do ZigZag (parte I). Desenvolvimento da classe base do indicador - Artigos MQL5

Como nós podemos trabalhar com várias instâncias da classe simultaneamente, por exemplo, com dados do ZigZag de
diferentes períodos de tempo, talvez seja necessário visualizar os segmentos obtidos usando as linhas de tendência de
cores diferentes. Portanto, nós incluímos o arquivo ChartObjectsLines.mqh da biblioteca padrão para o arquivo da
classe CZigZagModule. A partir deste arquivo, nós vamos precisar da classe CChartObjectTrend para trabalhar com as
linhas de tendência. A cor das linhas de tendência pode ser especificada pelo método público
CZigZagModule::LinesColor(). A cor cinza (clrGray) é definida por padrão.

//+------------------------------------------------------------------+
//| ZigZagModule.mqh |
//| Copyright 2018, MetaQuotes Software Corp. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include <ChartObjects\ChartObjectsLines.mqh>
//+------------------------------------------------------------------+
//| Classe para a obtenção de dados do indicador ZigZag |
//+------------------------------------------------------------------+
class CZigZagModule
{
protected:
//--- linhas de segmento
CChartObjectTrend m_trend_lines[];

//--- Cor das linhas segmentadas


color m_lines_color;
//---
public:
CZigZagModule(void);
~CZigZagModule(void);
//---
public:
//--- Cor da linha
void LinesColor(const color clr) { m_lines_color=clr; }
};
//+------------------------------------------------------------------+
//| Construtor |
//+------------------------------------------------------------------+
CZigZagModule::CZigZagModule(void) : m_lines_color(clrGray)
{
// ...
}
//+------------------------------------------------------------------+
//| Destrutor |
//+------------------------------------------------------------------+
CZigZagModule::~CZigZagModule(void)
{
}

https://www.mql5.com/pt/articles/5543 10/42
01/01/2021 O poder do ZigZag (parte I). Desenvolvimento da classe base do indicador - Artigos MQL5

Antes de obter os dados do indicador ZigZag, nós precisamos definir o número de valores extremos necessários para o
trabalho. Para conseguir isso, nós devemos chamar o método CZigZagModule::CopyExtremums(). Os arrays dinâmicos
separados foram declarados para armazenar (1) as extremidades do preços, (2) índices das barras extremas, (3) o
tempo de suas barras e o (4) número de segmentos para construção das linhas de tendência em um gráfico. O tamanho
dos arrays é definido no mesmo método.

O número de segmentos é calculado automaticamente a partir do número de extremos especificados. Por exemplo, se
nós passarmos 1 para o método CZigZagModule::CopyExtremums(), nós recebemos os dados em uma máxima e
mínima. Neste caso, ele é apenas um segmento do indicador ZigZag. Se um valor maior que 1 for passado, o número de
segmentos é sempre igual ao número de extremos copiados multiplicado por 2 menos 1. Em outras palavras, o número
de segmentos sempre será ímpar:

Um extremo - 1 segmento
Dois extremos - 3 segmentos
Três extremos - 5 segmentos, etc.

class CZigZagModule
{
protected:
int m_copy_extremums; // Número de máximas/mínimas salvas
int m_segments_total; // Número de segmentos
//--- Preços extremos
double m_zz_low[];
double m_zz_high[];
//--- Índices das barras extremas
int m_zz_low_bar[];
int m_zz_high_bar[];
//--- Horário das barras extremas
datetime m_zz_low_time[];
datetime m_zz_high_time[];
//---
};
//+------------------------------------------------------------------+
//| Construtor |
//+------------------------------------------------------------------+
CZigZagModule::CZigZagModule(void) : m_copy_extremums(1),
m_segments_total(1)
{
CopyExtremums(m_copy_extremums);
}

//+------------------------------------------------------------------+
//| Número de extremos para trabalhar |
//+------------------------------------------------------------------+
void CZigZagModule::CopyExtremums(const int total)
{

https://www.mql5.com/pt/articles/5543 11/42
01/01/2021 O poder do ZigZag (parte I). Desenvolvimento da classe base do indicador - Artigos MQL5
if(total<1)
return;
//---
m_copy_extremums =total;
m_segments_total =total*2-1;
//---
::ArrayResize(m_zz_low,total);
::ArrayResize(m_zz_high,total);
::ArrayResize(m_zz_low_bar,total);
::ArrayResize(m_zz_high_bar,total);
::ArrayResize(m_zz_low_time,total);
::ArrayResize(m_zz_high_time,total);
::ArrayResize(m_trend_lines,m_segments_total);
}

Antes de nós começarmos a trabalhar com os dados do indicador ZigZag, coloque-os nos arrays da classe descrita acima
para um uso mais conveniente. Nós vamos precisar de campos auxiliares para serem usados como contadores de
extremos. 

Para obter os dados, nós precisamos do método CZigZagModule::GetZigZagData(). É necessário passar ele o array
contendo os dados iniciais do indicador ZigZag junto com o array de tempo. Estes dados de origem podem ser obtidos
usando as funções CopyBuffer() e CopyTime(). Antes de obter os valores necessários dos dados de origem, todos os
campos e arrays devem ser redefinidos. Em seguida, obtenha o número especificado dos extremos (1) dos preços, (2)
dos índices das barras e (3) do horário. 

A direção do segmento atual é definida no final do método. Aqui, se o horário do segmento da máxima atual exceder o
da mínima, a direção é para cima. Caso contrário, é para baixo.

class CZigZagModule
{
protected:
int m_direction; // Direção
int m_counter_lows; // Contador da Mínima
int m_counter_highs; // Contado da Máxima
//---
public:
//--- Obtém os dados
void GetZigZagData(const double &zz_h[],const double &zz_l[],const datetime &ti
//--- Redefine a estrutura
void ZeroZigZagData(void);

};
//+------------------------------------------------------------------+
//| Obtém os dados do ZigZag |
//+------------------------------------------------------------------+
void CZigZagModule::GetZigZagData(const double &zz_h[],const double &zz_l[],const datetime &tim
{
https://www.mql5.com/pt/articles/5543 12/42
01/01/2021 O poder do ZigZag (parte I). Desenvolvimento da classe base do indicador - Artigos MQL5

int h_total =::ArraySize(zz_h);


int l_total =::ArraySize(zz_l);
int total =h_total+l_total;
//--- Redefine as variáveis do ZZ
ZeroZigZagData();
//--- Mover ao longo dos valores copiados de ZZ em um loop
for(int i=0; i<total; i++)
{
//--- Se o número necessário de máximas e mínimas do ZZ já for recebido, saia do loop
if(m_counter_highs==m_copy_extremums && m_counter_lows==m_copy_extremums)
break;
//--- Gerencia o avanço além do array
if(i>=h_total || i>=l_total)
break;
//--- Preenche o array contendo o valor da máxima até que a quantia necessária seja copia
if(zz_h[i]>0 && m_counter_highs<m_copy_extremums)
{
m_zz_high[m_counter_highs] =zz_h[i];
m_zz_high_bar[m_counter_highs] =i;
m_zz_high_time[m_counter_highs] =time[i];
//---
m_counter_highs++;
}
//--- Preenche o array contendo o valor da mínima até que o valor necessário seja copiado
if(zz_l[i]>0 && m_counter_lows<m_copy_extremums)
{
m_zz_low[m_counter_lows] =zz_l[i];
m_zz_low_bar[m_counter_lows] =i;
m_zz_low_time[m_counter_lows] =time[i];
//---
m_counter_lows++;
}
}
//--- Define a direção do movimento do preço
m_direction=(m_zz_high_time[0]>m_zz_low_time[0])? 1 : -1;
}

Agora que os dados foram recebidos, nós podemos considerar outros métodos dessa classe. Para obter os preços
extremos, índices da barra extrema e o horário das barras em que esses extremos foram formados, basta chamar o
método apropriado (veja o código abaixo) especificando um índice extremo. Apenas o código do método
CZigZagModule::LowPrice() é fornecido aqui como exemplo, uma vez que são quase idênticos.

class CZigZagModule
{
public:

https://www.mql5.com/pt/articles/5543 13/42
01/01/2021 O poder do ZigZag (parte I). Desenvolvimento da classe base do indicador - Artigos MQL5
//--- Preço dos extremos por um índice especificado
double LowPrice(const int index);
double HighPrice(const int index);
//--- Índice de uma barra extrema por um índice especificado
int LowBar(const int index);
int HighBar(const int index);
//--- Horário de uma barra extrema por um índice especificado
datetime LowTime(const int index);
datetime HighTime(const int index);
};
//+------------------------------------------------------------------+
//| Valor da mínima pelo índice especificado |
//+------------------------------------------------------------------+
double CZigZagModule::LowPrice(const int index)
{
if(index>=::ArraySize(m_zz_low))
return(0.0);
//---
return(m_zz_low[index]);
}

Se você precisar obter o tamanho do segmento, chame o método CZigZagModule::SegmentSize() especificando o


índice do segmento como o único parâmetro. Dependendo se o índice especificado for um valor par ou ímpar, os índices
extremos são definidos de acordo com o tamanho do segmento calculado. Se o valor do índice for par, os índices
extremos combinam entre si e não precisam ser calculados dependendo da direção do segmento.

class CZigZagModule
{
public:
//--- Tamanho do segmento por um índice especificado
double SegmentSize(const int index);
};
//+------------------------------------------------------------------+
//| Retorna o tamanho do segmento pelo índice |
//+------------------------------------------------------------------+
double CZigZagModule::SegmentSize(const int index)
{
if(index>=m_segments_total)
return(-1);
//---
double size=0;
//--- Se o valor for par
if(index%2==0)
{
int i=index/2;
size=::fabs(m_zz_high[i]-m_zz_low[i]);

https://www.mql5.com/pt/articles/5543 14/42
01/01/2021 O poder do ZigZag (parte I). Desenvolvimento da classe base do indicador - Artigos MQL5
}
//--- Se o valor for ímpar
else
{
int l=0,h=0;
//---
if(Direction()>0)
{
h=(index-1)/2+1;
l=(index-1)/2;
}
else
{
h=(index-1)/2;
l=(index-1)/2+1;
}
//---
size=::fabs(m_zz_high[h]-m_zz_low[l]);
}
//---
return(size);
}

O método CZigZagModule::SegmentsSum() é usado para obter a soma de todos os segmentos. Tudo aqui é simples, já
que o método CZigZagModule::SegmentSize() descrito acima é chamado quando ele passa ao longo de todos os
segmentos em um loop.

class CZigZagModule
{
public:
//--- Soma de todos os segmentos
double SegmentsSum(void);
};
//+------------------------------------------------------------------+
//| Tamanho total de todos os segmentos |
//+------------------------------------------------------------------+
double CZigZagModule::SegmentsSum(void)
{
double sum=0.0;
//---
for(int i=0; i<m_segments_total; i++)
sum+=SegmentSize(i);
//---
return(sum);
}

https://www.mql5.com/pt/articles/5543 15/42
01/01/2021 O poder do ZigZag (parte I). Desenvolvimento da classe base do indicador - Artigos MQL5

Além disso, talvez seja necessário obter a soma de todos os segmentos direcionados apenas para cima ou para baixo. O
código para segmentos ascendentes é exibido abaixo como um exemplo. Tudo depende da direção do segmento atual.
Se for direcionado para cima, os índices atuais são usados em um loop para os cálculos. Se a direção atual for para
baixo, o cálculos devem ser iniciados a partir do primeiro índice com um deslocamento de um elemento para trás para
as máximas. Se você quiser obter a soma de todos os segmentos direcionados para baixo, use o mesmo método, tendo
uma única diferença se a direção atual for para cima, na qual o deslocamento acontece para as mínimas.

class CZigZagModule
{
public:
//--- Soma dos segmentos direcionados (1) para cima e (2) para baixo
double SumSegmentsUp(void);
double SumSegmentsDown(void);
};
//+------------------------------------------------------------------+
//| Retorna o tamanho de todos os segmentos ascendentes |
//+------------------------------------------------------------------+
double CZigZagModule::SumSegmentsUp(void)
{
double sum=0.0;
//---
for(int i=0; i<m_copy_extremums; i++)
{
if(Direction()>0)
sum+=::fabs(m_zz_high[i]-m_zz_low[i]);
else
{
if(i>0)
sum+=::fabs(m_zz_high[i-1]-m_zz_low[i]);
}
}
//---
return(sum);
}

Pode ser útil obter uma taxa percentual das somas de segmentos unidirecionais para o número total de segmentos no
conjunto. Para conseguir isso, use os métodos CZigZagModule::PercentSumSegmentsUp() e
CZigZagModule::PercentSumSegmentsDown(). Eles permitem obter a diferença percentual destas taxas — o método
CZigZagModule::PercentSumSegmentsDifference(), que por sua vez pode nos mostrar a direção do preço atual
(tendência). Se a diferença é insignificante, então o preço flutua uniformemente em ambas as direções (lateralizado). 

class CZigZagModule
{
public:
//--- Taxa percentual dos segmentos somados ao número total de todos os segmentos no conjunt
double PercentSumSegmentsUp(void);
https://www.mql5.com/pt/articles/5543 16/42
01/01/2021 O poder do ZigZag (parte I). Desenvolvimento da classe base do indicador - Artigos MQL5
g p( );
double PercentSumSegmentsDown(void);
//--- Diferença entre as somas dos segmentos
double PercentSumSegmentsDifference(void);
};
//+------------------------------------------------------------------+
//| Retorna o percentual da soma de todos os segmentos de alta |
//+------------------------------------------------------------------+
double CZigZagModule::PercentSumSegmentsUp(void)
{
double sum=SegmentsSum();
if(sum<=0)
return(0);
//---
return(SumSegmentsDown()/sum*100);
}
//+------------------------------------------------------------------+
//| Retorna o percentual da soma de todos os segmentos de baixa |
//+------------------------------------------------------------------+
double CZigZagModule::PercentSumSegmentsDown(void)
{
double sum=SegmentsSum();
if(sum<=0)
return(0);
//---
return(SumSegmentsUp()/sum*100);
}
//+------------------------------------------------------------------+
//| Retorna a diferença da soma de todos os segmentos em percentual |
//+------------------------------------------------------------------+
double CZigZagModule::PercentSumSegmentsDifference(void)
{
return(::fabs(PercentSumSegmentsUp()-PercentSumSegmentsDown()));
}

Para definir o comportamento do preço, nós precisamos de métodos para obter a duração dos segmentos separados e
todo o conjunto resultante. O método CZigZagModule::SegmentBars() serve para obter o número de barras no
segmento especificado. A lógica do código do método é a mesma que a do método CZigZagModule::SegmentSize() para
obter o tamanho do segmento. Portanto, não faz sentido fornecer o seu código aqui. 
Para obter o número total de barras no conjunto de dados obtidos, use o método
CZigZagModule::SegmentsTotalBars(). Aqui, são definidos os índices da barra inicial e final no conjunto e retornado a
diferença. O método CZigZagModule::SegmentsTotalSeconds() segue o mesmo princípio. A única diferença é que ele
retorna o número de segundos no conjunto. 

https://www.mql5.com/pt/articles/5543 17/42
01/01/2021 O poder do ZigZag (parte I). Desenvolvimento da classe base do indicador - Artigos MQL5

class CZigZagModule
{
public:
//--- Número de barras em um segmento especificado
int SegmentBars(const int index);
//--- (1) Número de barras e (2) segundos no conjunto de segmentos
int SegmentsTotalBars(void);
long SegmentsTotalSeconds(void);
};
//+------------------------------------------------------------------+
//| Número de barras de todos os segmentos |
//+------------------------------------------------------------------+
int CZigZagModule::SegmentsTotalBars(void)
{
int begin =0;
int end =0;
int l =m_copy_extremums-1;
//---
begin =(m_zz_high_bar[l]>m_zz_low_bar[l])? m_zz_high_bar[l] : m_zz_low_bar[l];
end =(m_zz_high_bar[0]>m_zz_low_bar[0])? m_zz_low_bar[0] : m_zz_high_bar[0];
//---
return(begin-end);
}
//+------------------------------------------------------------------+
//| Número de segundos de todos os segmentos |
//+------------------------------------------------------------------+
long CZigZagModule::SegmentsTotalSeconds(void)
{
datetime begin =NULL;
datetime end =NULL;
int l=m_copy_extremums-1;
//---
begin =(m_zz_high_time[l]<m_zz_low_time[l])? m_zz_high_time[l] : m_zz_low_time[l];
end =(m_zz_high_time[0]<m_zz_low_time[0])? m_zz_low_time[0] : m_zz_high_time[0];
//---
return(long(end-begin));
}

Muitas vezes, pode ser necessário descobrir a faixa de preços dentro do conjunto de dados observado. Para essa
finalidade, a classe apresenta métodos para obter os extremos mínimo e máximo, bem como a diferença entre eles
(faixa de preço).

class CZigZagModule
{
public:
//--- Valores da (1) mínima e (2) máxima do conjunto
https://www.mql5.com/pt/articles/5543 18/42
01/01/2021 O poder do ZigZag (parte I). Desenvolvimento da classe base do indicador - Artigos MQL5
double LowMinimum(void);
double HighMaximum(void);
//--- Faixa de preço
double PriceRange(void);
};
//+------------------------------------------------------------------+
//| Valor mínimo do conjunto |
//+------------------------------------------------------------------+
double CZigZagModule::LowMinimum(void)
{
return(m_zz_low[::ArrayMinimum(m_zz_low)]);
}
//+------------------------------------------------------------------+
//| Valor máximo do conjunto |
//+------------------------------------------------------------------+
double CZigZagModule::HighMaximum(void)
{
return(m_zz_high[::ArrayMaximum(m_zz_high)]);
}
//+------------------------------------------------------------------+
//| Faixa de preço |
//+------------------------------------------------------------------+
double CZigZagModule::PriceRange(void)
{
return(HighMaximum()-LowMinimum());
}

Ainda há outro conjunto de métodos da classe CZigZagModule que permite receber valores como:

SmallestSegment() – retorna o menor segmento nos dados obtidos.


LargestSegment() – retorna o maior segmento nos dados obtidos. 
LeastNumberOfSegmentBars() – retorna o menor número de barras em um segmento nos dados obtidos.
MostNumberOfSegmentBars() – retorna o maior número de barras em um segmento nos dados obtidos.

A classe já possui os métodos para obtenção do tamanho dos segmentos e o número de barras do segmento pelo índice
especificado. Portanto, será fácil entender o código dos métodos da lista acima. Todos eles são diferentes apenas nos
métodos chamados dentro deles, portanto, eu vou fornecer os códigos de apenas dois deles —
CZigZagModule::SmallestSegmen() e CZigZagModule::MostNumberOfSegmentBars().

class CZigZagModule
{
public:
//--- O menor segmento do conjunto
double SmallestSegment(void);
//--- O maior segmento do conjunto
double LargestSegment(void);

https://www.mql5.com/pt/articles/5543 19/42
01/01/2021 O poder do ZigZag (parte I). Desenvolvimento da classe base do indicador - Artigos MQL5
//--- O menor número de barras de um segmento no conjunto
int LeastNumberOfSegmentBars(void);
//--- O maior número de barras de um segmento no conjunto
int MostNumberOfSegmentBars(void);
};
//+------------------------------------------------------------------+
//| O menor segmento do conjunto |
//+------------------------------------------------------------------+
double CZigZagModule::SmallestSegment(void)
{
double min_size=0;
for(int i=0; i<m_segments_total; i++)
{
if(i==0)
{
min_size=SegmentSize(0);
continue;
}
//---
double size=SegmentSize(i);
min_size=(size<min_size)? size : min_size;
}
//---
return(min_size);
}
//+------------------------------------------------------------------+
//| O maior número de barras de um segmento no conjunto |
//+------------------------------------------------------------------+
int CZigZagModule::MostNumberOfSegmentBars(void)
{
int max_bars=0;
for(int i=0; i<m_segments_total; i++)
{
if(i==0)
{
max_bars=SegmentBars(0);
continue;
}
//---
int bars=SegmentBars(i);
max_bars=(bars>max_bars)? bars : max_bars;
}
//---
return(max_bars);
}

https://www.mql5.com/pt/articles/5543 20/42
01/01/2021 O poder do ZigZag (parte I). Desenvolvimento da classe base do indicador - Artigos MQL5

Ao buscar por padrões, nós podemos precisar definir quanto um segmento específico difere em tamanho (em %) do
anterior. Para resolver essas tarefas, use o método CZigZagModule::PercentDeviation().

class CZigZagModule
{
public:
//--- Desvio em porcentagem
double PercentDeviation(const int index);
};
//+------------------------------------------------------------------+
//| Desvio em percentagem |
//+------------------------------------------------------------------+
double CZigZagModule::PercentDeviation(const int index)
{
return(SegmentSize(index)/SegmentSize(index+1)*100);
}

Agora vamos ver como visualizar os dados obtidos e usar a classe CZigZagModule nos projetos personalizados.

Visualização do conjunto de dados obtidos


Depois de receber os identificadores do indicador ZigZag de diferentes períodos de tempo, nós podemos visualizar
segmentos no gráfico atual no qual o EA é iniciado. Vamos usar os objetos gráficos do tipo linha de tendência para
visualização. O método privado CZigZagModule::CreateSegment() é usado para criar objetos. Ele recebe o índice do
segmento e o sufixo (parâmetro opcional) usado para formar um nome exclusivo do objeto gráfico para evitar
duplicações no caso de você precisar exibir os dados do indicador do ZigZag com parâmetros diferentes e de diferentes
períodos gráficos. 

Os métodos públicos CZigZagModule::ShowSegments() e CZigZagModule::DeleteSegments() permitem exibir e


remover objetos gráficos.

class CZigZagModule
{
public:
//--- (1) Exibe e (2) exclui os objetos
void ShowSegments(const string suffix="");
void DeleteSegments(void);
//---
private:
//--- Cria objetos
void CreateSegment(const int segment_index,const string suffix="");
};
//+------------------------------------------------------------------+
//| Exibe os segmentos ZZ em um gráfico |

https://www.mql5.com/pt/articles/5543 21/42
01/01/2021 O poder do ZigZag (parte I). Desenvolvimento da classe base do indicador - Artigos MQL5
//+------------------------------------------------------------------+
void CZigZagModule::ShowSegments(const string suffix="")
{
for(int i=0; i<m_segments_total; i++)
CreateSegment(i,suffix);
}
//+------------------------------------------------------------------+
//| Remove os segmentos |
//+------------------------------------------------------------------+
void CZigZagModule::DeleteSegments(void)
{
for(int i=0; i<m_segments_total; i++)
{
string name="zz_"+string(::ChartID())+"_"+string(i);
::ObjectDelete(::ChartID(),name);
}
}

Os métodos para exibir os comentários em um gráfico foram adicionados à classe para obter rapidamente as
informações básicas sobre os dados dos indicadores obtidos. O código do método que mostra brevemente os dados do
indicador calculado é exibido abaixo.

class CZigZagModule
{
public:
//--- Comentário no gráfico
void CommentZigZagData();
void CommentShortZigZagData();
};
//+------------------------------------------------------------------+
//| Exibe os dados do ZigZag como um comentário no gráfico |
//+------------------------------------------------------------------+
void CZigZagModule::CommentShortZigZagData(void)
{
string comment="Current direction : "+string(m_direction)+"\n"+
"Copy extremums: "+string(m_copy_extremums)+
"\n---\n"+
"SegmentsTotalBars(): "+string(SegmentsTotalBars())+"\n"+
"SegmentsTotalSeconds(): "+string(SegmentsTotalSeconds())+"\n"+
"SegmentsTotalMinutes(): "+string(SegmentsTotalSeconds()/60)+"\n"+
"SegmentsTotalHours(): "+string(SegmentsTotalSeconds()/60/60)+"\n"+
"SegmentsTotalDays(): "+string(SegmentsTotalSeconds()/60/60/24)+
"\n---\n"+
"PercentSumUp(): "+::DoubleToString(SumSegmentsUp()/SegmentsSum()*100,2)+"\n"
"PercentSumDown(): "+::DoubleToString(SumSegmentsDown()/SegmentsSum()*100,2)+
"PercentDifference(): "+::DoubleToString(PercentSumSegmentsDifference(),2)+

https://www.mql5.com/pt/articles/5543 22/42
01/01/2021 O poder do ZigZag (parte I). Desenvolvimento da classe base do indicador - Artigos MQL5

"\n---\n"+
"SmallestSegment(): "+::DoubleToString(SmallestSegment()/_Point,0)+"\n"+
"LargestSegment(): "+::DoubleToString(LargestSegment()/_Point,0)+"\n"+
"LeastNumberOfSegmentBars(): "+string(LeastNumberOfSegmentBars())+"\n"+
"MostNumberOfSegmentBars(): "+string(MostNumberOfSegmentBars());
//---
::Comment(comment);
}

Vamos desenvolver um aplicativo para receber e visualizar os dados obtidos.

EA para testar os resultados obtidos


Vamos desenvolver um EA de teste simples para receber e visualizar os dados do indicador ZigZag. Nós não vamos
realizar as verificações adicionais para simplificar o código ao máximo possível. O principal objetivo do exemplo é
demonstrar o próprio princípio de obtenção dos dados. 

Inclua o arquivo que contém a classe CZigZagModule para o arquivo do EA e declare sua instância. Existem dois
parâmetros externos que permitem especificar o número de extremos a serem copiados e a distância mínima para
formar um novo segmento do indicador ZigZag. No nível global, nós também declaramos os arrays dinâmicos para obter
os dados de origem e uma variável para o manipulador do indicador. 

//+------------------------------------------------------------------+
//| TestZZ_01.mq5 |
//| Copyright 2018, MetaQuotes Software Corp. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include <ZigZagModule.mqh>
CZigZagModule zz_current;

//--- Parâmetros de entrada


input int CopyExtremum =3;
input int MinImpulseSize =0;

//--- Arrays para os dados iniciais


double l_zz[];
double h_zz[];
datetime t_zz[];

//--- Manipulador do indicador ZZ


int zz_handle_current=WRONG_VALUE;

https://www.mql5.com/pt/articles/5543 23/42
01/01/2021 O poder do ZigZag (parte I). Desenvolvimento da classe base do indicador - Artigos MQL5

Na função OnInit(), nós (1) recebemos o manipulador do indicador, (2) definimos o número de extremos para formar os
dados finais e a cor das linhas de segmento do conjunto obtido, bem como (3) definimos a ordem de indexação reversa
para os arrays de dados de origem.

//+------------------------------------------------------------------+
//| Função de inicialização do Expert |
//+------------------------------------------------------------------+
int OnInit(void)
{
//--- Caminho para o indicador ZZ
string zz_path="Custom\\ZigZag\\ExactZZ_Plus.ex5";
//--- Obtém o manipulador do indicador
zz_handle_current=::iCustom(_Symbol,_Period,zz_path,10000,MinImpulseSize,true,true);
//--- Define a cor para os segmentos e o número de extremos para obtê-lo
zz_current.LinesColor(clrRed);
zz_current.CopyExtremums(CopyExtremum);
//--- Define a ordem de indexação reversa (... 3 2 1 0)
::ArraySetAsSeries(l_zz,true);
::ArraySetAsSeries(h_zz,true);
::ArraySetAsSeries(t_zz,true);
return(INIT_SUCCEEDED);
}

Na função OnTick(), nós obtemos os dados do indicador pelo seu manipulador e o horário de abertura das barras. Então,
preparamos os dados finais chamando o método CZigZagModule::GetZigZagData(). Finalmente, nós visualizamos os
segmentos dos dados obtidos do indicador ZigZag e exibimos esses dados no gráfico como um comentário.

//+------------------------------------------------------------------+
//| Função Tick do Expert |
//+------------------------------------------------------------------+
void OnTick(void)
{
//--- Obtém os dados de origem
int copy_total=1000;
::CopyTime(_Symbol,_Period,0,copy_total,t_zz);
::CopyBuffer(zz_handle_current,2,0,copy_total,h_zz);
::CopyBuffer(zz_handle_current,3,0,copy_total,l_zz);
//--- Obtém os dados finais
zz_current.GetZigZagData(h_zz,l_zz,t_zz);
//--- Visualiza os segmentos em um gráfico
zz_current.ShowSegments();
//--- Exibe os valores dos dados no gráfico como um comentário
zz_current.CommentZigZagData();
}

https://www.mql5.com/pt/articles/5543 24/42
01/01/2021 O poder do ZigZag (parte I). Desenvolvimento da classe base do indicador - Artigos MQL5

Se nós executarmos o EA no testador de estratégia no modo de visualização, nós veremos o seguinte. 5 extremos de
alta e baixa foram obtidos nesse caso. Como resultado, 9 segmentos foram destacados em vermelho no gráfico.

Fig. 3. Demonstração no modo de visualização (um ZigZag)

Se nós precisarmos obter os dados do indicador ZigZag de diferentes períodos de tempo ao mesmo tempo, o código do
EA de teste deverá ser um pouco aprimorado. Vamos considerar um exemplo quando você precisa obter os dados de
três períodos gráficos. Neste caso, você precisa declarar três instâncias da classe CZigZagModule. O primeiro período
gráfico é retirado do gráfico atual no qual o EA foi iniciado. Deixe dois outros ser, por exemplo, M15 e H1.

#include <Addons\Indicators\ZigZag\ZigZagModule.mqh>
CZigZagModule zz_current;

https://www.mql5.com/pt/articles/5543 25/42
01/01/2021 O poder do ZigZag (parte I). Desenvolvimento da classe base do indicador - Artigos MQL5
CZigZagModule zz_m15;
CZigZagModule zz_h1;

Cada indicador tem sua própria variável para obter o manipulador:

//--- Manipulador do indicador ZZ


int zz_handle_current =WRONG_VALUE;
int zz_handle_m15 =WRONG_VALUE;
int zz_handle_h1 =WRONG_VALUE;

Em seguida, na função OnInit(), nós recebemos os manipuladores de forma separada para cada indicador, definindo
cores e o número de extremos:

//+------------------------------------------------------------------+
//| Função de inicialização do Expert |
//+------------------------------------------------------------------+
int OnInit(void)
{
//--- Caminho para o indicador ZZ
string zz_path="Custom\\ZigZag\\ExactZZ_Plus.ex5";
//--- Obtemos os manipuladores do indicador
zz_handle_current =::iCustom(_Symbol,_Period,zz_path,10000,MinImpulseSize,false,false);
zz_handle_m15 =::iCustom(_Symbol,PERIOD_M15,zz_path,10000,MinImpulseSize,false,false);
zz_handle_h1 =::iCustom(_Symbol,PERIOD_H1,zz_path,10000,MinImpulseSize,false,false);
//--- Define a cor dos segmentos
zz_current.LinesColor(clrRed);
zz_m15.LinesColor(clrCornflowerBlue);
zz_h1.LinesColor(clrGreen);
//--- Define o número de extremos para receber
zz_current.CopyExtremums(CopyExtremum);
zz_m15.CopyExtremums(CopyExtremum);
zz_h1.CopyExtremums(CopyExtremum);
//--- Define a ordem de indexação invertida (... 3 2 1 0)
::ArraySetAsSeries(l_zz,true);
::ArraySetAsSeries(h_zz,true);
::ArraySetAsSeries(t_zz,true);
return(INIT_SUCCEEDED);
}

Os dados são recebidos na função OnTick() como é exibido acima para cada instância do indicador ZigZag de forma
separada. Os comentários de apenas um indicador podem ser exibidos no gráfico. Nesse caso, nós olhamos os dados
brevemente para o período gráfico atual do indicador.

https://www.mql5.com/pt/articles/5543 26/42
01/01/2021 O poder do ZigZag (parte I). Desenvolvimento da classe base do indicador - Artigos MQL5

//+------------------------------------------------------------------+
//| Função Tick do Expert |
//+------------------------------------------------------------------+
void OnTick(void)
{
int copy_total=1000;
::CopyTime(_Symbol,_Period,0,copy_total,t_zz);
::CopyBuffer(zz_handle_current,2,0,copy_total,h_zz);
::CopyBuffer(zz_handle_current,3,0,copy_total,l_zz);
zz_current.GetZigZagData(h_zz,l_zz,t_zz);
zz_current.ShowSegments("_current");
zz_current.CommentShortZigZagData();
//---
::CopyTime(_Symbol,PERIOD_M15,0,copy_total,t_zz);
::CopyBuffer(zz_handle_m15,2,0,copy_total,h_zz);
::CopyBuffer(zz_handle_m15,3,0,copy_total,l_zz);
zz_m15.GetZigZagData(h_zz,l_zz,t_zz);
zz_m15.ShowSegments("_m15");
//---
::CopyTime(_Symbol,PERIOD_H1,0,copy_total,t_zz);
::CopyBuffer(zz_handle_h1,2,0,copy_total,h_zz);
::CopyBuffer(zz_handle_h1,3,0,copy_total,l_zz);
zz_h1.GetZigZagData(h_zz,l_zz,t_zz);
zz_h1.ShowSegments("_h1");
}

É assim que ele se parece:

https://www.mql5.com/pt/articles/5543 27/42
01/01/2021 O poder do ZigZag (parte I). Desenvolvimento da classe base do indicador - Artigos MQL5

Fig. 4. Demonstração no modo de visualização (três ZigZags)

Nós podemos ver que os extremos dos indicadores a partir de períodos gráficos maiores são deslocados ligeiramente
para a esquerda. A razão é que os topos e fundos são definidos pelo tempo de abertura das barras do período em que o
manipulador foi recebido. 

Retomando o desenvolvimento da classe CZigZagModule


Olhando para os resultados já obtidos, pode-se pensar que eles são suficientes para completar o trabalho com o
indicador ZigZag. Mas, na verdade, esse não é o caso. Nós precisamos continuar o desenvolvimento do código da classe
CZigZagModule preenchendo-o com novos métodos úteis. 

https://www.mql5.com/pt/articles/5543 28/42
01/01/2021 O poder do ZigZag (parte I). Desenvolvimento da classe base do indicador - Artigos MQL5

Até agora, nós obtivemos os dados do indicador ZigZag a partir da barra mais recente e se aprofundando nos dados
históricos. No entanto, talvez seja necessário nós obtermos também os dados em uma faixa de tempo específica. Para
conseguir isso, vamos escrever outro método CZigZagModule::GetZigZagData() com um conjunto diferente de
parâmetros. Nesta versão, nós receberemos os dados iniciais dentro do método, portanto, nós precisaremos do
manipulador do indicador, símbolo, período gráfico e o intervalo de tempo (datas de início e término) como
parâmetros.

Mais adiante, nós precisamos contar o número de máximas e mínimas nos dados obtidos de forma separada. Nesse caso,
o número de extremos para o trabalho futuro deve ser definido pela quantidade mínima entre esses contadores. 
O método de mesmo nome CZigZagModule::GetZigZagData() com outro conjunto de parâmetros é chamado aqui no
final. Nós consideramos esse conjunto acima, enquanto descrevemos como os arrays contendo os dados de origem
devem ser passados como parâmetros para a obtenção dos dados finais.

class CZigZagModule
{
private:
//--- Arrays para a obtenção dos dados de origem
double m_zz_lows_temp[];
double m_zz_highs_temp[];
datetime m_zz_time_temp[];
//---
public:
//--- Obtém os dados
void GetZigZagData(const int handle,const string symbol,const ENUM_TIMEFRAMES p
};
//+------------------------------------------------------------------+
//| Obtém os dados de ZZ do manipulador passado |
//+------------------------------------------------------------------+
void CZigZagModule::GetZigZagData(const int handle,const string symbol,const ENUM_TIMEFRAMES pe
{
//--- Obtém os dados de origem
::CopyTime(symbol,period,start_time,stop_time,m_zz_time_temp);
::CopyBuffer(handle,2,start_time,stop_time,m_zz_highs_temp);
::CopyBuffer(handle,3,start_time,stop_time,m_zz_lows_temp);
//--- Contadores
int lows_counter =0;
int highs_counter =0;
//--- Contagem das máximas
int h_total=::ArraySize(m_zz_highs_temp);
for(int i=0; i<h_total; i++)
{
if(m_zz_highs_temp[i]>0)
highs_counter++;
}
//--- Contagem das mínimas
int l_total=::ArraySize(m_zz_lows_temp);
https://www.mql5.com/pt/articles/5543 29/42
01/01/2021 O poder do ZigZag (parte I). Desenvolvimento da classe base do indicador - Artigos MQL5
for(int i=0; i<l_total; i++)
{
if(m_zz_lows_temp[i]>0)
lows_counter++;
}
//--- Obtém o número de extremos
int copy_extremums=(int)::fmin((double)highs_counter,(double)lows_counter);
CopyExtremums(copy_extremums);
//--- Mover ao longo dos valores copiados de ZZ em um loop
GetZigZagData(m_zz_highs_temp,m_zz_lows_temp,m_zz_time_temp);
}

Use os métodos CZigZagModule::SmallestMinimumTime() e CZigZagModule::LargestMaximumTime() para obter o


horário dos extremos da menor mínima e da maior máxima no conjunto de dados obtidos. 

class CZigZagModule
{
public:
//--- Horário da menor mínima
datetime SmallestMinimumTime(void);
//--- Horário da maior máxima
datetime LargestMaximumTime(void);
};
//+------------------------------------------------------------------+
//| Horário da menor mínima |
//+------------------------------------------------------------------+
datetime CZigZagModule::SmallestMinimumTime(void)
{
return(m_zz_low_time[::ArrayMinimum(m_zz_low)]);
}
//+------------------------------------------------------------------+
//| Horário da maior máxima |
//+------------------------------------------------------------------+
datetime CZigZagModule::LargestMaximumTime(void)
{
return(m_zz_high_time[::ArrayMaximum(m_zz_high)]);
}

Além disso, vamos expandir a lista de métodos para trabalhar com os segmentos do ZigZag. Pode ser conveniente obter
vários valores em variáveis passadas por referência de uma só vez. A classe apresenta três desses métodos:

SegmentBars() retorna os índices de barra inicial e final de um segmento especificado.


SegmentPrices() retorna os preços inicial e final de um segmento especificado.
SegmentTimes() retorna a hora inicial e final de um segmento especificado.
https://www.mql5.com/pt/articles/5543 30/42
01/01/2021 O poder do ZigZag (parte I). Desenvolvimento da classe base do indicador - Artigos MQL5

Uma estrutura semelhante está presente em outros métodos considerados anteriormente, portanto, apenas um código
de exemplo é fornecido abaixo. 

class CZigZagModule
{
public:
//--- Retorna as barras inicial e final de um segmento especificado
bool SegmentBars(const int index,int &start_bar,int &stop_bar);
//--- Retorna os preços inicial e final de um segmento especificado
bool SegmentPrices(const int index,double &start_price,double &stop_price);
//--- Retorna as horas de início e término de um segmento especificado
bool SegmentTimes(const int index,datetime &start_time,datetime &stop_time);
};
//+------------------------------------------------------------------+
//| Retorna as barras inicial e final de um segmento especificado |
//+------------------------------------------------------------------+
bool CZigZagModule::SegmentBars(const int index,int &start_bar,int &stop_bar)
{
if(index>=m_segments_total)
return(false);
//--- No caso de um número par
if(index%2==0)
{
int i=index/2;
//---
start_bar =(Direction()>0)? m_zz_low_bar[i] : m_zz_high_bar[i];
stop_bar =(Direction()>0)? m_zz_high_bar[i] : m_zz_low_bar[i];
}
//--- No caso de um número ímpar
else
{
int l=0,h=0;
//---
if(Direction()>0)
{
h=(index-1)/2+1;
l=(index-1)/2;
//---
start_bar =m_zz_high_bar[h];
stop_bar =m_zz_low_bar[l];
}
else
{
h=(index-1)/2;
l=(index-1)/2+1;
//---
start_bar =m_zz_low_bar[l];
https://www.mql5.com/pt/articles/5543 31/42
01/01/2021 O poder do ZigZag (parte I). Desenvolvimento da classe base do indicador - Artigos MQL5
stop_bar =m_zz_high_bar[h];
}
}
//---
return(true);
}

Suponha que nós temos um gráfico em M5 e recebemos os dados de H1. Nós buscamos por padrões a partir do período
gráfico H1 e precisamos definir o comportamento do preço de um determinado segmento do ZigZag a partir do período
H1 sob o atual. Em outras palavras, nós queremos saber como o segmento especificado foi formado em um período
gráfico menor.

Como mostrado na seção anterior, os extremos dos segmentos de períodos gráficos maiores são exibidos no período
atual pelo horário de abertura dos períodos gráficos maiores. Nós já temos o método CZigZagModule::SegmentTimes()
retornando a hora inicial e final de um segmento especificado. Se nós usarmos esse intervalo de tempo para obter os
dados do ZigZag a partir de um período gráfico menor, na maioria dos casos nós teremos muitos segmentos redundantes
realmente pertencentes a outros segmentos de um período gráfico maior. Vamos escrever mais um método
CZigZagModule::SegmentTimes() com outro conjunto de parâmetros no caso de ser necessária uma maior precisão.
Além disso, nós precisaremos de vários métodos auxiliares privados para receber os (1) dados de origem e os (2) índices
dos valores mínimos e máximos nos arrays passados. 

class CZigZagModule
{
private:
//--- Copia os dados de origem para os arrays passados
void CopyData(const int handle,const int buffer_index,const string symbol,
const ENUM_TIMEFRAMES period,datetime start_time,datetime stop_ti
double &zz_array[],datetime &time_array[]);
//--- Retorna o índice dos valores (1) mínimo e (2) máximo do array passado
int GetMinValueIndex(double &zz_lows[]);
int GetMaxValueIndex(double &zz_highs[]);
};
//+------------------------------------------------------------------+
//| Copia os dados de origem para os arrays passados |
//+------------------------------------------------------------------+
void CZigZagModule::CopyData(const int handle,const int buffer_index,const string symbol,
const ENUM_TIMEFRAMES period,datetime start_time,datetime stop_tim
double &zz_array[],datetime &time_array[])
{
::CopyBuffer(handle,buffer_index,start_time,stop_time,zz_array);
::CopyTime(symbol,period,start_time,stop_time,time_array);
}
//+------------------------------------------------------------------+
//| Retorna o índice do valor máximo do array passado |
//+------------------------------------------------------------------+
int CZigZagModule::GetMaxValueIndex(double &zz_highs[])
{
https://www.mql5.com/pt/articles/5543 32/42
01/01/2021 O poder do ZigZag (parte I). Desenvolvimento da classe base do indicador - Artigos MQL5
{
int max_index =0;
double max_value =0;
int total=::ArraySize(zz_highs);
for(int i=0; i<total; i++)
{
if(zz_highs[i]>0)
{
if(zz_highs[i]>max_value)
{
max_index =i;
max_value =zz_highs[i];
}
}
}
//---
return(max_index);
}
//+------------------------------------------------------------------+
//| Retorna o índice do valor mínimo do array passado |
//+------------------------------------------------------------------+
int CZigZagModule::GetMinValueIndex(double &zz_lows[])
{
int min_index =0;
double min_value =INT_MAX;
int total=::ArraySize(zz_lows);
for(int i=0; i<total; i++)
{
if(zz_lows[i]>0)
{
if(zz_lows[i]<min_value)
{
min_index =i;
min_value =zz_lows[i];
}
}
}
//---
return(min_index);
}

Outro método CZigZagModule::SegmentTimes() é implementado para receber o horário de início e término de um


segmento especificado, considerando um período gráfico menor. Isso requer alguma explicação. Os seguintes
parâmetros são passados para o método:

handle — manipulador do indicador ZigZag de um período gráfico menor.


https://www.mql5.com/pt/articles/5543 33/42
01/01/2021 O poder do ZigZag (parte I). Desenvolvimento da classe base do indicador - Artigos MQL5

highs_buffer_index — índice do buffer do indicador contendo os extremos máximos.


lows_buffer_index — índice do buffer do indicador contendo os extremos mínimos.
symbol — símbolo de menor período gráfico.
period — maior período gráfico.
in_period — menor período gráfico.
index — índice de segmento de maior período gráfico.

Valores de retorno dos parâmetros passados por referência:

start_time — horário de início do segmento considerando um período gráfico menor.


stop_time — horário final do segmento considerando um período gráfico menor.

Primeiro, nós precisamos obter o horário de abertura da primeira e da última barras de um segmento especificado. Para
fazer isso, chame o primeiro método CZigZagModule::SegmentTimes() descrito acima. 

Em seguida, use o método CZigZagModule::CopyData() para receber os dados sobre o horário das barras e extremos.
Dependendo da direção do segmento, nós obtemos os dados em uma determinada sequência. No caso da direção
ascendente, nós primeiro obtemos os dados sobre as mínimas do ZigZag de período gráfico menor que fazem parte do
segmento da primeira barra em um período gráfico maior. Depois disso, nós obtemos os dados sobre as máximas do
ZigZag de período gráfico menor que fazem parte do último segmento da barra em um período gráfico maior. No caso
da direção descendente, a sequência de ações é invertida. Primeiro, nós precisamos obter os dados sobre as máximas
seguidas de informações sobre as mínimas. 

Depois de receber os dados de origem, encontre o índices de valores máximos e mínimos. Usando esses índices, você
pode descobrir o horário de início e término do segmento analisado em um período gráfico menor.

class CZigZagModule
{
public:
//--- Retorna o horário de início e término de um segmento especificado considerando um perí
bool SegmentTimes(const int handle,const int highs_buffer_index,const int lows_
const string symbol,const ENUM_TIMEFRAMES period,const ENUM_T
const int index,datetime &start_time,datetime &stop_time);
};
//+------------------------------------------------------------------+
//| Retorna o horário de início e término de um segmento especificado|
//| considerando o período gráfico menor |
//+------------------------------------------------------------------+
bool CZigZagModule::SegmentTimes(const int handle,const int highs_buffer_index,const int lows_b
const string symbol,const ENUM_TIMEFRAMES period,const ENUM_TI
const int index,datetime &start_time,datetime &stop_time)
{
//--- Obtém o horário sem considerar o período gráfico atual
datetime l_start_time =NULL;
datetime l_stop_time =NULL;
if(!SegmentTimes(index,l_start_time,l_stop_time))
https://www.mql5.com/pt/articles/5543 34/42
01/01/2021 O poder do ZigZag (parte I). Desenvolvimento da classe base do indicador - Artigos MQL5
return(false);
//---
double zz_lows[];
double zz_highs[];
datetime zz_lows_time[];
datetime zz_highs_time[];
datetime start =NULL;
datetime stop =NULL;
int period_seconds=::PeriodSeconds(period);
//--- Obtém os dados de origem no caso da direção ascendente
if(SegmentDirection(index)>0)
{
//--- Dados na primeira barra do período gráfico maior
start =l_start_time;
stop =l_start_time+period_seconds;
CopyData(handle,lows_buffer_index,symbol,in_period,start,stop,zz_lows,zz_lows_time);
//--- Dados na última barra do período gráfico maior
start =l_stop_time;
stop =l_stop_time+period_seconds;
CopyData(handle,highs_buffer_index,symbol,in_period,start,stop,zz_highs,zz_highs_time);
}
//--- Obtém os dados de origem no caso da direção descendente
else
{
//--- Dados na primeira barra do período gráfico maior
start =l_start_time;
stop =l_start_time+period_seconds;
CopyData(handle,highs_buffer_index,symbol,in_period,start,stop,zz_highs,zz_highs_time);
//--- Dados na última barra do período gráfico maior
start =l_stop_time;
stop =l_stop_time+period_seconds;
CopyData(handle,lows_buffer_index,symbol,in_period,start,stop,zz_lows,zz_lows_time);
}
//--- Busca o índice do valor máximo
int max_index =GetMaxValueIndex(zz_highs);
//--- Busca pelo índice do valor mínimo
int min_index =GetMinValueIndex(zz_lows);
//--- Obtém o horário de início e término do segmento
start_time =(SegmentDirection(index)>0)? zz_lows_time[min_index] : zz_highs_time[max_index]
stop_time =(SegmentDirection(index)>0)? zz_highs_time[max_index] : zz_lows_time[min_index]
//--- Bem sucedido
return(true);
}

Agora vamos escrever um EA para testes. O período atual é M5. Use-o para iniciar o EA no modo de visualização do
testador de estratégia. Nós vamos receber os dados a partir de H1, assim como do período gráfico atual. O código do EA
https://www.mql5.com/pt/articles/5543 35/42
01/01/2021 O poder do ZigZag (parte I). Desenvolvimento da classe base do indicador - Artigos MQL5

é semelhante ao considerado anteriormente, então eu mostrarei apenas o funcionamento do conteúdo da OnTick()


aqui.

Primeiro, nós obteremos os dados de H1 usando o primeiro método e exibiremos os segmentos no gráfico para maior
clareza. Em seguida, obtenha os dados do ZigZag do período gráfico atual (M5) no intervalo de tempo do terceiro
(índice 2) segmento do ZigZag em H1. Para fazer isso, obtenha o início e o fim do segmento considerando o período
gráfico atual.

Então, obtenha os dados para o período gráfico atual usando o segundo método e também exiba os segmentos no
gráfico para garantir que tudo esteja bem.

//+------------------------------------------------------------------+
//| Função Tick do Expert |
//+------------------------------------------------------------------+
void OnTick(void)
{
int copy_total=1000;
int h_buff=2,l_buff=3;
//--- Primeiro método para obtenção dos dados
::CopyTime(_Symbol,PERIOD_H1,0,copy_total,t_zz);
::CopyBuffer(zz_handle_h1,h_buff,0,copy_total,h_zz);
::CopyBuffer(zz_handle_h1,l_buff,0,copy_total,l_zz);
zz_h1.GetZigZagData(h_zz,l_zz,t_zz);
zz_h1.ShowSegments("_h1");
//---
int segment_index =2;
int start_bar =0;
int stop_bar =0;
double start_price =0.0;
double stop_price =0.0;
datetime start_time =NULL;
datetime stop_time =NULL;
datetime start_time_in =NULL;
datetime stop_time_in =NULL;
//---
zz_h1.SegmentBars(segment_index,start_bar,stop_bar);
zz_h1.SegmentPrices(segment_index,start_price,stop_price);
zz_h1.SegmentTimes(segment_index,start_time,stop_time);
zz_h1.SegmentTimes(zz_handle_current,h_buff,l_buff,_Symbol,PERIOD_H1,_Period,segment_index,s

//--- Segundo método para obtenção dos dados


zz_current.GetZigZagData(zz_handle_current,_Symbol,_Period,start_time_in,stop_time_in);
zz_current.ShowSegments("_current");

//--- Exibe os dados nos comentários do gráfico


string comment="Current direction : "+string(zz_h1.Direction())+"\n"+

https://www.mql5.com/pt/articles/5543 36/42
01/01/2021 O poder do ZigZag (parte I). Desenvolvimento da classe base do indicador - Artigos MQL5
"\n---\n"+
"Direction > segment["+string(segment_index)+"]: "+string(zz_h1.SegmentDirect
"\n---\n"+
"Start bar > segment["+string(segment_index)+"]: "+string(start_bar)+"\n"+
"Stop bar > segment["+string(segment_index)+"]: "+string(stop_bar)+
"\n---\n"+
"Start price > segment["+string(segment_index)+"]: "+::DoubleToString(start_p
"Stop price > segment["+string(segment_index)+"]: "+::DoubleToString(stop_pri
"\n---\n"+
"Start time > segment["+string(segment_index)+"]: "+::TimeToString(start_time
"Stop time > segment["+string(segment_index)+"]: "+::TimeToString(stop_time,T
"\n---\n"+
"Start time (in tf) > segment["+string(segment_index)+"]: "+::TimeToString(st
"Stop time (in tf) > segment["+string(segment_index)+"]: "+::TimeToString(sto
"\n---\n"+
"Extremums copy: "+string(zz_current.CopyExtremums())+"\n"+
"SmallestMinimumTime(): "+string(zz_current.SmallestMinimumTime())+"\n"+
"LargestMaximumTime(): "+string(zz_current.LargestMaximumTime());
//---
::Comment(comment);
}

Segue abaixo como ele se parece:

https://www.mql5.com/pt/articles/5543 37/42
01/01/2021 O poder do ZigZag (parte I). Desenvolvimento da classe base do indicador - Artigos MQL5

Fig. 5. Recebendo os dados dentro do segmento especificado

Em seguida, desenvolva mais um EA para receber os dados dos três segmentos de um período gráfico maior.

Nós agora devemos declarar quatro instâncias da classe CZigZagModule no início do arquivo. Um deles é destinado ao
período gráfico maior (H1), enquanto os três restantes destinam-se ao período atual. Neste caso, nós realizamos os
testes no M5. 

CZigZagModule zz_h1;
CZigZagModule zz_current0;
CZigZagModule zz_current1;
CZigZagModule zz_current2;

https://www.mql5.com/pt/articles/5543 38/42
01/01/2021 O poder do ZigZag (parte I). Desenvolvimento da classe base do indicador - Artigos MQL5

Para maior clareza, os segmentos do menor período gráfico dentro dos segmentos do maior serão exibidos em cores
diferentes:

//--- Define a cor do segmento


zz_current0.LinesColor(clrRed);
zz_current1.LinesColor(clrLimeGreen);
zz_current2.LinesColor(clrMediumPurple);
zz_h1.LinesColor(clrCornflowerBlue);

Na função OnTick(), nós recebemos primeiro os dados do período gráfico em H1 e, em seguida, obtemos os dados do
período gráfico menor para o primeiro, segundo e terceiro segmentos em sequência. Exibe os dados em cada grupo dos
segmentos obtidos de período gráfico menor e no período gráfico maior de forma separada nos comentário do gráfico.
Nesse caso, essa é a diferença entre as taxas percentuais das somas do segmento. Ele pode ser obtido usando o método
CZigZagModule::PercentSumSegmentsDifference(). 

//+------------------------------------------------------------------+
//| Função Tick do Expert |
//+------------------------------------------------------------------+
void OnTick(void)
{
int copy_total=1000;
int h_buff=2,l_buff=3;
//--- Primeiro método para obtenção dos dados
::CopyTime(_Symbol,PERIOD_H1,0,copy_total,t_zz);
::CopyBuffer(zz_handle_h1,h_buff,0,copy_total,h_zz);
::CopyBuffer(zz_handle_h1,l_buff,0,copy_total,l_zz);
zz_h1.GetZigZagData(h_zz,l_zz,t_zz);
zz_h1.ShowSegments("_h1");
//---
datetime start_time_in =NULL;
datetime stop_time_in =NULL;
//--- Dado do primeiro segmento
zz_h1.SegmentTimes(zz_handle_current,h_buff,l_buff,_Symbol,PERIOD_H1,_Period,0,start_time_in
zz_current0.GetZigZagData(zz_handle_current,_Symbol,_Period,start_time_in,stop_time_in);
zz_current0.ShowSegments("_current0");
//--- Dado do segundo segmento
zz_h1.SegmentTimes(zz_handle_current,h_buff,l_buff,_Symbol,PERIOD_H1,_Period,1,start_time_in
zz_current1.GetZigZagData(zz_handle_current,_Symbol,_Period,start_time_in,stop_time_in);
zz_current1.ShowSegments("_current1");
//--- Dado do terceiro segmento
zz_h1.SegmentTimes(zz_handle_current,h_buff,l_buff,_Symbol,PERIOD_H1,_Period,2,start_time_in
zz_current2.GetZigZagData(zz_handle_current,_Symbol,_Period,start_time_in,stop_time_in);
zz_current2.ShowSegments("_current2");
//--- Exibe os dados nos comentários do gráfico
string comment="H1: "+::DoubleToString(zz_h1.PercentSumSegmentsDifference(),2)+"\n"+
"segment[0]: "+::DoubleToString(zz_current0.PercentSumSegmentsDifference(),2
https://www.mql5.com/pt/articles/5543 39/42
01/01/2021 O poder do ZigZag (parte I). Desenvolvimento da classe base do indicador - Artigos MQL5
"segment[1]: "+::DoubleToString(zz_current1.PercentSumSegmentsDifference(),2
"segment[2]: "+::DoubleToString(zz_current2.PercentSumSegmentsDifference(),2
//---
::Comment(comment);
}

Aqui está como ele fica no gráfico:

Fig. 6. Recebendo os dados dentro dos três segmentos especificados

Essa abordagem fornece oportunidades adicionais para analisar a natureza do comportamento do preço dentro dos
padrões. Suponha que nós definimos o padrão em H1 e analisamos como o preço se comportou dentro de cada
https://www.mql5.com/pt/articles/5543 40/42
01/01/2021 O poder do ZigZag (parte I). Desenvolvimento da classe base do indicador - Artigos MQL5

segmento. Os métodos da classe CZigZagModule permitem obter todas as propriedades dos extremos e segmentos, tais
como:

Preço, horário e índice de uma barra de cada extremo separado.


Tamanho de cada segmento separado.
Duração de cada segmento em barras.
Tamanho da faixa de preço de todo o conjunto de segmentos obtido.
Toda a duração de formação do conjunto de segmentos (em barras).
Soma dos segmentos unidirecionais.
Proporções das somas dos segmentos de direção oposta, etc. 

Esse conjunto básico pode ser usado como ponto de partida para o desenvolvimento de vários parâmetros
personalizados para a criação de indicadores. Os testes mostrarão quais benefícios podem ser derivados disso. Este site
contém vários artigos que podem ser úteis na condução de sua própria pesquisa sobre o assunto. 

Conclusão
A ideia de que o ZigZag não é adequado para gerar sinais de negociação é amplamente difundida em fóruns de
negociação. Este é um grande equívoco. De fato, nenhum outro indicador fornece tanta informação para determinar a
natureza do comportamento do preço. Agora você tem uma ferramenta que lhe permite obter facilmente todos os
dados necessários do indicador ZigZag para uma análise mais detalhada.

Nos próximos artigos da série, eu mostrarei quais indicadores podem ser desenvolvidos usando a classe CZigZagModule,
bem como os EAs para obter estatísticas sobre diferentes símbolos do indicador ZigZag e a verificação de algumas
estratégias de negociação baseadas no ZigZag que podem ser desenvolvidas.

Nome do arquivo Comentário


MQL5\Indicators\Custom\ZigZag\ExactZZ_Plus.mq5 Indicador ZigZag modificado
MQL5\Experts\ZigZag\TestZZ_01.mq5 EA para testar um único conjunto de dados
EA para testar três conjuntos de dados de diferentes períodos
MQL5\Experts\ZigZag\TestZZ_02.mq5
gráficos
EA para testar a aquisição dos dados dentro de um segmento de
MQL5\Experts\ZigZag\TestZZ_03.mq5
período de tempo maior especificado
EA para testar a obtenção dos dados dentro de três segmentos de
MQL5\Experts\ZigZag\TestZZ_04.mq5
período de tempo maior especificados

Traduzido do russo pela MetaQuotes Software Corp.


Artigo original: https://www.mql5.com/ru/articles/5543

Arquivos anexados | Download ZIP


https://www.mql5.com/pt/articles/5543 41/42
01/01/2021 O poder do ZigZag (parte I). Desenvolvimento da classe base do indicador - Artigos MQL5

MQL5.zip (17.45 KB)

Aviso: Todos os direitos a estes materiais são reservados a MetaQuotes Ltd. A cópia ou reprodução destes materiais total ou parcial é proibida.

Negociação on-line / Terminal Plataforma de negociação Sobre o projeto Windows


web MetaTrader 5
Histórico do site iPhone/iPad
Indicadores e experts gratuitos Últimas atualizações do
Termos de uso Mac OS
MetaTrader 5
Artigos sobre programação e
Contrato de pagamento Android
negociação Notícias, implementações e
recorrente
tecnologia Huawei
Encomendar experts ou
Política de privacidade e
indicadores de negociação Guia do usuário para Linux
proteção de dados
MetaTrader 5
Comprar robôs de negociação e Calendário Econômico Tradays
Política de Cookies
indicadores Linguagem de estratégias de
negociação MQL5 Contatos Não é uma corretora, não tem contas de
Sinais de negociação Forex
MQL5 Cloud Network negociação reais
Forex VPS para negociação
13 Anastasi Sioukri, 3105, Limassol,
Análise de ponta a ponta
Fórum de traders Cyprus
Baixar a MetaTrader 5 Copyright 2000-2021, MetaQuotes Ltd.
Blogs de traders
Instalação da plataforma
Gráficos
Desinstalação do programa

https://www.mql5.com/pt/articles/5543 42/42

Você também pode gostar