Trailing Stop [Code Help]

To add comments, please log in or register
Fernando Jose Velasco Borea
894
Fernando Jose Velasco Borea  

Hello, I'm working on some EA's that uses Trailing Stop Loss, I came around with this code:

void Trailing_SL()
{ 
   for (int i = 0; i < OrdersTotal(); i++) //Iterar con todas las ordenes
    {
      bool res = OrderSelect(i,SELECT_BY_POS,MODE_TRADES); //Seleccionar por index i 
       int Local_ticket = OrderTicket(); //Guardar el numero de orden 
              
       if(OrderMagicNumber() == Magic) //Si la orden fue colocada por el bot
         {
           if (OrderType() == OP_BUY) //Y es una compra
            {
             if ( Ask - OrderOpenPrice() >= Trailing_Start * Pips() ) //Revisar si cumple con las condiciones para Trailing SL
               {
                if(Ask - OrderStopLoss() >= Trailing_Start * Pips())
                {
                 double New_TSL_Buy = OrderStopLoss() + Trailing_Step * Pips(); //Calcular el nuevo Stop Loss
                 bool Local_Res; //Indicativo para Fail Safe
                 Local_Res = OrderModify(Local_ticket,OrderOpenPrice(),New_TSL_Buy,OrderTakeProfit(),0); //Y colocarlo
                 
                 if (Local_Res == false)//Si la orden no se modifico correctamente
                  {
                     Alert("Falla en el Trailing Stop Loss para orden #", OrderTicket()); //Notificar que orden es
                     Alert("Codigo del error: ", GetLastError()); //Y la causa
                    }
                   }
                  }
                }
               else if(OrderType() == OP_SELL) //y si es compra
                  {
                    if ( OrderOpenPrice() - Bid >= Trailing_Start * Pips() )//Revisar si cumple con las condiciones para Trailing SL
                      {
                       if(OrderStopLoss() - Bid >= Trailing_Start * Pips()) //Y la diferencia del SL y el Bid es mas grande que la cantidad del trailing
                       {
                        double New_TSL_Sell = OrderStopLoss() - Trailing_Step * Pips(); //Calcular el nuevo Stop Loss
                        bool Local_Res; //Indicativo para Fail Safe
                        Local_Res = OrderModify(Local_ticket,OrderOpenPrice(),New_TSL_Sell,OrderTakeProfit(),0); //Y colocarlo
                          
                          if (Local_Res == false) //Si la orden no se modifico correctamente
                           {
                              Alert("Falla en el Trailing Stop Loss para orden #", OrderTicket()); //Notificar que orden es
                              Alert("Codigo del error: ", GetLastError()); //Y la causa
                             }
                            }
                          }
                        }
                     } 
                  }  
                }

My logic is this:

  • As long the order has the amount of pips on profit or more than the Trailing Start
  • And the difference between the Stop Loss and the current price is more or equal to the Trailing Start
  • Modify the order with the new SL calculated by adding to the current one the ammount of pips specified on the trailing step (This, for scalping systems convenience, in this case, I would take point values istead of entire pips to be suitable for smaller Time Frames)
Is my logic right or I am missing something?

