Ошибки, баги, вопросы - страница 3027

 
Сергей Таболин:

Индикаторы - это моё САМОЕ слабое место )))

Но!

Или я вооще ничего не понимаю, или ты маленько ошибаешься. 

Насколько я знаю, prev_calculated это счётчик не обсчитанных данных. А раз поступившие данные посчитаны, то и этот счётчик обнуляется... Типа, всё, парень, нет больше новых данных для расчёта.... )))

И по какой причине индикатор должен полностью пересчитаться в таком случае - я не знаю!

---------------

Соврал маленько )))

Перерисовываются не индикаторы, а "индюки" только для того, чтобы "красиво" выглядеть на истории ;)

счётчик сбрасывается по независящим от программиста причинам в исходное состояние, так, как будто индикатор запущен в первые!

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



Необходимо отметить связь между значением, возвращаемым функцией OnCalculate() и вторым входным параметром prev_calculated. Параметр prev_calculated при вызове функции содержит значение, которое вернула функция OnCalculate() на предыдущем вызове. Это позволяет реализовать экономные алгоритмы расчета пользовательского индикатора с тем, чтобы избежать повторных расчетов для тех баров, которые не изменились с предыдущего запуска этой функции.

-это из документации. не работающий как надо прев кальк ломает всю концепцию экономичных рассчетов. 
 
Andrey Dik:
счётчик сбрасывается по независящим от программиста причинам в исходное состояние, так, как будто индикатор запущен в первые!

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

Это на каждом новом баре такое? Перестраховываются, что ли..

Если не на каждом, то там есть разные причины, когда сбрасывается прев_калк.

 

Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий

Ошибки, баги, вопросы

Andrey Dik, 2021.05.27 13:53

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

такая конструкция знакома?:

if (rates_total == prev_calculated) return rates_total;
  
int startInd = rates_total - prev_calculated;

for (int i = startInd; i >= 0; i--)
{
  //тут считаем индикатор, который обращается к другому индикатору на старшем ТФ
}

дело не в логике советника (перерисовывающий, неперерисовывающий, недорисовывающий или какой то ещё), а втом, что prev_calculated обнуляется в то время как его об этом никто не просил!

по моему проблема в:

if (rates_total == prev_calculated) return rates_total;

Вы не даете вызываемому индикатору на другом ТФ рассчитываться каждый тик, а потом вызываете его и происходит синхронизация истории и расчет с нуля этого индикатора


набросал тест, у меня вызываемый индикатор все считает и не сбрасывается в prev_calculated == 0

рисуем в индикаторе close и распринтовываем события новый бар и  prev_calculated == 0 :

// tst.mq5

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 start;
   static datetime t = 0;
   if(t != time[rates_total-1])
   {
      t = time[rates_total-1];
      Print(MQLInfoString(MQL_PROGRAM_NAME), " New bar ", t);
   }
   
   if(prev_calculated == 0)
   {
      start = 0;
      ArrayInitialize(Buffer, EMPTY_VALUE);
      Print(MQLInfoString(MQL_PROGRAM_NAME), " prev_calculated == 0");
   }
   else start = prev_calculated - 1;


   for(int i = start; i < rates_total; i++)
   {
      Buffer[i] = close[i];
   }
//--- return value of prev_calculated for next call
   return(rates_total);
}

вызываем этот индикатор (получаем 2 последних значения буфера) и тоже рисуем close на своем ТФ:

input ENUM_TIMEFRAMES TF = PERIOD_M5;
int OnInit()
{
//--- indicator buffers mapping
   SetIndexBuffer(0, Buffer, INDICATOR_DATA);
   ind_handle = iCustom(NULL, TF, "NewFolder\\tst");
//---
   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[])
{
   int start;
   static datetime t = 0;
   if(t != time[rates_total-1])
   {
      t = time[rates_total-1];
      Print(MQLInfoString(MQL_PROGRAM_NAME), " New bar ", t);
   }

   if(prev_calculated == 0)
   {
      start = 0;
      ArrayInitialize(Buffer, EMPTY_VALUE);
      Print(MQLInfoString(MQL_PROGRAM_NAME), " prev_calculated == 0");
   }
   else start = prev_calculated - 1;


   for(int i = start; i < rates_total; i++)
   {
      Buffer[i] = close[i];
   }
   double buf[];
   if(CopyBuffer(ind_handle, 0, 0, 2, buf) < 0) Print("Error CopyBuffer # ",GetLastError());
//--- return value of prev_calculated for next call
   return(rates_total);
}


запустил последний индикатор на М1 , лог:

2021.05.27 21:48:34.196 tst_tf (EURUSD,M1) tst_tf New bar 2021.05.27 21:48:00

2021.05.27 21:48:34.197 tst_tf (EURUSD,M1) tst_tf prev_calculated == 0

2021.05.27 21:48:34.197 tst_tf (EURUSD,M1) Error CopyBuffer # 4806

2021.05.27 21:48:34.197 tst (EURUSD,M5) tst New bar 2021.05.27 21:45:00

2021.05.27 21:48:34.197 tst (EURUSD,M5) tst prev_calculated == 0

2021.05.27 21:49:01.636 tst_tf (EURUSD,M1) tst_tf New bar 2021.05.27 21:49:00

2021.05.27 21:50:00.149 tst_tf (EURUSD,M1) tst_tf New bar 2021.05.27 21:50:00

2021.05.27 21:50:00.149 tst (EURUSD,M5) tst New bar 2021.05.27 21:50:00

2021.05.27 21:51:01.789 tst_tf (EURUSD,M1) tst_tf New bar 2021.05.27 21:51:00

2021.05.27 21:52:02.832 tst_tf (EURUSD,M1) tst_tf New bar 2021.05.27 21:52:00

2021.05.27 21:53:00.920 tst_tf (EURUSD,M1) tst_tf New bar 2021.05.27 21:53:00

2021.05.27 21:54:02.778 tst_tf (EURUSD,M1) tst_tf New bar 2021.05.27 21:54:00

2021.05.27 21:55:00.308 tst_tf (EURUSD,M1) tst_tf New bar 2021.05.27 21:55:00

2021.05.27 21:55:00.308 tst (EURUSD,M5) tst New bar 2021.05.27 21:55:00

2021.05.27 21:56:00.118 tst_tf (EURUSD,M1) tst_tf New bar 2021.05.27 21:56:00

2021.05.27 21:57:00.419 tst_tf (EURUSD,M1) tst_tf New bar 2021.05.27 21:57:00

 
Andrey Khatimlianskii:

Это на каждом новом баре такое? Перестраховываются, что ли..

Если не на каждом, то там есть разные причины, когда сбрасывается прев_калк.

именно на каждом новом баре старшего ТФ.

пример, если индикатор работает на М1 и обращается к индикатору на М5, то каждые 5 минут индикатор просчитается полностью заново. существенное замедление оптимизации гарантировано. 

 
Igor Makanu:

по моему проблема в:

Вы не даете вызываемому индикатору на другом ТФ рассчитываться каждый тик, а потом вызываете его и происходит синхронизация истории и расчет с нуля этого индикатора


набросал тест, у меня вызываемый индикатор все считает и не сбрасывается в prev_calculated == 0

рисуем в индикаторе close и распринтовываем события новый бар и  prev_calculated == 0 :

вызываем этот индикатор (получаем 2 последних значения буфера) и тоже рисуем close на своем ТФ:

я делаю проверку синхронизированости данных на запрашиваемом старшем ТФ (М5) и готовность индикатора на нём, если не готово, то выход.

в итоге индикатор работает только 1 раз на открытии бара М1, а не на каждом тике:


//проверка готовности данных и индикатора на другом TF
if (SeriesInfoInteger (Symbol (), tf, SERIES_SYNCHRONIZED))
{
  if (iBars (Symbol (), tf) != BarsCalculated (handleFr)) return 0;
}
else return 0;

//проверка на наличие нового бара
if (rates_total == prev_calculated) return rates_total;

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

 
Andrey Dik:

я делаю проверку синхронизированости данных на запрашиваемом старшем ТФ (М5) и готовность индикатора на нём, если не готово, то выход.

в итоге индикатор работает только 1 раз на открытии бара М1, а не на каждом тике:


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

это не должно корректно работать в индикаторах:

if (SeriesInfoInteger (Symbol (), tf, SERIES_SYNCHRONIZED))

если не ошибаюсь, то в справке есть разбор скрипта для подкачки данных по всем ТФ и должно быть предупреждение, что нельзя так запрашивать исторические данные из индикатора по причине того, что индикатор работает асинхронно

да и BarsCalculated() рекомендуют использовать один раз после связывания хэндла


UPD: скрипт для подкачки истории и объяснение, почему это не работает в индикаторах: https://www.mql5.com/ru/docs/series/timeseries_access

 
Andrey Dik:

я делаю проверку синхронизированости данных на запрашиваемом старшем ТФ (М5) и готовность индикатора на нём, если не готово, то выход.

в итоге индикатор работает только 1 раз на открытии бара М1, а не на каждом тике:


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

А зачем такая проверка

//проверка готовности данных и индикатора на другом TF
if (SeriesInfoInteger (Symbol (), tf, SERIES_SYNCHRONIZED))
{
  if (iBars (Symbol (), tf) != BarsCalculated (handleFr)) return 0;
}
else return 0;

Проще будет без условия написать return 0; и все дела…

На каждом новом баре условие будет выполнено и независимо от синхронизации будет пересчёт всех баров. Вы написали необдуманный код и выдаёте это за баг терминала…

 
Ошибка при компиляции:
union X1 { //(1) нормально
        char x11[INT_MAX/2+1];
};
union X2 { //(2) Error: 'X2' - struct is too large
        char x21[INT_MAX/2+1];
        char x22[INT_MAX/2+1];
};
А какая принципиальная разница между (1) и (2) ?
 
union с единственным полем - странная штука.
 
Alexey Viktorov:

А зачем такая проверка

Проще будет без условия написать return 0; и все дела…

На каждом новом баре условие будет выполнено и независимо от синхронизации будет пересчёт всех баров. Вы написали необдуманный код и выдаёте это за баг терминала…

подумайте ещё раз.

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