Limit open orders problem

 

I have always been able to limit open orders across multiple pairs that all have different "magic numbers" but recently I am having a problem because my EA will open more than the allowed 1 trade if the entry criteria is met at the same time on different pairs. E.g. if the EA opens a trade when price opens above an MA and 2 pairs have this occur at the open of a bar even with the below code both orders can still be sent. Frustrating and wondering if there is any way to solve this?


void LimitOrders()
{
    int count = 0;
    for (int i=OrdersTotal()-1; i >= 0; i--)
    if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
    {
        {
            count++;
        }
    }
    else
    {
        Print("OrderSend() error - ", ErrorDescription(GetLastError()));
    }
    if (count < 1)
    {
            OpenOrder();
    }
}
 
gangsta1:

I have always been able to limit open orders across multiple pairs that all have different "magic numbers" but recently I am having a problem because my EA will open more than the allowed 1 trade if the entry criteria is met at the same time on different pairs. E.g. if the EA opens a trade when price opens above an MA and 2 pairs have this occur at the open of a bar even with the below code both orders can still be sent. Frustrating and wondering if there is any way to solve this?


You can add a Mutex to stop more than one EA sending an order at the same time. Search for Mutex you will find lots of info . . .
 
gangsta1:

I have always been able to limit open orders across multiple pairs that all have different "magic numbers" but recently I am having a problem because my EA will open more than the allowed 1 trade if the entry criteria is met at the same time on different pairs. E.g. if the EA opens a trade when price opens above an MA and 2 pairs have this occur at the open of a bar even with the below code both orders can still be sent. Frustrating and wondering if there is any way to solve this?


The code you post doesn't make sense as your count variable will always be equal to OrderTotal() except if there is an error with OrderSelect().

A minor error :

        Print("OrderSend() OrderSelect() error - ", ErrorDescription(GetLastError()));
 
gangsta1: EA will open more than the allowed 1 trade if the entry criteria is met at the same time on different pairs.

Why do you want to limit the EA when it's on multiple pairs? Different pairs, different signals. Diversify, you want to trade both to lessen risk.

