Разрешения на торговлю

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

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

Описание

SYMBOL_TRADE_MODE

Разрешения для разных торговых режимов по символу (см. ENUM_SYMBOL_TRADE_MODE далее)

SYMBOL_ORDER_MODE

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

Оба свойства имеют целочисленный тип и доступны через функцию SymbolInfoInteger.

Свойство SYMBOL_TRADE_MODE мы уже задействовали в скрипте SymbolPermissions.mq5. Его значением является один из элементов перечисления ENUM_SYMBOL_TRADE_MODE.

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

Значение

Описание

SYMBOL_TRADE_MODE_DISABLED

0

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

SYMBOL_TRADE_MODE_LONGONLY

1

Разрешены только покупки

SYMBOL_TRADE_MODE_SHORTONLY

2

Разрешены только продажи

SYMBOL_TRADE_MODE_CLOSEONLY

3

Разрешены только операции закрытия позиций

SYMBOL_TRADE_MODE_FULL

4

Нет ограничений на торговые операции

Напомним, что в классе Permissions есть метод isTradeOnSymbolEnabled, который проверяет несколько аспектов, влияющих на доступность торговли по символу, и один из них — свойство SYMBOL_TRADE_MODE. По умолчанию мы считаем, что нас интересует полный доступ к торговле, то есть продажи и покупки: SYMBOL_TRADE_MODE_FULL. В зависимости от торговой стратегии MQL-программа может рассматривать достаточными, например, разрешения только на покупку, только на продажу или только на закрытие операций.

   static bool isTradeOnSymbolEnabled(string symbolconst datetime now = 0,
      const ENUM_SYMBOL_TRADE_MODE mode = SYMBOL_TRADE_MODE_FULL)
   {
      // проверка сессий
      bool found = now == 0;
      ...
      // проверка режима торговли для символа
      return found && (SymbolInfoInteger(symbolSYMBOL_TRADE_MODE) == mode);
   }

В дополнение к режиму торгов нам в будущем потребуется анализировать и разрешения на приказы разных типов: они обозначаются отдельными битами в свойстве SYMBOL_ORDER_MODE и могут быть произвольным образом скомбинированы логическим ИЛИ ('|'). Например, значение 127 (0x7F) соответствует всем взведенным битам, то есть доступность всех типов приказов.

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

Значение

Описание

SYMBOL_ORDER_MARKET

1

Разрешены рыночные ордера (Buy и Sell)

SYMBOL_ORDER_LIMIT

2

Разрешены лимитные ордера (Buy Limit и Sell Limit)

SYMBOL_ORDER_STOP

4

Разрешены стоп-ордера (Buy Stop и Sell Stop)

SYMBOL_ORDER_STOP_LIMIT

8

Разрешены стоп-лимит ордера (Buy Stop Limit и Sell Stop Limit)

SYMBOL_ORDER_SL

16

Разрешена установка Stop Loss

SYMBOL_ORDER_TP

32

Разрешена установка Take Profit

SYMBOL_ORDER_CLOSEBY

64

Разрешение на закрытие позиции с помощью встречной — то есть открытой в противоположном направлении по тому же инструменту.

Свойство SYMBOL_ORDER_CLOSEBY задается только для счетов с хеджинговой системой учета (ACCOUNT_MARGIN_MODE_RETAIL_HEDGING, см. Тип счета).

В тестовом скрипте SymbolFilterTradeMode.mq5 запросим пару описываемых свойств для видимых символов Обзора рынка. Вывод битов и их сочетаний в виде чисел не очень информативен, поэтому воспользуемся тем, что в классе SymbolMonitor у нас есть удобный метод stringify для печати элементов перечислений и битовых масок всех свойств.

void OnStart()
{
   SymbolFilter f;                      // объект фильтра
   string symbols[];                    // массив под имена
   long permissions[][2];               // массив для данных (значений свойств)
   
   // перечень запрашиваемых свойств символов
   ENUM_SYMBOL_INFO_INTEGER modes[] =
   {
      SYMBOL_TRADE_MODE,
      SYMBOL_ORDER_MODE
   };
   
   // применим фильтр, получим массивы с результатами
   f.let(SYMBOL_VISIBLEtrue).select(truemodessymbolspermissions);
   
   const int n = ArraySize(symbols);
   PrintFormat("===== Trade permissions 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]);
      }
   }
}

Ниже с сокращениями приводится фрагмент журнала, получившегося в результате запуска скрипта.

===== Trade permissions for the symbols (13) =====
EURUSD:
  SYMBOL_TRADE_MODE_FULL (4)
  [ _SYMBOL_ORDER_MARKET _SYMBOL_ORDER_LIMIT _SYMBOL_ORDER_STOP
  _SYMBOL_ORDER_STOP_LIMIT _SYMBOL_ORDER_SL _SYMBOL_ORDER_TP
  _SYMBOL_ORDER_CLOSEBY ] (127)
GBPUSD:
  SYMBOL_TRADE_MODE_FULL (4)
  [ _SYMBOL_ORDER_MARKET _SYMBOL_ORDER_LIMIT _SYMBOL_ORDER_STOP
  _SYMBOL_ORDER_STOP_LIMIT _SYMBOL_ORDER_SL _SYMBOL_ORDER_TP
  _SYMBOL_ORDER_CLOSEBY ] (127)
... 
SP500m:
  SYMBOL_TRADE_MODE_DISABLED (0)
  [ _SYMBOL_ORDER_MARKET _SYMBOL_ORDER_LIMIT _SYMBOL_ORDER_STOP
  _SYMBOL_ORDER_STOP_LIMIT _SYMBOL_ORDER_SL _SYMBOL_ORDER_TP ] (63)

Обратите внимание, что по последнему символу "SP500m" торговля полностью запрещена (его котировки поставляются только как "индикативные"). При этом его набор флагов по типам приказов отличен от 0, но не играет роли.

В зависимости от событий на рынке брокер может менять свойства символа по своему усмотрению, например, оставить на какое-то время только возможность закрывать позиции, поэтому корректный торговый робот обязан контролировать данные свойства перед каждой операцией.