William Roeder
19120
William Roeder  
           if (OrderType() == OP_BUY) //Y es una compra
            {
             if ( Ask - OrderOpenPrice() >= Trailing_Start * Pips() ) //Revisar si cumple con las condiciones para Trailing SL
               {
                if(Ask - OrderStopLoss() >= Trailing_Start * Pips())
                {
                 double New_TSL_Buy = OrderStopLoss() + Trailing_Step * Pips(); //Calcular el nuevo Stop Loss
                 bool Local_Res; //Indicativo para Fail Safe
                 Local_Res = OrderModify(Local_ticket,OrderOpenPrice(),New_TSL_Buy,OrderTakeProfit(),0); //Y colocarlo
                 
                 if (Local_Res == false)//Si la orden no se modifico correctamente
  1. You buy at the Ask and sell at the Bid.
    • Your buy order's TP/SL are triggered when the Bid reaches it. Not the Ask.
    • Your sell order's TP/SL will be triggered when the Ask reaches it. To trigger at a specific Bid price, add the average spread.
                MODE_SPREAD (Paul) - MQL4 and MetaTrader 4 - MQL4 programming forum - Page 3
    • The charts show Bid prices only. Turn on the Ask line to see how big the spread is (Tools -> Options {control-O} -> charts -> Show ask line.)

  2. A TSL is price - amount, not SL + amount. Your modify might run once. Then on the next tick you move it (by amount) again, and then again...

  3. Correct and simplify your code:
               if (OrderType() == OP_BUY) //Y es una compra
                {
                 double New_TSL_Buy = Bid - Trailing_Start * Pips();
                 if( New_TSL_Buy > MathMax( OrderOpenPrice(), OrderStopLoss() + _Point )
                     if(!OrderModify( ...

  4. You should be able to read your code out loud and have it make sense. You would never write if( (2+2 == 4) == true) would you? if(2+2 == 4) is sufficient. So don't write if(bool == true), just use if(bool) or if(!bool). Code becomes self documenting when you use meaningful variable names, like bool isLongEnabled where as Long_Entry sounds like a trigger price or a ticket number and "if long entry" is an incomplete sentence.

Fernando Jose Velasco Borea
894
Fernando Jose Velasco Borea  
whroeder1:
  1. You buy at the Ask and sell at the Bid.
    • Your buy order's TP/SL are triggered when the Bid reaches it. Not the Ask.
    • Your sell order's TP/SL will be triggered when the Ask reaches it. To trigger at a specific Bid price, add the average spread.
                MODE_SPREAD (Paul) - MQL4 and MetaTrader 4 - MQL4 programming forum - Page 3
    • The charts show Bid prices only. Turn on the Ask line to see how big the spread is (Tools -> Options {control-O} -> charts -> Show ask line.)

  2. A TSL is price - amount, not SL + amount. Your modify might run once. Then on the next tick you move it (by amount) again, and then again...

  3. Correct and simplify your code:

  4. You should be able to read your code out loud and have it make sense. You would never write if( (2+2 == 4) == true) would you? if(2+2 == 4) is sufficient. So don't write if(bool == true), just use if(bool) or if(!bool). Code becomes self documenting when you use meaningful variable names, like bool isLongEnabled where as Long_Entry sounds like a trigger price or a ticket number and "if long entry" is an incomplete sentence.

Thanks a lot! if you don't mind, could you help me with some aspects that I didn't got well:

Is there any utility of adding the Trailing Step function to a Trailing SL?

What is this line for?

if( New_TSL_Buy > MathMax( OrderOpenPrice(), OrderStopLoss() + _Point )
Fernando Jose Velasco Borea
894
Fernando Jose Velasco Borea  
whroeder1:
  1. You buy at the Ask and sell at the Bid.
    • Your buy order's TP/SL are triggered when the Bid reaches it. Not the Ask.
    • Your sell order's TP/SL will be triggered when the Ask reaches it. To trigger at a specific Bid price, add the average spread.
                MODE_SPREAD (Paul) - MQL4 and MetaTrader 4 - MQL4 programming forum - Page 3
    • The charts show Bid prices only. Turn on the Ask line to see how big the spread is (Tools -> Options {control-O} -> charts -> Show ask line.)

  2. A TSL is price - amount, not SL + amount. Your modify might run once. Then on the next tick you move it (by amount) again, and then again...

  3. Correct and simplify your code:

  4. You should be able to read your code out loud and have it make sense. You would never write if( (2+2 == 4) == true) would you? if(2+2 == 4) is sufficient. So don't write if(bool == true), just use if(bool) or if(!bool). Code becomes self documenting when you use meaningful variable names, like bool isLongEnabled where as Long_Entry sounds like a trigger price or a ticket number and "if long entry" is an incomplete sentencOh,

Oh, and just to make sure, although it might look like a stupid question,on sell orders instead of Bid - TSL would be Ask + TSL right?

William Roeder
19120
William Roeder  
FernandoBorea: What is this line for?
if( New_TSL_Buy > MathMax( OrderOpenPrice(), OrderStopLoss() + _Point )
  1. You don't trail until it is above open price.
  2. You never trail away from the market.
  3. You never trail with the same value (Error 1.)
Fernando Jose Velasco Borea
894
Fernando Jose Velasco Borea  
whroeder1:
  1. You don't trail until it is above open price.
  2. You never trail away from the market.
  3. You never trail with the same value (Error 1.)

Thanks! I made the modifications to the code, I'd like to add some new features and I have some other questions.

void Trailing_SL()
{ 
   for (int i = 0; i < OrdersTotal(); i++) //Iterar con todas las ordenes
    {
      bool res = OrderSelect(i,SELECT_BY_POS,MODE_TRADES); //Seleccionar por index i 
       int Local_ticket = OrderTicket(); //Guardar el numero de orden 
              
       if(OrderMagicNumber() == Magic) //Si la orden fue colocada por el bot
         {
           if (OrderType() == OP_BUY) //Y es una compra
            {
             if (Bid - OrderOpenPrice() >= Trailing_Start * Pips() ) //Revisar si cumple con las condiciones para Trailing SL
               {
                if(Bid - OrderStopLoss() >= Trailing_Start * Pips()) //Y la diferencia del Bid y el SL es superior o igual al Trailing
                {
                 double New_TSL_Buy = (Bid - Trailing_Start * Pips()) + Trailing_Step * Pips(); //Calcular el nuevo Stop Loss
                 bool Local_Res; //Indicativo para Fail Safe
                 Local_Res = OrderModify(Local_ticket,OrderOpenPrice(),New_TSL_Buy,OrderTakeProfit(),0); //Y colocarlo
                 
                 if (Local_Res == false)//Si la orden no se modifico correctamente
                  {
                     Alert("Falla en el Trailing Stop Loss para orden #", OrderTicket()); //Notificar que orden es
                     Alert("Codigo del error: ", GetLastError()); //Y la causa
                    }
                   }
                  }
                }
               else if(OrderType() == OP_SELL) //y si es compra
                  {
                    if ( OrderOpenPrice() - Ask >= Trailing_Start * Pips() )//Revisar si cumple con las condiciones para Trailing SL
                      {
                       if(OrderStopLoss() - Ask >= Trailing_Start * Pips()) //Y la diferencia del SL y el Ask es mas grande que la cantidad del trailing
                       {
                        double New_TSL_Sell = (Ask + Trailing_Start * Pips()) - Trailing_Step * Pips(); //Calcular el nuevo Stop Loss
                        bool Local_Res; //Indicativo para Fail Safe
                        Local_Res = OrderModify(Local_ticket,OrderOpenPrice(),New_TSL_Sell,OrderTakeProfit(),0); //Y colocarlo
                          
                          if (Local_Res == false) //Si la orden no se modifico correctamente
                           {
                              Alert("Falla en el Trailing Stop Loss para orden #", OrderTicket()); //Notificar que orden es
                              Alert("Codigo del error: ", GetLastError()); //Y la causa
                             }
                            }
                          }
                        }
                     } 
                  }  
                }        

I corrected the Bid and Ask errors and the Price - Amount errors, but I have some other questions, as the EA uses Break Even too, I considered that this line:

if(OrderStopLoss() - Ask >= Trailing_Start * Pips())

Would be useful to avoid to move the SL away when BE is activated (Because if the BE moves the SL to entry spot + Safe Pips (a function that I implemented on the EA that makes the trader able to move the SL to X pips in profit when the BE is activated) and the trailing SL is active then it might move back the SL to where it should be according to the trailing stop).

But I have some questions regarding the Price +- amount situation

  • The approach I took making the (Price -+ Amount) -+ Trailing Step part is correct to add the trailing step functionality?
  • The Trailing SL functionality is supposed to move the SL directly to maintain the distance specified (Making kind of a Break Even functionality  (For example, using the code I putted in this comment, when the order has the ammount of pips in profit selected on Trailing_Start it moves the SL directly to the price - that amount on pips, therefore, it moves the SL to profit))?
  • How can I make the trailing stop to trail without necessary moving the SL to profit? (For example, if the price moves 5 pips in profit then the SL is moved 5 pips although it stills below in the case of a buy order or above in the case of a sell order) I think that making something like check for the difference between the actual price and the SL then if its greater than the SL specified on the input then add the ammount of the Trailing Step value in pips to the SL,  (To avoid the EA to over comunicate with the server and flagging the account as hyperactive for moving the SL each tick on a big market movement) so then if the difference is equal or shorter (if it ends up a couple of points shorter due to the trailing step or requotations or if the price moves against) than the SL specified it would just do nothing until the order either hits the SL or moves in profit again so the conditions to move the SL are met. Is that approach correct? (Although if that's not the intended usage of a Trailing SL I think it can be useful to prevent overtaking losses on a situation where the price moves on profit several pips and then turns around, specially on scalping systems where this might happen pretty offen. I know it can sometimes work against the trader because well, if the order gets closed on a pull back  due to the SL movement and then moves back to what would be profits if the order would have kept openend, but for some systems this might improve the overall performance, specially on either short SL or scalping systems working on smaller Time Frames, so it might be good to add an option to activate this behaviour to run some backtesting and optimization to see if it improves the performance over the other Trailing Stop behaviour (Still not sure wich one is the "correct" or intended one).

I hope you are able to help me again on those new questions, I really appreciate your responses as well as those from other moderators! Sorry for keep asking and asking new stuffs.




Trinity Uruturi
33
Trinity Uruturi  
whroeder1:
  1. You buy at the Ask and sell at the Bid.
    • Your buy order's TP/SL are triggered when the Bid reaches it. Not the Ask.
    • Your sell order's TP/SL will be triggered when the Ask reaches it. To trigger at a specific Bid price, add the average spread.
                MODE_SPREAD (Paul) - MQL4 and MetaTrader 4 - MQL4 programming forum - Page 3
    • The charts show Bid prices only. Turn on the Ask line to see how big the spread is (Tools -> Options {control-O} -> charts -> Show ask line.)

  2. A TSL is price - amount, not SL + amount. Your modify might run once. Then on the next tick you move it (by amount) again, and then again...

  3. Correct and simplify your code:

  4. You should be able to read your code out loud and have it make sense. You would never write if( (2+2 == 4) == true) would you? if(2+2 == 4) is sufficient. So don't write if(bool == true), just use if(bool) or if(!bool). Code becomes self documenting when you use meaningful variable names, like bool isLongEnabled where as Long_Entry sounds like a trigger price or a ticket number and "if long entry" is an incomplete sentence.

//+------------------------------------------------------------------+
//          BREAK-EVEN                                               |
//+------------------------------------------------------------------+
void MoveToBreakeven()
{
      //buy order section   
   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(Bid-OrderOpenPrice()>WhenToMoveToBE*pips)
                  if(OrderOpenPrice()>OrderStopLoss())
                     OrderModify(OrderTicket(),OrderOpenPrice(),OrderOpenPrice()+(PipsToLockIn*pips),OrderTakeProfit(),0,CLR_NONE);
   }
//sell order section
   for (int s=OrdersTotal()-1; s >= 0; s--)              {          if(OrderSelect(s,SELECT_BY_POS,MODE_TRADES))                 if(OrderMagicNumber()== MagicNumber)                    if(OrderSymbol()==Symbol())                       if(OrderType()==OP_SELL)                   if(OrderOpenPrice()-Ask>WhenToMoveToBE*pips)                      if(OrderOpenPrice()<OrderStopLoss())                             OrderModify(OrderTicket(),OrderOpenPrice(),OrderOpenPrice()-(PipsToLockIn*pips),OrderTakeProfit(),0,CLR_NONE);         } } //+------------------------------------------------------------------+ //          TRAILING                                                 | //+------------------------------------------------------------------+ void AdjustTrail() { //buy order section       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(Bid-OrderOpenPrice()>WhenToTrail*pips)                         if(OrderStopLoss()<Bid-pips*TrailAmount)                            OrderModify(OrderTicket(),OrderOpenPrice(),Bid-(pips*TrailAmount),OrderTakeProfit(),0,CLR_NONE);          } //sell order section       for(int s=OrdersTotal()-1;s>=0;s--)               {          if(OrderSelect(s,SELECT_BY_POS,MODE_TRADES))             if(OrderMagicNumber()== MagicNumber)                if(OrderSymbol()==Symbol())                   if(OrderType()==OP_SELL)                      if(OrderOpenPrice()-Ask>WhenToTrail*pips)                         if((OrderStopLoss()>Ask+TrailAmount*pips) || (OrderStopLoss()==0))                            OrderModify(OrderTicket(),OrderOpenPrice(),Ask+(TrailAmount*pips),OrderTakeProfit(),0,CLR_NONE);          } }

Hi there,

So, I think I'm missing something in these 2 functions, because they both work like a charm for the BUY SECTIONS, but Absolutely nothing in the opposite direction.
I
'm a newbie coder by the way, so kindly pardon me if this may somewhat seem annoying to the more Experienced.

I would be eternally all the help I could get for this.

To add comments, please log in or register