Устранение пробелов в индикаторе, после перезагрузки.

 

Здравствуйте. Пробую рисовать разные индикаторы.

Вот пару месяцев назад нарисовал индикатор из четырех EMA со стрелкой, при пересечении.

Вроде бы все исправно работает, но есть странный момент при загрузке компьютера.

Выглядит все следующим образом: компьютер работает, данные считаются, индикатор обновляется.

Потом компьютер выключаю. Допустим на ночь. Включаю утром (через 6-8 часов) и вижу вот такую картину (см.рисунок).

Т.е. при единичной загрузке индикатор отчего-то не пересчитывает данные за тот период, что ПК был выключен.

При закрытии/открытии терминала - данные обновляются, и индикатор опять считается должным образом, без "пробелов".

Подскажите, в чем может быть дело? Я уже и чужой код смотрел, и стандартные библиотеки ковырял, в поисках решения, ничего так и не понял.

Спасибо. Код приложен.

#property version   "1.00"
#property indicator_chart_window
#property indicator_buffers 6
#property indicator_plots   6
//--- plot MA_1
#property indicator_label1  "MA_1"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrRed
#property indicator_style1  STYLE_SOLID
#property indicator_width1  2
//--- plot MA_2
#property indicator_label2  "MA_2"
#property indicator_type2   DRAW_LINE
#property indicator_color2  clrYellow
#property indicator_style2  STYLE_SOLID
#property indicator_width2  2
//--- plot MA_3
#property indicator_label3  "MA_3"
#property indicator_type3   DRAW_LINE
#property indicator_color3  clrLime
#property indicator_style3  STYLE_SOLID
#property indicator_width3  2
//--- plot MA_4
#property indicator_label4  "MA_4"
#property indicator_type4   DRAW_LINE
#property indicator_color4  clrAqua
#property indicator_style4  STYLE_SOLID
#property indicator_width4  2
//--- plot ARR_1_UP
#property indicator_label5  "ARR_1_UP"
#property indicator_type5   DRAW_ARROW
#property indicator_color5  clrWhite
#property indicator_style5  STYLE_SOLID
#property indicator_width5  2
//--- plot ARR_1_DN
#property indicator_label6  "ARR_1_DN"
#property indicator_type6   DRAW_ARROW
#property indicator_color6  clrBlack
#property indicator_style6  STYLE_SOLID
#property indicator_width6  2

//
input int                  Period_1    =     10;
input ENUM_APPLIED_PRICE   Price_1     =     PRICE_CLOSE;
//
input int                  Period_2    =     20;
input ENUM_APPLIED_PRICE   Price_2     =     PRICE_CLOSE;
input int                  Dist_1_2    =     0;
//
input int                  Period_3    =     30;
input ENUM_APPLIED_PRICE   Price_3     =     PRICE_CLOSE;
input int                  Dist_2_3    =     0;
//
input int                  Period_4    =     40;
input ENUM_APPLIED_PRICE   Price_4     =     PRICE_CLOSE;
input int                  Dist_3_4    =     0;
//

//--- indicator buffers
double         MA_1Buffer[], MA_2Buffer[], MA_3Buffer[], MA_4Buffer[], Arr_UP[], Arr_DN[];
int            MA_1, MA_2, MA_3, MA_4, limit;
bool           first = true, arrUp=true, arrDn=true;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,MA_1Buffer,INDICATOR_DATA);
   SetIndexBuffer(1,MA_2Buffer,INDICATOR_DATA);
   SetIndexBuffer(2,MA_3Buffer,INDICATOR_DATA);
   SetIndexBuffer(3,MA_4Buffer,INDICATOR_DATA);
   SetIndexBuffer(4,Arr_UP,INDICATOR_DATA);
   PlotIndexSetInteger(4,PLOT_ARROW,233);
   PlotIndexSetInteger(4,PLOT_ARROW_SHIFT,20);
   SetIndexBuffer(5,Arr_DN,INDICATOR_DATA);
   PlotIndexSetInteger(5,PLOT_ARROW,234);
   PlotIndexSetInteger(5,PLOT_ARROW_SHIFT,-20);
//
   MA_1 = iMA(NULL,PERIOD_CURRENT,Period_1,0,MODE_EMA,Price_1);
   MA_2 = iMA(NULL,PERIOD_CURRENT,Period_2,0,MODE_EMA,Price_2);
   MA_3 = iMA(NULL,PERIOD_CURRENT,Period_3,0,MODE_EMA,Price_3);
   MA_4 = iMA(NULL,PERIOD_CURRENT,Period_4,0,MODE_EMA,Price_4);
   if(MA_1==INVALID_HANDLE || MA_2==INVALID_HANDLE|| MA_3==INVALID_HANDLE|| MA_4==INVALID_HANDLE)
     {
      Print("Неверный хэндл. Инициализация невозможна! Код ошибки: " +IntegerToString(GetLastError()));
      return(INIT_FAILED);
     }
   ArrayInitialize(MA_1Buffer,EMPTY_VALUE);
   ArrayInitialize(MA_2Buffer,EMPTY_VALUE);
   ArrayInitialize(MA_3Buffer,EMPTY_VALUE);
   ArrayInitialize(MA_4Buffer,EMPTY_VALUE);
   ArrayInitialize(Arr_UP,EMPTY_VALUE);
   ArrayInitialize(Arr_DN,EMPTY_VALUE);
   ArraySetAsSeries(MA_1Buffer,true);
   ArraySetAsSeries(MA_2Buffer,true);
   ArraySetAsSeries(MA_3Buffer,true);
   ArraySetAsSeries(MA_4Buffer,true);
   ArraySetAsSeries(Arr_UP,true);
   ArraySetAsSeries(Arr_DN,true);
   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(first)
     {
      limit=rates_total-1;
      first=false;
     }
   else
      limit=1;
   CopyBuffer(MA_1,0,0,limit,MA_1Buffer);
   CopyBuffer(MA_2,0,0,limit,MA_2Buffer);
   CopyBuffer(MA_3,0,0,limit,MA_3Buffer);
   CopyBuffer(MA_4,0,0,limit,MA_4Buffer);
   for(int i = limit-1; i>=0; i--)
     {
      if(MA_1Buffer[i]<MA_2Buffer[i]&&MA_2Buffer[i]<MA_3Buffer[i]&&MA_3Buffer[i]<MA_4Buffer[i]&&arrDn
         &&((MA_2Buffer[i]-MA_1Buffer[i])>Dist_1_2*_Point)&&((MA_3Buffer[i]-MA_2Buffer[i])>Dist_2_3*_Point)&&((MA_4Buffer[i]-MA_3Buffer[i])>Dist_3_4*_Point))
        {
         Arr_DN[i]=MA_4Buffer[i];
         arrDn=false;
         arrUp=true;
        }
      if(MA_1Buffer[i]>MA_2Buffer[i]&&MA_2Buffer[i]>MA_3Buffer[i]&&MA_3Buffer[i]>MA_4Buffer[i]&&arrUp
         &&((MA_1Buffer[i]-MA_2Buffer[i])>Dist_1_2*_Point)&&((MA_2Buffer[i]-MA_3Buffer[i])>Dist_2_3*_Point)&&((MA_3Buffer[i]-MA_4Buffer[i])>Dist_3_4*_Point))
        {
         Arr_UP[i]=MA_4Buffer[i];
         arrDn=true;
         arrUp=false;
        }
     }
   return(rates_total);
  }
//+------------------------------------------------------------------+
Файлы:
e9o92z6wa.png  22 kb
 
AltAndGen:

Здравствуйте. Пробую рисовать разные индикаторы.

Вот пару месяцев назад нарисовал индикатор из четырех EMA со стрелкой, при пересечении.

Вроде бы все исправно работает, но есть странный момент при загрузке компьютера.

Выглядит все следующим образом: компьютер работает, данные считаются, индикатор обновляется.

Потом компьютер выключаю. Допустим на ночь. Включаю утром (через 6-8 часов) и вижу вот такую картину (см.рисунок).

Т.е. при единичной загрузке индикатор отчего-то не пересчитывает данные за тот период, что ПК был выключен.

При закрытии/открытии терминала - данные обновляются, и индикатор опять считается должным образом, без "пробелов".

Подскажите, в чем может быть дело? Я уже и чужой код смотрел, и стандартные библиотеки ковырял, в поисках решения, ничего так и не понял.

Спасибо. Код приложен.

Я не могу понять какой чужой код вы смотрели. Я такого

   if(first)
     {
      limit=rates_total-1;
      first=false;
     }
   else
      limit=1;

ни у кого не видел.

Определять первый запуск привычней ориентируясь на количество посчитанных баров prev_calculated

 

для начала нужно избавиться от переменной first, а вообще limit если запуск не первый должен быть равен не 1, а rates_total минус prev_calculated.

это все нужно грамотно закодировать.

 
AltAndGen:

Здравствуйте. Пробую рисовать разные индикаторы.

Т.е. при единичной загрузке индикатор отчего-то не пересчитывает данные за тот период, что ПК был выключен.

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

Для правильной обработки этого процесса все уже давно придумано:

  int limit = rates_total - prev_calculated;

  //---- последний посчитанный бар будет пересчитан 
  if (prev_calculated > 0) 
     ++limit;

Хотя я для простоты кода выделяю всего два случая:

  1. Если prev_calculated отличается от rates_total на 0 или 1, то рассчитывается только 1 или 2 последних бара соответственно. Это ситуация с равномерным обновлением истории котировок, т. е. либо поступил новый тик текущего бара, либо в течение естественного течения времени появился новый бар на графике.
  2. Все остальные случаи (prev_calculated отличается от rates_total на 2 бара и более) - загрузка котировок. Проще всего пересчитать всю историю.
 
Alexey Viktorov #:

Я не могу понять какой чужой код вы смотрели. Я такого

ни у кого не видел.

Определять первый запуск привычней ориентируясь на количество посчитанных баров prev_calculated

Собственная придумка.
Логику видел так: при загрузке индикатора (открылся ли терминал в целом, или поместили индикатор на график, в частности), при инициализации - рассчитать один раз весь объем доступных данных.
Затем подсчитывать каждый бар при его появлении, чтобы не пересчитывать все заново на каждом тике/баре.

На истину не претендую, профессионалом себя не считаю, пробую разобраться, ничего более.

 
Ihor Herasko #:

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

Для правильной обработки этого процесса все уже давно придумано:

Хотя я для простоты кода выделяю всего два случая:

  1. Если prev_calculated отличается от rates_total на 0 или 1, то рассчитывается только 1 или 2 последних бара соответственно. Это ситуация с равномерным обновлением истории котировок, т. е. либо поступил новый тик текущего бара, либо в течение естественного течения времени появился новый бар на графике.
  2. Все остальные случаи (prev_calculated отличается от rates_total на 2 бара и более) - загрузка котировок. Проще всего пересчитать всю историю.

Спасибо за развернутый ответ, буду пробовать!

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