Совместное использование CopyTime и CopyBuffer - как получить гарантированное соответствие данных?

 

Требуется  получить синхронизированные данные Время+Значение_индикатора+Значение_индикатора+...

Индикаторы могут использовать разные Symbol'ы

Вариант №1: 

Использую функции CopyTime и CopyBuffer в виде "по начальной и конечной датам требуемого интервала времени"

int  CopyTime(
   string           symbol_name,     // имя символа
   ENUM_TIMEFRAMES  timeframe,       // период
   datetime         start_time,      // с какой даты
   datetime         stop_time,       // по какую дату
   datetime         time_array[]     // массив для копирования времени открытия
   );


int  CopyBuffer(
   int       indicator_handle,     // handle индикатора
   int       buffer_num,           // номер буфера индикатора
   datetime  start_time,           // с какой даты
   datetime  stop_time,            // по какую дату
   double    buffer[]              // массив, куда будут скопированы данные
   );

При sym="AUSUSD", tf=PERIOD_D1, dt1=D'2010.03.09 00:00:00', dt2=D'2010.03.11 00:00:00',i_type=IND_MA следующий код

        CheckLoadHistory(sym,tf,dt1-100*PeriodSeconds(tf));
        int h=IndicatorCreate(sym,tf,i_type,ArraySize(params),params);
        datetime dates[];
        int dates_cnt=0;
        double data[];
        int data_cnt=0;

        data_cnt=CopyBuffer(h,buf,dt1,dt2,data);
        dates_cnt=CopyTime(sym,tf,dt1,dt2,dates);

на выходе дает data_cnt=2, dates_cnt=3,

Т.о. даже для одного Symbol возникает "нестыковка" по количеству баров и количеству данных

 

Вариант №2:

CopyTime и CopyBuffer вызываю в формате "по начальной дате и количеству требуемых элементов" для одного бара.

CheckLoadHistory(sym,tf,dt1-100*PeriodSeconds(tf));
int h=IndicatorCreate(sym,tf,i_type,ArraySize(params),params);
datetime dates[];
int dates_cnt=0;
double data[];
int data_cnt=0;
for (datetime d=dt1; d<dt2; d+=PeriodSeconds(tf)) {    
  while (!IsStopped() && !((CopyBuffer(h,buf,d,1,data)>0) && (CopyTime(sym,tf,d,1,dates)>0)))
    Sleep(100);
  if (d==dates[0]) {
  // Обрабатываем data[0] и dates[0]
  }
}

Проверил на конкретных индикаторах - данные возвращаются корректно. 

Возникают сомнения: успеет ли индикатор просчитать данные по всей истории прежде, чем сработает CopyBuffer (подозреваю, что эти процессы выполняются в разных thread) ?

Конструкция while (...) Sleep() как раз пытается решить этот вопрос. 

Это корректно?  

Документация по MQL5: Стандартные константы, перечисления и структуры / Торговые константы / Информация об исторических данных по инструменту
Документация по MQL5: Стандартные константы, перечисления и структуры / Торговые константы / Информация об исторических данных по инструменту
  • www.mql5.com
Стандартные константы, перечисления и структуры / Торговые константы / Информация об исторических данных по инструменту - Документация по MQL5
 
yu-sha писал(а) # :

При sym="AUSUSD", tf=PERIOD_D1, dt1=D'2010.03.09 00:00:00', dt2=D'2010.03.11 00:00:00',i_type=IND_MA следующий код

на выходе дает data_cnt=2, dates_cnt=3,

Т.о. даже для одного Symbol возникает "нестыковка" по количеству баров и количеству данных

Спасибо за сообщение об ошибке. Ошибка в CopyBuffer исправлена.

 

Вариант №2:

CopyTime и CopyBuffer вызываю в формате "по начальной дате и количеству требуемых элементов" для одного бара.

Проверил на конкретных индикаторах - данные возвращаются корректно. 

Возникают сомнения: успеет ли индикатор просчитать данные по всей истории прежде, чем сработает CopyBuffer (подозреваю, что эти процессы выполняются в разных thread) ?

Конструкция while (...) Sleep() как раз пытается решить этот вопрос. 

Это корректно?  

В экспертах и скриптах можно писать любые циклы и делать любые задержки выполнения, т.к. они выполняются в отдельном потоке. В кастомных индикаторах Sleep() игнорируется и самодельные задержки делать тоже не рекомендуется, т.к. в этом случае поток обработки общий для расчета всех индикаторов одного символа и для обработки самой истории по этому символу (втч обработка тиков).

Для контроля готовности данных индикатора можно использовать BarsCalculated().

 
antt писал(а) # :

Спасибо за сообщение об ошибке. Ошибка в CopyBuffer исправлена. 

Мое мнение - удобнее запрашивать данные CopyXXX в формате "с dt1 и до dt2", а не "по".  

"По" зацепит лишь один бар М1 из бара старшего ТФ в пограничных ситуациях. 

Исправлено: Хотя dt2-PeriodSecons(tf) меняет "по" на "до" ))

antt  писал(а) # :

В экспертах и скриптах можно писать любые циклы и делать любые задержки выполнения, т.к. они выполняются в отдельном потоке. В кастомных индикаторах Sleep() игнорируется и самодельные задержки делать тоже не рекомендуется, т.к. в этом случае поток обработки общий для расчета всех индикаторов одного символа и для обработки самой истории по этому символу (втч обработка тиков).

Для контроля готовности данных индикатора можно использовать BarsCalculated().

Спасибо за описание внутреннего устройства терминала - познавательно для оптимизации

BarsCalculated - именно то, что мне было нужно 

 

Появились какие-то "косяки" в CopyBuffer (билд 256)

Из эксперта вызываю 

int h1=iMA("AUDUSD",PERIOD_D1,21,0,MODE_SMA,PRICE_CLOSE);
values_cnt=CopyBuffer(h1,0,datetime(D'2010-03-12'),int(5),values);

Возвращает значения МА21 для 5ти баров, но не вперед, а назад: за 12.03, 11.03, 10.03, ... 

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