Loops and Closing or Deleting Orders - page 5

 
Eleni Anna Branou:

Please use the </> button to insert your code.


My apologies...  Here it is in proper format..

OrdersTotal() not correct...

I have been surprised by looping code sequence which uses OrdersTotal() not giving correct results (observed with two different brokers). 

I am using MT4 version 1090 on a Linux Ubuntu-MATE 16.04 desktop, running WINE 3.0

Here is what I have been using...

Here it is:

for(int cc = 0; cc < OrdersTotal(); cc++)
{
      if (!OrderSelect(cc, SELECT_BY_POS, MODE_TRADES) ) continue;
      if (OrderSymbol() != Symbol() ) continue;
      if (OrderType() > 1) continue;    //--ignore pending trades

      OpenTradecnt++;    //--counts up for every live position of that symbol that exists
      Print("count of the open trades of this symbol is: ", OpenTradecnt);

I have noticed with two different brokers that the OrdersTotal() value does not always agree with what is shown in the 'Trade' tab of the MT4 broker.  Initially, I thought that it was the broker causing OrdersTotal() to not function properly.  When I noticed on the 2nd broker, I began to wonder if MT4 had an internal 'issue', or if my code was wrong OR if this was a problem with MT4 properly synchronizing with the server....?

After reading this forum thread, I wonder if I would have better results by altering the for..loop to read:

for(int cc = OrdersTotal() - 1; cc >= 0; cc--)
{
      if (!OrderSelect(cc, SELECT_BY_POS, MODE_TRADES) ) continue;
      if (OrderSymbol() != Symbol() ) continue;
      if (OrderType() > 1) continue;    //--ignore pending trades

      OpenTradecnt++;    //--counts up for every live position of that symbol that exists
      Print("count of the open trades of this symbol is: ", OpenTradecnt);
OR, is there a flag or line of code that will ensure that the OrdersTotal() is properly synchronized during an OnTick() event?

Any clarification regarding this would be very helpful and would be greatly appreciated!

 
Simon Gniadkowski:

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:

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

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

thank you very much! it is very clear explaination
 
Hello coders,
I have gone through this thread reading about order selection s. Indeed, I have a code where I believe to have done things right but the selection does not work for me as I cannot read the OpenPrice of the selected order. Everything else works fine, just that part of the code provided. I am not sure why.
The entire code has 4 sections where I need call the OrderOpenPrice right after that order is sent... OrderSend works well, OrderSelect won't get me the results I need. Refer to 1 section of the code if you can help.
Thank you.
 if(Protection_Step_One==1)
        {
        while(Protective_Order<0)
          {
          RefreshRates();
          Protective_Order=OrderSend(Symbol(),OP_SELL,Protective_Lots,NormalizeDouble(MarketInfo(Symbol(),MODE_BID),MarketInfo(Symbol(),MODE_DIGITS)),3,0,0,"Intermediary",MN_Sell_Intermediary_Protection,0,Cyan);
          }
  //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Addition for Clamp       
          for (int i=OrdersTotal()-1; i>=0; i--)
            {if(OrderSelect(i,SELECT_BY_POS, MODE_TRADES)==true)
               {if (OrderMagicNumber()==MN_Sell_Intermediary_Protection)
                  { RefreshRates();
                  Intermediary_OpenPrice_Sell= OrderOpenPrice();
                  }
                }
             }   
               //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>..
        if(Protective_Order!=-1)
          { 
          Protection_Step_One=0;
          RealTime_Drawing=2;
          Protective_Mode_Activated=1;
          Protective_Order=-2;
          Defcon=2;

 

Thanks dear Simon Gniadkowski,

Your post really saved my time.

 
Gelson Kasonia:
void OnStart()
{
     int Protective_Order=OrderSend(_Symbol,ORDER_TYPE_BUY,0.01,Ask,3,0,0,"Intermediary");
     if(Protective_Order<0)
          return;
     if(!OrderSelect(Protective_Order,SELECT_BY_TICKET, MODE_TRADES))
          return;
     Print(Protective_Order, " OrderOpenPrice: ", OrderOpenPrice());
}
 

This is the code I suggest for closing market orders

int MagicNo=1234;
int Slippage=10;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CloseOrdersBackward()
  {
   for(int i=OrdersTotal()-1; i>=0 && !IsStopped(); i--)
     {
      if(!OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
        {
         Print("Order Select failed, order index: ",i," Error: ",GetLastError());
         continue;
        }

      if(OrderSymbol()==Symbol() && OrderMagicNumber()==MagicNo && OrderType()<=OP_SELL)
        {
         if(!OrderClose(OrderTicket(),OrderLots(),OrderClosePrice(),Slippage))

            Print("Order Close failed, order ticket: ",OrderTicket()," Error: ",GetLastError());
        }
     }
  }

And I suggest that, this is the correct way if a forward for loop is used  (to comply with FIFO Rules of US brokers)

int MagicNo=1234;
int Slippage=10;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CloseOrdersForward()
  {
   for(int i=0; i<OrdersTotal() && !IsStopped(); i++)
     {
      if(!OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
        {
         Print("Order Select failed, order index: ",i," Error: ",GetLastError());
         continue;
        }

      if(OrderSymbol()==Symbol() && OrderMagicNumber()==MagicNo && OrderType()<=OP_SELL)
        {
         if(OrderClose(OrderTicket(),OrderLots(),OrderClosePrice(),Slippage))
           {
            i--;
           }
         else
           {
            Print("Order Close failed, order ticket: ",OrderTicket()," Error: ",GetLastError());
           }
        }
     }
  }

In the forward loop,

  1. The OrderTotal() function is used inside the for loop to update the remaining number of open orders with each loop iteration, to avoid index out of array range.
  2. The index i is decremented with each order closed, to avoid skipping some orders.
 
amrali: The index i is decremented with each order closed, to avoid skipping some orders.
In the presence of multiple orders (one EA multiple charts, multiple EAs, manual trading,) while you are waiting for the current operation (closing, deleting, modifying) to complete, any number of other operations on other orders could have concurrently happened and changed the position indexing:
  1. For non- FIFO ( US brokers,)(or the EA only opens one order per symbol,) you can simply count down in a position loop, and you won't miss orders. Get in the habit of always counting down.
              Loops and Closing or Deleting Orders - MQL4 programming forum
    For FIFO ( US brokers,)and you (potentially) process multiple orders per symbol, you must Find the earliest order, close it, and on a successful operation, reprocess all remaining positions.
              CloseOrders by FIFO Rules - Strategy Tester - MQL4 programming forum - Page 2 #16

  2. and check OrderSelect in case earlier positions were deleted.
              What are Function return values ? How do I use them ? - MQL4 programming forum
              Common Errors in MQL4 Programs and How to Avoid Them - MQL4 Articles
  3. and if you (potentially) process multiple orders, must call RefreshRates() after server calls if you want to use, on the next order / server call, the Predefined Variables (Bid/Ask) or (be direction independent and use) OrderClosePrice().
 

You'll know how much this has helped me. Not with just the code I was working on but my understanding entirely. It works perfectly now and I have the understanding to implement it in different ways. 

Really really appreciate this info.

Reason: