- Главное событие экспертов: OnTick
- Основные принципы и понятия: ордер, сделка, позиция
- Типы торговых операций
- Типы ордеров
- Режимы исполнения ордеров по цене и объемам
- Сроки действия отложенных ордеров
- Расчет залога для будущего ордера: OrderCalcMargin
- Оценка прибыли торговой операции: OrderCalcProfit
- Структура торгового запроса MqlTradeRequest
- Структура проверки запроса MqlTradeCheckResult
- Проверка корректности запроса: OrderCheck
- Результат отправки запроса: структура MqlTradeResult
- Отправка торгового запроса: OrderSend и OrderSendAsync
- Совершение покупки или продажи
- Модификация уровней Stop Loss и/или Take Profit позиции
- Трейлинг стоп
- Полное и частичное закрытие позиции
- Полное и частичное закрытие встречных позиций (хедж)
- Установка отложенного ордера
- Модификация отложенного ордера
- Удаление отложенного ордера
- Получение списка действующих ордеров
- Свойства ордеров (действующих и в истории)
- Функции для чтения свойств действующих ордеров
- Отбор ордеров по свойствам
- Получение списка позиций
- Свойства позиций
- Функции для чтения свойств позиций
- Свойства сделок
- Выборка ордеров и сделок из истории
- Функции для чтения свойств ордеров из истории
- Функции для чтения свойств сделок из истории
- Типы торговых транзакций
- Событие OnTradeTransaction
- Синхронные и асинхронные запросы
- Событие OnTrade
- Контроль за изменениями торгового окружения
- Особенности создания мультисимвольных экспертов
- Ограничения и преимущества экспертов
- Создание заготовки эксперта в Мастере MQL
Функции для чтения свойств ордеров из истории
Функции чтения свойств исторических ордеров разделены на 3 группы по базовому типу значений свойств, в соответствии с делением идентификаторов доступных свойств по трем перечислениям ENUM_ORDER_PROPERTY_INTEGER, ENUM_ORDER_PROPERTY_DOUBLE и ENUM_ORDER_PROPERTY_STRING, рассмотренных ранее в отдельном разделе при изучении действующих ордеров.
Перед вызовом этих функций нужно тем или иным способом выбрать соответствующий набор тикетов в истории.
Если попытаться читать свойства ордера или сделки, тикеты которых не попали в выбранный контекст истории, среда может сгенерировать ошибку WRONG_INTERNAL_PARAMETER (4002), доступную для анализа через _LastError.
Для каждого базового типа свойств существует 2 формы функции: одна непосредственно возвращает значение запрашиваемого свойства, вторая — записывает его в передаваемый по ссылке параметр, и возвращает признак успеха (true) или ошибки (false).
Для целочисленных и совместимых типов (datetime, перечисления) свойств выделена функция HistoryOrderGetInteger.
long HistoryOrderGetInteger(ulong ticket, ENUM_ORDER_PROPERTY_INTEGER property)
bool HistoryOrderGetInteger(ulong ticket, ENUM_ORDER_PROPERTY_INTEGER property,
long &value)
Функция позволяет узнать свойство property ордера из выбранной истории по номеру его тикета.
Для вещественных свойств предназначена функция HistoryOrderGetDouble.
double HistoryOrderGetDouble(ulong ticket, ENUM_ORDER_PROPERTY_DOUBLE property)
bool HistoryOrderGetDouble(ulong ticket, ENUM_ORDER_PROPERTY_DOUBLE property,
double &value)
Наконец строковые свойства можно прочитать с помощью HistoryOrderGetString.
string HistoryOrderGetString(ulong ticket, ENUM_ORDER_PROPERTY_STRING property)
bool HistoryOrderGetString(ulong ticket, ENUM_ORDER_PROPERTY_STRING property,
string &value)
Эти новые знания дают возможность дополнить класс OrderMonitor (OrderMonitor.mqh) для работы с историческими ордерами. Прежде всего, добавим в класс логическую переменную history, которую будем заполнять в конструкторе на основании того, в каком сегменте удалось выделить ордер с переданным тикетом: среди действующих (OrderSelect) или в истории (HistoryOrderSelect).
class OrderMonitor: public OrderMonitorInterface
|
Вызов функции ResetLastError в успешной ветке if нужен для сброса ошибки, которую могла взвести функция OrderSelect (если ордер в истории).
На самом деле, данный вариант конструктора содержит серьезную логическую ошибку, и мы вернемся к нему через несколько абзацев.
Для чтения свойств в get-методах мы теперь должны вызывать разные встроенные функции, в зависимости от значения переменной history.
virtual long get(const ENUM_ORDER_PROPERTY_INTEGER property) const override { return history ? HistoryOrderGetInteger(ticket, property) : OrderGetInteger(property); }
virtual double get(const ENUM_ORDER_PROPERTY_DOUBLE property) const override { return history ? HistoryOrderGetDouble(ticket, property) : OrderGetDouble(property); }
virtual string get(const ENUM_ORDER_PROPERTY_STRING property) const override { return history ? HistoryOrderGetString(ticket, property) : OrderGetString(property); } ... |
Основное предназначение класса OrderMonitor — снабжать данными другие аналитические классы. Напомним, что объекты OrderMonitor используются для фильтрации активных ордеров в классе OrderFilter, и нам потребуется аналогичный класс для выборки ордеров по произвольным условиям на истории — HistoryOrderFilter.
Напишем этот класс в том же файле — OrderFilter.mqh. Вполне логично в нем применены две новых функции для работы на истории: HistoryOrdersTotal и HistoryOrderGetTicket.
class HistoryOrderFilter: public TradeFilter<OrderMonitor,
|
Этот простой код наследуется от шаблонного класса TradeFilter, куда в качестве первого параметра шаблона передается класс OrderMonitor для чтения свойств соответствующих объектов (мы видели аналог для позиций, и скоро создадим для сделок).
Здесь и кроется проблема с конструктором OrderMonitor. Как мы узнали в разделе Выборка ордеров и сделок из истории, для анализа счета мы должны предварительно настроить контекст с помощью одной из функций, таких как HistorySelect. Поэтому здесь в исходном коде HistoryOrderFilter предполагается, что MQL-программа уже выделила нужный фрагмент истории. Однако в новом, промежуточном варианте конструктора OrderMonitor используется вызов HistoryOrderSelect для проверки существования тикета на истории. Между тем эта функция сбрасывает предыдущий контекст исторических ордеров и выбирает единственный ордер.
Поэтому нам требуется вспомогательный метод historyOrderSelectWeak, который мог бы проверить тикет "мягким" способом, не нарушая существующий контекст. Для этого достаточно проверить равенство свойства ORDER_TICKET с самим переданным тикетом t: (HistoryOrderGetInteger(t, ORDER_TICKET) == t). Если такой тикет уже отобран (доступен), проверка завершится успешно, и монитору не нужно манипулировать историей.
class OrderMonitor: public OrderMonitorInterface
|
Пример применения фильтрации ордеров на истории рассмотрим в следующем разделе, после подготовки аналогичного функционала для сделок.