MqlTradeResult.price is zero after blocking OrderSend()

 

My EA opens positions at market price using OrderSend(). In the Strategy Tester, and on demo, when the call returns "10009 Request Completed", the MqlTradeResult.price field holds the price at which the position was opened, and the MqlTradeResult.deal field holds the corresponding deal ID.

However, on a live account, the MqlTradeResult.price and MqlTradeResult.deal fields can be zero. I am using the blocking OrderSend() call, not the asynchronous OrderSendASync() call, so I expected the MqlTradeResult structure to be filled upon return.

Can I not rely on this? If so, how long do I need to wait before calling PositionGetDouble(POSITION_PRICE_OPEN) gives me the correct non-zero value?

Example logging below:

MqlTradeRequest
    action       : TRADE_ACTION_DEAL
    magic        : 123456
    order        : 0
    symbol       : EURUSD
    volume       : 0.01
    price        : 1.13807
    stopLimit    : 0.00000
    sl           : 1.13667
    tp           : 1.13857
    deviation    : 6
    type         : ORDER_TYPE_BUY
    type_filling : ORDER_FILLING_IOC
    type_time    : ORDER_TIME_GTC
    expiration   : (none)
    comment      : 
    position     : 0
    position_by  : 0

Last EURUSD tick
    bid          : 1.13807
    ask          : 1.13807
    time         : 2022-02-16 23:02:09.295

OrderSend
    success      : true
    lastError    : 0 (Ok)
    duration     : 127.026 milliseconds

MqlTradeResult
    retcode      : 10009 (Request completed)
    deal         : 0
    order        : 207502150
    volume       : 0.01
    price        : 0.00000
    bid          : 0.00000
    ask          : 0.00000
    comment      : Request executed
    request_id   : 1
    retcode_ext  : 0
 

In the meantime, I found this thread: https://www.mql5.com/en/forum/357245#comment_19607440

Apparently OrderSend() is just as asynchronously as OrderSendASync(). When OrderSend() returns, the internal bookkeeping in MT5 can still be lagging and not updated yet. You need to implement OnTrade() or OnTradeTransaction() handlers to be sure. That is quite unusual for a blocking "synchronous" call. In other words: you might as well use OrderSendASync() because you are forced to implement a handler anyway.

I am disappointed in this architecture. This does not make sense.

Even worse: the Strategy Tester and demo accounts do not show this behaviour, so to properly test my implementation I need to do trades on an actual live account. @MetaQuotes: please emulate this behaviour in your Strategy Tester and on demo accounts so programmers can better test their code. It is not nice to discover this after months of successful demo trading.

OnTrade/OnTradeTransaction - Are deal results always async?
OnTrade/OnTradeTransaction - Are deal results always async?
  • 2020.12.05
  • www.mql5.com
Hi, since some time I am facing the issue, that after a position was closed/partially closed the deal database does not provide valid results - and...
 
yoriz #:

In the meantime, I found this thread: https://www.mql5.com/en/forum/357245#comment_19607440

Apparently OrderSend() is just as asynchronously as OrderSendASync(). When OrderSend() returns, the internal bookkeeping in MT5 can still be lagging and not updated yet. You need to implement OnTrade() or OnTradeTransaction() handlers to be sure. That is quite unusual for a blocking "synchronous" call. In other words: you might as well use OrderSendASync() because you are forced to implement a handler anyway.

I am disappointed in this architecture. This does not make sense.

Even worse: the Strategy Tester and demo accounts do not show this behaviour, so to properly test my implementation I need to do trades on an actual live account. @MetaQuotes: please emulate this behaviour in your Strategy Tester and on demo accounts so programmers can better test their code. It is not nice to discover this after months of successful demo trading.

I understand your feeling but they will not change anything obviously, it's know behaviour since 2014 at least (and fortunately as it would break a lot of existing code).

It may happen on demo account too, I have seen it, though it's rare as they are is no real order processing in this case.

May I ask why you need to know price just after OrderSend() returned ?

 
Alain Verleyen #:

they will not change anything [...] as it would break a lot of existing code.

Yes, but it would be helpful if the strategy tester and demo account showed the same behaviour to enable coders to make sure their code is robust.

Alain Verleyen #:

May I ask why you need to know price just after OrderSend() returned ?

My EA keeps a detailed transaction log showing recent ticks, the full MqlTradeRequest structure, the exact time the request was send, the full MqlTradeResult, the exact latency/duration of the round-trip to the server, the ping time, and also the slippage we got from the broker. For that last one, I obviously need to know the open price.

Having such detailed logging has helped me to keep brokers honest and in one case made it clear the broker was cheating. I had all the evidence to show.

Inspired by the great MT4Orders library of @fxsaber (https://www.mql5.com/ru/code/16006), I now implemented a busy-wait loop that actively polls the HistoryDeals until the corresponding deal appears. When the market opens on Monday I will give it a try to see how long MT5 needs before it updates its internal state after OrderSend() returned. Hopefully this is fast enough. I have added a time-out of 5 seconds just in case, but expect it to be milliseconds, not seconds.

MT4Orders
MT4Orders
  • www.mql5.com
Параллельное использование ордерных систем MetaTrader 4 и MetaTrader 5.
 
yoriz #:

Yes, but it would be helpful if the strategy tester and demo account showed the same behaviour to enable coders to make sure their code is robust.

My EA keeps a detailed transaction log showing recent ticks, the full MqlTradeRequest structure, the exact time the request was send, the full MqlTradeResult, the exact latency/duration of the round-trip to the server, the ping time, and also the slippage we got from the broker. For that last one, I obviously need to know the open price.

Having such detailed logging has helped me to keep brokers honest and in one case made it clear the broker was cheating. I had all the evidence to show.

Inspired by the great MT4Orders library of @fxsaber (https://www.mql5.com/ru/code/16006), I now implemented a busy-wait loop that actively polls the HistoryDeals until the corresponding deal appears. When the market opens on Monday I will give it a try to see how long MT5 needs before it updates its internal state after OrderSend() returned. Hopefully this is fast enough. I have added a time-out of 5 seconds just in case, but expect it to be milliseconds, not seconds.

I really don't get why you need to use a timer or a loop when you have events at your disposal. Anyway...

 
Alain Verleyen #:

I really don't get why you need to use a timer or a loop when you have events at your disposal. Anyway...

Because I want to log more than just the open price/slippage, and I want my logs to be in chronological order.

Using events would either require me to log bits and pieces in multiple messages all referring to the same transaction. As a human reading back the log, I need to try to collect all info at different places.

The alternative is to store the transaction details in a data structure, and log all in one message once the event comes in. But then the log messages are no longer in chronological order. The EA might have logged why it decided to make a trade, logged some values of internal state, made the trade, logged some results, etc. And then several messages later the transaction details will be logged delayed.

To properly do this, I would need to create a log mechanism that sorts messages and only writes to disk with a delay, but that is much to complex for what it is: simply a text file with messages.

 
yoriz #:

how long MT5 needs before it updates its internal state after OrderSend() returned. Hopefully this is fast enough.н

Typically, this is a few milliseconds. It rarely exceeds a second, but it happens.

yoriz #:

I want my logs to be in chronological order.

A full OrderSend-function response is important for this as well. It also makes writing code much easier.

Reason: