O que as funções mais baixas e mais altas retornam

 
Caros desenvolvedores Metatrader!

O que as funções mais baixas e mais altas retornam?
Por que eu faço tal pergunta? A descrição dessas funções é confusa. Ao analisar porque o ZigZag incluído no MetaTrader não funciona corretamente, me deparei com o fato de que não está claro o que as funções acima retornam. Ou talvez por causa da descrição confusa que eles estão sendo mal aplicados? Descrevi este problema na página 77 deste fórum na seção "Estratégia comercial baseada na teoria das ondas de Elliot". Estou tentando entender, talvez o algoritmo ZigZag esteja errado. Mas tudo depende de como essas funções funcionam.

Observei também problemas com estas funções em outros indicadores. Mas, no momento, está em ZigZag.

Por favor, esclareça.
 
Eles devolvem o número da barra que é a mais alta e a mais baixa sobre N barras, desde a barra atual até o final da história. Neste caso, se dois valores forem iguais (duas barras são extremos nesta amostra), o número da barra que veio antes (é mais antigo) é sempre devolvido.

O algoritmo Zigzag (incluído no MT4 como padrão) não leva em conta a situação quando uma barra pode ser ao mesmo tempo um máximo e um mínimo (uma barra externa).
 
Rosh, isso é compreensível. Tente inserir no texto em ziguezague aquelas linhas que eu dei na linha de análise de ondas. E veja o que você recebe. E você recebe lixo. Foi por isso que surgiu a pergunta.

Tudo fica claro com a teoria até que ela começa a divergir da prática. Se ocorrerem erros, você deve ir até o fim. E descubra de onde os erros estão vindo.
 
Rosh, isso é compreensível. Tente inserir no texto em ziguezague aquelas linhas que eu dei no fio de análise de ondas. E veja o que você recebe. E você recebe lixo. É por isso que eu lhe fiz esta pergunta. <br / translate="no">


Eu olhei aquela página no onyx e abri o Zigzag padrão para comparar. Os códigos são diferentes, você precisa encontrar sua variante de Zigzag, desmontá-la completamente e só então você pode dizer algo. É por isso que eu não posso responder.

Mas sim, há algumas diferenças no registro de valores no código, que é mostrado em sua página, mas talvez deva ser assim, é difícil dizer. Tenho feito tais indicadores com valores de rastejamento, parece um canal, mas pelo menos não se baseia na história.
 
Rosh, aqui está o código em ziguezague do codebase.mql.com

//+------------------------------------------------------------------+
//| Média móvel personalizada.mq4 |
//| Copyright © 2005, MetaQuotes Software Corp.
//| https://www.metaquotes.net/ |
//+------------------------------------------------------------------+
#direitos autorais "Copyright © 2005, MetaQuotes Software Corp."
#link da propriedade "https://www.metaquotes.net/

#janela_do_cartão_indicador de propriedade
#property indicator_buffers 1
#indicador de propriedade_cores1 Vermelho
//---- parâmetros indicadores
intDepth=12;
ExtDeviação Externa Interna=5;
ExtBackstep ExtBackstep=3;
//---- buffers indicadores
duplo ExtMapBuffer[];
duplo ExtMapBuffer2[];

//+------------------------------------------------------------------+
//| Função de inicialização do indicador personalizado |
//+------------------------------------------------------------------+
int init()
{
IndicatorBuffers(2);
//---- definições de desenho
SetIndexStyle(0,DRAW_SECTION);
//---- mapeamento de buffers indicadores
SetIndexBuffer(0,ExtMapBuffer);
SetIndexBuffer(1,ExtMapBuffer2);
SetIndexEmptyValue(0,0,0.0);
//---- indicador nome curto
IndicatorShortName("ZigZag("+ExtDepth+", "+ExtDeviation+", "+ExtBackstep+")"));
//---- inicialização feita
retorno(0);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
int start()
{
int shift,back,lasthighpos,lastlowpos;
duplo val,res;
duplo curlow,curhigh,lasthigh,lastlow;

for(shift=Bars-ExtDepth; shift>=0; shift--)
{
val=Low[Lowest(NULL,0,MODE_LOW,ExtDepth,shift)];
if(val===lastlow) val=0,0;
senão
{
lastlow=val;
if((Low[shift]-val)>(ExtDeviation*Point)) val=0,0;
senão
{
for(back=1; back<=ExtBackstep; back++)
{
res=ExtMapBuffer[shift+back];
if((res!=0)&&(res>val)) ExtMapBuffer[shift+back]=0,0;
}
}
}
****** ExtMapBuffer[shift]=val;
//--- alto
val=Alto[Alto[NULL,0,MODE_HIGH,ExtDepth,shift)];
if(val===lasthigh) val=0,0;
senão
{
lasthigh=val;
if((val-High[shift])>(ExtDeviation*Point)) val=0,0;
senão
{
for(back=1; back<=ExtBackstep; back++)
{
res=ExtMapBuffer2[shift+back];
if((res!=0)&&(res<val)) ExtMapBuffer2[shift+back]=0,0;
}
}
}
***** ExtMapBuffer2[shift]=val;
}


============================

Os asteriscos indicam lugares que citei na página 77 de minha filial na análise de ondas. Em que este código é diferente daquele que citei? Este é um código padrão.

Agora eu cito suas palavras do segundo post deste tópico

Rosh 18.10.06 10:14

Ele retorna o número da barra, que é a mais alta e a mais baixa dentro das barras N da profundidade atual na história. Neste caso, se dois valores forem iguais (duas barras são extremas naquela amostra), eles sempre retornam o número da barra que veio primeiro (é a mais antiga).

O algoritmo Zigzag (incluído no MT4 como padrão) não leva em conta a situação quando uma barra pode ser um máximo e um mínimo ao mesmo tempo (barra externa).
======================
Há uma linha no código: val=Highest[Highest(NULL,0,MODE_HIGH,ExtDepth,shift)];
Os colchetes contêm o número de barras... bem, sua resposta diz qual é este número de barra

Então na linha: ExtMapBuffer[shift]=val; - o que nós temos? É preciso explicar melhor?

Primeiro, o índice do tampão indicador deve ser igual ao índice da barra, da qual tomamos o valor de val. Caso contrário, haverá uma discrepância. O que realmente temos, quando vemos que o ziguezague tem uma pausa no ar.

Rosh, não se desvie do assunto. Sua criação é um ziguezague. Vamos ao fundo da questão. Há muitos erros no código. Se você analisar cuidadosamente o que eu escrevo, você verá erros óbvios.

Mas isso também não é o principal. Se fosse apenas sobre estes erros, eu não teria feito a pergunta, que é o título deste tópico.
 
Novamente sobre as funções mais baixas e mais altas.

No post anterior, escrevi sobre um erro no código ziguezague.

O erro principal.

Em um trecho de barras ExtDepth a barra com a mais alta alta ou a mais baixa é procurada. A busca é realizada a partir da barra SHIFT. Roche deu a seguinte definição de função: retorna o número da barra mais alta e mais baixa dentro de N barras da barra atual na seção da história. Mas não há uma definição do que é a barra atual. A barra atual é uma barra zero ou uma barra com número de turno. A julgar pelo código dado do ziguezague, a barra atual deve ser entendida como uma barra com número de turno.

Suponha que tenhamos encontrado o número da barra na seção ExtDepth das barras, contando a partir da barra com o número de turno. E esse bar não teria necessariamente um número de turno. Mas o valor do extremo da barra que encontramos que difere da barra com o número do turno é colocado no buffer indicador com o número do turno: ExtMapBuffer[shift]=val. Assim, temos pausas no ziguezague penduradas no ar. Todos que tentaram trabalhar com ziguezague da MT já o viram.

Isto é um grande erro. Mas este erro é fácil de corrigir. E não valeu a pena falar sobre isso.

Quando se começa a limpar este erro, se pergunta: na barra com que número as funções mais baixas e mais altas encontraram o extremo que estamos procurando? Nenhuma lógica ajuda aqui. Por mais que eu tentasse descobrir o número desta barra, ela não funcionava.

É por isso que a pergunta foi dirigida aos desenvolvedores.

Mas fiquei feliz que a pergunta tenha sido respondida por Rosh. É depois de suas edições que temos usado o ziguezague incluído com a MT por um longo tempo.

Caros desenvolvedores, por favor, prestem atenção às perguntas feitas. As questões são sérias. Muitos indicadores utilizam o ziguezague que está incluído no MT. Não posso contar o número de reclamações sobre o trabalho do ziguezague.
Eu dei uma descrição dos erros. Em boa medida, os erros devem ser corrigidos. Ignorar a correção de erros prejudica a reputação da empresa. E isso não é bom. Ninguém quer isso.
 
...surge a pergunta, em que barra as funções mais baixas e mais altas encontraram o extremo que estamos procurando? Nenhuma lógica ajuda aqui. Por mais que eu tentasse calcular o número da barra, ela não funcionava.
Em teoria, índice da barra = mais alto(NULL,0,MODE_HIGH,ExtDepth,shift)

Ou seja, deve ser ExtMapBuffer2[Highest(NULL,0,MODE_HIGH,ExtDepth,shift)]=val;
 
nen, agora eu pesquisei o algoritmo padrão Zig-Zag - há outro algoritmo, diferente do que você deu:

//+------------------------------------------------------------------+
//|                                                       ZigZag.mq4 |
//|                      Copyright © 2005, MetaQuotes Software Corp. |
//|                                       http://www.metaquotes.net/ |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2005, MetaQuotes Software Corp."
#property link      "http://www.metaquotes.net/"

#property indicator_chart_window
#property indicator_buffers 1
#property indicator_color1 Red
//---- indicator parameters
extern int ExtDepth=12;
extern int ExtDeviation=5;
extern int ExtBackstep=3;
//---- indicator buffers
double ExtMapBuffer[];
double ExtLowBuffer[];
double ExtHighBuffer[];

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
  {
   IndicatorBuffers(3);
//---- drawing settings
   SetIndexStyle(0,DRAW_SECTION);
//---- indicator buffers mapping
   SetIndexBuffer(0,ExtMapBuffer);
   SetIndexBuffer(1,ExtLowBuffer);
   SetIndexBuffer(2,ExtHighBuffer);
   SetIndexEmptyValue(0,0.0);
//---- indicator short name
   IndicatorShortName("ZigZag("+ExtDepth+","+ExtDeviation+","+ExtBackstep+")");
//---- initialization done
   return(0);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int start()
  {
   int    shift, back,lasthighpos,lastlowpos,index;
   double val,res;
   double curlow,curhigh,lasthigh,lastlow;
//----
   for(shift=Bars-ExtDepth; shift>=0; shift--)
     {
      index=Lowest(NULL,0,MODE_LOW,ExtDepth,shift);
      val=Low[index];
      if(val==lastlow) val=0.0;
      else 
        { 
         lastlow=val; 
         if((Low[shift]-val)>(ExtDeviation*Point)) val=0.0;
         else
           {
            for(back=1; back<=ExtBackstep; back++)
              {
               res=ExtLowBuffer[shift+back];
               if((res!=0)&&(res>val)) ExtLowBuffer[shift+back]=0.0; 
              }
           }
        } 
      ExtLowBuffer[shift]=0.0;
      if(val!=0.0) ExtLowBuffer[index]=val;
      //--- high
      index=Highest(NULL,0,MODE_HIGH,ExtDepth,shift);
      val=High[index];
      if(val==lasthigh) val=0.0;
      else 
        {
         lasthigh=val;
         if((val-High[shift])>(ExtDeviation*Point)) val=0.0;
         else
           {
            for(back=1; back<=ExtBackstep; back++)
              {
               res=ExtHighBuffer[shift+back];
               if((res!=0)&&(res<val)) ExtHighBuffer[shift+back]=0.0; 
              } 
           }
        }
      ExtHighBuffer[shift]=0.0;
      if(val!=0.0) ExtHighBuffer[index]=val;
     }
//---- final cutting 
   lasthigh=-1; lasthighpos=-1;
   lastlow=-1;  lastlowpos=-1;

   for(shift=Bars-ExtDepth; shift>=0; shift--)
     {
      curlow=ExtLowBuffer[shift];
      curhigh=ExtHighBuffer[shift];
      if(curlow==0 && curhigh==0) continue;
      //---
      if(curhigh!=0)
        {
         if(lasthigh>0) 
           {
            if(lasthigh<curhigh) ExtHighBuffer[lasthighpos]=0;
            else ExtHighBuffer[shift]=0;
           }
         //---
         if(lasthigh<curhigh || lasthigh<0)
           {
            lasthigh=curhigh;
            lasthighpos=shift;
           }
         lastlow=-1;
        }
      //----
      if(curlow!=0)
        {
         if(lastlow>0)
           {
            if(lastlow>curlow) ExtLowBuffer[lastlowpos]=0;
            else ExtLowBuffer[shift]=0;
           }
         //---
         if((curlow<lastlow)||(lastlow<0))
           {
            lastlow=curlow;
            lastlowpos=shift;
           } 
         lasthigh=-1;
        }
     }
//---- merge 2 buffers
   lasthighpos=-1;
   lastlowpos=-1;
   for(shift=Bars-1; shift>=0; shift--)
     {
      if(shift>=Bars-ExtDepth) ExtMapBuffer[shift]=0.0;
      else
        {
         curlow=ExtLowBuffer[shift];
         curhigh=ExtHighBuffer[shift];
         //----
         res=0;
         if(curlow!=0)
           {
            if(lastlowpos==-1)
              {
               res=curlow;
               lastlowpos=shift;
              }
            else
              {
               if(lasthighpos!=-1 && lastlowpos>lasthighpos)
                 {
                  res=curlow;
                  lastlowpos=shift;
                 }
              }
           }
         if(curhigh!=0)
           {
            if(lasthighpos==-1)
              {
               res=curhigh;
               lasthighpos=shift;
              }
            else
              {
               if(lastlowpos!=-1 && lasthighpos>lastlowpos)
                 {
                  res=curhigh;
                  lasthighpos=shift;
                 }
              }
           }
         //----
         ExtMapBuffer[shift]=res;
        }
     }
  }
//+------------------------------------------------------------------+



Tudo parece estar correto aqui - tanto o índice é salvo quanto o valor é escrito no elemento de matriz desejado. Comecemos a partir deste algoritmo.

 
nen, desculpe-me, mas não seria mais fácil escrever um código curto que encontre os mais baixos e os mais altos? Eu simplesmente nunca usei estas funções, precisamente porque obtenho os dados que preciso para extrema por um simples código curto, pois certamente funcionará mais rápido do que as funções padrão. Parece-me que fazem sentido usá-los apenas quando é necessário obter dados de outro período de tempo.
 
komposter, é isso mesmo. Em seguida, veja para onde está escrito. No buffer de indicadores com que índice.
Vladislav, o código é de codebase.mql.com e é exatamente o mesmo. Vou tentar colocar seu código. Vou ver o que pode acontecer.
Candidato, eu concordo que pode ser mais simples. Mas vou precisar destas funções para trabalhar com outro cronograma.