What I do is adjust lotsize appropriately. When a pair is about to open (hasn't reached it's trigger price yet) it creates a Global Variable such as EA_pair_tf. The value is a timeout (like at end of bar.) When the trigger is reached, I lock a mutex, count the number of EAs about to trade (nOpening) and adjust:

  1. account balance * percentage = Risk = (OrderOpenPrice - OrderStopLoss)*DIR * DeltaPerLot() * Lotsize; therefor:
  2. Lotsize = (account balance * percentage / (OOP-OSL) / DeltaPerLot. Reduce AB by currently open orders at risk amounts, and by number of EAs about to open:
  3. Lotsize = ([account balance - balance_chart_atRisk )* percentage / (OOP-OSL) / DeltaPerLot / nOpening.
 

Thank you all so much. I spent a lot of time reading and coding a "mutex" and came up with the following bits of code that seems to work, however if orders get sent at the exact same time there can still be multiple orders open.


//checks if there is an open order
int IfOrderDoesNotExist2()
{
    bool exists = false;
    for (int i=OrdersTotal()-1; i >= 0; i--)
    if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
    {
        {
            exists = true;
        }
    }
    else
    {
        Print("OrderSelect() error - ", ErrorDescription(GetLastError()));
    }
    
    if (exists == false)
    {
            TradeIsNotBusy();
    }
}

//sends buy order if trade is not busy

void BuyOrder4()
{
    double SL = Ask - BuyStoploss4*PipValue*Point;
    if (BuyStoploss4 == 0) SL = 0;
    double TP = Ask + BuyTakeprofit4*PipValue*Point;
    if (BuyTakeprofit4 == 0) TP = 0;
    if(TradeIsBusy() < 0) 
    return(-1); 
   // RefreshRates();
    int ticket = -1;
    if (true)
    ticket = OrderSend(Symbol(), OP_BUY, BuyLots4, Ask, 4, 0, 0, "My Expert", OrderID, 0, Blue);
    else
    ticket = OrderSend(Symbol(), OP_BUY, BuyLots4, Ask, 4, SL, TP, "My Expert", OrderID, 0, Blue);
    if (ticket > -1)
    {
        if (true)
        {
            OrderSelect(ticket, SELECT_BY_TICKET);
            bool ret = OrderModify(OrderTicket(), OrderOpenPrice(), SL, TP, 0, Blue);
            if (ret == false)
            Print("OrderModify() error - ", ErrorDescription(GetLastError()));
        }
           // TradeIsNotBusy();
    }
    else
    {
        Print("OrderSend() error - ", ErrorDescription(GetLastError()));
    }
    
}

//functions for trade is busy

 /////////////////////////////////////////////////////////////////////////////////
// int TradeIsBusy( int MaxWaiting_sec = 30 )
//
// The function replaces the TradeIsBusy value 0 with 1.
// If TradeIsBusy = 1 at the moment of launch, the function waits until TradeIsBusy is 0, 
// and then replaces.
// If there is no global variable TradeIsBusy, the function creates it.
// Return codes:
//  1 - successfully completed. The global variable TradeIsBusy was assigned with value 1
// -1 - TradeIsBusy = 1 at the moment of launch of the function, the waiting was interrupted by the user
//      (the expert was removed from the chart, the terminal was closed, the chart period and/or symbol 
//      was changed, etc.)
// -2 - TradeIsBusy = 1 at the moment of launch of the function, the waiting limit was exceeded
//      (MaxWaiting_sec)
/////////////////////////////////////////////////////////////////////////////////
int TradeIsBusy( int MaxWaiting_sec = 30 )
  {
    // at testing, there is no resaon to divide the trade context - just terminate 
    // the function
    if(IsTesting()){
        return(1);
    }
    GetLastError();
    int _GetLastError = 0, StartWaitingTime = GetTickCount();
    
    //+------------------------------------------------------------------+
    //| Check whether a global variable exists and, if not, create it    |
    //+------------------------------------------------------------------+
    while(true)
      {
        // if the expert was terminated by the user, stop operation
        if(IsStopped()) 
          { 
            Print("The expert was terminated by the user!"); 
            return(-1); 
          }
        // if the waiting time exceeds that specified in the variable 
        // MaxWaiting_sec, stop operation, as well
        if(GetTickCount() - StartWaitingTime > MaxWaiting_sec * 1000)
          {
            Print("Waiting time (" + MaxWaiting_sec + " sec) exceeded!");
            return(-2);
          }
        // check whether the global variable exists
        // if it does, leave the loop and go to the block of changing 
        // TradeIsBusy value
        if(GlobalVariableCheck( "TradeIsBusy" )) 
            break;
        else
        // if the GlobalVariableCheck returns FALSE, it means that it does not exist or  
        // an error has occurred during checking
          {
            _GetLastError = GetLastError();
            // if it is still an error, display information, wait for 0.1 second, and 
            // restart checking
            if(_GetLastError != 0)
             {
              Print("TradeIsBusy()-GlobalVariableCheck(\"TradeIsBusy\")-Error #",
                    _GetLastError );
              Sleep(100);
              continue;
             }
          }
        // if there is no error, it means that there is just no global variable, try to create
        // it
        // if the GlobalVariableSet > 0, it means that the global variable has been successfully created. 
        // Leave the function
        if(GlobalVariableSet( "TradeIsBusy", 1.0 ) > 0 ) 
            return(1);
        else
        // if the GlobalVariableSet has returned a value <= 0, it means that an error 
        // occurred at creation of the variable
         {
          _GetLastError = GetLastError();
          // display information, wait for 0.1 second, and try again
          if(_GetLastError != 0)
            {
              Print("TradeIsBusy()-GlobalVariableSet(\"TradeIsBusy\",0.0 )-Error #",
                    _GetLastError );
              Sleep(100);
              continue;
            }
         }
      }
    //+----------------------------------------------------------------------------------+
    //| If the function execution has reached this point, it means that global variable  | 
    //| variable exists.                                                                 |
    //| Wait until the TradeIsBusy becomes = 0 and change the value of TradeIsBusy for 1 |
    //+----------------------------------------------------------------------------------+
    while(true)
     {
     // if the expert was terminated by the user, stop operation
     if(IsStopped()) 
       { 
         Print("The expert was terminated by the user!"); 
         return(-1); 
       }
     // if the waiting time exceeds that specified in the variable 
     // MaxWaiting_sec, stop operation, as well
     if(GetTickCount() - StartWaitingTime > MaxWaiting_sec * 1000)
       {
         Print("The waiting time (" + MaxWaiting_sec + " sec) exceeded!");
         return(-2);
       }
     // try to change the value of the TradeIsBusy from 0 to 1
     // if succeed, leave the function returning 1 ("successfully completed")
     if(GlobalVariableSetOnCondition( "TradeIsBusy", 1.0, 0.0 )) 
         return(1);
     else
     // if not, 2 reasons for it are possible: TradeIsBusy = 1 (then one has to wait), or 

     // an error occurred (this is what we will check)
      {
      _GetLastError = GetLastError();
      // if it is still an error, display information and try again
      if(_GetLastError != 0)
      {
   Print("TradeIsBusy()-GlobalVariableSetOnCondition(\"TradeIsBusy\",1.0,0.0 )-Error #",
         _GetLastError );
       continue;
      }
     }
     //if there is no error, it means that TradeIsBusy = 1 (another expert is trading), then display 
     // information and wait...
     Comment("Wait until another expert finishes trading...");
     Sleep(1000);
     Comment("");
    }
  }
  
  /////////////////////////////////////////////////////////////////////////////////
// void TradeIsNotBusy()
//
// The function sets the value of the global variable TradeIsBusy = 0.
// If the TradeIsBusy does not exist, the function creates it.
/////////////////////////////////////////////////////////////////////////////////
void TradeIsNotBusy()
  {
    int _GetLastError;
    GetLastError();
    // at testing, there is no sense to divide the trade context - just terminate 
    // the function
    if(IsTesting()) 
      { 
        return(0); 
      }
    while(true)
      {
        // if the expert was terminated by the user, ïðåêðàùàåì ðàáîòó
        if(IsStopped()) 
          { 
            Print("The expert was terminated by the user!"); 
            return(-1); 
          }
        // try to set the global variable value = 0 (or create the global 
        // variable)
        // if the GlobalVariableSet returns a value > 0, it means that everything 
        // has succeeded. Leave the function
        if(GlobalVariableSet( "TradeIsBusy", 0.0 ) > 0) 
            return(1);
        else
        // if the GlobalVariableSet returns a value <= 0, this means that an error has occurred. 
        // Display information, wait, and try again
         {
         _GetLastError = GetLastError();
         if(_GetLastError != 0 )
           Print("TradeIsNotBusy()-GlobalVariableSet(\"TradeIsBusy\",0.0)-Error #", 
                 _GetLastError );
         }
        Sleep(100);
      }
  }
 
gangsta1: if orders get sent at the exact same time there can still be multiple orders open.
Only SetVaribleOnCondition is atomic you can't use Set and lock. Try my functions
 

Thanks again I have had a good study and tried to implement aspects of your code. I can get the mutex to work the majority of the time but every now and then an additional trade slips through the gap at the exact same time, despite my EA having a limit open order set to 1, a mutex to prevent 2 being send and the same time and the fact that it only trades at the open of a bar! This is my order send code and I have included both functions from the article in global variables/mutex: https://www.mql5.com/en/articles/1412

Perhaps I am missing something like having TradeIsBusy() and TradeIsNotBusy() in the wrong position? Maybe I need to change the waiting time so that the order that got blocked out initially is never actually sent? Maybe it is just possible that both orders will always go through as they are sent at EXACTLY the same time.

void BuyOrder4()
{
    if(TradeIsBusy() < 0) //correct place??
    return(-1);  //correct place??
    double SL = Ask - BuyStoploss4*PipValue*Point;
    if (BuyStoploss4 == 0) SL = 0;
    double TP = Ask + BuyTakeprofit4*PipValue*Point;
    if (BuyTakeprofit4 == 0) TP = 0;
    int ticket = -1; 
    if (true)
    ticket = OrderSend(Symbol(), OP_BUY, BuyLots4, Ask, 4, 0, 0, "My Expert", OrderID, 0, Blue);
    else
    ticket = OrderSend(Symbol(), OP_BUY, BuyLots4, Ask, 4, SL, TP, "My Expert", OrderID, 0, Blue);
    if (ticket > -1)
    {
        if (true)
        {     
            OrderSelect(ticket, SELECT_BY_TICKET);
            bool ret = OrderModify(OrderTicket(), OrderOpenPrice(), SL, TP, 0, Blue);
            if (ret == false)
            Print("OrderModify() error - ", ErrorDescription(GetLastError()));
        }
            
    }
    else
    {
        Print("OrderSend() error - ", ErrorDescription(GetLastError()));
        
    }
        TradeIsNotBusy();  //correct place??
        return(0);  //correct place??
}
 
gangsta1:

Thanks again I have had a good study and tried to implement aspects of your code. I can get the mutex to work the majority of the time but every now and then an additional trade slips through the gap at the exact same time, despite my EA having a limit open order set to 1, a mutex to prevent 2 being send and the same time and the fact that it only trades at the open of a bar! This is my order send code and I have included both functions from the article in global variables/mutex: https://www.mql5.com/en/articles/1412

Perhaps I am missing something like having TradeIsBusy() and TradeIsNotBusy() in the wrong position? Maybe I need to change the waiting time so that the order that got blocked out initially is never actually sent? Maybe it is just possible that both orders will always go through as they are sent at EXACTLY the same time.

When is . .

if (true)

. . . ever false ? so why bother with the if and the else ?

 
Thanks Raptor, this piece of code seems to be limiting the orders to 1 now and not allowing multiple orders to open even if sent at the exact time. Did you notice anything else about that code snippet that may be wrong and cause multiple trades? Think I have the TradeIsBusy() and TradeIsNotBusy() in the correct place now and the functions are working as they should.
Reason: