Проверка на существующую сделку

 

Здравствуйте!

Нужна помощь! Кто может - помогите понять, что не так.

Есть проверка на существующую сделку. Выглядит она вот так:

for(int i=0; i<PositionsTotal(); i++)
           {
            ulong positionTicket=PositionGetTicket(i); 
            if(PositionSelectByTicket(positionTicket))
              { 
               if(PositionGetString(POSITION_SYMBOL)==Symbol() && PositionGetInteger(POSITION_MAGIC)==InMagicNumber) 
                 {
                  ENUM_POSITION_TYPE positionType=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE); 
                  if(positionType == POSITION_TYPE_SELL) 
                    { 
                     return; 
                    } 
                  mTrade.PositionClose(positionTicket); 
                  break; 
                 } 
              }
           }

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

Код срабатывает как задудманно почти всегда. Проблема в том что "почти". Есть ситуация, которая видимо ни чем не отличается от стандартной, но при которой код открывает несколько позиций одинакого типа с интервалом в несколько секунд.

Документация по MQL5: Константы, перечисления и структуры / Торговые константы / Свойства позиций
Документация по MQL5: Константы, перечисления и структуры / Торговые константы / Свойства позиций
  • www.mql5.com
Тикет позиции. Уникальное число, которое присваивается каждой вновь открытой позиции. Как правило, соответствует тикету ордера, в результате которого она была открыта, за исключением случаев изменения тикета в результате служебных операций на сервере. Например, начисления свопов переоткрытием позиции. Для нахождения ордера, которым была открыта...
 

PositionSelectByTicket не нужна в данном коде - ни на что не влияет.

В MT5 нет команды открыть позицию. Есть только создание маркет-ордера на создание позиции. Поэтому и получаются дубли.


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

 
fxsaber:

PositionSelectByTicket не нужна в данном коде - ни на что не влияет.

В MT5 нет команды открыть позицию. Есть только создание маркет-ордера на создание позиции. Поэтому и получаются дубли.


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

Огромная благодарность за овтет. Если не справлюсь - могу обратиться за помощью? Конечно же за вознаграждение. Добро надо поощрять!

 
// https://www.mql5.com/ru/forum/326877
// В данном случае проверка идёт перед созданием позиции на продажу.
// если позиция принадлежит советнику (позиция имеет выбранный символ и магическое число),
// то проверяется тип позиции, если это позиция на продажу,
// то нам ничего не надо делать, если на покупку,
// то закрываем эту позицию, далее по коду логика открытия новой позиции.

// Код кроссплатформенный - будет работать в MT4/5.
// Документация - https://docs.mql4.com/ru/trading

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

input MAGIC_TYPE inMagic = 0;
input double inLots = 1;
input int inSlippage = 3;

#define Bid SymbolInfoDouble(_Symbol, SYMBOL_BID)

bool OrderScan( const int Type )
{
  bool Res = false;
  
  for (int i = OrdersTotal() - 1; (i >= 0) && (!Res); i--)
    Res = OrderSelect(i, SELECT_BY_POS) && (OrderType() == Type) && (OrderMagicNumber() == inMagic) && (OrderSymbol() == _Symbol);

  return(Res);  
}

#define _CS(A) ((!IsStopped()) && (A))

void OnTick()
{
  bool Res = true;
  
  while (_CS(Res && OrderScan(OP_BUY)))
    Res &= OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), inSlippage);
  
  if (_CS(Res && !OrderScan(OP_SELL)))
    OrderSend(_Symbol, OP_SELL, inLots, Bid, inSlippage, 0, 0, "Hello World!", inMagic);
}
Причина обращения: