Invalid Ticket (ERR_INVALID_TICKET) error, Server time vs. Terminal time

 
The way the backend server works at my broker, after a pending order is filled, a new ticket is assigned to the filled order and the old one is deleted. Because they are an ECN, orders may even get split and from a single pending order I may get more than one filled order. I am using the following code in my EA and at times I get the invalid ticket error ERR_INVALID_TICKET. I don't get that every time but frequently enough trading 5 min charts.

for (int i = OrdersTotal() - 1; i >= 0; i--) {
    if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) {
        if (OrderSymbol() != Symbol())
            continue;

    if (OrderCloseTime() > 0)
        continue;

    int ticket = OrderTicket();
    int type = OrderType();

    switch (type) {
        case OP_BUY:
            // Buy order trailing stop: modify the order with ticket# 'ticket'
            break;

        case OP_SELL:
            // Sell order trailing stop: modify the order with ticket# 'ticket'
            break;
        ...
    }
    ...
}
As you see I am explicitly passing MODE_TRADES to OrderSelect(), only if the order is not closed I check the OrderType(), only if it is an open order (OP_BUY or OP_SELL) I'll modify it. OrderModify() is passed the same OrderTicket() selected here but sometimes fails with the ERR_INVALID_TICKET error.

Provided detailed logs and info to my broker. They claim that in the instances they have investigated the invalid tickets were deleted in their backend "bridge" 6 seconds before it was attempted to be modified. Here I am quoting a couple of their responses worth mentioning:

"May be it is related to client’s terminal specific, especially to functions pair OrdersTotal+ OrderSelect – may be these calls caching current position state. In any case there is question for MT4 support."
...
"May be time difference between [the] server and client’s machine was 6 seconds and orders disappears between OrderSelect and OrderModify calls. It’s most probable case, because clients EA trying to change s/l based on market data tick and your system executing orders based on the same tick, but executions from [the server] side coming faster than clients changing s/l. So at OrderSelect call order still open, but at OrderModify call order does not exist. So have error message in the client’s terminal log."

FYI, I purposely set the Windows clock time zone to EST which is the same time zone as the broker's server and I do not see 6 sec time delay with the clocks on the Internet.

So, the blame so far is on the MT4 Terminal either caching stuff or lagging behind in the order of 6 seconds at times. Please note that the above code is on top of the function which is called at every tick from the beginning of the start() in the EA. And with latest Intel processors I cannot imagine the code processing from OrderSelect() to OrderModify() ever takes more than milliseconds, let alone seconds.

Here are the questions?
1. Am I doing something wrong? Can I improve anything to avoid this situation in the EA? ... Yes, I do check the return from OrderModify() and have proper error recovery path.

2. Has anyone experienced the same with their brokers?

3. Does MT4 cache anything with respect to order tickets and order pools?

4. Wouldn't MT4 Terminal try to stay in sync with the server?

5. Any comments on the broker's assertions above?

Thanks
 
bbehzadimql:
1. Am I doing something wrong? Can I improve anything to avoid this situation in the EA? ... Yes, I do check the return from OrderModify() and have proper error recovery path.

To solve your problem it's important to understand how OrderSelect() works: when u select a ticket using OrderSelect() a buffer is filled with all order details (the ones u get when u call OrderTicket(), OrderCloseTime(), etc.). This buffer is NOT a dynamic buffer. The values in it will remain constant until the next time u call OrderSelect()!

From your code:

if (OrderCloseTime() > 0)
continue;
This part is completely pointless; since u selected the order from the trading pool (MODE_TRADES) the order was open while selected, hence the expression will always evaluate FALSE (as I said - the buffer is static, it will not change until the next time u call OrderSelect(), even if the selected order was closed in the meanwhile...).

Your problem is that between the time u call OrderSelect() and the time u call OrderModify() the ticket number changes. I would do the following:
  1. Try to minimize the code between the OrderSelect() and OrderModify() calls as much as possible (if at all possible).
  2. Add logic to restart the loop in case this error happens (many ways to do this...).

Another possible solution is to attempt selecting the order again just before OrderModify(). That might lower the number of errors considerably (but in theory there still might be errors):
//reselect order just before attempting OrderModify()
if ( OrderSelect(ticket,SELECT_BY_TICKET) && OrderCloseTime()==0 )
   OrderModify(...)
else
   //do something... maybe restart the entire loop
2. Has anyone experienced the same with their brokers?
Only very very rarely. But it does happen.

3. Does MT4 cache anything with respect to order tickets and order pools?
Not sure what u mean by this.

4. Wouldn't MT4 Terminal try to stay in sync with the server?
It does and is.

5. Any comments on the broker's assertions above?
The comment regarding the time difference between server and client clocks is bull. It's completely irrelevant what time the local clock is set to (unless u refer to TimeLocal() in your code). There is no reason to attempt 'syncing' these clocks... And their other comments are not very accurate... But as they said - these are really questions for MQ support and for the broker, since they are highly technical and are regarding the client (not the server).
 
If have seen this with the tester.
Do not assume that in a real-money EA that a stop or take profit will actually be executed if the price has gone through that value. Yes, they are unethical and mean. --LibOrderReliable
I have code that checks for market below the SL. I was seeing the market several points below SL and the forced orderClose failed with 4108, unknown ticket.
So I changed that test from now-SL<0 to now-SL< -pip which fixed that.

In your case you should also be checking for now-SL < minGaps.change and TP-now < minGaps.change
If either of these are true then you can't even attempt to modify or close the order.
minGap.stops  = MarketInfo( Symbol(), MODE_STOPLEVEL )*Point;
minGap.change = MathMax(minGap.stops, MarketInfo( Symbol(), MODE_FREEZELEVEL )*Point);
Also once you do a single order send, modify, close or delete, you must call RefreshRates() before any additional order processing, as significant time can elapse during that call.

And next time USE THE SRC button before pasting code.
 
*IMHO* LibOrderReliable is an outdated buggy piece of $hit... *IMHO*
 
gordon:

...
From your code:

This part is completely pointless; since u selected the order from the trading pool (MODE_TRADES) the order was open while selected, hence the expression will always evaluate FALSE (as I said - the buffer is static, it will not change until the next time u call OrderSelect(), even if the selected order was closed in the meanwhile...).
Yes in theory that is correct. While debugging this problem, first I added MODE_TRADES explicitly as the 3rd arg to OrderSelect() - not assuming the default. Then I added the check for OrderClose() with a debug message and to my surprise I did get that a few times. I must say it was rare but I DID have closed tickets after successful OrderSelect(). That's why I have been arguing with the broker that there's something wrong with their Trade Pool. Even after they admitted the problem they are saying "so what":

"We have two async processes: one is [the] terminal,another is [the ECN] bridge ..they are not coordinated …

[EA] has to assume that position might be closed after he selected it …"

 
gordon:
...
Your problem is that between the time u call OrderSelect() and the time u call OrderModify() the ticket number changes. I would do the following:
  1. Try to minimize the code between the OrderSelect() and OrderModify() calls as much as possible (if at all possible).
  2. Add logic to restart the loop in case this error happens (many ways to do this...).

Another possible solution is to attempt selecting the order again just before OrderModify(). That might lower the number of errors considerably (but in theory there still might be errors):
Only very very rarely. But it does happen.
...

I am doing exactly as you are suggesting in (1) and (2) above. And just before calling OrderModify() I call OrderSelect(ticket, SELECT_BY_TICKET) with the given ticket and AGAIN I am checking if OrderCloseTime() returns >0 or not. If it does, I won't call OrderModify(). Still the problem occurs.

 
gordon:
...
The comment regarding the time difference between server and client clocks is bull. It's completely irrelevant what time the local clock is set to (unless u refer to TimeLocal() in your code). There is no reason to attempt 'syncing' these clocks... And their other comments are not very accurate... But as they said - these are really questions for MQ support and for the broker, since they are highly technical and are regarding the client (not the server).

No, I do not use TimeLocal() and as a matter of fact I have set my PC Windows time zone to that of the broker server's time zone.

Not sure what you mean by your last sentence. What they meant by MT4 support (I think) I had to get help outside the broker, from MetaQuotes or this community or ...

Thanks a lot for your insightful responses gordon.

 
WHRoeder:
If have seen this with the tester.I have code that checks for market below the SL. I was seeing the market several points below SL and the forced orderClose failed with 4108, unknown ticket.
So I changed that test from now-SL<0 to now-SL< -pip which fixed that.

In your case you should also be checking for now-SL < minGaps.change and TP-now < minGaps.change
If either of these are true then you can't even attempt to modify or close the order.
Also once you do a single order send, modify, close or delete, you must call RefreshRates() before any additional order processing, as significant time can elapse during that call.

And next time USE THE SRC button before pasting code.

Sorry about the SRC issue. Just editted and added the code in the proper format. ... other than that I don't see any relevance in what your saying.

 
bbehzadimql:
Yes in theory that is correct. While debugging this problem, first I added MODE_TRADES explicitly as the 3rd arg to OrderSelect() - not assuming the default. Then I added the check for OrderClose() with a debug message and to my surprise I did get that a few times. I must say it was rare but I DID have closed tickets after successful OrderSelect(). That's why I have been arguing with the broker that there's something wrong with their Trade Pool. Even after they admitted the problem they are saying "so what":

"We have two async processes: one is [the] terminal,another is [the ECN] bridge ..they are not coordinated …

[EA] has to assume that position might be closed after he selected it …"

This is the first time I have heard of such problems. Weird indeed.

I don't have any other suggestions except that there are plenty of brokers out there... No reason to stick to one u r not happy with. Good luck!

 
gordon:
*IMHO* LibOrderReliable is an outdated buggy piece of $hit... *IMHO*

I didn't say I used it, only used the quote.

other than that I don't see any relevance in what your saying.

If the market is that close to your stop/take you can't modify it (it would be rejected) and that would eliminate the problem, On the next tick the order would have closed.
 
WHRoeder:

I didn't say I used it, only used the quote.

If the market is that close to your stop/take you can't modify it (it would be rejected) and that would eliminate the problem, On the next tick the order would have closed.

No, more often than not, the market is at a distance from where I am moving the stop. Thanks for the thought, though.

Reason: