How to separate (and close) (Market) Sell orders and Buy orders separately?

 

Looked quite a bit here and in my hard copy book on how to separate (Market) Sell and Buy orders. Then in this case, close one or the other type out separately. Though this would be useful for other purposes as well. This should be possible with them all in the same ticket pool shouldn't it? Though I guess I could put the different conditions for each type and only close the Sell or Buy orders based on testing them as OP_BUY & OP_SELL orders etc? However if I do it this way and am counting down the tickets by position and only closing out one type or the other, my stack/buffer is never going to empty if their are the type that I am not closing out in the buffer. In which case I would never get to the end of the stack and would be stuck there? Though I guess if I go through all of the stack once closing out the ones that I want to, I could go past it. But how will I tell when this occurs with orders left in the stack?

I'm thinking that their is probably a fairly easy and straight forward method for doing this as opposed to perhaps sorting the 2 types into 2 separate buffers or perhaps putting each type in a different 'dimension' within one array?

 

This subject crops up at least once a week usually with people closing/deleting orders in a loop that increments . . . the loop must decrement.

Imaging you have 5 open orders, positions 0, 1, 2, 3 & 4. You want to close your SELL orders leaving your BUY orders open, positions 4 & 2 are SELLs . . .

Your loop starts at position 4, it's a SELL so you close it, the loop now is at position 3, it's a BUY so you do nothing, the loop is now at 2, it's a SELL so you close it . . . the BUY that was at position 3 now moves to position 2 . . . but he loop now moves to position 1, it's a BUY so do nothing, loop now moves to position 0 which is also a BUY . . . .

What is the problem ?

 
//+------------------------------------------------------------------+
//| Partial order close.                                             |
//+------------------------------------------------------------------+
bool    CloseOrder(int ticket=EMPTY, double size=INF){  // INF == entire.
    if      (ticket == EMPTY)   ticket = OrderTicket();
    else if (!OrderSelect(ticket, SELECT_BY_TICKET)){
        Alert("OrderSelect(",ticket,",ticket) failed: ", GetLastError());
                                                                return(false); }
    double  minLot      = MarketInfo(chart.symbol, MODE_MINLOT),
            lotStep     = MarketInfo(chart.symbol, MODE_LOTSTEP),
            sizeCurr    = OrderLots(),
            sizeClose   = MathRound(size/lotStep)*lotStep,
            sizeRem     = sizeCurr - sizeClose;

    if (sizeClose < minLot)                                     return(false);
    if (sizeRem   < minLot){    sizeClose = sizeCurr;   // Close all
        color   op.color    = IfI(Color.Buy, Color.Sell);   }
    else        op.color    = Aqua;

    if (GetTradeContext() < TC_LOCKED)                          return(false);
    if (OrderClose( ticket, sizeClose, OrderClosePrice(),
                    Slippage.Pips*pips2points, op.color )){
        RelTradeContext();                                      return(true);  }
    Alert("OrderClose(ticket=", ticket, ", ...) [1] failed: ", GetLastError());
    RelTradeContext();      // After GetLastError
                                                                return(false);
}
void CloseAllOrders(int op = -1){
    for(int iPos = OrdersTotal()-1; iPos >= 0 ; iPos--) if (
        OrderSelect(iPos, SELECT_BY_POS)                    // Only my orders w/
    &&  OrderMagicNumber() == Magic.Number                  // my magic number
    &&  OrderSymbol()      == chart.symbol                  // and my pair,
    &&  (op < 0 || op == OrderType())                       // and wanted type.
    ){  // Don't combine with &&'s Compiler bug.
        CloseOrder();
    }
    ModifyStops();                                          // Update global var
}
From my code.
 
RaptorUK:

This subject crops up at least once a week usually with people closing/deleting orders in a loop that increments . . . the loop must decrement.

Imaging you have 5 open orders, positions 0, 1, 2, 3 & 4. You want to close your SELL orders leaving your BUY orders open, positions 4 & 2 are SELLs . . .

Your loop starts at position 4, it's a SELL so you close it, the loop now is at position 3, it's a BUY so you do nothing, the loop is now at 2, it's a SELL so you close it . . . the BUY that was at position 3 now moves to position 2 . . . but he loop now moves to position 1, it's a BUY so do nothing, loop now moves to position 0 which is also a BUY . . . .

What is the problem ?


Hi Raptor,

I understand that I need to decrement it. but as I am testing for the open orders going to zero, it loops back for another pass if opposite orders still open. If I only want to close Sell orders and their are Buy orders then this is not going to happen. I realize that I can do as you say, but with this method it does not confirm it by their still being orders open. As they say, it really takes a computer to SNAFU things. With me FINALLY accepting the inevitable and learning MQL4, then I am very much a NuB that will make my share of SNAFU. Hence my lack of confidence in KNOWING that I have closed out all of the open orders of the type that I want to close out.

 
If there are a mix of Buy and Sell orders and you just want to close Buy orders then there will be Orders open when you finish successfully closing the Buy Orders . . . it can be no other way. Don't try to complicate something which is simple . . . open Orders cannot go to 0 if you have a mix and just close one type . . . so don't test for it.
 
WHRoeder:
From my code.


Hi WH,

Thanks. I gave it a quick once over in here and will check out more to really get a handle on it.

Can you clarify for me the 'Compiler Error' that you are referring to?

 

Throw a couple of minor questions in here:

1 - Trying to get a handle on when I need a semi-colon after an 'if(statement);' and when I don't?

2 - Execution scope: I understand that unless I code it in otherwise, everything with in the scope of the 'start' function executes on every tick.

But what about outside the scope of the Start function such as code that is often seen prior to this? Does it execute on every new bar or do I have to code in specific execution code?

 

1. never.

either if (condition) do_something;

or, if (condition)

{

do_something;

do_something_else;

}

2. correct . . . as long as what you have in start can complete before the next tick arrives . . .

The only thing before start is init, it is executed once at the start of the EA/Indicator/Script . . . and also if the EA/Indicator is reinitialised due to changing timeframe/parameters, etc. see https://docs.mql4.com/check/UninitializeReason

 
RaptorUK:
If there are a mix of Buy and Sell orders and you just want to close Buy orders then there will be Orders open when you finish successfully closing the Buy Orders . . . it can be no other way. Don't try to complicate something which is simple . . . open Orders cannot go to 0 if you have a mix and just close one type . . . so don't test for it.

As I see it I start at the top of the stack and just go though them one by one till I get to the bottom of the stack. If I just want to close the sell orders, then I test for these and do so. Otherwise I pass it by, decrement the index by 1, and then loop through until I get to the bottom of the order pool index.

You're right: i was making it harder than it is by thinking that I had to separate the different types of orders out first and then process them. Thanks.

But the bottom of the stack is at zero rather than one isn't it? Hence having to subtract one from the number of orders returned when queried about this. Thus when the open order pool is empty, then it isn't going to return zero as this is a valid number for an order and there would still be one order in the pool. So do I test for 'NumberOfOrdersProcessed' < 0' to find out when i have gone through all of the stack including the last one at index position zero?

 
FourX:

But the bottom of the stack is at zero rather than one isn't it? Hence having to subtract one from the number of orders returned when queried about this. Thus when the open order pool is empty, then it isn't going to return zero as this is a valid number for an order and there would still be one order in the pool. So do I test for 'NumberOfOrdersProcessed' < 0' to find out when i have gone through all of the stack including the last one at index position zero?

When there are no open orders and no pending orders OrdersTotal() will return 0 . . . . this value is the number of orders, it has nothing to do with with any positions of any orders in the pool . . . there are no orders in the pool. When you have orders in the pool and you reference them by position valid positions are >= 0 the last position is OrdersTotal() - 1 if OrdersTotal() is 0 then 0 - 1 = -1 and this is not a valid position.
 
FourX:
Can you clarify for me the 'Compiler Error' that you are referring to?

According to the documentation, IF (A && B && C) evaluates A and if it true then it evaluates B and if it is also true then evaluates C.

This is what C/C++ does and you can write things like IF (A != 0 && B/A > x) or IF(A && functionWithSideAffects() ) ...

Mql4 does not do this. It evaluates A and B and C and then tests if A and B and C. Thus it's demonstrably faster to use IF(A) IF(B) IF(C) and you must with divide by zero and function call with side affects (Like OrderClose/OrderSend)

Reason: