Array sorting - page 2

 
Donald Gibson:


Why sort when you can close them with a simple function?

I have been using this function for more than a year now with absolutely no problems.

All I know is it works flawlessly every time in every condition.

 
Donald Gibson:

I have been using this function for more than a year now with absolutely no problems.

All I know is it works flawlessly every time in every condition.

I hate to break it to you bro, but anytime you close an order the order pool shifts, and if you are counting up then I guarantee you are skipping over orders.

Consider the following:

pseudo-pool

pool = [1234, 1235, 1236, 1237] //ticket numbers

 

Now let's say you close an order in the pool @ index 0. Pool has shifted before the next iteration. 

pool = [1235, 1236, 1237]

Your next iteration will be 1, however, since the pool shifted you will skip over ticket 1235 since it was shifted to index 0.  

 
Donald Gibson:

I have been using this function for more than a year now with absolutely no problems.

All I know is it works flawlessly every time in every condition.

Not in every conditions. Follow Nicholishen's advice.

 
Donald Gibson:

I have been using this function for more than a year now with absolutely no problems.

All I know is it works flawlessly every time in every condition.

I just noticed that you're decrementing [i] if you close an order in the loop, which BTW is why I hate when unexpected statements show up on the same line as the expression, ugh. Anyway, this is only ok if this is the only EA running in the terminal. Otherwise, if another EA modifies the pool during the lengthily time in between iterations (while your program is communicating with the broker server) then you're screwed. Also, this implies the assumption that the order pool is always sorted FIFO, and that is also not guaranteed. So let's say you wanted to stick with counting forward, keeping your code small, and accept the risk of not verifying FIFO order -- you'd still want to start iterating the pool from the start after each successful order close. 

 

bool positions_closeall()
{
   for(int i=0; OrderSelect(i, SELECT_BY_POS); i++) {
      if(OrderType() < 2 && OrderSymbol() == _Symbol) {
         if(OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 0)) {
            return positions_closeall();
         }else{
            return false;
         }
      }
   }
   return true;
}
 
nicholi shen:

I just noticed that you're decrementing [i] if you close an order in the loop, which BTW is why I hate when unexpected statements show up on the same line as the expression, ugh. Anyway, this is only ok if this is the only EA running in the terminal. Otherwise, if another EA modifies the pool during the lengthily time in between iterations (while your program is communicating with the broker server) then you're screwed. Also, this implies the assumption that the order pool is always sorted FIFO, and that is also not guaranteed. So let's say you wanted to stick with counting forward, keeping your code small, and accept the risk of not verifying FIFO order -- you'd still want to start iterating the pool from the start after each successful order close. 

 

Well I guess I will just have to keep working on my own programs and stop trying to help someone else.

The function works perfectly for me in "Every Situation", that is all I can add to this conversation.

WOW

 
Donald Gibson:

Well I guess I will just have to keep working on my own programs and stop trying to help someone else.

The function works perfectly for me in "Every Situation", that is all I can add to this conversation.

WOW

Why aren't you open to comments ?

Your code works for you and that's fine. But it may happen it will not work depending of the context, for example if several EA are working and trying to close order(s) simultaneously. It's a possibility.

Thanks trying to help.

 
Donald Gibson:

Well I guess I will just have to keep working on my own programs and stop trying to help someone else.

The function works perfectly for me in "Every Situation", that is all I can add to this conversation.

WOW

There's nothing wrong with learning something new. "Every situation" needs to include logic ensuring that the thing you're iterating over is either immutable or smart enough to recover from a mutating iterable. In this case, all it takes is for one order to be closed and/or deleted by another process to break your code entirely. So in reality it doesn't work perfectly in every situation, and you've been lucky that you haven't experienced an error. It's not far fetched to imagine a scenario where multiple EAs go into "oh sh!#" mode and start closing orders down at the same time. If/when that happens your code will break. Why wouldn't you want to fix it?  

 

To have a recent reference about "open orders pool is not guaranteed to be sorted (by opentime)", I want to provide some evidences. That was explained years ago by several "old" members, for example here and here. Special thanks to JC.

However, I don't think you can rely on the ordering of MT4's list in this way. The list is presumably in trade-placement order, not fill-order. Therefore if orders 1 and 2 start off as pending, and 2 gets filled first, the MT4 list probably isn't reordered to take account of the fact. Therefore, the MT4 order list doesn't necessarily give you the orders on the sort of FIFO basis you're looking for.

Longer answer: yes, but note that the open time of the new ticket is the original open time of the trade, not the time of the partial close which creates the new ticket.

So using pending orders, or closing partially an order, can lead to unsorted open orders pool.

For example :

2018.11.12 14:33:14.067    OutputOpenOrdersPool EURUSD.ECN,M1: 0: ticket = 27551338 open = 2018.11.12 21:10:25 :
2018.11.12 14:33:14.067    OutputOpenOrdersPool EURUSD.ECN,M1: 2: ticket = 27551349 open = 2018.11.12 21:32:20 : this was a buy limit
2018.11.12 14:33:14.067    OutputOpenOrdersPool EURUSD.ECN,M1: 3: ticket = 27551411 open = 2018.11.12 21:22:11 :
2018.11.12 14:33:14.067    OutputOpenOrdersPool EURUSD.ECN,M1: 4: ticket = 27551413 open = 2018.11.12 21:21:20 : from #27551408 (partially closed).

Code :

   for(int i=OrdersTotal();i>=0;i--)
     {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
        {
         int type=OrderType();
         if(type==OP_BUY || type==OP_SELL)
           {
            printf("%i: ticket = %i open = %s : %s",i,OrderTicket(),TimeToString(OrderOpenTime(),TIME_DATE|TIME_SECONDS),OrderComment());
           }
        }
     }

As everyone can see, the orders are not sorted by open time.

And for completeness, it's clearly stated in the documentation :

Consecutive selection of orders using the SELECT_BY_POS parameter returns information in the sequence in which it was received from the trading server. Sorting of the resulting list of orders cannot be guaranteed.

OrderSelect - Trade Functions - MQL4 Reference
OrderSelect - Trade Functions - MQL4 Reference
  • docs.mql4.com
To find out from what list the order has been selected, its close time must be analyzed. If the order close time equals to 0, the order is open or pending and taken from the terminal open orders list. One can distinguish an opened order from a pending order by the order type. If the order close time does not equal to 0, the order is a closed...
 
Alain Verleyen:

To have a recent reference about "open orders pool is not guaranteed to be sorted (by opentime)", I want to provide some evidences. 

Thanks for sharing this. I knew the order pool had no guaranteed order, but I never knew the exact conditions in which it would become unordered. TIL

 
nicholi shen:

Thanks for sharing this. I knew the order pool had no guaranteed order, but I never knew the exact conditions in which it would become unordered. TIL

Thanks for pushing me to post it ;-)