OPEN-SOURCE SCRIPT

Liquidity crypt


//version=5
indicator(" 💧TFO_LVL_OI_LIQ 💧 ", " 💧TFO_LVL_OI_LIQ 💧", true, max_bars_back=5000, max_lines_count = 500, max_polylines_count = 100, max_labels_count = 500, max_boxes_count = 500)
string userSymbol = 'BINANCE' + ":" + string(syminfo.basecurrency) + 'USDT.P'
string Formula = str.format("{0}_OI", userSymbol)
OI = request.security(Formula, timeframe.period, close)
OI_delta = OI - nz(OI[1])

maLength = input(60, title="MA Length")
numOfLines = 500

OI_delta_MA = ta.sma(OI_delta, maLength)
OI_delta_abs = math.abs(OI_delta)
OI_delta_abs_MA = ta.sma(OI_delta_abs, maLength)

h3 = input(3.0, title="Large Liquidation Level")
h2 = input(2.0, title="Middle Liquidation Level")
h1 = input(1.2, title="Small Liquidation Level")

OI_delta_open_h3 = (OI_delta_abs >= OI_delta_abs_MA * h3) and OI_delta > 0
OI_delta_open_h2 = (OI_delta_abs >= OI_delta_abs_MA * h2 and OI_delta_abs < OI_delta_abs_MA * h3) and OI_delta > 0
OI_delta_open_h1 = (OI_delta_abs >= OI_delta_abs_MA * h1 and OI_delta_abs < OI_delta_abs_MA * h2) and OI_delta > 0

kline_price = (open + close + high + low) / 4

showLine = input(true, title="Show lines")
showHist = input(true, title="Show histgram")
showLocalOnly = input(true, title="Only show local liquidation levels")

i_5xColor = input.color(#626367a2, '5x Leverage color', group='5x Leverage')
i_10xColor = input.color(#017cff7a, '10x Leverage color', group='10x Leverage')
i_25xColor = input.color(#0dff0064, '25x Leverage color', group='25x Leverage')
i_50xColor = input.color(#f0a02966, '50x Leverage color', group='50x Leverage')
i_100xColor = input.color(color.rgb(218, 55, 101, 44), '100x Leverage color', group='100x Leverage')

var h3Array = array.new_line()
var h2Array = array.new_line()
var h1Array = array.new_line()

// histgram
barColor = input(color.rgb(0, 55, 254, 4), "Bar Color")
numOfBars = input(120, 'Number of bars to lookback')
distLastCandle = input(5, 'Histgram distance from last candle')
local_high = ta.highest(high, numOfBars)
local_low = ta.lowest(low, numOfBars)
rangeHigh = local_high * (1 + local_high / local_low / 10)
rangeLow = local_low * (1 - local_high / local_low / 10)
rangeHeight = rangeHigh - rangeLow

numOfHistograms = input(120, 'Number of histograms (<=120)')
histogramHeight = rangeHeight / numOfHistograms

histogramLowList = array.new_float(numOfHistograms, na)
histogramHighList = array.new_float(numOfHistograms, na)

histogramData = array.new_float()
histogramtargetList = array.new_float(numOfHistograms, 0.0)

var Bars = array.new_box(numOfHistograms, na)
// Clean up drawings every tick
for i=0 to numOfHistograms - 1
box.delete(array.get(Bars, i))

f_drawLine(_x1, _x2, _yValue, _lineColor, _style, _width) =>
line.new(x1=_x1, y1=_yValue, x2=_x2, y2=_yValue, color=_lineColor, style=_style, width=_width)

f_extendArray(_lineArray, _extendLines) =>
if array.size(_lineArray) > 0
for _i = array.size(_lineArray) - 1 to 0 by 1

x2 = line.get_x2(array.get(_lineArray, _i))
yValue = line.get_y1(array.get(_lineArray, _i))

if _extendLines or bar_index - 1 == x2 - 1 and not(high > yValue and low < yValue)
line.set_x2(array.get(_lineArray, _i), bar_index + 1)
if bar_index == last_bar_index
array.push(histogramData, yValue)

f_calculateLeverage100x(_pivotValue, _shortSell) =>
_shortSell ? _pivotValue * (1 - 0.01) : _pivotValue * (1 + 0.01)

f_calculateLeverage50x( _pivotValue, _shortSell) =>
_shortSell ? _pivotValue * (1 - 0.02) : _pivotValue * (1 + 0.02)

f_calculateLeverage25x(_pivotValue, _shortSell) =>
_shortSell ? _pivotValue * (1 - 0.04) : _pivotValue * (1 + 0.04)

f_calculateLeverage10x(_pivotValue, _shortSell) =>
_shortSell ? _pivotValue * (1 - 0.1) : _pivotValue * (1 + 0.1)

f_calculateLeverage5x(_pivotValue, _shortSell) =>
_shortSell ? _pivotValue * (1 - 0.2) : _pivotValue * (1 + 0.2)

float yValue = na
int x1 = na
int x2 = na
line l = na

x1 := bar_index
x2 := bar_index

f_append(Array, l) =>
if array.size(Array) == numOfLines
line.delete(array.shift(Array))
array.push(Array, l)

if OI_delta_open_h3
yValue := f_calculateLeverage5x(kline_price, true)
l := f_drawLine(x1, x2, yValue, i_5xColor, line.style_solid, 1)
f_append(h3Array, l)

yValue := f_calculateLeverage5x(kline_price, false)
l := f_drawLine(x1, x2, yValue, i_5xColor, line.style_solid, 1)
f_append(h3Array, l)

yValue := f_calculateLeverage10x(kline_price, true)
l := f_drawLine(x1, x2, yValue, i_10xColor, line.style_solid, 1)
f_append(h3Array, l)

yValue := f_calculateLeverage10x(kline_price, false)
l := f_drawLine(x1, x2, yValue, i_10xColor, line.style_solid, 1)
f_append(h3Array, l)

yValue := f_calculateLeverage25x(kline_price, true)
l := f_drawLine(x1, x2, yValue, i_25xColor, line.style_solid, 1)
f_append(h3Array, l)

yValue := f_calculateLeverage25x(kline_price, false)
l := f_drawLine(x1, x2, yValue, i_25xColor, line.style_solid, 1)
f_append(h3Array, l)

yValue := f_calculateLeverage50x(kline_price, true)
l := f_drawLine(x1, x2, yValue, i_50xColor, line.style_solid, 1)
f_append(h3Array, l)

yValue := f_calculateLeverage50x(kline_price, false)
l := f_drawLine(x1, x2, yValue, i_50xColor, line.style_solid, 1)
f_append(h3Array, l)

yValue := f_calculateLeverage100x(kline_price, true)
l := f_drawLine(x1, x2, yValue, i_100xColor, line.style_solid, 1)
f_append(h3Array, l)

yValue := f_calculateLeverage100x(kline_price, false)
l := f_drawLine(x1, x2, yValue, i_100xColor, line.style_solid, 1)
f_append(h3Array, l)

if OI_delta_open_h2
yValue := f_calculateLeverage10x(kline_price, true)
l := f_drawLine(x1, x2, yValue, i_10xColor, line.style_solid, 1)
f_append(h2Array, l)

yValue := f_calculateLeverage10x(kline_price, false)
l := f_drawLine(x1, x2, yValue, i_10xColor, line.style_solid, 1)
f_append(h2Array, l)

yValue := f_calculateLeverage25x(kline_price, true)
l := f_drawLine(x1, x2, yValue, i_25xColor, line.style_solid, 1)
f_append(h2Array, l)

yValue := f_calculateLeverage25x(kline_price, false)
l := f_drawLine(x1, x2, yValue, i_25xColor, line.style_solid, 1)
f_append(h2Array, l)

yValue := f_calculateLeverage50x(kline_price, true)
l := f_drawLine(x1, x2, yValue, i_50xColor, line.style_solid, 1)
f_append(h2Array, l)

yValue := f_calculateLeverage50x(kline_price, false)
l := f_drawLine(x1, x2, yValue, i_50xColor, line.style_solid, 1)
f_append(h2Array, l)

yValue := f_calculateLeverage100x(kline_price, true)
l := f_drawLine(x1, x2, yValue, i_100xColor, line.style_solid, 1)
f_append(h2Array, l)

yValue := f_calculateLeverage100x(kline_price, false)
l := f_drawLine(x1, x2, yValue, i_100xColor, line.style_solid, 1)
f_append(h2Array, l)

if OI_delta_open_h1
yValue := f_calculateLeverage25x(kline_price, true)
l := f_drawLine(x1, x2, yValue, i_25xColor, line.style_dotted, 1)
f_append(h1Array, l)

yValue := f_calculateLeverage25x(kline_price, false)
l := f_drawLine(x1, x2, yValue, i_25xColor, line.style_dotted, 1)
f_append(h1Array, l)

yValue := f_calculateLeverage50x(kline_price, true)
l := f_drawLine(x1, x2, yValue, i_50xColor, line.style_dotted, 1)
f_append(h1Array, l)

yValue := f_calculateLeverage50x(kline_price, false)
l := f_drawLine(x1, x2, yValue, i_50xColor, line.style_dotted, 1)
f_append(h1Array, l)

yValue := f_calculateLeverage100x(kline_price, true)
l := f_drawLine(x1, x2, yValue, i_100xColor, line.style_dotted, 1)
f_append(h1Array, l)

yValue := f_calculateLeverage100x(kline_price, false)
l := f_drawLine(x1, x2, yValue, i_100xColor, line.style_dotted, 1)
f_append(h1Array, l)

f_extendArray(h3Array, false)
f_extendArray(h2Array, false)
f_extendArray(h1Array, false)

// draw hist
if barstate.islast and showHist
// Define lows and highs of the histograms
for i = 0 to numOfHistograms - 1
histogramLow = rangeLow + histogramHeight * i
histogramHigh = rangeLow + histogramHeight * (i + 1)
array.set(histogramLowList, i, histogramLow)
array.set(histogramHighList, i, histogramHigh)

for i = 0 to array.size(histogramData) - 1
y = array.get(histogramData, i)

for j = 0 to numOfHistograms - 1
histogramLow = array.get(histogramLowList, j)
histogramHigh = array.get(histogramHighList, j)
if y >= histogramLow and y <= histogramHigh
array.set(histogramtargetList, j, array.get(histogramtargetList, j) + 1)

for i = 0 to numOfHistograms - 1
histogramLow = array.get(histogramLowList, i)
histogramHigh = array.get(histogramHighList, i)
histogramtarget = array.get(histogramtargetList, i)
histogramWidth = math.floor((histogramtarget + 0.49) * 2)

// Draw histograms
array.set(Bars, i, box.new(left=bar_index + distLastCandle, top=histogramHigh, right=bar_index + distLastCandle + histogramWidth, bottom=histogramLow, bgcolor=barColor, border_color=barColor))


if barstate.islast and not showLine
for i=0 to array.size(h3Array) - 1
line.delete(array.get(h3Array, i))

for i=0 to array.size(h2Array) - 1
line.delete(array.get(h2Array, i))

for i=0 to array.size(h1Array) - 1
line.delete(array.get(h1Array, i))

else if barstate.islast and showLocalOnly
for i=0 to array.size(h3Array) - 1
if line.get_y1(array.get(h3Array, i)) < rangeLow or line.get_y1(array.get(h3Array, i)) > rangeHigh
line.delete(array.get(h3Array, i))

for i=0 to array.size(h2Array) - 1
if line.get_y1(array.get(h2Array, i)) < rangeLow or line.get_y1(array.get(h2Array, i)) > rangeHigh
line.delete(array.get(h2Array, i))

for i=0 to array.size(h1Array) - 1
if line.get_y1(array.get(h1Array, i)) < rangeLow or line.get_y1(array.get(h1Array, i)) > rangeHigh
line.delete(array.get(h1Array, i))



// Volume Profile Inputs
var g_VP = "Volume Profile"
rows = input.int(200, "Rows", tooltip = "The number of price levels/rows that will be used to approximate the cumulative volume profile", group = g_VP)
tf = input.timeframe("D", "Profile Timeframe", tooltip = "The aggregate timeframe that the volume profile represents", group = g_VP)
ltf = input.timeframe("1", "Resolution Timeframe", tooltip = "The timeframe whose price data will be used to build the volume profile", group = g_VP)
extend = input.int(100, "Profile Extend %", 0, 100, tooltip = "How much the volume profile should extend to the next session", group = g_VP)
vp_color = input.color(color.new(color.blue, 70), "Profile Color", tooltip = "The color of the volume profile", group = g_VP)

// Volume Point of Control Inputs
var g_VPOC = "Volume Point of Control"
show_vpoc = input.bool(true, "Show VPOC", inline = "VPOC", tooltip = "Whether to show the volume point of control (VPOC), or the level with the largest volume in a given volume profile", group = g_VPOC)
vpoc_color = input.color(color.yellow, "", inline = "VPOC", group = g_VPOC)
ext_vpoc = input.bool(true, "Extend Last N VPOCs", inline = "EXT", tooltip = "Whether to extend the last N number of VPOCs to the right of the chart", group = g_VPOC)
ext_n_vpoc = input.int(5, "", 0, 100, inline = "EXT", group = g_VPOC)
vpoc_label_above = input.timeframe("D", "Show Labels Above", tooltip = "With extend last N VPOCs turned on, labels displaying the date of said VPOCs will be shown when the profile timeframe is greater than or equal to this", group = g_VPOC)
vpoc_label_size = input.string('Normal', "Label Size", options = ['Auto', 'Tiny', 'Small', 'Normal', 'Large', 'Huge'], tooltip = "The size of VPOC date labels", group = g_VPOC)
vpoc_width = input.int(2, "Line Width", tooltip = "The width of VPOC lines", group = g_VPOC)

// High Volume Nodes Inputs
var g_HVN = "High Volume Nodes"
show_hvn = input.bool(true, "Show Previous HVNs", inline = "HVN", tooltip = "Whether to show high volume nodes (HVNs) from the previous session. Using the previous session's close, HVNs above this price will use the first color, and HVNs below this price will use the second color", group = g_HVN)
hvn_color_bull = input.color(color.new(color.teal, 70), "", inline = "HVN", group = g_HVN)
hvn_color_bear = input.color(color.new(color.red, 70), "", inline = "HVN", group = g_HVN)
hvn_strength = input.int(10, "HVN Strength", tooltip = "HVNs are validated when a given level in the volume profile contains more volume than this many rows both above and below it", group = g_HVN)
hvn_type = input.string("Areas", "HVN Type", options = ['Levels','Areas'], tooltip = "Whether to display HVNs as levels (lines) or areas (boxes). Levels use a solid line to denote the prior session's VPOC, and dotted lines for all other HVNs", group = g_HVN)
hvn_width = input.int(1, "Line Width", tooltip = "The width of HVN lines, if the HVN type is selected as levels", group = g_HVN)

// Bubbles AcadAlgo Inputs
showBubbles = input.bool(true, "Display Bubbles", group="Bubbles", inline="1")
useHeatMap = input.bool(false, "Enable HeatMap", group="Bubbles")

showLevels = input.bool(false, "Highlight Significant Levels", group="Volume Levels")
levelsCount = input.int(10, "Number of Levels", group="Volume Levels")

mainColor = input.color(color.green, "Main Color", group="Colors")

heatMapColor1 = input.color(color.new(color.aqua, 50), "HeatMap Color 1", group="Colors")
heatMapColor2 = input.color(color.new(color.green, 50), "HeatMap Color 2", group="Colors")
heatMapColor3 = input.color(color.new(color.yellow, 50), "HeatMap Color 3", group="Colors")
heatMapColor4 = input.color(color.new(color.orange, 30), "HeatMap Color 4", group="Colors")
heatMapColor5 = input.color(#d32626, "HeatMap Color 5", group="Colors")

calculateInDollars = input.bool(false, "Calculate Volume in Dollars", group="Volume Options")
volumeFilterOn = input.bool(true, "Enable Volume Filter", group="Volume Filters") // Toggle button for volume filter
minVolumeDollars = input.float(100, "Minimum Volume ($)", minval=1, group="Volume Filters")
maxVolumeDollars = input.float(1000000000000, "Maximum Volume ($)", minval=1, group="Volume Filters")

// SPL Level Inputs
swingSizeR = input.int(10, 'Bars Right-Left', inline='brl')
swingSizeL = input.int(15, '-', inline='brl')
showBoxes = input.bool(true, 'Show Boxes ', inline='aa')
showSwingLines = input.bool(true, 'Show Lines', inline='aa')
showBubblesSPL = input.bool(true, 'Show Labels ', inline='bb')
showVol = input.bool(false, 'Show Volume', inline='bb')
showOId = input.bool(false, 'Show OI Δ   ', inline='cc')
extendtilfilled = input.bool(true, 'Extend Until Fill', inline='cc')

hidefilled = input.bool(false, 'Hide Filled', group='Conditions')
voltresh = input.int(0, 'Volume >', group='Conditions')
oitresh = input.int(0, 'OI Δ (abs.) >', group='Conditions')
pnoid = input.string('/', 'Only Swings With', options=['Positive OI Delta', 'Negative OI Delta', '/'], group='Conditions')

showhighs = input.bool(true, '', inline='sh', group='Appearance')
showlows = input.bool(true, '', inline='sl', group='Appearance')
sellcol = input.color(#aa2430, 'Lows (Line - Label - Box)', inline='sh', group='Appearance')
buycol = input.color(#66bb6a, 'Highs (Line - Label - Box)', inline='sl', group='Appearance')
sellcolB = input.color(#aa2430, '', inline='sh', group='Appearance')
buycolB = input.color(#66bb6a, '', inline='sl', group='Appearance')
sellboxCol = input.color(#80192231, '', inline='sh', group='Appearance')
buyboxCol = input.color(#66bb6a31, '', inline='sl', group='Appearance')
lineStyle = input.string('Dotted', 'Line Style + Width', ['Solid', 'Dashed', 'Dotted'], inline='l', group='Appearance')
lineWid = input.int(1, '', inline='l', group='Appearance')
boxWid = input.float(0.7, 'Box Width + Type ', step=0.1, inline='xx', group='Appearance')
boxStyle = input.string('TYPE 1', '', options=['TYPE 1', 'TYPE 2'], inline='xx', group='Appearance')
labelsize = input.string('Size: Tiny', 'Text Style        ', options=['Size: Normal','Size: Large', 'Size: Small', 'Size: Tiny', 'Size: Auto' ], inline='txt', group='Appearance' )
texthalign = input.string('Right','', options=['Middle', 'Right', 'Left'], inline='txt', group='Appearance')
lookback = input.bool(false, '', inline='lb')
daysBack = input.float(150, 'Lookback (D)               ',inline='lb')

binance = input.bool(true, 'Binance USDT.P', inline='src', group='Open Interest')
binance2 = input.bool(true, 'Binance USD.P', inline='src', group='Open Interest')
binance3 = input.bool(true, 'Binance BUSD.P', inline='src2', group='Open Interest')
bitmex = input.bool(true, 'BitMEX USD.P', inline='src2', group='Open Interest')
bitmex2 = input.bool(true, 'BitMEX USDT.P ', inline='src3', group='Open Interest')
kraken = input.bool(true, 'Kraken USD.P', inline='src3', group='Open Interest')

// Calculating inRange, used for lookback in days
MSPD = 24 * 60 * 60 * 1000
lastBarDate = timestamp(year(timenow), month(timenow), dayofmonth(timenow), hour(timenow), minute(timenow), second(timenow))
thisBarDate = timestamp(year, month, dayofmonth, hour, minute, second)
daysLeft = math.abs(math.floor((lastBarDate - thisBarDate) / MSPD))
inRange = lookback ? (daysLeft < daysBack) : true

// Volume Profile Variables
var vpoc = array.new_line()
var dates = array.new_label()
var values = array.new_float()
var x_vol = array.new_int()
var y_vol = array.new_float()
var hvn_lines = array.new_line()
var hvn_boxes = array.new_box()
var hvn_Ly = array.new_float()
var hvn_By = array.new_float()
var PLA = array.new<chart.point>()
var polyline PL = na
var line temp_vpoc = na
var int lb_idx = na
var int lb_time = na

// SPL Level Variables
int prevHighIndex= na, int prevLowIndex= na, bool highActive= false, bool lowActive= false, bool h= false, bool lv= false
pivHi = ta.pivothigh(high, swingSizeL, swingSizeR)
pivLo = ta.pivotlow(low, swingSizeL, swingSizeR)

if not na(pivHi)
h := true
prevHighIndex := bar_index - swingSizeR
if not na(pivLo)
lv := true
prevLowIndex := bar_index - swingSizeR

// Getting OI data
mex = syminfo.basecurrency == 'BTC' ? 'XBT' : string(syminfo.basecurrency)
oid1 = nz(request.security('BINANCE:' + string(syminfo.basecurrency) + 'USDT.P_OI', timeframe.period, close - close[1], ignore_invalid_symbol=true), 0)
oid2 = nz(request.security('BINANCE:' + string(syminfo.basecurrency) + 'USD.P_OI', timeframe.period, close - close[1], ignore_invalid_symbol=true), 0)
oid3 = nz(request.security('BINANCE:' + string(syminfo.basecurrency) + 'BUSD.P_OI', timeframe.period, close - close[1], ignore_invalid_symbol=true), 0)
oid4 = nz(request.security('BITMEX:' + mex + 'USD.P_OI', timeframe.period, close - close[1], ignore_invalid_symbol=true), 0)
oid5 = nz(request.security('BITMEX:' + mex + 'USDT.P_OI', timeframe.period, close - close[1], ignore_invalid_symbol=true), 0)
oid6 = nz(request.security('KRAKEN:' + string(syminfo.basecurrency) + 'USD.P_OI', timeframe.period, close - close[1], ignore_invalid_symbol=true), 0)

deltaOI = (binance ? nz(oid1, 0) : 0) + (binance2 ? nz(oid2, 0) / close : 0) + (binance3 ? nz(oid3, 0) : 0) + (bitmex ? nz(oid4, 0) / close : 0) + (bitmex2 ? nz(oid5, 0) / close : 0) + (kraken ? nz(oid6, 0) / close : 0)

// Volume, OI, box width
vol = volume[swingSizeR]
oitreshcond = oitresh > 0 ? math.abs(deltaOI[swingSizeR]) > oitresh : true
voltreshcond = voltresh > 0 ? vol > voltresh : true
oicond = pnoid == 'Positive OI Delta' ? deltaOI[swingSizeR] > 0 : pnoid == 'Negative OI Delta' ? deltaOI[swingSizeR] < 0 : true

CLEAR = color.rgb(0, 0, 0, 100)
boxWid1 = 0.001 * boxWid

// Styles
boxStyle(x) =>
switch x
'TYPE 1' => h ? pivHi : lv ? pivLo : na
'TYPE 2' => h ? pivHi * (1 - boxWid1) : lv ? pivLo * (1 + boxWid1) : na
lineStyle(x) =>
switch x
'Solid' => line.style_solid
'Dashed' => line.style_dashed
'Dotted' => line.style_dotted
switchtextsize(textsize) =>
switch textsize
'Size: Normal' => size.normal
'Size: Small' => size.small
'Size: Tiny' => size.tiny
'Size: Auto' => size.auto
'Size: Large' => size.large
switchhalign(texthalign) =>
switch texthalign
'Middle' => text.align_center
'Right' => text.align_right
'Left' => text.align_left

// Swing level labels
var levelBoxes = array.new_box()
var levelLines = array.new_line()

if h and inRange and showhighs and oitreshcond and voltreshcond and oicond
hBox = box.new(prevHighIndex, pivHi * (1 + boxWid1), bar_index, boxStyle(boxStyle), border_color=na, bgcolor=showBoxes ? sellboxCol : CLEAR, text=(showVol ? str.tostring(vol, format.volume) : na) + ' ' + (showOId ? str.tostring(deltaOI[swingSizeR], format.volume) : ''), text_halign=switchhalign(texthalign), text_valign=text.align_center, text_color=chart.fg_color, text_size=switchtextsize(labelsize))
hLine = line.new(prevHighIndex, pivHi, bar_index, pivHi, color=showSwingLines ? sellcol : CLEAR, style=lineStyle(lineStyle), width=lineWid)
array.push(levelBoxes, hBox)
array.push(levelLines, hLine)

if lv and inRange and showlows and oitreshcond and voltreshcond and oicond
lBox = box.new(prevLowIndex, pivLo * (1 - boxWid1), bar_index, boxStyle(boxStyle), border_color=na, bgcolor=showBoxes ? buyboxCol : CLEAR, text=(showVol ? str.tostring(vol, format.volume) : na) + ' ' + (showOId ? str.tostring(deltaOI[swingSizeR], format.volume) : ''), text_halign=switchhalign(texthalign), text_valign=text.align_center, text_color=chart.fg_color, text_size=switchtextsize(labelsize))
lLine = line.new(prevLowIndex, pivLo, bar_index, pivLo, color=showSwingLines ? buycol : CLEAR, style=lineStyle(lineStyle), width=lineWid)
array.push(levelBoxes, lBox)
array.push(levelLines, lLine)

// Looping over the full array of lines and updating them, and deleting them if they have been touched
size = array.size(levelBoxes)
if size > 0
for i = 0 to size - 1
j = size - 1 - i
box = array.get(levelBoxes, j)
line = array.get(levelLines, j)
level = line.get_y2(line)
filled = (high >= level and low <= level)

if filled and extendtilfilled and not hidefilled
array.remove(levelLines, j)
array.remove(levelBoxes, j)
continue

box.set_right(box, bar_index + 1)
line.set_x2(line, bar_index + 1)
if filled and hidefilled
array.remove(levelLines, j)
array.remove(levelBoxes, j)
line.delete(line)
box.delete(box)

if not filled and not extendtilfilled
array.remove(levelLines, j)
array.remove(levelBoxes, j)
continue

// Deleting the oldest lines if array is too big
if array.size(levelBoxes) >= 500
int i = 0
while array.size(levelBoxes) >= 500
box = array.get(levelBoxes, i)
line = array.get(levelLines, i)
box.delete(box)
line.delete(line)
array.remove(levelBoxes, i)
array.remove(levelLines, i)
i += 1

// Plotting circle labels for SPL
plotshape(showhighs and showBubblesSPL and h and oitreshcond and voltreshcond and oicond ? high[swingSizeR] : na, style=shape.triangleup, location=location.absolute, offset=-swingSizeR, color=sellcolB, size=size.tiny)
plotshape(showlows and showBubblesSPL and lv and oitreshcond and voltreshcond and oicond ? low[swingSizeR] : na, style=shape.triangledown, location=location.absolute, offset=-swingSizeR, color=buycolB, size=size.tiny)

// Calculations for Bubbles AcadAlgo
volumeData = volume
priceSource = hl2
volumeInDollars = volumeData * close
selectedVolume = calculateInDollars ? volumeInDollars : volumeData
normalizedVolume = selectedVolume / ta.stdev(selectedVolume, 200)

gradientColor = not useHeatMap
? color.from_gradient(
normalizedVolume, 0, 8,
chart.bg_color == color.white ? color.new(mainColor, 100) : color.rgb(18, 34, 18, 50),
mainColor
)
:
(
normalizedVolume < 1
? color.from_gradient(normalizedVolume, 0, 1, heatMapColor1, heatMapColor2)
: normalizedVolume >= 1 and normalizedVolume < 4
? color.from_gradient(normalizedVolume, 1, 4, heatMapColor3, heatMapColor4)
: normalizedVolume >= 4
? color.from_gradient(normalizedVolume, 4, 8, heatMapColor4, heatMapColor5) : na
)

volumeCondition = volumeFilterOn ? (selectedVolume >= minVolumeDollars and selectedVolume < maxVolumeDollars) : true

conditionTiny = volumeCondition and normalizedVolume > 0 and normalizedVolume < 1 and showBubbles
conditionSmall = volumeCondition and normalizedVolume >= 1 and normalizedVolume < 2 and showBubbles
conditionNormal= volumeCondition and normalizedVolume >= 2 and normalizedVolume < 3 and showBubbles
conditionLarge = volumeCondition and normalizedVolume >= 3 and normalizedVolume < 4 and showBubbles
conditionHuge = volumeCondition and normalizedVolume >= 4 and showBubbles

// Plotting for Bubbles AcadAlgo
if conditionHuge and (showLevels or showBubbles)
label.new(showBubbles ? bar_index : last_bar_index, priceSource, str.tostring(selectedVolume, format.volume), xloc.bar_index, yloc.price,
#00000000, showBubbles ? label.style_label_center : label.style_label_left, chart.fg_color)

if conditionHuge and showLevels
line.new(bar_index, priceSource, last_bar_index, priceSource, xloc.bar_index, extend.none, gradientColor, width=2)

// figure
plotshape(conditionTiny ? priceSource : na, "", shape.square, location.absolute, gradientColor, 0, "", na, size=size.tiny)
plotshape(conditionSmall ? priceSource : na, "", shape.circle, location.absolute, gradientColor, 0, "", na, size=size.small)
plotshape(conditionNormal? priceSource : na, "", shape.circle, location.absolute, gradientColor, 0, "", na, size=size.normal)
plotshape(conditionLarge ? priceSource : na, "", shape.square, location.absolute, gradientColor, 0, "", na, size=size.normal)
plotshape(conditionHuge ? priceSource : na, "", shape.diamond, location.absolute, gradientColor, 0, "", na, size=size.huge)

// Manage the number of lines and labels on the chart
a_allLines = line.all
if array.size(a_allLines) > levelsCount
line.delete(array.shift(a_allLines))

a_allLabels = label.all
if array.size(a_allLabels) > levelsCount and not showBubbles
label.delete(array.shift(a_allLabels))

// Warning if no Volume data Provided
if ta.cum(volume) <= 0 and barstate.islast
label.new(bar_index, hl2, "No Volume Data Available\nUse Another Symbol",
style=label.style_label_left,
textcolor=chart.fg_color)

// Volume Profile Functions
get_label_size(x) =>
result = switch x
'Auto' => size.auto
'Tiny' => size.tiny
'Small' => size.small
'Normal' => size.normal
'Large' => size.large
'Huge' => size.huge

get_hvn() =>
if values.size() > hvn_strength
for i = 0 to values.size() - 1
start = values.get(i)
valid = true

for j = -hvn_strength to hvn_strength
k = i + j
if k < 0 or k > values.size() - 1
continue
else
if j != 0 and values.get(k) > start
valid := false
break

if valid
idx = values.indexof(start)

if idx != -1
y1 = y_vol.get(idx)
y2 = y_vol.get(idx)
val = y_vol.get(idx)

if i < values.size() - 1
for m = i to values.size() - 2
if values.get(m + 1) > values.get(m)
y1 := y_vol.get(m)
break
if i > 0
for m = i to 1
if values.get(m - 1) > values.get(m)
y2 := y_vol.get(m)
break

new_color = close[1] > math.avg(y1, y2) ? hvn_color_bull : hvn_color_bear

if hvn_type == "Levels"
if hvn_Ly.indexof(val) == -1
hvn_Ly.unshift(val)
hvn_lines.unshift(line.new(time, val, time + timeframe.in_seconds(tf)*1000, val, xloc = xloc.bar_time, color = color.new(new_color, 0), style = start == values.max() ? line.style_solid : line.style_dotted, width = hvn_width))
else
if hvn_By.indexof(y1) == -1
hvn_By.unshift(y1)
hvn_boxes.unshift(box.new(time, y1, time + timeframe.in_seconds(tf)*1000, y2, xloc = xloc.bar_time, bgcolor = new_color, border_color = na))

ltf := timeframe.in_seconds(ltf) <= timeframe.in_seconds() ? ltf : ""
[ltf_H, ltf_L, ltf_V] = request.security_lower_tf(syminfo.tickerid, ltf, [high, low, volume])

if not na(lb_idx)
lb = bar_index - lb_idx > 0 ? (bar_index - lb_idx) : 1

y_max = ta.highest(high[1], lb)
y_min = ta.lowest(low[1], lb)

if timeframe.change(tf) or barstate.islast
x_vol.clear()
y_vol.clear()
values.clear()

for i = 0 to rows
y = y_min + i * (y_max - y_min) / rows
x_vol.push(lb_time)
y_vol.push(y)
values.push(0)

for i = bar_index - lb_idx to 1
vol = ltf_V,
if vol.size() > 0
for j = 0 to values.size() - 1
temp = y_vol.get(j)
for k = 0 to vol.size() - 1
H = ltf_H
L = ltf_L
V = ltf_V
if H.get(k) >= temp and L.get(k) <= temp
add = math.floor(V.get(k) / ((H.get(k) - L.get(k)) / (y_max - y_min) / rows))
values.set(j, values.get(j) + add)

max_y = y_vol.get(values.indexof(values.max()))
sf = values.max() / (time[1] - lb_time) / (extend / 100)

for j = 0 to values.size() - 1
set = (lb_time + math.floor(values.get(j) / sf))
x_vol.set(j, set)

PLA.clear()
PLA.push(chart.point.from_time(lb_time, y_min))
for i = 0 to x_vol.size() - 1
PLA.push(chart.point.from_time(x_vol.get(i), y_vol.get(i)))
PLA.push(chart.point.from_time(lb_time, y_max))

PL.delete()
if timeframe.change(tf)
polyline.new(PLA, curved = false, closed = true, line_color = vp_color, fill_color = vp_color, xloc = xloc.bar_time)
temp_vpoc.delete()
vpoc.unshift(line.new(lb_time, max_y, time, max_y, xloc = xloc.bar_time, color = show_vpoc ? vpoc_color : na, extend = ext_vpoc ? extend.right : extend.none, width = vpoc_width))
if ext_vpoc and timeframe.in_seconds(tf) >= timeframe.in_seconds(vpoc_label_above)
dates.unshift(label.new(bar_index, max_y, str.format("{0,date,short}", time("", session = "0000-0000", timezone = "America/New_York")), textcolor = show_vpoc ? vpoc_color : na, color = na, size = get_label_size(vpoc_label_size)))
else
PL := polyline.new(PLA, curved = false, closed = true, line_color = vp_color, fill_color = vp_color, xloc = xloc.bar_time)
if na(temp_vpoc)
temp_vpoc := line.new(lb_time, max_y, time, max_y, xloc = xloc.bar_time, color = show_vpoc ? vpoc_color : na, extend = ext_vpoc ? extend.right : extend.none, width = vpoc_width)
temp_vpoc.set_y1(max_y)
temp_vpoc.set_y2(max_y)
temp_vpoc.set_x2(time)

if timeframe.change(tf)
lb_idx := bar_index
lb_time := time

if show_hvn
hvn_lines.clear()
hvn_boxes.clear()
hvn_Ly.clear()
hvn_By.clear()
get_hvn()

if ext_vpoc and vpoc.size() > ext_n_vpoc
line.set_extend(vpoc.pop(), extend.none)
if timeframe.in_seconds(tf) >= timeframe.in_seconds(vpoc_label_above)
label.delete(dates.pop())

if dates.size() > 0
for i = 0 to dates.size() - 1
dates.get(i).set_x(bar_index + 20)

คำจำกัดสิทธิ์ความรับผิดชอบ