MetaTrader5
ZigZag de Fibonacci: O Indicador Essencial para MetaTrader 5
A Configuração
Para começarmos, vamos precisar de:
1 gráfico zigzag
2 buffers de dados para os altos e baixos
parâmetros de entrada
um conjunto contínuo de variáveis do sistema que se reiniciam sempre que o indicador é recalculado
O array upWaves armazenará os altos e o array dwWaves armazenará os baixos.
Variáveis do sistema:
Precisamos saber o último tipo de onda, onde começou, onde terminou, a distância em barras do início ao fim.
Em seguida, precisamos de uma variável de alto local e uma de baixo local, assim como as distâncias em barras de cada ponto.
//--- mantendo o controle do zigzag
int wave_type=0;
//--- preço da onda (preço de início)
double wave_start_price=0.0;
//--- preço da onda (preço de fim)
double wave_end_price=0.0;
//--- distância em barras do preço de início
int wave_start_distance=0;
//--- distância em barras do preço de fim
int wave_end_distance=0;
//--- acompanhamento do preço alto
double high_mem=0.0;
int distance_from_high=0;
//--- acompanhamento do preço baixo
double low_mem=0.0;
int distance_from_low=0;
//--- cálculo do atr
double rollingAtr=0.0;
int rollingAtrs=0;
Por fim, o cálculo do atr em andamento e quantos já foram calculados.
Agora vamos criar uma função de reinício do sistema:
void resetSystem(){
ArrayFill(upWaves,0,ArraySize(upWaves),0.0);
ArrayFill(dwWaves,0,ArraySize(dwWaves),0.0);
wave_type=0;
wave_start_price=0.0;
wave_end_price=0.0;
wave_start_distance=0;
wake_end_distance=0;
high_mem=0.0;
low_mem=0.0;
distance_from_high=0;
distance_from_low=0;
rollingAtr=0.0;
rollingAtrs=0;
}
Com isso, reiniciamos as variáveis do sistema.
No método OnInit, configuramos os buffers, o gráfico e chamamos o reset pela primeira vez:
SetIndexBuffer(0,upWaves,INDICATOR_DATA);
SetIndexBuffer(1,dwWaves,INDICATOR_DATA);
PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0.0);
PlotIndexSetInteger(0,PLOT_DRAW_TYPE,DRAW_ZIGZAG);
PlotIndexSetInteger(0,PLOT_LINE_COLOR,0,Color);
PlotIndexSetInteger(0,PLOT_LINE_WIDTH,Width);
PlotIndexSetInteger(0,PLOT_LINE_STYLE,Style);
resetSystem();
Agora vamos para o cálculo.
A primeira coisa que precisamos cuidar é do cálculo do atr.
Até que tenhamos coletado mais barras do que o período do atr, não faremos mais nada.
A parte que gerencia o atr é a seguinte:
se não temos coletado mais do que o período, continuamos adicionando a faixa das barras a uma soma
uma vez que chegamos ao período, fazemos a primeira divisão (média)
depois, cortamos uma parte do atr em andamento, que é atr/período, e adicionamos uma nova parte que é a faixa da barra / período
Colocamos a última parte primeiro porque vai acontecer mais vezes e não precisaremos acessar dois ifs.
//--- gerenciando o atr
rollingAtrs++;
if(rollingAtrs>rollingAtrPeriod){
double new_portion=((high[i]-low[i])/_Point)/((double)rollingAtrPeriod);
//--- removemos uma parte antiga e adicionamos uma nova
rollingAtr=(rollingAtr)-(rollingAtr/((double)rollingAtrPeriod))+new_portion;
}
else if(rollingAtrshigh_mem&&low[i]>=low_mem){
double new_wave_size_in_atr_units=((high[i]-low_mem)/_Point)/rollingAtr;
//--- se o novo tamanho da onda é válido
if(new_wave_size_in_atr_units>=minSizeInAtrUnits){
//--- inicia uma nova onda de alta
wave_type=1;
//--- preço de início é o baixo mem
wave_start_price=low_mem;
wave_start_distance=distance_from_low;
//--- o preço de fim é o novo alto
wave_end_price=high[i];
wave_end_distance=0;
//--- desenha a onda
dwWaves[i-wave_start_distance]=low_mem;
upWaves[i]=high[i];
//--- atualiza o alto
high_mem=high[i];
distance_from_high=0;
//--- atualiza o baixo
low_mem=low[i];
distance_from_low=0;
}
}
//--- se rompemos o baixo e não o alto
else if(low[i]wave_end_price){
//--- remove o preço de fim anterior de sua posição no array (0.0= vazio)
upWaves[i-wave_end_distance]=0.0;
//--- coloca na nova posição
upWaves[i]=high[i];
wave_end_price=high[i];
wave_end_distance=0;
//--- atualiza o alto
high_mem=high[i];
distance_from_high=0;
//--- atualiza o baixo
low_mem=low[i];
distance_from_low=0;
}
//--- verifica o retrocesso
if(low[i]0.0){
double retraced=(size_of_retracement/size_of_wave)*100.0;
double new_wave_size_in_atr_units=((wave_end_price-low_mem)/_Point)/rollingAtr;
//--- se o novo tamanho da onda é válido
if(new_wave_size_in_atr_units>=minSizeInAtrUnits){
//--- se o retrocesso é significativo, inicia uma onda de baixa
if(retraced>=retracement){
//--- inicia uma nova onda de baixa
wave_type=-1;
//--- preço de início é o alto mem
wave_start_price=high[i-distance_from_high];
wave_start_distance=distance_from_high;
//--- o preço de fim é o novo baixo
wave_end_price=low[i];
wave_end_distance=0;
//--- desenha a onda
upWaves[i-wave_start_distance]=high_mem;
dwWaves[i]=low[i];
//--- atualiza o alto
high_mem=high[i];
distance_from_high=0;
//--- atualiza o baixo
low_mem=low[i];
distance_from_low=0;
}
}
}
}
}
Fazemos o oposto quando temos uma onda de baixa.
E estamos prontos! Nosso zigzag de retrocesso está finalizado.
Aqui está o zigzag com 23.6% de retrocesso e 0.0 min tamanho das ondas em unidades de atr.
E aqui está o mesmo zigzag com 3 min tamanho das ondas em unidades de atr.
2025.03.03