Торговые условия и режимы исполнения приказов по символу

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

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

В MQL5 API данные режимы доступны для каждого символа как следующие свойства, получаемые через функцию SymbolInfoInteger.

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

Описание

SYMBOL_TRADE_EXEMODE

Режим заключения сделок по цене

SYMBOL_FILLING_MODE

Флаги разрешенных режимов заливки ордера по объему (битовая маска, см. далее)

Значение свойства SYMBOL_TRADE_EXEMODE является элементом перечисления ENUM_SYMBOL_TRADE_EXECUTION.

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

Описание

SYMBOL_TRADE_EXECUTION_REQUEST

Торговля по предварительно запрошенной цене

SYMBOL_TRADE_EXECUTION_INSTANT

Немедленное исполнение (торговля по потоковым ценам)

SYMBOL_TRADE_EXECUTION_MARKET

Исполнение ордеров по рынку

SYMBOL_TRADE_EXECUTION_EXCHANGE

Биржевое исполнение

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

  • Исполнение по запросу (SYMBOL_TRADE_EXECUTION_REQUEST) — исполнение рыночного ордера по цене, предварительно полученной от брокера. Перед отправкой рыночного ордера у брокера запрашивается актуальная цена, после получения которой выполнение ордера по ней можно либо подтвердить, либо отклонить.
  • Немедленное исполнение (SYMBOL_TRADE_EXECUTION_INSTANT) — исполнение рыночного ордера по текущей цене. При отправке торгового запроса на исполнение терминал автоматически подставляет в ордер текущие цены. Если брокер принимает цену, то ордер будет исполнен. Если брокер не принимает запрошенную цену, то происходит "реквотирование" (Requote) — брокер возвращает цены, по которым может быть исполнен данный ордер.
  • Исполнение по рынку (SYMBOL_TRADE_EXECUTION_MARKET) — цену исполнения подставляет в приказ брокер без дополнительного согласования с трейдером. Отправка рыночного ордера в таком режиме подразумевает досрочное согласие с ценой, по которой он будет выполнен.
  • Биржевое исполнение (SYMBOL_TRADE_EXECUTION_EXCHANGE) — торговые операции совершаются по ценам текущих рыночных предложений.

Что касается битов в SYMBOL_FILLING_MODE, которые могут комбинироваться оператором логического ИЛИ ('|'), то их наличие или отсутствие обозначает следующие действия.

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

Значение

Политика заполнения

SYMBOL_FILLING_FOK

1

Все или Ничего (Fill Or Kill) — ордер должен быть исполнен исключительно в указанном объеме или отменен

SYMBOL_FILLING_IOC

2

Немедленно и хотя бы Частично (Immediate or Cancel) — сделка по максимально доступному на рынке объему в пределах указанного в ордере или отмена

(Идентификатор отсутствует)

(любое,
в т.ч. 0)

Вернуть (Return) — в случае частичного исполнения рыночный или лимитный ордер с остаточным объемом не снимается, а продолжает действовать

Возможность использования режимов FOK и IOC определяется торговым сервером.

Если разрешен режим SYMBOL_FILLING_FOK, то MQL-программа сможет для отправки приказа с помощью функции OrderSend использовать в структуре MqlTradeRequest созвучный режиму способ заполнения ордера — ORDER_FILLING_FOK. Если при этом на рынке не окажется достаточного объема финансового инструмента, то ордер не будет исполнен. Следует учитывать, что необходимый объем может быть составлен из нескольких предложений, доступных в данный момент на рынке, в результате чего получится несколько сделок.

Если разрешен режим SYMBOL_FILLING_IOC, MQL-программе становится доступен одноименный способ заливки приказов ORDER_FILLING_IOC (он также указывается в специальном поле "заливки" (type_filling) в структуре MqlTradeRequest перед отправкой приказа функцией OrderSend). При использовании этого режима в случае невозможности полного исполнения ордер будет исполнен на доступный объем, а оставшийся объем ордера будет отменен.

Последняя политика без идентификатора является режимом по умолчанию и доступна вне зависимости от других режимов (именно поэтому она соответствует нулю или любому другому значению). Иными словами, даже если мы получим для свойства SYMBOL_FILLING_MODE значение 1 (SYMBOL_FILLING_FOK), 2 (SYMBOL_FILLING_IOC) или 3 (SYMBOL_FILLING_FOK | SYMBOL_FILLING_IOC), режим "вернуть" будет подразумеваться. Для использования этой политики следует при формировании ордера (заполнении структуры MqlTradeRequest) указывать тип заливки ORDER_FILLING_RETURN.

