Структура торгового запроса MqlTradeRequest

Торговые функции MQL5 API, в частности OrderCheck и OrderSend, оперируют несколькими встроенными структурами. Поэтому нам придется рассмотреть эти структуры до того, как переходить к самим функциям.

Начнем мы со структуры MqlTradeRequest, которая содержит все поля, необходимые для заключения торговых сделок.

struct MqlTradeRequest 

   ENUM_TRADE_REQUEST_ACTIONS action;       // Тип выполняемого действия 
   ulong                      magic;        // Уникальный номер эксперта 
   ulong                      order;        // Тикет ордера 
   string                     symbol;       // Имя торгового инструмента 
   double                     volume;       // Запрашиваемый объем сделки в лотах 
   double                     price;        // Цена  
   double                     stoplimit;    // Уровень StopLimit ордера 
   double                     sl;           // Уровень Stop Loss ордера 
   double                     tp;           // Уровень Take Profit ордера 
   ulong                      deviation;    // Максимальное отклонение от заданной цены 
   ENUM_ORDER_TYPE            type;         // Тип ордера 
   ENUM_ORDER_TYPE_FILLING    type_filling// Тип ордера по исполнению 
   ENUM_ORDER_TYPE_TIME       type_time;    // Тип ордера по времени действия 
   datetime                   expiration;   // Срок истечения ордера 
   string                     comment;      // Комментарий к ордеру 
   ulong                      position;     // Тикет позиции 
   ulong                      position_by;  // Тикет встречной позиции 
};

Не следует пугаться большого количества полей: структура спроектирована для обслуживания абсолютно всех возможных видов торговых запросов, однако в каждом конкретном случае обычно используется всего несколько полей.

Перед заполнением полей рекомендуется обнулить структуру либо с помощью явной инициализации в её определении, либо вызовом функции ZeroMemory.

   MqlTradeRequest request = {};
   ...
   ZeroMemory(request);

Это позволит избежать потенциальных ошибок и побочных эффектов от передачи в функции API случайных значений в тех поля, которые не были явно присвоены.

В следующей таблице приводится краткое описание полей. Про их заполнение будет сказано в описаниях торговых операций.

Поле

Описание

action

Тип торговой операции из ENUM_TRADE_REQUEST_ACTIONS

magic

Идентификатор эксперта (опционально)

order

Тикет отложенного ордера, для которого запрашивается модификация

symbol

Имя торгового инструмента

volume

Запрашиваемый объем сделки в лотах

price

Цена, при достижении которой ордер должен быть исполнен

stoplimit

Цена, где будет выставлен лимитный ордер при активации ордеров ORDER_TYPE_BUY_STOP_LIMIT и ORDER_TYPE_SELL_STOP_LIMIT

sl

Цена, по которой сработает Stop Loss ордер при движении цены в неблагоприятном направлении

tp

Цена, по которой сработает Take Profit ордер при движении цены в благоприятном направлении

deviation

Максимально приемлемое отклонение от запрашиваемой цены, в пунктах

type

Тип ордера из ENUM_ORDER_TYPE

type_filling

Тип ордера по заполнению объемом из ENUM_ORDER_TYPE_FILLING

type_time

Тип истечения отложенного ордера из ENUM_ORDER_TYPE_TIME

expiration

Срок истечения отложенного ордера

comment

Комментарий к ордеру

position

Тикет позиции

position_by

Тикет встречной позиции для операции TRADE_ACTION_CLOSE_BY

Для отправки приказов на совершение торговых операций необходимо заполнять различный набор полей, в зависимости от сути операции. Некоторые поля являются обязательными, а некоторые — опциональными (могут быть опущены при заполнении). Далее мы подробно рассмотрим требования к полям в контексте конкретных действий.

Оформленную структуру MqlTradeRequest программа может проверить на корректность с помощью функции OrderCheck или отправить на сервер с помощью функции OrderSend, и в случае успеха будет выполнена требуемая операция.

Поле action является единственным, необходимым для всех торговых действий.

Уникальный номер в поле magic имеет смысл указывать только в запросах на покупку/продажу по рынку или при создании нового отложенного ордера. Это приводит к последующей маркировке совершенных сделок и позиций этим числом, что позволяет организовать аналитическую обработку торговых действий. При модификации ценовых уровней позиции или отложенных ордеров, а также их удалении это поле не имеет эффекта.

При ручном выполнении торговых операций из интерфейса MetaTrader 5 magic-идентификатор нельзя установить, и потому он равен нулю. Это дает популярный, но не совсем надежный способ отличить ручную и автоматическую торговлю при анализе истории. На самом деле, эксперты также могут использовать нулевой идентификатор. Поэтому выяснять, кто и как выполнял конкретные торговые действия, следует с помощью соответствующих свойств ордеров (ORDER_REASON), сделок (DEAL_REASON) и позиций (POSITION_REASON).

Каждый эксперт может выставлять свой собственный уникальный идентификатор или даже использовать несколько для разных целей (в разбивке по торговым стратегиям, сигналам и т.д.). Magic-номер позиции соответствует magic-номеру последней сделки, участвовавшей в формировании позиции.

Название инструмента в поле symbol важно только для операций открытия или наращивания позиции, а также при выставлении отложенных ордеров. В случаях модификации и закрытии ордеров и позиций оно будет проигнорировано, но здесь есть небольшое исключение. Поскольку на неттинг-счетах по каждому символу может существовать только одна позиция, то поле symbol можно использовать для идентификации позиции в запросе на изменение её защитных ценовых уровней (Stop Loss и Take Profit).

Похожим образом используется и поле volume: оно нужно в приказах на немедленную покупку/продажу или при создании отложенных ордеров. Следует учитывать, что реальное значение объема в сделке будет зависеть от режима исполнения и может отличаться от запрошенного.

Поле price также имеет некоторые ограничения: при отправке рыночных ордеров (TRADE_ACTION_DEAL в поле action) по инструментам с режимом исполнения SYMBOL_TRADE_EXECUTION_MARKET или SYMBOL_TRADE_EXECUTION_EXCHANGE это поле игнорируется.

Поле stoplimit имеет смысл только при установке стоп-лимитных ордеров, то есть когда в поле type содержится ORDER_TYPE_BUY_STOP_LIMIT или ORDER_TYPE_SELL_STOP_LIMIT. Здесь задается цена, по которой будет выставлен отложенный лимитный ордер при достижении ценой значения price (этот факт отслеживается сервером MetaTrader 5, и до этого момента отложенный ордер в торговую систему не выводится).

При установке отложенных ордеров их правила истечения задаются в паре полей type_time и expiration. Последнее содержит значение типа datetime, которое принимается во внимание, только если type_time равно ORDER_TIME_SPECIFIED или ORDER_TIME_SPECIFIED_DAY.

Наконец, пара последних полей связана с идентификацией позиций в запросах. Каждой новой позиции, созданной на основе приказов (вручную или программно), системой присваивается тикет — уникальное число. Как правило, оно соответствует тикету ордера, в результате которого позиция открыта, но может меняться в результате служебных операций на сервере, например, начисления свопов переоткрытием позиции.

О получении свойств позиций, сделок и ордеров мы поговорим в отдельных разделах. Здесь же для нас пока важно, что поле position следует заполнять при изменении и закрытии позиции в целях её однозначной идентификации. В принципе, на неттинговых счетах для этого достаточно указания инструмента позиции в поле symbol, но для унификации алгоритмов лучше оставить поле position в работе.

Поле position_by используется для операции закрытия встречных позиций (TRADE_ACTION_CLOSE_BY). В нем следует указывать позицию, открытую по тому же инструменту, но в противоположном направлении по отношению к position (это возможно только на хеджинговом счете).

Поле deviation влияет на исполнение рыночных ордеров только в режимах Instant Execution и Request Execution.

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