Особенности языка mql5, тонкости и приёмы работы - страница 185

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

template <typename T>
T MyPrint( const T Value, const string Str )
{
  Print(Str + " = " + (string)Value);

  return(Value);
}

#define _P(A) MyPrint(A, ": " + #A)

sinput double inLots = 100;

int OnInit()
{
  MqlTradeResult Result = {0};
  MqlTradeRequest Request = {0};
  
  Request.action = TRADE_ACTION_PENDING;
  Request.symbol = _Symbol;
  Request.volume = inLots;
  Request.price = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
  Request.type = ORDER_TYPE_BUY_LIMIT;
  
  return(OrdersTotal() || PositionsTotal() || !OrderSend(Request, Result)); // Работаем, когда ничего не открыто.
}

// Возвращает сумму лотов всех позиций и ордеров.
double GetSumLots()
{
  double Lots = 0;
  
  for (int i = _P(OrdersTotal()) - 1; i >= 0; i--)
    if (_P(OrderGetTicket(_P(i))))
      Lots += _P(OrderGetDouble(ORDER_VOLUME_CURRENT));
    
  for (int i = _P(PositionsTotal()) - 1; i >= 0; i--)
    if (_P(PositionGetTicket(_P(i))))
      Lots += _P(PositionGetDouble(POSITION_VOLUME));

  return(Lots);
}

void OnTradeTransaction(const MqlTradeTransaction& trans,
                        const MqlTradeRequest& request,
                        const MqlTradeResult& result)
{
  Print("---------");
    
  // Проверяем, что сумма лотов всех позиций и ордеров совпадает с заданной.
  if (NormalizeDouble(_P(GetSumLots()) - inLots, _Digits))
    Alert("BUG!");
}


Результат.

2020.08.21 01:18:13.375 : OrdersTotal() = 1
2020.08.21 01:18:13.375 : i = 0
2020.08.21 01:18:13.375 : OrderGetTicket(MyPrint(i,: +i)) = 1197440
2020.08.21 01:18:13.375 : OrderGetDouble(ORDER_VOLUME_CURRENT) = 68.59999999999999
2020.08.21 01:18:13.375 : PositionsTotal() = 1
2020.08.21 01:18:13.375 : i = 0
2020.08.21 01:18:13.375 : PositionGetTicket(MyPrint(i,: +i)) = 1197440
2020.08.21 01:18:13.375 : PositionGetDouble(POSITION_VOLUME) = 31.4
2020.08.21 01:18:13.375 : GetSumLots() = 100.0
2020.08.21 01:18:13.377 ---------
2020.08.21 01:18:13.377 : OrdersTotal() = 1
2020.08.21 01:18:13.377 : i = 0
2020.08.21 01:18:13.377 : OrderGetTicket(MyPrint(i,: +i)) = 1197440
2020.08.21 01:18:13.377 : OrderGetDouble(ORDER_VOLUME_CURRENT) = 68.59999999999999
2020.08.21 01:18:13.377 : PositionsTotal() = 1
2020.08.21 01:18:13.377 : i = 0
2020.08.21 01:18:13.377 : PositionGetTicket(MyPrint(i,: +i)) = 1197440
2020.08.21 01:18:13.377 : PositionGetDouble(POSITION_VOLUME) = 31.4
2020.08.21 01:18:13.377 : GetSumLots() = 100.0
2020.08.21 01:18:13.389 ---------
2020.08.21 01:18:13.389 : OrdersTotal() = 1
2020.08.21 01:18:13.389 : i = 0
2020.08.21 01:18:13.389 : OrderGetTicket(MyPrint(i,: +i)) = 1197440
2020.08.21 01:18:13.389 : OrderGetDouble(ORDER_VOLUME_CURRENT) = 41.4
2020.08.21 01:18:13.389 : PositionsTotal() = 1
2020.08.21 01:18:13.389 : i = 0
2020.08.21 01:18:13.389 : PositionGetTicket(MyPrint(i,: +i)) = 1197440
2020.08.21 01:18:13.389 : PositionGetDouble(POSITION_VOLUME) = 31.4
2020.08.21 01:18:13.389 : GetSumLots() = 72.8
2020.08.21 01:18:13.389 Alert: BUG!
2020.08.21 01:18:13.389 ---------
2020.08.21 01:18:13.389 : OrdersTotal() = 1
2020.08.21 01:18:13.389 : i = 0
2020.08.21 01:18:13.389 : OrderGetTicket(MyPrint(i,: +i)) = 1197440
2020.08.21 01:18:13.389 : OrderGetDouble(ORDER_VOLUME_CURRENT) = 41.4
2020.08.21 01:18:13.389 : PositionsTotal() = 1
2020.08.21 01:18:13.389 : i = 0
2020.08.21 01:18:13.389 : PositionGetTicket(MyPrint(i,: +i)) = 1197440
2020.08.21 01:18:13.389 : PositionGetDouble(POSITION_VOLUME) = 31.4
2020.08.21 01:18:13.389 : GetSumLots() = 72.8
2020.08.21 01:18:13.389 Alert: BUG!
2020.08.21 01:18:13.389 ---------
2020.08.21 01:18:13.389 : OrdersTotal() = 1
2020.08.21 01:18:13.389 : i = 0
2020.08.21 01:18:13.389 : OrderGetTicket(MyPrint(i,: +i)) = 1197440
2020.08.21 01:18:13.389 : OrderGetDouble(ORDER_VOLUME_CURRENT) = 41.4
2020.08.21 01:18:13.389 : PositionsTotal() = 1
2020.08.21 01:18:13.389 : i = 0
2020.08.21 01:18:13.389 : PositionGetTicket(MyPrint(i,: +i)) = 1197440
2020.08.21 01:18:13.389 : PositionGetDouble(POSITION_VOLUME) = 31.4
2020.08.21 01:18:13.389 : GetSumLots() = 72.8
2020.08.21 01:18:13.389 Alert: BUG!
2020.08.21 01:18:13.389 ---------
2020.08.21 01:18:13.389 : OrdersTotal() = 1
2020.08.21 01:18:13.389 : i = 0
2020.08.21 01:18:13.389 : OrderGetTicket(MyPrint(i,: +i)) = 1197440
2020.08.21 01:18:13.389 : OrderGetDouble(ORDER_VOLUME_CURRENT) = 41.4
2020.08.21 01:18:13.389 : PositionsTotal() = 1
2020.08.21 01:18:13.389 : i = 0
2020.08.21 01:18:13.389 : PositionGetTicket(MyPrint(i,: +i)) = 1197440
2020.08.21 01:18:13.390 : PositionGetDouble(POSITION_VOLUME) = 58.6
2020.08.21 01:18:13.390 : GetSumLots() = 100.0

Выставили 100 лотов, но в какой-то момент лотов стало 72.8. Очевидно, что в такой ситуации торговый алгоритм может быть дезориентирован.

Строка для поиска: Oshibka 011.
 

fxsaber:
Он должен быть неизменным - равным тому, что был отправлен в OrderSend.

вообще-то нет, есть вероятность попасть на рассинхрон, что и происходит, обойти можно, совсем простого решения нет

 
Andrei Trukhanovich:

вообще-то нет, есть вероятность попасть на рассинхрон, что и происходит, обойти можно, совсем простого решения нет

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

 
fxsaber:

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

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

вероятность рассинхрона доли или единицы процентов, так что на производительности почти не скажется.

__________

посмотрел ваши принты, может и баг, если дело в рассинхроне, ошибочная сумма не должна повторяться одинаково в нескольких подсчетах

 
Andrei Trukhanovich:

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

вероятность рассинхрона доли или единицы процентов, так что на производительности почти не скажется.

В логе выше три подряд расчета показывают неправильный результат. Нужен Sleep, но это чревато задержками, когда можно не успеть среагировать на выставление торгового приказа.

Неприятная ситуация.

 
fxsaber:

В логе выше три подряд расчета показывают неправильный результат.

да, увидел, добавил сверху

 
Комментарии, не относящиеся к этой теме, были перенесены в "Любые вопросы новичков по MQL4 и MQL5, помощь и обсуждение по алгоритмам и кодам".
 
Alexey Viktorov:

Зря вы обижаетесь. Самая большая вероятность, это ошибка в коде. На втором месте заоблачный спред. Но кто кроме вас может отбросить первый вариант и начнёт рассматривать второй не видя кода. Да и не ту тему вы выбрали, надеюсь модераторы перенесут.

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

 
Evgeny Vlasov:

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

Это не по теме особенностей.
 
Artyom Trishkin:
Это не по теме особенностей.

Согласен.

Причина обращения: