Detecção automática de pontos extremos com base numa variação de preço especificado

Sergey Strutinskiy | 15 fevereiro, 2017


Introdução

Muitas estratégias de negociação populares são baseadas no uso de diferentes padrões gráficos: cabeça e ombros, topo/fundo duplo e outros. Algumas estratégias também analisam a divergência de pontos extremos nos gráficos. Ao automatizar tais sistemas de negociação, surge a necessidade de encontrar, processar e interpretar picos e fundos nos gráficos. As ferramentas existentes nem sempre nos permitem encontrar pontos extremos de acordo com os critérios estabelecidos. O artigo apresenta algoritmos eficientes e soluções de programas para encontrar e processar pontos extremos em gráficos de preços, dependendo de uma variação de preço. 

1. Ferramentas existentes para procurar pontos extremos

1.1. Fractais e ferramentas similares

Fractais são ferramentas populares para encontrar pontos extremos. Eles permitem encontrar os Mínimos e as Máximas dos preços para a série de 5 barras (Fig. 1). Os pontos extremos são definidos tanto durante os movimentos de preços fortes como os fracos. Se um período de tempo é selecionado corretamente, os fractais podem mostrar bons resultados, embora sejam fortemente afetados pelas condições de mercado.


Fig. 1. Resultados do uso de fractais: pontos extremos com um tamanho relativo de 140 a 420 pips quando uma tendência está presente (a), pontos extremos durante um movimento lateral, o tamanho relativo não é mais de 50 pips (b)

No segundo caso, o tamanho relativo dos pontos extremos (mudança de preço de um ponto extremo para outro) não pode exceder alguns pips. Esses picos e fundos insignificantes, geralmente não são considerados ao negociar manualmente. A alternância entre timeframes não permite a classificação de pontos extremos insignificantes - eles ainda são definidos durante uma longa lateralidade. 

Também pode haver um incidente do tipo oposto: nem todos os pontos extremos podem ser definidos. Se houver alguma volatilidade considerável do mercado com um grande número de picos e fundos dentro de um curto intervalo de tempo, eles não serão detectados. Os fractais são capazes de detectar apenas 2 pontos extremos dentro de um intervalo de tempo definido por 5 barras do período do timeframe. Assim, não podemos recomendar os fractais para a detecção automática de todos ou da maioria dos pontos extremos críticos durante uma negociação automatizada. 

As ferramentas descritas no artigo "A contribuição de Thomas DeMark para a análise técnica" têm os mesmos inconvenientes que os fractais. Se selecionarmos um intervalo grande para procurar pontos extremos, muitos deles podem ser ignorados. Se o intervalo for demasiadamente pequeno, alguns pontos extremos insignificantes também podem ser definidos. Em qualquer caso, ao processar os resultados, ou temos que otimizar manualmente os parâmetros o tempo todo, descartando Mínimos e Máximas insignificantes, ou desenvolver um algoritmo especial para isso.


1.2. Usando médias móveis ao procurar pontos extremos

Usar uma linha média, tipo uma média móvel, como uma base para automatizar a busca de pontos extremos parece potencialmente viável. A pesquisa é realizada num número especificado de barras se o preço desvia-se da linha média para uma distância predefinida em pontos. A ferramenta permite escolher picos e fundos insignificantes, que aparentam ser melhor do que os fractais. No entanto, ainda não resolve a questão da detecção de Mínimos e as Máximas muito próximos (Fig. 2, a).

 

Fig. 2. Usando médias móveis na busca de pontos extremos: os dois pontos extremos são definidos como um (a), o ponto extremo localizado na proximidade da média móvel é ignorado (b)

Podemos usar médias móveis e fractais juntos. A média móvel é usada para classificar pontos extremos insignificantes, enquanto os fractais são usados para realizar uma busca dentro de um intervalo especificado. No entanto, esta abordagem não elimina todos os problemas também. Nós ainda precisamos selecionar constantemente os parâmetros de variação optimal. Caso contrário, apenas um ponto extremo será definido a partir dos dois espaçamentos próximos (Fig. 2, a).

Há também outra questão relacionada a este método específico. Durante a alta volatilidade, uma média móvel pode ignorar tal sinal dependendo de um período de tempo. Neste caso, (figura 2, b), o fundo entre os dois picos e próximo da média móvel não é detectado. Tais ocasiões são bastante raras no mercado, mas eles levantam questões sobre a seleção correta da faixa média móvel. 

Assim, os métodos para pesquisa de pontos extremos, bem como as suas modificações descritas acima, têm desvantagens e requerem soluções de programação adicionais. Vamos considerar as questões que surgem na busca de pontos extremos, bem como os algoritmos que permitem resolvê-los em mais detalhes.

2. Questões e ambiguidades surgidas na busca por pontos extremos

2.1. Seleção da faixa de variação para pesquisa de picos e fundos

Estratégias e táticas existentes podem usar pontos extremos implicitamente ou explicitamente. Encontrar pontos extremos é muitas vezes uma tarefa arbitrária: pessoas diferentes podem detectar e realçar diferentes picos e fundos no mesmo gráfico. Vamos examinar um dos padrões gráficos bem conhecidos - o topo duplo.

Fig. 3. O padrão de topo duplo 

 Fig. 3. O padrão de topo duplo

Os dois gráficos (Fig. 3) contêm o mesmo padrão. No entanto, podemos detectá-lo ou não, dependendo da faixa de variação de pontos extremos. No primeiro gráfico, o primeiro pico é seguido pelo fundo, que por sua vez é seguido pelo segundo pico. Por conseguinte, se não houvesse fundo entre os picos, não teríamos sido capazes de detectar o padrão de topo duplo. O padrão teria sido definido como um ponto extremo comum. A mesma coisa ocorre quando um fundo não é claramente visível, obscurecendo o padrão de topo duplo e complicando a sua detecção. Assim, é mais fácil detectar o padrão no primeiro gráfico quando comparado ao segundo, enquanto a única diferença entre eles é a variação entre os pontos extremos adjacentes. 

Vamos considerar outro exemplo: algumas estratégias definem a tendência como ascendente se os pontos extremos subseqüentes (tanto picos quanto fundos) estiverem localizados acima dos anteriores. Uma tendência descendente é definida de forma semelhante. Na Fig. 4, podemos definir uma direção da tendência usando pontos extremos.


Fig. 4. Movimento de preços oposto no mesmo gráfico: tendência de alta (a), tendência de baixa (b)

Um único gráfico contém tanto uma tendência de alta quanto uma baixa. No primeiro caso (Fig. 4, a), os pontos extremos 1, 2, 3 e 4 mostram claramente uma tendência de alta. No entanto, se usarmos os pontos extremos 2, 5, 6 e 3 (Fig. 4, b), veremos uma tendência de baixa. Assim, é possível obter um dos possíveis resultados utilizando diferentes pontos extremos. Considerando isso, podemos concluir que o intervalo de variação tem maior impacto na localização dos pontos extremos.

2.2. Separação eficiente de picos ou fundos adjacentes

Há também outra questão que surge quando se definem pontos extremos. A fim de definir e separar eficientemente dois ou mais picos, deve haver um fundo entre eles. Isto é verdade tanto para o primeiro exemplo (encontrar o topo inferior) e para o segundo, embora o caso é ainda mais interessante aqui. De acordo com a estratégia descrita, podemos detectar uma tendência nos gráficos abaixo (Fig. 5, 6) somente depois de encontrar pontos extremos. 

Fig. 5. Detecção de picos e fundos durante investimentos de longo prazo 

Fig. 5. Detecção de picos e fundos durante investimentos de longo prazo 

Fig. 6. Detecção de picos e fundos insignificantes 

Fig. 6. Detecção de picos e fundos insignificantes 

Se não houver fundos que separem picos (e vice-versa), a estratégia não pode funcionar de acordo com os critérios especificados, embora uma tendência de alta possa ser vista no gráfico. Vamos considerar um exemplo típico. Durante uma tendência de alta, cada pico é maior do que o anterior. Se não há fundo entre eles ou se não é claramente visto, apenas o pico mais alto é definido como um ponto extremo. Se pontos extremos são definidos em relação a uma linha média (como uma média móvel), a tarefa de separar dois picos ou fundos adjacentes permanece relevante. Para separar dois picos, devemos usar um ponto extremo entre eles.

Assim, podemos aplicar a seguinte suposição a todas as estratégias usando pontos extremos implicitamente ou explicitamente: o preço se move de um pico para um fundo e de um fundo para um pico, tanto quando se move para a frente (para o futuro) e para trás. Se não usarmos esse pressuposto, então, dependendo do ponto de vista subjetivo, os dois picos no gráfico de preços:

  • São detectados,
  • Ou apenas o pico mais alto é detectado,
  • Ou nenhum deles é detectado.

O mesmo é verdadeiro para os fundos. Esta suposição nos permite desenvolver o algoritmo para a busca precisa de pontos extremos usando um intervalo de variação selecionado.

2.3. Definindo o primeiro ponto extremo

A terceira questão também está relacionada a uma variação de preços e ocorre quando se define o primeiro ponto extremo. Para qualquer tática de negociação ou estratégia, os pontos extremos mais recentes são mais importantes do que os mais antigos. Como já descobrimos, a definição de um único ponto extremo afeta a localização dos picos e fundos adjacentes. Portanto, se selecionamos um ponto extremo a alguma distância do tempo atual, os resultados obtidos são fortemente afetados por dados históricos mais distantes e, em muito menor grau, afetados pelas flutuações de preços mais recentes. Este problema está presente ao usar o ZigZag. A localização dos últimos pontos extremos não depende muito das últimas flutuações de preços.  

No entanto, a situação é completamente diferente ao procurar pontos extremos do final do gráfico. Neste caso, devemos primeiro encontrar um pico ou um fundo que é o mais próximo do fim do gráfico, e todos os outros são definidos inequivocamente. Dependendo de uma estratégia aplicada e de uma faixa de variação selecionada, três opções podem ser usadas:

  • Encontrar o pico mais próximo,
  • Encontrar o fundo mais próximo,
  • Encontrar o ponto extremo mais próximo (um pico ou um fundo).

Vamos considerar encontrar o ponto extremo mais próximo. Depois de selecionar um determinado intervalo de variação, podemos definir com precisão o primeiro ponto extremo mais próximo. No entanto, isso ocorre com um certo atraso, o que pode ter um impacto negativo sobre a operação da estratégia. Para "ver" um ponto extremo, precisamos definir a mudança de preço especificado por uma variação relativa a esse ponto. A mudança de preço leva algum tempo, daí o atraso. Podemos também usar o último valor de preço conhecido como um ponto extremo, embora seja improvável que ele realmente venha a ser um pico ou um fundo. 

Neste caso, parece razoável encontrar o primeiro ponto extremo usando uma relação adicional como uma parte fracionária da faixa de variação usada para encontrar outros pontos extremos. Por exemplo, vamos selecionar o valor de 0,5.  

O valor da relação adicional selecionada, define uma mudança de preço mínimo do valor atual para o preço mínimo do fundo mais próximo (o preço máximo para o pico mais próximo), permitindo-nos definir este fundo (pico) como um ponto extremo. Se a variação entre os valores atual e extremo para o pico mais próximo (inferior), for menor que o valor especificado, tal ponto extremo não é definido. Neste caso, o primeiro ponto extremo detectado provavelmente se tornará um pico ou um fundo. Ao mesmo tempo, resolvemos também a questão da detecção precoce de pontos extremos, bem como a sua posterior análise e (se necessário) acordos de abertura.

Vamos considerar um exemplo com uma faixa de variação definida para 140 pips. Uma relação adicional deve ser usada para detectar o primeiro ponto extremo. No primeiro caso, é igual a 0,9 (Fig. 7, a), no segundo, igual a 0,7 (Fig. 7, b). Aqui, o valor da relação adicional define a variação de preço mínimo em pips que nos permite detectar o primeiro ponto extremo. No primeiro caso, a variação é 126 pips, enquanto que para o segundo caso, é de 98 pips. O mesmo gráfico é considerado em ambos os casos. A linha vertical indica o período de tempo atual, para o qual o cálculo é executado. Os pontos extremos detectados dentro deste período são mostrados como pontos. 


 

Fig. 7. A influência da relação adicional na definição dos pontos extremos: para o valor de 0,9 (126 pips), o primeiro ponto extremo é detectado na variação de 205 pips (a), para o valor de 0,7 (98 pips), o primeiro ponto extremo é detectado na variação de 120 pips, enquanto os dois restantes são detectados de acordo com a faixa de variação especificada (b)

O valor da relação adicional selecionada para o primeiro caso ajudou a definir o primeiro fundo apenas na faixa de 205 pips, enquanto a variação do preço mínimo é 126  pips. Para o segundo caso, se a relação adicional for igual a 0,7 (98 pips), o primeiro fundo é definido na variação de 120 pips em relação ao preço atual. Os dois valores extremos subsequentes são detectados de acordo com a faixa de variação especificada igual a 140 pips. Consequentemente, a variação de preços entre o primeiro fundo e o pico subsequente excede ligeiramente 140  pips. O segundo fundo também é definido pela variação de preço que excede 140 pips, porém em relação ao pico detectado.

Como podemos ver, a relação adicional afeta significativamente a localização do primeiro ponto extremo detectado. Isso pode afetar seu tipo também. Para vários valores (de 0 a 1), um pico ou um fundo podem ser detectados primeiro no mesmo gráfico. Os dois primeiros pontos extremos detectados para o segundo caso (Fig. 7 b), não foram definidos no primeiro.

No caso de uma proporção ainda mais baixa, o primeiro ponto extremo é definido mais rapidamente. No segundo caso (Figura 7 b), com a relação adicional de  0,4, o primeiro valor extremo detectado pode ser definido 5 barras mais cedo (5 minutos mais cedo na escala de tempo atual).

3. As soluções algorítmicas para tarefas de busca de pontos extremos e sua implementação

3.1 Os algoritmos para encontrar pontos extremos dependendo do intervalo de variação

Vamos começar a partir da seleção da faixa de preço para a construção de pontos extremos. Obviamente, os tamanhos de barras e parâmetros de ponto extremo variam muito dependendo de um período de tempo. A presença e ausência de picos/fundos também é afetada por uma tendência, hora do dia e outros fatores. Os indicadores existentes, como os fractais e as ferramentas similares, permitem que nós encontremos pontos extremos em todo o período de tempo não obstante se uma tendência está atual. Se usarmos uma média móvel na busca de picos e fundos, o tamanho dos pontos extremos em relação à média móvel pode compreender 2 pontos, bem como 100. Devemos prestar atenção aos valores extremos de 2 pontos na negociação intraday? Provavelmente não. No caso de um investimento de longo prazo, não estamos interessados em valores extremos inferiores a 20 pontos, independentemente do timeframe.

É por isso que precisamos do termo "intervalo de variação" significando um valor mínimo. Uma média móvel pode ser usada como um ponto de referência que nos permite definir a distância até um ponto extremo e limitar seu valor mínimo. No entanto, o período de média móvel afeta significativamente a posição dos picos e fundos detectados, tornando difícil selecionar um determinado período como referência.

Portanto, vamos supor a partir de agora que o preço se move de pico para baixo e para trás, e o intervalo de variação é definido como uma mudança de preço mínimo em pontos, que são os dois pontos extremos vizinhos - o pico e o fundo. Se alguns dos pontos extremos já estiverem definidos, o vizinho deve estar localizado a uma distância não inferior à especificada pelo intervalo de variação. Isso nos permite definir pontos extremos, independentemente de um período de tempo e de uma tendência. A ferramenta é perfeitamente adequada para negociação intraday e investimento de longo prazo.

Vamos considerar seu algoritmo de operação. Primeiro, vamos definir visualmente os pontos extremos usando o mesmo gráfico, embora no primeiro gráfico, o intervalo de variação seja de 60 pips (Fig. 8), enquanto no segundo gráfico é de 30 pips (Fig. 9). Vamos também assumir que o primeiro ponto extremo já é detectado (ponto 1) e estamos procurando os precedentes. 

 

Fig. 8. Usando a faixa de variação de 60 pips


Fig. 9. Usando a faixa de variação de 30 pips

A procura de pontos extremos é realizada a partir do final do gráfico (a partir do ponto 1). No primeiro caso, foram encontrados 4 pontos extremos do intervalo exibido, no segundo caso, foram detectados 10 pontos extremos no mesmo intervalo. Ao aumentar o intervalo de variação numa parte especificada do gráfico, os pontos extremos não são detectados. Portanto, devemos ser realistas ao selecionar o intervalo de busca de pontos extremos e ter em conta a volatilidade do mercado e o prazo. Aqui, o intervalo é um número de barras, em que a pesquisa é realizada.

Tendo em mente tudo o que mencionamos acima, vamos introduzir o algoritmo de iteração para procurar por pontos extremos. Por que iteração? O primeiro pico deve ser sempre seguido pelo fundo, o segundo pico vai depois dele, etc. Se o segundo pico não for encontrado (o gráfico não se move para cima), a posição do fundo é redefinida, e é movida mais e mais longe na série de tempo. A posição do primeiro pico (assim como qualquer outro ponto extremo) pode ser corrigida da mesma maneira. Devemos também descartar os casos quando a mesma barra é definida tanto como um pico e como um fundo.

Naturalmente, esta abordagem requer uma grande quantidade de cálculo. Eu aconselho aplicá-la ao procurar por vários pontos extremos. Quanto menor o número de pontos, mais rápido o programa funciona. A velocidade de cálculo também é afetada por um intervalo de pesquisa. Esta busca é justificada, pois permite definir determinados picos e fundos no máximo impacto das flutuações de preços mais recentes. Se você precisa encontrar vários pontos extremos, eu recomendo usar o ZigZag.

3.2 Implementação de indicadores 

O algoritmo de iteração, código apresentado abaixo, usa um pequeno número de iterações para melhor desempenho. Esta simplificação não causa perda significativa da qualidade de detecção de pontos extremos. Os principais parâmetros de entrada - o intervalo para procurar pontos extremos e o intervalo de variação.

input int      bars=500;                 //  Pesquisando a variação do ponto extremo
input double   delta_points=160;         //  Faixa de variação que define a distância mínima entre um pico e um fundo em pontos
input double   first_extrem=0.9;         //  Proporção adicional para procurar o primeiro valor extremo
input double   reload_time=5;            //  Intervalo de tempo, após o qual os valores dos indicadores são recalculados, em segundos

O corpo do programa contém três loops aninhados, necessários para definir quatro pontos extremos. Somente o primeiro fundo e os pontos extremos relacionados são definidos nesta parte do programa. Definir o primeiro pico e pontos extremos relacionados é implementado de forma semelhante.  

double High[],Low[];
datetime Time[];

ArraySetAsSeries(Low,true);
int copied1=CopyLow(Symbol(),0,0,bars+2,Low);
ArraySetAsSeries(High,true);
int copied2=CopyHigh(Symbol(),0,0,bars+2,High);
ArraySetAsSeries(Time,true);
int copied3=CopyTime(Symbol(),0,0,bars+2,Time);

double delta=delta_points*Point();  //  Variação entre pontos extremos em termos absolutos

int j,k,l;
int j2,k2,l2;
double  j1,k1,l1;
int min[6];  // array que define fundos, o valor corresponde ao índice de barras para um ponto extremo detectado
int max[6];  // array que define os picos, o valor corresponde ao índice de barras para um ponto extremo detectado

int mag1=bars;
int mag2=bars;
int mag3=bars;
int mag4=bars;

j1=SymbolInfoDouble(Symbol(),SYMBOL_BID)+(1-first_extrem)*delta_points*Point();
// Quando se procura o primeiro ponto extremo, a proporção adicional define o preço mínimo, abaixo do qual se situará o primeiro fundo

j2=0; // Na primeira iteração, a busca é realizada a partir da última barra do histórico

for(j=0;j<=15;j++) // loop que define o primeiro fundo - min [1]
  {
   min[1]=minimum(j2,bars,j1);
   //define o fundo mais próximo dentro do intervalo especificado

   j2=min[1]+1;     // Na próxima iteração, a busca é realizada a partir do fundo min[1] detectado
   j1=Low[min[1]]+delta;
   //A Mínima do preço para o fundo detectado na iteração subseqüente deve ser menor que o preço baixo para o fundo encontrado na iteração atual

   k1=Low[min[1]];
   //Mínimo do preço para a parte inferior quando se procura o próximo ponto extremo define a Máxima do preço, acima do qual o pico deve ser localizado

   k2=min[1];         //a procura do pico localizado após o fundo é realizado a partir do fundo min[1] detectado

   for(k=0;k<=12;k++) // Loop que define o primeiro pico - max[1]
     {
      max[1]=maximum(k2,bars,k1);
      //--- Definir o pico mais próximo num intervalo especificado
      k1=High[max[1]]-delta;
      //A Máxima do preço para a próxima iteração deve exceder a Máxima para o pico detectado na iteração atual

      k2=max[1]+1;   // Na próxima iteração, a pesquisa é realizada a partir do pico já detectado max[1]

      l1=High[max[1]];
      //A Máxima do preço para o ponto extremo ao procurar o próximo fundo define o Mínimo do preço, abaixo do qual o fundo deve ser localizado
      l2=max[1];     // Procurar o fundo localizado após o pico é realizado a partir do pico máximo detectado [1]
      for(l=0;l<=10;l++) // Loop definindo o segundo fundo - min[2] e o segundo pico max[2]
        {
         min[2]=minimum(l2,bars,l1);
         //---Definir o fundo mais próximo dentro do intervalo especificado
         l1=Low[min[2]]+delta;
         // Mínimo do preço para o fundo detectado na iteração subseqüente deve ser menor que o Mínimo do preço para o fundo encontrado na iteração atual

         l2=min[2]+1;     // Na próxima iteração, a busca é realizada a partir do fundo min[2] detectado
         max[2]=maximum(min[2],bars,Low[min[2]]);
         //Definir o pico mais próximo num intervalo especificado

         if(max[1]>min[1] && min[1]>0 && min[2]>max[1] && min[2]<max[2] && max[2]<mag4)
           // Classificar valores extremos coincidentes e casos especiais
           {
            mag1=min[1];   // Em cada iteração, os locais dos valores extremos detectados são salvos se a condição for atendida
            mag2=max[1];
            mag3=min[2];
            mag4=max[2];
           }
        }
     }
  }
min[1]=mag1; // Pontos extremos são definidos, caso contrário o valor 'barras' é atribuído a todas as variáveis
max[1]=mag2;
min[2]=mag3;
max[2]=mag4;

Encontrar a barra mais próxima, cujo o Mínimo do preço está abaixo do valor especificado (ou a Máxima do preço que excede o valor especificado) é uma tarefa bastante simples e é transformada numa função separada.

int minimum(int a,int b,double price0)
//a função define o fundo mais próximo no intervalo especificado. O fundo está localizado abaixo do preço 0 a uma distância maior do que a faixa de variação
  {
   double High[],Low[];
   ArraySetAsSeries(Low,true);
   int copied4=CopyLow(Symbol(),0,0,bars+2,Low);

   int i,e;
   e=bars;
   double pr=price0-delta_points*Point();    // O preço abaixo do qual o fundo com a variação adicionada deve ser localizado
   for(i=a;i<=b;i++)                         // Procure o fundo dentro do intervalo especificado pelos parâmetros a e b
     {
      if(Low[i]<pr && Low[i]<Low[i+1])       // Definir o fundo mais próximo, após o crescimento dos preços começa
        {
         e=i;
         break;
        }
     }

   return(e);
  }
int maximum(int a,int b,double price1)
//--- A função define o pico mais próximo no intervalo especificado. O fundo está localizado acima do price1 a uma distância superior à faixa de variação
  {
   double High[],Low[];
   ArraySetAsSeries(High,true);
   int copied5=CopyHigh(Symbol(),0,0,bars+2,High);

   int i,e;
   e=bars;
   double pr1=price1+delta_points*Point();   // O preço acima do qual o pico com a variação adicionada deve ser localizado
   for(i=a;i<=b;i++)                         // Procure o pico dentro do intervalo especificado pelos parâmetros a e b
     {
      if(High[i]>pr1 && High[i]>High[i+1])   // Definir o pico mais próximo, após o preço começar a cair    
        {
         e=i;
         break;
        }
     }
   return(e);
  }

A tarefa de encontrar pontos extremos é resolvida, mas apenas numa primeira aproximação. Devemos considerar que o pico (localizado entre os dois fundos) encontrado usando o algoritmo pode não ser o mais alto dentro do algoritmo especificado. Uma vez que a pesquisa começou a partir do final do gráfico, a posição dos picos e fundos deve ser clarificada a partir do final para o primeiro, segundo, terceiro pontos extremos subseqüentes. A verificação e a correção das posições de pico e de fundo são feitas como funções separadas. A implementação do esboço da posição de pontos extremos é a seguinte:

min[1]=check_min(min[1],max[1]); // Verificar e corrigir a posição do primeiro fundo dentro do intervalo especificado    
max[1]=check_max(max[1],min[2]); // Verificar e corrigir a posição do primeiro pico dentro do intervalo especificado
min[2]=check_min(min[2],max[2]); // Verificar e corrigir a posição do segundo fundo dentro do intervalo especificado  

 


int check_min(int a,int b)
// a função para verificar e corrigir a posição inferior dentro do intervalo especificado      
  {
   double High[],Low[];
   ArraySetAsSeries(Low,true);
   int copied6=CopyLow(Symbol(),0,0,bars+1,Low);
   int i,c;
   c=a;
   for(i=a+1;i<b;i++)                     // Ao procurar o fundo, todas as barras especificadas pelo intervalo são verificadas
     {
      if(Low[i]<Low[a] && Low[i]<Low[c])  // Se o fundo localizado mais baixo for encontrado
         c=i;                             // O local do fundo é redefinido
     }
   return(c);
  }

int check_max(int a,int b)
//--- A função para verificar e corrigir a posição de pico dentro do intervalo especificado  
  {
   double High[],Low[];
   ArraySetAsSeries(High,true);
   int copied7=CopyHigh(Symbol(),0,0,bars+1,High);
   int i,d;
   d=a;
   for(i=(a+1);i<b;i++)                         // Ao procurar o fundo, todas as barras especificadas pelo intervalo são verificadas
     {
      if(High[i]>High[a] && High[i]>High[d])    // Se o pico localizado mais alto for encontrado
         d=i;                                   // A localização do pico é redefinida
     }
   return(d);
  }

Se quatro pontos extremos são encontrados, precisamos esclarecer as posições de apenas os três primeiros. A função de verificação e correção funciona dentro do intervalo definido para o ponto extremo atual usando sua própria posição e a posição do ponto extremo a seguir. Após o esclarecimento, podemos ter certeza de que os pontos extremos encontrados correspondem aos critérios definidos.

Depois disso, a busca do primeiro pico é realizada a partir da extremidade do gráfico e as posições do primeiro pico e do fundo são comparadas. Como resultado dos cálculos realizados, obtemos as posições do primeiro ponto extremo e os pontos extremos relacionados que estão mais próximos do final do gráfico.

Vamos falar mais uma vez sobre como encontrar o primeiro ponto extremo. Eu já ofereci para introduzir a relação de pesquisa adicional - parte fracionária da faixa de variação, por exemplo 0.7. Ao mesmo tempo, seus valores elevados (0,8...0,9) permitem definir com precisão o primeiro ponto extremo com um ligeiro atraso, enquanto seus valores baixos (0,1...0,25) diminuem o atraso para o mínimo, mas a precisão é seriamente diminuída na medida nesse caso. Consequentemente, o valor da razão adicional deve ser seleccionado dependendo da estratégia aplicada.

Os picos e fundos detectados são mostrados como setas. As setas mostram as coordenadas de pontos extremos (séries de tempo e Máximas/Mínimas do preço para um pico/fundo detectado). Como isso requer muitos cálculos, o programa apresenta o parâmetro de entrada que define o intervalo usado para recalcular os valores do indicador. Se não forem encontrados picos e fundos, o indicador gera uma mensagem apropriada. A implementação da exibição gráfica de pontos extremos tem a seguinte aparência:

if(min[1]<Max[1]) // Se o fundo estiver localizado mais próximo, sua posição, bem como as posições dos valores extremos relacionados são exibidos
  {
   ObjectDelete(0,"id_1");       // Eliminar as etiquetas feitas durante a fase anterior
   ObjectDelete(0,"id_2");
   ObjectDelete(0,"id_3");
   ObjectDelete(0,"id_4");
   ObjectDelete(0,"id_5");
   ObjectDelete(0,"id_6");

   ObjectCreate(0,"id_1",OBJ_ARROW_UP,0,Time[min[1]],Low[min[1]]);         // Destaque o primeiro fundo
   ObjectSetInteger(0,"id_1",OBJPROP_ANCHOR,ANCHOR_TOP);
   //--- Para o primeiro fundo detectado, a ligação é realizada por sua posição na série de tempo e o Mínimo do preço    

   ObjectCreate(0,"id_2",OBJ_ARROW_DOWN,0,Time[max[1]],High[max[1]]);      // Destaque o primeiro pico
   ObjectSetInteger(0,"id_2",OBJPROP_ANCHOR,ANCHOR_BOTTOM);
   //--- Para o pico detectado, a ligação é realizada por sua posição na série de tempo e a Máxima do preço    

   ObjectCreate(0,"id_3",OBJ_ARROW_UP,0,Time[min[2]],Low[min[2]]);         // Destaque o segundo fundo
   ObjectSetInteger(0,"id_3",OBJPROP_ANCHOR,ANCHOR_TOP);
   //--- Para o segundo fundo detectado, a ligação é realizada por sua posição na série de tempo e o Mínimo do preço  
  }

 


if(min[1]>Max[1]) // Se o pico estiver localizado mais próximo, sua posição, bem como as posições dos valores extremos relacionados, são exibidas
  {
   ObjectDelete(0,"id_1");  // Eliminar as etiquetas feitas durante a fase anterior
   ObjectDelete(0,"id_2");
   ObjectDelete(0,"id_3");
   ObjectDelete(0,"id_4");
   ObjectDelete(0,"id_5");
   ObjectDelete(0,"id_6");

   ObjectCreate(0,"id_4",OBJ_ARROW_DOWN,0,Time[Max[1]],High[Max[1]]);         // Definir o primeiro pico
   ObjectSetInteger(0,"id_4",OBJPROP_ANCHOR,ANCHOR_BOTTOM);
   //Para o primeiro pico detectado, a ligação é realizada pela sua posição na série temporal e a Máxima do preço

   ObjectCreate(0,"id_5",OBJ_ARROW_UP,0,Time[Min[1]],Low[Min[1]]);            // Destaque o primeiro fundo
   ObjectSetInteger(0,"id_5",OBJPROP_ANCHOR,ANCHOR_TOP);
   //para o fundo detectado, a ligação é realizada por sua posição na série de tempo e o Minimo do preço 

   ObjectCreate(0,"id_6",OBJ_ARROW_DOWN,0,Time[Max[2]],High[Max[2]]);         // Definir o segundo pico
   ObjectSetInteger(0,"id_6",OBJPROP_ANCHOR,ANCHOR_BOTTOM);
   //Para o segundo pico detectado, a ligação é realizada pela sua posição na série temporal e a Máxima do preço
  }

if(min[1]==Max[1]) Alert("Com a variação especificada, ",bars," sem barras e pontos extremos encontrados");
// Se nenhum ponto extremo for encontrado, a mensagem apropriada aparecerá

Ao desinicializar o indicador, os objetos que definem picos e fundos são removidos. 

Os algoritmos fornecidos foram usados para desenvolver o indicador personalizado que procura por pontos extremos e destaca-os no gráfico (Fig. 10).


 

Fig. 10. Os resultados da operação do indicador: o intervalo de variação 120 pips (a), o intervalo de variação 160 pips (b)

Os resultados obtidos são definidos pelo intervalo de variação. Para o valor de 120 pips e menor (Fig. 10, a), os pontos extremos estão localizados bastante próximos um do outro e o tamanho do intervalo não é de grande importância. Para o valor de 160 pips e mais (Fig. 10, b), os pontos extremos localizados são suficientes. Isso deve ser observado, ao selecionar o intervalo de pesquisa. No caso de um mercado lateral, uma ótima seleção da variação, permite encontrar automaticamente picos e fundos no caso de um movimento fraco e escolher (pular) pontos extremos separados por intervalos de tempo muito grandes.

3.3 O Expert Advisor implementa a estratégia de divergência entre histograma MACD e preços

Os algoritmos fornecidos podem ser implementados para uma variedade de estratégias. Os resultados da operação do indicador scale_factor são adequados para trabalhar com modelos gráficos, como cabeça e ombros, topo duplo, fundo duplo, etc. Eles podem ser utilizados nas estratégias de aplicação de picos e divergências de fundos para gráficos de preços e indicadores. Um dos exemplos é um Expert Advisor (EA) que segue o gráfico de preços e estratégia de divergência de histograma MACD. Esta estratégia é descrita na literatura em detalhes (ver "Trading for a Living" por Alexander Elder).

De acordo com a estratégia, se o preço vai para cima e forma um novo pico acima do anterior, mas o pico do MACD é menor do que o anterior, temos um sinal de venda. 

Se o preço se move para baixo formando um novo fundo abaixo do anterior, mas o MACD inferior é maior do que o anterior, temos um sinal de compra. 

O EA que implementa este algoritmo detecta com precisão os picos e fundos necessários de acordo com a faixa de variação, localizando principalmente as últimas mudanças no gráfico de preços. 

Os parâmetros de entrada - o intervalo para procurar pontos extremos e o intervalo de variação. Também é necessário estabelecer a divergência de preço mínimo para os dois últimos picos durante o movimento ascendente de preços (para os dois últimos fundos durante o movimento descendente de preços), desvio mínimo do histograma MACD para pontos extremos. O risco e a razão adicional são definidos por cada transação na moeda de depósito. O parâmetro guard_points define a mudança do stop loss adicional em relação ao valor de preço mínimo para o fundo mais próximo se uma posição de compra esta aberta. Consequentemente, um stop loss é deslocado para cima quando se abre uma posição de venda. Também é possível deduzir os parâmetros dos pontos extremos detectados ao abrir negociações (show_info=1).

input int      bars=500;                 //  Faixa de busca de pontos extremos
input double   delta_points=160;         //  Faixa de variação que define a distância mínima entre um pico e um fundo em pontos
input double   first_extrem=0.9;         //  Proporção adicional para procurar o primeiro valor extremo
input int      orderr_size=10;           //  Risco por cada negociação
input double   macd_t=0.00002;           //  Desvio mínimo do histograma MACD
input double   trend=100;                //  Desvio de preço mínimo para os dois picos/fundos mais próximos
input double   guard_points=30;          //  Mude o stop loss
input int      time=0;                   //  Atraso em segundos
input int      show_info=0;              //  Exibir dados sobre pontos extremos

Cálculos podem ser realizados por cada tick. O mesmo é verdadeiro para negociações. A estratégia funciona bem, mesmo com um atraso de tempo. Após definir os parâmetros principais em termos absolutos, devemos passar à busca de pontos extremos. A primeira parte do programa permite encontrar pontos extremos caso o primeiro deles seja um fundo. Depois disso, seu status é esclarecido. A segunda parte do código permite encontrar pontos extremos para o caso quando um pico está localizado primeiro no fim do gráfico. Os parâmetros de picos e de fundo são clarificados no passo seguinte.

void OnTick()
  {
   Sleep(1000*time);                //  Introduzir o atraso

   double High[],Low[];

   ArraySetAsSeries(Low,true);
   int copied1=CopyLow(Symbol(),0,0,bars+2,Low);
   ArraySetAsSeries(High,true);
   int copied2=CopyHigh(Symbol(),0,0,bars+2,High);
   ArraySetAsSeries(Time,true);
   int copied3=CopyTime(Symbol(),0,0,bars+2,Time);

   MqlTick last_tick;
   double Bid=last_tick.bid;
   double Ask=last_tick.ask;

   double delta=delta_points*Point();  // Valor de variação em termos absolutos
   double trendd=trend*Point();        // Desvio de preço mínimo para os dois picos/fundos mais próximos em termos absolutos
   double guard=guard_points*Point();  // deslocamento do stop loss em termos absolutos


   int j,k,l;
   int j2,k2,l2;
   double  j1,k1,l1;
   int min[6];  // array define fundos se o primeiro valor extremo detectado for inferior, o valor corresponde ao índice de barras para um ponto extremo detectado
   int max[6];  // array define picos se o primeiro valor extremo detectado for um fundo, o valor corresponde ao índice de barras para um ponto extremo detectado
   int Min[6];  // array define fundos se o primeiro valor extremo detectado for um pico, o valor corresponde ao índice de barras para um extremo detectado
   int Max[6];  // array define picos se o primeiro valor extremo detectado for um pico, o valor corresponde ao índice de barra para um ponto extremo detectado

   int mag1=bars;
   int mag2=bars;
   int mag3=bars;
   int mag4=bars;

   j1=SymbolInfoDouble(Symbol(),SYMBOL_BID)+(1-first_extrem)*delta_points*Point();
   // Quando se procura o primeiro ponto extremo, a relação adicional define o preço mínimo, abaixo do qual se situará o primeiro fundo

   j2=0;                         // Na primeira iteração, a busca é realizada a partir da última barra do histórico
   for(j=0;j<=15;j++)            // Loop definindo o primeiro fundo - min[1]
     {
      min[1]=minimum(j2,bars,j1);
      //Definir o fundo mais próximo dentro do intervalo especificado

      j2=min[1]+1;              //Na próxima iteração, a busca é realizada a partir do fundo min[1] detectado
      j1=Low[min[1]]+delta;
      //--- A Mínima do preço para o fundo detectado na iteração subseqüente deve ser menor que a Mínima do preço para o fundo encontrado na iteração atual
      k1=Low[min[1]];
      //Mínima do preço para a parte inferior quando se procura o próximo ponto extremo define a Máxima do preço, acima do qual o pico deve ser localizado

      k2=min[1];                 // Procurar o pico localizado após o fundo ser realizado a partir do fundo min[1] detectado

      for(k=0;k<=12;k++)         // loop que define o primeiro pico - max[1]
        {
         max[1]=maximum(k2,bars,k1);
         //--- Definir o pico mais próximo num intervalo especificado
         k1=High[max[1]]-delta;
         //--- A Máxima do preço para a próxima iteração deve exceder a Máxima do preço para o pico detectado na iteração atual
         k2=max[1]+1;            // Na próxima iteração, a pesquisa é realizada a partir do pico max[1] detectado
         l1=High[max[1]];
         //--- A Máxima do preço para o ponto extremo ao procurar o próximo fundo define a Mínima do preço, abaixo do qual o fundo deve ser localizado
         l2=max[1];              // a procura do fundo localizado após o pico é realizada a partir do pico max[1] detectado
         for(l=0;l<=10;l++)      // Loop definindo o segundo fundo - min[2] e o segundo pico max[2]
           {
            min[2]=minimum(l2,bars,l1);
            //---Definir o fundo mais próximo dentro do intervalo especificado
            l1=Low[min[2]]+delta;
            //O baixo preço para o fundo detectado na iteração subseqüente deve ser menor que o preço baixo para o fundo encontrado na iteração atual

            l2=min[2]+1;         //Na próxima iteração, a busca é realizada a partir do fundo min[2] detectado

            max[2]=maximum(min[2],bars,Low[min[2]]);
            //Definir o pico mais próximo num intervalo especificado
            if(max[1]>min[1] && min[1]>0 && min[2]>max[1] && min[2]<max[2] && max[2]<mag4)
              //--- Classificar valores extremos coincidentes e casos especiais
              {
               mag1=min[1];      // Em cada iteração, os locais dos valores extremos detectados são salvos se a condição for atendida
               mag2=max[1];
               mag3=min[2];
               mag4=max[2];

              }
           }
        }

     }

//---Pontos extremos são definidos, caso contrário o valor 'bars' é atribuído a todas as variáveis
   min[1]=mag1;
   max[1]=mag2;
   min[2]=mag3;
   max[2]=mag4;
//--- Verificar e corrigir a posição de pontos extremos dentro do intervalo especificado

   min[1]=check_min(min[1],max[1]);  
   max[1]=check_max(max[1],min[2]);
   min[2]=check_min(min[2],max[2]);

//---------------------------------------------------------------------------------------------------------------
   mag1=bars;
   mag2=bars;
   mag3=bars;
   mag4=bars;

   j1=SymbolInfoDouble(Symbol(),SYMBOL_BID)-(1-first_extrem)*delta_points*Point();
   // Ao procurar o primeiro ponto extremo, a relação adicional define o preço máximo, acima do qual o primeiro pico deve ser localizado

   j2=0;  // Na primeira iteração, a busca é realizada a partir da última barra do histórico

   for(j=0;j<=15;j++)      // Loop que define o primeiro pico - Max[1]
     {
      Max[1]=maximum(j2,bars,j1);
      //Definir o pico mais próximo dentro do intervalo especificado

      j1=High[Max[1]]-delta;
      //A Máxima do preço para a próxima iteração deve exceder a Maxima do preço para o pico detectado na iteração atual
      j2=Max[1]+1;         // Na próxima iteração, a pesquisa é realizada a partir do pico Max[1] detectado

      k1=High[Max[1]];
      //A Máxima do preço para o ponto extremo ao procurar o próximo fundo define a Mínima do preço, abaixo do qual o fundo deve ser localizado

      k2=Max[1];           // A procura do fundo localizado após o pico é realizado a partir do pico max[1] detectado

      for(k=0;k<=12;k++)   //Loop definindo o primeiro pico - Min[1]
        {
         Min[1]=minimum(k2,bars,k1);
         //--- Definir o fundo mais próximo dentro do intervalo especificado
         k1=Low[Min[1]]+delta;
         //A Mínima do preço para o fundo detectado na iteração subseqüente deve ser menor que a Mínima do preço para o fundo encontrado na iteração atual
         k2=Min[1]+1;      // Na próxima iteração, a busca é realizada a partir do fundo min[1] detectado
         l1=Low[Min[1]];
         //---Mínima do preço para a parte inferior ao procurar o próximo ponto extremo que define a Máxima do preço, acima do qual o pico deve ser localizado
         l2=Min[1];        // a procura do pico localizado após o fundo é realizado a partir do fundo min[1] detectado
         for(l=0;l<=10;l++)//loop definindo o segundo pico - Max[2] e o segundo fundo Min[2]
           {
            Max[2]=maximum(l2,bars,l1);
            //Definir o pico mais próximo dentro do intervalo especificado

            l1=High[Max[2]]-delta;
            //A Maxima do preço para a próxima iteração deve exceder o preço alto para o pico detectado na iteração atual
            l2=Max[2]+1;  //Na próxima iteração, a busca é realizada a partir do pico Max[2] detectado

            Min[2]=minimum(Max[2],bars,High[Max[2]]);
            //---Definir o fundo mais próximo dentro do intervalo especificado
            if(Max[2]>Min[1] && Min[1]>Max[1] && Max[1]>0 && Max[2]<Min[2] && Min[2]<bars)
              //--- Classificar valores extremos coincidentes e casos especiais
              {
               mag1=Max[1];  //Em cada iteração, os locais dos valores extremos detectados são salvos se a condição for atendida
               mag2=Min[1];
               mag3=Max[2];
               mag4=Min[2];
              }
           }
        }
     }
   Max[1]=mag1;  // Pontos extremos são definidos, caso contrário o valor 'bars' é atribuído a todas as variáveis
   Min[1]=mag2;
   Max[2]=mag3;
   Min[2]=mag4;

   Max[1]=check_max(Max[1],Min[1]);  // Verificar e corrigir as posições dos pontos extremos dentro do intervalo especificado
   Min[1]=check_min(Min[1],Max[2]);
   Max[2]=check_max(Max[2],Min[2]);

Mais adiante, podemos usar o primeiro pico ou o primeiro fundo detectado, no entanto, parece mais razoável usar o ponto extremo mais próximo, bem como picos e fundos obtidos com base nele. 

Para ambos os casos, são calculados o tamanho do lote, assim como os valores dos indicadores correspondentes às posições pontuais extremas. Verifica-se a condição para detecção correta de pontos extremos e a ausência de posições abertas.

Se houver uma divergência entre os preços de pontos extremos e o histograma do MACD e não for menor que os valores definidos pelas entradas, a posição apropriada é aberta. As divergências devem ser dirigidas de forma oposta.

   double lot_buy=NormalizeDouble(0.1*orderr_size/(NormalizeDouble(((SymbolInfoDouble(Symbol(),SYMBOL_BID)-Low[min[1]]+guard)*10000),0)+0.00001),2);
   //Calcular o lote na compra

   double lot_sell=NormalizeDouble(0.1*orderr_size/(NormalizeDouble(((High[Max[1]]-SymbolInfoDouble(Symbol(),SYMBOL_ASK)+guard)*10000),0)+0.00001),2);
   //--- Calcular o lote na venda
   int index_handle=iMACD(NULL,PERIOD_CURRENT,12,26,9,PRICE_MEDIAN);
   double MACD_all[];
   ArraySetAsSeries(MACD_all,true);
   int copied4=CopyBuffer(index_handle,0,0,bars+2,MACD_all);
   double index_min1=MACD_all[min[1]];
   double index_min2=MACD_all[min[2]];
   //---Calcular os valores dos indicadores correspondentes aos pontos extremos se o primeiro ponto extremo for um fundo
   double index_Max1=MACD_all[Max[1]];
   double index_Max2=MACD_all[Max[2]];
   //Calcular os valores dos indicadores correspondentes aos pontos extremos se o primeiro ponto extremo for um pico
   bool flag_1=(min[2]<bars && min[2]!=0 && max[1]<bars && max[1]!=0 && max[2]<bars && max[2]!=0); //Verifique se o estado da condição de ponto extremo está correto
   bool flag_2=(Min[1]<bars && Min[1]!=0 && Max[2]<bars && Max[2]!=0  && Min[2]<bars && Min[2]!=0);
   bool trend_down=(Low[min[1]]<(Low[min[2]]-trendd));
   bool trend_up=(High[Max[1]]>(High[Max[2]]+trendd));
   //---Diferença entre valores de preços de pontos extremos não deve ser inferior a um valor definido
   openedorder=PositionSelect(Symbol());  //Verificar a condição para a ausência de posições abertas
   if(min[1]<Max[1] && trend_down && flag_1 && !openedorder && (index_min1>(index_min2+macd_t)))
      //Se o primeiro ponto extremo é um fundo, uma negociação de compra é aberta
      //Diferença entre valores MACD para pontos extremos não é menor do que o valor de macd_t definido como uma entrada
      // A negociação é aberto em caso de movimentos dos preços opostos e o indicador calculado com base em pontos extremos
     {
      if(show_info==1) Alert("Para as últimas",bars," barras, a distância em barras para o fundo mais proximo e pontos extremos",min[1]," ",max[1]," ",min[2]);
      //--- Exibir dados em pontos extremos
      MqlTradeResult result={0};
      MqlTradeRequest request={0};
      request.action=TRADE_ACTION_DEAL;
      request.magic=123456;
      request.symbol=_Symbol;
      request.volume=lot_buy;
      request.price=SymbolInfoDouble(Symbol(),SYMBOL_ASK);
      request.sl=Low[min[1]]-guard;
      request.tp=MathAbs(2*SymbolInfoDouble(Symbol(),SYMBOL_BID)-Low[min[1]])+guard;
      request.type=ORDER_TYPE_BUY;
      request.deviation=50;
      request.type_filling=ORDER_FILLING_FOK;

      OrderSend(request,result);
     }

   if(min[1]>Max[1] && trend_up && flag_2 && !openedorder && (index_Max1<(index_Max2-macd_t)))
      // Se o primeiro ponto extremo é um pico, uma negociação de venda é aberta
      //Diferença entre valores MACD para pontos extremos não é menor do que o valor de macd_t definido como uma entrada
      // A negociação é aberta em caso de movimentos dos preços opostos e o indicador calculado com base em pontos extremos
     {
      if(show_info==1) Alert("Para as últimas",bars," barras, a distância em barras para o pico mais proximo e pontos extremos",Max[1]," ",Min[1]," ",Max[2]);
      //---Exibir dados em pontos extremos
      MqlTradeResult result={0};
      MqlTradeRequest request={0};
      request.action=TRADE_ACTION_DEAL;
      request.magic=123456;
      request.symbol=_Symbol;
      request.volume=lot_sell;
      request.price=SymbolInfoDouble(Symbol(),SYMBOL_BID);
      request.sl=High[Max[1]]+guard;
      request.tp=MathAbs(High[Max[1]]-2*(High[Max[1]]-SymbolInfoDouble(Symbol(),SYMBOL_ASK)))-guard;
      request.type=ORDER_TYPE_SELL;
      request.deviation=50;
      request.type_filling=ORDER_FILLING_FOK;

      OrderSend(request,result);
     }

Ao abrir uma posição de venda, uma stop loss é definido pela posição do pico mais próximo, enquanto ao abrir uma posição de compra, é definida pela posição do fundo mais próximo, o que nos permite estabelecer alvos realistas tanto durante fortes flutuações de preços quanto em mercados silenciosos Em ambos os casos, um take profit é definido simétricamente a um stop loss em relação ao valor do preço atual. Na negociação intraday, é selecionada uma pequena faixa de variação, enquanto no investimento de longo prazo é aconselhável definir a faixa de variação algumas vezes maior.

Vamos considerar o seguinte exemplo da operação EA (Fig. 11). Os principais parâmetros aplicados: faixa de variação  — 160 pips, divergência mínima do histograma MACD - 0,0004; divergência de preços mínimos para os dois mais próximos picos/fundos - 120 pips e razão adicional - 0,9. 


Fig. 11. Os resultados da operação do EA

Primeiro, a EA procura os últimos 3 pontos extremos. No momento de tomar a decisão para ir adiante, o EA detecta um pico e dois fundos (marcados como setas). Ao contrário do indicador, o EA não destaca os pontos extremos. No entanto, podemos obter dados sobre posições de pontos extremos ao abrir negociações definindo show_info como 1.

A divergência de preços para os dois fundos mais próximos é composta por 148 pips que excedem o valor especificado. A divergência do histograma MACD abrange 0,00062 para os mesmos extremos que ultrapassam também o valor especificado. Considerando os movimentos de preços e movimentos indicados de forma oposta, detectados pelos dois últimos fundos, a posição longa é aberta no ponto definido pela relação adicional (150 pips). Se usar uma relação adicional mais baixa, a posição poderia ter sido aberta mais cedo, assim o lucro poderia ter sido fixado mais cedo.

Abaixo estão os resultados do teste EA (Fig. 12). O impacto máximo dos parâmetros macd_t e de tendência sobre a rentabilidade foi revelado durante o teste. Quanto maior o valor dos parâmetros, maior a quantidade de negócios rentáveis em valor percentual. No entanto, o aumento da rentabilidade ocorre simultaneamente com a diminuição do número total de negócios. 

Por exemplo, se macd_t = 0.0006 e a tendência = 160 (Fig. 12), 56% dos negócios revelaram-se rentáveis em 44. Se macd_t = 0.0004 e a tendência = 120, 84 negócios são realizados com 51% deles sendo lucrativos.


 Fig. 12. Os resultados do teste EA

Ao otimizar a estratégia, os parâmetros macd_t e tendência corretamente definidos são de importância crítica. O intervalo de variação e o valor adicional também afetam os parâmetros da negociação. O intervalo de variação define o número de pontos extremos detectados e negociações. A relação adicional define o quão próximos o take profit e o stop loss devem ser localizados ao abrir posições.

Esta estratégia, bem como uma série de outras, podem funcionar tão correctamente quanto possível apenas quando se utiliza as ferramentas propostas acima. Caso contrário, pode haver situações em que uma negociação com um take profit especificado e stop loss em 200 pontos do valor do preço atual é aberto com base nos sinais recebidos quando se utiliza pontos extremos de 5 pontos ou menos. A importância de tais pontos extremos é muito baixa neste caso. Nestas e em muitas outras situações, as ferramentas convencionais definem demasiados pontos extremos insignificantes ou não detectam picos e fundos. Além disso, essas ferramentas muitas vezes têm problemas definindo pontos extremos no final de uma série de tempo.

Conclusão

Os algoritmos e soluções descritos no artigo permitem definir com precisão pontos extremos nos gráficos de preços, dependendo da variação de preço. Os resultados obtidos são aplicáveis tanto na definição dos padrões gráficos quanto na implementação de estratégias de negociação que utilizam padrões e indicadores gráficos. As ferramentas desenvolvidas apresentam uma série de vantagens sobre as soluções bem conhecidas. Apenas pontos extremos críticos são definidos independentemente da situação do mercado (tendência ou lateral). Somente pontos extremos que excedam um valor predefinido são detectados. Outros picos e fundos são ignorados. A busca de pontos extremos é realizada a partir do fim do gráfico, o que nos permite obter resultados principalmente dependendo das recentes flutuações de preços. Estes resultados não são fortemente afetados por um prazo selecionado e são apenas definidos por uma variação de preço especificada.