Trailing Feature Creating Crazy Big TP and SL

 

Can someone please help me with my crap code? I have this trailing feature that seems to backtest fine, but when I put it on accounts it will create some crazy TP and SL 1000+ pips big when it should only be 10 pips.


void TrailingAlls(int trail)
{
   if (trail==0)
    return;
    
                int b;
   b=OrdersTotal();
   double stopcrnt;
   double stopcal;
   double tpcal;
   int trade;
   int trades=OrdersTotal();
  
   
   for(trade=0;trade<trades;trade++)
   {
      bool sel=OrderSelect(trade,SELECT_BY_POS,MODE_TRADES);
                
                 if(OrderSymbol()==Symbol() && OrderMagicNumber()==MagicNumber)
                 {
       //continue;
      
      pp = MarketInfo(OrderSymbol(), MODE_POINT); 
      
      
 //Long
      
      if(OrderType()==OP_BUY)
      {
         
         pBid = MarketInfo(OrderSymbol(), MODE_BID);
         double buystep = OrderTakeProfit()-TrailingStep*Pips();
         
         if(buystep <= Bid){     
         stopcrnt=OrderStopLoss();
         
         if(stopcrnt==0)
         {stopcal=Bid-trail*Pips();}
         
         else if(Bid-OrderStopLoss() >= RealStopLoss*Pips())
         {stopcal=Bid-trail*Pips();}
         
         else
         {stopcal=OrderStopLoss()+trail*Pips();}
         
         tpcal=OrderTakeProfit()+TrailTP*Pips();
         
NormalizeDouble(tpcal,Digits);
NormalizeDouble(stopcal,Digits);
NormalizeDouble(buystep,Digits);
     
     for(i=0;i<b;i++)
     {
      bool c;
      ERROR=0;
      c=OrderSelect(i,SELECT_BY_POS,MODE_TRADES);
      double h = OrderTakeProfit()-Bid;
      if(h < TrailTP*Pips()){
         for (c1 = 0; c1 < NumberOfTries; c1++) {
         sel=OrderModify(OrderTicket(),OrderOpenPrice(),stopcal,tpcal,0,Blue);
         ERROR = GetLastError();
         if (ERROR == 0 || ERROR == 1/* NO_ERROR */) break;
         if (!(ERROR == 4/* SERVER_BUSY */ || ERROR == 137/* BROKER_BUSY */ || ERROR == 146/* TRADE_CONTEXT_BUSY */ || ERROR == 136/* OFF_QUOTES */ || ERROR == 130/* INVALID_STOP */)) break;
         Sleep(1000);
      }
     }}
      
         return;
   }
}//Long 
     
//Shrt
      if(OrderType()==OP_SELL)      
      {
         
         
    pAsk = MarketInfo(OrderSymbol(), MODE_ASK);
      double sellstep = OrderTakeProfit()+TrailingStep*Pips();
         if(sellstep <= Ask){
         stopcrnt=OrderStopLoss();
         
         if(stopcrnt==0)
         {stopcal=Ask+trail*Pips();}
         
         else if(OrderStopLoss()-Ask >= RealStopLoss*Pips())
         {stopcal=Ask+trail*Pips();}
         
         else
         {stopcal=OrderStopLoss()-trail*Pips();}
         
         tpcal=OrderTakeProfit()-TrailTP*Pips();
         
NormalizeDouble(tpcal,Digits);
NormalizeDouble(stopcal,Digits);
NormalizeDouble(sellstep,Digits);
            
     for(i=0;i<b;i++)
     {
      bool c;
      c=OrderSelect(i,SELECT_BY_POS,MODE_TRADES);
      bool mod;
      double k = Ask-OrderTakeProfit();
      if(k < TrailTP*Pips()){
            

         for (c1 = 0; c1 < NumberOfTries; c1++) {
         mod=OrderModify(OrderTicket(),OrderOpenPrice(),stopcal,tpcal,0,Red);
         ERROR = GetLastError();
         if (ERROR == 0 || ERROR == 1/* NO_ERROR */) break;
         if (!(ERROR == 4/* SERVER_BUSY */ || ERROR == 137/* BROKER_BUSY */ || ERROR == 146/* TRADE_CONTEXT_BUSY */ || ERROR == 136/* OFF_QUOTES */ || ERROR == 130/* INVALID_STOP */)) break;
         Sleep(1000);
      }}
            }   
      
      }
        return;
   //}
}//Shrt
                 }//if
   }//for
   
}


double Pips()
  {
   double pips;
   pips=Point;
   int digit;
   digit=Digits();
   int DR;
   DR=digit%2;
   if(DR==1)
     {
      pips*=10;
     }
   return(pips);
  }
 
bump
 

Hey,

I suppose the problem lies in using NormalizeDouble() and not if you are backtesting or not. My guess is that you are seeing problems in pairs which are less than 1.0000. So if your pair is like 0.95959, NormalizeDouble will likely turn it to 9.5959e-1, but Order functions will not catch that e-1. Also, as a general rule, almost everybody here will tell you not to use NormalizeDouble, "ever". 

 Of course, I could be wrong

best regards 

edit:

on a second approach, some more things. First, all the weird stuff you are experiencing may have to do with financial instruments not only with the format 0.XXXXX but also with those which are having more than one digits in the integer part (e.g. SP500) - as NormalizeDouble will affect those too. Right? The reason all that is happening because, as I am suspecting, MetaQuotes filters the outgoing order messages (probably to save off some bandwidth), by cutting off the exponent part in the binary representation of the Double number; that, would save them 11 bits out of the 64, which is a good 20% reduction in size. I am saying so as to explain why you are not experiencing any problems in backtests, as backtests are local to our computers and as such, there is not any important need to cut off the number of bits. And lastly, not only that, but another thought that comes to my mind is also that all that stuff would explain why the manual insists on using NormalizeDouble in Order functions or not to use any calculated price; it looks like that if we are going to use our (calculated) numbers, they should be at the format X.XXXXX, e.g. for SP500 we should send 2.16666 instead of 2,166.66. Of course there should be no need for those steps in normal X.XXXXX pairs (at least, as long as they are staying as such - maybe for example EURUSD will go to less than 1, and it would be a good idea for your code to be ready to handle that situation). Again, I could be wrong, as I have not tested any of all the arguments I am making

 
  1. bool sel=OrderSelect(trade,SELECT_BY_POS,MODE_TRADES);
    
    c=OrderSelect(i,SELECT_BY_POS,MODE_TRADES);
    
    mod=OrderModify(OrderTicket(),OrderOpenPrice(),stopcal,tpcal,0,Red);
        ERROR = GetLastError();
    
    Check your return codes. What are Function return values ? How do I use them ? - MQL4 forum and Common Errors in MQL4 Programs and How to Avoid Them - MQL4 Articles
  2. for(trade=0;trade<trades;trade++){
    
    for(i=0;i<b;i++){
    
    In the presence of multiple orders (one EA multiple charts, multiple EA's, manual trading) you must count down when closing/deleting/modifying in a position loop. Get in the habit of always counting down. Loops and Closing or Deleting Orders - MQL4 forum
  3. You have a OrderSelect loop inside a OrderSelect loop. Both unreadable and bad practice. One is sufficient.

  4. NormalizeDouble(tpcal,Digits);
    NormalizeDouble(stopcal,Digits);
    NormalizeDouble(sellstep,Digits);
    
    These three lines do absolutely nothing. Delete them.

  5. pp = MarketInfo(OrderSymbol(), MODE_POINT); 
    
    pBid = MarketInfo(OrderSymbol(), MODE_BID);
    You know the OrderSymbol is _Symbol because you check, just use _Point and Bid.
  6. Do NOT use NormalizeDouble, EVER. For ANY Reason. It's a kludge, don't use it. It's use is always wrong
  7. n a second approach, some more things. First, all the weird stuff you are experiencing may have to do with financial instruments not only with the format 0.XXXXX but also with those which are having more than one digits in the integer part (e.g. SP500) - as NormalizeDouble will affect those too. Right? The reason all that is happening because, as I am suspecting, MetaQuotes filters the outgoing order messages (probably to save off some bandwidth), by cutting off the exponent part in the binary representation of the Double number; that, would save them 11 bits out of the 64, which is a good 20% reduction in size. I am saying so as to explain why you are not experiencing any problems in backtests, as backtests are local to our computers and as such, there is not any important need to cut off the number of bits. And lastly, not only that, but another thought that comes to my mind is also that all that stuff would explain why the manual insists on using NormalizeDouble in Order functions or not to use any calculated price; it looks like that if we are going to use our (calculated) numbers, they should be at the format X.XXXXX, e.g. for SP500 we should send 2.16666 instead of 2,166.66. Of course there should be no need for those steps in normal X.XXXXX pairs (at least, as long as they are staying as such - maybe for example EURUSD will go to less than 1, and it would be a good idea for your code to be ready to handle that situation). Again, I could be wrong, as I have not tested any of all the arguments I am making
    Learn to Write English. One thought per sentence. Related thoughts per paragraph. I'm not going to even try to understand your run on sentence.
 
WHRoeder:
  1. n a second approach, some more things. First, all the weird stuff youare experiencing may have to do with financial instruments not only withthe format 0.XXXXX but also with those which are having more than onedigits in the integer part (e.g. SP500) - as NormalizeDouble willaffect those too. Right? The reason all that is happening because, as Iam suspecting, MetaQuotes filters the outgoing order messages (probablyto save off some bandwidth), by cutting off the exponent part in thebinary representation of the Double number; that, would save them 11bits out of the 64, which is a good 20% reduction in size. I am sayingso as to explain why you are not experiencing any problems in backtests,as backtests are local to our computers and as such, there is not anyimportant need to cut off the number of bits. And lastly, not only that,but another thought that comes to my mind is also that all that stuffwould explain why the manual insists on using NormalizeDouble inOrder functions or not to use any calculated price; it looks like thatif we are going to use our (calculated) numbers, they should be at theformat X.XXXXX, e.g. for SP500 we should send 2.16666 instead of2,166.66. Of course there should be no need for those steps in normalX.XXXXX pairs (at least, as long as they are staying as such - maybe forexample EURUSD will go to less than 1, and it would be a good idea foryour code to be ready to handle that situation). Again, I could bewrong, as I have not tested any of all the arguments I am making
    Learn to Write English. One thought per sentence. Related thoughts per paragraph. I'm not going to even try to understand your run on sentence.

hehe, you are right; it was late and I also have an inclination to rants :) Soo, to put it simply, I tried to understand why the problems OP has, appear only in a live/demo situation and not when backtesting. My guess is that the problem lies within NormalizeDouble, and that it can affect pairs, either with 0 (zero) at the begining, like 0.95959, or with more digits at the integer part, like 111.55. I am supposing so, because what Normalize is supposed to do (not in MQL only, but in general) is to cut all leading or last zeroes of a number and then create a number with only one digit in the integer part. So, back to MQL, if, for example, 0.95959 becomes 9.5959 (because of normalization) it could be the reason why OP experiences trailing stops of 1000s of pips instead of 10s.

best regards 

 

hello,

sorry for digging up on an old thread, but somehow I came across that article https://www.mql5.com/en/articles/1561 and I started thinking again about NormalizeDouble(). I have to say that I do not like much the way MetaQuotes handles the meaning of Normalization, since the way it executes it, it is more of a truncation processing rather than a variation of all the Normalization variations someone could find on the internet :)

So, back to to the original problem, the problem may be lying to the fact that, at some point you are writing (if you are reading this topic after so much time has passed ) )

NormalizeDouble(tpcal,Digits);
NormalizeDouble(stopcal,Digits);
NormalizeDouble(buystep,Digits);

 and then later, you are writing

         sel=OrderModify(OrderTicket(),OrderOpenPrice(),stopcal,tpcal,0,Blue);

 In other words, you NormalizeDouble(tpcal,Digits) and then you are going on and use tpcal in OrderModify(). But here is the problem (and this is what I realized about NormalizeDouble after reading the article I posted before): NormalizeDouble returns a double, it does not modify e.g. tpcal. So you pass tpcal unchanged to OrderModify, which may be the source of your problems 

 I hope that helps ,

 

best regards 

 
NormalizeDouble(tpcal,Digits);
NormalizeDouble(stopcal,Digits);
NormalizeDouble(buystep,Digits);

As I pointed out in #6, if you are trading a symbol where tick size != point those are wrong.

And if you use strict, the compile would warn about return values.

 

ok, one can understand that Metals are binary compatible (multilples of 0.25), whereas currencies are not. But then again, is it fair for bitcoin? :)

Reason: