Error when closing positions at the end of the day: 10036 - TRADE_RETCODE_POSITION_CLOSED

 

Hello guys!

I've been racking my brain for days with errors that I'm having to close positions at the end of the day by time if I am still positioned. I already searched the forum and Google and I didn't find anything to solve it.

I have always used this logic for years and it has always worked, but recently it started to have some errors. The positions are closed correctly at the parameterized time, but the error occurs.

In fact, errors vary, in the order that they most often occur:

  • 10036 - TRADE_RETCODE_POSITION_CLOSED
  • 10039 - TRADE_RETCODE_CLOSE_ORDER_EXIST
  • 10014 - TRADE_RETCODE_INVALID_VOLUME

My suspicion was that the CTrade class PositionClose call was being called more than once due to the high volume/ticks of brazilian mini index (WINV20), that before the end of processing a tick with the position closed, another tick was already calling the OnTick procedure simultaneously and so was calling PositionClose repeatedly. Then I researched in more detail about how MT5 works and in the documentation it appears that the ticks do not run in parallel and do not queue, a new tick will only be processed when the previous one finishes processing. So I ended up dropping that option.

I also thought it might be a problem with the loop to find the position of the respective EA, as there are days like today that there were 6 positions opened at the end of the day and all closed at the same time, if the first position had been closed before the last one EA processing the loop completely and selecting its position, could give some problem in the position selection, since the order of the positions change and interfere with the PositionGetTicket function. However, if it hadn't found the position, it wouldn't have executed the PositionClose command, so I wouldn't have given the error. And even if there is this interference in the loop and it can't find the position in OnTick, in the next tick the function would be executed again and find the position. But this is not the case because as we will see in the log below, the function is only being called once.

My entire code is really big so I'm going to put just the relevant sections. I put some extra prints to try to identify the problem.

This excerpt is in a function called by OnTick:

   // Close position at the end of the day if position are opened
   if(SymbolHasPosition && EAhasPosition && current_time >= TimeMaxClose && DayTrade == true)
     {
      Print("Closing position at the end of the day for EA ",EA_Magic);
      ClosePosition();
      Print("Sleeping 10 seconds...");
      Sleep(10000);
      Print("Awake");
      return false;
     }

I even tried to use Sleep to not execute another closing call without having completed the previous one.

This is the ClosePosition function called in the previous section.

CTrade trade;

bool ClosePosition()
  {
      bool res_order=true,res_order1=true;
      
      Print("Calling function ClosePosition for EA ",EA_Magic);

      if(HedgeAccount == true)
        {
         for(int i=PositionsTotal()-1; i>=0; i--)
           {
            ticket_position = PositionGetTicket(i);
            if(PositionSelectByTicket(ticket_position)==true)
              {
               if(PositionGetString(POSITION_SYMBOL)==_Symbol && PositionGetInteger(POSITION_MAGIC)==EA_Magic)
                 {
                  res_order1 = trade.PositionClose(ticket_position);
                  if(!res_order1)
                     res_order = false;
                 }
              }
           }
         ticket_position = 0;
        }
      else
         res_order = trade.PositionClose(_Symbol);
   
      // Check order result
      if(res_order == false || (trade.ResultRetcode() != TRADE_RETCODE_DONE && trade.ResultRetcode() != TRADE_RETCODE_PLACED))
        {
         Alert("The order request could not be completed. Return code=",trade.ResultRetcode(),". Code description: ",trade.ResultRetcodeDescription());
         return false;
        }

      return true;
  }

In it I deal with hedge and netting accounts. I am using a hedge account and I operate multiple EAs on the same symbol.

Now the log of the Experts tab of today's execution:

2020.09.10 17:38:59.982 EA1 (WINV20,M10) Closing position at the end of the day for EA 1
2020.09.10 17:38:59.982 EA1 (WINV20,M10) Calling function ClosePosition for EA 1
2020.09.10 17:38:59.982 EA2 (WINV20,M20) Closing position at the end of the day for EA 2
2020.09.10 17:38:59.982 EA2 (WINV20,M20) Calling function ClosePosition for EA 2
2020.09.10 17:38:59.982 EA3 (WINV20,M20) Closing position at the end of the day for EA 3
2020.09.10 17:38:59.982 EA3 (WINV20,M20) Calling function ClosePosition for EA 3
2020.09.10 17:38:59.982 EA4 (WINV20,M30) Closing position at the end of the day for EA 4
2020.09.10 17:38:59.982 EA4 (WINV20,M30) Calling function ClosePosition for EA 4
2020.09.10 17:38:59.982 EA5 (WINV20,M15) Closing position at the end of the day for EA 5
2020.09.10 17:38:59.982 EA5 (WINV20,M15) Calling function ClosePosition for EA 5
2020.09.10 17:38:59.982 EA6 (WINV20,H1)  Closing position at the end of the day for EA 6
2020.09.10 17:38:59.982 EA6 (WINV20,H1)  Calling function ClosePosition for EA 6
2020.09.10 17:38:59.997 EA1 (WINV20,M10) Sleeping 10 seconds...
2020.09.10 17:39:00.004 EA2 (WINV20,M20) Sleeping 10 seconds...
2020.09.10 17:39:00.063 EA3 (WINV20,M20) Sleeping 10 seconds...
2020.09.10 17:39:00.067 EA4 (WINV20,M30) CTrade::OrderSend: exchange buy 3.00 position #286375387 WINV20 [position closed]
2020.09.10 17:39:00.067 EA4 (WINV20,M30) Alert: The order request could not be completed. Return code=10036. Code description: position closed
2020.09.10 17:39:00.067 EA4 (WINV20,M30) Sleeping 10 seconds...
2020.09.10 17:39:00.067 EA6 (WINV20,H1)  CTrade::OrderSend: exchange sell 3.00 position #286380535 WINV20 [position closed]
2020.09.10 17:39:00.067 EA6 (WINV20,H1)  Alert: The order request could not be completed. Return code=10036. Code description: position closed
2020.09.10 17:39:00.067 EA6 (WINV20,H1)  Sleeping 10 seconds...
2020.09.10 17:39:00.067 EA5 (WINV20,M15) CTrade::OrderSend: exchange buy 3.00 position #286375546 WINV20 [invalid volume]
2020.09.10 17:39:00.067 EA5 (WINV20,M15) Alert: The order request could not be completed. Return code=10014. Code description: invalid volume
2020.09.10 17:39:00.067 EA5 (WINV20,M15) Sleeping 10 seconds...
2020.09.10 17:39:10.937 EA1 (WINV20,M10) Awake
2020.09.10 17:39:10.937 EA2 (WINV20,M20) Awake
2020.09.10 17:39:10.999 EA3 (WINV20,M20) Awake
2020.09.10 17:39:10.999 EA6 (WINV20,H1)  Awake
2020.09.10 17:39:10.999 EA5 (WINV20,M15) Awake
2020.09.10 17:39:11.000 EA4 (WINV20,M30) Awake

Note that by the messages, both the first code and the ClosePosition function are executed only once by EA. So it is illogical that the Position error has already been closed. If we look at the History tab, the 6 positions were closed correctly at the same time in the log.

This is the detailed log of operations:

2020.09.10 17:38:59.982 Trades 'XXXXX': exchange buy 3 WINV20 at market, close #286375386 sell 3 WINV20 100350
2020.09.10 17:38:59.982 Trades 'XXXXX': exchange buy 3 WINV20 at market, close #286375963 sell 3 WINV20 100210
2020.09.10 17:38:59.982 Trades 'XXXXX': exchange buy 3 WINV20 at market, close #286374454 sell 3 WINV20 100765
2020.09.10 17:38:59.982 Trades 'XXXXX': exchange buy 3 WINV20 at market, close #286375387 sell 3 WINV20 100350
2020.09.10 17:38:59.982 Trades 'XXXXX': exchange buy 3 WINV20 at market, close #286375546 sell 3 WINV20 100350
2020.09.10 17:38:59.982 Trades 'XXXXX': exchange sell 3 WINV20 at market, close #286380535 buy 3 WINV20 98725
2020.09.10 17:38:59.984 Trades 'XXXXX': accepted exchange buy 3 WINV20 at market, close #286375963 sell 3 WINV20 100210
2020.09.10 17:38:59.984 Trades 'XXXXX': accepted exchange buy 3 WINV20 at market, close #286375386 sell 3 WINV20 100350
2020.09.10 17:38:59.984 Trades 'XXXXX': accepted exchange buy 3 WINV20 at market, close #286374454 sell 3 WINV20 100765
2020.09.10 17:38:59.985 Trades 'XXXXX': accepted exchange buy 3 WINV20 at market, close #286375387 sell 3 WINV20 100350
2020.09.10 17:38:59.985 Trades 'XXXXX': accepted exchange buy 3 WINV20 at market, close #286375546 sell 3 WINV20 100350
2020.09.10 17:38:59.985 Trades 'XXXXX': accepted exchange sell 3 WINV20 at market, close #286380535 buy 3 WINV20 98725
2020.09.10 17:38:59.985 Trades 'XXXXX': exchange buy 3 WINV20 at market, close #286375963 sell 3 WINV20 100210 placed for execution
2020.09.10 17:38:59.985 Trades 'XXXXX': exchange buy 3 WINV20 at market, close #286375386 sell 3 WINV20 100350 placed for execution
2020.09.10 17:38:59.985 Trades 'XXXXX': exchange buy 3 WINV20 at market, close #286374454 sell 3 WINV20 100765 placed for execution
2020.09.10 17:38:59.986 Trades 'XXXXX': exchange buy 3 WINV20 at market, close #286375387 sell 3 WINV20 100350 placed for execution
2020.09.10 17:38:59.986 Trades 'XXXXX': exchange sell 3 WINV20 at market, close #286380535 buy 3 WINV20 98725 placed for execution
2020.09.10 17:38:59.986 Trades 'XXXXX': exchange buy 3 WINV20 at market, close #286375546 sell 3 WINV20 100350 placed for execution
2020.09.10 17:38:59.997 Trades 'XXXXX': order #286381556 buy 3   3 WINV20 at market done in 15.111 ms
2020.09.10 17:38:59.998 Trades 'XXXXX': deal #16797436 buy 3 WINV20 at 98730 done (based on order #286381556)
2020.09.10 17:39:00.003 Trades 'XXXXX': order #286381557 buy 3   3 WINV20 at market done in 21.401 ms
2020.09.10 17:39:00.009 Trades 'XXXXX': deal #16797439 buy 3 WINV20 at 98730 done (based on order #286381557)
2020.09.10 17:39:00.063 Trades 'XXXXX': order #286381558 buy 3   3 WINV20 at market done in 81.331 ms
2020.09.10 17:39:00.064 Trades 'XXXXX': deal #16797444 buy 3 WINV20 at 98730 done (based on order #286381558)
2020.09.10 17:39:00.064 Trades 'XXXXX': order #286381559 buy 3   3 WINV20 at market done in 81.768 ms
2020.09.10 17:39:00.064 Trades 'XXXXX': deal #16797445 buy 3 WINV20 at 98730 done (based on order #286381559)
2020.09.10 17:39:00.064 Trades 'XXXXX': exchange buy 3 WINV20 at market
2020.09.10 17:39:00.064 Trades 'XXXXX': order #286381561 sell 3   3 WINV20 at market done in 82.016 ms
2020.09.10 17:39:00.064 Trades 'XXXXX': deal #16797446 sell 2 WINV20 at 98725 done (based on order #286381561)
2020.09.10 17:39:00.064 Trades 'XXXXX': exchange sell 3 WINV20 at market, close #286380535 buy 1 WINV20 98725
2020.09.10 17:39:00.064 Trades 'XXXXX': deal #16797447 sell 1 WINV20 at 98725 done (based on order #286381561)
2020.09.10 17:39:00.065 Trades 'XXXXX': order #286381560 buy 3   3 WINV20 at market done in 82.587 ms
2020.09.10 17:39:00.065 Trades 'XXXXX': deal #16797449 buy 1 WINV20 at 98730 done (based on order #286381560)
2020.09.10 17:39:00.065 Trades 'XXXXX': exchange buy 3 WINV20 at market, close #286375546 sell 2 WINV20 100350
2020.09.10 17:39:00.065 Trades 'XXXXX': deal #16797450 buy 1 WINV20 at 98730 done (based on order #286381560)
2020.09.10 17:39:00.067 Trades 'XXXXX': failed exchange buy 3 WINV20 at market [Position doesn't exist]
2020.09.10 17:39:00.067 Trades 'XXXXX': failed exchange sell 3 WINV20 at market [Position doesn't exist]
2020.09.10 17:39:00.067 Trades 'XXXXX': failed exchange buy 3 WINV20 at market, close #286375546 sell 1 WINV20 100350 [Invalid volume]
2020.09.10 17:39:00.104 Trades 'XXXXX': deal #16797453 buy 1 WINV20 at 98730 done (based on order #286381560)

The position closing logic is very simple, it has no complex treatment. It looks like the issue can be some internal problem in the CTrade class.

Does anyone have any ideas or direction to resolve these errors?

Thank you all!

 
Ok, no anwers at all. But fixed myself. Thanks.
 
rodsibin: Ok, no anwers at all. But fixed myself. Thanks.

Don't do that. Someone searching might find this thread and still be clueless. What was the problem? What solved what?

How To Ask Questions The Smart Way. 2004
     When You Ask.
          Follow up with a brief note on the solution.

 
rodsibin:
Ok, no anwers at all. But fixed myself. Thanks.

Hi I'm having the same problem. I keep getting 10039 - TRADE_RETCODE_CLOSE_ORDER_EXIST , but the order always gets closed with no problem. What was the cause of the issue for you and how did you fix it? Thanks

 

Well I believe the issue was not in my code itself, it is more related to how MT5 processes the requests.

The problem is at this basic classic Positions loop, which all EAs run the same, at the same time at the end of the day:

         for(int i=PositionsTotal()-1; i>=0; i--)
           {
            ticket_position = PositionGetTicket(i);
            if(PositionSelectByTicket(ticket_position)==true)
              {
               if(PositionGetString(POSITION_SYMBOL)==_Symbol && PositionGetInteger(POSITION_MAGIC)==EA_Magic)
                 {
                  res_order1 = trade.PositionClose(ticket_position);
                  if(!res_order1)
                     res_order = false;
                 }
              }
           }

So each EA will close its own position using this code.

Supose there are 10 opened positions for 10 different EAs. The first EA requesting PositionClose had the position #5. The fourth EA requesting had the position #8. Basically all EAs will request at the same time, with a difference of less than 10ms. But some orders will process faster than others (in miliseconds difference).

So if first EA closes position #5 first, all positions numbers above 5 will decrement 1 in the position index. What I noticed is that PositionClose function is not synchronous, so EA will proceed with code execution even if position close order was not completed (successfull or not).

Then fourth EA mentioned above, didn't had its position closed yet but will continue the loop interation and now it will check position #7 while #8 is still in progress. But at this point #8 became #7 in positions index, because #5 was already removed! And here is where the errors happen. EA will try to close the same position again! And it will receive different errors depending of the status of the previous order. If between this time, it was completely closed, the error will be TRADE_RETCODE_POSITION_CLOSED. It it was partially closed by some of the contracts only, the error will be TRADE_RETCODE_INVALID_VOLUME. And some other errors can come depending of the time and status.

My workaround was to create an array of requested closed positions and each time EA calls PositionClose it adds the position ticket on this array. And before trying to close any position, it will check if that ticket is at the array. And Voilà! Problem solved! Never got the errors again.

But I think this position handling should be more automatic from MQL5, because doing a simple position loop has flaws and it is not ideal.

Reason: