Stochastic RSI Heat Bollinger Bands
// 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("Stochastic RSI Heat Bollinger Bands", shorttitle="SRSI Heat BB", overlay=true)

// Functions
ma(source, length, type) =>
    type == "SMA" ? ta.sma(source, length) :
     type == "EMA" ? ta.ema(source, length) :
     type == "SMMA (RMA)" ? ta.rma(source, length) :
     type == "WMA" ? ta.wma(source, length) :
     type == "VWMA" ? ta.vwma(source, length) :
     na

invert_colors = input.bool(title="Invert colors", defval=false, group='Options')
color_value(value, transp=0) =>
    step = (255/100.0)
    d = value * step
    r = 0.0
    g = 0.0
    if invert_colors
        r := value < 50 ? d : 127
        g := value < 50 ? 127: 255 - d
    else
        g := value < 50 ? d : 127
        r := value < 50 ? 127: 255 - d       
    color.rgb(math.round(r), math.round(g), 0, transp)

// Inputs
show_screener = input.bool(title='Show Screener', defval=true, group='Options')

color_src = input.string(title="Color Source", options=["Stochastic RSI", "RSI"], defval="Stochastic RSI", group='Options')
fill_bb_heat = input.bool(title="Fill Bollinger bands with heat", defval=true, group='Options')
show_bb = input.bool(title="Show upper and lower lines", defval=true, group='Options')
show_bb_heat = input.bool(title="Color upper and lower bands with heat", defval=true, group='Options')
show_basis_heat = input.bool(title="Color basis line with heat", defval=true, group='Options')

length = input.int(20, minval=1, group="Bollinger Bands")
bb_src = input(close, title="Source", group="Bollinger Bands")
mult = input.float(2.0, minval=0.001, maxval=50, title="StdDev", group="Bollinger Bands")
offset = input.int(0, "Offset", minval = -500, maxval = 500, group="Bollinger Bands")
ma_type   = input.string("SMA", title="Moving average type", options=["SMA", "EMA", "SMMA (RMA)", "WMA", "VWMA"], group="Bollinger Bands")

show_over_signals = input.bool(true, "Show overbought/oversold diamonds", group='Stochastic RSI')
smoothK = input.int(3, "K", minval=1, group='Stochastic RSI')
smoothD = input.int(3, "D", minval=1, group='Stochastic RSI')
lengthRSI = input.int(14, "RSI Length", minval=1, group='Stochastic RSI')
lengthStoch = input.int(14, "Stochastic Length", minval=1, group='Stochastic RSI')
srsi_src = input(close, title="RSI Source", group='Stochastic RSI')

// Calculations BB
basis = ma(bb_src, length, ma_type)
dev = mult * ta.stdev(bb_src, length)
upper = basis + dev
lower = basis - dev

// Calculations SRSI
rsi = ta.rsi(srsi_src, lengthRSI)
k =  ta.sma(ta.stoch(rsi, rsi, rsi, lengthRSI), smoothK)
d = ta.sma(k, smoothD)
a = (k + d) / 2

// Plots
col = color_value(color_src == "RSI" ? rsi : a)
bands_col = show_bb ? (show_bb_heat ? col : color.green) : #00000000
basis_col = show_basis_heat ? col : color.blue
bg_col = color_value(color_src == "RSI" ? rsi : a, transp=(fill_bb_heat ? 70: 100))

plot(basis, "Basis", color=basis_col, offset = offset, linewidth=1)
p1 = plot(upper, "Upper", color=bands_col, offset = offset)
p2 = plot(lower, "Lower", color=bands_col, offset = offset)
fill(p1, p2, title = "Background", color=bg_col)

// Screener
sr_ob = a > 80
sr_os = a < 20
rsi_ob = a > 70
rsi_os = a < 30

srsi_status = sr_ob ? "Overbought" : sr_os ? "Oversold" : "OK"
rsi_status = rsi_ob ? "Overbought" : rsi_os ? "Oversold" : "OK"
ob = color_src == "RSI" ? rsi_ob : sr_ob
os = color_src == "RSI" ? rsi_os : sr_os

plotshape(show_over_signals and (ob or os) ? 1 : 0, style=shape.diamond, location=location.top, color=bg_col)

default_bg = #cccccc
var tbl = table.new(position.top_right, 6, 2)

if show_screener
    if barstate.islast
        table.cell(tbl, 0, 0, 'K', bgcolor=default_bg)
        table.cell(tbl, 1, 0, 'D', bgcolor=default_bg)
        table.cell(tbl, 2, 0, 'RSI', bgcolor=default_bg)
        table.cell(tbl, 3, 0, 'SR Status', bgcolor=default_bg)
        table.cell(tbl, 4, 0, 'RSI Status', bgcolor=default_bg)

        table.cell(tbl, 0, 1, str.tostring(k, '#.##'), bgcolor=col, text_color=color.white)
        table.cell(tbl, 1, 1, str.tostring(d, '#.##'), bgcolor=col, text_color=color.white)
        table.cell(tbl, 2, 1, str.tostring(rsi, '#.##'), bgcolor=col, text_color=color.white)
        table.cell(tbl, 3, 1, srsi_status, bgcolor=col, text_color=color.white)
        table.cell(tbl, 4, 1, rsi_status, bgcolor=col, text_color=color.white)