Библиотеки: MT4Orders - страница 68

 
fxsaber #:
Последняя версия всегда здесь.

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


Эта проблема была исправлена в последней версии.

Скачать последнюю версию библиотеки можно с русскоязычной страницы.

 
'DEAL_SL' - undeclared identifier       MT4Orders.mqh   1186    89
'DEAL_TP' - undeclared identifier       MT4Orders.mqh   1187    91
'MQL_HANDLES_USED' - undeclared identifier      MT4Orders.mqh   1345    104
'MQL_HANDLES_USED' - undeclared identifier      MT4Orders.mqh   1726    124

На старых версиях MT5 не билдится.

А последняя релизная бажная https://www.mql5.com/ru/forum/380278/page31#comment_26286913

Новая версия платформы MetaTrader 5 build 3091: Улучшения в работе
Новая версия платформы MetaTrader 5 build 3091: Улучшения в работе
  • 2021.12.04
  • www.mql5.com
В пятницу 22 октября 2021 года будет выпущена обновленная версия платформы MetaTrader 5...
 
traveller00 #:

На старых версиях MT5 не билдится.

Компилирую на свежих версиях, использую на b2958. К релиз-сборкам отношусь, как и к бетам.

 

У меня небольшой вопрос по частичному закрытию.

В MT4 закрытие 0.01 лота ордера размером 0.1 лота приводит к тому, что первоначальный тикет закрывается с размером 0.01 лота, а комментарий к ордеру, который был частично закрыт, меняется на "to: xxxxxx". В то же время открывается новый ордер размером 0,09 лота с комментарием "от: xxxxxx".

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

У вас есть фрагмент кода, совместимого с MT4Orders, которым вы можете поделиться, или вы можете объяснить, как я могу сделать это надежно?

 

Как посмотреть частичное исполнение открытых позиций.

#include <MT4Orders.mqh> // https://www.mql5.com/ru/code/16006

#define Ask SymbolInfoDouble(_Symbol, SYMBOL_ASK)

void OnStart()
{
  // Open position.
  const TICKET_TYPE Ticket  = OrderSend(_Symbol, OP_BUY, 0.1, Ask, 0, 0, 0, "Hello!");
  
  // Partial Closes.
  if (OrderSelect(Ticket, SELECT_BY_TICKET))
  {
    OrderClose(OrderTicket(), 0.01, OrderClosePrice(), 0);
    OrderClose(OrderTicket(), 0.02, OrderClosePrice(), 0);
  }
    
  for (int i = OrdersTotal() - 1; i >= 0; i--)
    if (OrderSelect(i, SELECT_BY_POS))
    {
      PrintFullOrder();
      
      Print("");
    }
}

#include <fxsaber\TradesID\TradesID.mqh> // https://www.mql5.com/ru/code/34173

void PrintFullOrder()
{
  static TRADESID TradesID;
  
  long Deals[];  
  const int Size = TradesID.GetDealsByID(OrderTicketID(), Deals);
  
  for (int i = 0; i < Size; i++)
    if (OrderSelect(Deals[i], SELECT_BY_TICKET))
      OrderPrint();  
}


Результат.

#50005051444 2021.12.20 21:22:29.566 buy 0.07 GBPUSD 1.32174 0.00000 0.00000 1.32169 0.00 0.00 -0.31 Hello! 0
#50004982892 2021.12.20 21:22:29.566 buy 0.01 GBPUSD 1.32174 0.00000 0.00000 2021.12.20 21:22:29.631 1.32169 0.00 0.00 -0.04 Hello! 0
#50004982893 2021.12.20 21:22:29.566 buy 0.02 GBPUSD 1.32174 0.00000 0.00000 2021.12.20 21:22:29.694 1.32169 0.00 0.00 -0.09 Hello! 0

#50005051217 2021.12.20 21:22:05.921 buy 0.09 USDCHF 0.92179 0.00000 0.00000 0.92179 0.00 0.00 0.00 Hello! 0
#50004982634 2021.12.20 21:22:05.921 buy 0.01 USDCHF 0.92179 0.00000 0.00000 2021.12.20 21:22:05.984 0.92174 0.00 0.00 -0.05 Hello! 0
 
SysFX комментарий к ордеру, который был частично закрыт, меняется на "to: xxxxxx". В то же время открывается новый ордер размером 0,09 лота с комментарием "от: xxxxxx".

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

У вас есть фрагмент кода, совместимого с MT4Orders, которым вы можете поделиться, или вы можете объяснить, как я могу сделать это надежно?

Пример.

 
fxsaber #:

Пример.

Это идеально! ...спасибо за быстрый ответ :)

 
// Список изменений:
// 28.12.2021
//   Fix: OrderSelect(Index, SELECT_BY_POS, MODE_TRADES) учитывает еще одну рассинхронизацию со стороны MT5.
//   Fix: OrderLots(true) учитывает еще одну рассинхронизацию со стороны MT5. 


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

Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий

Библиотеки: MT4Orders

fxsaber, 2021.05.12 18:24

На первый взгляд эти два кода должны давать одинаковый результат.

while (OrdersTotal() <= 1)
  if (OrderSelect(0, SELECT_BY_POS))
    OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 0);
  else
    OrderSend(_Symbol, OP_BUY, 1, Ask, 0, 0, 0);    


while (OrdersTotal() <= 1)
  if (!OrdersTotal())
    OrderSend(_Symbol, OP_BUY, 1, Ask, 0, 0, 0);    
  else if (OrderSelect(0, SELECT_BY_POS))
    OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 0);


На самом деле это не так. Попробуйте осознать причину.

В общем, получилось еще лучше защититься от особенностей задвоений ордеров в MT5.

 
// Список изменений:
// 29.12.2021
//   Fix: Улучшена синхронизация в ByPass-режиме.
 

В MT4 при переборе ордеров возможны задвоения (двойной учет) из-за перетряхивания таблицы ордеров.


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

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

#define Ask SymbolInfoDouble(_Symbol, SYMBOL_ASK)
#define MinLot SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN)

double GetLots()
{
  double Lots = 0;
  
  for (int i = OrdersTotal() - 1; i >= 0; i--) // Бежим по всем ордерам - здесь может быть сбой.
    if (OrderSelect(i, SELECT_BY_POS))
      Lots += OrderLots();
      
  return(NormalizeDouble(Lots, 2));
}

void OnStart()
{
  MT4ORDERS::OrderSend_MaxPause = 0; // Отказываемся от встроенной коррекции результата MT5-OrderSend.

  const double NewLots = 0.11;
  
  while (!IsStopped())
  {
    const double Lots = NormalizeDouble(GetLots() + NewLots, 2); // Сколько должно быть лотов суммарно после выставления ордера.
    const TICKET_TYPE Ticket = OrderSend(_Symbol, OP_BUY, NewLots, Ask, 0, 0 ,0); // Выставили маркет-ордер.
    
    if (Ticket != -1)
    {
      while (!PositionSelectByTicket(Ticket)) // Ждем, пока маркет-ордер не превратился в позицию.
      {
        const double Lots2 = GetLots(); // Вычисляем суммарный объем.
        
        if (Lots2 != Lots) // Суммарный объем не совпадает с предварительным расчетом - выводим.
          Alert((string)Lots + " " + (string)Lots2);                        
      }
    }
          
    if (OrderSelect(Ticket, SELECT_BY_TICKET) &&
        OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 0)) // Отправляем маркет-ордер на закрытие позиции.
      while (PositionSelectByTicket(Ticket))                          // Ждем закрытия позиции.
        ;      
  }
    
  Print(MT4ORDERS::ByPass.ToString()); // Распечатываем статистику синхронизаций.
}


Такой советник будет Алерить на некоторых конфигурациях. ByPass-режим делает значения Алертов стабильными, но все равно не избавляет от них.


Сам не торгую без ByPass-режима, т.к. это очень сильная штука по обходу MT5-сюрпризов. А еще не торгую без снепшотов. Именно снепшот-механизм позволяет исцелиться от переиндексации.


Вот так это выглядит на том же примере.

#define VIRTUAL_SNAPSHOT_REFRESHTIME 1000 // Время жизни снепшота для обновления. В MT5 требует подключенной MT4Orders.mqh
#define VIRTUAL_SNAPSHOT_WITHOUT_HISTORY // Отказ от снепшота истории для повышения производительности
#include <fxsaber\Virtual\Virtual.mqh> // https://www.mql5.com/ru/code/22577

double GetLots()
{
  double Lots = 0;

  VIRTUAL::Snapshot(0, -1, false, ""); // Заснепшотили реальное торговое окружение.
  
  for (int i = OrdersTotal() - 1; i >= 0; i--) // За счет снепшот-механизма бежим по всем ордерам безопасно.
    if (OrderSelect(i, SELECT_BY_POS))
      Lots += OrderLots();

  VIRTUAL::SnapshotDelete(); // Удалили снепшот.
      
  return(NormalizeDouble(Lots, 2));
}


Рекомендую связку ByPass+Snapshot. Помогает не только обходить подводные камни, но и значительно уменьшает потребление вычислительных ресурсов. Особенно, когда много мультивалютных ордеров/советников.