RSI Exponential Smoothing (Expo) for ThinkOrSwim

samer800

Moderator - Expert
VIP
Lifetime
uFQvWLA.png

Author Message:
Background information
The Relative Strength Index (RSI) and the Exponential Moving Average (EMA) are two popular indicators. Traders use these indicators to understand market trends and predict future price changes. However, traders often wonder which indicator is better: RSI or EMA.

  • What if these indicators give similar results? To find out, we wanted to study the relationship between RSI and EMA. We focused on a hypothesis: when the RSI goes above 50, it might be similar to the price crossing above a certain length of EMA. Similarly, when the RSI goes below 50, it might be similar to the price crossing below a certain length of EMA.

  • Our goal was simple: to figure out if there is any connection between RSI and EMA.

  • Conclusion: Yes, it seems that there is a correlation between RSI and EMA, and this indicator clearly displays that relationship.
Overview of the indicator
The RSI Exponential Smoothing indicator
displays RSI levels with clear overbought and oversold zones, shown as easy-to-understand moving averages, and the RSI 50 line as an EMA. Another excellent feature is the added FIB levels. To activate, open the settings and click on "FIB Bands." These levels act as short-term support and resistance levels which can be used for scalping.

Benefits of using this indicator instead of regular RSI
The findings about the Relative Strength Index (RSI) and the Exponential Moving Average (EMA) highlight that both indicators are equally accurate (when it comes to crossings), meaning traders can choose either one without compromising accuracy. This empowers traders to pick the indicator that suits their personal preferences and trading style.

CODE:
CSS:
#// https://www.tradingview.com/v/OhFeqKQX/
#This work is licensed under a Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0)
#// © Zeiierman
#indicator("RSI Exponential Smoothing (Expo)", overlay=true)
# Converted by Sam4Cok@Samer800        - 05/2023
#// ~~ Inputs {
input showLabel   = yes;           # "Show Table"
input ShowCloud   = yes;           # "Show highlight"
input rsiPeriod   = 14;            # "RSI Period"
input Overbought  = 70;            # "Overbought"
input Oversold    = 30;            # "Oversold"
input obosBands   = yes;           # "OBOS Band"
input fibBands    = no;            # "FIB Band"
input ShowBubbles = no;            # "RSI Bubbles"
input validity_check = no;         # "Show Validity check"

def na = Double.NaN;
def last = isNaN(close[-1]);

#// ~~ Exponential Smoothing Coefficient Calculation {   
#emaresult(level)=>
script emaresult {
    input level = 50;
    input rsiperiod = 14;
    def exponential_period    = 2 * rsiperiod - 1;
    def smoothing_coefficient = 2 / (exponential_period + 1);
    def averageUp   = if close > close[1] then
                smoothing_coefficient * (close - close[1]) + (1 - smoothing_coefficient) * (If(averageUp[1], averageUp[1], 1)) else
                                                           (1 - smoothing_coefficient) * (If(averageUp[1], averageUp[1], 1));
    def averageDown = if close > close[1] then
               (1 - smoothing_coefficient) * (If(averageDown[1], averageDown[1], 1)) else
                smoothing_coefficient * (close[1] - close) + (1 - smoothing_coefficient) * (If(averageDown[1], averageDown[1], 1));
    def netValue = (rsiperiod - 1) * (averageDown * level / (100 - level) - averageUp);
    def result   = if netValue >= 0 then close + netValue else close + netValue * (100 - level) / level;
    plot out = result;
}
#// ~~ Calculate RSI Standard Deviation, in order to calculate the Deviation { 
#StandardDeviation(src, period)=>
Script StandardDeviation {
input src = close;
input period = 14;
    def mean              = Average(src, period);
    def squared_diff      = ((src - mean) * (src - mean));
    def sum_squared_diff  = sum(squared_diff, period);
    def std_dev           = sqrt(sum_squared_diff/period);
    plot out              = std_dev;
}
#dev(obos)=>
script dev {
input obos = 50;
input ema_result = close;
input std_dev = close;
    def deviating = (obos-ema_result)/std_dev;
    plot out = deviating;
}
#// ~~ Hull Moving Average Calculation, in order to smooth the Upper OB and Lower OS lines  { 
#hma(src,len)=>
Script hma {
input src = close;
input len = 14;
    def halfLen = Round(len/2, 0);
    def wma1 = wma(2 * wma(src, halfLen) - wma(src, len), round(sqrt(0.5),0));
    def wma2 = wma(2 * wma(wma1, halfLen) - wma(wma1, len), round(sqrt(0.5),0));
    plot out = wma2;
}
#// ~~ Calculate fib 50% from OB to 50 level and OS to 50 level {
#fib(src)=>
Script fib {
input src = close;
input ema_result = close;
    def fib = ema_result + (src-ema_result)*0.5;
    plot out = fib;
}

