Too many orders being placed

 

Hi,

I am working on an EA that is based on MACD and bollinger bands. The idea is that when MACD crosses and price crossing the middle bollinger band coincide, price rides the band all the way up or down.

I have attempted to code this, and have explained in the comments what I intend each snippet of code to be.

//+------------------------------------------------------------------+
//|                                                   MACD Bands.mq4 |
//|                                                          Gulzaar |
//|                                    http://gulzaarfx.blogspot.com |
//+------------------------------------------------------------------+

#property copyright "Gulzaar"
#property link      "http://gulzaarfx.blogspot.com"

//External Variables//-------------------------

extern double Lots = 0.1;
extern int MagicNumber = 78652;
extern int MACDfast = 21,
           MACDslow = 55,
           MACDsignal = 8,
           Window = 10;



//Global Variables//---------------------------

int Ticket;
bool IsTrade = false;
bool BuyOne, SellOne;

//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
  {
//----
   if(Digits == 5)
      {
         Window = Window * 10;
         
      }
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
  {
//----
double TwentyEMA = iMA(NULL,0,20,0,MODE_EMA,PRICE_CLOSE,1);
double MACDmain = iMACD(NULL,0,MACDfast,MACDslow,MACDsignal,PRICE_CLOSE,MODE_MAIN,1);
double MACDsignal = iMACD(NULL,0,MACDfast,MACDslow,MACDsignal,PRICE_CLOSE,MODE_SIGNAL,1);

//Check Open positions

bool Closed;

for(int a = OrdersTotal(); a >= 0; a--)
   {
      OrderSelect(a,SELECT_BY_POS,MODE_TRADES);
      if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber && OrderType() == OP_BUY) 
//Close Buy orders 
         {
            IsTrade = true;
            double BuyStop = iBands(NULL,0,20,2,0,PRICE_CLOSE,MODE_LOWER,0); //Change the StopLoss to reflect the Lower Bollinger band for that candle
            if(OrderStopLoss() < BuyStop + Window * Point) OrderModify(OrderTicket(),OrderOpenPrice(),BuyStop,0,0,CLR_NONE);
            if(Close[1] < TwentyEMA - Window * Point) Closed = OrderClose(OrderTicket(),OrderLots(),Bid,MarketInfo(Symbol(),MODE_SPREAD),CLR_NONE);//If the close is below the 
            if(Closed) IsTrade = False;                                                                                                            //middle band(20EMA) close the
                                                                                                                                                   //order 
          }
//Close Sell Orders 
      if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber && OrderType() == OP_SELL) 
         {
            IsTrade = true;
            double SellStop = iBands(NULL,0,20,2,0,PRICE_CLOSE,MODE_UPPER,0);//Same principle as above
            if(OrderStopLoss() > SellStop + Window*Point) OrderModify(OrderTicket(),OrderOpenPrice(),SellStop,0,0,CLR_NONE);

            if(Close[1] > TwentyEMA + Window * Point) Closed = OrderClose(OrderTicket(),OrderLots(),Ask,MarketInfo(Symbol(),MODE_SPREAD),CLR_NONE); 
            if(Closed) IsTrade = false;

         }
         
         
     }
//Check conditions

//BUY

if(MACDmain > MACDsignal) //MACD cross to the upside
   {
      for(int i = 1; i <=4; i++)
         {
            double EMA = iMA(NULL,0,20,0,MODE_EMA,PRICE_CLOSE,i);          //The for loop tests whether a crossover
            double EMA2 = iMA(NULL,0,20,0,MODE_EMA,PRICE_CLOSE,i+1);       //happened or not. A candle opening below 
            if(Close[i] > EMA && Open[i] < EMA && Close[i+1] < EMA2)       //the MA and closing above it signals a cross
               {                                                           //with the additional confirmation of the close of
                  BuyOne = true;                                           //previous candle being below the MA
                  break;
                }
            continue;
          }           
      
    }

//SELL

if(MACDmain < MACDsignal) //MACD cross to the downside
   {
      for(int j = 1; j <=4; j++)
         {
            EMA = iMA(NULL,0,20,0,MODE_EMA,PRICE_CLOSE,j);              //Same principle as the BUY signal except in reverse
            EMA2 = iMA(NULL,0,20,0,MODE_EMA,PRICE_CLOSE,j+1);
            if(Close[j] < EMA && Open[j] > EMA && Close[j+1] > EMA2) 
               {
                  SellOne = true;
                  break;
                }
            continue;
          }           
      
    }
//End Check conditions

if(BuyOne == true && IsTrade == false)
   {
      Ticket = OrderSend(Symbol(),OP_BUY,Lots,Ask,MarketInfo(Symbol(),MODE_SPREAD),0,0,NULL,MagicNumber,0,Green); 
      if (Ticket==-1)   ShowERROR(Ticket,0,0);
    }
    
if(SellOne == true && IsTrade == false)
   {
      Ticket = OrderSend(Symbol(),OP_SELL,Lots,Bid,MarketInfo(Symbol(),MODE_SPREAD),0,0,NULL,MagicNumber,0,Red); 
      if (Ticket==-1)   ShowERROR(Ticket,0,0);

    }      
      
   


            
//----
   return(0);
  }
//+------------------------------------------------------------------+


void ShowERROR(int Ticket,double SL,double TP)
{
   int err=GetLastError();
   switch ( err )
   {                  
      case 1:                                                                               return;
      case 2:   Alert("No connection with the trading server ",        Ticket," ",Symbol());return;
      case 130: Alert("Error close foot Ticket ",                      Ticket," ",Symbol());return;
      case 134: Alert("Not enough money ",                             Ticket," ",Symbol());return;
      case 146: Alert("Error Subsystem busy trade ",                   Ticket," ",Symbol());return;
      case 129: Alert("Error Invalid price ",                          Ticket," ",Symbol());return;
      case 131: Alert("Error Invalid volume ",                         Ticket," ",Symbol());return;
      default:  Alert("Error : ",err, "   ",                           Ticket," ",Symbol());return;
   }
}


 

Now, when I run this in Strategy tester visual mode (H4 TF) none of the trades that should be taken are taken. Instead, something like the attached image happens.

In that small cluster, nearly 2-300 trades were executed AND closed, and they weren't even according to my signal!

So my questions are:

1) Where am I going wrong with my signal code?

2) Why are so many trades being placed and closed at once?

Your help is always very appreciated.

Thanks!

 
 

(1) You're almost there already, albeit I don't see any Bands set-up.

(2) The prb is:

double TwentyEMA = iMA(NULL,0,20,0,MODE_EMA,PRICE_CLOSE,1); 
double MACDmain = iMACD(NULL,0,MACDfast,MACDslow,MACDsignal,PRICE_CLOSE,MODE_MAIN,1);
double MACDsignal = iMACD(NULL,0,MACDfast,MACDslow,MACDsignal,PRICE_CLOSE,MODE_SIGNAL,1);

TwentyEMA, MACDmain, MACDsignal --- they all remain SAME values, during test. This is because they are not iterating on every bar, but remains "lock" at Bar=1, as you hard-coded '1' in the iMA(.....1), iMACD(...1), respectively.

These variables may work for forward demo/live because with each new bar, bar=1 is different. Unfortunately, for Strategy Tester, this is not the case.

Hope this helps.

 
diostar:

(1) You're almost there already, albeit I don't see any Bands set-up.

(2) The prb is:

TwentyEMA, MACDmain, MACDsignal --- they all remain SAME values, during test. This is because they are not iterating on every bar, but remains "lock" at Bar=1, as you hard-coded '1' in the iMA(.....1), iMACD(...1), respectively.

These variables may work for forward demo/live because with each new bar, bar=1 is different. Unfortunately, for Strategy Tester, this is not the case.

Hope this helps.


Thanks - Yeah, the bands concept was more from visual observation, but I couldn't find what to use for the middle band(as opposed to MODE_UPPER and MODE_LOWER), so I used a 20EMA instead.

I didn't exactly get what you meant by "SAME values, during test. This is because they are not iterating on every bar, but remains "lock" at Bar=1, as you hard-coded '1' in the iMA(.....1), iMACD(...1), respectively."

Does this mean that it gets stuck on the value assigned at the first bar in the test?

I tried changing it to zero(since the for loop assigns the value in each iteration) and results instantly got better, now I'm getting 50% accuracy, but it still opens and closes trades way too fast, and takes way too many trades.

I'm attaching a picture of an ideal signal - perhaps that can clear it up a little - please check the picture against my code - thanks in advance

The candle where the line is should be the entry. MACD(shift 1) would have crossed, plus, if you shift 3-4 candles back, the entire candle is below the EMA. The EA completely misses these trades.

 
  1. for(int a = OrdersTotal(); a >= 0; a--)
       {
          OrderSelect(a,SELECT_BY_POS,MODE_TRADES);
          if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber && OrderType() == OP_BUY) 
    1) If OrderSelect fails then everything thereafter are bogus.
    2) OrderSelect fails because the positions are 0 through OrdersTotal() -1 and the first select uses OrderSelect( OrdersTotal )
    3) The thought is to select all buy orders so ONE statement - put a brace after the end of the if, the FOR doesn't need one.
    for(int pos = OrdersTotal() - 1 ; pos >= 0; pos--) if(
        OrderSelect(pos, SELECT_BY_POS,MODE_TRADES)
    &&  OrderSymbol() == Symbol() 
    &&  OrderMagicNumber() == MagicNumber 
    ){
       if (OrderType() == OP_BUY){ ... }
       else if (OrderType() == OP_SELL){ ...
    }
    

  2. if(Close[1] < TwentyEMA - Window * Point) Closed = OrderClose(OrderTicket(),OrderLots(),Bid,MarketInfo(Symbol(),MODE_SPREAD),CLR_NONE);//If the close is below the 
                if(Closed) IsTrade = False;                
    What is Closed when closed[1] > TewentyEMA?
    if(Close[1] < TwentyEMA - Window * Point){
       Closed = OrderClose(OrderTicket(),OrderLots(),Bid,MarketInfo(Symbol(),MODE_SPREAD),CLR_NONE);//If the close is below the 
       if(Closed) IsTrade = False;                
    }

  3. What is Window * point - on a 5 digit broker it is ONE pip
    //++++ These are adjusted for 5 digit brokers.
    int     pips2points;    // slippage  3 pips    3=points    30=points
    double  pips2dbl;       // Stoploss 15 pips    0.0015      0.00150
    int     Digits.pips;    // DoubleToStr(dbl/pips2dbl, Digits.pips)
    int     init(){
         if (Digits % 2 == 1){      // DE30=1/JPY=3/EURUSD=5 https://www.mql5.com/en/forum/135345
                    pips2dbl    = Point*10; pips2points = 10;   Digits.pips = 1;
        } else {    pips2dbl    = Point;    pips2points =  1;   Digits.pips = 0; }
        // OrderSend(... Slippage.Pips * pips2points, Bid - StopLossPips * pips2dbl
    
    Window * pips2dbl is 10 pips on either.
  4. if(OrderStopLoss() > SellStop + Window*Point) OrderModify(OrderTicket(),...
    if(Close[1] > TwentyEMA + Window * Point) Closed = OrderClose(OrderTicket(),...
    
    Always test return codes
    if(OrderStopLoss() > SellStop + Window*Point){
       if (!OrderModify(OrderTicket(),OrderOpenPrice(),SellStop,0,0,CLR_NONE))
          Alert("OrderModify failed: ", GetLastError());
       if(Close[1] > TwentyEMA + Window * Point){
           if(!OrderClose(OrderTicket(),OrderLots(),OrderClosePrice(),MarketInfo(Symbol(),MODE_SPREAD),CLR_NONE))
               Alert("OrderClosed failed: ",GetLastError());
           else IsTrade = false;
       }
    }

 
gulzaar:
Does this mean that it gets stuck on the value assigned at the first bar in the test? NO.

Its just that with Strategy Tester, don't take any chances. So do this.


int Ticket;
bool IsTrade = false;
bool BuyOne, SellOne;

double TwentyEMA,MACDmain,MACDsignal; <----- declare at GLOBAL LEVEL, instead of in start()


 //+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
  {
//----
   if(Digits == 5)
      {
         Window = Window * 10;
         
      }
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
  {
//---- Also, good to have some check for new Bar logic here. (test mode).


TwentyEMA = iMA(NULL,0,20,0,MODE_EMA,PRICE_CLOSE,1);OK. '0' is fine, too.
MACDmain = iMACD(NULL,0,MACDfast,MACDslow,MACDsignal,PRICE_CLOSE,MODE_MAIN,1);OK.'0' is fine, too.
MACDsignal = iMACD(NULL,0,MACDfast,MACDslow,MACDsignal,PRICE_CLOSE,MODE_SIGNAL,1);OK.'0' is fine, too.

then,

if(MACDmain > MACDsignal) //MACD cross to the upside Get all your signals processed early, before executions - buy, sell, close. 
   {
      for(int i = 1; i <=4; i++)
         {
            double EMA = iMA(NULL,0,20,0,MODE_EMA,PRICE_CLOSE,i);          //The for loop tests whether a crossover
            double EMA2 = iMA(NULL,0,20,0,MODE_EMA,PRICE_CLOSE,i+1);       //happened or not. A candle opening below 
            if(Close[i] > EMA && Open[i] < EMA && Close[i+1] < EMA2)       //the MA and closing above it signals a cross
               {                                                           //with the additional confirmation of the close of
                  BuyOne = true;                                           //previous candle being below the MA
                  break;
                }
            continue;
          }           
      
    }

//SELL

if(MACDmain < MACDsignal) //MACD cross to the downside
   {
      for(int j = 1; j <=4; j++)
         {
            EMA = iMA(NULL,0,20,0,MODE_EMA,PRICE_CLOSE,j);              //Same principle as the BUY signal except in reverse
            EMA2 = iMA(NULL,0,20,0,MODE_EMA,PRICE_CLOSE,j+1);
            if(Close[j] < EMA && Open[j] > EMA && Close[j+1] > EMA2) 
               {
                  SellOne = true;
                  break;
                }
            continue;
          }           
      
    }
//End Check conditions

You may also use/add the above signals to help the closing of orders

if(OrdersTotal()>0){....closing...

 

Thanks for the pointers, guys! Am working on it - will keep you updated.

Cheers

 

So I made the changes, but still doesn't work properly. It takes one valid trade, then immediately after that trade closes it opens hundreds of positions:

Any ideas? I declared the indicator vars globally, I changed the OrderSelecT() to what WHRoeder suggested. Am attaching a picture of visual mode on the next post

//+------------------------------------------------------------------+
//|                                                   MACD Bands.mq4 |
//|                                                          Gulzaar |
//|                                    http://gulzaarfx.blogspot.com |
//+------------------------------------------------------------------+

#property copyright "Gulzaar"
#property link      "http://gulzaarfx.blogspot.com"

//External Variables//-------------------------

extern double Lots = 0.1;
extern int MagicNumber = 78652;
extern int fast = 21,
           slow = 55,
           signal = 8,
           Window = 10;



//Global Variables//---------------------------

int Ticket;
bool IsTrade = false;
bool BuyOne, SellOne;
bool Closed;
double TwentyEMA, MACDmain, MACDsignal;
int BarTrade;

//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
  {
//----
   if(Digits == 5)
      {
         Window = Window * 10;
         
      }
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
  {
//----
TwentyEMA = iMA(NULL,0,20,0,MODE_EMA,PRICE_CLOSE,1);
MACDmain = iMACD(NULL,0,fast,slow,signal,PRICE_CLOSE,MODE_MAIN,1);
MACDsignal = iMACD(NULL,0,fast,slow,signal,PRICE_CLOSE,MODE_SIGNAL,1);

//Check Open positions

for(int pos = OrdersTotal() - 1; pos >= 0; pos--){
 
  OrderSelect(OrderTicket(),SELECT_BY_POS,MODE_TRADES);
  if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
  {
      if(OrderType() == OP_BUY) 
         {
            IsTrade = true;
            double BuyStop = iBands(NULL,0,20,2,0,PRICE_CLOSE,MODE_LOWER,0); //Change the StopLoss to reflect the Lower Bollinger band for that candle
            if(OrderStopLoss() < BuyStop + Window * Point) OrderModify(OrderTicket(),OrderOpenPrice(),BuyStop,0,0,CLR_NONE);
            if(Close[1] < TwentyEMA - Window * Point) Closed = OrderClose(OrderTicket(),OrderLots(),Bid,MarketInfo(Symbol(),MODE_SPREAD),CLR_NONE);//If the close is below the 
            if(Closed) IsTrade = False;                                                                                                            //middle band(20EMA) close the
                                                                                                                                                   //order 
          }
   
   
   else if (OrderType() == OP_SELL){
   
            IsTrade = true;
            double SellStop = iBands(NULL,0,20,2,0,PRICE_CLOSE,MODE_UPPER,0);//Same principle as above
            if(OrderStopLoss() > SellStop + Window*Point) OrderModify(OrderTicket(),OrderOpenPrice(),SellStop,0,0,CLR_NONE);

            if(Close[1] > TwentyEMA + Window * Point) Closed = OrderClose(OrderTicket(),OrderLots(),Ask,MarketInfo(Symbol(),MODE_SPREAD),CLR_NONE); 
            if(Closed) IsTrade = false;

         }
         }
         
     
//Check conditions

//BUY

if(MACDmain > MACDsignal) //MACD cross to the upside
   {
      for(int i = 1; i <=4; i++)
         {
            double EMA = iMA(NULL,0,20,0,MODE_EMA,PRICE_CLOSE,i);          //The for loop tests whether a crossover
            double EMA2 = iMA(NULL,0,20,0,MODE_EMA,PRICE_CLOSE,i+1);       //happened or not. A candle opening below 
            if(Close[i] > EMA && Open[i] < EMA && Close[i+1] < EMA2)       //the MA and closing above it signals a cross
               {                                                           //with the additional confirmation of the close of
                  BuyOne = true;                                           //previous candle being below the MA
                  break;
                }
            continue;
          }           
      
    }

//SELL

if(MACDmain < MACDsignal) //MACD cross to the downside
   {
      for(int j = 1; j <=4; j++)
         {
            EMA = iMA(NULL,0,20,0,MODE_EMA,PRICE_CLOSE,j);              //Same principle as the BUY signal except in reverse
            EMA2 = iMA(NULL,0,20,0,MODE_EMA,PRICE_CLOSE,j+1);
            if(Close[j] < EMA && Open[j] > EMA && Close[j+1] > EMA2) 
               {
                  SellOne = true;
                  break;
                }
            continue;
          }           
      
    }
//End Check conditions

if(BuyOne == true && IsTrade == false && BarTrade != Bars)
   {
      Ticket = OrderSend(Symbol(),OP_BUY,Lots,Ask,MarketInfo(Symbol(),MODE_SPREAD),0,0,NULL,MagicNumber,0,Green); 
      int BarTrade = Bars; //The trade only executes on a new bar 
      if (Ticket==-1)   ShowERROR(Ticket,0,0);
    }
    
if(SellOne == true && IsTrade == false && BarTrade != Bars)
   {
      Ticket = OrderSend(Symbol(),OP_SELL,Lots,Bid,MarketInfo(Symbol(),MODE_SPREAD),0,0,NULL,MagicNumber,0,Red); 
      BarTrade = Bars;
      if (Ticket==-1)   ShowERROR(Ticket,0,0);

    }      
      
   


            
//----
   return(0);
  }
  }
//+------------------------------------------------------------------+


void ShowERROR(int Ticket,double SL,double TP)
{
   int err=GetLastError();
   switch ( err )
   {                  
      case 1:                                                                               return;
      case 2:   Alert("No connection with the trading server ",        Ticket," ",Symbol());return;
      case 130: Alert("Error close foot Ticket ",                      Ticket," ",Symbol());return;
      case 134: Alert("Not enough money ",                             Ticket," ",Symbol());return;
      case 146: Alert("Error Subsystem busy trade ",                   Ticket," ",Symbol());return;
      case 129: Alert("Error Invalid price ",                          Ticket," ",Symbol());return;
      case 131: Alert("Error Invalid volume ",                         Ticket," ",Symbol());return;
      default:  Alert("Error : ",err, "   ",                           Ticket," ",Symbol());return;
   }
}


 
Reason: