Simple Volume/RSI Map
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © atolelole

//@version=5
indicator("Simple Volume/RSI Map", overlay=false, max_lines_count=500, max_labels_count=500, max_bars_back=1000)

top   = input(20, "Plot size: ", group="Plot")
bot   = 0
left  = bar_index - int(top/2)
right = bar_index + int(top/2)

var basebox        = box.new(left     , top    , right    , bot    , bgcolor=na                        , border_color=na)
var bearbox_weak   = box.new(left     , top / 2, bar_index, bot    , bgcolor=color.new(color.red, 90)  , border_color=na)
var bearbox_strong = box.new(bar_index, top / 2, right    , bot    , bgcolor=color.new(color.red, 80)  , border_color=na)
var bullbox_weak   = box.new(left     , top    , bar_index, top / 2, bgcolor=color.new(color.green, 90), border_color=na)
var bullbox_strong = box.new(bar_index, top    , right    , top / 2, bgcolor=color.new(color.green, 80), border_color=na)
var rsibox         = box.new(left     , top*0.7, right    , top*0.3, bgcolor=na, border_color=color.gray, border_style=line.style_dashed)

lerp(l, h, s) => 
    l + (h - l) * s

lerp_x_axis(s) =>
    int(lerp(left, right, s))
    
lerp_y_axis(s) =>
    lerp(bot, top, s)
    
var l00 = label.new(lerp_x_axis(0.0), lerp_y_axis(0.0), '(0.0, 0.0)\nvol, rsi\nWeak bearish'  , style=label.style_label_up  , size=size.small, color=color.new(color.blue, 98), textcolor=color.white)
var l10 = label.new(lerp_x_axis(1.0), lerp_y_axis(0.0), '(1.0, 0.0)\nvol, rsi\nStrong bearish', style=label.style_label_up  , size=size.small, color=color.new(color.blue, 98), textcolor=color.white)
var l01 = label.new(lerp_x_axis(0.0), lerp_y_axis(1.0), 'Weak bullish\nvol, rsi\n(0.0, 1.0)'  , style=label.style_label_down, size=size.small, color=color.new(color.blue, 98), textcolor=color.white)
var l11 = label.new(lerp_x_axis(1.0), lerp_y_axis(1.0), 'Strong bullish\nvol, rsi\n(1.0, 1.0)', style=label.style_label_down, size=size.small, color=color.new(color.blue, 98), textcolor=color.white)

limit_rsi  = input.bool(false, "Limit normalization to RSI(30-70) zone")
rsi_len    = input(14, "RSI Length"                 , group="Data")
volume_len = input(35, "Volume Normalization Length", group="Data")
n_samples  = input(35, "N Samples (last n candles)" , group="Data")

vol_highest = ta.highest(volume, volume_len)
rsi         = ta.rsi(close, rsi_len)

plot(limit_rsi ? ((rsi-30.0) / 40.0) : (rsi / 100.0), color=na)
plot(volume / vol_highest, color=na)

var plotpoints = array.new_label()

if barstate.islast
    if limit_rsi
        box.set_top(rsibox, top)
        box.set_bottom(rsibox, bot)
    box.set_left(rsibox, left)
    box.set_right(rsibox, right)
    box.set_left(basebox, left)
    box.set_right(basebox, right)
    box.set_left(bearbox_weak, left)
    box.set_right(bearbox_weak, bar_index)
    box.set_left(bearbox_strong, bar_index)
    box.set_right(bearbox_strong, right)
    box.set_left(bullbox_weak, left)
    box.set_right(bullbox_weak, bar_index)
    box.set_left(bullbox_strong, bar_index)
    box.set_right(bullbox_strong, right)
    
    for i = 0 to array.size(plotpoints)
        if array.size(plotpoints) > 0
            label.delete(array.shift(plotpoints))
    
    rsi_avg = 0.0
    vol_avg = 0.0
    
    for i = 1 to n_samples - 1
        rsi_coef = limit_rsi ? ((rsi[i] - 30.0) / 40.0) : (rsi[i] / 100.0)
        vol_coef = volume[i] / vol_highest
        
        rsi_avg += rsi_coef
        vol_avg += vol_coef
        
        clr = color.new(color.gray, (100 / n_samples) * i)
        array.push(plotpoints, label.new(lerp_x_axis(vol_coef), lerp_y_axis(rsi_coef), '✸', style=label.style_label_center, size=size.small, textcolor=clr, color=na))

    crsi_coef = limit_rsi ? ((rsi - 30.0) / 40.0) : (rsi / 100.0)
    cvol_coef = volume / vol_highest
    
    array.push(plotpoints, label.new(lerp_x_axis(cvol_coef), lerp_y_axis(crsi_coef), '◉', style=label.style_label_center, size=size.small, textcolor=color.white, color=na))
    
    rsi_avg += crsi_coef
    vol_avg += cvol_coef
    
    rsi_avg /= n_samples
    vol_avg /= n_samples
    
    clr_avg = rsi_avg < 0.5 ? color.red : color.lime
    
    array.push(plotpoints, label.new(lerp_x_axis(vol_avg), lerp_y_axis(rsi_avg), '◉', style=label.style_label_center, size=size.small, textcolor=clr_avg ,color=na))

    label.set_x(l00, bar_index - int(top/2))
    label.set_x(l10, bar_index + int(top/2))
    label.set_x(l01, bar_index - int(top/2))
    label.set_x(l11, bar_index + int(top/2))
