Нужна помощь в оптимизации циклов

Peter Vorobyev
479
Peter Vorobyev  

Ниже код варианта стохастика. Не могу сообразить как оптимизировать код чтобы не пересчитывать все 500 (Barcount) баров за тик. 
Подскажите где докрутить?

#property indicator_separate_window
#property indicator_minimum 0.00
#property indicator_maximum 100.00
#property indicator_color1 Lime
#property indicator_buffers 2
#property indicator_color2 Red
#property indicator_level1 20
#property indicator_level2 80
#property strict

extern double  Slw = 5;
extern int     Pds = 3;
extern double  Slwsignal = 3;
extern int     Barcount = 500;

int LastTradeTime;
double ExtHistoBuffer[];
double ExtHistoBuffer2[];
bool BuyAlert=false, SellAlert=false;

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void SetIndexValue(int shift, double value)
  {
   ExtHistoBuffer[shift] = value;
  }

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void SetIndexValue2(int shift, double value)
  {
   ExtHistoBuffer2[shift] = value;
  }

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
double GetIndexValue(int shift)
  {
   return(ExtHistoBuffer[shift]);
  }

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
double GetIndexValue2(int shift)
  {
   return(ExtHistoBuffer2[shift]);
  }

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int init()
  {
   IndicatorShortName("");
   PlotIndexSetInteger(0, DRAW_LINE, STYLE_SOLID);
   SetIndexBuffer(0, ExtHistoBuffer);
   IndicatorShortName("");
   PlotIndexSetInteger(1, DRAW_LINE, STYLE_SOLID);
   SetIndexBuffer(1, ExtHistoBuffer2);

   IndicatorShortName("");
   SetIndexLabel(0,NULL);
   SetIndexLabel(1,NULL);

   return(0);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
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[])
  {
   double AA = 0;
   double bb = 0;
   double aa1 = 0;
   int shift = 0;
   double loopbegin = 0;
   double loopbegin2 = 0;
   double loopbegin3 = 0;
   double smconst = 0;
   double smconst1 = 0;
   double prev = 0;
   double prev1 = 0;
   double prev2 = 0;
   double prev3 = 0;
   double MAValue = 0;
   double MAValue2 = 0;
   double mavalue3 = 0;
   double MyHigh = 0;
   double MyLow = 0;
   int counter = 0;
   double Price = 0;
   double tmpDevAA = 0;

   smconst = 2 / (1+Slw);
   smconst1 = 2 / (1+Slwsignal);

   loopbegin = loopbegin+1;
   for(shift =Barcount; shift >=0 ; shift --)
     {
      prev = GetIndexValue2(shift+1);

      AA = 0;
      tmpDevAA = (High[iHighest(NULL, 0, MODE_HIGH,shift+Pds,Pds)] - Low[iLowest(NULL, 0, MODE_LOW,shift+Pds,Pds)]);

      if(tmpDevAA != 0)
         AA = 100* ((Close[shift] - Low[iLowest(NULL, 0, MODE_LOW,shift+Pds,Pds)]) / tmpDevAA);

      MAValue2 = smconst * (AA-prev) + prev;
      SetIndexValue2(shift,MAValue2);
      loopbegin = loopbegin-1;
     }

   loopbegin2 = loopbegin2+1;
   for(shift =Barcount-Pds; shift >=0 ; shift --)
     {
      MyHigh = -999999;
      MyLow = 99999999;
      for(counter =shift; counter <=Pds + shift ; counter ++)
        {
         Price= GetIndexValue2(counter);
         if(Price > MyHigh)
            MyHigh = Price;
         if(Pds <= 0)
            MyHigh = Price;
         if(Price < MyLow)
            MyLow = Price;
         if(Pds <= 0)
            MyLow = Price;
        }

      prev1 = GetIndexValue(shift+1);
      aa1=GetIndexValue2(shift);

      bb= 0;
      if((MyHigh-MyLow) != 0)
         bb=100*(aa1-MyLow)/(MyHigh-MyLow);

      MAValue = smconst * (bb-prev1) + prev1;
      SetIndexValue(shift,MAValue);
      loopbegin2 = loopbegin2-1;
     }

   loopbegin3 = loopbegin3+1;
   for(shift =Barcount; shift >=0 ; shift --)
     {
      prev2=GetIndexValue2(shift+1);
      prev3=GetIndexValue(shift);
      mavalue3= smconst1 * (prev3-prev2) +prev2;
      SetIndexValue2(shift,mavalue3);
      loopbegin3 = loopbegin3-1;
     }

   Comment("\n ",ExtHistoBuffer[0],"\n ",ExtHistoBuffer[1]);

   return(rates_total);
  }

Файлы:
Aleksey Mavrin
7564
Aleksey Mavrin  
Peter Vorobyev:

Ниже код варианта стохастика. Не могу сообразить как оптимизировать код чтобы не пересчитывать все 500 (Barcount) баров за тик. 
Подскажите где докрутить?

 for(shift =prev_calculated; shift <rates_total ; shift ++)
Peter Vorobyev
479
Peter Vorobyev  
Aleksey Mavrin:

в shift будет номер первого бара истории с индексом в несколько тысяч

вы наверно имели ввиду 

shift = rates_total - prev_calculated

получаю 2020.02.06 02:34:18.484 ptr_DDS_test EURUSD.I,M1: array out of range in 'ptr_DDS_test.mq4' (53,32)

но не понимаю почему выход за диапазон. 
Файлы:
Ihor Herasko
26658
Ihor Herasko  
Peter Vorobyev:

в shift будет номер первого бара истории с индексом в несколько тысяч

вы наверно имели ввиду 

получаю 2020.02.06 02:34:18.484 ptr_DDS_test EURUSD.I,M1: array out of range in 'ptr_DDS_test.mq4' (53,32)

но не понимаю почему выход за диапазон. 

Потому что если limit указывает на первый бар в истории (тот, что левее всех по графику), то левее него (индекс + 1 и более) ничего нет - выход за пределы массива.

А вот здесь:

     for(counter =shift; counter <=Pds + shift ; counter ++)
        {
         Price= GetIndexValue2(counter);
         if(Price > MyHigh)
            MyHigh = Price;
         if(Pds <= 0)
            MyHigh = Price;
         if(Price < MyLow)
            MyLow = Price;
         if(Pds <= 0)
            MyLow = Price;
        }

происходит обращение к элементам массива ExtHistoBuffer2, которых не существует (они должны быть левее на графике, но их нет).

Все потому, что в функции GetIndexValue2() нет проверки на ошибку выхода за пределы массива.

Документация по MQL5: Основы языка / Переменные
Документация по MQL5: Основы языка / Переменные
  • www.mql5.com
Переменные должны быть объявлены перед их использованием. Для идентификации переменных используются уникальные имена. Описания переменных используются для их определения и объявления типов. Описание не является оператором. Индексом массива может быть только целое число. Допускаются не более чем четырехмерные массивы. Нумерация элементов...
Aleksey Mavrin
7564
Aleksey Mavrin  
Peter Vorobyev:

в shift будет номер первого бара истории с индексом в несколько тысяч

вы наверно имели ввиду 

получаю 2020.02.06 02:34:18.484 ptr_DDS_test EURUSD.I,M1: array out of range in 'ptr_DDS_test.mq4' (53,32)

но не понимаю почему выход за диапазон. 

Вы спросили что надо чтобы не пересчитывать все 500 баров, я именно это и ответил, что вы с shift дальше делаете для этого не важно.

Peter Vorobyev
479
Peter Vorobyev  
Ihor Herasko:

Потому что если limit указывает на первый бар в истории (тот, что левее всех по графику), то левее него (индекс + 1 и более) ничего нет - выход за пределы массива.

А вот здесь:

происходит обращение к элементам массива ExtHistoBuffer2, которых не существует (они должны быть левее на графике, но их нет).

Все потому, что в функции GetIndexValue2() нет проверки на ошибку выхода за пределы массива.

спасибо за подсказку - исправил.
Историю отрисовывает правильно. А вот онлайн рисовать не хочет. 

Файлы:
Peter Vorobyev
479
Peter Vorobyev  
Peter Vorobyev:

спасибо за подсказку - исправил.
Историю отрисовывает правильно. А вот онлайн рисовать не хочет. 

т.е. что-то не могу сообразить из алгоритма, вообще реально не пересчитывать всю историю чтобы получить теже данные на выходе, что и при пересчете.

Aleksey Mavrin
7564
Aleksey Mavrin  
судя по тому что вы пишите про шифт - вы не запутались с индексацией массивов индикатора? он индексируется так что 0 ячейка массива - самый старый бар - самый левый т.е.
Peter Vorobyev
479
Peter Vorobyev  
Aleksey Mavrin:
судя по тому что вы пишите про шифт - вы не запутались с индексацией массивов индикатора? он индексируется так что 0 ячейка массива - самый старый бар - самый левый т.е.

да вроде не запутался

ArraySetAsSeries(ExtHistoBuffer, true);
***
int limit = rates_total - prev_calculated;
if (limit != 0) limit --;

for(shift = limit; shift >=0 ; shift --)
   ExtHistoBuffer[shift] = value;   
Aleksey Mavrin
7564
Aleksey Mavrin  
Peter Vorobyev:

да вроде не запутался

а какой смысл в  ExtHistoBuffer[shift] = value

шифт всегда будет ноль, кроме первого просчёта истории. т.е. вы меняете самый старый бар, а надо наверное самый новый, не? а говорите не запутались)

Peter Vorobyev
479
Peter Vorobyev  
Aleksey Mavrin:

а какой смысл в  ExtHistoBuffer[shift] = value

шифт всегда будет ноль, кроме первого просчёта истории. т.е. вы меняете самый старый бар, а надо наверное самый новый, не? а говорите не запутались)

почему 0 - это самый старый ? 
0 - это самый новый бар - нулевая свеча. Ведь ArraySetAsSeries(ExtHistoBuffer, true); указывает что хранение элементов как в тайм серии. Или я чего-то не понимаю?