Синхронизация разных данных с разных таймфреймов при вызове из индикатора - страница 2

 
XXX:

только что запустил приаттаченный Movings.ex5

Супер, буду пилить. Благодарю за конструктив!

 
Sergey Savinkin:


Ситуация следующая: Индикатор запускается и пытается получить данные с большего таймфрейма того же символа. Я пока не поднимаю тему получения хэндлов индикаторов. Нужно хотя бы получить историю функциями Bars, iBarsShift и т.д. В момент запуска индикатора эти данные могут быть не рассчитаны. При этом использование стандартного примера проверки (из описания функции Bars()) не возможно по причине запрета на использование Sleep(). Индикатор не будет ждать подгрузки истории, чтобы не тормозить общий поток. Документация рекомендует в этом случае использовать проверку в процедурах-обработчиках событий (OnTimer, OnCalculate и т.д.) В нижеприведенном примере я так и сделал. Индикатор ждет  прихода следующего тика, а в это время подкачивается история. Но что делать, когда индикатор запускается в нерабочее время или же когда тики не возможно получить по другим причинам (например, по фьючерсам с истекшим сроком исполнения). Особенно часто такая проблема возникает при старте терминала. С приходом тика история подкачивается. А если тик не придет в разумное время? 
Вот тут и нужны какие-то костыли для решения этой проблемы. Как вариант - создать принудительный вызов процедур OnInit или OnCalculate из таймера (кстати, как это сделать?). Поделитесь опытом, как вы решали данную задачу. Текст шаблона индикатора с проверками прилагаю.
Прошу обратить особое внимание на его работу при старте терминала. И еще раз напоминаю - речь идет о получении данных индикатором, а не экспертом. Там проще.

Заранее спасибо.


Класс скачивает историю необходимого размера необходимого символа необходимого ТФ. Создает массивы (close, open, low, high, time) и поддерживает в актуальном состоянии.
Для этого необходимы только три строчки: создать экземпляр класса, в таймере необходимо вставить Timer(), а в OnCalculate или OnTick необходимо вставить NewTick(). Всё.

Пример индикатора с этим классом. В отдельном окне выводит цену close любого символа и тф.

#property indicator_separate_window
#property indicator_buffers 1
#property indicator_plots   1
//--- plot OtherTF
#property indicator_label1  "OtherTF"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrViolet
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1

#include  <LoadHistory.mqh>
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
input string NewSymbol="";          // Какой символ? Если пусто, то текущий
input ENUM_TIMEFRAMES TF=PERIOD_H1; // Какой ТаймФрейм отображаем?
input int N=10000;                  // Какой размер истории необходим?

CLoadHistory H(NewSymbol,TF,N);
double         OtherTFBuffer[];
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int OnInit()
  {
   SetIndexBuffer(0,OtherTFBuffer,INDICATOR_DATA);
   IndicatorSetString(INDICATOR_SHORTNAME,H.Symb()+"("+StringSubstr(EnumToString(TF),7)+")");
   ArrayInitialize(OtherTFBuffer,EMPTY_VALUE);
   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[])
  {
   H.NewTick();
   static int preN=0;
   if(H.Sync())
     {
      if(preN!=H.Size() || prev_calculated!=rates_total)
        {
         ArrayInitialize(OtherTFBuffer,EMPTY_VALUE);
         int total=ArrayCopy(OtherTFBuffer,H.close,rates_total-H.Size(),0,H.Size());
        }
      else OtherTFBuffer[rates_total-1]=H.close[H.Size()-1];
      preN=H.Size();
     }
   return(rates_total);
  }
//+------------------------------------------------------------------+
//| Timer function                                                   |
//+------------------------------------------------------------------+
void OnTimer()
  {
   H.Timer();
  }
Файлы:
 
Nikolai Semko:

Класс скачивает историю необходимого размера необходимого символа необходимого ТФ. Создает массивы (close, open, low, high, time) и поддерживает в актуальном состоянии.
Для этого необходимы только три строчки: создать экземпляр класса, в таймере необходимо вставить Timer(), а в OnCalculate или OnTick необходимо вставить NewTick(). Всё.

Нет, описываемую мной проблему он не решает, при запуске терминала с несколькими индикаторами, использующими одинаковые тайм-серии, точно так же зависает при загрузке истории с сообщением "Loading of history: 0.04%".

Допускаю, что мог ошибиться где-то при подключении (пришлось немного подправить класс для возможности использования массива объектов), но вряд ли. Еще проверю.

 
Andrey Khatimlianskii:

Нет, описываемую мной проблему он не решает, при запуске терминала с несколькими индикаторами, использующими одинаковые тайм-серии, точно так же зависает при загрузке истории с сообщением "Loading of history: 0.04%".

Допускаю, что мог ошибиться где-то при подключении (пришлось немного подправить класс для возможности использования массива объектов), но вряд ли. Еще проверю.

Зависание происходит только с несколькими индикаторами или с одним тоже?

 
Nikolai Semko:

Зависание происходит только с несколькими индикаторами или с одним тоже?

С одним тоже. Использующим 5 чужих тайм-серий.

 

У меня была ситуация, когда нужно было получать данные с других символов, а в общем случае и с разных таймфреймов в МТ5. Т.е. индикатор работает на eurusd и нужны значения rsi с audusd, cadnzd b и т.п. Это было полным кошмаром ( Задачу я решил, но не уверен, что смогу нормально вырезать решение из коммерческого индикатора.

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

Как раз на тему синхронизации.

Файлы:
GetHistory.mqh  10 kb
 
XXX:

только что запустил приаттаченный Movings.ex5

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

А сейчас перегрузил терминал и увидел вот такое: До перезагрузки:

До

После:

После


Явно что-то не так.

 
да, есть проблемы

1. в папке терминала  очистил все в symbols, ticks, history
2. перезапустил терминал
3. терминал начал грузить историю текущего графика, но такое ощущение, что как-то заблочил отрисовку индикатора, т.к. индикатору вернулись данные и они синхронизированы по барам, просто не отрисовываются

добавил в метод getSyncQuotes для проверки сколько баров доступно в истории и закончилась ли трансформация тиков в бары текущего таймфрейма

for (int k = 0; k < size; k++)
{
  indexes[k] = 0;
  items = MathMin(items, CopyRates(series[k].name, period, position, count, sources[k].rates));

Print(
series[k].name, " ", 
Bars(series[k].name, PERIOD_CURRENT), " ", 
SeriesInfoInteger(series[k].name, PERIOD_CURRENT, SERIES_SYNCHRONIZED));

  if (items < 1)
  {
    Print(
      "Synchronization : " + series[k].name + ", " + 
      "Position : " + IntegerToString(position) + ", " + 
      "Depth : " + IntegerToString(count));

    return 0;
  }
}

добавил в индикаторе проверку загружены ли индикаторные буферы 

void OnTimer()
{
Print("TIMER ", ArraySize(C0), " ", ArraySize(C1)); 
}

int OnCalculate(const int bars, const int counted, const int start, const double &price[])
{
Print("CALC ", ArraySize(C0), " ", ArraySize(C1));
}

и вот принты с результатами

2018.07.14 15:38:31.564 Movings (GOOG,H1)       CALC 208 208                                          // first call for OnCalculate, number of bars in indicator buffer is 208
2018.07.14 15:38:31.571 Movings (GOOG,H1)       AMZN 0 0                                              // AMZN is not synced
2018.07.14 15:38:31.571 Movings (GOOG,H1)       Synchronization : AMZN, Position : 0, Depth : 1500    // wait for sync on the next tick
2018.07.14 15:38:31.670 Movings (GOOG,H1)       CALC 417 417                                          // OnCalculate called second time, number of bars in indicator buffer is 417
2018.07.14 15:38:31.670 Movings (GOOG,H1)       AMZN 208 1                                            
2018.07.14 15:38:31.670 Movings (GOOG,H1)       GOOG 417 1                                            // AMZN and GOOG are synced and have 208 & 417 bars respectively
2018.07.14 15:38:31.733 Movings (GOOG,H1)       CALC 627 627                                          
2018.07.14 15:38:31.733 Movings (GOOG,H1)       AMZN 208 1
2018.07.14 15:38:31.733 Movings (GOOG,H1)       GOOG 627 1
2018.07.14 15:38:31.794 Movings (GOOG,H1)       CALC 837 837
2018.07.14 15:38:31.794 Movings (GOOG,H1)       AMZN 208 1
2018.07.14 15:38:31.794 Movings (GOOG,H1)       GOOG 837 1
2018.07.14 15:38:31.868 Movings (GOOG,H1)       CALC 1046 1046
2018.07.14 15:38:31.868 Movings (GOOG,H1)       AMZN 208 1
2018.07.14 15:38:31.868 Movings (GOOG,H1)       GOOG 1046 1
2018.07.14 15:38:31.964 Movings (GOOG,H1)       CALC 1254 1254
2018.07.14 15:38:31.964 Movings (GOOG,H1)       AMZN 208 1
2018.07.14 15:38:31.964 Movings (GOOG,H1)       GOOG 1254 1
2018.07.14 15:38:32.044 Movings (GOOG,H1)       CALC 1464 1464
2018.07.14 15:38:32.044 Movings (GOOG,H1)       AMZN 208 1
2018.07.14 15:38:32.044 Movings (GOOG,H1)       GOOG 1464 1
2018.07.14 15:38:32.114 Movings (GOOG,H1)       CALC 1674 1674
2018.07.14 15:38:32.114 Movings (GOOG,H1)       AMZN 208 1
2018.07.14 15:38:32.114 Movings (GOOG,H1)       GOOG 1674 1
2018.07.14 15:38:32.209 Movings (GOOG,H1)       CALC 1882 1882
2018.07.14 15:38:32.209 Movings (GOOG,H1)       AMZN 208 1
2018.07.14 15:38:32.209 Movings (GOOG,H1)       GOOG 1882 1
2018.07.14 15:38:32.282 Movings (GOOG,H1)       CALC 2092 2092
2018.07.14 15:38:32.282 Movings (GOOG,H1)       AMZN 208 1
2018.07.14 15:38:32.282 Movings (GOOG,H1)       GOOG 2092 1
2018.07.14 15:38:32.358 Movings (GOOG,H1)       CALC 2302 2302
2018.07.14 15:38:32.358 Movings (GOOG,H1)       AMZN 208 1
2018.07.14 15:38:32.358 Movings (GOOG,H1)       GOOG 2302 1
2018.07.14 15:38:32.430 Movings (GOOG,H1)       CALC 2512 2512
2018.07.14 15:38:32.430 Movings (GOOG,H1)       AMZN 208 1
2018.07.14 15:38:32.430 Movings (GOOG,H1)       GOOG 2512 1
2018.07.14 15:38:32.518 Movings (GOOG,H1)       CALC 2881 2881
2018.07.14 15:38:32.518 Movings (GOOG,H1)       AMZN 208 1
2018.07.14 15:38:32.518 Movings (GOOG,H1)       GOOG 2881 1
2018.07.14 15:38:32.559 Movings (GOOG,H1)       TIMER 2881 2881                                     // the only call of OnTimer is here, indicator thinks that history is ready and DISABLES it	
2018.07.14 15:38:32.559 Movings (GOOG,H1)       AMZN 208 1
2018.07.14 15:38:32.559 Movings (GOOG,H1)       GOOG 2881 1
2018.07.14 15:38:32.599 Movings (GOOG,H1)       CALC 3247 3247
2018.07.14 15:38:32.599 Movings (GOOG,H1)       AMZN 208 1
2018.07.14 15:38:32.599 Movings (GOOG,H1)       GOOG 3247 1
2018.07.14 15:38:32.695 Movings (GOOG,H1)       CALC 3625 3625
2018.07.14 15:38:32.699 Movings (GOOG,H1)       AMZN 627 1
2018.07.14 15:38:32.699 Movings (GOOG,H1)       GOOG 3625 1
2018.07.14 15:38:32.827 Movings (GOOG,H1)       CALC 3968 3968
2018.07.14 15:38:32.857 Movings (GOOG,H1)       AMZN 0 1
2018.07.14 15:38:32.857 Movings (GOOG,H1)       Synchronization : AMZN, Position : 0, Depth : 2     // new bars has come, so we sync only 2 last bars instead of 1500
2018.07.14 15:38:33.058 Movings (GOOG,H1)       CALC 4299 4299
2018.07.14 15:38:33.058 Movings (GOOG,H1)       AMZN 1255 1
2018.07.14 15:38:33.058 Movings (GOOG,H1)       GOOG 4299 1
2018.07.14 15:38:33.176 Movings (GOOG,H1)       CALC 4652 4652
2018.07.14 15:38:33.180 Movings (GOOG,H1)       AMZN 0 1                                            // new bar for AMZN is not ready, wait for syncing
2018.07.14 15:38:33.180 Movings (GOOG,H1)       Synchronization : AMZN, Position : 0, Depth : 2
2018.07.14 15:38:33.326 Movings (GOOG,H1)       CALC 5090 5090
2018.07.14 15:38:33.341 Movings (GOOG,H1)       AMZN 0 1
2018.07.14 15:38:33.341 Movings (GOOG,H1)       Synchronization : AMZN, Position : 0, Depth : 2
2018.07.14 15:38:33.640 Movings (GOOG,H1)       CALC 5771 5771
2018.07.14 15:38:33.640 Movings (GOOG,H1)       AMZN 2849 1
2018.07.14 15:38:33.640 Movings (GOOG,H1)       GOOG 5771 1
2018.07.14 15:38:34.006 Movings (GOOG,H1)       CALC 6454 6454
2018.07.14 15:38:34.006 Movings (GOOG,H1)       AMZN 3624 1
2018.07.14 15:38:34.006 Movings (GOOG,H1)       GOOG 6454 1
2018.07.14 15:38:34.620 Movings (GOOG,H1)       CALC 7134 7134
2018.07.14 15:38:34.620 Movings (GOOG,H1)       AMZN 4972 1
2018.07.14 15:38:34.620 Movings (GOOG,H1)       GOOG 7134 1
2018.07.14 15:38:35.003 Movings (GOOG,H1)       CALC 7715 7715                                       
2018.07.14 15:38:35.003 Movings (GOOG,H1)       AMZN 5024 1
2018.07.14 15:38:35.003 Movings (GOOG,H1)       GOOG 7715 1

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


 
что мы имеем, индикаторы и основной чарт грузятся асинхронно, но отрисовываются синхронно только после основного чарта
проверим наше предположение по костылю для терминала о том, как синхронизировать индикаторы и основной чарт
добавляем такой костыль в OnTimer
int iLastBars = 0;

void OnTimer()
{
  if (History(iSeries) && iLastBars == ArraySize(C0)) 
  {
    EventKillTimer();
  }

  Print(iLastBars, " = ", ArraySize(C0));  

  iLastBars = ArraySize(C0);
}
видим нормальную отрисовку чарта и такие принты
2018.07.14 16:03:02.081 Movings (GOOG,H1)       Synchronization : AMZN, Position : 0, Depth : 1500
2018.07.14 16:03:02.140 Movings (GOOG,H1)       Synchronization : AMZN, Position : 0, Depth : 2
2018.07.14 16:03:03.077 Movings (GOOG,H1)       0 = 3625
2018.07.14 16:03:03.190 Movings (GOOG,H1)       Synchronization : AMZN, Position : 0, Depth : 2
2018.07.14 16:03:03.384 Movings (GOOG,H1)       Synchronization : AMZN, Position : 0, Depth : 2
2018.07.14 16:03:04.124 Movings (GOOG,H1)       3625 = 6454
2018.07.14 16:03:05.077 Movings (GOOG,H1)       6454 = 7715
2018.07.14 16:03:06.076 Movings (GOOG,H1)       7715 = 7715
уииии, заработало!!!
Файлы:
Movings.mq5  8 kb
 
XXX:

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


Возможно, из-за того, что я поменял в двух местах PERIOD_CURRENT на PERID_M1?

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