Multi timeframe Stochastic RSI Screener by noop42
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © noop42

//@version=5
indicator('MTF StochRSI Screener & indicator by noop42', overlay=false)

// Input parameters
src = input(close, title='Source')
average_value = input.bool(title='Use average value mode (K+D/2)', defval=true, group='Options')
repainting = input.bool(title='Allow repaint ? (enable to get live values)', defval=true, group='Options')
show_screener = input.bool(title='Show Screener', defval=true, group='Options')
show_lines = input.bool(title='Show StochasticRSI lines ?', defval=true, group='Options')
color_mode = input.string(title='Color mode', options=["Binary", "Progressive"], defval="Progressive", group='Options')

tf1 = input.timeframe(title='Timeframe 1', defval='1', group='Options')
tf2 = input.timeframe(title='Timeframe 2', defval='5', group='Options')
tf3 = input.timeframe(title='Timeframe 3', defval='15', group='Options')
tf4 = input.timeframe(title='Timeframe 4', defval='60', group='Options')

tf1_cvg_opt = input.bool(true, 'Include Timeframe #1 in convergence signals', group='Options')
tf2_cvg_opt = input.bool(true, 'Include Timeframe #2 in convergence signals', group='Options')
tf3_cvg_opt = input.bool(true, 'Include Timeframe #3 in convergence signals', group='Options')
tf4_cvg_opt = input.bool(false, 'Include Timeframe #4 in convergence signals', group='Options')

smoothKD = input.int(3, 'K & D smoothing', minval=1, group='Stoch RSI')
lengthRSI = input.int(14, 'RSI Length', minval=1, group='Stoch RSI')
lengthStoch = input.int(14, 'Stochastic Length', minval=1, group='Stoch RSI')
stoch_low = input.int(20, title='Stoch Oversold Level', group='Stoch RSI')
stoch_high = input.int(80, title='Stoch Overbought Level', group='Stoch RSI')
rsi_low = input.int(30, title='RSI Oversold Level', group='Stoch RSI')
rsi_high = input.int(70, title='RSI Overbought Level', group='Stoch RSI')

// Custom functions
rp_security(_symbol, _res, _src) =>
    request.security(_symbol, _res, _src[barstate.isrealtime ? repainting ? 0 : 1 : 0], gaps=barmerge.gaps_off)
    
get_movement(k, d) =>
    k > d ? 'Bull' : 'Bear'

show_drawings(data) =>
    show_lines ? data : na

color_value(value) =>
    step = (200/100.0)
    d = value * step
    g = value < 50 ? d : 127
    r = value < 50 ? 127: 200 - d
    color.rgb(math.round(r), math.round(g), 0, 0)

// MTF Stochastic RSI
rsi_tf1 = rp_security(syminfo.tickerid, tf1, ta.rsi(src, lengthRSI))
stoch_k_tf1 = rp_security(syminfo.tickerid, tf1, ta.sma(ta.stoch(rsi_tf1, rsi_tf1, rsi_tf1, lengthStoch), smoothKD))
stoch_d_tf1 = rp_security(syminfo.tickerid, tf1, ta.sma(stoch_k_tf1, smoothKD))

rsi_tf2 = rp_security(syminfo.tickerid, tf2, ta.rsi(src, lengthRSI))
stoch_k_tf2 = rp_security(syminfo.tickerid, tf2, ta.sma(ta.stoch(rsi_tf2, rsi_tf2, rsi_tf2, lengthStoch), smoothKD))
stoch_d_tf2 = rp_security(syminfo.tickerid, tf2, ta.sma(stoch_k_tf2, smoothKD))

rsi_tf3 = rp_security(syminfo.tickerid, tf3, ta.rsi(src, lengthRSI))
stoch_k_tf3 = rp_security(syminfo.tickerid, tf3, ta.sma(ta.stoch(rsi_tf3, rsi_tf3, rsi_tf3, lengthStoch), smoothKD))
stoch_d_tf3 = rp_security(syminfo.tickerid, tf3, ta.sma(stoch_k_tf3, smoothKD))

rsi_tf4 = rp_security(syminfo.tickerid, tf4, ta.rsi(src, lengthRSI))
stoch_k_tf4 = rp_security(syminfo.tickerid, tf4, ta.sma(ta.stoch(rsi_tf4, rsi_tf4, rsi_tf4, lengthStoch), smoothKD))
stoch_d_tf4 = rp_security(syminfo.tickerid, tf4, ta.sma(stoch_k_tf4, smoothKD))

avgtf1 = (stoch_k_tf1 + stoch_d_tf1) / 2
avgtf2 = (stoch_k_tf2 + stoch_d_tf2) / 2
avgtf3 = (stoch_k_tf3 + stoch_d_tf3) / 2
avgtf4 = (stoch_k_tf4 + stoch_d_tf4) / 2

tf1ob = avgtf1 > stoch_high
tf1os = avgtf1 < stoch_low
tf2ob = avgtf2 > stoch_high
tf2os = avgtf2 < stoch_low
tf3ob = avgtf3 > stoch_high
tf3os = avgtf3 < stoch_low
tf4ob = avgtf4 > stoch_high
tf4os = avgtf4 < stoch_low

rsi1ob = rsi_tf1 > rsi_high
rsi1os = rsi_tf1 < rsi_low
rsi2ob = rsi_tf2 > rsi_high
rsi2os = rsi_tf2 < rsi_low
rsi3ob = rsi_tf3 > rsi_high
rsi3os = rsi_tf3 < rsi_low
rsi4ob = rsi_tf4 > rsi_high
rsi4os = rsi_tf4 < rsi_low

// Screener
obColor = #1c701e
osColor = #a11806

tf1mov = get_movement(stoch_k_tf1, stoch_d_tf1)
tf2mov = get_movement(stoch_k_tf2, stoch_d_tf2)
tf3mov = get_movement(stoch_k_tf3, stoch_d_tf3)
tf4mov = get_movement(stoch_k_tf4, stoch_d_tf4)

tf1movColor = tf1mov == 'Bull' ? color.lime : color.red
tf2movColor = tf2mov == 'Bull' ? color.lime : color.red
tf3movColor = tf3mov == 'Bull' ? color.lime : color.red
tf4movColor = tf4mov == 'Bull' ? color.lime : color.red

tf1Color = color_mode == "Binary" ? (tf1ob ? obColor : tf1os ? osColor : tf1movColor) : color_value(avgtf1)
tf2Color = color_mode == "Binary" ? (tf2ob ? obColor : tf2os ? osColor : tf2movColor) : color_value(avgtf2)
tf3Color = color_mode == "Binary" ? (tf3ob ? obColor : tf3os ? osColor : tf3movColor) : color_value(avgtf3)
tf4Color = color_mode == "Binary" ? (tf4ob ? obColor : tf4os ? osColor : tf3movColor) : color_value(avgtf4)

tf1status = tf1ob ? 'Overbought' : tf1os ? 'Oversold' : 'OK'
tf2status = tf2ob ? 'Overbought' : tf2os ? 'Oversold' : 'OK'
tf3status = tf3ob ? 'Overbought' : tf3os ? 'Oversold' : 'OK'
tf4status = tf4ob ? 'Overbought' : tf4os ? 'Oversold' : 'OK'

tf1RSIColor = color_mode == "Binary" ? (rsi1ob ? obColor : rsi1os ? osColor : tf1movColor) : color_value(rsi_tf1)
tf2RSIColor = color_mode == "Binary" ? (rsi2ob ? obColor : rsi2os ? osColor : tf2movColor) : color_value(rsi_tf2)
tf3RSIColor = color_mode == "Binary" ? (rsi3ob ? obColor : rsi3os ? osColor : tf3movColor) : color_value(rsi_tf3)
tf4RSIColor = color_mode == "Binary" ? (rsi4ob ? obColor : rsi4os ? osColor : tf4movColor) : color_value(rsi_tf4)

os_convergence = (tf1_cvg_opt ? tf1os : true) and (tf2_cvg_opt ? tf2os : true) and (tf3_cvg_opt ? tf3os : true) and (tf4_cvg_opt ? tf4os : true)
ob_convergence = (tf1_cvg_opt ? tf1ob : true) and (tf2_cvg_opt ? tf2ob : true) and (tf3_cvg_opt ? tf3ob : true) and (tf4_cvg_opt ? tf4ob : true)

rsi_ob_convergence = (tf1_cvg_opt ? rsi1ob : true) and (tf2_cvg_opt ? rsi2ob : true) and (tf3_cvg_opt ? rsi3ob : true) and (tf4_cvg_opt ? rsi4ob : true)
rsi_os_convergence = (tf1_cvg_opt ? rsi1os : true) and (tf2_cvg_opt ? rsi2os : true) and (tf3_cvg_opt ? rsi3os : true) and (tf4_cvg_opt ? rsi4os : true)

default_bg = #cccccc

var tbl = table.new(position.bottom_right, 6, 6)
if show_screener
    if barstate.islast
        table.cell(tbl, 0, 0, 'TimeFrame', bgcolor=default_bg)
        table.cell(tbl, 1, 0, 'K', bgcolor=default_bg)
        table.cell(tbl, 2, 0, 'D', bgcolor=default_bg)
        table.cell(tbl, 3, 0, 'RSI', bgcolor=default_bg)
        table.cell(tbl, 4, 0, 'Movement', bgcolor=default_bg)
        table.cell(tbl, 5, 0, 'StochRSI Status', bgcolor=default_bg)

        table.cell(tbl, 0, 1, tf1 + (tf1_cvg_opt ? '*' : ''), bgcolor=default_bg)
        table.cell(tbl, 1, 1, str.tostring(stoch_k_tf1, '#.##'), bgcolor=tf1Color)
        table.cell(tbl, 2, 1, str.tostring(stoch_d_tf1, '#.##'), bgcolor=tf1Color)
        table.cell(tbl, 3, 1, str.tostring(rsi_tf1, '#.##'), bgcolor=tf1RSIColor)
        table.cell(tbl, 4, 1, tf1mov, bgcolor=tf1movColor)
        table.cell(tbl, 5, 1, tf1status, bgcolor=tf1Color)

        table.cell(tbl, 0, 2, tf2 + (tf2_cvg_opt ? '*' : ''), bgcolor=default_bg)
        table.cell(tbl, 1, 2, str.tostring(stoch_k_tf2, '#.##'), bgcolor=tf2Color)
        table.cell(tbl, 2, 2, str.tostring(stoch_d_tf2, '#.##'), bgcolor=tf2Color)
        table.cell(tbl, 3, 2, str.tostring(rsi_tf2, '#.##'), bgcolor=tf2RSIColor)
        table.cell(tbl, 4, 2, tf2mov, bgcolor=tf2movColor)
        table.cell(tbl, 5, 2, tf2status, bgcolor=tf2Color)

        table.cell(tbl, 0, 3, tf3 + (tf3_cvg_opt ? '*' : ''), bgcolor=default_bg)
        table.cell(tbl, 1, 3, str.tostring(stoch_k_tf3, '#.##'), bgcolor=tf3Color)
        table.cell(tbl, 2, 3, str.tostring(stoch_d_tf3, '#.##'), bgcolor=tf3Color)
        table.cell(tbl, 3, 3, str.tostring(rsi_tf3, '#.##'), bgcolor=tf3RSIColor)
        table.cell(tbl, 4, 3, tf3mov, bgcolor=tf3movColor)
        table.cell(tbl, 5, 3, tf3status, bgcolor=tf3Color)

        table.cell(tbl, 0, 4, tf4 + (tf4_cvg_opt ? '*' : ''), bgcolor=default_bg)
        table.cell(tbl, 1, 4, str.tostring(stoch_k_tf4, '#.##'), bgcolor=tf4Color)
        table.cell(tbl, 2, 4, str.tostring(stoch_d_tf4, '#.##'), bgcolor=tf4Color)
        table.cell(tbl, 3, 4, str.tostring(rsi_tf4, '#.##'), bgcolor=tf4RSIColor)
        table.cell(tbl, 4, 4, tf4mov, bgcolor=tf4movColor)
        table.cell(tbl, 5, 4, tf4status, bgcolor=tf4Color)

        // Warning convergence alerts
        srsi_warning_message = os_convergence ? 'SRSI OS convergence' : ob_convergence ? 'SRSI OB convergence' : 'No SRSI warning'
        srsi_warning_color = os_convergence ? color.lime : ob_convergence ? color.red : default_bg
        rsi_warning_message = rsi_os_convergence ? 'RSI OS convergence' : rsi_ob_convergence ? 'RSI OB convergence' : 'No RSI warning'
        rsi_warning_color = rsi_os_convergence ? color.lime : rsi_ob_convergence ? color.red : default_bg

        table.cell(tbl, 0, 5, 'Warnings', bgcolor=color.orange)
        table.cell(tbl, 1, 5, srsi_warning_message, bgcolor=srsi_warning_color)
        table.cell(tbl, 2, 5, rsi_warning_message, bgcolor=rsi_warning_color)

// Oscillators
// Zones lines
ob_zone_color = #eb500e10
os_zone_color = #24fc0310
invisible = #00000000

h0 = hline(show_drawings(stoch_high), 'Upper Band', color=ob_zone_color)
hmid = hline(show_drawings(50), 'Middle Band', color=#ffffff45)
h1 = hline(show_drawings(stoch_low), 'Lower Band', color=os_zone_color)
hmax_display = hline(show_drawings(110), color=invisible)
hmin_display = hline(show_drawings(-10), color=invisible)
obZone = hline(show_drawings(stoch_high), color=invisible)
osZone = hline(show_drawings(stoch_low), color=invisible)
hmax = hline(show_drawings(100), color=ob_zone_color)
hmin = hline(show_drawings(0), color=os_zone_color)

fill(hmax, obZone, color=ob_zone_color, transp=90)
fill(hmin, osZone, color=os_zone_color, transp=90)

// Average mode
plot(show_drawings(average_value) ? avgtf1 : na, 'SRSI tf1 (avg mode)', color=color_mode == "Binary" ? tf1movColor: tf1Color, linewidth=1, transp=25)
plot(show_drawings(average_value) ? avgtf2 : na, 'SRSI tf2 (avg mode)', color=color_mode == "Binary" ? tf2movColor : tf2Color, linewidth=2, transp=25)
plot(show_drawings(average_value) ? avgtf3 : na, 'SRSI tf3 (avg mode)', color=color_mode == "Binary" ? tf3movColor : tf3Color, linewidth=4, transp=25)
plot(show_drawings(average_value) ? avgtf4 : na, 'SRSI tf4 (avg mode)', color=color_mode == "Binary" ? tf4movColor : tf4Color, linewidth=6, transp=25)

// Classic mode
plot(average_value ? na : stoch_k_tf1, 'K #1 (classic mode)', color=color.new(color.aqua, 0), linewidth=1)
plot(average_value ? na : stoch_d_tf1, 'D #1 (classic mode)', color=color.new(color.navy, 0), linewidth=1)
plot(average_value ? na : stoch_k_tf2, 'K #2 (classic mode)', color=color.new(color.lime, 0), linewidth=2)
plot(average_value ? na : stoch_d_tf2, 'D #2 (classic mode)', color=color.new(color.green, 0), linewidth=2)
plot(average_value ? na : stoch_k_tf3, 'K #3 (classic mode)', color=color.new(color.yellow, 0), linewidth=3)
plot(average_value ? na : stoch_d_tf3, 'D #3 (classic mode)', color=color.new(color.orange, 0), linewidth=3)
plot(average_value ? na : stoch_k_tf4, 'K #4 (classic mode)', color=color.new(color.fuchsia, 0), linewidth=4)
plot(average_value ? na : stoch_d_tf4, 'D #4 (classic mode)', color=color.new(color.purple, 0), linewidth=4)

// Shapes
plotshape(show_drawings(os_convergence) ? 1 : 0, color=color.new(color.lime, 0), location=location.bottom, size=size.tiny, style=shape.triangleup, title='Bullish movement')
plotshape(show_drawings(ob_convergence) ? 1 : 0, color=color.new(color.red, 0), location=location.top, size=size.tiny, style=shape.triangledown, title='Bearish movement')

