- Главное событие экспертов: OnTick
- Основные принципы и понятия: ордер, сделка, позиция
- Типы торговых операций
- Типы ордеров
- Режимы исполнения ордеров по цене и объемам
- Сроки действия отложенных ордеров
- Расчет залога для будущего ордера: OrderCalcMargin
- Оценка прибыли торговой операции: OrderCalcProfit
- Структура торгового запроса MqlTradeRequest
- Структура проверки запроса MqlTradeCheckResult
- Проверка корректности запроса: OrderCheck
- Результат отправки запроса: структура MqlTradeResult
- Отправка торгового запроса: OrderSend и OrderSendAsync
- Совершение покупки или продажи
- Модификация уровней Stop Loss и/или Take Profit позиции
- Трейлинг стоп
- Полное и частичное закрытие позиции
- Полное и частичное закрытие встречных позиций (хедж)
- Установка отложенного ордера
- Модификация отложенного ордера
- Удаление отложенного ордера
- Получение списка действующих ордеров
- Свойства ордеров (действующих и в истории)
- Функции для чтения свойств действующих ордеров
- Отбор ордеров по свойствам
- Получение списка позиций
- Свойства позиций
- Функции для чтения свойств позиций
- Свойства сделок
- Выборка ордеров и сделок из истории
- Функции для чтения свойств ордеров из истории
- Функции для чтения свойств сделок из истории
- Типы торговых транзакций
- Событие OnTradeTransaction
- Синхронные и асинхронные запросы
- Событие OnTrade
- Контроль за изменениями торгового окружения
- Особенности создания мультисимвольных экспертов
- Ограничения и преимущества экспертов
- Создание заготовки эксперта в Мастере MQL
Функции для чтения свойств действующих ордеров
Наборы функций, с помощью которых можно получить значения всех свойств ордера, отличаются для активных ордеров и ордеров из истории. В данном разделе описаны функции для чтения свойств активных ордеров. Функции для доступа к свойствам ордеров в истории смотрите в соответствующем разделе.
Целочисленные свойства можно прочитать с помощью функции OrderGetInteger, имеющей 2 формы: первая возвращает непосредственно значение свойства, вторая — логический признак успеха (true) или ошибки (false), а значением свойства заполняется переданный по ссылке второй параметр.
long OrderGetInteger(ENUM_ORDER_PROPERTY_INTEGER property)
bool OrderGetInteger(ENUM_ORDER_PROPERTY_INTEGER property, long &value)
Обе функции позволяют получить запрошенное свойство ордера совместимого с целым типа (datetime, long/ulong или перечисление). Хотя в прототипе упоминается long, с технической точки зрения значение хранится как 8-байтовая ячейка, которую можно приводить к совместимым типам без какой-либо конвертации внутреннего представления, в частности, к ulong, который используется для всех тикетов.
Аналогичная пара функций предназначена для свойств вещественного типа double.
double OrderGetDouble(ENUM_ORDER_PROPERTY_DOUBLE property)
bool OrderGetDouble(ENUM_ORDER_PROPERTY_DOUBLE property, double &value)
Наконец, строковые свойства доступны посредством пары функций OrderGetString.
string OrderGetString(ENUM_ORDER_PROPERTY_STRING property)
bool OrderGetString(ENUM_ORDER_PROPERTY_STRING property, string &value)
Все функции принимают в качестве первого параметра идентификатор интересующего нас свойства — это должен быть элемент одного из перечислений ENUM_ORDER_PROPERTY_INTEGER, ENUM_ORDER_PROPERTY_DOUBLE, ENUM_ORDER_PROPERTY_STRING, рассмотренных в предыдущем разделе.
Напомним, что перед вызовом любой из предыдущих функций необходимо предварительно выделить ордер с помощью OrderSelect или OrderGetTicket.
Для чтения всех свойств конкретного ордера разработаем класс OrderMonitor (OrderMonitor.mqh), действующий по такому же принципу, как уже знакомые нам мониторы символов (SymbolMonitor.mqh) или торгового счета (AccountMonitor.mqh).
Напомним, что эти и другие классы-мониторы, рассмотренные в книге, предлагают унифицированный способ анализа свойств за счет перегруженных версий виртуальных get-методов.
Несколько забегая вперед, скажем, что сделки и позиции имеют такую же группировку свойств по трём основным типам значений, и для них нам также потребуется реализовать мониторы. В связи с этим имеет смысл выделить общий алгоритм в базовый абстрактный класс MonitorInterface (TradeBaseMonitor.mqh). Он является шаблоном, три параметра которого предназначены для указания типов конкретных перечислений: для целочисленных (I), вещественных (D) и строковых (S) групп свойств.
#include <MQL5Book/EnumToArray.mqh>
|
Из-за того, что ордер (или сделка, или позиция) могут быть не найдены в торговом окружении по разным причинам, в классе зарезервирована переменная ready, в которую производные классы должны будут записать признак успешной инициализации, то есть выбора объекта для чтения его свойств.
Несколько чисто виртуальных методов декларируют доступ к свойствам соответствующих типов.
virtual long get(const I property) const = 0;
|
В первых трех методах тип свойства задан одним из шаблонных параметров, а во вторых трех — вторым параметром самого метода: это требуется, потому что последние методы принимают первым параметром не константы конкретного перечисления, а просто целое число. С одной стороны это удобно для сквозной нумерации идентификаторов (константы перечислений трех типов не пересекаются). Но с другой стороны нам нужен другой источник определения типа значения — напомним, что тип возвращаемый функцией/методом не участвует в процессе выбора подходящей перегрузки.
Такой подход позволяет получать свойства, руководствуясь различной исходной информацией, доступной в вызывающем коде. Далее мы создадим классы на основе OrderMonitor (а также будущих DealMonitor и PositionMonitor) для отбора объектов по набору произвольных условий, и там все эти методы будут востребованы.
Довольно часто в программах требуется получить строковое представление любых свойств, например, для вывода в журнал. В новых мониторах это поручено методам stringify. Очевидно, что они получают значения запрашиваемых свойств через вызовы вышеупомянутых методов get.
virtual string stringify(const long v, const I property) const = 0;
|
Единственный из этих методов, который не получил реализации, это первый вариант stringify для типа long. Это связано с тем, что в группе целочисленных свойств, как мы видели в предыдущем разделе, перемешаны свойства фактически разных прикладных типов — дата и время, перечисления, целые числа. Поэтому их преобразование в понятные строки смогут предоставить только производные классы. Данная ситуация является общей для всех торговых сущностей — не только ордеров, но и сделок, и позиций, свойства которых мы рассмотрим позднее.
Когда в целочисленном свойстве содержится элемент некоего перечисления (например, ENUM_ORDER_TYPE, ORDER_TYPE_FILLING и т.д.), для его преобразования в строку следует применять функцию EnumToString. Эту задачу решает вспомогательный метод enumstr — скоро мы увидим его широкое использования в классах конкретных мониторов, начиная с OrderMonitor через пару абзацев.
template<typename E>
|
Для вывода в журнал всех свойств конкретного типа создан метод list2log, использующий в цикле stringify.
template<typename E>
|
Наконец, для упрощения вывода в журнал свойств всех трех групп предоставлен метод print, вызывающий list2log трижды — для каждой группы свойств.
virtual void print() const
|
Имея в своем распоряжении базовый шаблонный класс MonitorInterface, опишем OrderMonitorInterface, где укажем конкретные типы перечислений для ордеров из предыдущего раздела и предоставим реализацию stringify для целочисленных свойств ордеров.
class OrderMonitorInterface:
|
Макрос STR_TIME_MSC для отображения времени с учетом миллисекунд определен следующим образом:
#define STR_TIME_MSC(T) (TimeToString((T) / 1000, TIME_DATE | TIME_SECONDS) \
|
Теперь мы готовы описать окончательный класс для чтения свойств любого ордера — OrderMonitor, наследник OrderMonitorInterface. В конструктор передается тикет ордера, и тот выбирается в торговом окружении с помощью OrderSelect.
class OrderMonitor: public OrderMonitorInterface
|
Главная рабочая часть монитора состоит из переопределений виртуальных функций для чтения свойств. Здесь мы видим обращение к функциям OrderGetInteger, OrderGetDouble, OrderGetString.
virtual long get(const ENUM_ORDER_PROPERTY_INTEGER property) const override
|
Данный фрагмент кода приведен с некоторыми сокращениями: из него убраны операторы для работы с ордерами в истории. После того как мы познакомимся с этим аспектом в последующих разделах, OrderMonitor будет показан в полном виде.
Важно отметить, что объект монитора не хранит в себе копии свойств. Поэтому доступ к методам get должен осуществляться сразу после создания объекта и, соответственно, вызова OrderSelect. Для чтения свойств в более поздний период потребуется вновь выделить ордер во внутреннем кеше MQL-программы, например, вызвав метод refresh.
void refresh()
|
Протестируем работу OrderMonitor, добавив его в эксперт MarketOrderSend.mq5. Новая версия с именем MarketOrderSendMonitor.mq5 подключает файл OrderMonitor.mqh директивой #include, а в теле функции OnTimer (в блоке успешного подтверждения открытия позиции по ордеру) создает объект монитора и вызывает его метод print.
#include <MQL5Book/OrderMonitor.mqh>
|
В журнале мы должны увидеть новые строки, содержащие все свойства ордера.
OK Order: #=1287846602
|
В четвертой строке начинается вывод из метода print, который включает полное название объекта монитора MonitorInterface вместе с типами-параметрами (в данном случае, тройка ENUM_ORDER_PROPERTY) и далее все свойства конкретного ордера.
Однако печать свойств — не самое интересное действие, которое может обеспечить монитор. Гораздо более востребованной в экспертах является задача отбора ордеров по условиям (значениям произвольных свойств). Используя монитор как вспомогательный инструмент, создадим механизм фильтрации ордеров, по аналогии с тем, что мы делали для символов: SymbolFilter.mqh.