Automated Trailing Stop

 

Hi Everyone,

I’m trying to make an EA that starts a trailing Stop when the profit reaches a certain level (in the code I have set the level to £1).  However, it is not working and I cannot work out why.  It seems to set the Break Even figure OK but when the profit reaches £1 it does not move the original Stop Loss set when I first placed the order.  Also, there’s a very minor problem with the Comment() command as when I have more than one Order open at the same time the Comment is displaying information for the wrong order.  The original code came from one of the examples on the Modification of Orders page in the Documentation Section but I have heavily modified it.

Regards, CrashnBurn


//+------------------------------------------------------------------+
//|                                               ModifyStopLoss.mq4 |
//|                                                                  |
//|                                                                  |
//+------------------------------------------------------------------+
#property strict

extern double StartProfit = 1;  //Amount of profit before start

double TrailingStart, TrailingStop, TrailingStep;
double dblBreakEvenPrice, dblOpenPrice, dblAsk, dblBid, dblSpread, dblTakeProfit;
string strText;

int Slippage = 3;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
        dblAsk = Ask;
        dblBid = Bid;
        dblSpread = NormalizeDouble(dblAsk-dblBid,Digits); 
        dblBreakEvenPrice = 0;
        
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
   
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
  //Comment(StringFormat("\nProgram 1 Working, Order Total:  %G ",OrdersTotal()));
            
   if(StartProfit>0) TrailOrder (TrailingStart, TrailingStop);
  
   return;                                      // Exit OnTick()
   }
  
  
//+------------------------------------------------------------------+
void TrailOrder(double Trailingstart,double Trailingstop)
   {
   int ticket = 0, intCount, intSlippage;
   double dblPoint; 

   double dblTrailingStopLoss = NormalizeDouble(OrderStopLoss(), Digits); // Stop Loss
   double dblStopLoss = NormalizeDouble(OrderStopLoss(), Digits); // Stop Loss

   if (Digits == 3 || Digits == 5)
      {
         dblPoint = Point * 10; intSlippage = Slippage * 10;
      }
   else
       {
         dblPoint = Point; intSlippage = Slippage;
       }

   RefreshRates();
   if(OrdersTotal()>0)
      {
         for(intCount=OrdersTotal();intCount>=0;intCount--)
            {
               if(OrderSelect(intCount,SELECT_BY_POS,MODE_TRADES)==true)
                  {
                  if (OrderSymbol()!=Symbol()||OrderType()>1) return;
                     Comment(StringFormat("\nDetails of Order Detected: \nOrder Profit is %G   Swap Fee is %G\nSpread is %G\nOrder Open Price is %G\nBreak Even Price is %G   Rolling Stop Loss is %G\nCurrent Price is %G",NormalizeDouble(OrderProfit()+OrderSwap(),2),OrderSwap(),dblSpread,OrderOpenPrice(),dblBreakEvenPrice,dblTrailingStopLoss,MarketInfo(Symbol(),MODE_BID)));
                     if(OrderType() == OP_BUY)
                        {
                           if(OrderProfit()>StartProfit && dblBreakEvenPrice == 0)
                              {
                                 dblBreakEvenPrice = NormalizeDouble(Ask - OrderOpenPrice(),Digits);
                                 TrailingStart = dblBreakEvenPrice;
                                 TrailingStop = dblBreakEvenPrice/2;
                                 TrailingStep = (dblBreakEvenPrice/10);
                              }
                           if(dblBreakEvenPrice==0) return;
                           if(Ask> NormalizeDouble(OrderOpenPrice()+TrailingStart,Digits) && dblTrailingStopLoss < NormalizeDouble(Bid-(TrailingStop+TrailingStep),Digits))
                              {
                                 dblTrailingStopLoss = NormalizeDouble(Bid-TrailingStop,Digits);
                                 dblTakeProfit = NormalizeDouble(Ask+ TrailingStop,Digits);
                                 ObjectDelete("H_StopLoss1");
                                 ObjectCreate(ChartID(),"H_StopLoss1",OBJ_HLINE,0,0,dblTrailingStopLoss);
                                 ObjectSet("H_StopLoss1",OBJPROP_COLOR,clrGreen);
                                 bool bolTicket=false;
                                 ticket = OrderModify(OrderTicket(),OrderOpenPrice(),dblTrailingStopLoss,dblTakeProfit,0,Blue);
                                 if (bolTicket==true)
                                    {
                                       Comment("TrailingStop Activated: %G  Stop Loss %G  Bid %G", OrderSymbol(), dblTrailingStopLoss, Bid);
                                       return;
                                    }
                                 else if (bolTicket==false)
                                    {
                                       Comment("TrailingStop Not Activated: %G  Stop Loss %G  Bid %G", OrderSymbol(), dblTrailingStopLoss, Bid);
                                       return;
                                    }
                              }
                        }

               if (OrderType()==OP_SELL)
                  {
                     if(OrderProfit()>StartProfit && dblBreakEvenPrice == 0)
                        {
                           dblBreakEvenPrice = NormalizeDouble(Ask - OrderOpenPrice(),Digits);
                           TrailingStart = dblBreakEvenPrice;
                           TrailingStop = dblBreakEvenPrice/2;
                           TrailingStep = (dblBreakEvenPrice/10);
                        }
                     if(dblBreakEvenPrice==0) return;
                     if ((Bid < NormalizeDouble(OrderOpenPrice()-TrailingStart,Digits) && dblStopLoss >(NormalizeDouble(Ask+(TrailingStop+TrailingStep),Digits))) || (OrderStopLoss()==0))
                        {
                           dblTrailingStopLoss = NormalizeDouble(Ask+TrailingStop,Digits);
                           dblTakeProfit = NormalizeDouble(Bid-TrailingStop,Digits);
                           ObjectDelete("H_StopLoss1");
                           ObjectCreate(ChartID(),"H_StopLoss1",OBJ_HLINE,0,0,dblTrailingStopLoss);
                           ObjectSet("H_StopLoss1",OBJPROP_COLOR,clrGreen);
                           bool bolTicket=false;
                           ticket = OrderModify(OrderTicket(),OrderOpenPrice(),dblTrailingStopLoss,dblTakeProfit,0,Red);
                           if (bolTicket==true)
                              {
                               Comment("TrailingStop Activated: %G  Stop Loss %G  Bid %G", OrderSymbol(), dblTrailingStopLoss, Ask);
                               return;
                              }
                           else if (bolTicket==false)
                              {
                           Comment("TrailingStop Not Activated: %G  Stop Loss %G  Bid %G", OrderSymbol(), dblTrailingStopLoss, Ask);
                                 return;
                              }
                         }
                        }
                  }
       }
     }
     return;
   }
 
Sorry, but your code is too wide to read easily.
 
CrashnBurn: not working and I cannot work out why.
  1. Are your books one column but two feet wide? No because that is unreadable. They are 6 inches, sometimes two columns, so you can read it easily. So should be your code. I'm not going to go scrolling back and forth trying to read it. Edit the post with formatted code and you might get additional help.
  2. "Doesn't work" is meaningless - just like saying the car doesn't work. Doesn't start, won't go in gear, no electrical, missing the key, flat tires - meaningless. There are no mind readers here.
  3. Print out your variable values before and inside if statements and find out why.
 
//+------------------------------------------------------------------+
//|                                               ModifyStopLoss.mq4 |
//|                                                                  |
//|                                                                  |
//+------------------------------------------------------------------+
#property strict

extern double StartProfit = 1;  //Amount of profit before start

double TrailingStart, TrailingStop, TrailingStep;
double dblBreakEvenPrice, dblOpenPrice, dblAsk, dblBid, dblSpread, dblTakeProfit;
string strText;

int Slippage = 3;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
        dblAsk = Ask;
        dblBid = Bid;
        dblSpread = NormalizeDouble(dblAsk-dblBid,Digits); 
        dblBreakEvenPrice = 0;
        
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
   
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
  //Comment(StringFormat("\nProgram 1 Working, Order Total:  %G ",OrdersTotal()));
            
   if(StartProfit>0) TrailOrder (TrailingStart, TrailingStop);
  
   return;                                      // Exit OnTick()
   }
  
  
