Liquidity Heatmap [StratifyTrade]
// This work is licensed under a Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0) https://creativecommons.org/licenses/by-nc-sa/4.0/
// © HunterAlgos

//@version=5
indicator("Liquidity Heatmap [HunterAlgos]", shorttitle = "Liquidity Heatmap [1.0.0]", overlay = true, max_lines_count = 500, max_bars_back = 500, max_labels_count = 500)

long_css  = input.color(#26c6da, "Long liquidity color" , group = "COLORS")
short_css = input.color(#ff0000, "Short liquidity color", group = "COLORS")

sensibility = input.int  (10000, "Opacity value"  , tooltip = "Adjust the opacity of the liquidity level manually - (Autopilot off)",                                                                                   group = "SETTINGS")
l_sens      = input.int  (500  , "Opacity Average", tooltip = "Set the average value of the opacity - Example : 500 set will take the average of 500 bar and 250 bar to determine the average of the liquidity levels", group = "SETTINGS")
leverage    = input.float(0.5  , "Leverage"       , tooltip = "Example : 0.5 = 100x leverage - 4.5 = 20x leverage",                                                                                                     group = "SETTINGS", step = 0.5)
width       = input.int  (10   , "Width"          ,                                                                                                                                                                     group = "SETTINGS")
leverage   /= 100

auto       = input.bool(true,  "Autopilot", tooltip = "Determine automatically a decent opacity value"                        , group = "GENERAL")
show_long  = input.bool(true,  "Enable long liquidity"                                                                        , group = "GENERAL")
show_short = input.bool(true,  "Enable short liquidity"                                                                       , group = "GENERAL")
filter     = input.bool(true, "Filtering", tooltip = "Long liquidity = only green candle, short liquidity = only down candle", group = "GENERAL")


data = input.string("nzVolume", options=["nzOI", "OI", "nzVolume", "Volume"], group = "DATA")

type bin
    float[] v
    line [] u
    line [] d

var z = bin.new(
   array.new< float >(1)
 , array.new< line  >(1)
 , array.new< line  >(1)
 )

main = data == "nzOI" ? request.security(str.tostring(syminfo.basecurrency) + "USDT.P_OI","", close - nz(close[1])) : data == "nzVolume" ? volume - nz(volume[1]) : data == "Volume" ? volume : data == "OI" ? math.abs(open - close) : na

calc() =>
    if z.v.size() > 50000
        z.v.shift()
    z.v.push(main)
    
    size     = l_sens
    avg      = math.avg(ta.highest(main, size), ta.highest(main, size / 2))
    round_to = 100
    ceil     = math.ceil (avg / round_to) * round_to
    floor    = math.floor(avg / round_to) * round_to 
    result   = math.abs  (avg - ceil    ) < math.abs(avg - floor) ? ceil : floor

    _math = auto ? result : sensibility
    
    _math
    

method gradient(array<float> y, color css) =>
    var color id = na
    id := color.from_gradient(y.last(), 0, calc(), color.new(color.white, 100), css)
    id


drawLine(x, y, _x, css) =>
    var line id = na
    id := line.new(x1 = x, y1 = y, x2 = _x, y2 = y, xloc = xloc.bar_index, color = css, width = width)
    id

method puts(bool mode, array<line> a, line l) =>
    if mode == true
        if a.size() == 500
            line.delete(a.shift())
        a.push(l)
    if mode == false
        for j = a.size() - 1 to 0 by 1
            x = line.get_x2(a.get(j))
            y = line.get_y1(a.get(j))
            if bar_index - 1 == x - 1 and not (high > y and low < y)
                line.set_x2(a.get(j), bar_index + 1)

filt(bool bull) =>
    bool out = false
    if bull == true and filter == true
        out := close > open ? true : false
    if bull == false and filter == true
        out := close < open ? true : false

    if filter == false
        out := true
    
    out

draw() =>
    bool up_dot = false
    bool dn_dot = false
    if show_long and filt(true) == true
        line l    = na
        l := drawLine(bar_index,  low * (1 - leverage), bar_index, z.v.gradient(long_css))
        true.puts  (z.u , l  )
        up_dot := true
    if show_short and filt(false) == true
        line l = na
        l := drawLine(bar_index, high * (1 + leverage), bar_index, z.v.gradient(short_css))
        true.puts(z.d, l)
        dn_dot := true

    [up_dot, dn_dot]

[up_dot, dn_dot] = draw()


false.puts(z.u, na)
false.puts(z.d, na)