#/ ~~ Return EMA { 
def ema_result = emaresult(50, rsiperiod);
#// Plot the Optimal EMA based on the RSI value
plot OptimalEMA = ema_result;    # "Optimal EMA"
OptimalEMA.SetDefaultColor(CreateColor(33,150,243));
#// ~~ Return RSI Standard Deviation  { 
def rsi     = rsi(Price=close,Length=rsiperiod);
def std_dev = StandardDeviation(rsi, rsiperiod);

def ob_dev = dev(emaresult(Overbought, rsiperiod),ema_result, std_dev);
def os_dev = dev(emaresult(Oversold, rsiperiod),ema_result, std_dev);
def upper  = hma(WildersAverage(ema_result + (ob_dev*std_dev),3),10);# // Returns the upper OB line on the chart.
def lower  = hma(WildersAverage(ema_result + (os_dev*std_dev),3),10);# // Returns the upper OS line on the chart.

#/ ~~ Plot Upper OB and Lower OS lines on the chart {
plot UpperOB = if obosbands then upper else na;#, "Upper OB"
plot LowerOS = if obosbands then lower else na;#, "Lower OS"
plot UpperDev = if obosbands then upper - stdev(upper,2) else na;#, "Upper OB"
plot LowerDev = if obosbands then lower + stdev(lower,2) else na;#, "Lower OS"

UpperOB.SetDefaultColor(Color.GREEN);
LowerOS.SetDefaultColor(Color.RED);
UpperDev.SetDefaultColor(Color.GREEN);
LowerDev.SetDefaultColor(Color.RED);
#// ~~ Plot the Fib lines on the chart {
def fibUp = fib(upper, ema_result);
def fibDn = fib(lower, ema_result);
plot UpperFib = if fibbands then fibUp else na;        # "Upper Fib 50%"
plot LowerFib = if fibbands then fibDn else na;        # "Lower Fib 50%"
UpperFib.SetDefaultColor(Color.DARK_GREEN);
LowerFib.SetDefaultColor(Color.DARK_RED);

#-- Cloud
AddCloud(if ShowCloud then upper else na, fibUp, Color.DARK_GREEN);
AddCloud(if ShowCloud then fibDn else na, lower, Color.DARK_RED);

#// ~~ Validity Checks {
#// ~~ Store crossover values to check Validity {
#// ~~ Optimal EMA Length {
def emavalue  =  Round(2*rsiperiod-1, 0);
def ema       =  ExpAverage(close,emavalue);

def occurrence;#     = 0
def non_occurrence;# = 0

if ((rsi Crosses Above 50) and (close Crosses Above ema)) or ((rsi Crosses below 50) and (close Crosses below ema)) {
    occurrence = occurrence[1] + 1;
    non_occurrence = non_occurrence[1];
    } else
if ((rsi Crosses Above 50) and !(close Crosses Above ema)) or ((rsi Crosses below 50) and !(close Crosses below ema)) {
    occurrence = occurrence[1];
    non_occurrence = non_occurrence[1] + 1;
    } else {
    occurrence = occurrence[1];
    non_occurrence = non_occurrence[1];
}
#// ~~ Precentage Check {
def percent = ((AbsValue(occurrence)/(occurrence + non_occurrence) * 100));
#// ~~ Trend Direction {
def dir   = rsi>50;
#// ~~ Overbought & Oversold {
def ob_  = rsi>Overbought;
def os_  = rsi<Oversold;

#// ~~ Labels
AddLabel(showLabel, "RSI Value: " + rsiperiod, CreateColor(33,150,243));
AddLabel(showLabel, "EMA Value: " + emavalue, CreateColor(33,150,243));
AddLabel(showLabel , "RSI" + if dir then " > 50 " else " < 50", CreateColor(33,150,243));
AddLabel(showLabel , "Trend: " + if dir then "Bullish" else "Bearish", if dir then Color.GREEN else Color.RED);
AddLabel(showLabel and (ob_ or os_), if ob_ then " > " + Overbought + "(Overbought)" else " < " + Oversold + " Oversold",
                                     if ob_ then Color.LIGHT_GREEN else Color.PINK);

AddLabel(showLabel and validity_check, "Validity Check: " + Round(percent,2) + "%", Color.WHITE);
AddLabel(showLabel and validity_check, "RSI Stdev: " + Round(std_dev,2) + "%", Color.WHITE);

AddChartBubble(ShowBubbles and last, ema_result, "RSI 50", CreateColor(33,150,243), yes);
AddChartBubble(ShowBubbles and last, upper, "RSI " + Overbought, Color.GREEN, yes);
AddChartBubble(ShowBubbles and last, lower, "RSI " + Oversold ,Color.RED, no);
AddChartBubble(ShowBubbles and fibbands and last, UpperFib, "FIB 50%", Color.DARK_GREEN, yes);
AddChartBubble(ShowBubbles and fibbands and last, LowerFib, "FIB 50%", Color.DARK_RED, no);


#--- END of CODE
 
This is one of my favorite indicators. I had to make a few tweaks to my liking. I added a couple of averages with a colored cloud. When the cloud changes to cyan or magenta, price has a good chance of breaking through, like in the example below. Arrows take into account a reversal in MACD Histogram. (Arrows are only reliable when the red/green average line is relatively flat, a non-trending market). I typically like to take the reversal trade when price is outside the wide red or green bands.

1692106753501.png


Code:
#// https://www.tradingview.com/v/OhFeqKQX/
#This work is licensed under a Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0)
#// © Zeiierman
#indicator("RSI Exponential Smoothing (Expo)", overlay=true)
# Converted by Sam4Cok@Samer800        - 05/2023
#// ~~ Inputs {

input obosBands   = no;           # "OBOS Band"
input ShowCloud   = yes;           # "Show highlight"
input rsiPeriod   = 12;            # "RSI Period"
input Overbought  = 70;            # "Overbought"
input Oversold    = 30;            # "Oversold"
input Overbought1  = 65;            # "Overbought"
input Oversold1    = 40;            # "Oversold"
input Overbought2  = 80;            # "Overbought"
input Oversold2    = 20;            # "Oversold"


def na = Double.NaN;
def last = IsNaN(close[-1]);

#// ~~ Exponential Smoothing Coefficient Calculation {  
#emaresult(level)=>
script emaresult {
    input level = 50;
    input rsiperiod = 12;
    def exponential_period    = 2 * rsiperiod - 1;
    def smoothing_coefficient = 2 / (exponential_period + 1);
    def averageUp   = if close > close[1] then
                smoothing_coefficient * (close - close[1]) + (1 - smoothing_coefficient) * (If(averageUp[1], averageUp[1], 1)) else
                                                           (1 - smoothing_coefficient) * (If(averageUp[1], averageUp[1], 1));
    def averageDown = if close > close[1] then
               (1 - smoothing_coefficient) * (If(averageDown[1], averageDown[1], 1)) else
                smoothing_coefficient * (close[1] - close) + (1 - smoothing_coefficient) * (If(averageDown[1], averageDown[1], 1));
    def netValue = (rsiperiod - 1) * (averageDown * level / (100 - level) - averageUp);
    def result   = if netValue >= 0 then close + netValue else close + netValue * (100 - level) / level;
    plot out = result;
}
#// ~~ Calculate RSI Standard Deviation, in order to calculate the Deviation {
#StandardDeviation(src, period)=>
script StandardDeviation {
    input src = close;
    input period = 12;
    def mean              = Average(src, period);
    def squared_diff      = ((src - mean) * (src - mean));
    def sum_squared_diff  = Sum(squared_diff, period);
    def std_dev           = Sqrt(sum_squared_diff / period);
    plot out              = std_dev;
}
#dev(obos)=>
script dev {
    input obos = 50;
    input ema_result = close;
    input std_dev = close;
    def deviating = (obos - ema_result) / std_dev;
    plot out = deviating;
}
#// ~~ Hull Moving Average Calculation, in order to smooth the Upper OB and Lower OS lines  {
#hma(src,len)=>
script hma {
    input src = close;
    input len = 12;
    def halfLen = Round(len / 2, 0);
    def wma1 = WMA(2 * WMA(src, halfLen) - WMA(src, len), Round(Sqrt(0.5), 0));
    def wma2 = WMA(2 * WMA(wma1, halfLen) - WMA(wma1, len), Round(Sqrt(0.5), 0));
    plot out = wma2;
}


#/ ~~ Return EMA {
def ema_result = emaresult(50, rsiperiod);
#// Plot the Optimal EMA based on the RSI value
plot OptimalEMA = ema_result;    # "Optimal EMA"
#OptimalEMA.SetDefaultColor(color.yellow);
OptimalEMA.DefineColor("BreakUp", Color.Cyan);
OptimalEMA.DefineColor("BreakDown", Color.magenta);
OptimalEMA.DefineColor("Normal", Color.yellow);

OptimalEMA.SetLineWeight(2);
OptimalEMA.HideTitle();
OptimalEMA.HideBubble();

#DYNAverage
input length = 30;
input price = close;
input rsiValue = 50.0;
input smoothingType = {default Wilders, EMA};
input Volatility_Band = 15;
input Volatility_Band1 = 20;

def coeff = rsiValue / (100 - rsiValue);
def chg = price - price[1];
def diff2;
switch (smoothingType) {
case Wilders:
    diff2 =  (length - 1) * (WildersAverage(Max(-chg, 0), length) * coeff - WildersAverage(Max(chg, 0), length));
case EMA:
    diff2 =  (length - 1) * (ExpAverage(Max(-chg, 0), length) * coeff - ExpAverage(Max(chg, 0), length)) / 2;
}
def value = price + if diff2 >= 0 then diff2 else diff2 / coeff;
def RevEngRSI = CompoundValue(1, value[1], Double.NaN);
plot DYNAverage = Average(RevEngRSI, Volatility_Band);
DYNAverage.SetLineWeight(2);
DYNAverage.HideBubble();
Dynaverage.HideTitle();

plot DYNAverage2 = Average(close, Volatility_Band);
DYNAverage2.SetDefaultColor(Color.light_gray);
DYNAverage2.SetLineWeight(1);
DYNAverage2.HideBubble();
Dynaverage2.HideTitle();

def direction = if DYNAverage[1] < DYNAverage then 1 else -1;
#def slope = reference LinearRegressionSlope(data, Max(RoundDown(length / 10,0), 2));
def slope = reference LinearRegressionSlope(DYNAverage, sqrt(Volatility_Band));
def concavity = if slope  > slope [1] then 1 else -1;

DYNAverage.AssignValueColor(if concavity > 0 and direction > 0 then Color.GREEN else
                      if concavity > 0 and direction < 0 then Color.DARK_GREEN else
                      if concavity < 0 and direction < 0 then Color.RED else
                      Color.DARK_ORANGE);

#Mid Level Average
plot DYNAverage1 = Average(OptimalEMA, Volatility_Band1);
DYNAverage1.SetLineWeight(3);
#DYNAverage1.SetDefaultColor(Color.cyan);
DYNAverage1.HideBubble();
DYNAverage1.HideTitle();

DYNAverage1.assignValueColor(if DYNaverage1 > OptimalEMA then color.red else if DYNaverage1 < OptimalEMA then color.green else color.cyan);
OptimalEMA.AssignValueColor(if OptimalEMA < DYNaverage1 and OptimalEMA > OptimalEMA[1] then OptimalEMA.Color("BreakUp") else if OptimalEMA > DYNaverage1 and OptimalEMA < OptimalEMA[1] then OptimalEMA.Color("BreakDown") else OptimalEMA.Color("Normal"));
AddCloud(DYNAverage1, OptimalEMA, Color.dark_RED, Color.dark_GREEN);
AddCloud(if(OptimalEMA < DYNaverage1 and OptimalEMA > OptimalEMA[1], OptimalEMA, double.NaN), DYNAverage1, color.cyan, color.cyan);
AddCloud(if(OptimalEMA > DYNaverage1 and OptimalEMA < OptimalEMA[1], OptimalEMA, double.NaN), DYNAverage1, OptimalEMA.color("breakdown"), OptimalEMA.color("breakdown"));

#// ~~ Return RSI Standard Deviation  {
def rsi     = RSI(Price = close, Length = rsiperiod);
def std_dev = StandardDeviation(rsi, rsiperiod);

def ob_dev = dev(emaresult(Overbought, rsiperiod), ema_result, std_dev);
def os_dev = dev(emaresult(Oversold, rsiperiod), ema_result, std_dev);
def upper  = hma(WildersAverage(ema_result + (ob_dev * std_dev), 3), 10);# // Returns the upper OB line on the chart.
def lower  = hma(WildersAverage(ema_result + (os_dev * std_dev), 3), 10);# // Returns the upper OS line on the chart.
def ob_dev1 = dev(emaresult(Overbought1, rsiperiod), ema_result, std_dev);
def os_dev1 = dev(emaresult(Oversold1, rsiperiod), ema_result, std_dev);
def upper1  = hma(WildersAverage(ema_result + (ob_dev1 * std_dev), 3), 10);# // Returns the upper OB line on the chart.
def lower1  = hma(WildersAverage(ema_result + (os_dev1 * std_dev), 3), 10);# // Returns the upper OS line on the chart.
def ob_dev2 = dev(emaresult(Overbought2, rsiperiod), ema_result, std_dev);
def os_dev2 = dev(emaresult(Oversold2, rsiperiod), ema_result, std_dev);
def upper2  = hma(WildersAverage(ema_result + (ob_dev2 * std_dev), 3), 10);# // Returns the upper OB line on the chart.
def lower2  = hma(WildersAverage(ema_result + (os_dev2 * std_dev), 3), 10);# // Returns the upper OS line on the chart.

#/ ~~ Plot Upper OB and Lower OS lines on the chart {
plot UpperOB =  upper;#, "Upper OB"
plot LowerOS = lower;#, "Lower OS"
def UpperDev =  upper - StDev(upper, 2);#, "Upper OB"
def LowerDev = lower + StDev(lower, 2);#, "Lower OS"

UpperOB.SetDefaultColor(Color.red);
LowerOS.SetDefaultColor(Color.green);
#UpperDev.SetDefaultColor(Color.RED);
#LowerDev.SetDefaultColor(Color.GREEN);
UpperOB.HideBubble();
UpperOB.HideTitle();
LowerOS.HideBubble();
LowerOS.HideTitle();

AddCloud(UpperOB, UpperDev, Color.red, Color.red);
AddCloud(lowerOS, LowerDev, Color.green, Color.green);

#Inner
#/ ~~ Plot Upper OB and Lower OS lines on the chart {
plot UpperOB1 = upper1;#, "Upper OB"
plot LowerOS1 = lower1;#, "Lower OS"
def UpperDev1 = upper1 - StDev(upper1, 2);#, "Upper OB"
def LowerDev1 = lower1 + StDev(lower1, 2);#, "Lower OS"

UpperOB1.SetDefaultColor(Color.dark_red);
LowerOS1.SetDefaultColor(Color.DARK_GREEN);
#UpperDev1.SetDefaultColor(Color.DARK_RED);
#LowerDev1.SetDefaultColor(Color.DARK_GREEN);

UpperOB1.HideBubble();
UpperOB1.HideTitle();
LowerOS1.HideBubble();
LowerOS1.HideTitle();
AddCloud(UpperOB1, UpperDev1, Color.dark_RED, Color.dark_red);
AddCloud(lowerOS1, LowerDev1, Color.dark_GREEN, Color.dark_GREEN);

#Outer

#/ ~~ Plot Upper OB and Lower OS lines on the chart {
plot UpperOB2 = if obosBands then upper2 else na;#, "Upper OB"
plot LowerOS2 = if obosBands then lower2 else na;#, "Lower OS"
DEF UpperDev2 = if obosBands then upper2 - StDev(upper2, 2) else na;#, "Upper OB"
DEF LowerDev2 = if obosBands then lower2 + StDev(lower2, 2) else na;#, "Lower OS"

UpperOB2.SetDefaultColor(Color.dark_gray);
LowerOS2.SetDefaultColor(Color.dark_gray);
#UpperDev2.SetDefaultColor(Color.dark_gray);
#LowerDev2.SetDefaultColor(Color.dark_gray);

UpperOB2.HideBubble();
UpperOB2.HideTitle();
LowerOS2.HideBubble();
LowerOS2.HideTitle();

AddCloud(UpperOB2, UpperDev2, Color.dark_gray, Color.dark_gray);
AddCloud(lowerOS2, LowerDev2, Color.dark_gray, Color.dark_gray);

#ARROWS
def fastLength = 12;
def slowLength = 26;
def MACDLength = 9;
input averageType = AverageType.EXPONENTIAL;
input showBreakoutSignals = YES;

def Diff1 = MACD(fastLength, slowLength, MACDLength, averageType).Diff *2;
plot UpSignal1 = if showBreakoutSignals and Low < LowerOS and Diff1 <= 0 and Diff1[1] < Diff1[2] and Diff1 > Diff1[1] then 1 else Double.NaN;
plot DownSignal1 = if showBreakoutSignals and High > UpperOB and Diff1 >= 0 and Diff1[1] > Diff1[2] and Diff1 < Diff1[1] then 1 else Double.NaN;


UpSignal1.SetHiding(!showBreakoutSignals);
DownSignal1.SetHiding(!showBreakoutSignals);

UpSignal1.SetDefaultColor(Color.plum);
UpSignal1.SetPaintingStrategy(PaintingStrategy.Boolean_arrow_up);
Upsignal1.setlineWeight(2);
DownSignal1.SetDefaultColor(Color.lime);
DownSignal1.SetPaintingStrategy(PaintingStrategy.Boolean_ARROW_DOWN);
Downsignal1.setlineWeight(2);
Upsignal1.HideBubble();
Upsignal1.HideTitle();
Downsignal1.HideBubble();
Downsignal1.HideTitle();
#--- END of CODE
 

Join useThinkScript to post your question to a community of 21,000+ developers and traders.

Similar threads

Not the exact question you're looking for?

Start a new thread and receive assistance from our community.

87k+ Posts
479 Online
Create Post

Similar threads

Similar threads

The Market Trading Game Changer

Join 2,500+ subscribers inside the useThinkScript VIP Membership Club
  • Exclusive indicators
  • Proven strategies & setups
  • Private Discord community
  • ‘Buy The Dip’ signal alerts
  • Exclusive members-only content
  • Add-ons and resources
  • 1 full year of unlimited support

Frequently Asked Questions

What is useThinkScript?

useThinkScript is the #1 community of stock market investors using indicators and other tools to power their trading strategies. Traders of all skill levels use our forums to learn about scripting and indicators, help each other, and discover new ways to gain an edge in the markets.

How do I get started?

We get it. Our forum can be intimidating, if not overwhelming. With thousands of topics, tens of thousands of posts, our community has created an incredibly deep knowledge base for stock traders. No one can ever exhaust every resource provided on our site.

If you are new, or just looking for guidance, here are some helpful links to get you started.

What are the benefits of VIP Membership?
VIP members get exclusive access to these proven and tested premium indicators: Buy the Dip, Advanced Market Moves 2.0, Take Profit, and Volatility Trading Range. In addition, VIP members get access to over 50 VIP-only custom indicators, add-ons, and strategies, private VIP-only forums, private Discord channel to discuss trades and strategies in real-time, customer support, trade alerts, and much more. Learn all about VIP membership here.
How can I access the premium indicators?
To access the premium indicators, which are plug and play ready, sign up for VIP membership here.
Back
Top