Проблема с заполнением массива.

 

Похожей ситуации нигде не нашёл, если кто находил кидайте ссылку!

Собственно сам кусок кода:

//фильруем хай (для определения ключивых точек)
         for(int i=0; ih_key<=TrendLinesOnGraph*4; i++)
           {
            //Если новый лоу ниже старого
            if(iCustom(Symbol(),0,"ZigZag",Depth,Deviation,Backstep,0,Low_[i+1])>iCustom(Symbol(),0,"ZigZag",Depth,Deviation,Backstep,0,Low_[i]))
              {
               //Ищем его хай
               for(int index=Low_[i]+1; key==false; index++)
                 {
                  if(iCustom(Symbol(),0,"ZigZag",Depth,Deviation,Backstep,High_index,index)>0)
                    {
                     High_key[ih_key]=index;
                     ih_key++;//после того как нашли ключивой хай, заполняем следующий индекс массива
                     key=true;
                    }
                 }
               key=false;
              }
           }
         ih_key=0;
         

Во внутреннем цикле массив заполняется правильно, через принт проверял(данные не повторяются).

но после этого куска кода проверяю массив и принтую результаты, данные начинают повторятся раз по 10-15 т.е данные записались не корректно, кто сталкивался, есть какие мысли?

 

Вопросы по старому терминалу обсуждаются в одном специальном разделе: MQL4 и MetaTrader 4

Вашу тему перенесу.

 
Maksim Slovakov:

Похожей ситуации нигде не нашёл, если кто находил кидайте ссылку!

Собственно сам кусок кода:

Во внутреннем цикле массив заполняется правильно, через принт проверял(данные не повторяются).

но после этого куска кода проверяю массив и принтую результаты, данные начинают повторятся раз по 10-15 т.е данные записались не корректно, кто сталкивался, есть какие мысли?

Первое, что бросается в глаза:

 for(int i=0; ih_key<=TrendLinesOnGraph*4; i++)

Здесь нет контроля выхода переменной i за пределы истории. За то есть контроль значения переменной ih_key. Но как она объявлена и какое у нее значение до входа цикл, опять же, непонятно. То есть проверить такой код не представляется возможным. Сделайте этот участок кода самодостаточным, чтобы его можно было запустить другому человеку.

 
Ihor Herasko:

Первое, что бросается в глаза:

Здесь нет контроля выхода переменной i за пределы истории. За то есть контроль значения переменной ih_key. Но как она объявлена и какое у нее значение до входа цикл, опять же, непонятно. То есть проверить такой код не представляется возможным. Сделайте этот участок кода самодостаточным, чтобы его можно было запустить другому человеку.

Проблему локализовал, при заполнении массива происходит какая-то ерунда, прикладываю скрин, код и файл.

//+------------------------------------------------------------------+
//|                                                         тест.mq4 |
//|                                                  Словаков Максим |
//|                                  https://vk.com/s4astliv4ik_1990 |
//+------------------------------------------------------------------+
#property copyright "Словаков Максим"
#property link      "https://vk.com/s4astliv4ik_1990"
#property version   "1.00"
#property strict
#property indicator_chart_window
#property indicator_buffers 1 //количество буферов

//--- Входные параметры
input string  s1="ЗигЗаг";//Настройки
input int     Depth = 12;
input int     Deviation = 5;
input int     Backstep = 3;
input string  s3="Трендовых линий сохранять на графике";//==>
input int     TrendLinesOnGraph=5;

int Bar;
int High_index=1;
int Low_index=2;
int il;
int ih;
int il_key;
int ih_key;
bool key=false;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping

//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
//---
   if(Bar==0 || Bar<iBars(Symbol(),0))
     {
      Bar=iBars(Symbol(),0);
      int Low_[];
      ArrayResize(Low_,Bar);
      int Low_key[];
      ArrayResize(Low_key,Bar);
      int High_[];
      ArrayResize(High_,Bar);
      int High_key[];
      ArrayResize(High_key,Bar);

      for(int i=1; i<Bar;  i++)
        {
         if(iCustom(Symbol(),0,"ZigZag",Depth,Deviation,Backstep,Low_index,i)>0)
           {
            Low_[il]=i;//Записываем все минимумы в массив
            il++;
             
           }
         if(iCustom(Symbol(),0,"ZigZag",Depth,Deviation,Backstep,High_index,i)>0)
           {
            High_[ih]=i;// Записываем все максимумы в массив
            ih++;
            
           }
        }
      il=0;
      ih=0;
      //фильруем хай (для определения ключивых точек)
      for(int i=0; il_key<=TrendLinesOnGraph*6; i++)
        {
         int Ii=i+1;
         //Если новый хай выше старого
         if(iCustom(Symbol(),0,"ZigZag",Depth,Deviation,Backstep,High_index,High_[Ii])<iCustom(Symbol(),0,"ZigZag",Depth,Deviation,Backstep,High_index,High_[i]))
           {
            //Ищем его лоу
            int index=High_[i];
            while(key==false)
              {
               if(iCustom(Symbol(),0,"ZigZag",Depth,Deviation,Backstep,Low_index,index)>0)
                 {
                 Print("Тут во время присвоения: ",il_key," = ",index);
                  Low_key[il_key]=index;
                  il_key++;//после того как нашли ключивой лоу, заполняем следующий индекс массива
                  key=true;
                 }
               Sleep(5000);
               index++;
              }
            key=false;
           }
        }
      //фильруем лоу (для определения ключивых точек)
      for(int i=0; ih_key<=TrendLinesOnGraph*6; i++)
        {
         int Ii=i+1;
         //Если новый лоу ниже старого
         if(iCustom(Symbol(),0,"ZigZag",Depth,Deviation,Backstep,0,Low_[Ii])>iCustom(Symbol(),0,"ZigZag",Depth,Deviation,Backstep,0,Low_[i]))
           {
            //Ищем его хай
            int index=Low_[i];
            while(key==false)
              {
               if(iCustom(Symbol(),0,"ZigZag",Depth,Deviation,Backstep,High_index,index)>0)
                 {
                  
                  High_key[ih_key]=index;
                  ih_key++;//после того как нашли ключивой хай, заполняем следующий индекс массива
                  key=true;
                 }
               Sleep(5000);
               index++;
              }
            key=false;
           }
        }
      for(int i = 0; i<20; i++)
        {
         Print("Тут после: ",i,"=",Low_key[i]);
        }
      Sleep(5000);
     }
   ih=0;
   il=0;
   ih_key=0;
   il_key=0;

  
//--- return value of prev_calculated for next call
return(rates_total);
  }
//+------------------------------------------------------------------+
Файлы:
mb8k.mq4  10 kb
 

Как выяснилось проблема c переменной "index" конкретно с записью Low_key[], по каким-то причинам она не меняется, хотя в конце цикла стоит index++;

Создал файл 1.txt и записал в него значения index  на каждой итерации, значения index периодически не менялись и записывали одинаковые значения.

 //фильруем хай (для определения ключивых точек)
      for(int i=0; il_key<=TrendLinesOnGraph*6; i++)
        {
         int Ii=i+1;
         //Если новый хай выше старого
         if(iCustom(Symbol(),0,"ZigZag",Depth,Deviation,Backstep,High_index,High_[Ii])<iCustom(Symbol(),0,"ZigZag",Depth,Deviation,Backstep,High_index,High_[i]))
           {
            Print(i);
            //Ищем его лоу
            int index=High_[i];
            while(key==false)
              {
               if(iCustom(Symbol(),0,"ZigZag",Depth,Deviation,Backstep,Low_index,index)>0)
                 {
                  //Print("Тут во время присвоения: ",il_key," = ",index);
                  Low_key[il_key]=index;
                  
                  il_key++;//после того как нашли ключивой лоу, заполняем следующий индекс массива
                  key=true;
                  //--- правильный способ работы в "файловой песочнице"
                  ResetLastError();
                  int filehandle=FileOpen("1.txt",FILE_WRITE|FILE_READ|FILE_ANSI,"/t");
                  if(filehandle!=INVALID_HANDLE)
                    {
                     FileSeek(filehandle, 1, SEEK_END);
                     FileWrite(filehandle," ",index);
                     FileClose(filehandle);
                     Print("FileOpen OK");
                    }
                  else
                     Print("Операция FileOpen неудачна, ошибка ",GetLastError());

                 }
               Sleep(5000);
               index++;

              }
            key=false;
           }
        }
 
Maksim Slovakov:

Проблему локализовал, при заполнении массива происходит какая-то ерунда, прикладываю скрин, код и файл.

Первый же цикл. Что и куда записывается? Ведь переменные il и ih содержат мусор, т. к. не проинициализированы.

Также наличие самих массивов Low_ и High_ не является оправданным, т. к. они дублируют массивы самого ZigZag (буферы с индексами 1 и 2). Таким образом, первый цикл - пустая трата времени и ресурсов.

Во втором и третьем цикле опять та же самая проблема, о которой уже говорилось выше: цикл по i, но выход из него по совершенно другим условиям. Это грубая ошибка, которая приведет к crush, обязательно проверяйте значение переменной цикла. При этом не запрещается проверять другие условия. Ну и, снова-таки, переменные il_key и ih_key не инициализированы.

 
Maksim Slovakov:

Как выяснилось проблема c переменной "index" конкретно с записью Low_key[], по каким-то причинам она не меняется, хотя в конце цикла стоит index++;

Создал файл 1.txt и записал в него значения index  на каждой итерации, значения index периодически не менялись и записывали одинаковые значения.

Значение этой переменной лишь отражает тот бардак, который творится в массивах Low_, Low_key, High_ и High_key. Ведь они заполнены случайным образом.

 
Ihor Herasko:

Первый же цикл. Что и куда записывается? Ведь переменные il и ih содержат мусор, т. к. не проинициализированы.

Также наличие самих массивов Low_ и High_ не является оправданным, т. к. они дублируют массивы самого ZigZag (буферы с индексами 1 и 2). Таким образом, первый цикл - пустая трата времени и ресурсов.

Во втором и третьем цикле опять та же самая проблема, о которой уже говорилось выше: цикл по i, но выход из него по совершенно другим условиям. Это грубая ошибка, которая приведет к crush, обязательно проверяйте значение переменной цикла. При этом не запрещается проверять другие условия. Ну и, снова-таки, переменные il_key и ih_key не инициализированы.

Low_ и High_ не дублируют ZigZag, Так-как в буфере ZigZag значения записаны только на свечах с экстремумами, все остальные значения в буфере нулевые, цикл фильтрует все нулевые значения  буфера зиг зага и записывает в массивы номера баров на которых были экстремумы. il и ih объявлены, по выходу из своего цикла сбрасываются(Они нужны для порядка записи в массивы  Low_ и High_, переменная i,это номер бара на котором не нулевое значение  ZigZag. Логика следующая, перебираем номера баров, находим не нулевое значение  ZigZag на каком то баре и номер этого бара записываем в масив под индексом "0", далее находим ещё один номер бара(допустим он будет 150ым) и записываем его в массив под индексом 1 и так далее, пока не заполним массив нужным количеством номеров баров(это номера баров на которых имеются экстремумы ZigZag ). Поскольку в  ZigZag нулевой буфер, это все экстремумы подряд, 1 буфер это хаи а 2 буфер лои, мы имеем возможность записать всё отдельно и с этим работать.

//---- indicator buffers ZigZag

   SetIndexBuffer(0,ExtZigzagBuffer);

   SetIndexBuffer(1,ExtHighBuffer);

   SetIndexBuffer(2,ExtLowBuffer);

 
Далее к примеру найдя нужный хай , мы берём номер бара на котором он расположен и начинаем от него перебирать бары ищя его лоу(т.е точку от которой цена сделала этот самый хай. И этот самый лоу уже будет Low_key(ключевой лоу для расчётов нашего индикатора)
 
Maksim Slovakov:

Low_ и High_ не дублируют ZigZag, Так-как в буфере ZigZag значения записаны только на свечах с экстремумами, все остальные значения в буфере нулевые, цикл фильтрует все нулевые значения  буфера зиг зага и записывает в массивы номера баров на которых были экстремумы. il и ih объявлены, по выходу из своего цикла сбрасываются(Они нужны для порядка записи в массивы  Low_ и High_, переменная i,это номер бара на котором не нулевое значение  ZigZag. Логика следующая, перебираем номера баров, находим не нулевое значение  ZigZag на каком то баре и номер этого бара записываем в масив под индексом "0", далее находим ещё один номер бара(допустим он будет 150ым) и записываем его в массив под индексом 1 и так далее, пока не заполним массив нужным количеством номеров баров(это номера баров на которых имеются экстремумы ZigZag ). Поскольку в  ZigZag нулевой буфер, это все экстремумы подряд, 1 буфер это хаи а 2 буфер лои, мы имеем возможность записать всё отдельно и с этим работать.

Зачем в таком случае они имеют размер, равный количеству баров графика? Добавляйте размер динамически и не нужно этого делать на каждом тике.

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

Ну и как-то Вы совсем не реагируете на ответы, данные на главный вопрос ветки. Решение проблемы уже два раза озвучено.

 

Проблема решена, дело было в особенностях самого индикатора, в нулевом буфере ZigZag хранятся те экстремумы, которые мы видим на графике, в 1 и 2 буфере хранятся хаи и лои, которые были бы на графике, если бы индикатор не перерисовывался по ходу движения цены. Таким образом на графике мы видим одно движение с одним экстремумом, который перерисовывался по ходу движения цены 3 раза, соответственно все эти три раза новый хай записывался в 1ый буфер (SetIndexBuffer(1,ExtHighBuffer)) самого индикатора ZigZag, а окончательный хай записался в нулевой буфер.Таже петруха и с лоями. Проблема решается дополнительным условием на соответствие текущего High или Low окончательному экстремуму.

for(int i=1; i<Bar;  i++)
        {
         if(iCustom(Symbol(),0,"ZigZag",Depth,Deviation,Backstep,Low_index,i)>0 && iCustom(Symbol(),0,"ZigZag",Depth,Deviation,Backstep,0,i)>0)
           {
           
            Low_[il]=i;//Записываем все минимумы в массив
            il++;
           }
         if(iCustom(Symbol(),0,"ZigZag",Depth,Deviation,Backstep,High_index,i)>0 && iCustom(Symbol(),0,"ZigZag",Depth,Deviation,Backstep,0,i)>0)
           {
            High_[ih]=i;// Записываем все максимумы в массив
            ih++;
           }
        }
      il=0;
      ih=0;
Причина обращения: