Time[0] на первом тике иногда глючит.

 

В OnCalculate, при смене периода графика, Time[0] на первом тике иногда глючит. Кто вникал в эту проблему? Хватит дождаться 2 тика или надо уже сделать проверку по умнее, например Time[0] сравнивать с последним временем сервера?

0       12:02:18.477    Test_FirstBarTime USDCAD,M30: -1784- Time[0]2019.06.03 12:00:00 TimeCurrent(): 2019.06.03 12:02:18
0       12:02:18.755    Test_FirstBarTime USDCAD,M30: uninit reason 3
0       12:02:18.757    Test_FirstBarTime USDCAD,M15: initialized
0       12:02:18.757    Test_FirstBarTime USDCAD,M15: -1784- Time[0]2019.04.17 16:00:00 TimeCurrent(): 2019.06.03 12:02:18
0       12:02:18.827    Test_FirstBarTime USDCAD,M15: -1784- Time[0]2019.06.03 12:00:00 TimeCurrent(): 2019.06.03 12:02:18
...

0       12:02:23.304    Test_FirstBarTime USDCAD,M5: -1784- Time[0]2019.06.03 12:00:00 TimeCurrent(): 2019.06.03 12:02:23
0       12:02:23.421    Test_FirstBarTime USDCAD,M5: uninit reason 3
0       12:02:23.428    Test_FirstBarTime USDCAD,M1: initialized
0       12:02:23.428    Test_FirstBarTime USDCAD,M1: -1784- Time[0]2019.04.17 18:05:00 TimeCurrent(): 2019.06.03 12:02:23
0       12:02:23.480    Test_FirstBarTime USDCAD,M1: -1784- Time[0]2019.06.03 12:02:00 TimeCurrent(): 2019.06.03 12:02:23
...

 

Не "глючит", а показывает последний известный бар (необновленную историю).
Терминал отслеживает (и строит) только активные периоды.

Остальные нужно обновлять (подгружать) самостоятельно.

 
Taras Slobodyanik:

Остальные нужно обновлять (подгружать) самостоятельно.

Какой функций это делается?

 
Nauris Zukas:

Какой функций это делается?

так как это в OnCalculate, то достаточно добавить проверку

if (rates_total-prev_calculated>1)
      {
      //пересчитываем всё заново
      }
 
Nauris Zukas:

Какой функций это делается?

индикаторы не умеют самостоятельно подгружать историю, можно конечно через iTime / iClose ... любую ф-ицю запустить подкачку истории


но обычно это делают для мультитаймфреймовых индикаторов, в обычном индикаторе достаточно проверить prev_calculated ==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[])
{
   int i,limit;
   if(prev_calculated == 0) {
      limit = rates_total - 1;    //--- Первый вызов индикатора или смена таймфрейма или подгрузка данных из истории
   }
   else limit = rates_total - prev_calculated + 1;

   for(i = limit; i >= 0; i--) { //--- В этом цикле основные вычисления. Таким образом обрабатываться будет только "свежая" информация                       
   }
   return(rates_total);
 
Taras Slobodyanik:

так как это в OnCalculate, то достаточно добавить проверку

Спасибо!

 
Igor Makanu:

я использую вот такой свой шаблон индикатора:

Спасибо!

 

Я смотрю свои код и вижу там проверку, но все портит функция которая пропускает один раз в час. Поскольку в алгоритме заложено изменение только по PERIOD_H1, то мне не надо чаще делать вычисления. Как в таком случае бы сделали вы?

ПС. В первом посте был сделан отдельный код для проверки, это из основного кода.

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[])
  {
//---
   int limit=0;

   if(rates_total<MaxBarsMod || MaxBarsMod==0)
      MaxBarsMod=rates_total;

   if(prev_calculated<rates_total && prev_calculated!=0)
     {
      MaxBarsMod+=rates_total-prev_calculated;
     }

   if(prev_calculated!=0)
      limit=MaxBarsMod-(rates_total-prev_calculated);
   else
      limit=0;

//--- здесь все расчеты значений индикатора
   if(prev_calculated<rates_total && NewBar1H())
     {

     }
   return(rates_total);
  }

bool NewBar1H() {bool r;static datetime bar=0;if(bar==0) bar=TimeCurrent();if(bar==iTime(Symbol(),PERIOD_H1,0)) r=false; else { bar=iTime(Symbol(),PERIOD_H1,0); r=true; }return(r);}
 
Nauris Zukas:

...то мне не надо чаще делать вычисления.

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

И эти новые бары могут появится где угодно, не обязательно в конце истории и последовательно.

 
Nauris Zukas:

Я смотрю свои код и вижу там проверку, но все портит функция которая пропускает один раз в час. Поскольку в алгоритме заложено изменение только по PERIOD_H1, то мне не надо чаще делать вычисления. Как в таком случае бы сделали вы?

примерно такой код, но не проверял как работать будет:

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[])
  {
   int i,limit;
   static int lasthour=-1;
   if(prev_calculated==0) //--- Первый вызов индикатора или смена таймфрейма или подгрузка данных из истории
     {
      limit=rates_total-1;
      lasthour=-1;
     }
   else limit=rates_total-prev_calculated+1;

   if(TimeHour(time[1])!=lasthour)  //--- Проверяем изменился ли час последнего бара, если час такой как и был на предыдущем тике, то вернем только количество рассчитанных баров
     {
      lasthour=TimeHour(time[1]);
     }
   else return(prev_calculated);

   for(i=limit; i>=0; i--) //--- В этом цикле основные вычисления. Таким образом обрабатываться будет только "свежая" информация  
     {
     }
   return(rates_total);
  }
 
Nauris Zukas:

Я смотрю свои код и вижу там проверку, но все портит функция которая пропускает один раз в час. Поскольку в алгоритме заложено изменение только по PERIOD_H1, то мне не надо чаще делать вычисления. Как в таком случае бы сделали вы?

ПС. В первом посте был сделан отдельный код для проверки, это из основного кода.

Два способа:

  1. Простой, но некошерный. Переместить проверку нового часового бара выше, до проверки prev_calculated.
  2. Правильный, но чуть более сложный. Перевести логику rates_total и prev_calculated на необходимый ТФ. В данном случае на Н1:
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Определение индекса бара, с которого необходимо производить перерасчет                                                                                                                            |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
int GetRecalcIndex()
{
   int nTotal = iBars(NULL, m_eTF);
   int nLimit = nTotal - 1; 
   
   // Первое отображение или произошла подкачка данных, т. е. на предыдущем тике баров было не на один бар меньше, как при нормальном развитии истории, а на два или более баров меньше
   if (m_nPrevCalculated < nTotal - 1)                     
   {
       // Какие-то действия по инициализации индикатора. Например, заполнение буферов индикатора значениями по умолчанию
   }
   // Нормальное развитие истории. Количество баров на текущем тике отличается от количества баров на предыдущем тике не больше, чем на один бар
   else
      nLimit = (MathMin(nTotal - m_nPrevCalculated, nTotal)); 
   
   m_nPrevCalculated = nTotal;
   return nLimit;
}

m_nPrevCalculated - собственная глобальная переменная, ничего общего с prev_calculated не имеет, хотя и выполняет ту же функцию.

m_eTF - ТФ, для которого производятся расчеты.

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