Features of the mql5 language, subtleties and tricks - page 185

 
There is one more bug in play. We set a Limit order at the current price and watch its gradual filling. We check the total lot of all positions and orders at every step. It should not change, and should be equal to the one which was sent to 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!");
}


Result.

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 lots were placed, but at some point the lots became 72.8. Obviously, the trading algorithm can be disoriented in such a situation.

Search string: Oshibka 011.
 

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

Actually no, there is a chance of being out of sync, which is what happens, there is a workaround, there is no easy solution at all

 
Andrei Trukhanovich:

Actually no, there's a chance of getting a timing mismatch, which is what happens, there's no easy solution at all

I don't even have a simple solution. How to make sure that there is a desync in some running script is not at all clear.

 
fxsaber:

I don't even have a complicated solution. How to make sure in any running script that there is an asynchrony is not at all clear.

If the total lot has changed, keep counting until the lots for orders and positions are the same twice.

There is a probability of fractions or just a few percent, so it won't affect the performance.

__________

I looked at your prints, maybe it's a bug, if it's a case of async, the wrong amount should not be repeated in the same way in several calculations

 
Andrei Trukhanovich:

If the total lot has changed, keep counting until the lots for orders and positions are the same twice.

There is a fraction or a few percent probability of a misalignment, so the performance is almost unaffected.

In the log above, three consecutive calculations show the wrong result. We need Sleep, but this may lead to delays, when we won't have time to react to the trade order being issued.

This is not a pleasant situation.

 
fxsaber:

In the log above, three consecutive calculations show the wrong result.

Yes, I saw that, I added it to the top

 
 
Alexey Viktorov:

You shouldn't be offended. The highest probability is an error in the code. In second place is the exorbitant spread. But who but you can discard the first option and begin to consider the second without seeing the code. I hope the moderators will move the topic to the wrong one.

Thanks for the adequate reply. I am not offended, I am upset)). I wrote to try to find a quick solution, which may be someone who has already encountered this. The code is absolutely standard, totalprofit loop summing and comparing to a given value, moreover the code has been working for a couple of months on two different accounts without failing. Have a nice day.

 
Evgeny Vlasov:

Thank you for the adequate response. I'm not offended, I'm saddened)). I wrote to try and find a quick solution, which maybe someone who has already encountered it has. The code is absolutely standard, totalprofit loop summing and comparing to a given value, moreover the code has been working for a couple of months on two different accounts without failing. Have a nice day.

This is not on the subject of features.
 
Artyom Trishkin:
This is not on the subject of features.

I agree.