TradeDispatcher: trade context is busy

 

Hi all,

To open an order I use the below routine so it will try again if the order failed because of the "trade context is busy" error.
But recently, orders are occasionally being missed because the initial attempt failed because of the trade context is busy error but there are no retries to be found in the log.
I am using a demo account. Could be that the trade failed but the ticket is not -1? Or is there something else I am missing? Thanks for any help.

ticket=OrderSend(Symbol(),order.type,lot.size,price,slip,0,0,0,Magic,0,0);
           
if(ticket<0){
   for(i=0;i<Retries;i++){
          while(IsTradeContextBusy())Sleep (10);
          RefreshRates();
          ticket=OrderSend(Symbol(),order.type,lot.size,price,slip,0,0,0,Magic,0,0);  
          if(ticket>0)break;
          if(i==Retries-1)Print("Could not open order. Error code = ",GetLastError());
         }
     }
 

Q. Why did the first OrderSend fail ?

A. You don't know because you don't check . . .

Some info: What are Function return values ? How do I use them ?

Q. Why is the Trade Context busy ?

 
Dingetje:

Hi all,

To open an order I use the below routine so it will try again if the order failed because of the "trade context is busy" error.
But recently, orders are occasionally being missed because the initial attempt failed because of the trade context is busy error but there are no retries to be found in the log.
I am using a demo account. Could be that the trade failed but the ticket is not -1? Or is there something else I am missing? Thanks for any help.

Why don't you run that first OrderSend() inside the for loop with i <= Retries ?. And every time you have the ticket, whether > 0, == 0, or < 0, print it, check the err if any, work on that err to see if it's worth retrying. There's this script called trade.mq4 in your script folder, it print the err description - copy that.

Is demo thing, may be your returned ticket is > 0, but broker was reset the server, so no order opened.

(btw, GetLastError() = 146 is "Trade Context is Busy").

 
RaptorUK:

Q. Why did the first OrderSend fail ?

A. You don't know because you don't check . . .

Some info: What are Function return values ? How do I use them ?

Q. Why is the Trade Context busy ?


Hi Raptor,

According to the docs OrderSend returns either the ticket number in case of success or -1 in case of failure.

The first OrderSend failed because of the trade context being busy.
14:59:54 '32794': order sell 4.50 EURUSD opening at 1.27625 sl: 0.00000 tp: 0.00000 failed [Trade context is busy]
14:59:54 TradeDispatcher: trade context is busy
Most likely because another EA was doing some order operations at the same time.
But regardless of the reason why the trade context is busy, there are only two options:
ticket no or -1. If the outcome is -1, the routine of trying again should kick in and after it still fails
after a x number of retries, the error codes gets printed. In the case at hand, the order fails (ticket should be -1, correct?) and yet the retry routine does not start.
Most of the times the code works but occasionaly and, in my view, randomly it doesn't. I have put in some extra print statements to see whether ticket can be != -1 and
still not placing the trade succesfully, but I would like to know if this is a known problem beforehand because I don't know when it will occur again.







 
Dingetje:

Hi Raptor,

According to the docs OrderSend returns either the ticket number in case of success or -1 in case of failure.

The first OrderSend failed because of the trade context being busy.
14:59:54 '32794': order sell 4.50 EURUSD opening at 1.27625 sl: 0.00000 tp: 0.00000 failed [Trade context is busy]
14:59:54 TradeDispatcher: trade context is busy
Most likely because another EA was doing some order operations at the same time.
But regardless of the reason why the trade context is busy, there are only two options:
ticket no or -1. If the outcome is -1, the routine of trying again should kick in and after it still fails
after a x number of retries, the error codes gets printed. In the case at hand, the order fails (ticket should be -1, correct?) and yet the retry routine does not start.
Most of the times the code works but occasionaly and, in my view, randomly it doesn't. I have put in some extra print statements to see whether ticket can be != -1 and
still not placing the trade succesfully, but I would like to know if this is a known problem beforehand because I don't know when it will occur again.

Your code does not know why the first OrderSend failed . . . you make the assumption it is because the trade context is busy . . the smart thing to do would be for your code to check the Error and act accordingly . . . for example if the error was error 131 you wouldn't want to keep retrying . .

The best way to avoid Trade Context is busy due to another EA is to use a Mutex . . . WHRoeder has posted code and I believe there is an article regarding using a Mutex. Found it: https://www.mql5.com/en/articles/1412

 
RaptorUK:

Your code does not know why the first OrderSend failed . . . you make the assumption it is because the trade context is busy . . the smart thing to do would be for your code to check the Error and act accordingly . . . for example if the error was error 131 you wouldn't want to keep retrying . .

The best way to avoid Trade Context is busy due to another EA is to use a Mutex . . . WHRoeder has posted code and I believe there is an article regarding using a Mutex. Found it: https://www.mql5.com/en/articles/1412


Thanks Raptor and Onewithzachy for your comments. I understand there is some improvement to be done. But whatever the reason for the first failure was, the return value of OrderSend can be != to -1 and still be not successfull? (Other than what the documentation sais on this subject)
 
Dingetje:

But whatever the reason for the first failure was, the return value of OrderSend can be != to -1 and still be not successfull?

No. I don't think it can . . . at least that is what the documentation says.

Add more print statements, so you know where you code is going . . .

ticket=OrderSend(Symbol(),order.type,lot.size,price,slip,0,0,0,Magic,0,0);
           
if(ticket<0){
   Print("OrderSend failed, Error: ", GetLastError() );    // add this line
   for(i=0;i<Retries;i++){
          Print("Retrying OrderSend() #", i);         // add this line 
          while(IsTradeContextBusy())Sleep (10);
          RefreshRates();                                                              // <-----  this is pointless . . .
          ticket=OrderSend(Symbol(),order.type,lot.size,price,slip,0,0,0,Magic,0,0);  
          if(ticket>0)break;
          if(i==Retries-1)Print("Could not open order. Error code = ",GetLastError());
         }
     }

The RefreshRates() is pointless, you are not using any PredefinedVariables in your OrderSend . . . perhaps your price variable is stale and needs to be refreshed . . . but you would get an error if that was the case.

 

If you simply want to trap the context-is-busy error, why not do something like the following:

 int TicketID = 0, MaxRetries = 5, counter = 1, err_code = 0;
 while (TicketID <= 0 && counter <= MaxRetries)
  {
    TicketID = OrderSend(Symbol(),order.type,lot.size,price,slip,0,0,0,Magic,0,0);
    if (TicketID > 0)
      break;  // OrderSend was successful
    else
      {
        err_code = GetLastError();
        if (err_code != ERR_TRADE_CONTEXT_BUSY)
          {
            Print ("An error has occurred while using OrderSend.  Error Code: ", err_code);
            break;  // exit due to unhandled error
          }
      }
    if (counter == MaxRetries)
      Print ("Maximum number of OrderSend retries has been reached.");
    else
      err_code = 0;  // clear var for next iteration
    counter++;
  }

This code is only an example that I created in a text editor and has not been complied (so there may be an error, please forgive me).

I think it is important that each time you use OrderSend, you should determine not only whether it failed (or was successful), but why it failed (i.e., by checking the result of OrderSend).

I would also try to stay away from Sleep(). It doesn't work well in MT4's strategy tester (see here and Testing Features and Limits in MT4).

I hope some of this helps.

 

Hi,

I have the same problem in the past, then I write a part of code which could help you.

=================

if (TradeLongNow ==true && TimeStamp != Time[0] && cb < MaxOrderLong && TimeCurrent() < SetupValideUp)
{
while(true)
{
ticket=OrderSend(Symbol(),OP_BUYSTOP,Lots,Ask+StopLevel*Point,Slippage,0,0,Period()+" TDMa w123",Magic,iTime(Symbol(),0,0)+ExpirationOrder*60,Lime);
if(ticket<=0) Print("Error = ",GetLastError()," Broker Manipulation ",StopLevel," ",spread," ",Ask+StopLevel*Point);
else { Print("ticket = ",ticket); break; }
Sleep(10000);
}
TimeStamp = Time[0];

}

================

 
Thirteen:

I would also try to stay away from Sleep(). It doesn't work well in MT4's strategy tester (see here and Testing Features and Limits in MT4).

The Strategy Tester doesn't simulate Trade Context is Busy either so I guess that means we don't need to check for it ? why didn't you just use a Mutex ?
 

The Strategy Tester doesn't simulate Trade Context is Busy either so I guess that means we don't need to check for it ?

Hmm...that is not really what I meant. I was simply attempting to steer the OP away from using Sleep() without adjusting for use in the tester by providing additional information via the links.

why didn't you just use a Mutex ?

Well, to be honest, I have read the posts (here and here) regarding a mutex, but I don't fully understand them yet (but I will continue to review the concept and the code). Please forgive some of my ignorance; I'm still learning. :)

Reason: