The great and terrible MT4 forever (or how to strategise a transition) - page 13

 
JRandomTrader:

Here is from the documentation:

"the order in which these transactions arrive in the terminal is not guaranteed, so you cannot base your trading algorithm on waiting for some trade transactions to arrive after others have arrived. " https://www.mql5.com/ru/docs/event_handlers/ontradetransaction

And from experience, TRADE_TRANSACTION_ORDER_DELETE, TRADE_TRANSACTION_DEAL_ADD, TRADE_TRANSACTION_HISTORY_ADD transactions can arrive in any order.

Hence we have situations where there is no deal or order in the history yet, but the order already exists. Or vice versa, the order is still there, but the deal has already been executed. But the situation when the order is present in the active, as well as in the history, is hardly possible.

I don't catch the events, I look at the full picture on a new tick.


JRandomTrader:

In fact, that's why I have refused to use CTrade class - it's stepping on all these pitfalls.

I have a solution - each EA keeps a list of its orders and monitors their state. This includes 'non-standard' states - 'order sent but not yet present in active orders' (this is where they might double up), 'order deleted but not present in history'. This also helps with simultaneous work on one symbol when netting.

Until recently I used a universal crutch which checked for missing orders. But at some point it started failing.

I have added one more personal crutch to the Expert Advisor which now monitors its own orders separately.

That's a lot of crutches...

 
Andrey Khatimlianskii:

That's a lot of crutches...

Studying the issue. I even come across this: OrderSend market order true, then PositionsTotal= 0, OrdersTotal = 0, historical tables unchanged.

Seems to have succeeded in writing IsSynchronized(). The code is a bit heavy. Haven't decided yet in which form to post it.

 
// Демонстрация открытия дубля позиции в MT5.

#include <Trade\Trade.mqh>

void OnStart()
{
  CTrade Trade;
  
  while (!IsStopped() && (PositionsTotal() <= 1)) // Закончим, когда появится более одной позиции.
    if (PositionsTotal() == 1)
      Trade.PositionClose(PositionGetTicket(0)); // Если есть позиция - закрываем.
    else if (!OrdersTotal())
      Trade.Buy(0.01); // Если нет позиции и ордера - открываем позицию.
}

Run this code on an empty demo account and see if two positions open after a few seconds.


The same logic on MT4 looks like this.

void OnStart()
{
  while (!IsStopped() && (OrdersTotal() <= 1)) // Закончим, когда появится более одной позиции.
    if (OrderSelect(0, SELECT_BY_POS))
      OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 0) // Если есть позиция - закрываем.
    else
      OrderSend(_Symbol, OP_BUY, 0.01, Ask, 0, 0, 0) // Если нет позиции и ордера - открываем позицию.
}

It is clear that such code on MT4 will not cause position reversal. But not on MT5.

 
fxsaber:

Run this code on an empty demo account and see if two positions open after a few seconds.


The same logic on MT4 looks like this.

It is clear that such code on MT4 will not cause position reversal. But not on MT5.

Finally, have you just discovered it? This problem is as old as the terminal itself. But finally terminal users noticed it... after a decade.

When you perform trade actions yourself, the problem can be solved in a simple way - to insert Sleep() for a second after the action is performed. But when the EA uses stoploss/stackprofit and market close, there is a danger of encountering this problem, and in this case there is no solution.

 
Dmitry Fedoseev:

Finally! Have you just discovered this? This problem is as old as the terminal itself. But terminal users have finally noticed it... after a decade.

The problem has been discussed for a long time. Almost everyone has encountered it. It is the first time that a stable code has reproduced it.

When you perform trade actions yourself, you can solve the problem in a simple way - insert Sleep() for a second after the action has been performed. But when Stop Loss/StackProfit and market close are used in an EA, there is a danger of encountering the problem, and there is no solution in this case.

The solution has been found.

 
fxsaber:

Run this code on an empty demo account and see if two positions open after a few seconds.

Strange. It's not reproducing. Checked on demo from MQ, build 2900, EURUSD, zero spread. Waited about five minutes.

Perhaps I need to use some specific server of a real DC/broker and not the MQ server?

 
Ihor Herasko:

Strange. It's not reproducing. Checked on demo from MQ, build 2900, EURUSD, zero spread. Waited about five minutes.

Perhaps I need to use some specific server of a real DC/broker and not the MQ server?

ForexTimeFXTM-Demo01

 
fxsaber:

ForexTimeFXTM-Demo01

Yes, now the script stops. But there is still one position left. I guess the second one has time to close?

 
Ihor Herasko:

Yes, now the script stops. But there's still one position left. The second one must have time to close?

I always have two left. If one remains, it's even more of a bug:

  1. PositionsTotal = 1 - sends an order to close.
  2. Then PositionsTotal = 2 and the order from point 1 is closed.
 
fxsaber:

I always have two left. If one remains, it's an even bigger bug:

  1. PositionsTotal = 1 - sends an order to close.
  2. Then PositionsTotal = 2 and the order from point 1 is closed.

Yes, that's what I mean. It turns out that the script manages to close one of the positions when there are actually two of them, but PositionsTotal() returns 1. And then, after closing, the condition of the loop termination is fulfilled, i.e., PositionsTotal() returns 2.