Grid strategy placing too many trades

 

Hello,

This EA is designed to place a number of buy and sell pending limit trades, using the TradesAboveBelow parameter. When the EA loads, it gets the current Bid price and places the specified number of trades above and below that Bid price, all spaced according to other variables. This part works just fine. It's supposed to keep a count of the trades so that when either the buys or the sells count goes lower than the variable, it finds the last trade from history, gets that trade's OpenOrderPrice, and places a new pending buy or sell limit order to replace the trade that closed with profit. Basically, there should always be the specified number of trades above and below the Bid price on the board at any one time.

Where I'm running into problems is when the EA replaces a trade, it does so correctly, but it often places too many trades causing my count to be above the specified variable, which then causes other EA functions not to work properly.

Can anyone suggest anything that may be causing this? I don't claim to know everything about coding, but i've never run into this before. Thanks.

#define DECIMAL_CONVERSION 10

//======================= Params ===============================
extern int MagicNumber        = 165443;
extern int TradesAboveBelow   = 30;
int StopLoss                  = 0;
extern double TakeProfit      = 6;
extern string OrderSpacing1   = "==========================";
extern bool UseADRPercentage  = false;
extern double ADR_Percentage  = 20;
extern int PipsBetweenOrders  = 30;
extern string OrderSpacing2   = "==========================";
extern bool UseAutoLots       = true;
extern double FixedLots       = 0.10;
extern int AutoLotLeverage    = 10;
extern int ADR_Period_Days    = 30;
int Slippage                  = 3;
int PercentMultiplier         = 100;

int      InitialBuyOrder, InitialSellOrder, ticket, TotalOrders, total, ordertotal, buy_total, sell_total;
double   OrderSpacing, BasePrice, buy_price, sell_price, ADR, ADRange, ADR_Percent, R30, TP, Lots, lotmin, lotmax;


//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
  {

      if (Digits == 3 || Digits == 5)
      {
        Slippage           *= DECIMAL_CONVERSION; 
        StopLoss           *= DECIMAL_CONVERSION;
        TakeProfit         *= DECIMAL_CONVERSION;
        PipsBetweenOrders  *= DECIMAL_CONVERSION;
        PercentMultiplier  /= DECIMAL_CONVERSION;
      }

   lotmin = MarketInfo(Symbol(), MODE_MINLOT);
   lotmax = MarketInfo(Symbol(), MODE_MAXLOT);
   
   TakeProfit = TakeProfit*Point;
   ADR_Percent = ADR_Percentage/PercentMultiplier;
   
   if(!GlobalVariableCheck("ADR")){
      ADR=GetADR();
      GlobalVariableSet("ADR",ADR);
      }

   if(!GlobalVariableCheck("BasePrice")){
      GlobalVariableSet("BasePrice",NormalizeDouble(Bid,Digits));}

   BasePrice = GlobalVariableGet("BasePrice");
   ADRange = GlobalVariableGet("ADR");
   
   if(UseADRPercentage)
      OrderSpacing = (ADRange*ADR_Percent)*Point;
   else OrderSpacing = PipsBetweenOrders*Point;

   buy_price = BasePrice - OrderSpacing;
   sell_price = BasePrice + OrderSpacing;
   InitialBuyOrder = 0;
   InitialSellOrder = 0;

   return(0);
  }
//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
  {
//----
   CancelPendingOrder();
   if(total==0){
   GlobalVariableDel("ADR");
   GlobalVariableDel("BasePrice");
   }
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
  {


   total = 0;
   buy_total = 0;
   sell_total = 0; 
   
   for(int i = 0; i < OrdersTotal(); i++){
      OrderSelect(i,SELECT_BY_POS,MODE_TRADES);
      if( OrderType() == OP_BUY || OrderType() == OP_SELL ) { 
         if (OrderSymbol()==Symbol() && OrderMagicNumber()==MagicNumber){
            total += 1; 
         }
      }

      if( OrderType() == OP_BUY || OrderType() == OP_BUYLIMIT ) { 
         if (OrderSymbol()==Symbol() && OrderMagicNumber()==MagicNumber){
            buy_total += 1; 
         }
      }
      if( OrderType() == OP_SELL || OrderType() == OP_SELLLIMIT ) { 
         if (OrderSymbol()==Symbol() && OrderMagicNumber()==MagicNumber){
            sell_total += 1; 
         }
      }
   }


   if(buy_total==TradesAboveBelow){
      InitialBuyOrder=1;
      }
      
   if(sell_total==TradesAboveBelow){
      InitialSellOrder=1;
      }

   if(buy_total<TradesAboveBelow && InitialBuyOrder==0){
         PlaceBuy(NormalizeDouble(buy_price,Digits), TakeProfit);
         buy_price -= OrderSpacing;
         }

   if(buy_total<TradesAboveBelow && InitialBuyOrder==1){
      for(int j=(OrdersHistoryTotal()-1);j>=0;j--){
         OrderSelect(j,SELECT_BY_POS,MODE_HISTORY);
            if(OrderType() == OP_BUY && OrderSymbol()==Symbol() && OrderMagicNumber()==MagicNumber){ 
               PlaceBuy(NormalizeDouble(OrderOpenPrice(),Digits), TakeProfit);
            }
         }   
      }
  
   if(sell_total<TradesAboveBelow && InitialSellOrder==0){
         PlaceSell(NormalizeDouble(sell_price,Digits), TakeProfit);
         sell_price += OrderSpacing;
         }

   if(sell_total<TradesAboveBelow && InitialSellOrder==1){
         for(int l=(OrdersHistoryTotal()-1);l>=0;l--){
            OrderSelect(l,SELECT_BY_POS,MODE_HISTORY);
            if(OrderType() == OP_SELL && OrderSymbol()==Symbol() && OrderMagicNumber()==MagicNumber){ 
               PlaceSell(NormalizeDouble(OrderOpenPrice(),Digits), TakeProfit);
            }
         }   
      }
   
   Comment("Buy Orders = ", buy_total, "\n", "Sell Orders = ", sell_total);
  
   return(0);
  }



//+------------------------------------------------------------------+
//| additional trade functions                                       |
//+------------------------------------------------------------------+
double GetADR(){
   
   R30=0;
   int i=0;

   for(i=1;i<=ADR_Period_Days;i++)
   R30 = R30 + (iHigh(NULL,PERIOD_D1,i)-iLow(NULL,PERIOD_D1,i))/Point;

   R30 = NormalizeDouble(( (R30/ADR_Period_Days)/10 ),1);

   return(R30);
   }
//+------------------------------------------------------------------+
double GetLots(){
   
      if(UseAutoLots)
         double Lots = ((AccountBalance()*AutoLotLeverage)/100000);
         else {Lots = FixedLots;}
         
      if(Lots<lotmin) Lots=lotmin;
      if(Lots>lotmax) Lots=lotmax;
      
      return(Lots);
   }
//+------------------------------------------------------------------+
void PlaceBuy(double entry, double TP){

      Lots = GetLots();

      ticket=OrderSend(Symbol(), OP_BUYLIMIT, Lots, entry, Slippage, 0.0, (entry+TP), "", MagicNumber, 0, CLR_NONE);
      if(ticket<=0) Print("Error = ",GetLastError());
//      else { 
//         Print("Ticket #", ticket, " -- Order Open Time ", TimeToStr(OrderOpenTime(),TIME_SECONDS)); 
//         if (OrderSelect(ticket, SELECT_BY_TICKET)){
//         OrderModify( ticket, OrderOpenPrice(), sl, tp, 0, CLR_NONE );}
//      }
      
      
return;
  }
//+--------------------------------------------------------------------------------
void PlaceSell(double entry, double TP){

      Lots = GetLots();
   
      ticket=OrderSend(Symbol(), OP_SELLLIMIT, Lots, entry, Slippage, 0.0, (entry-TP), "", MagicNumber, 0, CLR_NONE);
      if(ticket<=0) Print("Error = ",GetLastError());
//      else {  
//         if (OrderSelect(ticket, SELECT_BY_TICKET)){
//         OrderModify( ticket, OrderOpenPrice(), sl, tp, 0, CLR_NONE );}
//      }
      
      return;
   }
//+--------------------------------------------------------------------------------
void CancelPendingOrder()
{

   for(int i = 0; i < OrdersTotal(); i++)
   {
    OrderSelect(i,SELECT_BY_POS,MODE_TRADES);
    if (OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
    { 
      int type   = OrderType();
      bool result = false;
      switch(type)
      {
         //Close pending orders
         case OP_BUYLIMIT  :
         case OP_BUYSTOP   :
         case OP_SELLLIMIT :
         case OP_SELLSTOP  : result = OrderDelete( OrderTicket() );
      }
      if(result == false)
      {
         Alert("Order " , OrderTicket() , " failed to close. Error:" , GetLastError() );
         Sleep(3000);
      }
    }  
  }
  
return(0);
}

//+-------------------------------------------------------------------------------- 
 
  1.       if (Digits == 3 || Digits == 5)
          {
            Slippage           *= DECIMAL_CONVERSION; 
            :
    TakeProfit = TakeProfit*Point;
    Each time you go through an deinit/init cycle (change pair, change TF, etc. even ACDENTIALLY) your variables get multiplied by 10, 100, 1000... and TakeProfit get multipled by 0.00001, 0.0000000001, ...
    //++++ These are adjusted for 5 digit brokers.
    int     pips2points;    // slippage  3 pips    3=points    30=points
    double  pips2dbl;       // Stoploss 15 pips    0.015      0.0150
    int     Digits.pips;    // DoubleToStr(dbl/pips2dbl, Digits.pips)
    int     init(){
         if (Digits % 2 == 1){      // DE30=1/JPY=3/EURUSD=5 forum.mql4.com/43064#515262
                    pips2dbl    = Point*10; pips2points = 10;   Digits.pips = 1;
        } else {    pips2dbl    = Point;    pips2points =  1;   Digits.pips = 0; }
    

  2.  for(int i = 0; i < OrdersTotal(); i++){
          OrderSelect(i,SELECT_BY_POS,MODE_TRADES);
    This makes the EA incompatible with every other, including itself on other charts except you check 3 times later. Only need to check once.
        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()       == Symbol()                 // and my pair.
        ){

  3. Always count down when closing and deleteing. Count down always.
  4. determine that if a trade already exists at a particular OpenPrice, it doesn't need to place another one there.
    Your not doing that. No where are you checking price. Try something like
    bool buysAbove[5]; for (i=0; i<4; i++) buysAbove[i]=false;
    for/order select&&...{
       if ( OrderType() == OP_BUYSTOP){
          int igrid = (OrderOpenPrice() - Bid)/GridSize;
          if (iGrid > 4) closeOrder();
          else buysAbove[iGrid] = true;
       }
    }
    for (i=1; i< 4; i++) if (!buysAbove[i]){ open buy limit at Bid+gridSize * i }

 

Thanks for the response, but I'm not having success with your changes either. I implemented the "counting down" loop instead of what I had coded, but the EA is still opening too many trades when it replaces a trade that closed with profit. I don't necessarily need it to check the price to see if there's a trade already there, I just need it to not place multiple replacement trades.

My order counting loop was counting properly as is yours, but for some reason, it's still having issues. Basically, what the loop does is it tells the EA that a trade closed and needs to be replaced. The EA then checks the order history and get the last trade that matches the symbol and magic number and places a new pending limit order with the closed order's OpenOrderPrice.

Any other ideas? I'm stumped with this one.

 
bstocking:
Any other ideas? I'm stumped with this one.
Reread #4 and DO IT. No Slaves here, learn to code or pay someone. We're not going to code it FOR you. We are willing to HELP you.
 

This is what I wrote in my previous reply. "I don't necessarily need it to check the price to see if there's a trade already there, I just need it to not place multiple replacement trades."

I'm pretty sure I didn't ask you to do it FOR me. I just asked for ideas. If you look at my first post you'll see that I supplied the entire code and just asked for some HELP with a minor problem. Now, if you want to HELP, then do it, otherwise, go be condescending to someone else.

 

Why do you need two threads about the same thing . . .

Add some comments if you want other people to be able to follow your code. When looping through orders count down . . .

Reason: