fxsaber
fxsaber личный блог
06 августа 2022, 15:05

Частичное исполнение.

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

 

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

 

Поиск.

Этот скрипт находит события, когда один и тот же отложенный ордер создает несколько позиций, жизни которых не пересекаются. Т.е. сначала открылась и закрылась одна позиция, затем — вторая и т.д. И все они происходят из одного и того же отложенного ордера за счет его частичных исполнений на Hedge-счете.

 

#define MT4ORDERS_BYPASS_MAXTIME 1000000 // Максимальное время (в мкс.) на ожидание синхронизации торгового окружения
#include <MT4Orders.mqh> // https://www.mql5.com/ru/code/16006

// Распечатывает MT4-записи с одним и тем же PositionID-идентификатором.
void PrintPositionID( const ulong PositionID )
{
  const int Size = OrdersHistoryTotal();
  
  for (int i = 0; i < Size; i++)
    if (OrderSelect(i, SELECT_BY_POS, MODE_HISTORY) && (OrderTicketID() == PositionID))
      OrderPrint();
      
  return;
}

// Строковое представление сделки.
string DealToString( const ulong &Ticket )
{
  const ENUM_DEAL_ENTRY EntryDeal = (ENUM_DEAL_ENTRY)HistoryDealGetInteger(Ticket, DEAL_ENTRY);
  const int Digits = (int)SymbolInfoInteger(HistoryDealGetString(Ticket, DEAL_SYMBOL), SYMBOL_DIGITS);
  
  return((string)(datetime)HistoryDealGetInteger(Ticket, DEAL_TIME)) + " " +
         (string)Ticket + " " + ((EntryDeal == DEAL_ENTRY_IN) ? "+" : "-") + 
         DoubleToString(HistoryDealGetDouble(Ticket, DEAL_VOLUME), 2) + " " +
         DoubleToString(HistoryDealGetDouble(Ticket, DEAL_PRICE), Digits) + " " +
         EnumToString(EntryDeal) + " " + (string)HistoryDealGetInteger(Ticket, DEAL_POSITION_ID);
}

// Строковое представление массива сделок (с одним PositionID-идентификатором).
string DealsToString( const ulong &Deals[] )
{
  string Str = NULL;
  const int Size = ArraySize(Deals);

  double Lots = 0;
  int Amount = 0;
  
  for (int i = 0; i < Size; i++)
  {
    Lots += HistoryDealGetDouble(Deals[i], DEAL_VOLUME) *
            ((HistoryDealGetInteger(Deals[i], DEAL_ENTRY) == DEAL_ENTRY_IN) ? 1: -1);
        
    Str += DealToString(Deals[i]) + "_Lots = " + DoubleToString(Lots, 2) +
           ((MathAbs(Lots) < 1e-5) ? ": " + (string)(++Amount) : NULL) + "\n";
  }
    
  return(Str);
}

void OnStart()
{
  TRADESID TradesID;
  ulong PositionID[];

  for (int i = TradesID.GetPositionsID(PositionID) - 1; i >= 0; i--) // Бежим по всем PositionID-идентификаторам.
    if (PositionID[i]) // Торговый идентификатор (не балансовые операции).
    {
      ulong Deals[];
      double Lots = 0; // Суммарный лот порождаемых позиций.
      
      const int Size = TradesID.GetDealsByID(PositionID[i], Deals) - 1; // Получили все сделки с одинаковым PositionID-идентификаторам
      
      for (int j = 0; j < Size; j++) // Бежим по сделкам.
      {
        Lots += HistoryDealGetDouble(Deals[j], DEAL_VOLUME) *
                ((HistoryDealGetInteger(Deals[j], DEAL_ENTRY) == DEAL_ENTRY_IN) ? 1: -1);
                
        if (MathAbs(Lots) < 1e-5) // Если было порождено несколько позиций - распечатываем.
        {
          PrintPositionID(PositionID[i]); // В MT4-представлении.
          Print(DealsToString(Deals)); // Все сделки.
          
          break;
        }
      }  
    }
}

 

Пример 1.

Рассмотрим некоторые результаты выполнения скрипта.

// MT4-представление.
#2006402 2021.08.19 00:26:28.705 sell 0.03 USDJPY 109.790 0.000 109.781 2021.08.19 00:26:38.748 109.774 -0.056 -2.84 0.37 3;[0] 3
#2006466 2021.08.19 00:26:52.992 sell 0.17 USDJPY 109.790 0.000 109.782 2021.08.19 00:27:14.111 109.782 -0.32 0.00 1.06 3;[0];[0] 3
#2006474 2021.08.19 00:27:19.078 sell 0.03 USDJPY 109.790 0.000 109.782 2021.08.19 00:27:21.939 109.782 -0.06 0.00 0.19 3;[0];[0];[0];[0];[0];[0];[0] 3
#2006493 2021.08.19 00:27:24.011 sell 0.18 USDJPY 109.790 0.000 109.782 2021.08.19 00:27:45.709 109.782 -0.33 0.00 1.12 3;[0];[0];[0];[0];[0];[0];[0] 3
#2007698 2021.08.19 00:59:16.717 sell 0.26 USDJPY 109.798 0.000 109.790 2021.08.19 02:07:17.431 109.790 -0.44 0.00 1.62 3;[0];[0];[0];[0];[0];[0];[0] 3

// Все сделки.
2021.08.19 00:26:28 2006394 +0.03 109.790 DEAL_ENTRY_IN 3426935_Lots = 0.03
2021.08.19 00:26:38 2006402 -0.03 109.774 DEAL_ENTRY_OUT_BY 3426935_Lots = 0.00: 1 // Закрылась первая позиция (через CloseBy).
2021.08.19 00:26:52 2006418 +0.03 109.790 DEAL_ENTRY_IN 3426935_Lots = 0.03
2021.08.19 00:26:56 2006426 +0.03 109.790 DEAL_ENTRY_IN 3426935_Lots = 0.06
2021.08.19 00:27:00 2006431 +0.03 109.790 DEAL_ENTRY_IN 3426935_Lots = 0.09
2021.08.19 00:27:04 2006436 +0.03 109.790 DEAL_ENTRY_IN 3426935_Lots = 0.12
2021.08.19 00:27:09 2006439 +0.03 109.790 DEAL_ENTRY_IN 3426935_Lots = 0.15
2021.08.19 00:27:13 2006465 +0.02 109.790 DEAL_ENTRY_IN 3426935_Lots = 0.17
2021.08.19 00:27:14 2006466 -0.17 109.782 DEAL_ENTRY_OUT 3426935_Lots = -0.00: 2 // Закрылась вторая позиция.
2021.08.19 00:27:19 2006471 +0.03 109.790 DEAL_ENTRY_IN 3426935_Lots = 0.03
2021.08.19 00:27:21 2006474 -0.03 109.782 DEAL_ENTRY_OUT 3426935_Lots = -0.00: 3 // Закрылась третья позиция.
2021.08.19 00:27:24 2006476 +0.02 109.790 DEAL_ENTRY_IN 3426935_Lots = 0.02
2021.08.19 00:27:27 2006479 +0.02 109.790 DEAL_ENTRY_IN 3426935_Lots = 0.04
2021.08.19 00:27:30 2006482 +0.03 109.790 DEAL_ENTRY_IN 3426935_Lots = 0.07
2021.08.19 00:27:33 2006484 +0.03 109.790 DEAL_ENTRY_IN 3426935_Lots = 0.10
2021.08.19 00:27:36 2006486 +0.02 109.790 DEAL_ENTRY_IN 3426935_Lots = 0.12
2021.08.19 00:27:39 2006489 +0.03 109.790 DEAL_ENTRY_IN 3426935_Lots = 0.15
2021.08.19 00:27:42 2006491 +0.03 109.790 DEAL_ENTRY_IN 3426935_Lots = 0.18
2021.08.19 00:27:45 2006493 -0.18 109.782 DEAL_ENTRY_OUT 3426935_Lots = -0.00: 4 // Закрылась четвертая позиция.
2021.08.19 00:59:16 2006970 +0.26 109.798 DEAL_ENTRY_IN 3426935_Lots = 0.26
2021.08.19 02:07:17 2007698 -0.26 109.790 DEAL_ENTRY_OUT 3426935_Lots = 0.00:  5 // Закрылась пятая позиция.

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

 

Визуализация.

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

Частичное исполнение.

На скрине два представления рассматриваемой ситуации.

 

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

 

Нижний (таблица) — это визуализация MT4-представления той же истории исполнения, но за счет нескольких иных сущностей: MT4-позиций, которые создает библиотека MT4Orders.

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

 

Таково различие MT5 и MT4-представлений торговой истории. Первый — лаконичный, второй — подробный.

 

Пример 2.

// MT4-представление.
#2429648 2021.11.16 23:58:39.093 sell 0.30 AUDCHF 0.67939 0.00000 0.67913 2021.11.16 23:58:42.309 0.67963 -0.964 0.00 -6.84 103;[0] 103
#2429915 2021.11.16 23:59:44.453 sell 0.50 AUDCHF 0.67939 0.00000 0.67910 2021.11.17 00:10:02.531 0.67901 -1.61 -3.48 18.05 103;[0];[0];[0] 103
#2429920 2021.11.16 23:59:44.453 sell 0.10 AUDCHF 0.67939 0.00000 0.67910 2021.11.17 00:10:03.693 0.67904 -0.32 -0.69 3.32 103;[0];[0];[0] 103
#2430627 2021.11.17 00:30:39.016 sell 0.29 AUDCHF 0.67928 0.00000 0.67906 2021.11.17 01:01:37.912 0.67906 -0.94 0.00 6.06 103;[0];[0];[0];[0];[0];[0];[0] 103

// Все сделки.
2021.11.16 23:58:39 2429630 +0.15 0.67939 DEAL_ENTRY_IN 5697587_Lots = 0.15
2021.11.16 23:58:42 2429647 +0.15 0.67939 DEAL_ENTRY_IN 5697587_Lots = 0.30
2021.11.16 23:58:42 2429648 -0.30 0.67963 DEAL_ENTRY_OUT_BY 5697587_Lots = 0.00: 1 // Закрылась первая позиция (через CloseBy).
2021.11.16 23:59:44 2429680 +0.15 0.67939 DEAL_ENTRY_IN 5697587_Lots = 0.15
2021.11.16 23:59:47 2429695 +0.15 0.67939 DEAL_ENTRY_IN 5697587_Lots = 0.30
2021.11.16 23:59:51 2429705 +0.15 0.67939 DEAL_ENTRY_IN 5697587_Lots = 0.45
2021.11.16 23:59:55 2429706 +0.15 0.67939 DEAL_ENTRY_IN 5697587_Lots = 0.60
2021.11.17 00:10:02 2429915 -0.50 0.67901 DEAL_ENTRY_OUT 5697587_Lots = 0.10     // Частичное закрытие второй позиции.
2021.11.17 00:10:03 2429920 -0.10 0.67904 DEAL_ENTRY_OUT 5697587_Lots = -0.00: 2 // Закрылась вторая позиция.
2021.11.17 00:30:39 2430264 +0.29 0.67928 DEAL_ENTRY_IN 5697587_Lots = 0.29
2021.11.17 01:01:37 2430627 -0.29 0.67906 DEAL_ENTRY_OUT 5697587_Lots = -0.00: 3 // Закрылась третья позиция.

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

 

Частичное исполнение.

Мы снова видим, что MT5-предсталение максимально лаконично. Однако, MT4-представление имеет не три, а четыре позиции. Именно такой способ выбран для визуализации частичных закрытий позиций. В таблице четко показано, что было частичное исполнение TakeProfit-позиции (зеленая рамка), реджект оставшейся части и другие подробности.

 

MT4/MT5-представления торговой истории.

На примере PartialFills продемонстрировано, что разные сущности MT4/MT5-позиций позволяют соответствующим образом видеть/оценивать хронологию торговых событий.

 

Сама концепция такого представления позиций является платформо-независимой и может быть реализована для многих торговых API и рынков.

 

Частичное исполнение.

Даже на приведенных примерах нельзя не заметить, что частичное исполнение может проходить очень мелкими лотами на FOREX-рынке. Происходит и на открытии и на закрытии позиций. Безусловно, важно правильно обрабатывать все эти события. И, наверное, MT4-представления истории (и текущего торгового состояния) дают более подготовленную основу для этого.

 

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

 

Загромождать этим не стал пост. Благо каждый при желании может воспользоваться предложенным инструментарием на своем торговом счете и оценить исполнение именно своих ордеров.

0 Комментариев

Активные форумы
Что сейчас обсуждают

Старый дизайн
Старый
дизайн