Среди всех режимов SYMBOL_TRADE_EXEMODE есть одна особенность, касающаяся исполнения по рынку (SYMBOL_TRADE_EXECUTION_MARKET): Return-ордера всегда запрещены в режиме исполнения по рынку.

Поскольку ORDER_FILLING_FOK соответствует константе 0, отсутствие явного указания типа заливки в торговом запросе будет подразумевать именно этот режим.

Все эти нюансы мы рассмотрим на практике при разработке экспертов, а пока проверим чтение свойств в простом скрипте SymbolFilterExecMode.mq5.

#include <MQL5Book/SymbolFilter.mqh>
   
void OnStart()
{
   SymbolFilter f;                      // объект фильтра
   string symbols[];                    // массив названий символов
   long permissions[][2];               // массив с векторами значений свойств
   
   // свойства для чтения
   ENUM_SYMBOL_INFO_INTEGER modes[] =
   {
      SYMBOL_TRADE_EXEMODE,
      SYMBOL_FILLING_MODE
   };
   // применяем фильтр - заполняем массивы
   f.select(truemodessymbolspermissions);
   
   const int n = ArraySize(symbols);
   PrintFormat("===== Trade execution and filling modes for the symbols (%d) ====="n);
   for(int i = 0i < n; ++i)
   {
      Print(symbols[i] + ":");
      for(int j = 0j < ArraySize(modes); ++j)
      {
         // выводим свойства в виде описаний и чисел
         PrintFormat("  %s (%d)",
            SymbolMonitor::stringify(permissions[i][j], modes[j]),
            permissions[i][j]);
      }
   }
}

Ниже приведен фрагмент журнала с результатами работы скрипта. Здесь практически все символы имеют режим немедленного исполнения по ценам (SYMBOL_TRADE_EXECUTION_INSTANT) за исключением последнего SP500m (SYMBOL_TRADE_EXECUTION_MARKET). Заполнение объемов встречается всех типов — как отдельные SYMBOL_FILLING_FOK, SYMBOL_FILLING_IOC, так и их комбинация. Только для BTCUSD указан SYMBOL_FILLING_RETURN, то есть было получено значение равное 0 (отсутствуют биты FOK и IOC).

===== Trade execution and filling modes for the symbols (13) =====
EURUSD:
  SYMBOL_TRADE_EXECUTION_INSTANT (1)
  [ _SYMBOL_FILLING_FOK ] (1)
GBPUSD:
  SYMBOL_TRADE_EXECUTION_INSTANT (1)
  [ _SYMBOL_FILLING_FOK ] (1)
...
USDCNH:
  SYMBOL_TRADE_EXECUTION_INSTANT (1)
  [ _SYMBOL_FILLING_FOK _SYMBOL_FILLING_IOC ] (3)
USDRUB:
  SYMBOL_TRADE_EXECUTION_INSTANT (1)
  [ _SYMBOL_FILLING_IOC ] (2)
AUDUSD:
  SYMBOL_TRADE_EXECUTION_INSTANT (1)
  [ _SYMBOL_FILLING_FOK ] (1)
NZDUSD:
  SYMBOL_TRADE_EXECUTION_INSTANT (1)
  [ _SYMBOL_FILLING_FOK _SYMBOL_FILLING_IOC ] (3)
...
XAUUSD:
  SYMBOL_TRADE_EXECUTION_INSTANT (1)
  [ _SYMBOL_FILLING_FOK _SYMBOL_FILLING_IOC ] (3)
BTCUSD:
  SYMBOL_TRADE_EXECUTION_INSTANT (1)
  [(_SYMBOL_FILLING_RETURN)] (0)
SP500m:
  SYMBOL_TRADE_EXECUTION_MARKET (2)
  [ _SYMBOL_FILLING_FOK ] (1)

Напомним, что подчеркивания в идентификаторах режимов заливки появляются из-за того, что нам пришлось для визуализации констант (битов в маске SYMBOL_FILLING_MODE) определить собственное перечисление SYMBOL_FILLING (SymbolMonitor.mqh) с элементами, равными константам. Это было сделано, поскольку MQL5 не имеет подобного встроенного перечисления, но при этом мы не можем называть элементы своего перечисления точно так же, как встроенные константы — это вызвало бы конфликт имен.