Download MetaTrader 5

Loops and Closing or Deleting Orders

To add comments, please log in or register
Simon Gniadkowski
Moderator
18003
Simon Gniadkowski 2012.05.24 10:48 

This is one of the most common errors I see, probably due in part to the likes of garbage such as Expert Advisor Builder. So I thought it was time for a thread dedicated to the subject so that it can be linked to for future reference.

The Problem

Let's take a simple example; we want a function to close all open orders for our EA, there are plenty of examples but let's create one from scratch.

We need a loop because we want to close all our orders for a specific EA, within this loop we will have code to select the order, code to check it is the correct symbol and magic number and finally code to close the order:

int PositionIndex;    //  <-- this variable is the index used for the loop

int TotalNumberOfOrders;   //  <-- this variable will hold the number of orders currently in the Trade pool

TotalNumberOfOrders = OrdersTotal();    // <-- we store the number of Orders in the variable

for(PositionIndex = 0; PositionIndex < TotalNumberOfOrders; PositionIndex++)  //  <-- for loop to loop through all Orders
   {
   if( ! OrderSelect(PositionIndex, SELECT_BY_POS, MODE_TRADES) ) continue;   // <-- if the OrderSelect fails advance the loop to the next PositionIndex
   
   if( OrderMagicNumber() == MagicNo       // <-- does the Order's Magic Number match our EA's magic number ? 
      && OrderSymbol() == Symbol()         // <-- does the Order's Symbol match the Symbol our EA is working on ? 
      && ( OrderType() == OP_BUY           // <-- is the Order a Buy Order ? 
      ||   OrderType() == OP_SELL ) )      // <-- or is it a Sell Order ?

      if ( ! OrderClose( OrderTicket(), OrderLots(), OrderClosePrice(), Slippage ) )               // <-- try to close the order
         Print("Order Close failed, order number: ", OrderTicket(), " Error: ", GetLastError() );  // <-- if the Order Close failed print some helpful information 
      
   } //  end of For loop

This code is bad . . . DO NOT USE IT . . . I will explain why in the next section . . .

The Explanation

Let's work through the code above . . . line by line, Order by Order . . .

Let's assume we have the following Orders that we want to close, they all have the same magic number and Symbol as our EA so we want our code to close them all:

Position Ticket Number
0111
1222
2 333
3444
4555

1st run through the loop:

the initial value of PositionIndex is 0 so the order at position 0 is selected, ticket number 111, this order is successfully deleted and the remaining Orders change position as follows:

Position Ticket Number
0222
1 333
2444
3555

2nd run through the loop:

now the value of PositionIndex is 1 so the order at position 1 is selected, ticket number 333, this order is successfully deleted and the remaining Orders change position as follows:

Position Ticket Number
0222
1 444
2555

3rd run through the loop:

now the value of PositionIndex is 2 so the order at position 2 is selected, ticket number 555, this order is successfully deleted and the remaining Orders change position as follows:

Position Ticket Number
0222
1 444

4th run through the loop:

now the value of PositionIndex is 3 OrderSelect() tries to select the Order at position 3 and fails, the continue takes execution of the code to the next value in the loop . .


5th and last run through the loop:

now the value of PositionIndex is 4 OrderSelect() tries to select the Order at position 4 and fails, the continue takes execution of the code to the next value in the loop . . . the loop has finished.


We are now left with 2 Orders, tickets 222 and 444 which should have been closed but were not . . . next, how to resolve this issue.

The Solution

The following code is the correct approach when closing open orders or deleting pending orders . . .

The key difference is that the loop decrements from ( TotalNumberOfOrders - 1 ) to 0

int PositionIndex;    //  <-- this variable is the index used for the loop

int TotalNumberOfOrders;   //  <-- this variable will hold the number of orders currently in the Trade pool

TotalNumberOfOrders = OrdersTotal();    // <-- we store the number of Orders in the variable

for(PositionIndex = TotalNumberOfOrders - 1; PositionIndex >= 0 ; PositionIndex --)  //  <-- for loop to loop through all Orders . .   COUNT DOWN TO ZERO !
   {
   if( ! OrderSelect(PositionIndex, SELECT_BY_POS, MODE_TRADES) ) continue;   // <-- if the OrderSelect fails advance the loop to the next PositionIndex
   
   if( OrderMagicNumber() == MagicNo       // <-- does the Order's Magic Number match our EA's magic number ? 
      && OrderSymbol() == Symbol()         // <-- does the Order's Symbol match the Symbol our EA is working on ? 
      && ( OrderType() == OP_BUY           // <-- is the Order a Buy Order ? 
      ||   OrderType() == OP_SELL ) )      // <-- or is it a Sell Order ?
   
      if ( ! OrderClose( OrderTicket(), OrderLots(), OrderClosePrice(), Slippage ) )               // <-- try to close the order
         Print("Order Close failed, order number: ", OrderTicket(), " Error: ", GetLastError() );  // <-- if the Order Close failed print some helpful information 
      
   } //  end of For loop

Once again let's work through the code above . . . line by line, Order by Order . . .

We have the same orders as before:

Position Ticket Number
0111
1222
2333
3444
4555

1st run through the loop:

the initial value of PositionIndex is TotalNumberOfOrders - 1 which is equal to 5 - 1 = 4, so the order at position 4 is selected, ticket number 555, this order is successfully deleted and the remaining Orders change position as follows:

Position Ticket Number
0111
1222
2333
3444

2nd run through the loop:

now the value of PositionIndex is 3 so the order at position 3 is selected, ticket number 444, this order is successfully deleted and the remaining Orders change position as follows:

Position Ticket Number
0111
1222
2333

3rd run through the loop:

now the value of PositionIndex is 2 so the order at position 2 is selected, ticket number 333, this order is successfully deleted and the remaining Orders change position as follows:

Position Ticket Number
0111
1222

4th run through the loop:

now the value of PositionIndex is 1 so the order at position 1 is selected, ticket number 222, this order is successfully deleted and the remaining Orders change position as follows:

Position Ticket Number
0111

5th and last run through the loop:

now the value of PositionIndex is 0 so the order at position 0 is selected, ticket number 111, this order is successfully deleted, value 0 is the last valid value for the loop . . . the loop has finished.

We have successfully deleted all our matching orders . . .

Link to this thread: Loops and Closing or Deleting Orders

Simon Gniadkowski
Moderator
18003
Simon Gniadkowski 2012.05.24 10:49  

Lets take a more complex example . . .

Lets assume we have the following Orders that we want to close, they all have the same magic number but some have a different Symbol as our EA, we want our code to close the orders for the same symbol as our EA, EURUSD:

Position Ticket Number Symbol
0111 EURUSD
1222 EURUSD
2333GBPUSD
3444 EURUSD
4555 EURUSD


1st run through the loop:

the initial value of PositionIndex is TotalNumberOfOrders - 1 which is equal to 5 - 1 = 4, so the order at position 4 is selected, ticket number 555, this order matches magic number and Symbol so is successfully deleted and the remaining Orders change position as follows:

Position Ticket Number Symbol
0111EURUSD
1222EURUSD
2333GBPUSD
3444EURUSD

2nd run through the loop:

now the value of PositionIndex is 3 so the order at position 3 is selected, ticket number 444, this order matches magic number and Symbol so is successfully deleted and the remaining Orders change position as follows:

Position Ticket Number Symbol
0111EURUSD
1222EURUSD
2333GBPUSD


3rd run through the loop:

now the value of PositionIndex is 2 so the order at position 2 is selected, ticket number 333, this order matches magic number but NOT Symbol so it is not deleted, the remaining Orders do not change:

Position Ticket Number Symbol
0111EURUSD
1222EURUSD
2333GBPUSD

4th run through the loop:

now the value of PositionIndex is 1 so the order at position 1 is selected, ticket number 222, this order matches magic number and Symbol so is successfully deleted and the remaining Orders change position as follows:

Position Ticket Number Symbol
0111EURUSD
1333GBPUSD

5th and last run through the loop:

now the value of PositionIndex is 0 so the order at position 0 is selected, ticket number 111, this order is successfully deleted, value 0 is the last valid value for the loop . . . the loop has finished.

We have successfully deleted all our matching orders leaving the one order that did not match our symbol, ticket number 333 now at position 0 . . .

Position Ticket Number Symbol
0333GBPUSD


Link to this thread: Loops and Closing or Deleting Orders

whroeder1
14756
whroeder1 2012.05.24 13:22  
Yochanan Gerbi
608
Yochanan Gerbi 2012.05.29 09:42  

Thank you Raptor for this important explanation.

Y.

RJo
61
RJo 2012.06.05 20:21  
This is extremely helpful to me, King of the garbage expert advisor builder! Oh, how I do enjoy hacking away at the resulting code. Many thanks.
CollaborativeFx.Forumer.com
117
CollaborativeFx.Forumer.com 2012.06.05 20:29  

Wow. All that information for closing an order.

I wonder how much information it would take to net 50+ pips a day, consistently, everyday (on average) - without fail, through the last 137 trades.

Show me how to do something like that, and I would consider it extremely helpful information and Guru, shall be your title, forever and ever, Amen.

Simon Gniadkowski
Moderator
18003
Simon Gniadkowski 2012.06.15 07:51  
CFx:

Wow. All that information for closing an order.

I wonder how much information it would take to net 50+ pips a day, consistently, everyday (on average) - without fail, through the last 137 trades.

I have no interest in pips . . . what can I do with them ? I can't spend them, what is the GBPPIPS rate ? you show your ignorance by counting success in pips . . .
whroeder1
14756
whroeder1 2012.06.15 12:29  
CFx:

I wonder how much information it would take to net 50+ pips a day, consistently, everyday (on average) - without fail, through the last 137 trades.

Show me how to do something like that, and I would consider it extremely helpful information and Guru, shall be your title, forever and ever, Amen.

  1. Don't Hijack thread with off topic information
  2. We are NOT going to show you that because you didn't read the rules Any discussions except of concerning MetaQuotes Language 4 and auto trading are forbidden
MirTD
220
MirTD 2013.01.14 18:02  

Raptor,i do know at 1st glance of ur post that u r quite n expert in mql4.this thread again helps clear my doubts!keep up the good works.tnx

Joao Rosas
391
Joao Rosas 2013.01.14 18:23  

Just another idea:

for(PositionIndex = 0; PositionIndex < OrdersTotal() ; PositionIndex ++)  //  <-- for loop to loop through all Orders . .   COUNT DOWN TO ZERO !
   {
   if( ! OrderSelect(PositionIndex, SELECT_BY_POS, MODE_TRADES) ) continue;   // <-- if the OrderSelect fails advance the loop to the next PositionIndex
   
   if( OrderMagicNumber() == MagicNo       // <-- does the Order's Magic Number match our EA's magic number ? 
      && OrderSymbol() == Symbol()         // <-- does the Order's Symbol match the Symbol our EA is working on ? 
      && ( OrderType() == OP_BUY           // <-- is the Order a Buy Order ? 
      ||   OrderType() == OP_SELL ) )      // <-- or is it a Sell Order ?
   
         add_trade_to_close_queue( OrderTicket());  // <--  You need to model the queue mechanism ...
      
   } //  end of For loop


Regards.

shonick
79
shonick 2013.02.10 18:01  
abstract_mind:


Just another idea:


Regards.

yes, understand the logic behind of MT4, it is up to you to code increase or decrease counter.
1234
To add comments, please log in or register