Индикатор зря пересчитывается.

 

Я написал индикатор, который рисует 8 баров рядом с последними барами обычного графика цен.

Этот индикатор использует другой индикатор (тоже самодельный) (и не очень быстрый) (Типа ATR).

Когда я присоединяю этот MyATR индикатор к графику цен, он ведёт себя нормально: в начале проходит по всем барам, потом только последний бар пересчитывает.

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

В результате получаю сильное торможение.

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

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

 

 что может заставлять индикатор пересчитываться...?

RefreshRates () используете?

( в mql5 Refresh() ) 

 
Evgeny Potapov:

Я написал индикатор, который рисует 8 баров рядом с последними барами обычного графика цен.

Этот индикатор использует другой индикатор (тоже самодельный) (и не очень быстрый) (Типа ATR).

Когда я присоединяю этот MyATR индикатор к графику цен, он ведёт себя нормально: в начале проходит по всем барам, потом только последний бар пересчитывает.

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

В результате получаю сильное торможение.

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

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

С кодом было бы по-проще. Но, я бы предположил, что где-то в вашем индикаторе в OnCalculate() есть строка return( 0 ); Это означает, что происходит полный пересчет текущего индикатора, а раз он использует MyATR, то задействует и его данные на всей истории.

Второй вариант: Ваш индикатор (рисующий 8 баров) достаточно медленный. И MyATR достаточно медленный. В совокупности - все крайне медленно.

Да, а с чего Вы взяли, что пересчитываются все бары MyATR? 

 
Evgeny Potapov:

Я написал индикатор, который рисует 8 баров рядом с последними барами обычного графика цен.

Этот индикатор использует другой индикатор (тоже самодельный) (и не очень быстрый) (Типа ATR).

Когда я присоединяю этот MyATR индикатор к графику цен, он ведёт себя нормально: в начале проходит по всем барам, потом только последний бар пересчитывает.

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

В результате получаю сильное торможение.

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

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

Попробуйте в расчете первого индикатора считать только нужное кол-во баров назад, то есть 2 или 3 или сколько надо а не по всей истории
 
Tapochun:

С кодом было бы по-проще. Но, я бы предположил, что где-то в вашем индикаторе в OnCalculate() есть строка return( 0 ); Это означает, что происходит полный пересчет текущего индикатора, а раз он использует MyATR, то задействует и его данные на всей истории.

Второй вариант: Ваш индикатор (рисующий 8 баров) достаточно медленный. И MyATR достаточно медленный. В совокупности - все крайне медленно.

Да, а с чего Вы взяли, что пересчитываются все бары MyATR? 

1. Вот функция start вызываемого индикатора я его в первом посте условно назвал MyATR. Где GuestSmb - это один из инпутов. SMB - символ к которому присоединён индикатор, TF-общий таймфрейм

int start()  {
   int counter, counterBars, counted_bars=IndicatorCounted();
   int shortestBars = MathMin(Bars, iBars(GuestSmb, TF))-1;
   int k,i,limit=shortestBars;
   if(shortestBars < InpAtrPeriod + 12) return(0);
   if ( counted_bars > 0 )  limit=shortestBars-counted_bars+2;
   if ( counted_bars <= 0 )  limit=shortestBars;
   if(Bars<=InpAtrPeriod || InpAtrPeriod<=0)
      return(0);
   if(true)     { 
      ExtTRBuffer[0]=0.0;
      counterBars=0;
      for(k=limit; k>0; k--) {
         datetime guestDateTime = iTime(GuestSmb, TF, k);
         i = iBarShift(SMB, TF, guestDateTime, false);
         datetime guestDateTime2 = iTime(GuestSmb, TF, k+1);
         int i2 = iBarShift(SMB, TF, guestDateTime2, false);
         if(i == -1 || i2 == -1 || iClose(GuestSmb, TF, k+1) == 0 || i+1 != i2) {
            ExtTRBuffer[k] = EMPTY_VALUE;
            continue;
         }
         counterBars++;
         if(i < 1) break;
         double guest;
         if(InpAtrReverse) {
            guest = MathMax(1.0/iLow(GuestSmb, TF, k),1.0/iClose(GuestSmb, TF, k+1)) - MathMin(1.0/iHigh(GuestSmb, TF, k),1.0/iClose(GuestSmb, TF, k+1));
         }
         else {
            guest = MathMax(iHigh(GuestSmb, TF, k),iClose(GuestSmb, TF, k+1)) - MathMin(iLow(GuestSmb, TF, k),iClose(GuestSmb, TF, k+1));
         }
         double native = MathMax(High[i],Close[i2])-MathMin(Low[i],Close[i2]);
         if(native != 0) ExtTRBuffer[k]=guest/native;
         else ExtTRBuffer[k]=EMPTY_VALUE;
      }
      int secondCycleLimit = limit-InpAtrPeriod;
      if(secondCycleLimit < 2) secondCycleLimit = 2;
      bool calculationDone = false;
      for(k=1; k<secondCycleLimit; k++) {
         double firstValue=0.0;
         ExtATRBuffer[k]=0.0;
         counter=0;
         int foundCounter = 0;
         for(i=1; foundCounter<=InpAtrPeriod; i++) {
            int barShift = k+i+counter;
            if(barShift > shortestBars) calculationDone = true; //  // secondCycleLimit
            if(calculationDone) break;
            if(ExtTRBuffer[barShift] == EMPTY_VALUE) {
               counter++;
               continue;
            }
            foundCounter++;
            firstValue+=ExtTRBuffer[barShift];
         }
         if(calculationDone) break;
         firstValue/=InpAtrPeriod;
         ExtATRBuffer[k]=firstValue;
      }
      
   }



2. В случае полного пересчёта, внешний индикатор перечитывает только 8 баров (поскольку MaxBars = 8). Вот и его код:

int start()  {
   int counted_bars=IndicatorCounted();
   int shortestBars = MathMin(Bars, iBars(symbol, TF))-1;
   int k,i,limit=shortestBars;
   if(shortestBars < ScalePeriod + 12) return(0);
   limit = MaxBars;
//--- check for bars count and input parameter
   if(Bars<=ScalePeriod || ScalePeriod<=0)    return(0);
   //=============================================
   if(true)     { // counted_bars==0
      for(k=limit; k>1; k--) {
         datetime hostDateTime = iTime(SMB, TF, k);
         i = iBarShift(symbol, TF, hostDateTime, false);
         if(i == -1) {
            ExtLowHighBuffer[k] = EMPTY_VALUE;
            ExtHighLowBuffer[k] = EMPTY_VALUE;
            ExtOpenBuffer[k] = EMPTY_VALUE;
            ExtCloseBuffer[k] = EMPTY_VALUE;
            continue;
         }
         ScaleData2 sd = MakeScaleCoeff3(symbol, DoRevese, ScalePeriod, k) ;
         ScaledBar b = ScaleOneBar2(Time[k], symbol, sd, DoRevese) ;
         if(b.o < b.c) {
            ExtLowHighBuffer[k] = b.l;
            ExtHighLowBuffer[k] = b.h;
         }
         else {
            ExtLowHighBuffer[k] = b.h;
            ExtHighLowBuffer[k] = b.l;
         }
         ExtOpenBuffer[k] = b.o;
         ExtCloseBuffer[k] = b.c;
      }
   }
   return(0);
  }

это вроде не должно приводить к полному пересчёту вызываемого индикатора, поскольку функция MakeScaleCoef3 читает значения индикатора MyATR только с нескольких последних баров. Или я тут что-то неправильно понимаю?

3. Он пересчитывает все бары, потому что я добавлял Print(BarNumber). Если присоединяю индикатор MyATR к графику, то он только один раз проходится по всем барам, а если MyATR вызывается внешним индикатором, то Print на каждом тике выводит мне полный список баров.

 
Oksana Berenko:

RefreshRates () используете?

( в mql5 Refresh() ) 

Нет не использую. Но всё равно спасибо!

Вам говорили, что у вас красивая фотка?

 
Aleksey Vakhrushev:
Попробуйте в расчете первого индикатора считать только нужное кол-во баров назад, то есть 2 или 3 или сколько надо а не по всей истории

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

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

 
Evgeny Potapov:

1. Вот функция start вызываемого индикатора я его в первом посте условно назвал MyATR. Где GuestSmb - это один из инпутов. SMB - символ к которому присоединён индикатор, TF-общий таймфрейм

2. В случае полного пересчёта, внешний индикатор перечитывает только 8 баров (поскольку MaxBars = 8). Вот и его код:

это вроде не должно приводить к полному пересчёту вызываемого индикатора, поскольку функция MakeScaleCoef3 читает значения индикатора MyATR только с нескольких последних баров. Или я тут что-то неправильно понимаю?

3. Он пересчитывает все бары, потому что я добавлял Print(BarNumber). Если присоединяю индикатор MyATR к графику, то он только один раз проходится по всем барам, а если MyATR вызывается внешним индикатором, то Print на каждом тике выводит мне полный список баров.

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

3. Коли так, то дело, скорее всего и есть в функции MakeScaleCoef3(), т.к. именно она, если верить Вашим словам, читает значения индикатора MyATR. 

 
Tapochun:

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

3. Коли так, то дело, скорее всего и есть в функции MakeScaleCoef3(), т.к. именно она, если верить Вашим словам, читает значения индикатора MyATR. 

Вот:

ScaleData2 MakeScaleCoeff3(string smb, bool reverse, int barsWind, int barStart) {
   ScaleData2 s;
   int i;
   int lastBar = barStart+barsWind;
   double avg = 0;
   
   double atrRatio = iCustom(smb, TF, "AtrRatio", barsWind, reverse, 0, barStart) ; // iATR(smb, TF, BarsWind, barStart);
      
   double coef = atrRatio;
   // if(reverse) coef = 1*atrHost/atrGuest;// atrGuest/atrHost;
   // Print(smb, " atrGuest = ", atrGuest, " atrHost = ", atrHost, " coef = ", coef, " reverse = ", reverse);
   double avgShift = 0;
   if(reverse) {
      for(i=barStart; i<lastBar; i++) {
         avgShift +=  iOpen(SMB, TF, i) - coef/iOpen(smb, TF, i);
         avgShift += iClose(SMB, TF, i) - coef/iClose(smb, TF, i);
      }
   }
   else {
      for(i=barStart; i<lastBar; i++) {
         avgShift +=  iOpen(SMB, TF, i) - coef*iOpen(smb, TF, i);
         avgShift += iClose(SMB, TF, i) - coef*iClose(smb, TF, i);
      }
   }
   avgShift = avgShift/barsWind/2.0;
   s.coef = coef;
   s.shift= avgShift;
   
   return s;
}


Вызывается для одного бара.

Здесь менее всего я ожидаю обнаружить ошибку.

 
Evgeny Potapov:

...

Везде напихайте Print() с разными значениями, и посмотрите, что и когда во вкладке "Эксперты" выводится. Мне это всегда помогает понять код.
 

Здесь помочь может только клуб телепатов.

Скорее всего индикатор вызывается с неправильными параметрами. 

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