O indicador ZigZag: nova abordagem e novas soluções

Sergey Pavlov | 21 março, 2014

Introdução

Todo investidor conhece certamente o indicador ZigZag destinado à análise dos movimentos de preço de uma dada amplitude ou maior. A linha ZigZag é uma linha quebrada, cujos nós ficam localizados nos altos e baixos do gráfico de preços.

Existem muitas variações desse indicador: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16. Ainda, muitos desenvolvedores de programas do MQL5 são entusiastas na criação de seus próprios ZigZags "ideais". Os principais aspectos negativos do indicador ZigZag são a demora, marcações incorretas de nós questionáveis (barra externa) e desempenho insatisfatório.

Na minha opinião, a implementação mais elegante do ZigZag foi proposta por Yuri Kulikov (Yurich). Além disso, existem alguns artigos do MQL4 muito bons, como o "Notas para os leigos: ZigZag..." e "O show deve continuar, ou Mais uma vez sobre o ZigZag". O assunto parece ter sido explorado substancialmente, com um grande número de publicações disponíveis. E, ainda, existe algo hipnotizante a respeito dele. Agora, também despertou meu interesse, particularmente na possibilidade de criação de um indicador avançado ZigZag.

Esse artigo descreve um método para criar um ZigZag avançado utilizando o indicador Envelopes. Presume-se que podemos encontrar uma certa combinação de parâmetros de entrada para uma série de Envelopes, pelos quais a maioria dos nós dos ZigZags se encontram nos confins das faixas dos Envelopes.

 

Um método para criar um indicador avançado ZigZag

Vamos estabelecer um objetivo: encontrar as coordenadas de dois nós - o nó atual e o nó previsto (Fig. 1). O nó atual é um nó que ainda não está completo e cujas coordenadas ainda estão sendo buscadas ou ajustadas. Além disso, ele está sempre na barra atual (zero). Apesar de estar no futuro, um nó previsto deve mostrar o nível estimado do próximo nó do ZigZag.

Prevendo novos nós do ZigZag

Fig. 1. Prevendo novos nós do ZigZag: o nó atual e o próximo nó

Então o objetivo está estabelecido e temos uma ideia de como utilizar Envelopes de média móvel como uma base para montar um indicador avançado (Fig. 2). Vamos procurar envelopes cujos desvios dos nós do ZigZag sejam mínimos. Parece bastante lógico que os envelopes para os altos e baixos do ZigZag devem ser buscados separadamente.

Indicadores ZigZag e envelopes de médias móveis

Fig. 2. Indicadores ZigZag e envelopes de médias móveis

Para aumentar a significância estatística da previsão, ao invés de utilizar somente um ou até mesmo 10 indicadores de envelopes, devemos utilizar um grupo de 100 ou mais indicadores com diferentes dados de entrada. Eles vão se diferenciar no período de referência na linha do indicador principal e no preço usado (alto para os picos e baixo para os baixos). Vamos apresentar as seguintes notas e fórmulas:

Temos dois grupos de indicadores: um para os picos e outro para as baixas (cerca de 100 indicadores em cada um). Vamos calcular o desvio dos nós do ZigZag da linha principal do indicador Envelopes para cada indicador no grupo e encontrar a média aritmética dos desvios para cada indicador de grupo utilizando as fórmulas acima. A figura a seguir demonstra um diagrama de desvios com respeito aos nós identificados ZZ da linha principal ENV para um indicador.

Diagrama de desvios dos nós ZZ do ENV

Fig. 3. Diagrama de desvios dos nós ZZ do ENV

A média aritmética dos desvios será utilizado para determinar o nível para o qual a linha principal do indicador Envelopes deve ser deslocado para plotar as faixas do envelope. Então, precisaremos da média aritmética dos picos do ZigZag para desenharmos a linha superior e a média aritmética dos desvios das baixas para desenharmos a linha inferior do indicador Envelopes.

São as linhas superiores e inferiores dos envelopes que usaremos para localizar pontos característicos e prever os nós do ZigZag. Mais uma vez, estamos interessados no grupo de envelopes que consiste em um conjunto dos indicadores Envelopes. A média aritmética dos desvios dos nós do ZigZag da linha principal de um envelope dado é calculado para cada indicador. Depois de plotar as linhas resultantes (as linhas superior e inferior) do grupo no gráfico, poderemos ver o seguinte:

As linhas de Envelopes no plano

Fig. 4. As linhas de Envelopes no plano

Se presumirmos que cada linha fica em um plano separado, enquanto todas elas juntas criam uma superfície, a figura acima mostra somente a projeção de cada indicador no plano do gráfico de preço. Uma imagem 3D dessas linhas será mais ou menos como a seguir:

As linhas de Envelopes em 3D

Fig. 5. As linhas de Envelopes em 3D

Agora vamos ter uma rápida aula de geometria. Imagine que o grupo de linhas do indicador envelopes seja uma superfície 3D. Tome um plano perpendicular ao gráfico de preço e corte a superfície na barra atual (zero).

Como resultado, obtemos um corte transversal da superfície representando uma curva (as figuras acima demonstram um caso especial onde a curva é uma linha reta). Para fazer a previsão, basta ter as coordenadas de cada ponto da curva que será utilizado nos cálculos mais adiante.

Precisaremos das seguintes características transeccionais: ponto de máximo e mínimo, assim como o centro de gravidade do corte transversal (a média aritmética de todos os valores dos pontos). Os pontos característicos obtidos serão lançados na barra atual (zero), com os dados relevantes sendo armazenados no histórico. Estes pontos característicos servirão como base para os atuais e os próximos ZigZag.

Já que a busca pelos laços do Envelope é realizada separadamente por picos e baixas, como resultado devemos obter dois cortes transversais: um para os picos e outro para as baixas.

Para obter a previsão, utilizaremos o ponto característico mais próximo. Por exemplo, ao buscar por um pico do ZigZag, tomamos os pontos característicos do corte transversal resultantes da interseção da superfície das linhas superiores do indicador Envelopes com um plano de corte. Por outro lado, para encontrar uma baixa tomamos os pontos característicos do corte transversal resultante da intersecção da superfície das linhas inferiores do indicador Envelopes com um plano de corte.

 

Testando um novo indicador

Agora que definimos o método, vamos criar o indicador. Primeiramente encontraremos os últimos nós do indicador ZigZag e desenhá-los no gráfico. Para isso, utilizaremos a classe AdvancedZigZag escrita para a tarefa em questão:

//+------------------------------------------------------------------+
//|                                               AdvancedZigZag.mqh |
//|                                           Copyright 2013, DC2008 |
//|                           https://www.mql5.com/ru/users/DC2008 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2013, DC2008"
#property link      "https://www.mql5.com/ru/users/DC2008"
#property version   "1.00"
//+------------------------------------------------------------------+
//|                                                 GetExtremums.mqh |
//+------------------------------------------------------------------+
#include <GetExtremums.mqh>   // author of the code Yurich
#property copyright "Copyright 2012, Yurich"
#property link      "https://www.mql5.com/ru/users/Yurich"
//+------------------------------------------------------------------+
//| ZigZag node structure                                            |
//+------------------------------------------------------------------+
struct MqlZigZag
  {
   double            price;   // Node coordinate
   datetime          t;       // Time
  };
//+------------------------------------------------------------------+
//| The AdvancedZigZag class                                         |
//+------------------------------------------------------------------+
class AdvancedZigZag
  {
private:
   MqlRates          rt[];
   dextremum         zz[];
   int               history;
   double            amplitude;
public:
   dextremum         zHL[];
   MqlZigZag         zzH[],zzL[];
   int               Count(const double range);
   int               Read(const int nodes);
                     AdvancedZigZag(const int bars);
                    ~AdvancedZigZag();
  };
//+------------------------------------------------------------------+
//| Class constructor                                                |
//+------------------------------------------------------------------+
AdvancedZigZag::AdvancedZigZag(const int bars)
  {
   history=bars;
   amplitude=0;
  }
//+------------------------------------------------------------------+
//| The Read method of the class                                     |
//+------------------------------------------------------------------+
int AdvancedZigZag::Read(const int nodes)
  {
   CopyRates(NULL,0,TimeCurrent(),history,rt);
   int cnt=GetExtremums(amplitude,rt,zHL,nodes);
   return(cnt);
  }
//+------------------------------------------------------------------+
//| The Count method of the class                                    |
//+------------------------------------------------------------------+
int AdvancedZigZag::Count(const double range)
  {
   amplitude=range;
   CopyRates(NULL,0,TimeCurrent(),history,rt);
   int cnt=GetExtremums(amplitude,rt,zz);
   ArrayResize(zzH,cnt);
   ArrayResize(zzL,cnt);
   int h=0;
   int l=0;
   for(int i=0; i<cnt; i++)
     {
      if(zz[i].type>0)
        {
         zzH[h]=(MqlZigZag)zz[i];
         h++;
        }
      else
        {
         zzL[l]=(MqlZigZag)zz[i];
         l++;
        }
     }
   ArrayResize(zzH,h);
   ArrayResize(zzL,l);
   return(cnt);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
AdvancedZigZag::~AdvancedZigZag()
  {
  }

Existem dois métodos ao todo:

A biblioteca GetExtremums (por Yury Kulikov) também será necessária na busca pelos nós.

Vamos colocar o indicador em análise em um Consultor Especialista. Por que um Consultor Especialista e não um indicador? Certamente é uma questão de gosto, mas me parece ser mais eficiente dessa forma. As características gráficas do Consultor Especialista são, sem sombra de dúvida, mais fracas, porém, ganhamos em desempenho já que os indicadores de mesmo símbolo operam em um único fluxo, enquanto cada CE opera em seu fluxo separado. Vamos dar uma olhada no código:

//+------------------------------------------------------------------+
//|                                                   two_Comets.mq5 |
//|                                           Copyright 2013, DC2008 |
//|                           https://www.mql5.com/ru/users/DC2008 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2013, DC2008"
#property link      "https://www.mql5.com/ru/users/DC2008"
#property version   "1.00"
#include <AdvancedZigZag.mqh>
//--- Depth of history for the indicator calculation
input int      depth_stories=5000;  // Depth stories for calculating the indicator [bars]
//--- Minimum ZigZag amplitude value
input int      amplitude=100;        // The minimum value of the amplitude of the indicator [points]
//--- Declaring the class
AdvancedZigZag Azz(depth_stories);
//---
#define NUMBER_MA   227
#define START_MA    5
//--- macros
#define SIZE(i)                     (double)i*0.3<1?1:(int)(i*0.25)
#define ObjF1                       ObjectSetString(0,name,OBJPROP_FONT,"Wingdings")
#define ObjF2                       ObjectSetInteger(0,name,OBJPROP_ANCHOR,ANCHOR_CENTER)
#define ObjF3(T)                    ObjectSetInteger(0,name,OBJPROP_TIME,T)
#define ObjF4(P)                    ObjectSetDouble(0,name,OBJPROP_PRICE,P)
#define ObjF5(size)                 ObjectSetInteger(0,name,OBJPROP_FONTSIZE,size)
#define ObjF6(code)                 ObjectSetString(0,name,OBJPROP_TEXT,CharToString(code))
#define ObjF7(clr)                  ObjectSetInteger(0,name,OBJPROP_COLOR,clr)
#define ObjF8                       ObjectSetInteger(0,name,OBJPROP_COLOR,clrMagenta)
#define ObjF9                       ObjectSetInteger(0,name,OBJPROP_WIDTH,3)
#define ObjF10                      ObjectSetInteger(0,name,OBJPROP_BACK,true) 
#define ObjFont                     ObjF1;ObjF2;
#define ObjCoordinates(T,P)         ObjF3(T);ObjF4(P);
#define ObjProperty(size,code,clr)  ObjF5(size);ObjF6(code);ObjF7(clr);
#define ObjZZ                       ObjF8;ObjF9;ObjF10;
//---
double      MA[1],sumHi[NUMBER_MA],sumLo[NUMBER_MA];
int         handle_MA_H[NUMBER_MA],handle_MA_L[NUMBER_MA];
datetime    t[1];
int         H,L;
int         t_min,t_max;
int         err=-1;
double      sumH[2],maxH[2],minH[2];
double      sumL[2],maxL[2],minL[2];
string      name;
int         count;
int         shift;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   shift=PeriodSeconds()/30;
//--- calculation of ZigZag nodes using historical data
   Azz.Count(amplitude*Point());
   H=ArraySize(Azz.zzH);
   L=ArraySize(Azz.zzL);
   if(H<30 || L<30)
     {
      Print("Not enough data to calculate ZigZag nodes: "+
            "increase the depth of history; "+
            "or decrease the amplitude value.");
      return(-1);
     }
//---
   for(int i=0; i<NUMBER_MA; i++)
     {
      handle_MA_H[i]=iMA(NULL,0,i+START_MA,0,MODE_SMA,PRICE_HIGH);
      handle_MA_L[i]=iMA(NULL,0,i+START_MA,0,MODE_SMA,PRICE_LOW);
     }
//---
   return(0);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   ObjectsDeleteAll(0,-1,-1);
   for(int i=0; i<NUMBER_MA; i++)
     {
      IndicatorRelease(handle_MA_H[i]);
      IndicatorRelease(handle_MA_L[i]);
     }
//---
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+

void OnTick()
  {
//--- get the current bar's opening time value
   CopyTime(NULL,0,0,1,t);
//--- ZigZag: last 7 nodes
   count=Azz.Read(7);
   for(int i=1; i<count; i++)
     {
      name="ZZ"+(string)i;
      ObjectCreate(0,name,OBJ_TREND,0,0,0);
      ObjectSetInteger(0,name,OBJPROP_COLOR,clrRed);
      ObjectSetInteger(0,name,OBJPROP_WIDTH,10);
      ObjectSetInteger(0,name,OBJPROP_BACK,true);
      ObjectSetDouble(0,name,OBJPROP_PRICE,0,Azz.zHL[i-1].value);
      ObjectSetInteger(0,name,OBJPROP_TIME,0,Azz.zHL[i-1].time);
      ObjectSetDouble(0,name,OBJPROP_PRICE,1,Azz.zHL[i].value);
      ObjectSetInteger(0,name,OBJPROP_TIME,1,Azz.zHL[i].time);
     }
//--- check for integrity of preliminary calculations
   if(err<0)
     {
      //--- calculate the sums of deviations of the nodes from MA for ZigZag peaks
      ArrayInitialize(sumHi,0.0);
      for(int j=H-1; j>=0; j--)
        {
         for(int i=0; i<NUMBER_MA; i++)
           {
            err=CopyBuffer(handle_MA_H[i],0,Azz.zzH[j].t,1,MA);
            if(err<0) return;
            sumHi[i]+=Azz.zzH[j].price-MA[0];
           }
        }
      //--- calculate the sums of deviations of the nodes from MA for ZigZag troughs
      ArrayInitialize(sumLo,0.0);
      for(int j=L-1; j>=0; j--)
        {
         for(int i=0; i<NUMBER_MA; i++)
           {
            err=CopyBuffer(handle_MA_L[i],0,Azz.zzL[j].t,1,MA);
            if(err<0) return;
            sumLo[i]+=MA[0]-Azz.zzL[j].price;
           }
        }
     }
  }
//+------------------------------------------------------------------+

Precisamos esclarecer algumas coisas aqui:

Então, o indicador resultante plota os últimos sete nós do ZigZag e calcula as coordenadas de todos os outros nós em um dado histórico. (Fig. 6). O cálculo somente é realizado uma vez e usamos posteriormente os dados calculados. Você pode, claro, implementá-lo de tal forma a permitir que os dados sejam atualizados regularmente, mas nesse artigo resumiremos a um único passo.

O indicador ZigZag (7 nós)

Fig. 6. O indicador ZigZag (7 nós)

Posteriormente, vamos plotar os cortes transversais das superfícies dos indicadores Envelopes. Para fazê-lo, adicionaremos o seguinte ao método OnTick ():

//--- PEAKS
   sumH[0]=0.0;
   maxH[0]=0.0;
   minH[0]=0.0;
   for(int i=0; i<NUMBER_MA; i++)
     {
      CopyBuffer(handle_MA_H[i],0,t[0],1,MA);
      double envelope=MA[0]+sumHi[i]/H;
      if(i==0 || envelope<minH[0])
        {
         minH[0]=envelope;
         t_min=SIZE(i);
        }
      if(envelope>maxH[0])
        {
         maxH[0]=envelope;
         t_max=SIZE(i);
        }
      sumH[0]+=envelope;
      name="H"+(string)i;
      ObjectCreate(0,name,OBJ_TEXT,0,0,0);
      ObjFont
      ObjCoordinates(t[0]-(NUMBER_MA-i*2)*shift,envelope)
      ObjProperty(SIZE(i),158,clrBlue)
     }
//--- TROUGHS
   sumL[0]=0.0;
   maxL[0]=0.0;
   minL[0]=0.0;
   for(int i=0; i<NUMBER_MA; i++)
     {
      CopyBuffer(handle_MA_L[i],0,t[0],1,MA);
      double envelope=MA[0]-sumLo[i]/L;
      if(i==0 || envelope<minL[0])
        {
         minL[0]=envelope;
         t_min=SIZE(i);
        }
      if(envelope>maxL[0])
        {
         maxL[0]=envelope;
         t_max=SIZE(i);
        }
      sumL[0]+=envelope;
      name="L"+(string)i;
      ObjectCreate(0,name,OBJ_TEXT,0,0,0);
      ObjFont
      ObjCoordinates(t[0]+(NUMBER_MA-i*2)*shift,envelope)
      ObjProperty(SIZE(i),158,clrGold)
     }
Uma nota para programadores iniciantes: os operadores ao final do bloco de picos e baixas não têm ';' no fim da cadeia. Não é um erro ou algo similar. São macros (veja a seção de dados onde eles são declarados) - eles são muito úteis! Eu recomendo que você os use em seus programas.

Para identificar os pontos do corte transversal da superfície formada pelas linhas envelopes, os pontos variam de tamanho: quanto maior for o período de média da linha principal dos indicadores Envelopes, maiores serão os pontos (Fig. 7). Além disso, os cortes transversais são rodados ao redor de um eixo vertical passando através da barra atual (zero) em direções diferentes: picos ficam a 90 graus a direita e baixas ficam a 90 graus a esquerda.

Agora eles podem ser vistos no plano do gráfico de preço. Inicialmente, eles estavam no plano de corte (Fig. 5) e não podiam ser observados. Podíamos somente imaginá-los, sem ter qualquer ideia a respeito de seu formato. As linhas transversais acabaram se tornando uma forma bastante peculiar. Isso também é feito para a comodidade da análise gráfica. Visualmente, os cortes transversais lembram dois cometas voadores:

Corte transversal do grupo de indicadores Envelopes

Fig. 7. Corte transversal do grupo de indicadores Envelopes

Vamos dar continuidade com o cálculo das características transeccionais: o máximo e o mínimo, assim como o centro de gravidade (a média aritmética). Os valores resultantes serão exibidos na forma de pontos na barra atual, com o tamanho do ponto correspondendo ao tamanho da característica relevante. Além disso, iremos gravá-los no histórico para análise posterior. Então, adicionaremos o seguinte ao código atual:

//--- PEAKS

...

//--- midi
   string str=(string)t[0];
   name="Hmidi"+str;
   ObjectCreate(0,name,OBJ_TEXT,0,0,0);
   ObjFont
   ObjCoordinates(t[0],sumH[0]/NUMBER_MA)
   ObjProperty(10,119,clrBlue)
//--- max
   name="Hmax"+str;
   ObjectCreate(0,name,OBJ_TEXT,0,0,0);
   ObjFont
   ObjCoordinates(t[0],maxH[0])
   ObjProperty(t_max,158,clrBlue)
//--- min
   name="Hmin"+str;
   ObjectCreate(0,name,OBJ_TEXT,0,0,0);
   ObjFont
   ObjCoordinates(t[0],minH[0])
   ObjProperty(t_min,158,clrBlue)

...

//--- TROUGHS

...

//--- midi
   name="Lmidi"+str;
   ObjectCreate(0,name,OBJ_TEXT,0,0,0);
   ObjFont
   ObjCoordinates(t[0],sumL[0]/NUMBER_MA)
   ObjProperty(10,119,clrGold)
//--- max
   name="Lmax"+str;
   ObjectCreate(0,name,OBJ_TEXT,0,0,0);
   ObjFont
   ObjCoordinates(t[0],maxL[0])
   ObjProperty(t_max,158,clrGold)
//--- min
   name="Lmin"+str;
   ObjectCreate(0,name,OBJ_TEXT,0,0,0);
   ObjFont
   ObjCoordinates(t[0],minL[0])
   ObjProperty(t_min,158,clrGold)

Agora vamos ver como se parece quando representado graficamente:

Características do corte transversal

Fig. 8. Características do corte transversal: o máximo e o mínimo, assim como o centro de gravidade plotado para os picos e baixas separadamente

Precisamos apenas adicionar o último retoque encontrando e plotando os nós do ZigZag. Melhoramos o código adicionando o seguinte:

//--- ZigZag: advanced nodes
   if(Azz.zHL[0].type>0) // peak
     {
      ObjectDelete(0,"MIN");
      ObjectDelete(0,"MINfuture");
      name="MAX";
      ObjectCreate(0,name,OBJ_TREND,0,0,0);
      ObjZZ
      ObjectSetDouble(0,name,OBJPROP_PRICE,0,Azz.zHL[1].value);
      ObjectSetInteger(0,name,OBJPROP_TIME,0,Azz.zHL[1].time);
      ObjectSetInteger(0,name,OBJPROP_TIME,1,t[0]);
      double price=minH[0];
      ObjectSetDouble(0,name,OBJPROP_PRICE,1,price);
      if(Azz.zHL[0].value>minH[0])
        {
         price=sumH[0]/NUMBER_MA;
         ObjectSetDouble(0,name,OBJPROP_PRICE,1,price);
        }
      if(Azz.zHL[0].value>sumH[0]/NUMBER_MA)
        {
         price=maxH[0];
         ObjectSetDouble(0,name,OBJPROP_PRICE,1,price);
        }
      //--- into the future
      name="MAXfuture";
      ObjectCreate(0,name,OBJ_TREND,0,0,0);
      ObjZZ
      ObjectSetDouble(0,name,OBJPROP_PRICE,0,price);
      ObjectSetInteger(0,name,OBJPROP_TIME,0,t[0]);
      ObjectSetDouble(0,name,OBJPROP_PRICE,1,maxL[0]);
      ObjectSetInteger(0,name,OBJPROP_TIME,1,t[0]+NUMBER_MA*shift);
      if(price<maxL[0])
         ObjectSetDouble(0,name,OBJPROP_PRICE,1,sumL[0]/NUMBER_MA);
      if(price<sumL[0]/NUMBER_MA)
         ObjectSetDouble(0,name,OBJPROP_PRICE,1,minL[0]);
     }
   if(Azz.zHL[0].type<0) // trough
     {
      ObjectDelete(0,"MAX");
      ObjectDelete(0,"MAXfuture");
      name="MIN";
      ObjectCreate(0,name,OBJ_TREND,0,0,0);
      ObjZZ
      ObjectSetDouble(0,name,OBJPROP_PRICE,0,Azz.zHL[1].value);
      ObjectSetInteger(0,name,OBJPROP_TIME,0,Azz.zHL[1].time);
      ObjectSetInteger(0,name,OBJPROP_TIME,1,t[0]);
      double price=maxL[0];
      ObjectSetDouble(0,name,OBJPROP_PRICE,1,price);
      if(Azz.zHL[0].value<maxL[0])
        {
         price=sumL[0]/NUMBER_MA;
         ObjectSetDouble(0,name,OBJPROP_PRICE,1,price);
        }
      if(Azz.zHL[0].value<sumL[0]/NUMBER_MA)
        {
         price=minL[0];
         ObjectSetDouble(0,name,OBJPROP_PRICE,1,price);
        }
      //--- into the future
      name="MINfuture";
      ObjectCreate(0,name,OBJ_TREND,0,0,0);
      ObjZZ
      ObjectSetDouble(0,name,OBJPROP_PRICE,0,price);
      ObjectSetInteger(0,name,OBJPROP_TIME,0,t[0]);
      ObjectSetDouble(0,name,OBJPROP_PRICE,1,minH[0]);
      ObjectSetInteger(0,name,OBJPROP_TIME,1,t[0]+NUMBER_MA*shift);
      if(price>minH[0])
         ObjectSetDouble(0,name,OBJPROP_PRICE,1,sumH[0]/NUMBER_MA);
      if(price>sumH[0]/NUMBER_MA)
         ObjectSetDouble(0,name,OBJPROP_PRICE,1,maxH[0]);
     }

Então, temos o novo e avançado indicador ZigZag que prevê a posição de novos nós (Fig. 9). Os nós ficam localizados nos pontos transeccionais característicos: o máximo, o mínimo e o centro de gravidade. O título provisório do indicador é "dois cometas".

Deve-se notar que o tempo de conclusão do próximo nó, o qual está no futuro, permaneceu desconhecido. Basicamente, podemos prever somente uma coordenada do nó - o preço.

Nós previstos do ZigZag

Fig. 9. O indicador do ZigZag avançado prevê os nós: o atual e o seguinte

 

Análise dos resultados e recomendações para desenvolvedores

As observações do indicador mostraram que:

  1. Desvios das coordenadas dos nós do ZigZag oriundos do nós previstos estão na margem de tolerância. O vasto número de nós fica na sombra do corte transversal correspondente. Esta é certamente uma simples avaliação qualitativa. Resultados mais precisos serão contemplados em futuros artigos.
  2. Os cortes transversais das linhas dos envelopes demonstram o comportamento do mercado e a conjuntura de preço esperada! Preste atenção à cauda do cometa que é composta de pontos com o menor período de média (o menor em tamanho). Ela é conduzida na direção do preço: A cauda do cometa dobra-se na forma mais complexa e quanto mais é virada para a direção oposta, maior as chances de se ver a tendência mudar. Observe simplesmente o comportamento do indicador em diferentes intervalor de tempo com diferentes amplitudes. Isso é extremamente interessante!
  3. Os pontos característicos dos cortes transversais formam linhas que podem apresentar forte resistência ao movimento de preço. Portanto, eles podem ser considerados como apoio e linhas de resistência.
  4. Quando os pontos do centro de gravidade do corte transversal ficam a frente dele (como os picos na Fig. 9), este é um indicador da presença de uma tendência de crescimento.

Então, o que temos como resultado é um indicador muito interessante que pode ser experimentado em uma estratégia de negócios!

 

Conclusão