Closing Pending Order and Opening new OrderSend?

 

I am wanting to close a pending order (assume we are only talking about a OP_BUYSTOP here) if the (iMA-iATR) > OrderStopLoss() on every H1 Close calculation. If that is true, then delete the order, and send a new order out with the new calculations based upon where the stop should now be on the OP_BUYSTOP. The lot's will also be re-calculated based upon the new stop distance, in-line with the risk profile. (at the moment just 2%).

I have got this pretty much there and had it working sweet as a nut, but I have made some changes, and now it will not work properly? Would appreciate someone shedding some light and where I am going wrong in my code? Technically, 90% of the orders placed, will be placed and then deleted because it needs new calculations done on it... At the moment, it will not do that on EVERY H1 close?

//+------------------------------------------------------------------+
//| Order Enter Function                                             |
//+------------------------------------------------------------------+
void OrderEntry(int direction)
{
   //determine amount to risk on this trade based on RiskPercent Above.
   double LotSize=0;
   double Equity=AccountEquity();
   double RiskedAmount=Equity*RiskPercent*0.01; // risk percent is just "2" at the moment.

   
   double ATR_Pad = iATR(NULL,60,14,1)/2; 
   double Buy_Pad = NormalizeDouble(ATR_Pad,Digits);
   double Sell_Pad = NormalizeDouble(ATR_Pad,Digits);
   
   //Get Highest Price in our lookback range and set buy price above it.
   int iTBT = iBarShift(NULL,60, triggerBarTime, true),
   iHH = iHighest(NULL,60, MODE_HIGH, iTBT + CandlesBeforeBiasObtained, 0);
   double Buy_Here = High[iHH] + Buy_Pad;
   double buyPrice= NormalizeDouble(Buy_Here,Digits);

   //Get Lowest Price in our lookback range and set sell price below it.
   datetime iTBT_1 = iBarShift(NULL, 60, triggerBarTime, true),
   iLL = iLowest(NULL, 60, MODE_LOW, iTBT_1 + CandlesBeforeBiasObtained, 0);
   double Sell_Here=Low[iLL] - Sell_Pad;
   double sellPrice= NormalizeDouble(Sell_Here,Digits);
   
   //Stop calculations.    
   double ATR = iATR(NULL,60,14,1);
   double MA = iMA(NULL,60,MA_Period,0,1,0,1);
   double BuyStopPriceMath = MA - ATR;
   double SellStopPriceMath = MA + ATR;
   double BuyStopPrice = NormalizeDouble(BuyStopPriceMath,Digits);
   double SellStopPrice = NormalizeDouble(SellStopPriceMath,Digits);


   //get our buystop price from below the ma and our takeprofit based on our r:r ratio.
   double pips_to_bsl=buyPrice-BuyStopPrice;
   double buy_tp_price=(pips_to_bsl*RewardRatio)+buyPrice;
   double buy_takeprofit_price= NormalizeDouble(buy_tp_price, Digits);

   //get our sellstop price from below the ma and our takeprofit based on our r:r ratio.
   double pips_to_ssl=SellStopPrice-sellPrice;
   double sell_tp_price=sellPrice-(pips_to_ssl*RewardRatio);
   double sell_takeprofit_price= NormalizeDouble(sell_tp_price, Digits);
   


//+-------------------------------------------------------------------------------------+
//| Order Buy Function                                                                  |
//+-------------------------------------------------------------------------------------+   

//Place a pending buystop if no orders exists.. pending or otherwise.
if(direction==0)
{ 
      double btp=buy_takeprofit_price;
      LotSize=(RiskedAmount/(pips_to_bsl/pips))/10;
      
      static double Stored_BuyPrice; // If the "BuyTicketOrder" is deleted because the iMA > OrderStopLoss(), 
                                 then the original OrderOpenPrice() is held here for the new OrderSend() function. 

      if(OpenOrdersThisPair(Symbol())==0)
         {
         int BuyTicketOrder= OrderSend(Symbol(),OP_BUYSTOP,LotSize,buyPrice,3,BuyStopPrice,btp,NULL,MagicNumber,0,Green);
         if(BuyTicketOrder == -1)Print("First Buy Order Last Error = ",GetLastError());
         //if(BuyTicketOrder > 0)Print("FIRST BUY ORDER PLACED:- Lots to open: ",DoubleToStr(LotSize,Digits)," Entry Price: ",DoubleToStr(buyPrice,Digits),
           //" Buy Stop Loss: ",DoubleToStr(bsl,Digits)," Buy Take Profit: ",DoubleToStr(btp,Digits)," Magic Number is: ",DoubleToStr(MagicNumber,Digits),
            //" FIRST BUY ORDER Open Time = ", OrderOpenTime());
            Print(" The Pad for the Order is: ", DoubleToStr(Buy_Pad, Digits), " ATR is: ", DoubleToStr(ATR,Digits));   
         } 

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

if(BuyTicketOrder>0)
{

      for(int b=OrdersTotal()-1; b>=0; b--)
         {
         if(OrderSelect(b,SELECT_BY_POS,MODE_TRADES)==true)
            {
            //Print(" Stop loss value for the order is ",OrderStopLoss());
            }
         else{
         } Print(" OrderSelect failed error code is ",GetLastError());
           
         if(!OrderType()==OP_BUYSTOP)continue;  
            if(OrderMagicNumber()==MagicNumber)
               if(OrderSymbol()==Symbol()) 
                     if(OrderStopLoss()<iMA(NULL,60,MA_Period,0,1,0,0)-ATR)
                        if(IsNewCandle()) // If it is a new H1 candle?
                        {
                        Stored_BuyPrice = OrderOpenPrice();
                        DeleteOrder = OrderDelete(OrderTicket());
                        //if(DeleteOrder != TRUE) Print("Buy Delete Order Failed = ",GetLastError());
                        //if(DeleteOrder==True)Print("Buy Order Deleted = ", OrderTicket());
                        }

         if(OpenOrdersThisPair(Symbol())==0 && DeleteOrder==True)// If there are no open orders = place a new order.
            {
            int NewBuyOrder = OrderSend(Symbol(),OP_BUYSTOP,LotSize,Stored_BuyPrice,3,BuyStopPrice,btp,NULL,MagicNumber,0,Green);
            if(NewBuyOrder == -1)Print("New Buy Order Last Error = ",GetLastError());
            //if(NewBuyOrder>0)Print("NEW BUY ORDER:- Lots to open: ",DoubleToStr(LotSize,Digits)," Entry Price: ",DoubleToStr(buyPrice,Digits),
               //" Buy Stop Loss: ",DoubleToStr(bsl,Digits)," Buy Take Profit: ",DoubleToStr(btp,Digits)," Magic Number is: ",DoubleToStr(MagicNumber,Digits));
               //Print(" The Pad for the Order is: ", DoubleToStr(Buy_Pad, Digits), " ATR is: ", DoubleToStr(ATR,Digits));
            }
      }
}   // end of  if(direction==0)
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
 
DomGilberto:

I am wanting to close a pending order (assume we are only talking about a OP_BUYSTOP here) if the (iMA-iATR) > OrderStopLoss() on every H1 Close calculation. If that is true, then delete the order, and send a new order out with the new calculations based upon where the stop should now be on the OP_BUYSTOP. The lot's will also be re-calculated based upon the new stop distance, in-line with the risk profile. (at the moment just 2%).

I have got this pretty much there and had it working sweet as a nut, but I have made some changes, and now it will not work properly? Would appreciate someone shedding some light and where I am going wrong in my code? Technically, 90% of the orders placed, will be placed and then deleted because it needs new calculations done on it... At the moment, it will not do that on EVERY H1 close?

You can't successfully use IsNewCandle() in this way . . . when you call this function and it returns true you change it's storder variable . . . if you want to test this write a indicator that calls it twice in succession and print the result each call, you will find that when you have the first tick of the new bar the first call will return true but the second call will return false . . . both on the same tick.

You can do what you are doing here and it may work but it may well come back to bit you and you may well not know why . . . the correct course of action is to do it properly.

 
Ah ok. Technically, I never used "IeNewCandle()" before. The order would delete and a new OrderSend() function would be sent out just on the basis of "OrderStopLoss() < iMa"...

But for some reason, it will not close out the order on the basis that, that if statement, is true. Instead, one order will be sent, and then the stoploss will not be updated relative to where the iMA is? How would I do it properly?
 
Call it once, at the beginning of start(). Return if false.
 
DomGilberto:
Ah ok. Technically, I never used "IeNewCandle()" before. The order would delete and a new OrderSend() function would be sent out just on the basis of "OrderStopLoss() < iMa"...

But for some reason, it will not close out the order on the basis that, that if statement, is true. Instead, one order will be sent, and then the stoploss will not be updated relative to where the iMA is? How would I do it properly?

One more issue . . .

!OrderType()

. . . OrderType() returns an int not a bool . . . check the precedence.

you should write some test scripts to make sure this kind of thing is doing what you think it should, it's a good way to learn.

And this . . .

 if(OrderSelect(b,SELECT_BY_POS,MODE_TRADES)==true)
            {
            //Print(" Stop loss value for the order is ",OrderStopLoss());
            }
         else{
         } Print(" OrderSelect failed error code is ",GetLastError());  // OrderSelect() has failed . . .
           
         if(!OrderType()==OP_BUYSTOP)continue;       // . . .  so the code continues here ! ! 
            if(OrderMagicNumber()==MagicNumber)
 
Woops - I don't even know why I did that! I think I got carried away with trial and error earlier this week and forgot to turn it back.

I've got it working again. WHRoder, you're right, I needed to call it within the start(). And to get the OrderSelect properly working for the for loop, I've set it up this way(See below.)

The last error I am now getting (As I had loads of prints and I have turned them all off!) is tonnes and tonnes of OrderModify error 1 - I've read somewhere that, that is to do with trying to modify an order with the same prices it already has, is that correct?


(P.S, because I am pretty slow with understanding the way things are written within the manual, I am right in saying "continue;" just stops where it is, and starts the for loop again, and "break;" exits the loop all together; in laymans terms?)
for(int b=OrdersTotal()-1; b>=0; b--)
         {
         if(!OrderSelect(b,SELECT_BY_POS,MODE_TRADES))continue;
 
DomGilberto:
Woops - I don't even know why I did that! I think I got carried away with trial and error earlier this week and forgot to turn it back.

I've got it working again. WHRoder, you're right, I needed to call it within the start(). And to get the OrderSelect properly working for the for loop, I've set it up this way(See below.)

The last error I am now getting (As I had loads of prints and I have turned them all off!) is tonnes and tonnes of OrderModify error 1 - I've read somewhere that, that is to do with trying to modify an order with the same prices it already has, is that correct?

Yes correct https://www.mql5.com/en/forum/146342

DomGilberto:


(P.S, because I am pretty slow with understanding the way things are written within the manual, I am right in saying "continue;" just stops where it is, and starts the for loop again, and "break;" exits the loop all together; in laymans terms?)

continue - A continue operator gives control to the beginning of the nearest outward cycle while or for operator, the next iteration being called - so when you have a for loop it will stop processing the loop for the current value and executes the loop for the next value.

break - A break operator terminates the execution of the nearest nested outward switch, while, or for operator. - so the break quits the loop and continues from where the loop ends.

 
This may sound like a stupid question, but is an Order Modify error 1 really that big of a deal? I mean, does it really matter whether I sort it or not? Would it have any material effect on my back-testing having that error? (i.e. missing trades, trades not being modified etc.)
 
DomGilberto:
This may sound like a stupid question, but is an Order Modify error 1 really that big of a deal? I mean, does it really matter whether I sort it or not? Would it have any material effect on my back-testing having that error? (i.e. missing trades, trades not being modified etc.)

Do you continually want to send OrderModify requests to your Broker asking him to . . . well, do nothing ? is that what you are designing your code to do ? if it is then you are set, if not then you need to fix it . . .

Error 1 is a pussy to sort . . . really, it's one of the easier errors to fix, compare new SL with old SL (or TP if you are modifying the TP) if they are the same don't execute the OrderModify() . . . and of course bear in mind the issue of comparing doubles . . . ( aren't you glad you understand that issue now )

 

Lol fair enough.

I modify lots, take profit and stop loss? I delete and re-open an order until it is triggered or cancelled. I've tried this, but it doesn't seem to work? Not sure if it has something to do with comparing the doubles? (Not sure what you mean by that? NormalizeDouble?)

//+-------------------------------------------------------------------------------------+
//| Order Buy Function                                                                  |
//+-------------------------------------------------------------------------------------+   

//Place a pending buystop if no orders exists.. pending or otherwise.
if(direction==0)
{ 
      double btp=buy_takeprofit_price; 
      double Min_Lot = MarketInfo(Symbol(),MODE_MINLOT);
      double Lot_Step = MarketInfo(Symbol(),MODE_LOTSTEP);
      double BuyLotSize =(RiskedAmount/(pips_to_bsl/pips))/10;
      double Lots = NormalizeDouble(BuyLotSize,2);
      LotSize = MathFloor(Lots/Lot_Step)*Lot_Step;
 
      static double Stored_BuyPrice;
      static double Old_Buy_TP;
      static double Old_Buy_SL;
      static double Old_Lots;

      if(OpenOrdersThisPair(Symbol())==0)
         {
         int BuyTicketOrder= OrderSend(Symbol(),OP_BUYSTOP,LotSize,buyPrice,3,BuyStopPrice,btp,NULL,MagicNumber,0,Green);
         if(BuyTicketOrder == -1)Print("First Buy Order Last Error = ",GetLastError());   
         } 

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


      for(int b=OrdersTotal()-1; b>=0; b--)
         {
         if(!OrderSelect(b,SELECT_BY_POS,MODE_TRADES))continue;
            {
            Print(" Stop loss value for the order is ",OrderStopLoss());
            }
           
         if(OrderType()==OP_BUYSTOP) 
            if(OrderMagicNumber()==MagicNumber)
               if(OrderSymbol()==Symbol()) 
                   if(OrderStopLoss()<iMA(NULL,60,MA_Period,0,1,0,0)-ATR)
                        {
                        Old_Lots = OrderLots(); // I am storing the number in here before it is deleted?
                        Stored_BuyPrice = OrderOpenPrice();
                        Old_Buy_TP = OrderTakeProfit();
                        Old_Buy_SL = OrderStopLoss();
                        DeleteOrder = OrderDelete(OrderTicket());
                        }

         if(OpenOrdersThisPair(Symbol())==0 && DeleteOrder==True)// If there are no open orders = place a new order.
           if(Old_Buy_TP != btp && Old_Buy_SL != BuyStopPrice && Old_Lots != LotSize) // if they do not equal to what I am trying to 
                                                                           change it to, then it will place the NewBuyOrder? (OrderSend())?
            {
            int NewBuyOrder = OrderSend(Symbol(),OP_BUYSTOP,LotSize,Stored_BuyPrice,3,BuyStopPrice,btp,NULL,MagicNumber,0,Green);
            if(NewBuyOrder == -1)Print("New Buy Order Last Error = ",GetLastError());
            }
      }
} 
 
DomGilberto:

Lol fair enough.

I modify lots, take profit and stop loss? I delete and re-open an order until it is triggered or cancelled. I've tried this, but it doesn't seem to work? Not sure if it has something to do with comparing the doubles? (Not sure what you mean by that? NormalizeDouble?)

Click the link in this post, read the thread until your eyes bleed and you understand: https://www.mql5.com/en/forum/146040/page6#824482
Reason: