What’s the Best Way to Decide TP/SL Levels Across Different Timeframes?

shanmugapradeep

Active Trader
Dec 18, 2020
162
13
34
40
Hello,

For example, let’s take the RSI indicator and EURUSD. Suppose you buy at oversold and sell at overbought, and you are trading across all timeframes. How do you decide what Take Profit and Stop Loss levels to set?

On the 1-minute timeframe, the average gap in points/pips between overbought and oversold is around ~80 points, but on the 5-minute timeframe the average gap is about 300 points. The bigger the timeframe, the bigger the gap between overbought and oversold.

So, how do you decide the Take Profit and Stop Loss levels based on the indicator and timeframe? What should the TP and SL values be?

I am asking this because I created a simple EA to test different indicators like RSI, Bollinger Bands, Moving Averages, etc. It checks all timeframes and trades whenever there is a signal. The problem is the EA uses fixed Take Profit and Stop Loss values for all timeframes. For example, if I set 100 points for TP and 100 points for SL, it works well for a 1-minute oversold/overbought signal, but it is too small for signals on higher timeframes. How can I decide these values so they can be automated?
 
A good idea is to use ATR-based SL/TP in such cases. If there is no possibility to add that to your EAs, it makes sense to check the ATR values for all the timeframes you are going to test on and calculate the appropriate SL/TP values to set during those backtests.
 
A good idea is to use ATR-based SL/TP in such cases
Like this

MQL4:
extern int ATR_Period = 14;
extern int RiskToReward_TP = 2;
extern int RiskToReward_SL = 1;
enum ATRMode_enum {AverageATR, FirstATR, LastATR};
extern ATRMode_enum ATRMode = AverageATR;
 
//+------------------------------------------------------------------+
//| Extract ATR based on first/last TF from comment                  |
//+------------------------------------------------------------------+
int GetATRFromComment(string comment, string symbol)
  {
   double fPoint = MarketInfo(symbol, MODE_POINT);
//--- detect first TF (scan from left)
   string firstTF = "";
   if(StringFind(comment, "1M")  != -1)
      firstTF = "1M";
   else
      if(StringFind(comment, "5M")  != -1)
         firstTF = "5M";
      else
         if(StringFind(comment, "15-M") != -1)
            firstTF = "15-M";
         else
            if(StringFind(comment, "30M") != -1)
               firstTF = "30M";
            else
               if(StringFind(comment, "1H")  != -1)
                  firstTF = "1H";
               else
                  if(StringFind(comment, "4H")  != -1)
                     firstTF = "4H";
                  else
                     if(StringFind(comment, "1D")  != -1)
                        firstTF = "1D";
 
//--- detect last TF (scan from right side)
   string lastTF = "";
   if(StringFind(comment, "1D") != -1)
      lastTF = "1D";
   else
      if(StringFind(comment, "4H") != -1)
         lastTF = "4H";
      else
         if(StringFind(comment, "1H") != -1)
            lastTF = "1H";
         else
            if(StringFind(comment, "30M") != -1)
               lastTF = "30M";
            else
               if(StringFind(comment, "15-M") != -1)
                  lastTF = "15-M";
               else
                  if(StringFind(comment, "5M")  != -1)
                     lastTF = "5M";
                  else
                     if(StringFind(comment, "1M")  != -1)
                        lastTF = "1M";
 
//--- convert TF strings to ENUM
   ENUM_TIMEFRAMES tfFirst = PERIOD_CURRENT;
   ENUM_TIMEFRAMES tfLast  = PERIOD_CURRENT;
 
   if(firstTF == "1M")
      tfFirst = PERIOD_M1;
   if(firstTF == "5M")
      tfFirst = PERIOD_M5;
   if(firstTF == "15-M")
      tfFirst = PERIOD_M15;
   if(firstTF == "30M")
      tfFirst = PERIOD_M30;
   if(firstTF == "1H")
      tfFirst = PERIOD_H1;
   if(firstTF == "4H")
      tfFirst = PERIOD_H4;
   if(firstTF == "1D")
      tfFirst = PERIOD_D1;
 
   if(lastTF == "1M")
      tfLast = PERIOD_M1;
   if(lastTF == "5M")
      tfLast = PERIOD_M5;
   if(lastTF == "15-M")
      tfLast = PERIOD_M15;
   if(lastTF == "30M")
      tfLast = PERIOD_M30;
   if(lastTF == "1H")
      tfLast = PERIOD_H1;
   if(lastTF == "4H")
      tfLast = PERIOD_H4;
   if(lastTF == "1D")
      tfLast = PERIOD_D1;
 
//--- ATR values
   double atrFirst = iATR(symbol, tfFirst, ATR_Period, 0);
   double atrLast  = iATR(symbol, tfLast, ATR_Period, 0);
 
//--- if only one TF found, both first and last will be same
   if(tfFirst == tfLast)
      return (int)MathRound(atrFirst / fPoint);
 
//--- choose based on mode
   if(ATRMode == AverageATR)
      return (int)MathRound(((atrFirst + atrLast) / 2.0) / fPoint);
   if(ATRMode == FirstATR)
      return (int)MathRound(atrFirst / fPoint);
   if(ATRMode == LastATR)
      return (int)MathRound(atrLast / fPoint);
 
   return 0; // default
  }
 
  int fATRValue = GetATRFromComment("1M", "EURUSD");
  TakeProfit = fATRValue * RiskToReward_TP;
  StopLoss = fATRValue * RiskToReward_SL;
 
Like this

MQL4:
extern int ATR_Period = 14;
extern int RiskToReward_TP = 2;
extern int RiskToReward_SL = 1;
enum ATRMode_enum {AverageATR, FirstATR, LastATR};
extern ATRMode_enum ATRMode = AverageATR;
 
//+------------------------------------------------------------------+
//| Extract ATR based on first/last TF from comment                  |
//+------------------------------------------------------------------+
int GetATRFromComment(string comment, string symbol)
  {
   double fPoint = MarketInfo(symbol, MODE_POINT);
//--- detect first TF (scan from left)
   string firstTF = "";
   if(StringFind(comment, "1M")  != -1)
      firstTF = "1M";
   else
      if(StringFind(comment, "5M")  != -1)
         firstTF = "5M";
      else
         if(StringFind(comment, "15-M") != -1)
            firstTF = "15-M";
         else
            if(StringFind(comment, "30M") != -1)
               firstTF = "30M";
            else
               if(StringFind(comment, "1H")  != -1)
                  firstTF = "1H";
               else
                  if(StringFind(comment, "4H")  != -1)
                     firstTF = "4H";
                  else
                     if(StringFind(comment, "1D")  != -1)
                        firstTF = "1D";
 
//--- detect last TF (scan from right side)
   string lastTF = "";
   if(StringFind(comment, "1D") != -1)
      lastTF = "1D";
   else
      if(StringFind(comment, "4H") != -1)
         lastTF = "4H";
      else
         if(StringFind(comment, "1H") != -1)
            lastTF = "1H";
         else
            if(StringFind(comment, "30M") != -1)
               lastTF = "30M";
            else
               if(StringFind(comment, "15-M") != -1)
                  lastTF = "15-M";
               else
                  if(StringFind(comment, "5M")  != -1)
                     lastTF = "5M";
                  else
                     if(StringFind(comment, "1M")  != -1)
                        lastTF = "1M";
 
//--- convert TF strings to ENUM
   ENUM_TIMEFRAMES tfFirst = PERIOD_CURRENT;
   ENUM_TIMEFRAMES tfLast  = PERIOD_CURRENT;
 
   if(firstTF == "1M")
      tfFirst = PERIOD_M1;
   if(firstTF == "5M")
      tfFirst = PERIOD_M5;
   if(firstTF == "15-M")
      tfFirst = PERIOD_M15;
   if(firstTF == "30M")
      tfFirst = PERIOD_M30;
   if(firstTF == "1H")
      tfFirst = PERIOD_H1;
   if(firstTF == "4H")
      tfFirst = PERIOD_H4;
   if(firstTF == "1D")
      tfFirst = PERIOD_D1;
 
   if(lastTF == "1M")
      tfLast = PERIOD_M1;
   if(lastTF == "5M")
      tfLast = PERIOD_M5;
   if(lastTF == "15-M")
      tfLast = PERIOD_M15;
   if(lastTF == "30M")
      tfLast = PERIOD_M30;
   if(lastTF == "1H")
      tfLast = PERIOD_H1;
   if(lastTF == "4H")
      tfLast = PERIOD_H4;
   if(lastTF == "1D")
      tfLast = PERIOD_D1;
 
//--- ATR values
   double atrFirst = iATR(symbol, tfFirst, ATR_Period, 0);
   double atrLast  = iATR(symbol, tfLast, ATR_Period, 0);
 
//--- if only one TF found, both first and last will be same
   if(tfFirst == tfLast)
      return (int)MathRound(atrFirst / fPoint);
 
//--- choose based on mode
   if(ATRMode == AverageATR)
      return (int)MathRound(((atrFirst + atrLast) / 2.0) / fPoint);
   if(ATRMode == FirstATR)
      return (int)MathRound(atrFirst / fPoint);
   if(ATRMode == LastATR)
      return (int)MathRound(atrLast / fPoint);
 
   return 0; // default
  }
 
  int fATRValue = GetATRFromComment("1M", "EURUSD");
  TakeProfit = fATRValue * RiskToReward_TP;
  StopLoss = fATRValue * RiskToReward_SL;
No, why does it do all that? It should get the ATR value for the timeframe you are trading on and calculate a SL or TP based on that value.
 
This doing same thing. get ATR value of timeframe for what i am trading. i am passing time timeframe in the function as string.


Doing same with Risktoreward

Can you tell me where i am wrong with this code?
The code that you inserted above will do one of three things depending on the ATRMode input parameter:
  1. Calculate the average of the two ATRs - one for the lowest timeframe and one for the highest timeframe. So, if you set it to work with M1 through D1, it will calculate the average of the M1 and D1 ATRs, which would be a meaningless number for almost any timeframe.
  2. Calculate the ATR for the first TF only. So, it cannot be used with the remaining timeframes.
  3. Calculate the ATR for the last TF only. Idem.