EA in infinite loop of opening/closing pending orders while certain conditions are met

 

I have been battling this for some time. Here is the general EA idea:

-Set pending BUYSTOP at this level

-If that level changes, delete old pending order, set new BUYSTOP

My problem is that my open order triggers, then my delete pending order triggers, and it goes back and forth a million times. I have previously solved this buy initiating the delete pending order at a time (say 0001) and then setting new orders (at say 0002). This just seems like an ugly work around, but it works. My new idea is to check the BUYSTOP level on the chart against the current pending order. If those numbers are different, delete all pending orders and make new ones. Let me show you what I have tried. The results of all this is the continued infinite loop of open/delete/open/delete/open/delete/open/delete.

start(){
double max = iCustom(Symbol(),PERIOD_D1,"my_fractal_channels",0,0,0); //this is level of BUYSTOP I want
double pendingBuyPrice = orderInfo(Symbol(), magicNumber, OP_BUYSTOP, OrderOpenPrice());

if(pendingBuyPrice != max)  //if the current BUYSTOP price is not the same as the "max" level that I want the BUYSTOP to be, continue
      {
         deletePendingOrders(Symbol(), OP_BUYSTOP, magicNumber); //current pending order is no longer valid, delete it
         
         tp = max + tpV;
         sl = mid;
         open = max;
         type = OP_BUYSTOP;
   
         stopPip = (open - sl) / UsePoint;

         calcLot = CalcLotSize(EquityPercent, stopPip);
         calcLot = VerifyLotSize(calcLot);
   
         placeOrder(type, open, sl, 0, calcLot, magicNumber); //place new order, and at this point when start() recycles it SHOULD show that pendingBuyPrice == max...right? not for me
      }

}

//here are my functions:

int placeOrder (int type, double entryPrice, double iStopLoss, double iTakeProfit, double icalcLot, int imagicNumber)
   {
      while(IsTradeContextBusy()) Sleep(10); //make sure MT4 not busy with trades from other EAs
      int Ticket = OrderSend(Symbol(),type, icalcLot, entryPrice,3, iStopLoss, iTakeProfit,NULL,imagicNumber,0,CLR_NONE);
      
      if ( Ticket == -1)
         {
            ErrorCode = GetLastError();
            ErrDesc = ErrorDescription(ErrorCode);
         
            ErrAlert = StringConcatenate("Open type (", type , ") Order - Error " , ErrorCode, ": ", ErrDesc);
            Alert(ErrAlert);
         
            ErrLog = StringConcatenate("Entry: ", entryPrice, " SL: ",iStopLoss," Lots: ", icalcLot);
            Print(ErrLog);
         }
   }

double orderInfo(string argSymbol, int argMagicNumber, int type, double info)
   {
         for(int Counter = OrdersTotal()-1; Counter >= 0; Counter--) 
            if(
               OrderSelect(Counter, SELECT_BY_POS)
               && OrderMagicNumber() == argMagicNumber 
               && OrderSymbol()      == argSymbol
               && OrderType()        == type) return(info);
                  return(false);
   }

So that is one attempt(above), trying to pull OrderOpenPrice from current BUYSTOP and check it against my "max" level.

My other idea was to send "max" level to a function that checks it against the current OrderOpenPrice, and returns true or false accordingly. Let me show you.

start()
{
bool pendingBuyOrderCheck = relevantPendingOrder(Symbol(), magicNumber, OP_BUYSTOP, max);

if(pendingBuyOrderCheck == false)
      {
         deletePendingOrders(Symbol(), OP_BUYSTOP, magicNumber);
         
         tp = max + tpV;
         sl = mid;
         open = max;
         type = OP_BUYSTOP;
   
         stopPip = (open - sl) / UsePoint;

         calcLot = CalcLotSize(EquityPercent, stopPip);
         calcLot = VerifyLotSize(calcLot);
   
         placeOrder(type, open, sl, 0, calcLot, magicNumber);
      }

}

//same placeOrder() function as above

bool relevantPendingOrder(string argSymbol, int argMagicNumber, int type, double openPrice)
   {
         for(int Counter = OrdersTotal()-1; Counter >= 0; Counter--) 
            if(
               OrderSelect(Counter, SELECT_BY_POS)
               && OrderMagicNumber() == argMagicNumber 
               && OrderSymbol()      == argSymbol
               && OrderType()        == type
               && OrderOpenPrice()   == openPrice) return(true);
                  return(false);
   }

Similar results. Let me know if you need more information, I have been banging my head against this for some time and need some help. Or, if you guys have any other ideas, ways you have overcome this issue yourself, I am open to those ideas as well. Thanks for your time.

 

I have some remarks, I'm not sure it solves the problem, but give it a try.

1. Before you use OrderOpenPrice(), an order must be selected by OrderSelect()

start(){
double max = iCustom(Symbol(),PERIOD_D1,"my_fractal_channels",0,0,0); //this is level of BUYSTOP I want
double pendingBuyPrice = orderInfo(Symbol(), magicNumber, OP_BUYSTOP, OrderOpenPrice());

2. I know that false is same as 0, but using as double return value is strange

double orderInfo(string argSymbol, int argMagicNumber, int type, double info)
   { ...
               && OrderType()        == type) return(info);
                  return(false);
   }

3. OrderOpenPrice() == openPrice is a double equal comparison, that is illegal in programming. There was a topic about it recently.

//+------------------------------------------------------------------+
//| right comparison of 2 doubles                                    |
//+------------------------------------------------------------------+
bool CompareDoubles(double number1, double number2)
  {
   if (NormalizeDouble(number1 - number2, 8) == 0) return(true);
   else return(false);
  }
 

Check the value of this first:

Print ("Pending Buy Price "+pendingBuyPrice+". max "+max); // <<== check this first
if(pendingBuyPrice != max)  //if the current BUYSTOP price is not the same as the "max" level that I want the BUYSTOP to be, continue

if you want to compare that two doubles, open MetaEditor libraries, look for stdlib.mq4, scroll down and you'l find what erzo has told you

//+------------------------------------------------------------------+
//| right comparison of 2 doubles                                    |
//+------------------------------------------------------------------+
bool CompareDoubles(double number1,double number2)
  {
   if(NormalizeDouble(number1-number2,8)==0) return(true);
   else return(false);
  }

BTW, when your orderinfo function returned false ( = 0), that's trigger the if(pendingBuyPrice != max), re-writes it and see it again

if(pendingBuyPrice != max && pendingBuyPrice != false)
 

doubles rarely compare equal (usually compare not equal) Can price != price ? - MQL4 forum

Never use NormalizeDouble, EVER. It's always unnecessary and will lie to you. Bid/Ask: (No Need) to use NormalizeDouble in OrderSend - MQL4 forum

Reason: