Что возвращают функции Lowest и Highest

 
Уважаемые разработчики Метатрейдера!.

Что возвращают функции Lowest и Highest?
Почему задаю такой вопрос? Описание этих функций путанное. Анализируя, почему ZigZag, поставляемый в комплекте с метатрейдером работает некорректно, столкнулся с тем, что вышеназванные функции непонятно что возвращают. Или, может быть, из-за путаного описания их неправильно применяют? На данной странице форума в ветке Торговая стратегия на база волновой теории Эллиота на странице 77 описал эту проблему. Пытаюсь понять, может быть, алгоритм ZigZag неверный. Но все упирается в работу этих функций.

Проблемы с данными функциями наблюдал и в других индикаторах. Но на данный момент - в ZigZag-е.

Пожалуйста, разъясните.
 
Они возвращают номер бара, который наиболее высокий и наиболее низкий на протяжении N баров от текущего в глубь истории. При этом, при равенстве двух значений (два бара являются экстремумами на этой выборке), всегда возращается номер того бара, который пришел раньше (является более старым).

Алгоритм Зигзага(идущего в МТ4 в стандартной поставке ) не учитывает ситуацию, когда один бар может являться и максимумом и минимумом одновременно (внешний бар).
 
Rosh, это понятно. Попробуй вставить в текст зигзага те строчки, что я привел в ветке по волновому анализу. И посмотри, что получается. А получается мусор. Из-за этого и возник вопрос.

С теорией все понятно до тех пор, пока она не начинает расходиться с практикой. Если возникают ошибки, то надо идти до конца. И выяснить, откуда ошибки лезут.
 
Rosh, это понятно. Попробуй вставить в текст зигзага те строчки, что я привел в ветке по волновому анализу. И посмотри, что получается. А получается мусор. Из-за этого и возник вопрос.


Я глянул ту страницу на ониксе и открыл стандартный Зигзаг чтобы сравнить. Коды отличаются, чтобы разобраться - нужно найти Ваш вариант Зигзага, досконально его разобрать и только потом можно что-то сказать. Поэтому ответить ничего не могу.

А так да - есть разногласия в записи значений в том коде , что приведен на вашей странице, но может так и надо, трудно сказать. Я ингода делаю такие индикаторы с ползущими значениями, получается что-то вроде канала, но зато на истории не врет.
 
Rosh, вот код зигзага с сайта codebase.mql.com

//+------------------------------------------------------------------+
//| Custom Moving Average.mq4 |
//| Copyright © 2005, MetaQuotes Software Corp. |
//| https://www.metaquotes.net/ |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2005, MetaQuotes Software Corp."
#property link "https://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 ExtMapBuffer2[];

//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
IndicatorBuffers(2);
//---- drawing settings
SetIndexStyle(0,DRAW_SECTION);
//---- indicator buffers mapping
SetIndexBuffer(0,ExtMapBuffer);
SetIndexBuffer(1,ExtMapBuffer2);
SetIndexEmptyValue(0,0.0);
//---- indicator short name
IndicatorShortName("ZigZag("+ExtDepth+","+ExtDeviation+","+ExtBackstep+")");
//---- initialization done
return(0);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
int start()
{
int shift, back,lasthighpos,lastlowpos;
double val,res;
double 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;
else
{
lastlow=val;
if((Low[shift]-val)>(ExtDeviation*Point)) val=0.0;
else
{
for(back=1; back<=ExtBackstep; back++)
{
res=ExtMapBuffer[shift+back];
if((res!=0)&&(res>val)) ExtMapBuffer[shift+back]=0.0;
}
}
}
****** ExtMapBuffer[shift]=val;
//--- high
val=High[Highest(NULL,0,MODE_HIGH,ExtDepth,shift)];
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=ExtMapBuffer2[shift+back];
if((res!=0)&&(res<val)) ExtMapBuffer2[shift+back]=0.0;
}
}
}
***** ExtMapBuffer2[shift]=val;
}


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

Это та часть, где и сидит ошибка.Звездочками обозначил места, которые я привел на 77 странице ветки по волновому анализу. Чем этот код отличается, от того , что я привел? Это стандартный код.

Теперь привожу твои слова из втоорого поста этой ветки

Rosh 18.10.06 10:14

Они возвращают номер бара, который наиболее высокий и наиболее низкий на протяжении N баров от текущего в глубь истории. При этом, при равенстве двух значений (два бара являются экстремумами на этой выборке), всегда возращается номер того бара, который пришел раньше (является более старым).

Алгоритм Зигзага(идущего в МТ4 в стандартной поставке ) не учитывает ситуацию, когда один бар может являться и максимумом и минимумом одновременно (внешний бар).
======================
В коде есть строчка: val=High[Highest(NULL,0,MODE_HIGH,ExtDepth,shift)];
В квадратных скобках находится номер бара... ну в твоем ответе сказано что это за номер бара

Далее в строчке: ExtMapBuffer[shift]=val; - что мы имеем? Дальше надо объяснять?

Во первых, индекс буфера индикаторного должен быть равен индексу бара, с которого мы взяли значение val. Иначе будет несоответствие. Что мы собственно и имеем, когда видим что зигзаг имеет перелом в воздухе.

Rosh, не уходи от ответа. Твое детище зигзаг. Давай разберемся. В коде много ошибок. Если ты внимательно разберешь, что я пишу, то увидишь явные ошибки.

Но и это не главное. Если б дело было только в этих ошибках, то я бы не задавал вопрос, которым озаглавлена ветка.
 
Еще раз про функции Lowest и Highest.

В предыдущем посте писал об ошибке в коде зигзага.

Главная ошибка.

На участке размером ExtDepth баров ищется бар с наибольшим максимумо или наименьшим минимумом. Поиск ведется с бара SHIFT. Рош дал такое определение функций: возвращается номер бара наиболее высокий и наиболее низкий на протяжении N баров от текущего в глубь истории. Но нет определения, что такое текущий бар. Текущий бар - это нулевой бар или бар с номером shift. Если судить по приведенному коду зигзага, то под текущим баром надо понимать бар с номером shift.

Допустим, что мы нашли номер бара на участке ExtDepth баров, считая от бара с номером shift. И этот бар будет не обязательно иметь номер shift. Но значение экстремума найденного бара, отличающегося от бара с номером shift, мы помещаем в индикаторный буфер под номером shift: ExtMapBuffer[shift]=val. Отсюда получаются у зигзага переломы, висящие в воздухе. Все, кто пытался работать с зигзагом из МТ, это видели.

Это главная ошибка. Но эту ошибку исправить просто. И поднимать вопрос не стоило.

Когда эту ошибку начинаешь убирать, то возникает вопрос, а на баре с каким номером функции Lowest и Highest нашли искомый экстремум? Никакая логика здесь не помогает. Как ни пытался вычислить номер этого бара, ничего не получилось.

Поэтому и вопрос был направлен к разработчикам.

Но я обрадовался, что на вопрос стал отвечать Rosh. Это после его правки долгое время мы пользуемся зигзагом, включенном в поставку MT.

Уважаемые разработчики, обратите, пожалуйста внимание на поставленные вопросы. Вопросы серьезные. Очень много индикаторов использует зигзаг, включенный в поставку МТ. Не сосчитаешь количество нареканий на работу зигзага.
Я привел описание ошибок. По хорошему, ошибки надо исправлять. Игнорирование исправления ошибок наносит урон репутации компании. А это не есть хорошо. Никому этого не нужно.
 
...возникает вопрос, а на баре с каким номером функции Lowest и Highest нашли искомый экстремум? Никакая логика здесь не помогает. Как ни пытался вычислить номер этого бара, ничего не получилось.
По идее, индекс бара = Highest(NULL,0,MODE_HIGH,ExtDepth,shift)

Т.е. должно быть ExtMapBuffer2[Highest(NULL,0,MODE_HIGH,ExtDepth,shift)]=val;
 
nen, cейчас глянул в стандартный алгоритм Зиг-Зага - там другой алгоритм, отличный от того, что Вы привели:

//+------------------------------------------------------------------+
//|                                                       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;
        }
     }
  }
//+------------------------------------------------------------------+



Вроде все правильно здесь - и индекс сохраняется и запиыівается значение в нужный элемент массива. Давайте отталкиваться от этого алгоритма.

 
nen, извините, а не проще написать коротенький код, находящий эти самые Lowest и Highest? Просто я никогда этими функциями не пользовался, именно потому, что нужные мне данные по экстремумам получал простым коротким кодом, ибо он наверняка будет работать быстрее стандартных функций. Мне кажется смысл их использовать появляется только при необходимости получить данные с другого таймфрейма.
 
komposter, все правильно. Посмотрите потом куда это записывается. В индикаторный буфер с каким индексом.
Vladislav, я код привел с сайта codebase.mql.com и у меня точно такой же. Попробую Ваш код поставить. Посмотрю, что получится.
Candid, согласен, что возможно это будет проще. Но мне эти функции нужны будут и для работа с другим таймфреймом.
Причина обращения: