//@version=5
indicator("Buyside & Sellside Liquidity [LuxAlgo]", "LuxAlgo - Buyside &
Sellside Liquidity", overlay = true, max_lines_count = 500,
max_boxes_count = 500, max_bars_back = 3000)
//-----------------------------------------------------------------------
-------
//Settings
//-----------------------------------------------------------------------
------{
liqGrp = 'Liquidity Detection'
liqLen = [Link] (7, title = 'Detection Length', minval = 3, maxval =
13, inline = 'LIQ', group = liqGrp)
liqMar = 10 / [Link] (6.9, 'Margin', minval = 4, maxval = 9, step =
0.1, inline = 'LIQ', group = liqGrp)
liqBuy = [Link] (true, 'Buyside Liquidity Zones, Margin', inline =
'Buyside', group = liqGrp)
marBuy = [Link](2.3, '', minval = 1.5, maxval = 10, step = .1,
inline = 'Buyside', group = liqGrp)
cLIQ_B = [Link] ([Link](#4caf50, 0), '', inline = 'Buyside',
group = liqGrp)
liqSel = [Link] (true, 'Sellside Liquidity Zones, Margin', inline =
'Sellside', group = liqGrp)
marSel = [Link](2.3, '', minval = 1.5, maxval = 10, step = .1,
inline = 'Sellside', group = liqGrp)
cLIQ_S = [Link] ([Link](#f23645, 0), '', inline = 'Sellside',
group = liqGrp)
lqVoid = [Link] (false, 'Liquidity Voids, Bullish', inline = 'void',
group = liqGrp)
cLQV_B = [Link] ([Link](#4caf50, 0), '', inline = 'void', group
= liqGrp)
cLQV_S = [Link] ([Link](#f23645, 0), 'Bearish', inline = 'void',
group = liqGrp)
lqText = [Link] (false, 'Label', inline = 'void', group = liqGrp)
mode = [Link]('Present', title = 'Mode', options =['Present',
'Historical'], inline = 'MOD', group = liqGrp)
visLiq = [Link] (3, ' # Visible Levels', minval = 1, maxval = 50,
inline = 'MOD', group = liqGrp)
//-----------------------------------------------------------------------
------}
//General Calculations
//-----------------------------------------------------------------------
------{
maxSize = 50
atr = [Link](10)
atr200 = [Link](200)
per = mode == 'Present' ? last_bar_index - bar_index <= 500 : true
//-----------------------------------------------------------------------
------}
//User Defined Types
//-----------------------------------------------------------------------
------{
// @type used to store pivot high/low data
//
// @field d (array<int>) The array where the trend direction is to be
maintained
// @field x (array<int>) The array where the bar index value of pivot
high/low is to be maintained
// @field y (array<float>) The array where the price value of pivot
high/low is to be maintained
type ZZ
int [] d
int [] x
float [] y
// @type bar properties with their values
//
// @field o (float) open price of the bar
// @field h (float) high price of the bar
// @field l (float) low price of the bar
// @field c (float) close price of the bar
// @field i (int) index of the bar
type bar
float o = open
float h = high
float l = low
float c = close
int i = bar_index
// @type liquidity object definition
//
// @field bx (box) box maitaing the liquity level margin extreme
levels
// @field bxz (box) box maitaing the liquity zone margin extreme levels
// @field bxt (box) box maitaing the labels
// @field brZ (bool) mainains broken zone status
// @field brL (bool) mainains broken level status
// @field ln (line) maitaing the liquity level line
// @field lne (line) maitaing the liquity extended level line
type liq
box bx
box bxz
box bxt
bool brZ
bool brL
line ln
line lne
//-----------------------------------------------------------------------
------}
//Variables
//-----------------------------------------------------------------------
------{
var ZZ aZZ = [Link](
[Link] <int> (maxSize, 0),
[Link] <int> (maxSize, 0),
[Link] <float>(maxSize, na)
)
bar b = [Link]()
var liq[] b_liq_B = [Link]<liq> (1, [Link](box(na), box(na), box(na),
false, false, line(na), line(na)))
var liq[] b_liq_S = [Link]<liq> (1, [Link](box(na), box(na), box(na),
false, false, line(na), line(na)))
var b_liq_V = array.new_box()
var int dir = na, var int x1 = na, var float y1 = na, var int x2 = na,
var float y2 = na
//-----------------------------------------------------------------------
------}
//Functions/methods
//-----------------------------------------------------------------------
------{
// @function maintains arrays
// it prepends a `value` to the arrays and removes
their oldest element at last position
// @param aZZ (UDT<array<int>, array<int>, array<float>>) The UDT
obejct of arrays
// @param _d (array<int>) The array where the trend direction is
maintained
// @param _x (array<int>) The array where the bar index value of
pivot high/low is maintained
// @param _y (array<float>) The array where the price value of
pivot high/low is maintained
//
// @returns none
method in_out(ZZ aZZ, int _d, int _x, float _y) =>
[Link](_d), [Link](_x), [Link](_y), [Link](),
[Link](), [Link]()
// @function (build-in) sets the maximum number of bars that is
available for historical reference
max_bars_back(time, 1000)
//-----------------------------------------------------------------------
------}
//Calculations
//-----------------------------------------------------------------------
------{
x2 := b.i - 1
ph = [Link](liqLen, 1)
pl = [Link] (liqLen, 1)
if ph
dir := [Link](0)
x1 := [Link](0)
y1 := [Link](0)
y2 := nz(b.h[1])
if dir < 1
aZZ.in_out(1, x2, y2)
else
if dir == 1 and ph > y1
[Link](0, x2), [Link](0, y2)
if per
count = 0
st_P = 0.
st_B = 0
minP = 0.
maxP = 10e6
for i = 0 to maxSize - 1
if [Link](i) == 1
if [Link](i) > ph + (atr / liqMar)
break
else
if [Link](i) > ph - (atr / liqMar) and
[Link](i) < ph + (atr / liqMar)
count += 1
st_B := [Link](i)
st_P := [Link](i)
if [Link](i) > minP
minP := [Link](i)
if [Link](i) < maxP
maxP := [Link](i)
if count > 2
getB = b_liq_B.get(0)
if st_B == [Link].get_left()
[Link].set_top([Link](minP, maxP) + (atr / liqMar))
[Link].set_rightbottom(b.i + 10, [Link](minP, maxP) -
(atr / liqMar))
else
b_liq_B.unshift(
[Link](
[Link](st_B, [Link](minP, maxP) + (atr / liqMar),
b.i + 10, [Link](minP, maxP) - (atr / liqMar), bgcolor=color(na),
border_color=color(na)),
[Link](na, na, na, na, bgcolor = color(na),
border_color = color(na)),
[Link](st_B, st_P, b.i + 10, st_P, text = 'Buyside
liquidity', text_size = [Link], text_halign = text.align_left,
text_valign = text.align_bottom, text_color = [Link](cLIQ_B, 25),
bgcolor = color(na), border_color = color(na)),
false,
false,
[Link](st_B , st_P, b.i - 1, st_P, color =
[Link](cLIQ_B, 0)),
[Link](b.i - 1, st_P, na , st_P, color =
[Link](cLIQ_B, 0), style = line.style_dotted))
)
alert('buyside liquidity level detected/updated for ' +
[Link])
if b_liq_B.size() > visLiq
getLast = b_liq_B.pop()
[Link]()
[Link]()
[Link]()
[Link]()
[Link]()
if pl
dir := [Link] (0)
x1 := [Link] (0)
y1 := [Link] (0)
y2 := nz(b.l[1])
if dir > -1
aZZ.in_out(-1, x2, y2)
else
if dir == -1 and pl < y1
[Link](0, x2), [Link](0, y2)
if per
count = 0
st_P = 0.
st_B = 0
minP = 0.
maxP = 10e6
for i = 0 to maxSize - 1
if [Link](i) == -1
if [Link](i) < pl - (atr / liqMar)
break
else
if [Link](i) > pl - (atr / liqMar) and
[Link](i) < pl + (atr / liqMar)
count += 1
st_B := [Link](i)
st_P := [Link](i)
if [Link](i) > minP
minP := [Link](i)
if [Link](i) < maxP
maxP := [Link](i)
if count > 2
getB = b_liq_S.get(0)
if st_B == [Link].get_left()
[Link].set_top([Link](minP, maxP) + (atr / liqMar))
[Link].set_rightbottom(b.i + 10, [Link](minP, maxP) -
(atr / liqMar))
else
b_liq_S.unshift(
[Link](
[Link](st_B, [Link](minP, maxP) + (atr / liqMar),
b.i + 10, [Link](minP, maxP) - (atr / liqMar), bgcolor=color(na),
border_color=color(na)),
[Link](na, na, na, na, bgcolor=color(na),
border_color=color(na)),
[Link](st_B, st_P, b.i + 10, st_P, text = 'Sellside
liquidity', text_size = [Link], text_halign = text.align_left,
text_valign = text.align_top, text_color = [Link](cLIQ_S, 25),
bgcolor=color(na), border_color=color(na)),
false,
false,
[Link](st_B , st_P, b.i - 1, st_P, color =
[Link](cLIQ_S, 0)),
[Link](b.i - 1, st_P, na , st_P, color =
[Link](cLIQ_S, 0), style = line.style_dotted))
)
alert('sellside liquidity level detected/updated for ' +
[Link])
if b_liq_S.size() > visLiq
getLast = b_liq_S.pop()
[Link]()
[Link]()
[Link]()
[Link]()
[Link]()
for i = 0 to b_liq_B.size() - 1
x = b_liq_B.get(i)
if not [Link]
[Link].set_x2(b.i)
if b.h > [Link].get_top()
[Link] := true
[Link] := true
alert('buyside liquidity level breached for ' +
[Link])
[Link].set_lefttop(b.i - 1, [Link]([Link].get_y1() + marBuy *
(atr), b.h))
[Link].set_rightbottom(b.i + 1, [Link].get_y1())
[Link].set_bgcolor([Link](cLIQ_B, liqBuy ? 73 : 100))
else if [Link]
if b.l > [Link].get_y1() - marBuy * (atr) and b.h < [Link].get_y1() +
marBuy * (atr)
[Link].set_right(b.i + 1)
[Link].set_top([Link](b.h, [Link].get_top()))
if liqBuy
[Link].set_x2(b.i + 1)
else
[Link] := false
for i = 0 to b_liq_S.size() - 1
x = b_liq_S.get(i)
if not [Link]
[Link].set_x2(b.i)
if b.l < [Link].get_bottom()
[Link] := true
[Link] := true
alert('sellside liquidity level breached for ' +
[Link])
[Link].set_lefttop(b.i - 1, [Link].get_y1())
[Link].set_rightbottom(b.i + 1, [Link]([Link].get_y1() -
marSel * (atr), b.l))
[Link].set_bgcolor([Link](cLIQ_S, liqSel ? 73 : 100))
else if [Link]
if b.l > [Link].get_y1() - marSel * (atr) and b.h < [Link].get_y1() +
marSel * (atr)
[Link].set_rightbottom(b.i + 1, [Link](b.l,
[Link].get_bottom()))
if liqSel
[Link].set_x2(b.i + 1)
else
[Link] := false
if lqVoid and per
bull = b.l - b.h[2] > atr200 and b.l > b.h[2] and b.c[1] > b.h[2]
bear = b.l[2] - b.h > atr200 and b.h < b.l[2] and b.c[1] < b.l[2]
if bull
l = 13
if bull[1]
st = [Link](b.l - b.l[1]) / l
for i = 0 to l - 1
[Link](b_liq_V, [Link](b.i - 2, b.l[1] + i * st,
b.i, b.l[1] + (i + 1) * st, border_color = na, bgcolor =
[Link](cLQV_B, 90) ))
else
st = [Link](b.l - b.h[2]) / l
for i = 0 to l - 1
if lqText and i == 0
[Link](b_liq_V, [Link](b.i - 2, b.h[2] + i * st,
b.i, b.h[2] + (i + 1) * st, text = 'Liquidity Void ', text_size =
[Link], text_halign = text.align_right, text_valign =
text.align_bottom, text_color = na, border_color = na, bgcolor =
[Link](cLQV_B, 90) ))
else
[Link](b_liq_V, [Link](b.i - 2, b.h[2] + i * st,
b.i, b.h[2] + (i + 1) * st, border_color = na, bgcolor =
[Link](cLQV_B, 90) ))
if bear
l = 13
if bear[1]
st = [Link](b.h[1] - b.h) / l
for i = 0 to l - 1
[Link](b_liq_V, [Link](b.i - 2, b.h + i * st, b.i,
b.h + (i + 1) * st, border_color = na, bgcolor = [Link](cLQV_S, 90) ))
else
st = [Link](b.l[2] - b.h) / l
for i = 0 to l - 1
if lqText and i == l - 1
[Link](b_liq_V, [Link](b.i - 2, b.h + i * st,
b.i, b.h + (i + 1) * st, text = 'Liquidity Void ', text_size =
[Link], text_halign = text.align_right, text_valign = text.align_top,
text_color = na, border_color = na, bgcolor = [Link](cLQV_S, 90) ))
else
[Link](b_liq_V, [Link](b.i - 2, b.h + i * st,
b.i, b.h + (i + 1) * st, border_color = na, bgcolor = [Link](cLQV_S,
90) ))
if b_liq_V.size() > 0
qt = b_liq_V.size()
for bn = qt - 1 to 0
if bn < b_liq_V.size()
cb = b_liq_V.get(bn)
ba = [Link](cb.get_bottom(), cb.get_top())
if [Link](b.c[1] - ba) != [Link](b.c - ba) or
[Link](b.c[1] - ba) != [Link](b.l - ba) or [Link](b.c[1] - ba)
!= [Link](b.h - ba)
b_liq_V.remove(bn)
else
cb.set_right(b.i + 1)
if b.i - cb.get_left() > 21
cb.set_text_color([Link]([Link], 25))
//-----------------------------------------------------------------------
------}