RSI with RateOfChange Indicator for ThinkorSwim

BenTen

BenTen

Administrative
Staff
VIP
Someone recently asked if we could combine the RSI and RateOfChange indicator into one. More specifically, using the RateOfChange (ROC) indicator as the source. This indicator was inspired by the OBV/RSI thread that @diazlaz converted from TradingView.



thinkScript Code

Code:
# RSI with RateOfChange
# An RSI, using RateOfChange (ROC) as the source
# Code based off of OBV/RSI thread from @diazlaz
# Assembled by BenTen at useThinkScript.com

declare lower;

input length = 14;
input over_Bought = 70;
input over_Sold = 30;
input src = close;
input averageType = AverageType.WILDERS;
input showBreakoutSignals = no;

# Rate of Change code
input price_ROC = close;
assert(length > 0, "'length' must be positive: " + length);
def ROC = if price_ROC[length] != 0 then(price_ROC / price_ROC[length] - 1) * 100 else 0;
#end of ROC code

def price = ROC;

def NetChgAvg = MovingAverage(averageType, price - price[1], length);
def TotChgAvg = MovingAverage(averageType, AbsValue(price - price[1]), length);
def ChgRatio = if TotChgAvg != 0 then NetChgAvg / TotChgAvg else 0;

plot RSI = 50 * (ChgRatio + 1);
plot OverSold = over_Sold;
plot OverBought = over_Bought;
plot UpSignal = if RSI crosses above OverSold then OverSold else Double.NaN;
plot DownSignal = if RSI crosses below OverBought then OverBought else Double.NaN;

plot mid = 50;
mid.SetPaintingStrategy(paintingStrategy = PaintingStrategy.DASHES);
mid.AssignValueColor(COLOR.DARK_GRAY);

UpSignal.SetHiding(!showBreakoutSignals);
DownSignal.SetHiding(!showBreakoutSignals);

RSI.DefineColor("OverBought", GetColor(5));
RSI.DefineColor("Normal", GetColor(7));
RSI.DefineColor("OverSold", GetColor(1));
RSI.AssignValueColor(if RSI > over_Bought then RSI.color("OverBought") else
  if RSI<over_Sold then RSI.color("OverSold") else RSI.color("Normal"));

OverSold.SetDefaultColor(GetColor(8));
OverBought.SetDefaultColor(GetColor(8));
UpSignal.SetDefaultColor(Color.UPTICK);
UpSignal.SetPaintingStrategy(PaintingStrategy.ARROW_UP);
DownSignal.SetDefaultColor(Color.DOWNTICK);
DownSignal.SetPaintingStrategy(PaintingStrategy.ARROW_DOWN);

# END OF ROC RSI
 
J

john3

Active member
2019 Donor
I don't use the code below. I just wanted to share it since it's on the same subject and someone might find it useful.

I keep an eye on this combo, intraday, 15 minutes or 8 minutes time frame.

Code:
# IBD newspaper's price momentum indicator located in the Futures section of the daily paper.

# As quoted: Price momentum equals rate of change of high, low and close for last 14 days. Change of short term price direction may be indicated when %F (dark line) crosses % S (thin line).

# Under each of the futures a chart with price momentum with a high of 75 and low of 25 and two lines. 1 representing the F.

# Response:  The green and Cyan is the RS line and the yellow and orange is the ROC that it compares to. As far as your percentiles I don't quite know how to come up with that but this comparison appears to be useful even on an intraday basis.  Lash - June 26, 2014

##########################

declare lower;

input length = 14;
input colorNormLength = 14;
input price = close;

assert(length > 0, "'length' must be positive: " + length);
def c = close;

plot RS = ((((C - C[63]) / C[63]) * .4) + (((C - C[126]) / C[126]) * .2) + (((C - C[189]) / C[189]) * .2) + (((C - C[252]) / C[252]) * .2)) * 100 ;
plot ROC = if price[length] != 0 then (price / price[length] - 1) * 100 else 0;
plot ZeroLine = 0;

ROC.DefineColor("Highest", Color.YELLOW);
ROC.DefineColor("Lowest", Color.LIGHT_RED);
ROC.AssignNormGradientColor(colorNormLength, ROC.color("Lowest"), ROC.color("Highest"));

RS.DefineColor("Highest", Color.Green);
RS.DefineColor("Lowest", Color.cyan);
RS.AssignNormGradientColor(colorNormLength, RS.color("Lowest"), RS.color("Highest"));
ZeroLine.SetDefaultColor(GetColor(5));
Lower:

Code:
#ChangeMomentumOscillator
declare lower;

input length = 8;

def curClose = close;
def prevClose = close[1];
def inc = if curClose > prevClose then curClose - prevClose else 0;
def dec = if prevClose > curClose then prevClose - curClose else 0;

def sumInc = sum(inc, length);
def sumDec = sum(dec, length);
plot CMO = if sumInc + sumDec == 0 then 0 else (sumInc - sumDec) / (sumInc + sumDec) * 100;
CMO.SetDefaultColor(GetColor(8));

plot ZeroLine = 0;
ZeroLine.SetDefaultColor(GetColor(5));

plot UpperLevel = 50;
UpperLevel.SetDefaultColor(GetColor(5));

plot LowerLevel = -50;
LowerLevel.SetDefaultColor(GetColor(5));

plot arrowup = if CMO crosses above LowerLevel then CMO else double.NaN;

arrowup.setPaintingStrategy(paintingStrategy.ARROW_UP);
arrowup.assignValueColor(color.green);

plot arrowdown = if CMO crosses below UpperLevel then CMO else double.NaN; #Plot pretty arrow

arrowdown.setPaintingStrategy(paintingStrategy.ARROW_DOWN);
arrowdown.assignValueColor(color.magenta);
Upper

Code:
#ChangeMomentumOscillator

input length = 8;

def curClose = close;
def prevClose = close[1];
def inc = if curClose > prevClose then curClose - prevClose else 0;
def dec = if prevClose > curClose then prevClose - curClose else 0;

def sumInc = sum(inc, length);
def sumDec = sum(dec, length);
plot CMO = if sumInc + sumDec == 0 then 0 else (sumInc - sumDec) / (sumInc + sumDec) * 100;
CMO.SetDefaultColor(GetColor(8));

plot ZeroLine = 0;
ZeroLine.SetDefaultColor(GetColor(5));

plot UpperLevel = 50;
UpperLevel.SetDefaultColor(GetColor(5));

plot LowerLevel = -50;
LowerLevel.SetDefaultColor(GetColor(5));

plot arrowup = if CMO crosses above LowerLevel then CMO else double.NaN;

arrowup.setPaintingStrategy(paintingStrategy.ARROW_UP);
arrowup.assignValueColor(color.green);

plot arrowdown = if CMO crosses below UpperLevel then CMO else double.NaN; #Plot pretty arrow

arrowdown.setPaintingStrategy(paintingStrategy.ARROW_DOWN);
arrowdown.assignValueColor(color.magenta);

plot SignalUP = if arrowup then HL2 else double.nan;
SignalUP.SetDefaultColor(Color.CYAN);
SignalUP.SetPaintingStrategy(PaintingStrategy.ARROW_UP);

plot SignalDOWN = if arrowdown then HL2 else double.nan;
SignalDOWN.SetDefaultColor(Color.MAGENTA);
SignalDOWN.SetPaintingStrategy(PaintingStrategy.ARROW_DOWN);
The EMA and the MOBO are both available in TOS.

The ChangeMomentumOscillator is also from TOS. I have added the arrows to the Lower study and created an upper study so that the arrows can be plotted on the price chart.

Usage: The ChangeMomentumOscillator is an early warning, it shows when momentum has changed and might reverse.
Early Trigger (High Risk): When EMA turns Green (Long), Red (short).
Normal Trigger (Safe): When EMA is Green and has crossed the MOBO (MOBO is Green), enter Long. Vice versa for Short.

Example: RTY, intraday, 15 minutes, past Thursday, 12/26/19.



Another example from yesterday, Friday, RTY, 15 minutes



Example of a long entry, RTY, 15 minutes, 12/23/19.

 
Last edited by a moderator:
markos

markos

Well-known member
VIP
@john3 Quite interesting. I noticed (JQ) in line 13 of the MOBO indicator.
Was that his creation or just from TSL? Either way it's ok, JQ is considered a friend and great resource.

What @BenTen is creating here is the premier ThinkorSwim education site, imo. Please tell us how you use each OR the combo so all can learn.
Thanks!
 
H

hurricane5

New member
2019 Donor
@john3 Thanks...Really like this one - and the EMAMobo section is tolerable on mobile (upper and lower not so much)! I've paired this with RSI Leguerre and the TMO for pretty good results. Also backtesting a mobile version of ORB as an addition - so far so good.

Wondering if there is any way to set a scan for the EMA crossovers?

Ben - I'm trying to alert the EMA when it crosses the MOBO bands (identifying normal long or normal short entries, per John3's screenshots above). On mobile, the green or red bands don't get filled in - but the green/red outline works, but and the EMA doesn't change trend color. I'm gong to try and see if I can get a scan to work, but didn't know if there was one lying around...

Update: Found a FW_MOBO_Basic and MOBO_Advanced built into TOS - looks similar...now need to see how to recreate the EMA version in the script above.
 
Last edited by a moderator:
T

tomsk

Well-known member
VIP
Folks, just found the study mentioned above in my files

Code:
# MOBO Basic Replica
# Mobius
# V01. 2015
# 9.4.2019

input price = close;
input displace = 0;
input length = 10;
input Num_Dev_Dn = -.80;
input Num_Dev_up = .80;
input averageType = AverageType.Simple;

def sDev = stdev(data = price[-displace], length = length);

plot MidLine = MovingAverage(averageType, data = price[-displace], length = length);
plot LowerBand = MidLine + num_Dev_Dn * sDev;
plot UpperBand = MidLine + num_Dev_Up * sDev;
LowerBand.SetDefaultColor(GetColor(0));
MidLine.SetDefaultColor(GetColor(1));
UpperBand.SetDefaultColor(GetColor(5));
plot ArrowUp = if close crosses above UpperBand 
               then close 
               else double.nan;
     ArrowUp.SetPaintingStrategy(PaintingStrategy.Arrow_UP);
     ArrowUp.SetDefaultColor(Color.Dark_Orange);
plot ArrowDn = if close crosses below LowerBand 
               then close 
               else double.nan;
     ArrowDn.SetPaintingStrategy(PaintingStrategy.Arrow_DOWN);
     ArrowDn.SetDefaultColor(Color.Cyan);
 
D

DeusMecanicus

Member
EMAMOBO from shared files.

Code:
## EMA with MOBO attached
# MOBO = Momentum breakout
declare upper;

input price = close;

input length = 8;
input displace = 0;
# MOBO parameters
input ColoredMobo = yes;
input ColoredFill = yes;

input MOBO_midline = no;
input MOBO_displace = 0;
input MOBO_length = 10;
input Num_Dev_Dn = -0.8;
input Num_Dev_Up = +0.8;

plot AvgExp = ExpAverage(price[-displace], length); # default is an 8 bar EMA (JQ)
AvgExp.DefineColor("Up", CreateColor( 0, 220, 0));
AvgExp.DefineColor("Down", Color.MAGENTA);
AvgExp.AssignValueColor(if AvgExp > AvgExp [1] then AvgExp.Color("Up") else AvgExp.Color("Down"));
AvgExp.SetLineWeight(5);
AvgExp.HideBubble();

def Midline = Average (data = AvgExp, MOBO_length); # the default is a 10 bar SMA of the previously calculated 8 bar EMA of close
def sDev = StDev(data = AvgExp[-MOBO_displace], length = MOBO_length);
def LowerBand = Midline + Num_Dev_Dn * sDev;
def UpperBand = Midline + Num_Dev_Up * sDev; # effectively creates an exponential Bollinger with .8 StdDev bands

def MoboStatus =
if AvgExp > UpperBand then 2 # Mobo Up
else
if AvgExp < LowerBand then -2 # Mobo Down
else 0; # between the bands

rec BreakStatus = CompoundValue(1,
if BreakStatus[1] == MoboStatus or MoboStatus == 0 then BreakStatus[1]
else
if MoboStatus == 2 then 2
else -2, 0);

plot MidlineP =
if MOBO_midline then Midline
else Double.NaN;
MidlineP.SetDefaultColor(GetColor(1));
MidlineP.HideBubble();

plot UpperBandP = UpperBand;
UpperBandP.AssignValueColor (
if !ColoredMobo then Color.WHITE
else
if BreakStatus[0] == 2 then Color.green
else Color.red);
UpperBandP. SetLineWeight(1);
UpperBandP.HideBubble();

plot LowerBandP = LowerBand;
LowerBandP.AssignValueColor (
if !ColoredMobo then Color.WHITE
else
if BreakStatus[0] == 2 then Color.green
else Color.red);
LowerBandP.SetLineWeight(1);
LowerBandP.HideBubble();

# colored clouds
plot GreenUpper = if ColoredFill and BreakStatus[0] == 2 then
UpperBandP else Double.NaN;
GreenUpper.SetDefaultColor(CreateColor(0, 230, 0));
plot GreenLower = if ColoredFill and BreakStatus[0] == 2 then
LowerBandP else Double.NaN;
GreenLower.SetDefaultColor(CreateColor(0, 230, 0));
AddCloud (GreenUpper, GreenLower, Color.green, Color.RED);

plot RedUpper = if ColoredFill and BreakStatus[0] == -2 then
UpperBandP else Double.NaN;
RedUpper.SetDefaultColor(CreateColor(230, 0, 0));
plot RedLower = if ColoredFill and BreakStatus[0] == -2 then
LowerBandP else Double.NaN;
RedLower.SetDefaultColor(CreateColor(230, 0, 0));
AddCloud (RedUpper, RedLower, Color.red, Color.RED);
#end
 
P

Pharmd2Retire

New member
VIP
Just for anyone interested here is RSI in pink and ROC RSI compared.
@horserider out of curiousity, do you mind sharing the code that gives you info about calls and puts? seems if it wasnt lagging, you could have made some good money with that strategy
 
horserider

horserider

Well-known member
VIP
@Pharmd2Retire Sorry should have erased those from the chart as I was working on that study when I put up the RSI and ROC RSI comparision. I am working on the put/call for someone so unable to share it. Hope you understand.
 
P

Pharmd2Retire

New member
VIP
@Pharmd2Retire Sorry should have erased those from the chart as I was working on that study when I put up the RSI and ROC RSI comparision. I am working on the put/call for someone so unable to share it. Hope you understand.
understood!
 
C

chillc15

New member
Regarding @DeusMecanicus post # 6 and for @horserider, @tomsk or anyone that would know how to AssignPriceColor when the MOBO "Breakstatus" occurs.

I see several code that dictates break status which then the upper and lower either go green or red. I have tried several assign price color but can't seem to get it. Also how would one use an up or down arrow condition for the same break status point?

Example portion of the code for the upper break status.
plot UpperBandP = UpperBand;
UpperBandP.AssignValueColor (
if !ColoredMobo then Color.WHITE
else
if BreakStatus[0] == 2 then Color.green
else Color.red);

Thanks for any assistance.
 
markos

markos

Well-known member
VIP
@chillc15 The MOBO comes with Alerts and Arrows built in. That's the best I can direct you. Best of luck.

 
Top