Market Smith Indicators
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © adaml735

//@version=5


// This script's goal is to closely replicate the tools utilized in market smith
// Included in this script is:
//      21, 50, 200 day moving averages
//      RS line and indicator
//      High and Low pivot indicators

// An inportant note is that the moving averages and RS Line will only be visible in the day view


// Huge thank you to the following coders who I took inspiration from their open source code
// Fred6724, RaviYendru

// -----------------------------------------------------------------------------------------------------

// Global variables and indicators
indicator("Market Smith Indicators", overlay=true, max_labels_count=500, max_bars_back = 253)
isDaily = timeframe.isdaily

// -----------------------------------------------------------------------------------------------------

// High and low pivot point indicators
lengthGroupTitle = "LENGTH LEFT / RIGHT"
colorGroupTitle = "Text Color / Label Color"
leftLenH = 10
rightLenH = 10
textColorH = color.rgb(103, 255, 154)

leftLenL = 10
rightLenL = 10
textColorL = color.rgb(255, 153, 153)

ph = ta.pivothigh(leftLenH, rightLenH)
pl = ta.pivotlow(leftLenL, rightLenL)

drawLabel(_offset, _pivot, _style, _color, _textColor) =>
    if not na(_pivot)
        label.new(bar_index[_offset], _pivot, str.tostring(_pivot, format.mintick), style=_style, color=_color, textcolor=_textColor)

drawLabel(rightLenH, ph, label.style_label_down, color.rgb(0,0,0,100), textColorH)
drawLabel(rightLenL, pl, label.style_label_up, color.rgb(0,0,0,100), textColorL)

// -----------------------------------------------------------------------------------------------------

// 21, 50, 200 moving day averages
// Define variables
ma1 = ta.sma(close, 21)
ma2 = ta.sma(close, 50)
ma3 = ta.sma(close, 200)

sym1 = "21 Day MA"
sym2 = "50 Day MA"
sym3 = "200 Day MA" 

color1 = color.new(color.fuchsia, 0)
color2 = color.new(color.orange, 0)
color3 = color.new(color.green, 0)

// Plot moving averages
maPlot1 = plot(ma1, color=color1, title=sym1)
maPlot2 = plot(ma2, color=color2, title=sym2)
maPlot3 = plot(ma3, color=color3, title=sym3)

// Plot labels to the right of the moving averages
var l1 = isDaily ? label.new(bar_index, ma1, sym1, color = color.rgb(0,0,0,100), size=size.normal, textcolor=color1, style=label.style_label_left, textalign=text.align_left, yloc=yloc.price) : na
var l2 = isDaily ? label.new(bar_index, ma2, sym2, color = color.rgb(0,0,0,100), size=size.normal, textcolor=color2, style=label.style_label_left, textalign=text.align_left, yloc=yloc.price) : na
var l3 = isDaily ? label.new(bar_index, ma3, sym3, color = color.rgb(0,0,0,100), size=size.normal, textcolor=color3, style=label.style_label_left, textalign=text.align_left, yloc=yloc.price) : na

// set up new xy params to labels on new bar
label.set_xy(l1, bar_index, ma1)
label.set_xy(l2, bar_index, ma2)
label.set_xy(l3, bar_index, ma3)


// -----------------------------------------------------------------------------------------------------

// Simplified RS Line and RS Rating
// Thank you to ©Fred6724

// Inputs
hideRSRat   = false
// seedetail   = input(false, title="Display the 3 results", group = "Parameters", inline="0")
src         = close
comparativeTickerId = "SP:SPX"
SpxValue    = 3900//input(4140, title="Value of Comparative Symbol", group = "RS Line", tooltip = "Used to display the RS Line under the price. If you modify the ticker, please report its value in this box.")
colorRS     = color.rgb(120, 150, 255,0)
offset      = 80
plotNewHigh = false
rsNewHigh   = "RS New Highs"
blueDotCol  = color.rgb(38, 198, 218,60)
lookback    = 40
plotNewLow  = false
rsNewLow    = "RS New Lows"
redDotCol   = color.rgb(255, 82, 82, 60)
lookback2   = 40

// Constants for calculation of RS Rating
// SMA method
W1Ma        = 40
W2Ma        = 20
W3Ma        = 20
W4Ma        = 20
//Classic perf method
W1P         = 40
W2P         = 20
W3P         = 20
W4P         = 20
//Spx
spxW1Ma     = 40
spxW2Ma     = 20
spxW3Ma     = 20
spxW4Ma     = 20
// Final
w1          = 2
w2          = 1
w3          = 1
// Using bar index in case of IPO for avoiding NaN results
// Added max_bars_max = 253 to improve display speed
n63      = bar_index < 63  ? bar_index:63 
n126     = bar_index < 126 ? bar_index:126
n189     = bar_index < 189 ? bar_index:189
n252     = bar_index < 252 ? bar_index:252


// Comparative Ticker for RS Line
comparativeSymbol   = request.security(comparativeTickerId, timeframe.period, close)
// RS Line but multiplied by a little bit less than the constant value of the comparative ticker for correct display
rsCurve             = (src/comparativeSymbol)
rsRatio             = timeframe.isweekly ? SpxValue*(offset-10)/100:SpxValue*offset/100  // 70 We - 80 Da
rs                  = rsCurve*rsRatio
prevlookback  = lookback
prevlookback2 = lookback2 // for new low
lookback := math.min(lookback - 1, bar_index)
rsPlot = plot(rs, title="RS Line", style=plot.style_line, linewidth=1, color=colorRS)

// Historical New Highs & New Highs Before Price
histNH = ta.highest(rs  , prevlookback)
histCl = ta.highest(high, prevlookback)
// Historical RS New High
if(rsNewHigh == "Historical RS New Highs" and plotNewHigh and rs == histNH)
    label.new(x = bar_index, y = rs, color = blueDotCol, style = label.style_circle, size = size.tiny)
// Historical RS New High Before Price
if(rsNewHigh == "Historical RS New Highs  Before Price" and plotNewHigh and rs == histNH and high < histCl)
    label.new(x = bar_index, y = rs, color = blueDotCol, style = label.style_circle, size = size.tiny)
// RS New High
if(barstate.islast and rsNewHigh == "RS New Highs" and plotNewHigh and rs == histNH)
    label.new(x = bar_index, y = rs, color = blueDotCol, style = label.style_circle, size = size.tiny)
// RS New High Before Price
if(barstate.islast and rsNewHigh == "RS New Highs Before Price" and plotNewHigh and rs == histNH and high < histCl)
    label.new(x = bar_index, y = rs, color = blueDotCol, style = label.style_circle, size = size.tiny)


// Historical New Lows & New Lows Before Price
histNL  = ta.lowest(rs , prevlookback2)
histClL = ta.lowest(low, prevlookback2)
// Historical RS New Low
if(rsNewLow == "Historical RS New Lows" and plotNewLow and rs == histNL)
    label.new(x = bar_index, y = rs, color = redDotCol, style = label.style_circle, size = size.tiny)
// Historical RS New Low Before Price
if(rsNewLow == "Historical RS New Lows  Before Price" and plotNewLow and rs == histNL and low > histClL)
    label.new(x = bar_index, y = rs, color = redDotCol, style = label.style_circle, size = size.tiny)
// RS New Low
if(barstate.islast and rsNewLow == "RS New Lows" and plotNewLow and rs == histNL)
    labelNL   = label.new(x = bar_index, y = rs, color = redDotCol, style = label.style_circle, size = size.tiny)
// RS New Low Before Price
if(barstate.islast and rsNewLow == "RS New Lows Before Price" and plotNewLow and rs == histNL and low > histClL)
    labelNLBP = label.new(x = bar_index, y = rs, color = redDotCol, style = label.style_circle, size = size.tiny)

// 1ST METHOD
// Tickers I will use
// MMTH - %Stock > 200 Da SMA
// MMOF - %Stock > 150 Da SMA
// MMOH - %Stock > 100 Da SMA
// MMFI - %Stock > 50 Da SMA
// MMTW - %Stock > 20 Da SMA
// MMFD - %Stock > 5 Da SMA (more or less only noise, I won't use the 5 Daily SMA)

//                 |Formula                     | Here I use this code to limite 75% up and 25% down regarding number of stock above SMA X
limitDown = 25                               // | This limitation will allow me to calculate a theorical max & min to limit the result to 99 & 1
limitUp   = 75
perStockAbove200 = request.security("MMTH", 'D', close) > limitUp ? limitUp:request.security("MMTH", 'D', close) < limitDown ? limitDown:request.security("MMTH", 'D', close)
perStockAbove150 = request.security("MMOF", 'D', close) > limitUp ? limitUp:request.security("MMOF", 'D', close) < limitDown ? limitDown:request.security("MMOF", 'D', close)
perStockAbove100 = request.security("MMOH", 'D', close) > limitUp ? limitUp:request.security("MMOH", 'D', close) < limitDown ? limitDown:request.security("MMOH", 'D', close)
perStockAbove50  = request.security("MMFI", 'D', close) > limitUp ? limitUp:request.security("MMFI", 'D', close) < limitDown ? limitDown:request.security("MMFI", 'D', close)
perStockAbove20  = request.security("MMTW", 'D', close) > limitUp ? limitUp:request.security("MMTW", 'D', close) < limitDown ? limitDown:request.security("MMTW", 'D', close)

// The goal is to gather as much data as possible as we can't compare the score relatively to every other ticker. We do an approximation based on SMA and % of stock above them at X moment.
closeDa = request.security(syminfo.tickerid, 'D', close)
// SMA Declaration based on SMA Daily on the ticker we're watching
sma200 = request.security(syminfo.tickerid, 'D', ta.sma(closeDa,200))
sma150 = request.security(syminfo.tickerid, 'D', ta.sma(closeDa,150))
sma100 = request.security(syminfo.tickerid, 'D', ta.sma(closeDa,100))
sma50  = request.security(syminfo.tickerid, 'D', ta.sma(closeDa,50))
sma20  = request.security(syminfo.tickerid, 'D', ta.sma(closeDa,20))
// Daily Close SPX500
spxCloseDa = request.security(comparativeTickerId, 'D', close)
// We save if we were above dedicated moving averages in a boolean variable
// Reference point ticker
bCloseAbove200 = closeDa > sma200 ? 1:0
bCloseAbove150 = closeDa > sma150 ? 1:0
bCloseAbove100 = closeDa > sma100 ? 1:0
bCloseAbove50  = closeDa > sma50  ? 1:0
bCloseAbove20  = closeDa > sma20  ? 1:0
// Refence 63 days back (3 months)
bClose63Above200 = closeDa[n63] > sma200[n63] ? 1:0
bClose63Above150 = closeDa[n63] > sma150[n63] ? 1:0
bClose63Above100 = closeDa[n63] > sma100[n63] ? 1:0
bClose63Above50  = closeDa[n63] > sma50[n63]  ? 1:0
bClose63Above20  = closeDa[n63] > sma20[n63]  ? 1:0
// Refence 126 days back (6 months)
bClose126Above200 = closeDa[n126] > sma200[n126] ? 1:0
bClose126Above150 = closeDa[n126] > sma150[n126] ? 1:0
bClose126Above100 = closeDa[n126] > sma100[n126] ? 1:0
bClose126Above50  = closeDa[n126] > sma50[n126]  ? 1:0
bClose126Above20  = closeDa[n126] > sma20[n126]  ? 1:0
// Refence 189 days back (9 months)
bClose189Above200 = closeDa[n189] > sma200[n189] ? 1:0
bClose189Above150 = closeDa[n189] > sma150[n189] ? 1:0
bClose189Above100 = closeDa[n189] > sma100[n189] ? 1:0
bClose189Above50  = closeDa[n189] > sma50[n189]  ? 1:0
bClose189Above20  = closeDa[n189] > sma20[n189]  ? 1:0
// Refence 252 days back (12 months)
bClose252Above200 = closeDa[n252] > sma200[n252] ? 1:0
bClose252Above150 = closeDa[n252] > sma150[n252] ? 1:0
bClose252Above100 = closeDa[n252] > sma100[n252] ? 1:0
bClose252Above50  = closeDa[n252] > sma50[n252]  ? 1:0
bClose252Above20  = closeDa[n252] > sma20[n252]  ? 1:0
// Calculation based on the formula: RS Score = 40% * P3 + 20% * P6 + 20% * P9 + 20% * P12
// I choosed to calculate like this: if we were above this moving average when only 20% of stock were above, we get 1/0.20 = higher score because it is more noticeable.
// The same when we are below the moving average whereas 80% of stocks are above, we loose the same amont with the formula 1/(1-0.8)
// 0 MONTHS RS
zeroMonthSma200Weight = bCloseAbove200 ? 100/(perStockAbove200):-100/(100-perStockAbove200)
zeroMonthSma150Weight = bCloseAbove150 ? 100/(perStockAbove150):-100/(100-perStockAbove150)
zeroMonthSma100Weight = bCloseAbove100 ? 100/(perStockAbove100):-100/(100-perStockAbove100)
zeroMonthSma50Weight  = bCloseAbove50  ? 100/(perStockAbove50 ):-100/(100-perStockAbove50 )
zeroMonthSma20Weight  = bCloseAbove20  ? 100/(perStockAbove20 ):-100/(100-perStockAbove20 )
zeroMonthWeight       = zeroMonthSma200Weight + zeroMonthSma150Weight + zeroMonthSma100Weight + zeroMonthSma50Weight + zeroMonthSma20Weight
// 3 MONTHS RS 
threeMonthSma200Weight = bClose63Above200 ? 100/(perStockAbove200[n63]):-100/(100-perStockAbove200[n63])
threeMonthSma150Weight = bClose63Above150 ? 100/(perStockAbove150[n63]):-100/(100-perStockAbove150[n63])
threeMonthSma100Weight = bClose63Above100 ? 100/(perStockAbove100[n63]):-100/(100-perStockAbove100[n63])
threeMonthSma50Weight  = bClose63Above50  ? 100/(perStockAbove50[n63] ):-100/(100-perStockAbove50[n63] )
threeMonthSma20Weight  = bClose63Above20  ? 100/(perStockAbove20[n63] ):-100/(100-perStockAbove20[n63] )
threeMonthWeight       = threeMonthSma200Weight + threeMonthSma150Weight + threeMonthSma100Weight + threeMonthSma50Weight + threeMonthSma20Weight
// 6 MONTHS RS
sixMonthSma200Weight = bClose126Above200 ? 100/(perStockAbove200[n126]):-100/(100-perStockAbove200[n126]) 
sixMonthSma150Weight = bClose126Above150 ? 100/(perStockAbove150[n126]):-100/(100-perStockAbove150[n126])
sixMonthSma100Weight = bClose126Above100 ? 100/(perStockAbove100[n126]):-100/(100-perStockAbove100[n126])
sixMonthSma50Weight  = bClose126Above50  ? 100/(perStockAbove50[n126] ):-100/(100-perStockAbove50[n126] )
sixMonthSma20Weight  = bClose126Above20  ? 100/(perStockAbove20[n126] ):-100/(100-perStockAbove20[n126] )
sixMonthWeight       = sixMonthSma200Weight + sixMonthSma150Weight + sixMonthSma100Weight + sixMonthSma50Weight + sixMonthSma20Weight
// 9 MONTH RS
nineMonthSma200Weight = bClose189Above200 ? 100/(perStockAbove200[n189]):-100/(100-perStockAbove200[n189])   
nineMonthSma150Weight = bClose189Above150 ? 100/(perStockAbove150[n189]):-100/(100-perStockAbove150[n189])
nineMonthSma100Weight = bClose189Above100 ? 100/(perStockAbove100[n189]):-100/(100-perStockAbove100[n189])
nineMonthSma50Weight  = bClose189Above50  ? 100/(perStockAbove50[n189] ):-100/(100-perStockAbove50[n189] )
nineMonthSma20Weight  = bClose189Above20  ? 100/(perStockAbove20[n189] ):-100/(100-perStockAbove20[n189] )
nineMonthWeight       = nineMonthSma200Weight + nineMonthSma150Weight + nineMonthSma100Weight + nineMonthSma50Weight + nineMonthSma20Weight
// 12 MONTH RS
twelveMonthSma200Weight = bClose252Above200 ? 100/(perStockAbove200[n252]):-100/(100-perStockAbove200[n252])
twelveMonthSma150Weight = bClose252Above150 ? 100/(perStockAbove150[n252]):-100/(100-perStockAbove150[n252])
twelveMonthSma100Weight = bClose252Above100 ? 100/(perStockAbove100[n252]):-100/(100-perStockAbove100[n252])
twelveMonthSma50Weight  = bClose252Above50  ? 100/(perStockAbove50[n252] ):-100/(100-perStockAbove50[n252] )
twelveMonthSma20Weight  = bClose252Above20  ? 100/(perStockAbove20[n252] ):-100/(100-perStockAbove20[n252] )
twelveMonthWeight       = twelveMonthSma200Weight + twelveMonthSma150Weight + twelveMonthSma100Weight + twelveMonthSma50Weight + twelveMonthSma20Weight
// IBD's Formula for score without border (used to apply the cross product)
scoreWithoutBorder        =  W1Ma * (zeroMonthWeight + threeMonthWeight) + W2Ma * sixMonthWeight + W3Ma * nineMonthWeight + W4Ma * twelveMonthWeight
// Calculation of theorical max and min scores (Truncated because results are very very arround 50-60 otherwise)
// (The real formula of maxScore should be   maxScore =  W1Ma * (5*2*100/limitDown) + P2ma * (5*3*100/limitDown)  )
maxScore =  W1Ma * (2*100/limitDown) + W2Ma * (100/limitDown) + W3Ma * (100/limitDown) + W4Ma * (100/limitDown)
minScore = -(W1Ma * (2*100/(100-limitUp)) + W2Ma * (100/(100-limitUp)) +  W3Ma * (100/(100-limitUp)) + W4Ma * (100/(100-limitUp)) )
// Formula for score without border adjusted (for the min value to be equals 1)
adjustedScoreWithoutBorder = scoreWithoutBorder - minScore + 1
adjustedMaxScore           = maxScore - minScore +1
adjustedMinScore           = minScore - minScore +1
// Formula for score with border (cross product) - Result should not be greater than 99 and lower than 1 to this point
rsRating1 = math.round((adjustedScoreWithoutBorder)*99/(adjustedMaxScore-adjustedMinScore))
// Rendering the result (results are mainly distributed at the middle so to get a better result I try to get a wider range by adding to good and removing to bad one)
// Again results are distributed arround 1 to 75 so to get something linear I add to the score proportionally with their distance with 50 (only for better scores)
if(rsRating1>=50)
    truncate = (rsRating1-50)/2
    rsRating1 := math.round(rsRating1 + truncate)
if(rsRating1>99)
    rsRating1 := 99
if(rsRating1<1)
    rsRating1 := 1

// 2nd METHOD - No modification except limitation to 100% to master the limit and fix it further to 99 and 1 (and also because -100 is the max)
// Relative strength IBD style -> Initial Calculation against itslef
limitPerf = 2  // +/- 100% limitation
ThreeMthRS  = (closeDa/closeDa[n63])
if(closeDa < closeDa[n63])
    ThreeMthRS := -(1/ThreeMthRS) // to remove the same score than if this is a positive move
if(ThreeMthRS > limitPerf)
    ThreeMthRS := limitPerf
if(ThreeMthRS < -limitPerf)
    ThreeMthRS := -limitPerf
SixMthRS    = (closeDa/closeDa[n126])
if(closeDa < closeDa[n126])
    SixMthRS := -(1/SixMthRS)
if(SixMthRS > limitPerf)
    SixMthRS := limitPerf
if(SixMthRS < -limitPerf)
    SixMthRS := -limitPerf
NineMthRS   = (closeDa/closeDa[n189])
if(closeDa < closeDa[n189])
    NineMthRS := -(1/NineMthRS)
if(NineMthRS > limitPerf)
    NineMthRS := limitPerf
if(NineMthRS < -limitPerf)
    NineMthRS := -limitPerf
TwelveMthRS = (closeDa/closeDa[n252])
if(closeDa < closeDa[n252])
    TwelveMthRS := -(1/TwelveMthRS)
if(TwelveMthRS > limitPerf)
    TwelveMthRS := limitPerf
if(TwelveMthRS < -limitPerf)
    TwelveMthRS := -limitPerf
// Calculation of theorical max and min scores
maxScore2 = limitPerf*W1P + limitPerf*W2P + limitPerf*W3P + limitPerf*W4P
minScore2 = -limitPerf*W1P - limitPerf*W2P - limitPerf*W3P - limitPerf*W4P
// Calulation of Score
RSraw = W1P * ThreeMthRS + W2P * SixMthRS + W3P * NineMthRS + W4P * TwelveMthRS
// Adjustment (used to apply the cross product)
adjustedPerfScoreWithoutBorder = RSraw - minScore2 + 1
adjustedPerfMaxScore           = maxScore2 - minScore2 + 1
adjustedPerfMinScore           = minScore2 - minScore2 + 1
// Formula for score with border (cross product)
rsRating2 = math.round((adjustedPerfScoreWithoutBorder)*99/(adjustedPerfMaxScore-adjustedPerfMinScore))
// Rendering the result
if(rsRating2>=50)
    truncate = (rsRating2-50)/2
    rsRating2 := math.round(rsRating2 + truncate)
if(rsRating2>99)
    rsRating2 := 99
if(rsRating2<1)
    rsRating2 := 1



// 3RD METHOD
// I was running the average of both precedent results and... I found it was actually not that bad!
// But something was missing, a score for relative strenght against the SPX500.
// Let's do it
// Here I wanted to compare perf of ticker vs perf of spx500
// Limited at 100% of original calculation (I use a limit to determine maxscore and minscore and not go above 99 or under 1)
perfTicker63  = closeDa/closeDa[n63]
perfComp63    = spxCloseDa/spxCloseDa[n63]
perfTicker126 = closeDa/closeDa[n126]
perfComp126   = spxCloseDa/spxCloseDa[n126]
perfTicker189 = closeDa/closeDa[n189]
perfComp189   = spxCloseDa/spxCloseDa[n189]
perfTicker252 = closeDa/closeDa[n252]
perfComp252   = spxCloseDa/spxCloseDa[n252]
// Calculation of relative/comparative performance
limiteComp = 2 // +/- 100% limitation
spxThreeMthRS  = ( perfTicker63/perfComp63 )
if(perfTicker63 < perfComp63)
    spxThreeMthRS := -(1/spxThreeMthRS)
if(spxThreeMthRS > limiteComp)
    spxThreeMthRS := limiteComp
if(spxThreeMthRS < -limiteComp)
    spxThreeMthRS := -limiteComp
spxSixMthRS    = ( perfTicker126/perfComp126 )
if(perfTicker126 < perfComp126)
    spxSixMthRS := -(1/spxSixMthRS)
if(spxSixMthRS > limiteComp)
    spxSixMthRS := limiteComp
if(spxSixMthRS < -limiteComp)
    spxSixMthRS := -limiteComp
spxNineMthRS   = (perfTicker189/perfComp189)
if(perfTicker189 < perfComp189)
    spxNineMthRS := -(1/spxNineMthRS)
if(spxNineMthRS > limiteComp)
    spxNineMthRS := limiteComp
if(spxNineMthRS < -limiteComp)
    spxNineMthRS := -limiteComp
spxTwelveMthRS = ( perfTicker252/perfComp252 )
if(perfTicker252 < perfComp252)
    spxTwelveMthRS := -(1/spxTwelveMthRS)
if(spxTwelveMthRS > limiteComp)
    spxTwelveMthRS := limiteComp
if(spxTwelveMthRS < -limiteComp)
    spxTwelveMthRS := -limiteComp
// Calculation of theorical max and min scores
spxMaxScore2 = limiteComp*spxW1Ma + limiteComp*spxW2Ma + limiteComp*spxW3Ma + limiteComp*spxW4Ma
spxMinScore2 = -limiteComp*spxW1Ma - limiteComp*spxW2Ma - limiteComp*spxW3Ma - limiteComp*spxW4Ma
// Calulation of Score
spxRSraw = spxW1Ma * spxThreeMthRS + spxW2Ma * spxSixMthRS + spxW3Ma * spxNineMthRS + spxW4Ma * spxTwelveMthRS
// Adjustment (used to apply the cross product)
spxAdjustedPerfScoreWithoutBorder = spxRSraw - spxMinScore2 + 1
spxAdjustedPerfMaxScore           = spxMaxScore2 - spxMinScore2 + 1
spxAdjustedPerfMinScore           = spxMinScore2 - spxMinScore2 + 1
// Formula for score with border (cross product)
rsRating3 = math.round((spxAdjustedPerfScoreWithoutBorder)*99/(spxAdjustedPerfMaxScore-spxAdjustedPerfMinScore))
// Rendering the result
if(rsRating3>99)
    rsRating3 := 99
if(rsRating3<1)
    rsRating3 := 1
// Combination of both systems (w1, w2, are weight to give to the 3 methods)
float totalRsRating = math.round((w1 * rsRating1 + w2 * rsRating2 + w3 * rsRating3) / (w1 + w2 + w3))  // Combining the 3 methods

// Score adjustment based on observation among vast amount of examples against IBD's ranking
// This is handiwork, if you want to work on improving the code you should remove this part
if(rsRating3<45 and rsRating3<rsRating1 and rsRating3<rsRating2) // When we have a great historic score, a great performance but a poor relative strenght, most of the time the rating decrease
    totalRsRating := math.round((w2 * rsRating2 + w3 * rsRating3) / (w2 + w3))
if(rsRating2>80 and rsRating1<70 and rsRating3>=68)// Many time when the stock is beaten down but have a huge momentum, this rating is down 20-30 points.
    totalRsRating := rsRating2-1                   // so we modify the score in this case to take into consideration only the RS Score which is usually not that bad alone at this moment
if(rsRating2>=59 and rsRating1<=30 and rsRating3>=50)// Many time when the stock is beaten down but have a huge/correct momentum, this rating is down 20-30 points.
    totalRsRating := rsRating2-1                     // And very often the RsRating is the closer to the final result
if(rsRating1>=80 and rsRating2>=49 and rsRating2<=65 and rsRating3<=45 and rsRating3>=33 and rsRating2-rsRating3>=6) // Sometimes when rsRating 2 & 3 are in between a given range, results seems OK. Exception here
    totalRsRating := math.round((w1 * rsRating1 + w2 * rsRating2 + w3 * rsRating3) / (w1 + w2 + w3))            // due to the first adjustment but still the first enhances and the second too
if(rsRating1 <= 5)
    totalRsRating := math.round((w2 * rsRating2 + w3 * rsRating3) / (w2 + w3))


// Display the RS Rating
// Results are only acceptable in Daily TimeFrame
labelText1 = "RS Rating"
if(isDaily == false)
    labelText1 := ""
labelText2 = "\n\n"+str.tostring(totalRsRating,"#0")
if(isDaily)
    labelText2 := "\n\n"+str.tostring(totalRsRating,"#0")
else
    labelText2 := ""
label1 = (hideRSRat == false) and barstate.islast ? label.new(bar_index, rs, text=labelText1 , color = color.rgb(0,0,0,100), size=size.normal, textcolor=colorRS, style=label.style_label_left, textalign=text.align_left, yloc=yloc.price) : na
label2 = (hideRSRat == false) and barstate.islast ? label.new(bar_index, rs, text=labelText2 , color = color.rgb(0,0,0,100), size=size.large, textcolor=colorRS, style=label.style_label_left, textalign=text.align_left, yloc=yloc.price) : na

// Delete previous Labels (When new candle opens or when replay mode, the labels were piling on)
label.delete(label1[1])
label.delete(label2[1])