//+------------------------------------------------------------------+
void TrailOrder(double Trailingstart,double Trailingstop)
   {
   int ticket = 0, intCount, intSlippage;
   double dblPoint; 

   double dblTrailingStopLoss = NormalizeDouble(OrderStopLoss(), Digits); // Stop Loss
   double dblStopLoss = NormalizeDouble(OrderStopLoss(), Digits); // Stop Loss

   if (Digits == 3 || Digits == 5)
      {
         dblPoint = Point * 10; intSlippage = Slippage * 10;
      }
   else
       {
         dblPoint = Point; intSlippage = Slippage;
       }

   RefreshRates();
   if(OrdersTotal()>0)
      {
         for(intCount=OrdersTotal();intCount>=0;intCount--)
            {
               if(OrderSelect(intCount,SELECT_BY_POS,MODE_TRADES)==true)
                  {
                  if (OrderSymbol()!=Symbol()||OrderType()>1) return;
                     Comment(StringFormat("\nDetails of Order Detected: \nOrder Profit is %G   Swap Fee is %G\nSpread is %G
                            \nOrder Open Price is %G\nBreak Even Price is %G   Rolling Stop Loss is %G
                            \nCurrent Price is %G",NormalizeDouble(OrderProfit()+OrderSwap(),2) ,OrderSwap(),dblSpread
                             ,OrderOpenPrice(),dblBreakEvenPrice,dblTrailingStopLoss,MarketInfo(Symbol(),MODE_BID)));
                     if(OrderType() == OP_BUY)
                        {
                           if(OrderProfit()>StartProfit && dblBreakEvenPrice == 0)
                              {
                                 dblBreakEvenPrice = NormalizeDouble(Ask - OrderOpenPrice(),Digits);
                                 TrailingStart = dblBreakEvenPrice;
                                 TrailingStop = dblBreakEvenPrice/2;
                                 TrailingStep = (dblBreakEvenPrice/10);
                              }
                           if(dblBreakEvenPrice==0) return;
                           if(Ask> NormalizeDouble(OrderOpenPrice()+TrailingStart,Digits) && dblTrailingStopLoss <
                           NormalizeDouble(Bid-(TrailingStop+TrailingStep),Digits))
                              {
                                 dblTrailingStopLoss = NormalizeDouble(Bid-TrailingStop,Digits);
                                 dblTakeProfit = NormalizeDouble(Ask+ TrailingStop,Digits);
                                 ObjectDelete("H_StopLoss1");
                                 ObjectCreate(ChartID(),"H_StopLoss1",OBJ_HLINE,0,0,dblTrailingStopLoss);
                                 ObjectSet("H_StopLoss1",OBJPROP_COLOR,clrGreen);
                                 bool bolTicket=false;
                                 ticket = OrderModify(OrderTicket(),OrderOpenPrice(),dblTrailingStopLoss,dblTakeProfit,0,Blue);
                                 if (bolTicket==true)
                                    {
                                       Comment("TrailingStop Activated: %G  Stop Loss %G  Bid %G", OrderSymbol()
                                       , dblTrailingStopLoss, Bid);
                                       return;
                                    }
                                 else if (bolTicket==false)
                                    {
                                       Comment("TrailingStop Not Activated: %G  Stop Loss %G  Bid %G", OrderSymbol()
                                       , dblTrailingStopLoss, Bid);
                                       return;
                                    }
                              }
                        }

               if (OrderType()==OP_SELL)
                  {
                     if(OrderProfit()>StartProfit && dblBreakEvenPrice == 0)
                        {
                           dblBreakEvenPrice = NormalizeDouble(Ask - OrderOpenPrice(),Digits);
                           TrailingStart = dblBreakEvenPrice;
                           TrailingStop = dblBreakEvenPrice/2;
                           TrailingStep = (dblBreakEvenPrice/10);
                        }
                     if(dblBreakEvenPrice==0) return;
                     if ((Bid < NormalizeDouble(OrderOpenPrice()-TrailingStart,Digits) 
                           && dblStopLoss >(NormalizeDouble(Ask+(TrailingStop+TrailingStep),Digits))) || (OrderStopLoss()==0))
                        {
                           dblTrailingStopLoss = NormalizeDouble(Ask+TrailingStop,Digits);
                           dblTakeProfit = NormalizeDouble(Bid-TrailingStop,Digits);
                           ObjectDelete("H_StopLoss1");
                           ObjectCreate(ChartID(),"H_StopLoss1",OBJ_HLINE,0,0,dblTrailingStopLoss);
                           ObjectSet("H_StopLoss1",OBJPROP_COLOR,clrGreen);
                           bool bolTicket=false;
                           ticket = OrderModify(OrderTicket(),OrderOpenPrice(),dblTrailingStopLoss,dblTakeProfit,0,Red);
                           if (bolTicket==true)
                              {
                               Comment("TrailingStop Activated: %G  Stop Loss %G  Bid %G", OrderSymbol(), dblTrailingStopLoss, Ask);
                               return;
                              }
                           else if (bolTicket==false)
                              {
                           Comment("TrailingStop Not Activated: %G  Stop Loss %G  Bid %G", OrderSymbol(), dblTrailingStopLoss, Ask);
                                 return;
                              }
                         }
                        }
                  }
       }
     }
     return;
   }
 

OK, I could not work out how to edit my previous post so I've posted the code again and tried to split the longer statements onto multiple lines so I hope you can see it better now.  Also, sorry I did not make my explanation clear enough.

Here are the problems in more detail:

1. What should happen is that when the Currency price reaches the break even amount it stores the figure in the variable dblBreakEven (this is currently working fine).  But it is the next part that is not working.  Then when the Profit figure reaches £1 the Stop Loss is moved up to the amount stored in the variable dblBreakEven.  This would then guard against any losses but also create a £1 buffer where the Currency price can oscillate without the Stop Loss triggering.  Also, the TrailingStop variable stores the half the amount in the variable dblBreakEven and the TrailingStep variable stores one tenth of the amount in dbltBreakEven.  When the Currency price moves up the equivalent of the amount in TrailingStep then the Stop Loss moves up the amount stored in the variable TrailingStop.  As the Currency price rises the Stop Loss follows it up.

2.  To help debug the program I have Comment statements containing the variables I want to monitor (including the ones mentioned above).  The Comments work fine when I only have the EA running on one chart.  But I had it running on three charts and the Comment on chart 1 was displaying the variable details from chart 2.  So how do I make sure the Comment statement displays the information for the correct chart.

Hopefully that is better but if you still have questions please ask.

Regards, CrashnBurn

P.S. WHRoeder - Programming is not like reading a book any more than creating a spreadsheet is.  Programs don't "flow" like a book because reading a book you work from left to right, top to bottom.  But programs are not created like that, they do not run that way (they work more like a stream including eddies that go round or even in the opposite direction to the general flow) and they are not debugged that way.  Finally, do you not find them more difficult to read when they are split between lines?

 

I only got as far as this

void TrailOrder(double Trailingstart,double Trailingstop)
   {
   int ticket = 0, intCount, intSlippage;
   double dblPoint; 

   double dblTrailingStopLoss = NormalizeDouble(OrderStopLoss(), Digits); // Stop Loss
   double dblStopLoss = NormalizeDouble(OrderStopLoss(), Digits); // Stop Loss

 Where is the OrderSelect for OrderStopLoss?

 
CrashnBurn:


P.S. WHRoeder - Programming is not like reading a book any more than creating a spreadsheet is.  Programs don't "flow" like a book because reading a book you work from left to right, top to bottom.  But programs are not created like that, they do not run that way (they work more like a stream including eddies that go round or even in the opposite direction to the general flow) and they are not debugged that way.  Finally, do you not find them more difficult to read when they are split between lines?

Yes, but when other people are trying to read your code, it is exactly like reading a book.

When reading code we want to read to the end of the line and then cast our eyes to the next line.

If the code is 3 times the width of the screen, we can't do that and have to keep scrolling back and forth 

 
 Programs don't "flow" like a book because reading a book you work from left to right, top to bottom.
But the basic way of coding is like that.
 
GumRai:

I only got as far as this

 Where is the OrderSelect for OrderStopLoss?

 

Hi GumRai,

 You are right - its in completely the wrong place.  Also, I may have sorted out the problem as it did not like the line that says "if (OrderSymbol()!=Symbol()||OrderType()>1) return;"  Not sure why but the OrderSymbol() variable was returning a different symbol to the Symbol() variable.  This was why it did not work with two or more open orders.  So I changed the conditions so it carries on when they do match (rather than exiting when they don't match) and it worked.  But thanks for pointing out the other error.

 Regards, CrashnBurn 

 

All the problems in this part

 if(OrdersTotal()>0)

And if To change

 For example :

if(OrdersTotal()==2) 

The problem will be solved

2 is the best 

 
s19780108: 2 is the best 
Not if you place the EA on any other chart, or there are other EAs or manual trading.
Reason: