Русский

Справочник MQL4 Доступ к таймсериям и индикаторам

Доступ к таймсериям и данным индикаторов

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

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

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

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

Если запрашивается информация с другого графика (название инструмента и/или значение таймфрейма отличаются от текущих), то возможна ситуация, что в клиентском терминале не открыт соответствующий график и необходимые данные должны быть запрошены у сервера. В этом случае в переменную _Last_error будет помещена ошибка ERR_HISTORY_WILL_UPDATED (4066 - запрошенные исторические данные в состоянии обновления) и необходимо через некоторое время повторить попытку запроса (см. пример ArrayCopySeries()).

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

Направление индексации в таймсерии и в обычном массиве

Исторически сложилось так, что доступ к данным в ценовом массиве производился с конца данных. Физически новые данные всегда дописываются в конец массива, но индекс этого массива всегда равен нулю. Индекс 0 в массиве-таймсерии означает данные текущего бара, то есть бара, который соответствует незавершенному промежутку времени на данном таймфрейме.

Таймфрейм – период времени, в течение которого формируется один ценовой бар. Существует несколько предопределенных стандартных таймфреймов.

Функция

Действие

SeriesInfoInteger

Возвращает информацию о состоянии исторических данных

RefreshRates

Осуществляет обновление данных в предопределенных переменных и массивах-таймсериях

CopyRates

Получает в массив исторические данные структуры Rates для указанных символа и периода

CopyTime

Получает в массив исторические данные по времени открытия баров по соответствующим символу и периоду

CopyOpen

Получает в массив исторические данные по цене открытия баров по соответствующим символу и периоду

CopyHigh

Получает в массив исторические данные по максимальной цене баров по соответствующим символу и периоду

CopyLow

Получает в массив исторические данные по минимальной цене баров по соответствующим символу и периоду

CopyClose

Получает в массив исторические данные по цене закрытия баров по соответствующим символу и периоду

CopyTickVolume

Получает в массив исторические данные по тиковым объемам для соответствующих символа и периода

Bars

Возвращает количество баров в истории по соответствующему символу периоду

iBars

Возвращает количество баров в истории по соответствующему символу и периоду

iBarShift

Возвращает смещение бара, которому принадлежит указанное время

iClose

Возвращает значение цены закрытия бара соответствующего графика

iHigh

Возвращает значение максимальной цены бара соответствующего графика

iHighest

Возвращает индекс наибольшего найденного значения соответствующего графика

iLow

Возвращает значение минимальной цены бара соответствующего графика

iLowest

Возвращает индекс наименьшего найденного значения соответствующего графика

iOpen

Возвращает значение цены открытия бара соответствующего графика

iTime

Возвращает значение времени открытия бара соответствующего графика

iVolume

Возвращает значение тикового объема бара соответствующего графика

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

   datetime TimeAsSeries[];
//--- установим доступ к массиву как к таймсерии
   ArraySetAsSeries(TimeAsSeries,true);
   ResetLastError();
   int copied=CopyTime(NULL,0,0,10,TimeAsSeries);
   if(copied<=0)
     {
      Print("Не удалось скопировать время открытия для последних 10 баров");
      return;
     }
   Print("TimeCurrent = ",TimeCurrent());
   Print("ArraySize(Time) = ",ArraySize(TimeAsSeries));
   int size=ArraySize(TimeAsSeries);
   for(int i=0;i<size;i++)
     {
      Print("TimeAsSeries["+i+"] = ",TimeAsSeries[i]);
     }
 
   datetime ArrayNotSeries[];
   ArraySetAsSeries(ArrayNotSeries,false);
   ResetLastError();
   copied=CopyTime(NULL,0,0,10,ArrayNotSeries);
   if(copied<=0)
     {
      Print("Не удалось скопировать время открытия для последних 10 баров");
      return;
     }   
   size=ArraySize(ArrayNotSeries);
   for(int i=size-1;i>=0;i--)
     {
      Print("ArrayNotSeries["+i+"] = ",ArrayNotSeries[i]);
     }

В результате будет произведен вывод подобный этому:

TimeCurrent = 2009.06.11 14:16:23
ArraySize(Time) = 10
TimeAsSeries[0] = 2009.06.11 14:00:00
TimeAsSeries[1] = 2009.06.11 13:00:00
TimeAsSeries[2] = 2009.06.11 12:00:00
TimeAsSeries[3] = 2009.06.11 11:00:00
TimeAsSeries[4] = 2009.06.11 10:00:00
TimeAsSeries[5] = 2009.06.11 09:00:00
TimeAsSeries[6] = 2009.06.11 08:00:00
TimeAsSeries[7] = 2009.06.11 07:00:00
TimeAsSeries[8] = 2009.06.11 06:00:00
TimeAsSeries[9] = 2009.06.11 05:00:00
 
ArrayNotSeries[9] = 2009.06.11 14:00:00
ArrayNotSeries[8] = 2009.06.11 13:00:00
ArrayNotSeries[7] = 2009.06.11 12:00:00
ArrayNotSeries[6] = 2009.06.11 11:00:00
ArrayNotSeries[5] = 2009.06.11 10:00:00
ArrayNotSeries[4] = 2009.06.11 09:00:00
ArrayNotSeries[3] = 2009.06.11 08:00:00
ArrayNotSeries[2] = 2009.06.11 07:00:00
ArrayNotSeries[1] = 2009.06.11 06:00:00
ArrayNotSeries[0] = 2009.06.11 05:00:00

Как видно из результатов вывода, для массива TimeAsSeries с ростом индекса уменьшается значение времени, находящегося под этим индексом, то есть мы продвигаемся от настоящего к прошлому. Для обычного массива ArrayNotSeries все наоборот - с ростом индекса мы двигаемся из прошлого к настоящему.

Смотри также

ArrayIsDynamic, ArrayGetAsSeries, ArraySetAsSeries, ArrayIsSeries