Partial Closing of orders - HELP PLEASE

 

Within my EA I want to partially close all open trades (eg close 50% of all open trades). The problem is how to do it!

If I do a for (i = 0; i < OrdersTotal(); i++) and then select orders by position when I close an order the system will open a new trade with the balance of the lots from the old trade. Then what happens is either the trade partially closes the next ok or a change of positions of the trades on the server will cause the code to take 50% of the newly opened trade. The second condition also results in one of the original trades not being partially closed at all. Using magic numbers will not work more than once because you can not change them (I am also not sure what happens with the newly opened system trade with respect to magic numbers - anyone know?). I really do not want to track individual ticket numbers either.

ANY IDEAS PLEASE.

 
BigAl:

Within my EA I want to partially close all open trades (eg close 50% of all open trades). The problem is how to do it!

If I do a for (i = 0; i < OrdersTotal(); i++)

Your problem is largely related to the fact that you're counting up through to OrdersTotal() while simultaneously doing something which affects the number of open orders. Have a think about the number of orders versus the value of the loop variable i on each iteration.


The following alternative, counting from OrdersTotal() - 1 downwards, works for me. However, I personally wouldn't use this because it includes an assumption that new orders will be appended to the end of the open-order list. The MQL documentation doesn't guarantee that the order list will be sorted in this way. Personally, despite the fact that you "do not want to track individual ticket numbers", I'd do a loop through the open orders storing their ticket numbers in an array, and then run through the array altering the orders by looking at the ticket numbers recorded there.


   // Example orders
   OrderSend(Symbol(), OP_BUY, 0.2, MarketInfo(Symbol(), MODE_ASK), 999, 0, 0);
   OrderSend(Symbol(), OP_BUY, 0.2, MarketInfo(Symbol(), MODE_ASK), 999, 0, 0);

   // Close 50% of each order (assuming that the lot size is exactly divisible by 2, and that the orders are buys)
   for (int i = OrdersTotal() - 1; i >= 0; i--) {
      if (OrderSelect(i, SELECT_BY_POS)) {
         OrderClose(OrderTicket(), OrderLots() / 2, MarketInfo(Symbol(), MODE_BID), 9999);
      }
   }
 
jjc wrote >>

Your problem is largely related to the fact that you're counting up through to OrdersTotal() while simultaneously doing something which affects the number of open orders. Have a think about the number of orders versus the value of the loop variable i on each iteration.

The following alternative, counting from OrdersTotal() - 1 downwards, works for me. However, I personally wouldn't use this because it includes an assumption that new orders will be appended to the end of the open-order list. The MQL documentation doesn't guarantee that the order list will be sorted in this way. Personally, despite the fact that you "do not want to track individual ticket numbers", I'd do a loop through the open orders storing their ticket numbers in an array, and then run through the array altering the orders by looking at the ticket numbers recorded there.

Thanks for the response - counting downwards doesn't work as the number of orders does not change and you can't guarantee the order as you correctly state.

An array would solve the problem but as I am trading lots of pairs the number of open trades would cause a considerable time overhead and that in itself would cause a problem. I would have to rebuild the array everytime I want to take 50% as their is no way of knowing the trade numbers of previously opened system trades (whereas ticket numbers of trades generated directly by my EA are easily added to an array). Those generated by the system would need looking for as would those ticket numbers that were made invalid by the trade being completely closed. (Why does a partially closed trade get a completely new ticket number?

Anyone else have any other ideas please

 
BigAl:

An array would solve the problem but as I am trading lots of pairs the number of open trades would cause a considerable time overhead [...]

What are you calling "considerable"? For example, the following code copies the ticket numbers of all open orders into an array and, on my perfectly normal hardware, it takes about 60 microseconds to execute on a list of 100 open orders:


   int OrderTickets[];
   int ctTickets = 0;
   for (int i = 0; i < OrdersTotal(); i++) {
      if (OrderSelect(i, SELECT_BY_POS)) {
         ctTickets++;
         ArrayResize(OrderTickets, ctTickets);
         OrderTickets[ctTickets - 1] = OrderTicket();
      }
   }

If 60 microseconds is too slow, then MT4 is probably the wrong platform given the - comparatively - enormous amount of time it takes to place/modify/close orders. Or, in backtesting, assuming a fairly high 0.5 simulated ticks per second, it's going to add about 2 minutes to the time taken to back-test over 1 year of trading data, and that's assuming that you'd need to do the array population on every single tick.

 
jjc wrote >>

What are you calling "considerable"? For example, the following code copies the ticket numbers of all open orders into an array and, on my perfectly normal hardware, it takes about 60 microseconds to execute on a list of 100 open orders:

If 60 microseconds is too slow, then MT4 is probably the wrong platform given the - comparatively - enormous amount of time it takes to place/modify/close orders. Or, in backtesting, assuming a fairly high 0.5 simulated ticks per second, it's going to add about 2 minutes to the time taken to back-test over 1 year of trading data, and that's assuming that you'd need to do the array population on every single tick.

OK I will take your word for it and give it a go. I thought it would take longer than that especially with all the delays of the net in South Africa. I already suffer with lots of requotes etc and even using context error prevention still get the occassional 129, 130 type errors but have been considering a server in another country so I guess its time to do it!! if I still get problems I will get back to you. For the time being assume its ok and working on a server somewhere else in the world unless you hear from me again within a week. Thanks again for your input

Reason: