Прокрутка графика по оси времени

Пользователям MetaTrader 5 известна панель быстрой навигации по графику, которая открывается по двойному нажатию мыши в левом углу шкалы времени или по нажатию клавиш Пробел или Ввод. Аналогичная возможность доступна и программно — с помощью функции ChartNavigate.

bool ChartNavigate(long chartId, ENUM_CHART_POSITION position, int shift = 0)

Функция осуществляет сдвиг графика chartId на указанное количество баров относительно предопределенной позиции графика, заданной параметром position. Он имеет тип перечисления ENUM_CHART_POSITION со следующими элементами.

Идентификатор

Описание

CHART_BEGIN

Начало графика (самые старые цены)

CHART_CURRENT_POS

Текущая позиция

CHART_END

Конец графика (самые свежие цены)

Параметр shift задает количество баров, на которое необходимо сместить график. Положительное значение смещает график вправо (к концу), отрицательное значение смещает график влево (к началу).

Функция возвращает true в случае успеха или false в результате ошибки.

Для проверки работы функции создадим простой скрипт ChartNavigate.mq5. С помощью входных переменных пользователь может выбрать точку отсчета и сдвиг в барах.

#property script_show_inputs
 
input ENUM_CHART_POSITION Position = CHART_CURRENT_POS;
input int Shift = 0;
   
void OnStart()
{
   ChartSetInteger(0CHART_AUTOSCROLLfalse);
   const int start = (int)ChartGetInteger(0CHART_FIRST_VISIBLE_BAR);
   ChartNavigate(0PositionShift);
   const int stop = (int)ChartGetInteger(0CHART_FIRST_VISIBLE_BAR);
   Print("Moved by: "stop - start", from "start" to "stop);
}

В журнал выводится номер первого видимого бара до и после перемещения.

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

void OnStart()
{
   datetime bar = 0// текущая позиция (время первого видимого бара)
  
   const string namePosition = __FILE__// имя глобальной переменной
  
   ChartSetInteger(0CHART_AUTOSCROLLfalse); // отключаем автопрокрутку
  
   while(!IsStopped())
   {
      const bool active = ChartGetInteger(0CHART_BRING_TO_TOP);
      const int move = (int)ChartGetInteger(0CHART_FIRST_VISIBLE_BAR);
   
      // активный график является ведущим, а остальные - ведомыми
      if(active)
      {
         const datetime first = iTime(_Symbol_Periodmove);
         if(first != bar)
         {
            // если позиция изменилась, сохраняем её в глобальной переменной
            bar = first;
            GlobalVariableSet(namePositionbar);
            Comment("Chart "ChartID(), " scrolled to "bar);
         }
      }
      else
      {
         const datetime b = (datetime)GlobalVariableGet(namePosition);
      
         if(b != bar)
         {
            // если изменилось значение глобальной переменной, подстраиваем позицию
            bar = b;
            const int difference = move - iBarShift(_Symbol_Periodbar);
            ChartNavigate(0CHART_CURRENT_POSdifference);
            Comment("Chart "ChartID(), " forced to "bar);
         }
      }
    
      Sleep(250);
   }
   Comment("");
}

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

На следующем изображении показан результат синхронизации графиков H1 и M15 для EURUSD.

Пример работы скрипта синхронизации позиции графиков

Пример работы скрипта синхронизации позиции графиков

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