Создание объектов

Для создания объекта требуется некий минимальный набор атрибутов, общих для всех типов. Дополнительные свойства, специфические для каждого типа, можно задать или изменить позднее, уже у существующего объекта. К числу обязательных атрибутов относятся идентификатор графика, где следует создать объект, имя объекта, номер окна/подокна, а также две координаты для первой точки привязки: время и цена.

Несмотря на то, что существует группа объектов, позиционируемая в экранных координатах, при их создании все равно требуется передать два значения, как правило, нулевые, потому что они не имеют значения.

В общем виде прототип функции ObjectCreate — следующий:

bool ObjectCreate(long chartId, const string name, ENUM_OBJECT type, int window,
  datetime time1, double price1, datetime time2 = 0, double price2 = 0, ...)

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

Типы объектов для параметра type мы приводили в предыдущих разделах: это элементы перечисления ENUM_OBJECT.

Как мы знаем, нумерация окон/подокон для параметра window начинается с 0, что означает основное окно графика. Если указан больший индекс для подокна, оно должно существовать, так как в противном случае функция завершится с ошибкой и вернет false.

Напомним, что возвращенный признак успеха — true — означает лишь, что команда на создание объекта успешно помещена в очередь. Результат её выполнения сразу неизвестен — это оборотная "сторона медали" асинхронного вызова, который применен для повышения быстродействия.

Для проверки результата выполнения можно использовать функцию ObjectFind или любые ObjectGet-функции, запрашивающие свойства объекта. Но следует иметь в виду, что такие функции дожидаются выполнения всей очереди команд графика и только потом выдают актуальный результат (состояние объекта). Данный процесс может потребовать некоторого времени, в течение которого код MQL-программы будет приостановлен. Иными словами функции проверки состояния объектов являются синхронными, в отличие от функций создания и модификации.

Дополнительные точки привязки, начиная со второй, опциональные. Допустимое количество точек привязки — до 30-ти — предусмотрено для будущего использования, а в текущих типах объектов используется не более 5.

Важно отметить, что вызов функции ObjectCreate с именем уже существующего объекта просто меняет точку/точки привязки (если координаты были изменены по сравнению с предыдущим вызовом). Это удобно использовать для написания унифицированного кода без ветвления на условия по наличию или отсутствию объекта. Иными словами, безусловный вызов ObjectCreate гарантирует наличие объекта, если нам не важно, был ли он до того или нет. Однако есть и нюанс. Если при вызове ObjectCreate тип объекта или номер подокна отличаются от уже существующего объекта, то они остаются прежними. И важно, что ошибки не возникает.

При вызове ObjectCreate можно оставить все точки привязки со значениями по умолчанию (т.е. нулевыми), при условии что после этой инструкции будут вызваны ObjectSet-функции с соответствующими свойствами OBJPROP_TIME и OBJPROP_PRICE.

Порядок указания точек привязки может быть важен для некоторых типов объектов. Например, для каналов линейной регрессии OBJ_REGRESSION и стандартного отклонения OBJ_STDDEVCHANNEL обязательно должно выполняться условия time1 < time2. В противном случае канал не построится нормально, хотя объект будет создан без ошибок.

В качестве примера работы функции возьмем скрипт ObjectSimpleShowcase.mq5, который создает на последних барах графика несколько объектов разных типов, требующих единственной точки привязки.

Все примеры работы с объектами будут использовать заголовочный файл ObjectPrefix.mqh, в котором находится определение строки с общим префиксом для имен объектов. Таким образом, нам будет удобнее при необходимости очищать графики от "своих" объектов.

const string ObjNamePrefix = "ObjShow-";

В функции OnStart определен массив с типами объектов.

void OnStart()
{
   ENUM_OBJECT types[] =
   {
      // прямые линии
      OBJ_VLINEOBJ_HLINE,
      // метки (стрелки и другие знаки)
      OBJ_ARROW_THUMB_UPOBJ_ARROW_THUMB_DOWN,
      OBJ_ARROW_UPOBJ_ARROW_DOWN,
      OBJ_ARROW_STOPOBJ_ARROW_CHECK,
      OBJ_ARROW_LEFT_PRICEOBJ_ARROW_RIGHT_PRICE,
      OBJ_ARROW_BUYOBJ_ARROW_SELL,
      // OBJ_ARROW, // см. пример ObjectWingdings.mq5
      
      // текст
      OBJ_TEXT,
      // флажок события (как в календаре) у нижней границы окна
      OBJ_EVENT,
   };

Далее, в цикле по его элементам создаем объекты в основном окне, передавая время и цену закрытия i-го бара.

   const int n = ArraySize(types);
   for(int i = 0i < n; ++i)
   {
      ObjectCreate(0ObjNamePrefix + (string)iTime(_Symbol_Periodi), types[i],
         0iTime(_Symbol_Periodi), iClose(_Symbol_Periodi));
   }
   
   PrintFormat("%d objects of various types created"n);
}

Вот что может получиться в результате запуска скрипта.

Объекты простых типов в точках закрытия последних баров

Объекты простых типов в точках закрытия последних баров

Здесь специально выставлен режим отрисовки линий по цене Close и выведена сетка. Размер, цвет и прочие атрибуты объектов мы научимся настраивать позднее. В частности, точки привязки большинства значков расположены по умолчанию в середине верхней стороны, поэтому они визуально смещены под линию. Однако значок продажи выведен над линией, потому что в нем точка привязки всегда в середине нижней стороны.

Обратите внимание, что объекты, созданные программным путем по умолчанию не выводятся в список объектов в одноименном диалоге. Для того чтобы их увидеть там, следует нажать кнопку Все.