Приведу один метод (использованный в SOH), как получить данные баров вышестоящего таймфрейма H1 в "любом" нижестоящем.
Для хранения OHLC бров будем использовать глобальные переменные типа DoubleList
Доступ из кода индикатора к часовым данным будет очень прост:
O[0..x] - Цена открытия последнего часа [0] и предшествующих
H[0..x] - Цена максимальная последнего часа [0] и предшествующих
L[0..x] - Цена минимальная последнего часа [0] и предшествующих
C[0..x] - Цена закрытия последнего часа [0] и предшествующих
Под последним часом понимается не текущий (формирующийся, незаконченный) бар, а предыдущий полностью законченный бар.
Open - Цена открытия текущего часа
Min - Цена минимальная текущего часа (может изменятся, т.к. текущий час формируется)
Max - Цена максимальная текущего часа (может изменятся, т.к. текущий час формируется)
Как видно выше, Close текущего часа нет, т.к. он ещё не определен в текущем часе, но доступен в качестве Input.Close[0] входного ряда.
Вообщем-то и Min, Max могут изменится к окончанию часа. Но если вдруг потребуется динамически отрисовывать индикатор по текущему часу то это тоже доступно через данные глобальные переменные.
В функции Initialize() добавляем глобальные переменные:
Код: Выделить всё
// для сохранения списков значений OHLC часовых баров
AddGlobalVariable("O", Types.DoubleList);
AddGlobalVariable("H", Types.DoubleList);
AddGlobalVariable("L", Types.DoubleList);
AddGlobalVariable("C", Types.DoubleList);
// для хранения минимальной и максимальной цены текущего часа
AddGlobalVariable("Min", Types.Double, 999999999);
AddGlobalVariable("Max", Types.Double, 0.0);
// для хранения цены открытия текущего часа
AddGlobalVariable("Open", Types.Double, 0.0);
в самом начале функции Evaluate() добавляем следующий код:
Код: Выделить всё
// закончился часовой бар и начался новый
// сохраняем часовые данные в списках
if (BarTime(0).Hours != BarTime(1).Hours)
{
// сохраняем данные часового бара
O.Insert(0, Open);
H.Insert(0, Max);
L.Insert(0, Min);
C.Insert(0, Input.Close[1]);
// лишнее удаляем
var CN = O.Count;
if (CN > Period)
{
O.RemoveAt(CN - 1);
H.RemoveAt(CN - 1);
L.RemoveAt(CN - 1);
C.RemoveAt(CN - 1);
}
// новый бар
Min = Double.MaxValue;
Max = 0.0;
Open = Input.Open[0];
}
if (Input.Low[0] < Min) Min = Input.Low[0];
if (Input.High[0] > Max) Max = Input.High[0];
Здесь неописанная переменная (или чаще параметр) "Period", которая ограничивает наши DoubleList по размерности, например это может быть период для H1 заданный в параметрах индикатора. Вообщем, он определяет максимально доступную длину истории для хранения наших данных от H1, при превышении которой происходит удаление последнего элемента.
После данного кода Evaluate() можно использовать ряды OHLC и переменные для текущего часа.
Ещё возможно изменить условие, которое описывает момент начала нового часового бара.
Код: Выделить всё
if (BarTime(0).Hours != BarTime(1).Hours)
см. TimeSpan (MSDN)
Например, для получения данных дневного таймфрема условие можно изменить на такое:
Код: Выделить всё
if (BarDate(0).Day != BarDate(1).Day)
см. DateTime (MSDN)
В данном примере объёмы не сохраняются, но ничего мешает завести ещё 3 глобальные переменные и сохранять Volume, VolumeBid, VolumeAsk.
Надеюсь, что кому-то поможет данный пример...
Если у кого-то есть собственные наработки или замечания буду рад увидеть