#RS_Rank - 8/28/2019 Developed by GHorschman ([email protected])
# This is a custom quote to compute the Relative Strength percentile.
# It is calculated the same way that IV_Percentile is computed. Just
# change the length to specify the time frame of interest. The
# background color is tied to the following ranges:
#
# RS_Rank > 80 -- Dark Green
# 80 <= RS_Rank < 60 -- Light Green
# 60 <= RS_Rank < 40 -- Gray
# 40 <= RS_Rank < 20 -- Light Red
# RS_Rank <= 20 -- Dark Red
######################################################################
# Set length to period of interest.
# 1 Wk – 5 trading days
# 1 Mos – 21 Days
# 3 Mos – 63 Days
# 6 Mos – 126 Days
# 12 Mos – 252 Days
def length = 10;
#def RS = if IsNan(relativeStrength("SPX")) then 0 else relativeStrength("SPX") ;
def RS = relativeStrength("SPX");
def RSLow = Lowest(RS, length);
def RSHigh = Highest(RS, length);
def RSRank = round(100 * (RS - RSLow) / (RSHigh - RsLow),1);
addlabel (yes,RSRank);
#AddLabel (yes, if RSRank >= 1 and RSRank < 100 then "000" + astext(RSRank) else astext( RSRank) );
assignbackgroundcolor (if RSRank > 80 then color.dark_green else
if RSRank > 60 and RSRank <= 80 then createcolor(0,175,0) else
if RSRank > 40 and RSRank <= 60 then color.gray else
if RSRank > 20 and RSRank <= 40 then CreateColor(220, 0,0) else
if RSRank <= 20 then CreateColor(150, 0,0) else
color.white);
ah got it, thank you I also had to remove the labels@ReyHak You need to edit the RSRank not the RS. It's a few lines below.
#RS_Rank - 8/28/2019 Developed by GHorschman ([email protected])
#######################################################################
Done, thank you@ReyHak @BenTen Above in post #83, the header was stripped out. We always do our best to leave the header intact to give credit where it is due.
Please edit the post above with these two lines:
Thank you, MarkosCode:#RS_Rank - 8/28/2019 Developed by GHorschman ([email protected]) #######################################################################
# SMO_RsRank.ts
# 2021-01-21
# Added comparison against a broad market index and ranks from 1 to 99
# O'Neil price performance RS ranking
# WTF_Dude
# 5.5.20
# color styling codes from #WLC_RS1Yr RS_Rank by GHorschman
# `
# RS_Rank > 80 -- Dark Green
# 80 <= RS_Rank < 60 -- Light Green
# 60 <= RS_Rank < 40 -- Gray
# 40 <= RS_Rank < 20 -- Light Red
# RS_Rank <= 20 -- Dark Red
######################################################################
script wtf_dude_rsrank {
# Set length to period of interest.
input len1 = 63;
input len2 = 126;
input len3 = 189;
input len4 = 252;
input cl = close;
def year = if cl-cl[len4] is less than 0 then 0 else cl-cl[len4] ;
def nine = if cl-cl[len3] is less than 0 then 0 else cl-cl[len3] ;
def six = if cl-cl[len2] is less than 0 then 0 else cl-cl[len2] ;;
def three = if cl-cl[len1] is less than 0 then 0 else cl-cl[len1] ;;
def weighted = if ((2*three) + six + nine + year)/4 is less than 0 then 0 else ((2*three + six + nine + year)/4); #decimal
def h = highest(high, len4);
def l = lowest(low, len4);
def hilo = absvalue(h-l);
def calc = weighted/ hilo;
plot rsrank = round(100* calc,0);
#addlabel (yes,RSRank);
}
# 1 Wk – 5 trading days
# 1 Mos – 21 Days
# 3 Mos – 63 Days
# 6 Mos – 126 Days
# 12 Mos – 252 Days
def len1 = 63;
def len2 = 126;
def len3 = 189;
def len4 = 252;
def stock_rsrank = wtf_dude_rsrank(len1, len2, len3, len4, close);
def index_rsrank = wtf_dude_rsrank(len1, len2, len3, len4, close("SPX"));
def RS = stock_rsrank/index_rsrank;
def HHData = HighestAll(RS);
def LLData = LowestAll(RS);
plot nr = (( 98 * ( RS - LLData )) / ( HHData - LLData )) + 1;
nr.hide();
#AddLabel(yes, Concat("RS Ranking: ", nr[0]), Color.WHITE);
AddLabel(yes, Concat("RS Ranking: ", round(nr[0], 0)),
if nr > 80 then color.dark_green else
if nr > 60 and nr <= 80 then createcolor(0,175,0) else
if nr > 40 and nr <= 60 then color.gray else
if nr > 20 and nr <= 40 then CreateColor(220, 0,0) else
if nr <= 20 then CreateColor(150, 0,0) else
color.white);
def h = highest(high, len4);
def l = lowest(low, len4);
def HHData = HighestAll(RS);
def LLData = LowestAll(RS);
to new code:
def HHData = Highest(RS, len4);
def LLData = Lowest(RS, len4);
#==============================================================================
# SMO_RsRank.ts: TOS script mimicking IBD Relative Strength Rank
# Version 1: 2021-01-24
# Calculated according to the following principles:
# The Relative Strength Rating is the result of calculating a stock’s
# percentage change of prices over the last 4 quarters:
# A 40% weight is assigned to the latest quarter period;
# the remaining three quarters each has 20% weight.
# The stock's price performance is compared w/ a general market index
# (e.g.SPX) to generate relative strength.
# It's intended to rate stocks in order of greatest price performance
# and assigned a percentile rank from 99 (highest) to 1 (lowest). A 50% rank
# indicates same price performance as the general market index.
#
# Two step usage procedure:
# 1). Get calibrated data first
# Create a custom scan by copying the code from the beginning to the
# the section marked as "End of Scan Code Section"
# Need to add a custom quote named as "IBD_RS" for sorting top and
# bottom scores
# 2). Input calibrated data
# Put the obtained data to the variables defined below the section
# named "Multipoint Calibration"
# There are 3 data points for this version and may be updated weekly
# or monthly, depending on your trading time frame.
# The prices used here are close prices and the quarter may be calendar
# quarter or other number of days if shorter term ranking is desired.
#==============================================================================
script my_rsrank {
# Set length to period of interest.
# Only total length of days is input and other periods are derived
input len4 = 252;
input cl = close;
def len1 = round(len4/4, 0); #63;
def len2 = len1 * 2; #126;
def len3 = len1 * 3; #189
# Calculate price change percentages per quarter
def p4q = (cl[len3]-cl[len4]) / cl[len4];
def p3q = (cl[len2]-cl[len3]) / cl[len3];
def p2q = (cl[len1]-cl[len2]) / cl[len2];
def p1q = (cl-cl[len1]) / cl[len1];
def weighted = ((2*p1q) + p2q + p3q + p4q) / 5;
plot rsrank = 100 * weighted;
}
# 1 Wk – 5 trading days
# 1 Mos – 21 Days
# 3 Mos – 63 Days
# 6 Mos – 126 Days
# 12 Mos – 252 Days
def len4 = 252;
# Use the following for 6 month period ranking
#def len4 = 126;
def stockCl = close;
def indexCl = close("SPX");
def stock_rsrank = my_rsrank(len4, stockCl);
#plot stockdbg = stock_rsrank;
def index_rsrank = my_rsrank(len4, indexCl);
#plot indexdbg = index_rsrank;
def index_rsrank1 = if (index_rsrank == 0, index_rsrank[1], index_rsrank);
def RS = stock_rsrank/index_rsrank1;
#------------------- Code required for Custom Quote in Scan Tab----------------
# Selectively uncomment the following code in scan tab
# The following RS scores as of today need to be adjusted in each periodical
# calibrations
# Possible RS scores for bottom 1%
#input rs_score = -1;
# Possible RS scores for top 1%
#input rs_score = 4.5;
# Possible RS scores for top 10%
#input rs_score = 2.8;
#plot scan = if rs_score <= 0 then rs < rs_score else
# rs > rs_score;
#---------------- End of Scan Code Section ------------------------------------
# Uncomment the following if display of relative strength is required
# Please select the option of left axis for this indicator
#plot rsCurve = rs;
#-------------------- Multipoint Calibration ----------------------------------
# Get the max & min values of RS for the reference index_rsrank (e.g. SPX)
# by using the TOS scan /w customized quote IBD_RS and sorting the results
# Max value is the min rs value of the top 5 (1%) stocks in the SP 500
# Min value is the max rs value of the bottom 5 (1%) stocks in the SP 500
# The calibration should be done weekly or at other time as necessary
# Replace the values below with the values obtained from custom quote
# RS score corresponding to 99 percentile
def HHData = 6.1;
# RS score corresponding to 1 percentile
def LLData = -1.1;
# Add a 90% calibration point since we are very interested at this percentile
# The RS score should be the score of top n'th stock,
# where n is the Total number of Index Stocks (e.g. 505 for SPX) x (100% - 90%)
# (e.g. 51 for SPX)
def d90 = 2.91;
#------------------- End of Calibration Data -----------------------------------
# For SPX & SPY, the RS score should be 1 and correlate to a 50 percentile rank
def d50 = 1;
def rsCalibrated = if rs > HHData then HHData else
if rs < LLData then LLData else
RS;
#plot dbgCal = rsCalibrated;
# Create final RS rank /w multiple point calibrated segments
# Formula for each segment:
# Segment RS Rank = [(End RS Rank - Start RS Rank) * (RScalibrated - Start RS)) /
# (End RS - Start RS)] + Start RS Rank
plot nr = # Segment: Start Rank: 1, End Rank: 50
if rsCalibrated <= 1 then
(( 49 * ( RScalibrated - LLData )) / ( d50 - LLData )) + 1
else
# Segment: Start Rank: 51, End Rank: 90
if rsCalibrated <= d90 then
(( 39 * ( RScalibrated - d50 )) / ( d90 - d50 )) + 51
# Segment: Start Rank: 91, End Rank: 99
else
(( 8 * ( RScalibrated - d90 )) / ( HHData - d90 )) + 91;
nr.hide();
# Color coding from top to bottom ranks:
# Bright Green -> Dark Green -> Grey -> Dark Red -> Bright Red
AddLabel(yes, Concat("RS Ranking: ", round(nr, 0)),
if nr > 80 then color.green else
if nr > 60 and nr <= 80 then color.dark_green else
if nr > 40 and nr <= 60 then color.gray else
if nr > 20 and nr <= 40 then color.red else
color.red) ;
# End of Code
Yes, this one is a bit more complicated, because of the need to find the 3 RS scores from the scan tab, in order to calculate the RS rank.This looks VERY neat, especially for those of us who have been pining for an IBD RS rank. But I am SO confused based on the provided directions...
You can reduce the value of 4.5 when the scan could not produce 5 stocks and increase the value when the scan produces too many number of stocks (e.g. over 50) for you to find the 5th one. Now sort the TOS scan results by IBD_RS (a custom quote added for this script) in a decreasing order, you can find the 5th stock is someone like DISA. Its IBD_RS score is 4.65.# Possible RS scores for top 1%
input rs_score = 4.5;
2). RS score corresponding to 1 percentiledef HHData = 4.65; # was 6.1;
The 5th lowest RS score may be NI or other stocks. If you find its IBD_RS score is -1.17. then, put this value into the variable below:# Possible RS scores for bottom 1%
input rs_score = -1;
3). Add a 90% calibration point since we are very interested at this percentiledef LLData = -1.17; #-1.1;
Make sure your scan results show all stocks satisfying the scan criteria by showing 100 or more stocks. Say you find the stock of the 50th (or 51th) highest RS value is NVDA and it has RS value of 3.07. Then, change the value of the following variable to 3.07 as shown below:# Possible RS scores for top 10%
input rs_score = 2.8;
# The RS score should be the score of top n'th stock,
# where n is the Total number of Index Stocks (e.g. 505 for SPX) x (100% - 90%)
# (e.g. 51 for SPX)
def d90 = 3.07; #2.91;
Join useThinkScript to post your question to a community of 21,000+ developers and traders.
Start a new thread and receive assistance from our community.
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.
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.