Início Indicador técnico Postagem

ZigZag de Fibonacci: O Indicador Essencial para MetaTrader 5

Anexo
56619.zip (2.54 KB, Baixar 0 vezes)

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(rollingAtrs<=rollingAtrPeriod){
    rollingAtr+=(high[i]-low[i])/_Point;
    if(rollingAtrs==rollingAtrPeriod){
        rollingAtr/=((double)rollingAtrs);
        //--- inicializa a memória para altos e baixos e o sistema
        high_mem=high[i];
        low_mem=low[i];
        distance_from_high=0;
        distance_from_low=0;
    }
}

Ótimo! Agora, existe outro problema.

A base desse zigzag é o retrocesso.

Mas para um retrocesso ocorrer, deve haver pelo menos uma onda.

Mas qual será a primeira onda a retroceder? 😄

Por isso, faremos o seguinte:

  • assim que o atr se preencher (atr coletado = período), pegamos o alto e o baixo nas variáveis do sistema
  • o lado que formar uma onda com um tamanho válido em unidades de atr, e formar um novo alto (onda de alta) ou um novo baixo (onda de baixa), vence

Dessa forma, não temos um retrocesso como uma onda inicial, mas precisamos iniciar a sequência de alguma forma.

Isso é o que fazemos enquanto não temos uma onda:

//--- se não temos um tipo de onda ainda
else{
    //--- se rompemos o alto e não o baixo
    if(high[i]>high_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]=minSizeInAtrUnits){
            //--- inicia uma nova onda de baixa
            wave_type=-1;
            //--- preço de início é o alto mem
            wave_start_price=high_mem;
            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;
        }
    }
    //--- se rompemos ambos
    else if(low[i]high_mem){
        //--- atualizamos
        high_mem=high[i];
        low_mem=low[i];
        distance_from_high=0;
        distance_from_low=0;
    }
}

Ótimo! Agora, a peça final.

  • Se temos uma onda de alta:
  1. se um novo alto é feito, movemos o zigzag da posição do alto anterior para a nova posição que podemos fazer, uma vez que mantemos as distâncias das barras. Também atualizamos o baixo e a distância do baixo. Fazemos isso para capturar o menor baixo desde o pico e verificar se ele retrocede o suficiente para iniciar um novo baixo.
  2. se um novo baixo é feito, ou, um novo baixo é definido, calculamos a distância do pico até o baixo e dividimos pelo tamanho da onda. E também multiplicamos por 100 para corresponder à escala do parâmetro de entrada. Então, se o tamanho da nova "onda" que retrocede a anterior também for válido em relação às unidades de atr, iniciamos uma nova onda de baixa, definimos os novos altos e baixos locais e definimos as distâncias das barras.

Aqui está o código relevante para o que foi mencionado acima:

//--- se temos uma onda de alta
if(wave_type==1){
    //--- se a onda se expande para cima
    if(high[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.


Publicações relacionadas

Comentário (0)