Trailing candle stoploss

 

Hi,

 

I'm trying to use a candle trailing stoploss. The one for the buy trades seems to work as it should. How ever the sell one keeps giving an order modify 1 error. I have looked this up but I dont understand what the issue is. The buy works so the sell should be the opposite. Well thats my logic anyway. Any help appreciated.

oid AdjustTrail()
  {
  
  int BuyStopCandle=iLowest(NULL,0,1,CandlesBackSL,1); // Finds the swing low
  int SellStopCandle=iHighest(NULL,0,2,CandlesBackSL,1); // Finds the swing high.
  
  double buy_stop_price=Low[BuyStopCandle]-SwingPadAmount*pips; // Adds SL on low when buying + Pad amount
  double sell_stop_price=High[SellStopCandle]+SwingPadAmount*pips; // Adds SL to High
  
// buy order

   for(int b=OrdersTotal()-1; b>=0; b--)
     {
      if(OrderSelect(b,SELECT_BY_POS,MODE_TRADES))
         if(OrderMagicNumber()==MagicNumber)
            if(OrderSymbol()==Symbol())
               if(OrderType()==OP_BUY)
                  if(IsNewCandle())
                    {
                     if(OrderStopLoss()<Low[BuyStopCandle]-TrailingStopPad*pips) // User variable to look back x amount of candles.
                        OrderModify(OrderTicket(),OrderOpenPrice(),buy_stop_price,OrderTakeProfit(),0,CLR_NONE);

                    }
      //+------------------------------------------------------------------+

     }

// Sell Order

   for(int s=OrdersTotal()-1; s>=0; s--)
     {
      if(OrderSelect(b,SELECT_BY_POS,MODE_TRADES))
         if(OrderMagicNumber()==MagicNumber)
            if(OrderSymbol()==Symbol())
               if(OrderType()==OP_SELL)
                  if(IsNewCandle())
                    {
                     if(OrderStopLoss()>High[SellStopCandle]+TrailingStopPad*pips) // User variable to look back x amount of candles.
                        OrderModify(OrderTicket(),OrderOpenPrice(),sell_stop_price,OrderTakeProfit(),0,CLR_NONE);
                       // else PrintFormat("Error in Modify. Error code=%d",GetLastError());

                    }
 
Ha for anyone reading. Make sure when you copy and paste you change everything. For the last 2 hours I have been burning my eyes out. On the sell order after order select it should be an "S" and not a "B". Lessons learnt.
 

There is no need to  use different variable names in different loops, most people seem to use "i" which is , I assume, short for "index". I tend to prefer to use "x" because "1" can easily be mistaken for "i" in the code. If you had stuck to a convention, you would not have made this error.

You should always strive to make your code as efficient as possible. From looking at your code, modications are only executed when there is a new candle, so why execute the calculations and loops at all?

void AdjustTrail()
  {
    if(IsNewCandle())
      return;

Also, I have never seen a function such as

    IsNewCandle()

that returns true from multiple calls in the same tick. It will usually return true the first time that it is called when a new bar is formed, but subsequent calls in the same tick will usually return false. Check your function and see if that is correct.

The other thing is - why loop through the orders twice?

void AdjustTrail()
  {
   if(IsNewCandle())
      return;

   int BuyStopCandle=iLowest(NULL,0,1,CandlesBackSL,1); // Finds the swing low
   int SellStopCandle=iHighest(NULL,0,2,CandlesBackSL,1); // Finds the swing high.

   double buy_stop_price=Low[BuyStopCandle]-SwingPadAmount*pips; // Adds SL on low when buying + Pad amount
   double sell_stop_price=High[SellStopCandle]+SwingPadAmount*pips; // Adds SL to High

   for(int b=OrdersTotal()-1; b>=0; b--)
     {
      if(OrderSelect(b,SELECT_BY_POS,MODE_TRADES))
         if(OrderMagicNumber()==MagicNumber)
            if(OrderSymbol()==Symbol())
              {
               if(OrderType()==OP_BUY)
                 {
                  if(OrderStopLoss()<Low[BuyStopCandle]-TrailingStopPad*pips) // User variable to look back x amount of candles.
                     OrderModify(OrderTicket(),OrderOpenPrice(),buy_stop_price,OrderTakeProfit(),0,CLR_NONE);
                 }
               if(OrderType()==OP_SELL)
                 {
                  if(OrderStopLoss()>High[SellStopCandle]+TrailingStopPad*pips) // User variable to look back x amount of candles.
                     OrderModify(OrderTicket(),OrderOpenPrice(),sell_stop_price,OrderTakeProfit(),0,CLR_NONE);
                  // else PrintFormat("Error in Modify. Error code=%d",GetLastError());
                 }
              }
     }

  }

.

 
I guess i'm new to coding and dont know all the shortcuts and making the code shorter. I just had written it like that thinking through the process and copying a few videos I found on youtube. Isnewcandle does check for a new bar. It works for me at the moment , but I will take your comments and help on board. Now to find a strategy that works ha. The million dollar question.
 

Isnewcandle does check for a new bar. It works for me at the moment

Please show your IsNewCandle function. Even without having seen it, I would almost bet the farm that it will not return true when called more than once in the same tick of a new candle.

 
bool IsNewCandle()
  {
   static int BarsOnChart;
   if(Bars==BarsOnChart) // if candles equal it will return false
      return(false);

   BarsOnChart=Bars; // Sets variable to amount on chart
   return(true);
  }

 

Thats the function. I'm confused as I thought I had the trailing candle. But its acting very strange. It moves down with the price ok. But then it moves away again as price comes towards it. Kind of defeats the idea of a stoploss ha. 

 
marine1983:

 

Thats the function. I'm confused as I thought I had the trailing candle. But its acting very strange. It moves down with the price ok. But then it moves away again as price comes towards it. Kind of defeats the idea of a stoploss ha. 

I would use Time[0], not Bars to detect a new bar.


As suspected, the function will only return true once per mew bar. So first call when there is a new bar, it will return true, subsequent calls in the same tick will return false.

 

Forgive me as i'm new to all of this. 

 

 Your statement indicates that is what I want. I only want to to return true when a new bar is created? Ticks within the same bar I want it to return false. Or am I not understanding correctly?

 

in your code

   for(int b=OrdersTotal()-1; b>=0; b--)
     {
      if(OrderSelect(b,SELECT_BY_POS,MODE_TRADES))
         if(OrderMagicNumber()==MagicNumber)
            if(OrderSymbol()==Symbol())
               if(OrderType()==OP_BUY)
                  if(IsNewCandle())
                    {
                     if(OrderStopLoss()<Low[BuyStopCandle]-TrailingStopPad*pips) // User variable to look back x amount of candles.
                        OrderModify(OrderTicket(),OrderOpenPrice(),buy_stop_price,OrderTakeProfit(),0,CLR_NONE);

                    }

the first pass through the loop it will return true, the 2nd and subsequent passes, although in the same tick will return false, so the code will not be executed.

 
  1. Bars is unreliable (a refresh/reconnect can change number of bars on chart) volume is unreliable (miss ticks) Always use time. New candle - MQL4 forum
  2. Anything that isn't changing inside a loop should be moved outside the loop. (IsNewCandle)
  3. While I like making functions, IsNewCandle can only be called once per tick, therefor I don't recommend that being a function, see the link.
 

Ok this is what I have now and it does not make a trade now. Its the same logic but with time. Why wont it trade?

 

 

   static datetime timeCur=Time[0];
   datetime timePre=timeCur;

   if(timeCur==timePre)
      return(false);


   timeCur=Time[0];
   return(true);

Reason: