Некорректно обновляются крайние значения пользовательского индикатора

 

Здравствуйте,

Помогите, пожалуйста, разобраться в следующем вопросе.

Экспериментирую с пользовательскими индикаторами. Заметил схожую для всех моих индикаторов проблему: после корректной первоначальной прорисовки графика, в дальнейшем, по мере поступления новых цен, индикатор или просто не перерисовывается, "замерев" на уровне тех значений, которые были в момент добавления его на график, либо и вовсе работает некорректно...


Чтобы не быть голословным, ниже привожу примеры. На рис. 1 показаны 2 индикатора (в отдельных окнах). Из рисунка видно, что для первого индикатора не прорисовались 2 последних значения, для второго они прорисовались, но равны нулю, что неверно.


Рис. 1


Если я удаляю эти индикаторы и вставляю их заново, то получаем корректные графики (см. рис. 2). График первого индикатора теперь включает в себя все необходимые значения, график второго индикатора не содержит ошибочных нулей:



Рис. 2


В чем может быть проблема?

Привожу код второго индикатора:


#property indicator_separate_window
#property indicator_color1 DodgerBlue
#property indicator_buffers 1
#property indicator_minimum 0
 
//---- buffers
double FR[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
  {
   IndicatorBuffers(1);
 
   //---- drawing settings
   SetIndexStyle(0,DRAW_LINE);
   IndicatorDigits(Digits+1);
   SetIndexDrawBegin(0, 50);
   SetIndexBuffer(0, FR);
 
   IndicatorShortName("Fractal Range");
   SetIndexLabel(0,NULL);
 
   return(0);
  }
 
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
  {
   int    limit;
   int    counted_bars=IndicatorCounted();
   double FMin, FMax;
   
   if(counted_bars>0) counted_bars--;
   limit=Bars-counted_bars;
 
   for(int i=0; i<limit; i++)
   {
      FMin = 0; FMax = 0;
      int j=i;
      while ((FMax == 0 || FMin == 0) && (j < limit))
      {
         if (FMax == 0) FMax = iFractals(NULL, 0, MODE_UPPER, j);
         if (FMin == 0) FMin = iFractals(NULL, 0, MODE_LOWER, j);
         j++;
      }
      FR[i] = FMax - FMin;
 
   }
   return(0);
  }

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


Ошибка, предположительно, где-то в определении количества пересчитываемых баров, но как раз эта часть кода стандартна...

 
проблема еще может быть в том, что фракталы появляются как минимум на третьем баре.
 
xrust:
проблема еще может быть в том, что фракталы появляются как минимум на третьем баре.

Нет-нет, тут явно дело не в этом. Если нет нового фрактала, просто тянется уровень предыдущего. Что мы и можем видеть на рис. 2.

Тут явно ошибка чисто программная, это я Вам как программист говорю :)

 

А я вам, как не программист говорю,что у вас не правильно организован поиск фракталов при отсутствии новых :))))))

 
xrust:

А я вам, как не программист говорю,что у вас не правильно организован поиск фракталов при отсутствии новых :))))))

Для алгоритма нет понятия "новый" или "старый" фрактал. В цикле перебираются все бары, начиная от текущего, пока не найдены будут ближайшие два с ненулевыми фракталами.

Но суть не в этом, данный индикатор приведен просто как пример. Аналогичная проблема и с другими самописными индикаторами.

 
DrShumiloff:
xrust:

А я вам, как не программист говорю,что у вас не правильно организован поиск фракталов при отсутствии новых :))))))

Для алгоритма нет понятия "новый" или "старый" фрактал. В цикле перебираются все бары, начиная от текущего, пока не найдены будут ближайшие два с ненулевыми фракталами.

Но суть не в этом, данный индикатор примеден просто как пример. Аналогичная проблема и с другими самописными индикаторами.

У Вас действительно проблемы с организацией цикла, как говорит xrust.

 
Rosh:

У Вас действительно проблемы с организацией цикла, как говорит xrust.

Вложенного, "while {}"?

Да там же ошибаться-то негде... :-(

 

Вставьте распринтовку в код:

      while ((FMax == 0 || FMin == 0) && (j < limit))
      {
         if (FMax == 0) FMax = iFractals(NULL, 0, MODE_UPPER, j);
         if (FMin == 0) FMin = iFractals(NULL, 0, MODE_LOWER, j);
         Print("j=",j);
         j++;
      }
И не забудьте, что фракталы для нулевого и первого бара не существуют и индикатор всегда вернет нулевое значение.
 
Rosh писал (а):

Вставьте распринтовку в код

Да, я тоже подумал об этом. Жаль, нет в MetaEditor брек-поинтов и дебага.

 
DrShumiloff:

 Жаль, нет в MetaEditor брек-поинтов и дебага.


Зато есть принты.

Первое, что бросается в глаза - пределы изменения переменной limit => от 0 (1) до 1 (2). Поскольку

int    counted_bars=IndicatorCounted();

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

Соответственно j от 0 (минимальный i) и до limit (который в общем случае не превышает 2, исключения - пропуск баров по истории и перезагрузка).

Теперь вопрос: а какие фракталы на последних двух барах, если фрактал реально формируется на третьем ( нужны два закрытых бара после) ?


При перезагрузке действительно пресчитывается все поскольку 

IndicatorCounted();

выдаст ноль (-1) и индикатор будет пересчитан для всей тайм серии, то есть limit будет равно Bars (если верить хэлпу Bars+1) .


Успехов.

 

Вот что значит свежий взгляд :)

Спасибо, Владислав! Выручили!

Действительно, чтобы не было выхода за пределы массива, условие должно быть j < Bars.

Стормозил...

Причина обращения: