Assista a como baixar robôs de negociação gratuitos
Encontre-nos em Telegram!
Participe de nossa página de fãs
Script interessante?
Coloque um link para ele, e permita que outras pessoas também o avaliem
Você gostou do script?
Avalie seu funcionamento no terminal MetaTrader 5
Visualizações:
335
Avaliação:
(7)
Publicado:
Freelance MQL5 Precisa de um robô ou indicador baseado nesse código? Solicite-o no Freelance Ir para Freelance

A configuração

Precisaremos de :

  • 1 gráfico em ziguezague
  • 2 buffers de dados para os altos e baixos
  • parâmetros de entrada
  • um conjunto contínuo de variáveis de sistema que são redefinidas sempre que o indicador é recalculado

#property indicator_buffers 2
#property indicator_plots 1
input double retracement=23.6;//valor da retração
input double minSizeInAtrUnits=0.0;//tamanho mínimo das ondas em unidades atr
input int rollingAtrPeriod=14;//período de rolagem atr
input color Color=clrDodgerBlue;//cor da onda
input int Width=3;//largura da onda
input ENUM_LINE_STYLE Style=STYLE_SOLID;//estilo de onda
//+------------------------------------------------------------------+




//| Função de inicialização do indicador personalizado
//+------------------------------------------------------------------+
//--- ondas ascendentes e descendentes
  double upWaves[],dwWaves[];

A matriz upWaves armazenará os máximos e a matriz dwWaves armazenará os mínimos

Variáveis do sistema:

Precisamos saber o tipo da última onda, onde ela começou, onde terminou, a distância em barras do início e do fim.

Em seguida, precisamos de uma variável local de alta e baixa, bem como as distâncias em barras de cada ponto.

//--- mantendo o controle do ziguezague
  //--- o tipo de onda que temos [0] nenhuma [1] para cima [2] para baixo
    int wave_type=0;
  //--- o preço a partir da onda (preço inicial) 
    double wave_start_price=0.0;
  //--- o preço até a onda (preço final)
    double wave_end_price=0.0;
  //--- a distância em barras do preço inicial
    int wave_start_distance=0;
  //--- a distância em barras do preço final
    int wave_end_distance=0;
  //--- rastreamento de preço alto
    double high_mem=0.0;
    int distance_from_high=0;
  //--- rastreamento de preço baixo
    double low_mem=0.0;
    int distance_from_low=0;
  //--- rolling atr
    double rollingAtr=0.0;
       int rollingAtrs=0;

Finalmente, a unidade de atr de rolagem e quantas foram calculadas

Em seguida, criamos uma função de reinicialização 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;
wave_end_distance=0;
high_mem=0.0;
low_mem=0.0;
distance_from_high=0;
distance_from_low=0;
rollingAtr=0.0;
rollingAtrs=0;
}

Coisas padrão, preencher as matrizes com zeros e redefinir as variáveis do sistema.

Na inicialização, configuramos os buffers, o gráfico e chamamos a funçã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();

Então, vamos direto para o cálculo.

A primeira coisa que precisamos resolver é o atr de rolagem.

Até que tenhamos coletado mais barras do que o período do atr, não faremos mais nada.

A parte que gerencia o atr móvel é a seguinte:

  • se não tivermos coletado mais do que o período, continuaremos adicionando o intervalo das barras encontradas a um somatório
  • quando atingirmos o período, faremos a primeira divisão (média)
  • depois disso, cortamos uma parte do rolling atr, que é atr/período, e adicionamos uma nova parte, que é o intervalo de barras/período
colocamos a última parte primeiro porque ela ocorrerá com mais frequência e não precisaremos acessar 2 instruções if

     //--- gerenciar o atr
       rollingAtrs++;
       if(rollingAtrs>rollingAtrPeriod){
       double new_portion=((high[i]-low[i])/_Point)/((double)rollingAtrPeriod);
       //--- removemos uma parte antiga e adicionamos uma nova parte
       rollingAtr=(rollingAtr)-(rollingAtr/((double)rollingAtrPeriod))+new_portion;
       }
       else if(rollingAtrs<=rollingAtrPeriod){
         rollingAtr+=(high[i]-low[i])/_Point;
         if(rollingAtrs==rollingAtrPeriod){
           rollingAtr/=((double)rollingAtrs);
           //--- iniciar 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;
           }
         }

Incrível, agora há outro problema.

A base desse ziguezague é um retrocesso.

Mas para que ocorra uma retração, deve haver pelo menos uma onda.

Mas qual será o retrocesso da primeira onda? xD

Por esse motivo, faremos o seguinte:

  • assim que o atr for preenchido (atr coletado = período), pegaremos a máxima e a mínima em nossas variáveis do sistema
  • o lado que conseguir formar uma onda com um tamanho válido em unidades de atr e formar uma nova máxima (onda ascendente) ou uma nova mínima (onda descendente) vence

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

Observe que também poderíamos ter optado por uma abordagem fractal clássica aqui apenas para a primeira onda e depois continuar com retrações.

É isso que fazemos enquanto não tivermos uma onda:

   //--- se ainda não tivermos um tipo de onda
     else{
       //--- se quebramos a máxima e não a mínima
         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 do pacote for válido
         if(new_wave_size_in_atr_units>=minSizeInAtrUnits){
           //--- iniciar uma nova onda ascendente 
             wave_type=1;
           //--- o preço inicial é o preço mínimo 
             wave_start_price=low_mem;
             wave_start_distance=distance_from_low;
           //--- o preço final é a nova máxima
             wave_end_price=high[i];
             wave_end_distance=0;
           //--- desenhar a onda 
             dwWaves[i-wave_start_distance]=low_mem;
             upWaves[i]=high[i];
           //--- mudar a alta
             high_mem=high[i];
             distance_from_high=0;
           //--- mudar a baixa 
             low_mem=low[i];
             distance_from_low=0;
           }
           } 
       //--- se quebramos a mínima e não a máxima
         else if(low[i]<low_mem&&high[i]<=high_mem){
         double new_wave_size_in_atr_units=((high_mem-low[i])/_Point)/rollingAtr;
         //--- se o novo tamanho do pacote for válido
         if(new_wave_size_in_atr_units>=minSizeInAtrUnits){         
           //--- iniciar uma nova onda descendente 
             wave_type=-1;
           //--- preço inicial é o mem alto 
             wave_start_price=high_mem;
             wave_start_distance=distance_from_high;
           //--- o preço final é o novo mínimo
             wave_end_price=low[i];
             wave_end_distance=0;
           //--- desenhar a onda 
             upWaves[i-wave_start_distance]=high_mem;
             dwWaves[i]=low[i];
           //--- mudar a alta
             high_mem=high[i];
             distance_from_high=0;
           //--- mudar a baixa 
             low_mem=low[i];
             distance_from_low=0;
           }
           }
       //--- se quebrarmos ambos
         else if(low[i]<low_mem&&high[i]>high_mem){
           //--- alterá-los
             high_mem=high[i];
             low_mem=low[i];
             distance_from_high=0;
             distance_from_low=0;
           }
       }

Ótimo. Agora, a parte final.

  • Se tivermos uma onda ascendente:
  1. Se houver uma nova alta, mova o ziguezague da posição da alta anterior para a nova posição da alta, o que podemos fazer, pois mantemos as distâncias das barras, e também atualizamos a mínima e a distância da mínima.
  2. Se uma nova mínima for registrada ou se uma nova mínima for estabelecida, calcularemos a distância do pico até a mínima e a dividiremos pelo tamanho da onda. Assim, se o tamanho da onda for de 100 pontos e a retração for de 24 pontos, obteremos 24/100 0,24 e, em seguida, x 100 24%. Se o tamanho da nova onda "seria" que retrai a anterior também for válido em relação às unidades atr, iniciaremos uma nova onda descendente, definiremos os novos máximos e mínimos locais e as distâncias das barras.

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

       //--- se tivermos uma onda ascendente 
         if(wave_type==1){
           //--- se a onda se expandir para cima 
             if(high[i]>wave_end_price){
               //--- remover o preço final anterior de sua posição na matriz (0,0=vazio)
                upWaves[i-wave_end_distance]=0.0;
               //--- coloque-o na nova posição
                upWaves[i]=high[i];
                wave_end_price=high[i];
                wave_end_distance=0;
               //--- mudar a alta
                high_mem=high[i];
                distance_from_high=0;
               //--- mudar a baixa 
                low_mem=low[i];
                distance_from_low=0;
               }
           //--- verificar a retração
             if(low[i]<low_mem||distance_from_low==0){
               low_mem=low[i];
               distance_from_low=0;
               double size_of_wave=(wave_end_price-wave_start_price)/_Point;
               double size_of_retracement=(wave_end_price-low_mem)/_Point;
               if(size_of_wave>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 do pacote for válido
               if(new_wave_size_in_atr_units>=minSizeInAtrUnits){
                 //--- se a retração for significativa, inicie uma onda descendente
                   if(retraced>=retracement){
                    //--- iniciar uma nova onda descendente 
                      wave_type=-1;
                    //--- preço inicial é o mem alto 
                      wave_start_price=high[i-distance_from_high];
                      wave_start_distance=distance_from_high;
                    //--- o preço final é o novo mínimo
                      wave_end_price=low[i];
                      wave_end_distance=0;
                    //--- desenhar a onda 
                      upWaves[i-wave_start_distance]=high_mem;
                      dwWaves[i]=low[i];
                    //--- mudar a alta
                      high_mem=high[i];
                      distance_from_high=0;
                    //--- mudar a baixa 
                      low_mem=low[i];
                      distance_from_low=0;                     
                     }
                   }
                 }
               }
           }

Fazemos o oposto quando temos uma onda de baixa.

E pronto, nosso ziguezague de retração está pronto.

Aqui está o ziguezague com retração de 23,6% e tamanho mínimo de 0,0 das ondas em unidades atr


e aqui está o mesmo ziguezague com tamanho de ondas de 3 minutos em unidades atr






Traduzido do inglês pela MetaQuotes Ltd.
Publicação original: https://www.mql5.com/en/code/56619

TradeReportExporter TradeReportExporter

O script TradeReportExporter foi projetado para exportar o histórico de negociações (trades) em um conveniente arquivo CSV. Ele coleta automaticamente dados sobre todas as negociações do último ano para o instrumento no qual está instalado. O arquivo inclui dados como data e hora, tipo de transação (compra/venda), preço, volume, comissão e lucro/perda. O resultado é salvo em um arquivo que pode ser aberto no Excel ou em qualquer outro editor de planilhas.

Swaps Monitor for a Single Symbol Swaps Monitor for a Single Symbol

Um utilitário simples para monitorar swaps longos e curtos de um único símbolo. Se os swaps de sua corretora forem especificados em pontos em vez da moeda da conta, esse utilitário converterá automaticamente os pontos em moeda da conta. Os swaps são triplicados na quarta-feira. O alinhamento horizontal e vertical pode ser ajustado nas entradas.

Autoscaling Zigzag Autoscaling Zigzag

Um indicador de ziguezague que usa uma única entrada para ajustar o tamanho da etapa para detectar mudanças na direção da onda.

Telegram integration made easy. Telegram integration made easy.

O objetivo é tornar a função prontamente disponível para qualquer tarefa de integração do Telegram no desenvolvimento da MQL5. Ao adicionar esse arquivo ao seu CodeBase, você pode simplesmente incluí-lo em seus Expert Advisors e chamar a função diretamente do módulo incluído. Isso elimina a necessidade de desenvolver o código do zero repetidamente, garantindo a reutilização em vários projetos.