SuperTrend Of MACD and AVG RSI

MichaelSF

MichaelSF

New member
I was playing around with Mobius's original SuperTrend script recently -
https://usethinkscript.com/threads/supertrend-indicator-by-mobius-for-thinkorswim.7/

- and combining it with other popular indicators and found a couple of interesting results after a lot of tweaking and testing. Below is the first Indicator I tested this with; the MACD. It plots the MACD Diff Line (The Histogram Part) and uses that to calculate a SuperTrend "of" that line in order to smooth its movement. I'm sure that I'm not the first person to have done this, but I couldn't find a thread on here relating to it so here's my shot at it.

Code:
#SuperTrendOfMACD
#MichaelSF 2/2020
#Original SuperTrend Code By Mobius

declare lower;

## MACD ##
input fastLength = 12;
input slowLength = 26;
input MACDLength = 9;
input averageType = AverageType.EXPONENTIAL;

def Value = MovingAverage(averageType, close, fastLength) - MovingAverage(averageType, close, slowLength);
def Avg = MovingAverage(averageType, Value, MACDLength);

plot MACDdiff = Value - Avg;
MACDdiff.SetPaintingStrategy(PaintingStrategy.LINE);

plot ZeroLine = 0;
ZeroLine.setDefaultColor(Color.dark_GRAY);

## SUPERTREND ##
input AtrMult = 1.0;
input nATR = 18;

def ATR = MovingAverage(AverageType.HULL, TrueRange(MACDdiff, MACDdiff, MACDdiff), nATR);
def UP = MACDdiff + (AtrMult * ATR);
def DN = MACDdiff + (-AtrMult * ATR);
def ST = if MACDdiff < ST[1] then UP else DN;

plot SuperTrend = ST;
SuperTrend.setDefaultColor(Color.dark_GRAY);

## COLORS & PLOTS ##

MACDDiff.AssignValueColor(if ST < MACDdiff then color.green else if ST > MACDdiff then color.red else color.Gray);

plot UpSignal = if ST crosses below MACDdiff then MACDdiff else Double.NaN;
plot DownSignal = if ST crosses above MACDdiff then MACDdiff else Double.NaN;
UpSignal.SetDefaultColor(Color.UPTICK);
UpSignal.SetPaintingStrategy(PaintingStrategy.ARROW_UP);
DownSignal.SetDefaultColor(Color.DOWNTICK);
DownSignal.SetPaintingStrategy(PaintingStrategy.ARROW_DOWN);


Above is an example of this indicator being used on SPY in combination with the normal RSI. I find it works best on extreme overbought/oversold conditions, which is why the RSI is a good pair with it.

Unsurprisingly, the next indicator I tried to convert to SuperTrend was the RSI. The thing with the RSI is that it tends to be very choppy, and SuperTrending it would just be a zig-zag mess of nothingness, which is pictured below. Still could be useful in some cases maybe, but too choppy to be reliable in my opinion.



The solution to this was creating a MovingAverage of the RSI, and then adding a SuperTrend calculated off of that line instead. Below is the result of this and the code for the script.



In the picture above its crosses were almost identical to the Original SuperTrend crosses, so I added another picture from a different day that shows it better below.
NOTE: I've found that when the Classic SuperTrend and AvgRSISuperTrend do line up it's actually a pretty good way of confirming a strong move, so if you choose to use this remember to look out for that.



Code:
#SuperTrendOfAvgRSI
#MichaelSF 2/2020
#Original SuperTrend Code By Mobius

declare lower;

## RSI ##
input AvgLength = 10;
input AvgType = AverageType.SIMPLE;
input price = close;

def NetChgAvg = MovingAverage(AverageType.WILDERS, price - price[1], 14);
def TotChgAvg = MovingAverage(AverageType.WILDERS, AbsValue(price - price[1]), 14);
def ChgRatio = if TotChgAvg != 0 then NetChgAvg / TotChgAvg else 0;

def RSI = 50 * (ChgRatio + 1);

plot RSIAvg = MovingAverage(AvgType, RSI, Avglength);
RSIAvg.SetPaintingStrategy(PaintingStrategy.Line);

## SUPERTREND ##
input AtrMult = 1.0;
input nATR = 20;

def ATR = MovingAverage(AverageType.HULL, TrueRange(RSIAvg, RSIAvg, RSIAvg), nATR);
def UP = RSIAvg + (AtrMult * ATR);
def DN = RSIAvg + (-AtrMult * ATR);
def ST = if RSIAvg < ST[1] then UP else DN;

plot SuperTrend = ST;
SuperTrend.setDefaultColor(Color.dark_GRAY);

## COLORS ##
RSIAvg.AssignValueColor(if SuperTrend < RSIAvg then color.green else if SuperTrend > RSIAvg then color.red else color.Gray);

plot OverSold = 30;
OverSold.setDefaultColor(Color.dark_GRAY);
plot OverBought = 70;
OverBought.setDefaultColor(Color.dark_GRAY);

plot UpSignal = if ST crosses below RSIAvg then RSIAvg else Double.NaN;
plot DownSignal = if ST crosses above  RSIAvg then RSIAvg else Double.NaN;
UpSignal.SetDefaultColor(Color.UPTICK);
UpSignal.SetPaintingStrategy(PaintingStrategy.ARROW_UP);
DownSignal.SetDefaultColor(Color.DOWNTICK);
DownSignal.SetPaintingStrategy(PaintingStrategy.ARROW_DOWN);
A few other things:
  • The colors on the chart are from the Mobius SuperTrend, not the indicators
  • The Settings on these indicators are what I found works best, but play around with them yourself to see if something works better for you.

Hopefully someone can find some use out of these. I've created a few strategies based on them and they ended up working pretty well.

Thank you to everyone that's apart of this community! Learned more than I could've imagined since finding this forum.
 
Last edited:
J

john3

Active member
2019 Donor
Warehouse
@MichaelSF Have you seen this contraption? It has everything, Superterend based on RSI, Ultimate and Chandelier.
Code:
## START STUDY
## SuperCombo Bull/Bear Indicator
## linus, 2014-07-24, v0.1

#hint: SuperTrend of price, RSI and Ultimate Oscillator, combined with Chandelier stops.

## Signal inputs:
input paintBars = {OFF, default DIR, STR};
input signals = {OFF, default ALL, ST, CS, RSI, UO};
input strength = {"1", "2", default "3", "4"};
input showLabel = Yes;
input showBubbles = Yes;
input showPrompt = Yes;

## SuperTrend of Price inputs:
input stATRMult = 3.5;
input stATRLength = 22;
input stATRType = AverageType.WILDERS;
input stPivot = hl2;

## Chandelier Stop inputs:
input csPeriod = 15;
input csATRLength = 5;
input csATRMult = 3.0;  
input csATRType = AverageType.SIMPLE;
input csShift = 1;
input csHideOpposite = Yes;

## SuperTrend of RSI inputs:
input rsiLength = 14;
input rsiPrice = close;
input rsiSmooth = 2;
input rsiSmoothType = AverageType.SIMPLE;
input rsiATRMult = 2.3;
input rsiATRLength = 25;
input rsiATRType = AverageType.WILDERS;

## SuperTrend of Ultimate Oscillator inputs:
input uoFastLen = 7;
input uoMedLen = 14;
input uoSlowLen = 28;
input uoATRMult = 2.8;
input uoATRLength = 3;
input uoATRType = AverageType.SIMPLE;

########################################
## SuperTrend of Price

def stATR = MovingAverage(stATRType, TrueRange(high, close, low), stATRLength) * stATRMult;

def stUp = stPivot + stATR;
def stDn = stPivot - stATR;

def rStTrend = compoundValue(1,
    if rStTrend[1] > 0 then
        if close < Max(stDn[1], rStTrend[1]) then -stUp
        else Max(stDn, rStTrend[1])
    else if rStTrend[1] < 0 then
        if close > Min(stUp[1], AbsValue(rStTrend[1])) then stDn
        else -Min(stUp, AbsValue(rStTrend[1]))
    else rStTrend[1]
, stPivot);

plot StTrend = if Sign(rStTrend) == Sign(rStTrend[1]) then absValue(rStTrend) else Double.NaN;
StTrend.DefineColor("Up", Color.CYAN);
StTrend.DefineColor("Dn", Color.MAGENTA);
StTrend.AssignValueColor(if rStTrend > 0 then StTrend.Color("Up") else StTrend.Color("Dn"));
StTrend.HideBubble();
StTrend.SetLineWeight(3);

########################################
## Chandelier_Stops

def csATR = MovingAverage(csATRType, TrueRange(high, close, low), csATRLength) * csATRMult;

def smax = Lowest(low, csPeriod)[csShift] + csATR[csShift];
def smin = Highest(high, csPeriod)[csShift] - csATR[csShift];

def rCSTrend = compoundValue(1, if close > smax[1] then 1 else if close < smin[1] then -1 else rCSTrend[1], 0);

def rUB = compoundValue(1, if rCSTrend > 0 then if smax > rUB[1] then smax else rUB[1] else if rCSTrend < 0 then if smax < rUB[1] then smax else rUB[1] else rUB[1], high);

def rLB = compoundValue(1, if rCSTrend < 0 then if smin < rLB[1] then smin else rLB[1] else if rCSTrend > 0 then if smin > rLB[1] then smin else rLB[1] else rLB[1], low);

plot UB = if !csHideOpposite or rCSTrend < 0 then rUB else Double.NaN;
UB.SetDefaultColor(Color.MAGENTA);
UB.SetLineWeight(3);
UB.SetStyle(Curve.SHORT_DASH);
UB.HideBubble();

plot LB = if !csHideOpposite or rCSTrend > 0 then rLB else Double.NaN;
LB.SetDefaultColor(Color.CYAN);
LB.SetLineWeight(3);
LB.SetStyle(Curve.SHORT_DASH);
LB.HideBubble();

########################################
## SuperTrend of RSI

def avgDif = WildersAverage(AbsValue(rsiPrice - rsiPrice[1]), rsiLength);
def RSI = MovingAverage(rsiSmoothType, 50 * ((if avgDif != 0 then WildersAverage(rsiPrice - rsiPrice[1], rsiLength) / avgDif else 0) + 1), rsiSmooth);

def rsiATR = MovingAverage(rsiATRType, TrueRange(Highest(RSI, ceil(rsiATRMult)), RSI, Lowest(RSI, ceil(rsiATRMult))), rsiATRLength) * rsiATRMult;
def rsiUp = RSI + rsiATR;
def rsiDn = RSI - rsiATR;

def rRSITrend = compoundValue(1,
    if rRSITrend[1] > 0 then
        if RSI < Max(rsiDn[1], rRSITrend[1]) then -rsiUp
        else Max(rsiDn, rRSITrend[1])
    else if rRSITrend[1] < 0 then
        if RSI > Min(rsiUp[1], AbsValue(rRSITrend[1])) then rsiDn
        else -Min(rsiUp, AbsValue(rRSITrend[1]))
    else rRSITrend[1]
, RSI);

########################################
## SuperTrend of Ultimate Oscillator

def TR = TrueRange(high, close, low);
def BP = close - Min(close[1], low);
def nFast = (uoSlowLen / uoFastLen);
def nMed = (uoSlowLen / uoMedLen);
def trFast = sum(TR, uoFastLen);
def trMed = sum(TR, uoMedLen);
def trSlow = sum(TR, uoSlowLen);

def UO = 100 * (((if trFast != 0 then (sum(BP, uoFastLen) / trFast) * nFast else 0)
    +  (if trMed != 0 then (sum(BP, uoMedLen) / trMed) * nMed else 0)
    + (if trSlow != 0 then (sum(BP, uoSlowLen) / sum(TR, uoSlowLen)) else 0))
/ (nFast + nMed + 1));

def uoATR = MovingAverage(uoATRType, TrueRange(Highest(UO, ceil(uoATRMult)), UO, Lowest(UO, ceil(uoATRMult))), uoATRLength) * uoATRMult;
def uoUp = UO + uoATR;
def uoDn = UO - uoATR;

def rUOTrend = compoundValue(1,
    if rUOTrend[1] > 0 then
        if UO < Max(uoDn[1], rUOTrend[1]) then -uoUp
        else Max(uoDn, rUOTrend[1])
    else if rUOTrend[1] < 0 then
        if UO > Min(uoUp[1], AbsValue(rUOTrend[1])) then uoDn
        else -Min(uoUp, AbsValue(rUOTrend[1]))
    else rUOTrend[1]
, UO);

########################################
## Signals

def orderDir;
def p;
def sumUp = (rStTrend > 0) + (rCSTrend > 0) + (rRSITrend > 0) + (rUOTrend > 0);
def sumDn = (rStTrend < 0) + (rCSTrend < 0) + (rRSITrend < 0) + (rUOTrend < 0);

switch (signals) {
case OFF:
    orderDir = 0;
    p = 0;
case ALL:
    orderDir = compoundValue(1, if sumUp >= strength+1 then 1 else if sumDn >= strength+1 then -1 else orderDir[1], 0);
    p = if showPrompt then 1 else 0;
case ST:
    orderDir = rStTrend;
    p = if showPrompt then 2 else 0;
case CS:
    orderDir = rCSTrend;
    p = if showPrompt then 3 else 0;
case RSI:
    orderDir = rRSITrend;
    p = if showPrompt then 4 else 0;
case UO:
    orderDir = rUOTrend;
    p = if showPrompt then 5 else 0;
}

def isOrder = orderDir crosses 0;

def orderCount = compoundValue(1, if isNaN(isOrder) then 0 else if isOrder then orderCount[1] + 1 else orderCount[1], 0);

def noBar = isNaN(open[-1]);

def orderPrice = if isOrder then if noBar then close else open[-1] else orderPrice[1];
def profitLoss = if !isOrder or orderCount == 1 then 0 else if orderDir > 0 then orderPrice[1] - orderPrice else if orderDir < 0 then orderPrice - orderPrice[1] else 0;
def profitLossSum = compoundValue(1, if isNaN(isOrder) then 0 else if isOrder then profitLossSum[1] + profitLoss else profitLossSum[1], 0);

AddLabel(signals and showLabel, (if p==1 then "ALL: " else if p==2 then "ST: " else if p==3 then "CS: " else if p==4 then "RSI: " else if p==5 then "UO: " else "") + orderCount + " orders | P/L " + AsDollars((profitLossSum / tickSize()) * tickValue()), if profitLossSum > 0 then Color.GREEN else if profitLossSum < 0 then Color.RED else Color.GRAY);

AddChartBubble(signals and showBubbles and isOrder and orderDir > 0, low, profitLoss, if noBar then Color.LIGHT_GRAY else Color.GREEN, 0);
AddChartBubble(signals and showBubbles and isOrder and orderDir < 0, high, profitLoss, if noBar then Color.GRAY else Color.RED, 1);

AssignPriceColor(if !paintBars then Color.CURRENT
else if paintBars == paintBars.DIR then
    if orderDir > 0 then
        if rSTTrend < 0 or rCSTrend < 0 then Color.DARK_ORANGE
        else Color.UPTICK
    else if orderDir < 0 then
        if rSTTrend > 0 or rCSTrend > 0 then Color.YELLOW
        else Color.DOWNTICK
    else Color.GRAY
else if sumUp >= strength+1 then Color.UPTICK
else if sumDn >= strength+1 then Color.DOWNTICK
else if sumUp > sumDn then Color.YELLOW
else if sumDn > sumUp then Color.DARK_ORANGE
else Color.GRAY);

## END STUDY
 
Last edited by a moderator:
horserider

horserider

Well-known member
VIP
How is this an ATR ?
def ATR = MovingAverage(AverageType.HULL, TrueRange(RSIAvg, RSIAvg, RSIAvg), nATR);
 
MichaelSF

MichaelSF

New member
How is this an ATR ?
def ATR = MovingAverage(AverageType.HULL, TrueRange(RSIAvg, RSIAvg, RSIAvg), nATR);
Yeah I'm sure it's not. I literally just spliced the MACD and RSI together with Mobius's code and got these indicators as the result, so it might be closer to a Moving Average than an ATR. It still ends up having unique smoothing similar to the Classic SuperTrend however, which is what I was going for.
 
Last edited:
H

HighBredCloud

Active member
VIP
@MichaelSF Which Mobius SuperTrend did you compare this to? The one below? The AVG RSI SuperTrend looks nice...I will have to test it out and see how it compares to standard Heikin Ashi.

Code:
# SuperTrend
# Mobius
# Chat Room Request
# 11.20.2019 tomsk Enhanced and adjusted bubbles with coloring and description tag

input AtrMult = 1.0;
input nATR = 4;
input AvgType = AverageType.HULL;
input PaintBars = yes;
input n = 0;
def n1  = n + 1;
def ATR = MovingAverage(AvgType, TrueRange(high, close, low), nATR);
def UP = HL2 + (AtrMult * ATR);
def DN = HL2 + (-AtrMult * ATR);
def ST = if close < ST[1] then UP else DN;
plot SuperTrend = ST;
SuperTrend.AssignValueColor(if close < ST then Color.RED else Color.GREEN);
AssignPriceColor(if PaintBars and close < ST
                 then Color.RED
                 else if PaintBars and close > ST
                      then Color.GREEN
                      else Color.CURRENT);

#AddChartBubble(close[n] crosses below ST[n], low[n+1] + TickSize() * n, "Sell @ " + low[n1], color.Cyan, yes);
#AddChartBubble(close[n] crosses above ST[n], high[n+1] - TickSize() * n, "Buy @ " + high[n1], color.Yellow, no);

# End Code SuperTrend
 
H

HighBredCloud

Active member
VIP
@HighBredCloud Yep, that's the one I based both on
Yeah that particular SuperTrend...IF you change the ATRMULT to .7 even .5 from 1.0 will hit faster for more precise results...Have you tested your RSIavg SuperTrend with such settings changed to see how it stacks up or what it can be improved...
 
horserider

horserider

Well-known member
VIP
If want a smoothed RSI not based on fuzzy calculations check the Derivative RSI.
 
MichaelSF

MichaelSF

New member
Yeah that particular SuperTrend...IF you change the ATRMULT to .7 even .5 from 1.0 will hit faster for more precise results...Have you tested your RSIavg SuperTrend with such settings changed to see how it stacks up or what it can be improved...
Yes, I did a lot of adjusting with different combinations of AtrMult and NAtr settings to see how it affected the quickness and effectiveness, but as I remember there wasn't anything that really stood out as a perfect setting for it. Keeping the AtrMult at 1.0 seems to be a good neutral level, but different settings work well for different tickers and timeframes.
 
Last edited:
MichaelSF

MichaelSF

New member
If want a smoothed RSI not based on fuzzy calculations check the Derivative RSI.
That looks like a good one too. Wasn't trying to say mine wasn't fuzzy, just thought id share it because I got some decent results with it.
 
retrobeast

retrobeast

New member
So there is 3 or 4 codes on this page. Which one is actually the one to use for trading futures or is it for stocks using a long time frame?
 
Last edited:
D

dolomick

Member
I like this but also like the normal MACD, so I made the crossover arrows an upper study and it gives good signals. Here you go...

Code:
#SuperTrendOfMACD
#MichaelSF 2/2020
#Original SuperTrend Code By Mobius



## MACD ##
input fastLength = 12;
input slowLength = 26;
input MACDLength = 9;
input averageType = AverageType.EXPONENTIAL;

def Value = MovingAverage(averageType, close, fastLength) - MovingAverage(averageType, close, slowLength);
def Avg = MovingAverage(averageType, Value, MACDLength);

plot MACDdiff = Value - Avg;
MACDdiff.SetPaintingStrategy(PaintingStrategy.LINE);
MACDdiff.Hide();

plot ZeroLine = 0;
ZeroLine.setDefaultColor(Color.dark_GRAY);
Zeroline.Hide();

## SUPERTREND ##
input AtrMult = 1.0;
input nATR = 18;

def ATR = MovingAverage(AverageType.HULL, TrueRange(MACDdiff, MACDdiff, MACDdiff), nATR);
def UP = MACDdiff + (AtrMult * ATR);
def DN = MACDdiff + (-AtrMult * ATR);
def ST = if MACDdiff < ST[1] then UP else DN;

plot SuperTrend = ST;
SuperTrend.setDefaultColor(Color.dark_GRAY);
SuperTrend.Hide();

## COLORS & PLOTS ##

MACDDiff.AssignValueColor(if ST < MACDdiff then color.green else if ST > MACDdiff then color.red else color.Gray);

plot UpSignal = if ST crosses below MACDdiff then MACDdiff else Double.NaN;
plot DownSignal = if ST crosses above MACDdiff then MACDdiff else Double.NaN;
UpSignal.SetDefaultColor(Color.UPTICK);
UpSignal.SetPaintingStrategy(PaintingStrategy.ARROW_UP);
DownSignal.SetDefaultColor(Color.DOWNTICK);
DownSignal.SetPaintingStrategy(PaintingStrategy.ARROW_DOWN);
 
horserider

horserider

Well-known member
VIP
Still using the same flawed calculation of ATR.
 
retrobeast

retrobeast

New member
Thanks I will give it a go. Looking for something to help with scalping futures. Also everybody keeps complaining about flawed ATR. If so then why dont someone fix it? happy friday.
 
horserider

horserider

Well-known member
VIP
Go ahead see if you can fix it. Think it might be only me complaining. 🙃
 
retrobeast

retrobeast

New member
Im not complaining at all. I just notice several posts saying ATR setting is wrong.
 
horserider

horserider

Well-known member
VIP
This whole study is flawed. Essentially what it does is multiply the MACDDIFF by 1. A lot of calculation for nothing. If you want the supertrend and MACDIFF crossing just add supertrend to standard MACD study.

Same with RSI study. Only thing making the RSI smoother is applying the simple moving average to the RSI plot. So just do the RSI average and supertrend crosses if that is what you want.

These both do not make a supertrend of the underlying indicators. So if anyone thought it was a study doing that it is not. Make sure you understand the studies you are using. Maybe it should be renamed MACDDIFF and Supertrend cross and RSI average and Supertrend cross.
 
MichaelSF

MichaelSF

New member
This whole study is flawed. Essentially what it does is multiply the MACDDIFF by 1. A lot of calculation for nothing. If you want the supertrend and MACDIFF crossing just add supertrend to standard MACD study.

Same with RSI study. Only thing making the RSI smoother is applying the simple moving average to the RSI plot. So just do the RSI average and supertrend crosses if that is what you want.

These both do not make a supertrend of the underlying indicators. So if anyone thought it was a study doing that it is not. Make sure you understand the studies you are using. Maybe it should be renamed MACDDIFF and Supertrend cross and RSI average and Supertrend cross.
I definitely understand what you're saying, but I would argue that it does more than "just multiply the MACDDIFF by 1".

In the main part of the code which is in question...

def ATR = MovingAverage(AverageType.HULL, TrueRange(MACDdiff, MACDdiff, MACDdiff), nATR);
def UP = MACDdiff + (AtrMult * ATR);
def DN = MACDdiff + (-AtrMult * ATR);
def ST = if MACDdiff < ST[1] then UP else DN;

Its actually adding to the MACD diff with a Hull moving average of the MACD Diff with a length of 4, and then makes it either positive or negative based on the candle before it. This is not the same as multiplying it by 1, and gives if an effect that I found was similar enough to a the original SuperTrend to call it by that name. Again, i was just splicing the two codes for fun and getting this as a result, if someone can make it better then I 100% encourage it.
 
Last edited:

Top