0% found this document useful (0 votes)
562 views59 pages

Smart Money Concepts V40

This document is a Pine Script™ code for a trading indicator called 'Smart Money Concepts Premium'. It includes various settings and options for displaying market structures, order blocks, and price zones on a trading chart. The script allows users to customize the appearance and functionality of the indicator based on their trading strategies.

Uploaded by

xizhongxiao83
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
562 views59 pages

Smart Money Concepts V40

This document is a Pine Script™ code for a trading indicator called 'Smart Money Concepts Premium'. It includes various settings and options for displaying market structures, order blocks, and price zones on a trading chart. The script allows users to customize the appearance and functionality of the indicator based on their trading strategies.

Uploaded by

xizhongxiao83
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 59

// This Pine Script™ code is subject to the terms of the Mozilla Public License 2.

0
at https://mozilla.org/MPL/2.0/
// © DrunkXiao

//@version=5

indicator("Smart Money Concepts Premium", "Smart Money Concepts Premium"


, overlay = true
, max_labels_count = 500
, max_lines_count = 500
, max_boxes_count = 500
, max_bars_back = 1000)
//-----------------------------------------------------------------------------{
//Constants
//-----------------------------------------------------------------------------{
color TRANSP_CSS = #ffffff00

switchboard_group = "████ Turn On/Off Overlay Indicators ████"

switch_breaker = input.bool (true, "Breaker Blocks", group=switchboard_group,


inline='Switch1')
switch_poi = input.bool (true, "Supply/Demand Zone", group=switchboard_group,
inline='Switch1')
switch_bsl = input.bool (true, "BSL/SSL Zone", group=switchboard_group,
inline='Switch1')
switch_fvg = input.bool (true, "FVG Zone", group=switchboard_group,
inline='Switch2')
switch_ema = input.bool (true, "EMA line", group=switchboard_group,
inline='Switch2')
switch_halftrend= input.bool (true, "Half Trend", group=switchboard_group,
inline='Switch2')
switch_ts = input.bool (true, "Turtle Soup", group=switchboard_group,
inline='Switch2')
HTF_FVG = input.bool (true, "HTF FVG", group=switchboard_group, inline='Switch2')

//Tooltips
string MODE_TOOLTIP = 'Allows to display historical Structure or only the
recent ones'
string STYLE_TOOLTIP = 'Indicator color theme'
string COLOR_CANDLES_TOOLTIP = 'Display additional candles with a color reflecting
the current trend detected by structure'
string SHOW_INTERNAL = 'Display internal market structure'
string CONFLUENCE_FILTER = 'Filter non significant internal structure
breakouts'
string SHOW_SWING = 'Display swing market Structure'
string SHOW_SWING_POINTS = 'Display swing point as labels on the chart'
string SHOW_SWHL_POINTS = 'Highlight most recent strong and weak high/low
points on the chart'
string INTERNAL_OB = 'Display internal order blocks on the chart\n\
nNumber of internal order blocks to display on the chart'
string SWING_OB = 'Display swing order blocks on the chart\n\nNumber
of internal swing blocks to display on the chart'
string FILTER_OB = 'Method used to filter out volatile order blocks \n\
nIt is recommended to use the cumulative mean range method when a low amount of
data is available'
string SHOW_EQHL = 'Display equal highs and equal lows on the chart'
string EQHL_BARS = 'Number of bars used to confirm equal highs and
equal lows'
string EQHL_THRESHOLD = 'Sensitivity threshold in a range (0, 1) used for
the detection of equal highs & lows\n\nLower values will return fewer but more
pertinent results'
string SHOW_FVG = 'Display fair values gaps on the chart'
string AUTO_FVG = 'Filter out non significant fair value gaps'
string FVG_TF = 'Fair value gaps timeframe'
string EXTEND_FVG = 'Determine how many bars to extend the Fair Value
Gap boxes on chart'
string PED_ZONES = 'Display premium, discount, and equilibrium zones on
chart'

//-----------------------------------------------------------------------------{
//Settings
//-----------------------------------------------------------------------------{
//General
//----------------------------------------{
mode = input.string('Historical'
, options = ['Historical', 'Present']
, group = 'Smart Money Concepts'
, tooltip = MODE_TOOLTIP)

style = input.string('Colored'
, options = ['Colored', 'Monochrome']
, group = 'Smart Money Concepts'
, tooltip = STYLE_TOOLTIP)

show_trend = input(false, 'Color Candles'


, group = 'Smart Money Concepts'
, tooltip = COLOR_CANDLES_TOOLTIP)

//----------------------------------------}
//Internal Structure
//----------------------------------------{
show_internals = input(true, 'Show Internal Structure'
, group = 'Real Time Internal Structure'
, tooltip = SHOW_INTERNAL)

show_ibull = input.string('All', 'Bullish Structure'


, options = ['All', 'BOS', 'CHoCH']
, inline = 'ibull'
, group = 'Real Time Internal Structure')

swing_ibull_css = input(#00bcd4, ''


, inline = 'ibull'
, group = 'Real Time Internal Structure')

//Bear Structure
show_ibear = input.string('All', 'Bearish Structure'
, options = ['All', 'BOS', 'CHoCH']
, inline = 'ibear'
, group = 'Real Time Internal Structure')

swing_ibear_css = input(#e91e63, ''


, inline = 'ibear'
, group = 'Real Time Internal Structure')

ifilter_confluence = input(false, 'Confluence Filter'


, group = 'Real Time Internal Structure'
, tooltip = CONFLUENCE_FILTER)
internal_structure_size = input.string('Small', 'Internal Label Size'
, options = ['Tiny', 'Small', 'Normal']
, group = 'Real Time Internal Structure')

//----------------------------------------}
//Swing Structure
//----------------------------------------{
show_Structure = input(true, 'Show Swing Structure'
, group = 'Real Time Swing Structure'
, tooltip = SHOW_SWING)

//Bull Structure
show_bull = input.string('All', 'Bullish Structure'
, options = ['All', 'BOS', 'CHoCH']
, inline = 'bull'
, group = 'Real Time Swing Structure')

swing_bull_css = input(#00bcd4, ''


, inline = 'bull'
, group = 'Real Time Swing Structure')

//Bear Structure
show_bear = input.string('All', 'Bearish Structure'
, options = ['All', 'BOS', 'CHoCH']
, inline = 'bear'
, group = 'Real Time Swing Structure')

swing_bear_css = input(#e91e63, ''


, inline = 'bear'
, group = 'Real Time Swing Structure')

swing_structure_size = input.string('Tiny', 'Swing Label Size'


, options = ['Tiny', 'Small', 'Normal']
, group = 'Real Time Swing Structure')

//Swings
show_swings = input(false, 'Show Swings Points'
, inline = 'swings'
, group = 'Real Time Swing Structure'
, tooltip = SHOW_SWING_POINTS)

length = input.int(50, ''


, minval = 10
, inline = 'swings'
, group = 'Real Time Swing Structure')

show_hl_swings = input(true, 'Show Strong/Weak High/Low'


, group = 'Real Time Swing Structure'
, tooltip = SHOW_SWHL_POINTS)

//----------------------------------------}
//Order Blocks
//----------------------------------------{
show_iob = input(true, 'Internal Order Blocks'
, inline = 'iob'
, group = 'Order Blocks'
, tooltip = INTERNAL_OB)
iob_showlast = input.int(5, ''
, minval = 1
, inline = 'iob'
, group = 'Order Blocks')

show_ob = input(false, 'Swing Order Blocks'


, inline = 'ob'
, group = 'Order Blocks'
, tooltip = SWING_OB)

ob_showlast = input.int(5, ''


, minval = 1
, inline = 'ob'
, group = 'Order Blocks')

ob_filter = input.string('Atr', 'Order Block Filter'


, options = ['Atr', 'Cumulative Mean Range']
, group = 'Order Blocks'
, tooltip = FILTER_OB)

ibull_ob_css = input.color(color.new(#00bcd4, 90), 'Internal Bullish OB'


, group = 'Order Blocks')

ibear_ob_css = input.color(color.new(#E20061, 90), 'Internal Bearish OB'


, group = 'Order Blocks')

bull_ob_css = input.color(color.new(#00bcd4, 90), 'Bullish OB'


, group = 'Order Blocks')

bear_ob_css = input.color(color.new(#E20061, 90), 'Bearish OB'


, group = 'Order Blocks')

//----------------------------------------}
//EQH/EQL
//----------------------------------------{
show_eq = input(true, 'Equal High/Low'
, group = 'EQH/EQL'
, tooltip = SHOW_EQHL)

eq_len = input.int(3, 'Bars Confirmation'


, minval = 1
, group = 'EQH/EQL'
, tooltip = EQHL_BARS)

eq_threshold = input.float(0.1, 'Threshold'


, minval = 0
, maxval = 0.5
, step = 0.1
, group = 'EQH/EQL'
, tooltip = EQHL_THRESHOLD)

eq_size = input.string('Tiny', 'Label Size'


, options = ['Tiny', 'Small', 'Normal']
, group = 'EQH/EQL')

//----------------------------------------}
//Previous day/week high/low
//----------------------------------------{
//Daily
show_pdhl = input(false, 'Daily'
, inline = 'daily'
, group = 'Highs & Lows MTF')

pdhl_style = input.string('⎯⎯⎯', ''


, options = ['⎯⎯⎯', '----', '····']
, inline = 'daily'
, group = 'Highs & Lows MTF')

pdhl_css = input(#2157f3, ''


, inline = 'daily'
, group = 'Highs & Lows MTF')

//Weekly
show_pwhl = input(false, 'Weekly'
, inline = 'weekly'
, group = 'Highs & Lows MTF')

pwhl_style = input.string('⎯⎯⎯', ''


, options = ['⎯⎯⎯', '----', '····']
, inline = 'weekly'
, group = 'Highs & Lows MTF')

pwhl_css = input(#2157f3, ''


, inline = 'weekly'
, group = 'Highs & Lows MTF')

//Monthly
show_pmhl = input(false, 'Monthly'
, inline = 'monthly'
, group = 'Highs & Lows MTF')

pmhl_style = input.string('⎯⎯⎯', ''


, options = ['⎯⎯⎯', '----', '····']
, inline = 'monthly'
, group = 'Highs & Lows MTF')

pmhl_css = input(#2157f3, ''


, inline = 'monthly'
, group = 'Highs & Lows MTF')

//----------------------------------------}
//Premium/Discount zones
//----------------------------------------{
show_sd = input(false, 'Premium/Discount Zones'
, group = 'Premium & Discount Zones'
, tooltip = PED_ZONES)

premium_css = input.color(#f23645, 'Premium Zone'


, group = 'Premium & Discount Zones')

eq_css = input.color(#b2b5be, 'Equilibrium Zone'


, group = 'Premium & Discount Zones')

discount_css = input.color(#089981, 'Discount Zone'


, group = 'Premium & Discount Zones')
//-----------------------------------------------------------------------------}
//Functions
//-----------------------------------------------------------------------------{
n = bar_index

atr = ta.atr(200)
cmean_range = ta.cum(high - low) / n

//HL Output function


hl() => [high, low]

//Get ohlc values function


get_ohlc()=> [close[1], open[1], high, low, high[2], low[2]]

//Display Structure function


display_Structure(x, y, txt, css, dashed, down, lbl_size)=>
structure_line = line.new(x, y, n, y
, color = css
, style = dashed ? line.style_dashed : line.style_solid)

structure_lbl = label.new(int(math.avg(x, n)), y, txt


, color = TRANSP_CSS
, textcolor = css
, style = down ? label.style_label_down : label.style_label_up
, size = lbl_size)

if mode == 'Present'
line.delete(structure_line[1])
label.delete(structure_lbl[1])

//Swings detection/measurements
swings(len)=>
var os = 0

upper = ta.highest(len)
lower = ta.lowest(len)

os := high[len] > upper ? 0 : low[len] < lower ? 1 : os[1]

top = os == 0 and os[1] != 0 ? high[len] : 0


btm = os == 1 and os[1] != 1 ? low[len] : 0

[top, btm]

//Order block coordinates function


ob_coord(use_max, loc, target_top, target_btm, target_left, target_type)=>
min = 99999999.
max = 0.
idx = 1

ob_threshold = ob_filter == 'Atr' ? atr : cmean_range

//Search for highest/lowest high within the structure interval and get range
if use_max
for i = 1 to (n - loc)-1
if (high[i] - low[i]) < ob_threshold[i] * 2
max := math.max(high[i], max)
min := max == high[i] ? low[i] : min
idx := max == high[i] ? i : idx
else
for i = 1 to (n - loc)-1
if (high[i] - low[i]) < ob_threshold[i] * 2
min := math.min(low[i], min)
max := min == low[i] ? high[i] : max
idx := min == low[i] ? i : idx

array.unshift(target_top, max)
array.unshift(target_btm, min)
array.unshift(target_left, time[idx])
array.unshift(target_type, use_max ? -1 : 1)

//Set order blocks


display_ob(boxes, target_top, target_btm, target_left, target_type, show_last,
swing, size)=>
for i = 0 to math.min(show_last-1, size-1)
get_box = array.get(boxes, i)

box.set_lefttop(get_box, array.get(target_left, i), array.get(target_top,


i))
box.set_rightbottom(get_box, array.get(target_left, i),
array.get(target_btm, i))
box.set_extend(get_box, extend.right)

color css = na

if swing
if style == 'Monochrome'
css := array.get(target_type, i) == 1 ? color.new(#b2b5be, 80) :
color.new(#5d606b, 80)
border_css = array.get(target_type, i) == 1 ? #b2b5be : #5d606b
box.set_border_color(get_box, border_css)
else
css := array.get(target_type, i) == 1 ? bull_ob_css : bear_ob_css
box.set_border_color(get_box, css)

box.set_bgcolor(get_box, css)
else
if style == 'Monochrome'
css := array.get(target_type, i) == 1 ? color.new(#b2b5be, 80) :
color.new(#5d606b, 80)
else
css := array.get(target_type, i) == 1 ? ibull_ob_css : ibear_ob_css

box.set_border_color(get_box, css)
box.set_bgcolor(get_box, css)

//Line Style function


get_line_style(style) =>
out = switch style
'⎯⎯⎯' => line.style_solid
'----' => line.style_dashed
'····' => line.style_dotted

//Set line/labels function for previous high/lows


phl(h, l, tf, css)=>
var line high_line = line.new(na,na,na,na
, xloc = xloc.bar_time
, color = css
, style = get_line_style(pdhl_style))

var label high_lbl = label.new(na,na


, xloc = xloc.bar_time
, text = str.format('P{0}H', tf)
, color = TRANSP_CSS
, textcolor = css
, size = size.small
, style = label.style_label_left)

var line low_line = line.new(na,na,na,na


, xloc = xloc.bar_time
, color = css
, style = get_line_style(pdhl_style))

var label low_lbl = label.new(na,na


, xloc = xloc.bar_time
, text = str.format('P{0}L', tf)
, color = TRANSP_CSS
, textcolor = css
, size = size.small
, style = label.style_label_left)

hy = ta.valuewhen(h != h[1], h, 1)
hx = ta.valuewhen(h == high, time, 1)

ly = ta.valuewhen(l != l[1], l, 1)
lx = ta.valuewhen(l == low, time, 1)

if barstate.islast
ext = time + (time - time[1])*20

//High
line.set_xy1(high_line, hx, hy)
line.set_xy2(high_line, ext, hy)

label.set_xy(high_lbl, ext, hy)

//Low
line.set_xy1(low_line, lx, ly)
line.set_xy2(low_line, ext, ly)

label.set_xy(low_lbl, ext, ly)

//-----------------------------------------------------------------------------}
//Global variables
//-----------------------------------------------------------------------------{
var trend = 0, var itrend = 0

var top_y = 0., var top_x = 0


var btm_y = 0., var btm_x = 0

var itop_y = 0., var itop_x = 0


var ibtm_y = 0., var ibtm_x = 0

var trail_up = high, var trail_dn = low


var trail_up_x = 0, var trail_dn_x = 0

var top_cross = true, var btm_cross = true


var itop_cross = true, var ibtm_cross = true

var txt_top = '', var txt_btm = ''

//Alerts
bull_choch_alert = false
bull_bos_alert = false

bear_choch_alert = false
bear_bos_alert = false

bull_ichoch_alert = false
bull_ibos_alert = false

bear_ichoch_alert = false
bear_ibos_alert = false

bull_iob_break = false
bear_iob_break = false

bull_ob_break = false
bear_ob_break = false

eqh_alert = false
eql_alert = false

//Structure colors
var bull_css = style == 'Monochrome' ? #b2b5be
: swing_bull_css

var bear_css = style == 'Monochrome' ? #b2b5be


: swing_bear_css

var ibull_css = style == 'Monochrome' ? #b2b5be


: swing_ibull_css

var ibear_css = style == 'Monochrome' ? #b2b5be


: swing_ibear_css

//Labels size
var internal_structure_lbl_size = internal_structure_size == 'Tiny'
? size.tiny
: internal_structure_size == 'Small'
? size.small
: size.normal

var swing_structure_lbl_size = swing_structure_size == 'Tiny'


? size.tiny
: swing_structure_size == 'Small'
? size.small
: size.normal

var eqhl_lbl_size = eq_size == 'Tiny'


? size.tiny
: eq_size == 'Small'
? size.small
: size.normal

//Swings
[top, btm] = swings(length)

[itop, ibtm] = swings(5)

//-----------------------------------------------------------------------------}
//Pivot High
//-----------------------------------------------------------------------------{
var line extend_top = na

var label extend_top_lbl = label.new(na, na


, color = TRANSP_CSS
, textcolor = bear_css
, style = label.style_label_down
, size = size.tiny)

if top
top_cross := true
txt_top := top > top_y ? 'HH' : 'LH'

if show_swings
top_lbl = label.new(n-length, top, txt_top
, color = TRANSP_CSS
, textcolor = bear_css
, style = label.style_label_down
, size = swing_structure_lbl_size)

if mode == 'Present'
label.delete(top_lbl[1])

//Extend recent top to last bar


line.delete(extend_top[1])
extend_top := line.new(n-length, top, n, top
, color = bear_css)

top_y := top
top_x := n - length

trail_up := top
trail_up_x := n - length

if itop
itop_cross := true

itop_y := itop
itop_x := n - 5

//Trailing maximum
trail_up := math.max(high, trail_up)
trail_up_x := trail_up == high ? n : trail_up_x

//Set top extension label/line


if barstate.islast and show_hl_swings
line.set_xy1(extend_top, trail_up_x, trail_up)
line.set_xy2(extend_top, n + 20, trail_up)

label.set_x(extend_top_lbl, n + 20)
label.set_y(extend_top_lbl, trail_up)
label.set_text(extend_top_lbl, trend < 0 ? 'Strong High' : 'Weak High')
//-----------------------------------------------------------------------------}
//Pivot Low
//-----------------------------------------------------------------------------{
var line extend_btm = na

var label extend_btm_lbl = label.new(na, na


, color = TRANSP_CSS
, textcolor = bull_css
, style = label.style_label_up
, size = size.tiny)

if btm
btm_cross := true
txt_btm := btm < btm_y ? 'LL' : 'HL'

if show_swings
btm_lbl = label.new(n - length, btm, txt_btm
, color = TRANSP_CSS
, textcolor = bull_css
, style = label.style_label_up
, size = swing_structure_lbl_size)

if mode == 'Present'
label.delete(btm_lbl[1])

//Extend recent btm to last bar


line.delete(extend_btm[1])
extend_btm := line.new(n - length, btm, n, btm
, color = bull_css)

btm_y := btm
btm_x := n-length

trail_dn := btm
trail_dn_x := n-length

if ibtm
ibtm_cross := true

ibtm_y := ibtm
ibtm_x := n - 5

//Trailing minimum
trail_dn := math.min(low, trail_dn)
trail_dn_x := trail_dn == low ? n : trail_dn_x

//Set btm extension label/line


if barstate.islast and show_hl_swings
line.set_xy1(extend_btm, trail_dn_x, trail_dn)
line.set_xy2(extend_btm, n + 20, trail_dn)

label.set_x(extend_btm_lbl, n + 20)
label.set_y(extend_btm_lbl, trail_dn)
label.set_text(extend_btm_lbl, trend > 0 ? 'Strong Low' : 'Weak Low')

//-----------------------------------------------------------------------------}
//Order Blocks Arrays
//-----------------------------------------------------------------------------{
var iob_top = array.new_float(0)
var iob_btm = array.new_float(0)
var iob_left = array.new_int(0)
var iob_type = array.new_int(0)

var ob_top = array.new_float(0)


var ob_btm = array.new_float(0)
var ob_left = array.new_int(0)
var ob_type = array.new_int(0)

//-----------------------------------------------------------------------------}
//Pivot High BOS/CHoCH
//-----------------------------------------------------------------------------{
//Filtering
var bull_concordant = true

if ifilter_confluence
bull_concordant := high - math.max(close, open) > math.min(close, open - low)

//Detect internal bullish Structure


if ta.crossover(close, itop_y) and itop_cross and top_y != itop_y and
bull_concordant
bool choch = na

if itrend < 0
choch := true
bull_ichoch_alert := true
else
bull_ibos_alert := true

txt = choch ? 'CHoCH' : 'BOS'

if show_internals
if show_ibull == 'All' or (show_ibull == 'BOS' and not choch) or
(show_ibull == 'CHoCH' and choch)
display_Structure(itop_x, itop_y, txt, ibull_css, true, true,
internal_structure_lbl_size)

itop_cross := false
itrend := 1

//Internal Order Block


if show_iob
ob_coord(false, itop_x, iob_top, iob_btm, iob_left, iob_type)

//Detect bullish Structure


if ta.crossover(close, top_y) and top_cross
bool choch = na

if trend < 0
choch := true
bull_choch_alert := true
else
bull_bos_alert := true

txt = choch ? 'CHoCH' : 'BOS'

if show_Structure
if show_bull == 'All' or (show_bull == 'BOS' and not choch) or (show_bull
== 'CHoCH' and choch)
display_Structure(top_x, top_y, txt, bull_css, false, true,
swing_structure_lbl_size)

//Order Block
if show_ob
ob_coord(false, top_x, ob_top, ob_btm, ob_left, ob_type)

top_cross := false
trend := 1

//-----------------------------------------------------------------------------}
//Pivot Low BOS/CHoCH
//-----------------------------------------------------------------------------{
var bear_concordant = true

if ifilter_confluence
bear_concordant := high - math.max(close, open) < math.min(close, open - low)

//Detect internal bearish Structure


if ta.crossunder(close, ibtm_y) and ibtm_cross and btm_y != ibtm_y and
bear_concordant
bool choch = false

if itrend > 0
choch := true
bear_ichoch_alert := true
else
bear_ibos_alert := true

txt = choch ? 'CHoCH' : 'BOS'

if show_internals
if show_ibear == 'All' or (show_ibear == 'BOS' and not choch) or
(show_ibear == 'CHoCH' and choch)
display_Structure(ibtm_x, ibtm_y, txt, ibear_css, true, false,
internal_structure_lbl_size)

ibtm_cross := false
itrend := -1

//Internal Order Block


if show_iob
ob_coord(true, ibtm_x, iob_top, iob_btm, iob_left, iob_type)

//Detect bearish Structure


if ta.crossunder(close, btm_y) and btm_cross
bool choch = na

if trend > 0
choch := true
bear_choch_alert := true
else
bear_bos_alert := true

txt = choch ? 'CHoCH' : 'BOS'

if show_Structure
if show_bear == 'All' or (show_bear == 'BOS' and not choch) or (show_bear
== 'CHoCH' and choch)
display_Structure(btm_x, btm_y, txt, bear_css, false, false,
swing_structure_lbl_size)

//Order Block
if show_ob
ob_coord(true, btm_x, ob_top, ob_btm, ob_left, ob_type)

btm_cross := false
trend := -1

//-----------------------------------------------------------------------------}
//Order Blocks
//-----------------------------------------------------------------------------{
//Set order blocks
var iob_boxes = array.new_box(0)
var ob_boxes = array.new_box(0)

//Delete internal order blocks box coordinates if top/bottom is broken


for element in iob_type
index = array.indexof(iob_type, element)

if close < array.get(iob_btm, index) and element == 1


array.remove(iob_top, index)
array.remove(iob_btm, index)
array.remove(iob_left, index)
array.remove(iob_type, index)
bull_iob_break := true

else if close > array.get(iob_top, index) and element == -1


array.remove(iob_top, index)
array.remove(iob_btm, index)
array.remove(iob_left, index)
array.remove(iob_type, index)
bear_iob_break := true

//Delete internal order blocks box coordinates if top/bottom is broken


for element in ob_type
index = array.indexof(ob_type, element)

if close < array.get(ob_btm, index) and element == 1


array.remove(ob_top, index)
array.remove(ob_btm, index)
array.remove(ob_left, index)
array.remove(ob_type, index)
bull_ob_break := true

else if close > array.get(ob_top, index) and element == -1


array.remove(ob_top, index)
array.remove(ob_btm, index)
array.remove(ob_left, index)
array.remove(ob_type, index)
bear_ob_break := true

iob_size = array.size(iob_type)
ob_size = array.size(ob_type)

if barstate.isfirst
if show_iob
for i = 0 to iob_showlast-1
array.push(iob_boxes, box.new(na,na,na,na, xloc = xloc.bar_time))
if show_ob
for i = 0 to ob_showlast-1
array.push(ob_boxes, box.new(na,na,na,na, xloc = xloc.bar_time))

if iob_size > 0
if barstate.islast
display_ob(iob_boxes, iob_top, iob_btm, iob_left, iob_type, iob_showlast,
false, iob_size)

if ob_size > 0
if barstate.islast
display_ob(ob_boxes, ob_top, ob_btm, ob_left, ob_type, ob_showlast, true,
ob_size)

//-----------------------------------------------------------------------------}
//EQH/EQL
//-----------------------------------------------------------------------------{
var eq_prev_top = 0.
var eq_top_x = 0

var eq_prev_btm = 0.
var eq_btm_x = 0

if show_eq
eq_top = ta.pivothigh(eq_len, eq_len)
eq_btm = ta.pivotlow(eq_len, eq_len)

if eq_top
max = math.max(eq_top, eq_prev_top)
min = math.min(eq_top, eq_prev_top)

if max < min + atr * eq_threshold


eqh_line = line.new(eq_top_x, eq_prev_top, n-eq_len, eq_top
, color = bear_css
, style = line.style_dotted)

eqh_lbl = label.new(int(math.avg(n-eq_len, eq_top_x)), eq_top, 'EQH'


, color = #00000000
, textcolor = bear_css
, style = label.style_label_down
, size = eqhl_lbl_size)

if mode == 'Present'
line.delete(eqh_line[1])
label.delete(eqh_lbl[1])

eqh_alert := true

eq_prev_top := eq_top
eq_top_x := n-eq_len

if eq_btm
max = math.max(eq_btm, eq_prev_btm)
min = math.min(eq_btm, eq_prev_btm)

if min > max - atr * eq_threshold


eql_line = line.new(eq_btm_x, eq_prev_btm, n-eq_len, eq_btm
, color = bull_css
, style = line.style_dotted)

eql_lbl = label.new(int(math.avg(n-eq_len, eq_btm_x)), eq_btm, 'EQL'


, color = #00000000
, textcolor = bull_css
, style = label.style_label_up
, size = eqhl_lbl_size)

eql_alert := true

if mode == 'Present'
line.delete(eql_line[1])
label.delete(eql_lbl[1])

eq_prev_btm := eq_btm
eq_btm_x := n-eq_len

///////////////////////////////////////////////////
///////// Fair Value gap
////////////////////////////////////////////////////

fvggroup = "████ Fair Value Gap (FVG) ████"


numDays = input.int(30, "number of days lookback",group=fvggroup)
showUP = input.bool(true, "'UP' FVGs:", inline ='1',group=fvggroup)
colUp = input.color(color.new(#00e676, 90), "", inline ='1',group=fvggroup)
showDN = input.bool(true, "'DOWN' FVGs:", inline ='2',group=fvggroup)
colDn = input.color(color.new(#f57c00, 90), "", inline ='2',group=fvggroup)
showCE = input.bool(true, "show CE", inline ='3',group=fvggroup)
ceCol = input.color(color.new(#ffffff, 70), "| color:", inline ='3',group=fvggroup)
ceStyle = input.string(line.style_dotted, "| style:",
options=[line.style_dotted,line.style_solid, line.style_dashed], inline
='3',group=fvggroup)
deleteFilledBoxes = input.bool(true, "delete filled boxes & lines",group=fvggroup)
CEcond = input.bool (false, "Use CE (as opposed to Full Fill)",group=fvggroup,
tooltip = "If toggled OFF, FVGs and CEs will paint until FVG has been completely
filled.\n\nThis threshold is used for Above/Below threshold Alert conditions too
(but does not effect the IOFED alerts):\ni.e. this will determine if your 'ABOVE
threshold' alert fires when price hits most recent FVG CE ABOVE or most recent FVG
Full Fill ABOVE\n\nAlerts are set by clicking the three dots on the indicator
display line.")
colorNone = color.new(color.white, 100)
_day = 24*3600*1000
var box bxUp = na, var box bxDn = na, var line lnUp = na, var line lnDn = na
var array<box> bxUpArr = array.new<box>(0), var array<line> lnUpArr =
array.new<line>(0)
var array<box> bxDnArr = array.new<box>(0), var array<line> lnDnArr =
array.new<line>(0)
dnCE = high[1] + (low[3]-high[1])/2
upCE = low[1] - (low[1]-high[3])/2
if low[3] > high[1] and time> timenow- numDays*_day and showDN and switch_fvg
bxDnArr.push(box.new(bar_index-3, low[3], bar_index, high[1], bgcolor = colDn,
border_color = colorNone))
lnDnArr.push(line.new(bar_index-3, dnCE, bar_index, dnCE, color = showCE?
ceCol:colorNone, style =ceStyle))
if high[3] < low[1] and time> timenow- numDays*_day and showUP and switch_fvg
bxUpArr.push(box.new(bar_index-3, low[1], bar_index, high[3], bgcolor = colUp,
border_color = colorNone))
lnUpArr.push(line.new(bar_index-3, upCE, bar_index, upCE, color = showCE?
ceCol:colorNone, style =ceStyle))

var array<int> _countArr =array.new<int>(0)


var array<int> _countArrIOFED =array.new<int>(0)

//modified form of @Bjorgum's looping function. This stops boxes/lines


painting when price passes to or through them
extendAndRemoveBx(array<box> boxArray, array<line> lineArray, array<int> countArr1,
array<int> countArr2, simple bool isBull, int maxSize) =>
if boxArray.size() > 0
for i = boxArray.size() -1 to 0
line ln = lineArray.get(i)
box bx = boxArray.get(i)
bx.set_right(bar_index+10)
ln.set_x2(bar_index+10)
float price = CEcond?ln.get_price(bar_index+10):(isBull?
bx.get_top():bx.get_bottom())
float price_IOFED = isBull?bx.get_bottom():bx.get_top()
int m = isBull ? 1 : -1
float hiLo = isBull ? high : low
if hiLo * m > price * m
boxArray.remove(i)
lineArray.remove(i)
countArr1.push(isBull?1:-1) //for 'above/below threshold alerts;
counter sum will decrement 1 on lower threshold hit, increment 1 on upper threshold
hit
if deleteFilledBoxes
bx.set_bgcolor(colorNone)
ln.set_color(colorNone)
if hiLo*m>price_IOFED*m
countArr2.push(isBull?1:-1)

if boxArray.size() > maxSize


box.delete(boxArray.shift())
line.delete(lineArray.shift())

extendAndRemoveBx(bxDnArr,lnDnArr,_countArr,_countArrIOFED, true, 12) //12 should


be good for around 2200 bars of history
extendAndRemoveBx(bxUpArr, lnUpArr,_countArr,_countArrIOFED, false, 12)

upThresholdLst = array.sum(_countArr)>array.sum(_countArr)[1]
dnThresholdLst = array.sum(_countArr)<array.sum(_countArr)[1]

upIOFEDlast= array.sum(_countArrIOFED)>array.sum(_countArrIOFED)[1]
dnIOFEDlast= array.sum(_countArrIOFED)<array.sum(_countArrIOFED)[1]

// alertcondition(upThresholdLst, "ABOVE threshold (CE or fvg High)", "UP threshold


hit")
// alertcondition(dnThresholdLst, "BELOW threshold (CE or fvg low)", "DOWN
threshold hit")

// alertcondition(upIOFEDlast, "IOFED up", "price entered FVG above")


// alertcondition(dnIOFEDlast, "IOFED down", "price entered FVG below")

//-----------------------------------------------------------------------------}
//Previous day/week high/lows
//-----------------------------------------------------------------------------{
//Daily high/low
[pdh, pdl] = request.security(syminfo.tickerid, 'D', hl()
, lookahead = barmerge.lookahead_on)

//Weekly high/low
[pwh, pwl] = request.security(syminfo.tickerid, 'W', hl()
, lookahead = barmerge.lookahead_on)

//Monthly high/low
[pmh, pml] = request.security(syminfo.tickerid, 'M', hl()
, lookahead = barmerge.lookahead_on)

//Display Daily
if show_pdhl
phl(pdh, pdl, 'D', pdhl_css)

//Display Weekly
if show_pwhl
phl(pwh, pwl, 'W', pwhl_css)

//Display Monthly
if show_pmhl
phl(pmh, pml, 'M', pmhl_css)

//-----------------------------------------------------------------------------}
//Premium/Discount/Equilibrium zones
//-----------------------------------------------------------------------------{
var premium = box.new(na, na, na, na
, bgcolor = color.new(premium_css, 80)
, border_color = na)

var premium_lbl = label.new(na, na


, text = 'Premium'
, color = TRANSP_CSS
, textcolor = premium_css
, style = label.style_label_down
, size = size.small)

var eq = box.new(na, na, na, na


, bgcolor = color.rgb(120, 123, 134, 80)
, border_color = na)

var eq_lbl = label.new(na, na


, text = 'Equilibrium'
, color = TRANSP_CSS
, textcolor = eq_css
, style = label.style_label_left
, size = size.small)

var discount = box.new(na, na, na, na


, bgcolor = color.new(discount_css, 80)
, border_color = na)

var discount_lbl = label.new(na, na


, text = 'Discount'
, color = TRANSP_CSS
, textcolor = discount_css
, style = label.style_label_up
, size = size.small)
//Show Premium/Discount Areas
if barstate.islast and show_sd
avg = math.avg(trail_up, trail_dn)

box.set_lefttop(premium, math.max(top_x, btm_x), trail_up)


box.set_rightbottom(premium, n, .95 * trail_up + .05 * trail_dn)

label.set_xy(premium_lbl, int(math.avg(math.max(top_x, btm_x), n)), trail_up)

box.set_lefttop(eq, math.max(top_x, btm_x), .525 * trail_up + .475*trail_dn)


box.set_rightbottom(eq, n, .525 * trail_dn + .475 * trail_up)

label.set_xy(eq_lbl, n, avg)

box.set_lefttop(discount, math.max(top_x, btm_x), .95 * trail_dn + .05 *


trail_up)
box.set_rightbottom(discount, n, trail_dn)
label.set_xy(discount_lbl, int(math.avg(math.max(top_x, btm_x), n)), trail_dn)

//-----------------------------------------------------------------------------}
//Trend
//-----------------------------------------------------------------------------{
var color trend_css = na

if show_trend
if style == 'Colored'
trend_css := itrend == 1 ? bull_css : bear_css
else if style == 'Monochrome'
trend_css := itrend == 1 ? #b2b5be : #5d606b

plotcandle(open, high, low, close


, color = trend_css
, wickcolor = trend_css
, bordercolor = trend_css
, editable = false)

//-----------------------------------------------------------------------------}
//Alerts
//-----------------------------------------------------------------------------{
//Internal Structure
//alertcondition(bull_ibos_alert, 'Internal Bullish BOS', 'Internal Bullish BOS
formed')
//alertcondition(bull_ichoch_alert, 'Internal Bullish CHoCH', 'Internal Bullish
CHoCH formed')

//alertcondition(bear_ibos_alert, 'Internal Bearish BOS', 'Internal Bearish BOS


formed')
//alertcondition(bear_ichoch_alert, 'Internal Bearish CHoCH', 'Internal Bearish
CHoCH formed')

//Swing Structure
//alertcondition(bull_bos_alert, 'Bullish BOS', 'Internal Bullish BOS formed')
//alertcondition(bull_choch_alert, 'Bullish CHoCH', 'Internal Bullish CHoCH
formed')

//alertcondition(bear_bos_alert, 'Bearish BOS', 'Bearish BOS formed')


//alertcondition(bear_choch_alert, 'Bearish CHoCH', 'Bearish CHoCH formed')
//order Blocks
//alertcondition(bull_iob_break, 'Bullish Internal OB Breakout', 'Price broke
bullish internal OB')
//alertcondition(bear_iob_break, 'Bearish Internal OB Breakout', 'Price broke
bearish internal OB')

//alertcondition(bull_ob_break, 'Bullish Swing OB Breakout', 'Price broke bullish


swing OB')
//alertcondition(bear_ob_break, 'Bearish Swing OB Breakout', 'Price broke bearish
swing OB')

//EQH/EQL
//alertcondition(eqh_alert, 'Equal Highs', 'Equal highs detected')
//alertcondition(eql_alert, 'Equal Lows', 'Equal lows detected')

//FVG
//alertcondition(bullish_fvg_cnd, 'Bullish FVG', 'Bullish FVG formed')
//alertcondition(bearish_fvg_cnd, 'Bearish FVG', 'Bearish FVG formed')

//HTF FVG D/W/M [TrunkXiao]


///////////////////////////////////////////////////////////////////////////////////
//////////////////////////// MTF FVG (price overlay)
tfinput2 = input.timeframe(defval="Weekly", title=' Timeframe ',
options=["Daily", "Weekly", "Monthly"], group = 'HTF FVG Settings', inline='1')
upcol1 = input.color(color.new(#ffffff, 94), 'Box/Border/Text - UP',
inline='appup', group = 'HTF FVG Settings')
upbordercol = input.color(color.rgb(76, 175, 79, 100), '', inline='appup',
group = 'HTF FVG Settings')
uptextcol = input.color(color.new(color.yellow,0), '', inline='appup', group
= 'HTF FVG Settings')
downcol1 = input.color(color.new(#ffffff, 94), 'Box/Border/Text - DOWN',
inline='appdown', group = 'HTF FVG Settings')
downbordercol = input.color(color.rgb(255, 82, 82, 100), '', inline='appdown',
group = 'HTF FVG Settings')
downtextcol = input.color(color.new(color.yellow, 0), '', inline='appdown',
group = 'HTF FVG Settings')
showboxtext = input.bool(defval=true, title="Text", inline='appdown2', group =
'HTF FVG Settings')
showboxes = input.bool(true, 'Show Boxes', inline='appdown2', group = 'HTF
FVG Settings')
extendtilfilled = input.bool(true, '', group = 'HTF FVG Settings', inline='fill')
filledtype = input.string('Full Fill', 'Fill Condition ',
options=['Touch', 'Full Fill', 'Half Fill'], group = 'HTF FVG Settings',
inline='fill')
hidefilled = input.bool(true, 'Hide Filled Levels', group = 'HTF FVG
Settings', inline='fill2')
lookbackm = input.bool(true, '', inline='lb', group = 'HTF FVG Settings')
fvgdaysBack = input.float(30, 'Lookback (D) ', group = 'HTF FVG
Settings',inline='lb')
maxBoxes = input.int(defval=4, title="Maximum Boxes", minval=0, maxval=499,
step=1, group = 'HTF FVG Settings',inline='lc')
conditiontype = 'None'
nmbars = 3500
linestylem = input.string(defval='Dotted', title="25/50/75% Style",
options=['Dotted', 'Solid', 'Dashed'], inline='he', group='HTF FVG Settings')
lineCol = input.color(color.new(color.silver,0), title='', inline='he',
group='HTF FVG Settings')
wdth = input.int(defval=1, title="Width", minval=0, maxval=4, step=1,
group = 'HTF FVG Settings',inline='he')
nbars = 4

//convert timeframe inputs


tfinput = ''
if tfinput2 == "Daily"
tfinput := "D"
if tfinput2 == "Weekly"
tfinput := "W"
if tfinput2 == "Monthly"
tfinput := "M"

// Requesting HTF data


[o, h, l, c] = request.security(syminfo.tickerid, tfinput, [open, high, low,
close])
[o1, h1, l1, c1] = request.security(syminfo.tickerid, tfinput, [open[1], high[1],
low[1], close[1]])
[o2, h2, l2, c2] = request.security(syminfo.tickerid, tfinput, [open[2], high[2],
low[2], close[2]])
t = request.security(syminfo.tickerid, tfinput, time)
bool new = ta.change(time(tfinput))

clear = color.rgb(0,0,0,100)
color upcol = showboxes ? upcol1 : clear
color downcol = showboxes ? downcol1 : clear

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 = lookbackm ? (daysLeft < fvgdaysBack) : true

// Timeframe labels
timeframelabel(tfinput) =>
switch tfinput
'' => timeframe.period + (timeframe.isminutes ? 'm' : na)
'1' => '1m'
'2' => '2m'
'3' => '3m'
'4' => '4m'
'5' => '5m'
'10' => '10m'
'15' => '15m'
'30' => '30m'
'60' => '1 Hr'
'120' => '2 Hr'
'240' => '4 Hr'
'480' => '8 Hr'
'720' => '12 Hr'
=> tfinput

// Box Text
var string imbboxtext = na, var string gapboxtext = na, var string wickboxtext
= na

if showboxtext and HTF_FVG//and textType == 'Labels + Timeframe'


imbboxtext := str.tostring(timeframelabel(tfinput) + ' ' +
str.tostring("FVG"))

// Line style and text label appearance


lineStyle(x) =>
switch x
'Solid' => line.style_solid
'Dashed' => line.style_dashed
'Dotted' => line.style_dotted

// Conditions for Imbalances, Gaps and Wicks


var bool condition = na, var bool condition2 = na, var bool condition3 = na, var
bool condition4 = na, var bool condition5 = na, var bool condition6 = na

if conditiontype == 'None'
condition := true
condition2 := true
condition3 := true
condition4 := true
condition5 := true
condition6 := true

// Drawing Boxes and Lines


var boxes = array.new_box(), var topLines = array.new_line(), var
middleLines = array.new_line(), var bottomLines = array.new_line()

if (l > h2) and condition and inRange and new and HTF_FVG//and fvg1hr
imbboxUP = box.new(t[2], l, time, h2, bgcolor = upcol,
border_color=upbordercol,border_width = 1, text=imbboxtext, text_size = size.small,
text_halign = text.align_right, text_valign = text.align_center, text_color =
uptextcol,xloc = xloc.bar_time)
topLine = line.new(t[2], (((l + h2)/2) + l)/2, time, (((l + h2)/2) + l)/2,
color=lineCol, style=lineStyle(linestylem), xloc = xloc.bar_time, width=wdth)
bottomLine = line.new(t[2], (((l + h2)/2) + h2)/2, time, (((l + h2)/2) + h2)/2,
color=lineCol, style=lineStyle(linestylem), xloc = xloc.bar_time, width=wdth)
middleLine = line.new(t[2], (l + h2)/2, last_bar_time, (l + h2)/2,
color=lineCol, style=lineStyle(linestylem), xloc = xloc.bar_time, width=wdth)
array.push(topLines, topLine)
array.push(middleLines, middleLine)
array.push(bottomLines, bottomLine)
array.push(boxes, imbboxUP)
if (h < l2) and condition2 and inRange and new and HTF_FVG//and fvg1hr
imbboxDOWN = box.new(t[2], h, time, l2, bgcolor = downcol,
border_color=downbordercol,border_width = 1, text=imbboxtext, text_size =
size.small, text_halign = text.align_right, text_valign = text.align_center,
text_color = downtextcol, xloc = xloc.bar_time)
topLine = line.new(t[2], (((l2 + h)/2) + l2)/2, time, (((l2 + h)/2) +
l2)/2, color=lineCol, style=lineStyle(linestylem), xloc = xloc.bar_time,
width=wdth)
bottomLine = line.new(t[2], (((l2 + h)/2) + h)/2, time, (((l2 + h)/2) + h)/2,
color=lineCol, style=lineStyle(linestylem), xloc = xloc.bar_time, width=wdth)
middleLine = line.new(t[2], (h+l2)/2, last_bar_time, (h+l2)/2, color=lineCol,
style=lineStyle(linestylem), xloc = xloc.bar_time, width=wdth)
array.push(topLines, topLine)
array.push(middleLines, middleLine)
array.push(bottomLines, bottomLine)
array.push(boxes, imbboxDOWN)

// Looping over the arrays and updating objects


size = array.size(boxes)
if size > 0
for i = 0 to size - 1
j = size - 1 - i
box = array.get(boxes, j)
topLine = array.get(topLines, j)
middleLine = array.get(middleLines, j)
bottomLine = array.get(bottomLines, j)
level = box.get_bottom(box)
level2 = box.get_top(box)
level3 = (level2+level)/2
// Defining fill conditions for zones and lines
var bool filled = na
unifill = (high > level and low < level) or (high > level2 and low <
level2)
if filledtype == 'Touch'
filled := (high > level and low < level) or (high > level2 and low <
level2)
if filledtype == 'Half Fill'
filled := (high > level3 and low < level3)
if filledtype == 'Full Fill'
for imbboxUP in boxes
filled := (high > level2 and low < level2)
for imbboxDOWN in boxes
filled := (high > level and low < level)
if hidefilled and filled
line.delete(topLine)
line.delete(middleLine)
line.delete(bottomLine)
box.delete(box)
array.remove(boxes, j)
array.remove(topLines, j)
array.remove(middleLines, j)
array.remove(bottomLines, j)
continue
if filled and extendtilfilled
array.remove(boxes, j)
array.remove(topLines, j)
array.remove(middleLines, j)
array.remove(bottomLines, j)
continue

box.set_right(box, last_bar_time)
line.set_x2(topLine, last_bar_time)
line.set_x2(middleLine, last_bar_time)
line.set_x2(bottomLine, last_bar_time)

if not filled and not extendtilfilled


array.remove(boxes, j)
array.remove(topLines, j)
array.remove(middleLines, j)
array.remove(bottomLines, j)
continue
box.set_right(box, time+nbars)
line.set_x2(topLine, time+nbars)
line.set_x2(middleLine, time+nbars)
line.set_x2(bottomLine, time+nbars)
continue
box.set_right(box, time)
line.set_x2(topLine, time)
line.set_x2(middleLine, time)
line.set_x2(bottomLine, time)

// Deleting if the array is too big


if array.size(boxes) >= maxBoxes
int i = 0
while array.size(boxes) >= maxBoxes
box = array.get(boxes, i)
topLine = array.get(topLines, i)
middleLine = array.get(middleLines, i)
bottomLine = array.get(bottomLines, i)

line.delete(topLine)
line.delete(middleLine)
line.delete(bottomLine)
box.delete(box)
array.remove(boxes, i)
array.remove(topLines, i)
array.remove(middleLines, i)
array.remove(bottomLines, i)
i += 1

// Session 1 - user inputs


showAsian = input.bool(true, '', inline='Asian', group='Sessions')
stringAsian = input.string('Asian', '', inline='Asian', group='Sessions')
AsianTimeX = input.session(defval="0000-0400", title=' ', inline='Asian2',
group='Sessions', tooltip = 'If you want to change the start/end time of the
session, just make sure they are in UTC. There is no need to change the timezone of
your Tradingview chart or to change the Timezone input below, because the sessions
will be plotted correctly as long as the start/end time is set in UTC.')
AsianCol = input.color(color.rgb(255, 255, 255, 94), '' , inline='Asian',
group='Sessions')
// Session 2 - user inputs
showLondon = input.bool(true, '', inline='London', group='Sessions')
stringLondon = input.string('LO-KZ', '', inline='London', group='Sessions')
LondonTimeX = input.session(defval="0700-1000", title=' ', inline='London2',
group='Sessions', tooltip = 'If you want to change the start/end time of the
session, just make sure they are in UTC. There is no need to change the timezone of
your Tradingview chart or to change the Timezone input below, because the sessions
will be plotted correctly as long as the start/end time is set in UTC.')
LondonCol = input.color(color.rgb(255, 255, 255, 94), '' , inline='London',
group='Sessions')
// Session 3 - user inputs
showNewYork = input.bool(true, title='', inline='New York', group='Sessions')
stringNewYork = input.string('NY-KZ', '', inline='New York', group='Sessions')
NewYorkTimeX = input.session(defval="1230-1530", title=' ', inline='New
York2', group='Sessions', tooltip = 'If you want to change the start/end time of
the session, just make sure they are in UTC. There is no need to change the
timezone of your Tradingview chart or to change the Timezone input below, because
the sessions will be plotted correctly as long as the start/end time is set in
UTC.')
NewYorkCol = input.color(color.rgb(255, 255, 255, 94), '', inline='New York',
group='Sessions')
// Session 4 - user inputs
showSydney = input.bool(false, title='', inline='Sydney', group='Sessions')
stringSydney = input.string('Sydney', '', inline='Sydney', group='Sessions')
SydneyTimeX = input.session(defval="2100-0600", title=' ', inline='Sydney2',
group='Sessions', tooltip = 'If you want to change the start/end time of the
session, just make sure they are in UTC. There is no need to change the timezone of
your Tradingview chart or to change the Timezone input below, because the sessions
will be plotted correctly as long as the start/end time is set in UTC.')
SydneyCol = input.color(color.rgb(255, 255, 255, 94), '', inline='Sydney',
group='Sessions')
// Additional tools and settings - user inputs
pipChange = input.bool(false, 'Change (Pips) ', inline='0', group =
'Additional Tools and Settings')
percentChange = input.bool(false, 'Change (%)', inline='0', group = 'Additional
Tools and Settings')
merge = input.bool(false, 'Merge Overlaps', inline='2', group =
'Additional Tools and Settings')
hideWeekends = input.bool(true, 'Hide Weekends', inline='2', group = 'Additional
Tools and Settings')
sessionOC = input.bool(false, 'Open/Close Line', inline='3', group =
'Additional Tools and Settings')
halfline = input.bool(false, 'Session 0.5 Level', inline='3', group =
'Additional Tools and Settings')
colorcandles = input.bool(false, 'Color Candles ', inline='4', group =
'Additional Tools and Settings')
showScreener = input.bool(false, 'Screener (Soon)', inline='4', group =
'Additional Tools and Settings')
displayType = input.string('Boxes', 'Display Type', options = ['Boxes',
'Zones','Timeline', 'Candles'], group='Additional Tools and Settings',
tooltip='Choose whether the scripts should plot session in the for of boxes or
colored background zones.')
daysBack = input.float(150, 'Lookback (Days)', group='Additional Tools and
Settings', tooltip= 'This inputs defines the lookback period for plotting sessions.
Eg. If it is set to 1, only the sessions of the past day will appear')
changeType = input.string('Session High/Low','Change (%/Pips) Source', options
= ['Session High/Low', 'Session Open/Close'], group='Additional Tools and
Settings', tooltip='Choose whether the Change (%) and Change (Pips) should measure
the distance between Session High and Session Low or the distance between Session
Open and Session Close.')
SessionZone = input.string("UTC", title="Input Timezone", group='Additional
Tools and Settings', tooltip = 'This input is defining the timezone for the session
times selected above. It has nothing to do with the timezone of your chart, because
the sessions will be plotted correctly even if your chart is not set to UTC.')
// Appearance - user inputs
borderWidth = input.int(1, 'Box Border', inline='border', group='Appearance')
borderStyle = input.string('Dotted', '', ['Solid', 'Dashed', 'Dotted'] ,
inline='border', group='Appearance', tooltip='Select the width and style of session
box borders')
levelsStyle = input.string('Dotted', 'Line Style', ['Solid', 'Dashed',
'Dotted'], group='Appearance', tooltip='Select the style of 0.5 and Open/Close
lines.')
labelSize = input.string('Small', 'Label Size', options = ['Auto', 'Tiny',
'Small', 'Normal'], group='Appearance', tooltip='Select the size of text labels.')
showLabels = input.bool(false, 'Session Labels ', inline='00', group =
'Appearance')
colorBoxes = input.bool(true, 'Box Background', inline='00', group =
'Appearance')
// Excluding or Including Weekends
var AsianTime = hideWeekends ? AsianTimeX+":123456" : AsianTimeX+":1234567"
var LondonTime = hideWeekends ? LondonTimeX+":123456" : LondonTimeX+":1234567"
var NewYorkTime = hideWeekends ? NewYorkTimeX+":123456" : NewYorkTimeX+":1234567"
var SydneyTime = hideWeekends ? SydneyTimeX+":123456" : SydneyTimeX+":1234567"

// Defining Line Style and Label Size Variables


//lineStyle(x) =>
// switch x
// 'Solid' => line.style_solid
// 'Dashed' => line.style_dashed
// 'Dotted' => line.style_dotted
labelStyle(x) =>
switch x
'Auto' => size.auto
'Tiny' => size.tiny
'Small' => size.small
'Normal' => size.normal

// Calculating inRange, used for lookback


//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 = daysLeft < daysBack

// Session Time
InAsian(AsianTime, AsianTimeZone=syminfo.timezone) =>
not na(time(timeframe.period, AsianTime, SessionZone))
InLondon(LondonTime, LondonTimeZone=syminfo.timezone) =>
not na(time(timeframe.period, LondonTime, SessionZone))
InNewYork(NewYorkTime, NewYorkTimeZone=syminfo.timezone) =>
not na(time(timeframe.period, NewYorkTime, SessionZone))
InSydney(SydneyTime, SydneyTimeZone=syminfo.timezone) =>
not na(time(timeframe.period, SydneyTime, SessionZone))

// Creating variables Session High, Low, Open and Session Boxes, Lines and Texts
var AsianHighPrice = 0.0, var AsianLowPrice = 0.0, var AsianOpenPrice
= 0.0, var box AsianBox = na, var line AsianLine = na, var label
AsianLabel = na, var line AsianOC = na, var string AsianText =
str.tostring(stringAsian)
var LondonHighPrice = 0.0, var LondonLowPrice = 0.0, var LondonOpenPrice
= 0.0, var box LondonBox = na, var line LondonLine = na, var label
LondonLabel = na, var line LondonOC = na, var string LondonText =
str.tostring(stringLondon)
var NewYorkHighPrice = 0.0, var NewYorkLowPrice = 0.0, var NewYorkOpenPrice
= 0.0, var box NewYorkBox = na, var line NewYorkLine = na, var label
NewYorkLabel = na, var line NewYorkOC = na, var string NewYorkText =
str.tostring(stringNewYork)
var SydneyHighPrice = 0.0, var SydneyLowPrice = 0.0, var SydneyOpenPrice
= 0.0, var box SydneyBox = na, var line SydneyLine = na, var label
SydneyLabel = na, var line SydneyOC = na, var string SydneyText =
str.tostring(stringSydney)

// Checking if session is active/has started


inAsian = InAsian(AsianTime, SessionZone) and timeframe.isintraday
AsianStart = inAsian and not inAsian[1]
inLondon = InLondon(LondonTime, SessionZone) and timeframe.isintraday
LondonStart = inLondon and not inLondon[1]
inNewYork = InNewYork(NewYorkTime, SessionZone) and timeframe.isintraday
NewYorkStart = inNewYork and not inNewYork[1]
inSydney = InSydney(SydneyTime, SessionZone) and timeframe.isintraday
SydneyStart = inSydney and not inSydney[1]

// Settings high, low, open at the beggining of the session


if AsianStart
AsianHighPrice := high
AsianLowPrice := low
AsianOpenPrice := open
if LondonStart
LondonHighPrice := high
LondonLowPrice := low
LondonOpenPrice := open
if NewYorkStart
NewYorkHighPrice := high
NewYorkLowPrice := low
NewYorkOpenPrice := open
if SydneyStart
SydneyHighPrice := high
SydneyLowPrice := low
SydneyOpenPrice := open

// Track session's max high and max low during the session
else if inAsian
AsianHighPrice := math.max(AsianHighPrice, high)
AsianLowPrice := math.min(AsianLowPrice, low)
else if inLondon
LondonHighPrice := math.max(LondonHighPrice, high)
LondonLowPrice := math.min(LondonLowPrice, low)
else if inNewYork
NewYorkHighPrice := math.max(NewYorkHighPrice, high)
NewYorkLowPrice := math.min(NewYorkLowPrice, low)
else if inSydney
SydneyHighPrice := math.max(SydneyHighPrice, high)
SydneyLowPrice := math.min(SydneyLowPrice, low)

// Plotting session boxes at the beginning of each session


if AsianStart and showAsian and inRange
AsianBox := displayType=='Boxes' ? box.new(left=bar_index, top=na,
right=na, bottom=na, border_width=borderWidth, bgcolor = colorBoxes ? AsianCol :
na, border_style = lineStyle(borderStyle), border_color=color.new(AsianCol, 40)) :
na
AsianLine := halfline ? line.new(x1=bar_index, y1=na, x2=na, y2=na,
style=lineStyle(levelsStyle), color = color.new(AsianCol, 40)) : na
AsianLabel := showLabels ? label.new(x=na, y=na, text=AsianText,
textcolor=color.new(AsianCol, 40), color=color.rgb(0,0,0,100),
size=labelStyle(labelSize)) : na
AsianOC := sessionOC ? line.new(x1=bar_index, y1=AsianOpenPrice, x2=na,
y2=na, style=lineStyle(levelsStyle), color = color.new(AsianCol, 40)) : na
if LondonStart and showLondon and inRange
LondonBox := displayType=='Boxes' ? box.new(left=bar_index, top=na,
right=na, bottom=na, border_width=borderWidth, bgcolor = colorBoxes ? LondonCol :
na, border_style = lineStyle(borderStyle), border_color=color.new(LondonCol, 40)) :
na
LondonLine := halfline ? line.new(x1=bar_index, y1=na, x2=na, y2=na,
style=lineStyle(levelsStyle), color = color.new(LondonCol, 40)) : na
LondonLabel := showLabels ? label.new(x=na, y=na, text=LondonText,
textcolor=color.new(LondonCol, 40), color=color.rgb(0,0,0,100),
size=labelStyle(labelSize)) : na
LondonOC := sessionOC ? line.new(x1=bar_index, y1=LondonOpenPrice, x2=na,
y2=na, style=lineStyle(levelsStyle), color = color.new(LondonCol, 40)) : na
if NewYorkStart and showNewYork and inRange
NewYorkBox := displayType=='Boxes' ? box.new(left=bar_index, top=na,
right=na, bottom=na, border_width=borderWidth, bgcolor = colorBoxes ? NewYorkCol :
na, border_style = lineStyle(borderStyle), border_color=color.new(NewYorkCol,
40)) : na
NewYorkLine := halfline ? line.new(x1=bar_index, y1=na, x2=na, y2=na,
style=lineStyle(levelsStyle), color = color.new(NewYorkCol, 40)) : na
NewYorkLabel := showLabels ? label.new(x=na, y=na, text=NewYorkText,
textcolor=color.new(NewYorkCol, 40), color=color.rgb(0,0,0,100),
size=labelStyle(labelSize)) : na
NewYorkOC := sessionOC ? line.new(x1=bar_index, y1=NewYorkOpenPrice, x2=na,
y2=na, style=lineStyle(levelsStyle), color = color.new(NewYorkCol, 40)) : na
if SydneyStart and showSydney and inRange
SydneyBox := displayType=='Boxes' ? box.new(left=bar_index, top=na,
right=na, bottom=na, border_width=borderWidth, bgcolor = colorBoxes ? SydneyCol :
na, border_style = lineStyle(borderStyle), border_color=color.new(SydneyCol, 40)) :
na
SydneyLine := halfline ? line.new(x1=bar_index, y1=na, x2=na, y2=na,
style=lineStyle(levelsStyle), color = color.new(SydneyCol, 40)) : na
SydneyLabel := showLabels ? label.new(x=na, y=na, text=SydneyText,
textcolor=color.new(SydneyCol, 40), color=color.rgb(0,0,0,100),
size=labelStyle(labelSize)) : na
SydneyOC := sessionOC ? line.new(x1=bar_index, y1=SydneyOpenPrice, x2=na,
y2=na, style=lineStyle(levelsStyle), color = color.new(SydneyCol, 40)) : na

// Creating variables for alternative Sessions Box top and bottom (used for merging
sessions)
var float AsianHighM = 0, var float AsianLowM = 0, var float LondonHighM = 0,
var float LondonLowM = 0, var float NewYorkHighM = 0, var float NewYorkLowM = 0,
var float SydneyHighM = 0, var float SydneyLowM = 0

// Updating session boxes during sessions


if inAsian and inRange
AsianHighPrice := math.max(AsianHighPrice, high)
AsianLowPrice := math.min(AsianLowPrice, low)
box.set_top(AsianBox, AsianHighPrice)
box.set_bottom(AsianBox, AsianLowPrice)
box.set_right(AsianBox, bar_index + 1)
label.set_x(AsianLabel, (box.get_left(AsianBox)+box.get_right(AsianBox))/2)
label.set_y(AsianLabel, AsianHighPrice)
if sessionOC
line.set_x2(AsianOC, bar_index)
line.set_y2(AsianOC, close)
if halfline
line.set_y1(AsianLine, (AsianHighPrice+AsianLowPrice)/2)
line.set_y2(AsianLine, (AsianHighPrice+AsianLowPrice)/2)
line.set_x2(AsianLine, bar_index+1)
if merge and not inLondon and showLondon
AsianHighM := AsianHighPrice
AsianLowM := AsianLowPrice
if merge and inLondon and showLondon
box.set_top(AsianBox, AsianHighM)
box.set_bottom(AsianBox, AsianLowM)
label.set_y(AsianLabel, AsianHighM)
box.set_right(AsianBox, (box.get_left(LondonBox)))
line.set_x2(AsianLine, (box.get_left(LondonBox)))
label.set_x(AsianLabel, (box.get_left(AsianBox)+box.get_right(AsianBox))/2)
line.set_x2(AsianOC, (box.get_left(LondonBox)))
line.set_y2(AsianOC, LondonOpenPrice)
line.set_y1(AsianLine, (AsianHighM+AsianLowM)/2)
line.set_y2(AsianLine, (AsianHighM+AsianLowM)/2)
var float pips = 0
var float chg = 0
pips := changeType=='Session High/Low' ? ((AsianHighPrice - AsianLowPrice) /
syminfo.mintick / 10) : ((close - AsianOpenPrice) / syminfo.mintick / 10)
chg := changeType=='Session Open/Close' ? (100 * (close - AsianOpenPrice) /
AsianOpenPrice) : ((AsianHighPrice - AsianLowPrice) / AsianLowPrice * 100)
if percentChange and not pipChange
label.set_text(AsianLabel, str.tostring(AsianText) + ' (' +
str.tostring(chg, format.percent) + ')')
if pipChange and not percentChange
label.set_text(AsianLabel, str.tostring(AsianText) + ' (' +
str.tostring(pips) + ')')
if percentChange and pipChange
label.set_text(AsianLabel, str.tostring(AsianText) + ' ('+
str.tostring(chg, format.percent)+ ' • ' + str.tostring(pips) + ')')
if inLondon and inRange
LondonHighPrice := math.max(LondonHighPrice, high)
LondonLowPrice := math.min(LondonLowPrice, low)
box.set_top(LondonBox, LondonHighPrice)
box.set_bottom(LondonBox, LondonLowPrice)
box.set_right(LondonBox, bar_index+1)
label.set_x(LondonLabel, (box.get_left(LondonBox)+box.get_right(LondonBox))/2)
label.set_y(LondonLabel, LondonHighPrice)
if sessionOC
line.set_x2(LondonOC, bar_index)
line.set_y2(LondonOC, close)
if halfline
line.set_y1(LondonLine, (LondonHighPrice+LondonLowPrice)/2)
line.set_y2(LondonLine, (LondonHighPrice+LondonLowPrice)/2)
line.set_x2(LondonLine, bar_index+1)
if merge and not inNewYork and showNewYork
LondonHighM := LondonHighPrice
LondonLowM := LondonLowPrice
if merge and inNewYork and showNewYork
box.set_top(LondonBox, LondonHighM)
box.set_bottom(LondonBox, LondonLowM)
label.set_y(LondonLabel, LondonHighM)
box.set_right(LondonBox, (box.get_left(NewYorkBox)))
line.set_x2(LondonLine, (box.get_left(NewYorkBox)))
label.set_x(LondonLabel, (box.get_left(LondonBox)
+box.get_right(LondonBox))/2)
line.set_x2(LondonOC, (box.get_left(NewYorkBox)))
line.set_y2(LondonOC, NewYorkOpenPrice)
line.set_y1(LondonLine, (LondonHighM+LondonLowM)/2)
line.set_y2(LondonLine, (LondonHighM+LondonLowM)/2)
var float pips = 0
var float chg = 0
pips := changeType=='Session High/Low' ? ((LondonHighPrice - LondonLowPrice) /
syminfo.mintick / 10) : ((close - LondonOpenPrice) / syminfo.mintick / 10)
chg := changeType=='Session Open/Close' ? (100 * (close - LondonOpenPrice) /
LondonOpenPrice) : ((LondonHighPrice - LondonLowPrice) / LondonLowPrice * 100)
if percentChange and not pipChange
label.set_text(LondonLabel, str.tostring(LondonText) + ' (' +
str.tostring(chg, format.percent) + ')')
if pipChange and not percentChange
label.set_text(LondonLabel, str.tostring(LondonText) + ' (' +
str.tostring(pips) + ')')
if percentChange and pipChange
label.set_text(LondonLabel, str.tostring(LondonText) + ' ('+
str.tostring(chg, format.percent)+ ' • ' + str.tostring(pips) + ')')
if inNewYork and inRange
NewYorkHighPrice := math.max(NewYorkHighPrice, high)
NewYorkLowPrice := math.min(NewYorkLowPrice, low)
box.set_top(NewYorkBox, NewYorkHighPrice)
box.set_bottom(NewYorkBox, NewYorkLowPrice)
box.set_right(NewYorkBox, bar_index + 1)
label.set_x(NewYorkLabel, (box.get_left(NewYorkBox)
+box.get_right(NewYorkBox))/2)
label.set_y(NewYorkLabel, NewYorkHighPrice)
if sessionOC
line.set_x2(NewYorkOC, bar_index)
line.set_y2(NewYorkOC, close)
if halfline
line.set_y1(NewYorkLine, (NewYorkHighPrice+NewYorkLowPrice)/2)
line.set_y2(NewYorkLine, (NewYorkHighPrice+NewYorkLowPrice)/2)
line.set_x2(NewYorkLine, bar_index+1)
if merge and not inSydney and showSydney
NewYorkHighM := NewYorkHighPrice
NewYorkLowM := NewYorkLowPrice
if merge and inSydney and showSydney
box.set_top(NewYorkBox, NewYorkHighM)
box.set_bottom(NewYorkBox, NewYorkLowM)
label.set_y(NewYorkLabel, NewYorkHighM)
box.set_right(NewYorkBox, (box.get_left(SydneyBox)))
line.set_x2(NewYorkLine, (box.get_left(SydneyBox)))
label.set_x(NewYorkLabel, (box.get_left(NewYorkBox)
+box.get_right(NewYorkBox))/2)
line.set_x2(NewYorkOC, (box.get_left(SydneyBox)))
line.set_y2(NewYorkOC, SydneyOpenPrice)
line.set_y1(NewYorkLine, (NewYorkHighM+NewYorkLowM)/2)
line.set_y2(NewYorkLine, (NewYorkHighM+NewYorkLowM)/2)
var float pips = 0
var float chg = 0
pips := changeType=='Session High/Low' ? ((NewYorkHighPrice -
NewYorkLowPrice) / syminfo.mintick / 10) : ((close - NewYorkOpenPrice) /
syminfo.mintick / 10)
chg := changeType=='Session Open/Close' ? (100 * (close - NewYorkOpenPrice) /
NewYorkOpenPrice) : ((NewYorkHighPrice - NewYorkLowPrice) / NewYorkLowPrice * 100)
if percentChange and not pipChange
label.set_text(NewYorkLabel, str.tostring(NewYorkText) + ' (' +
str.tostring(chg, format.percent) + ')')
if pipChange and not percentChange
label.set_text(NewYorkLabel, str.tostring(NewYorkText) + ' (' +
str.tostring(pips) + ')')
if percentChange and pipChange
label.set_text(NewYorkLabel, str.tostring(NewYorkText) + ' ('+
str.tostring(chg, format.percent)+ ' • ' + str.tostring(pips) + ')')
if inSydney and inRange
SydneyHighPrice := math.max(SydneyHighPrice, high)
SydneyLowPrice := math.min(SydneyLowPrice, low)
box.set_top(SydneyBox, SydneyHighPrice)
box.set_bottom(SydneyBox, SydneyLowPrice)
box.set_right(SydneyBox, bar_index + 1)
label.set_x(SydneyLabel, (box.get_left(SydneyBox)+box.get_right(SydneyBox))/2)
label.set_y(SydneyLabel, SydneyHighPrice)
if sessionOC
line.set_x2(SydneyOC, bar_index)
line.set_y2(SydneyOC, close)
if halfline
line.set_y1(SydneyLine, (SydneyHighPrice+SydneyLowPrice)/2)
line.set_y2(SydneyLine, (SydneyHighPrice+SydneyLowPrice)/2)
line.set_x2(SydneyLine, bar_index+1)
if merge and not inAsian and showAsian
SydneyHighM := SydneyHighPrice
SydneyLowM := SydneyLowPrice
if merge and inAsian and showAsian
box.set_top(SydneyBox, SydneyHighM)
box.set_bottom(SydneyBox, SydneyLowM)
label.set_y(SydneyLabel, SydneyHighM)
box.set_right(SydneyBox, (box.get_left(AsianBox)))
line.set_x2(SydneyLine, (box.get_left(AsianBox)))
label.set_x(SydneyLabel, (box.get_left(SydneyBox)
+box.get_right(SydneyBox))/2)
line.set_x2(SydneyOC, (box.get_left(AsianBox)))
line.set_y2(SydneyOC, AsianOpenPrice)
line.set_y1(SydneyLine, (SydneyHighM+SydneyLowM)/2)
line.set_y2(SydneyLine, (SydneyHighM+SydneyLowM)/2)
var float pips = 0
var float chg = 0
pips := changeType=='Session High/Low' ? ((SydneyHighPrice - SydneyLowPrice) /
syminfo.mintick / 10) : ((close - SydneyOpenPrice) / syminfo.mintick / 10)
chg := changeType=='Session Open/Close' ? (100 * (close - SydneyOpenPrice) /
SydneyOpenPrice) : ((SydneyHighPrice - SydneyLowPrice) / SydneyLowPrice * 100)
if percentChange and not pipChange
label.set_text(SydneyLabel, str.tostring(SydneyText) + ' (' +
str.tostring(chg, format.percent) + ')')
if pipChange and not percentChange
label.set_text(SydneyLabel, str.tostring(SydneyText) + ' (' +
str.tostring(pips) + ')')
if percentChange and pipChange
label.set_text(SydneyLabel, str.tostring(SydneyText) + ' ('+
str.tostring(chg, format.percent)+ ' • ' + str.tostring(pips) + ')')

// Coloring candles
TKLO = showLondon ? (not inLondon) : true
LONY = showNewYork ? (not inNewYork) : true
NYSY = showSydney ? (not inSydney) : true
SYTK = showAsian ? (not inAsian) : true
barcolor((colorcandles or displayType=='Candles') and not merge and showAsian
and inAsian and inRange ? color.new(AsianCol, 40) : na, editable =
false)
barcolor((colorcandles or displayType=='Candles') and not merge and showLondon
and inLondon and inRange ? color.new(LondonCol, 40) : na, editable =
false)
barcolor((colorcandles or displayType=='Candles') and not merge and showNewYork
and inNewYork and inRange ? color.new(NewYorkCol, 40) : na, editable =
false)
barcolor((colorcandles or displayType=='Candles') and not merge and showSydney
and inNewYork and inRange ? color.new(SydneyCol, 40) : na, editable =
false)
barcolor((colorcandles or displayType=='Candles') and merge and showAsian
and inAsian and TKLO and inRange ? color.new(AsianCol, 40) : na, editable =
false)
barcolor((colorcandles or displayType=='Candles') and merge and showLondon
and inLondon and LONY and inRange ? color.new(LondonCol, 40) : na, editable =
false)
barcolor((colorcandles or displayType=='Candles') and merge and showNewYork
and inNewYork and NYSY and inRange ? color.new(NewYorkCol, 40) : na, editable =
false)
barcolor((colorcandles or displayType=='Candles') and merge and showSydney
and inSydney and SYTK and inRange ? color.new(SydneyCol, 40) : na, editable =
false)

// Coloring background if displayType=='Zones'


AsianT = time(timeframe.period, AsianTime)
LondonT = time(timeframe.period, LondonTime)
NewYorkT = time(timeframe.period, NewYorkTime)
SydneyT = time(timeframe.period, SydneyTime)
bgcolor(displayType == 'Zones' and not merge and showAsian and inRange and time
== AsianT ? AsianCol : na, editable = false)
bgcolor(displayType == 'Zones' and not merge and showLondon and inRange and time
== LondonT ? LondonCol : na, editable = false)
bgcolor(displayType == 'Zones' and not merge and showNewYork and inRange and time
== NewYorkT ? NewYorkCol : na, editable = false)
bgcolor(displayType == 'Zones' and not merge and showSydney and inRange and time
== SydneyT ? SydneyCol : na, editable = false)
bgcolor(displayType == 'Zones' and merge and not inLondon and showAsian and
inRange and time == AsianT ? AsianCol : na, editable = false)
bgcolor(displayType == 'Zones' and merge and not inNewYork and showLondon and
inRange and time == LondonT ? LondonCol : na, editable = false)
bgcolor(displayType == 'Zones' and merge and not inSydney and showNewYork and
inRange and time == NewYorkT ? NewYorkCol : na, editable = false)
bgcolor(displayType == 'Zones' and merge and not inAsian and showSydney and
inRange and time == SydneyT ? SydneyCol : na, editable = false)

// Plotting sessions in Timeline form


plotshape(displayType=='Timeline' and (merge and showLondon ? (showAsian and
inAsian and not inLondon) : showAsian and inAsian), style=shape.square,
color=AsianCol, location = location.bottom, size=size.auto)
plotshape(displayType=='Timeline' and (merge and showNewYork ? (showLondon and
inLondon and not inNewYork) : showLondon and inLondon), style=shape.square,
color=LondonCol, location = location.bottom, size=size.auto)
plotshape(displayType=='Timeline' and (merge and showSydney ? (showNewYork and
inNewYork and not inSydney) : showNewYork and inNewYork), style=shape.square,
color=NewYorkCol, location = location.bottom, size=size.auto)
plotshape(displayType=='Timeline' and (merge and showAsian ? (showSydney and
inSydney and not inAsian) : showSydney and inSydney), style=shape.square,
color=SydneyCol, location = location.bottom, size=size.auto)

// Creating alerts
//alertcondition(inAsian and not inAsian[1], 'Asian Open', 'The Asian Session has
started')
//alertcondition(inLondon and not inLondon[1], 'London Open', 'The London Session
has started')
//alertcondition(inNewYork and not inNewYork[1], 'New York Open', 'The New York
Session has started')
//alertcondition(inSydney and not inSydney[1], 'Sydney Open', 'The Sydney Session
has started')
//alertcondition(high > AsianHighPrice[0] and inAsian, 'Asian Session - New
High', 'New High in Asian Session')
//alertcondition(high > LondonHighPrice[0] and inLondon, 'London Session - New
High', 'New High in London Session')
//alertcondition(high > NewYorkHighPrice[0] and inNewYork, 'New York Session - New
High', 'New High in New York Session')
//alertcondition(high > SydneyHighPrice[0] and inSydney, 'Sydney Session - New
High', 'New High in Sydney Session')
//alertcondition(low > AsianLowPrice[0] and inAsian, 'Asian Session - New
Low', 'New Low in Asian Session')
//alertcondition(low > LondonLowPrice[0] and inLondon, 'London Session - New
Low', 'New Low in London Session')
//alertcondition(low > NewYorkLowPrice[0] and inNewYork, 'New York Session - New
Low', 'New Low In New York Session')
//alertcondition(low > SydneyLowPrice[0] and inSydney, 'Sydney Session - New
Low', 'New Low In Sydney Session')

// © TrunkXiao

//@version=5
//indicator("Market Structure Break & Order Block", "MSB-OB", overlay=true,
max_lines_count=500, max_bars_back=4900, max_boxes_count=500)

zigzag_len = input.int(10, "ZigZag Length", group= "MSB-OB Settings")


msb_zigzag = input.bool(false, "Show Zigzag", group= "MSB-OB Settings")
fib_factor = input.float(0.33, "Fib Factor for breakout confirmation", 0, 1, 0.01,
group= "MSB-OB Settings")

msbtext_size = input.string(size.tiny, "Text Size", [size.tiny, size.small,


size.normal, size.large, size.huge], group= "MSB-OB Settings")

delete_boxes = input.bool(true, "Delete Old/Broken Boxes", group= "MSB-OB


Settings")

bu_ob_color = input.color(color.new(#00bcd4, 90), "Color", group= "Bu-OB Display


Settings", inline= "Bu-OB Colors")
bu_ob_border_color = input.color(color.new(#00bcd4, 70), "Border Color", group=
"Bu-OB Display Settings", inline= "Bu-OB Colors")
bu_ob_text_color = input.color(color.new(#00bcd4, 0), "Text Color", group= "Bu-OB
Display Settings", inline= "Bu-OB Colors")

be_ob_color = input.color(color.new(#e91e63, 90), "Color", group= "Be-OB Display


Settings", inline= "Be-OB Colors")
be_ob_border_color = input.color(color.new(#e91e63, 70), "Border Color", group=
"Be-OB Display Settings", inline= "Be-OB Colors")
be_ob_text_color = input.color(color.new(#e91e63, 0), "Text Color", group= "Be-OB
Display Settings", inline= "Be-OB Colors")

bu_bb_color = input.color(color.new(#00bcd4, 90), "Color", group= "Bu-BB & Bu-MB


Display Settings", inline= "Bu-BB Colors")
bu_bb_border_color = input.color(color.new(#00bcd4, 70), "Border Color", group=
"Bu-BB & Bu-MB Display Settings", inline= "Bu-BB Colors")
bu_bb_text_color = input.color(color.new(#00bcd4, 0), "Text Color", group= "Bu-BB &
Bu-MB Display Settings", inline= "Bu-BB Colors")

be_bb_color = input.color(color.new(#e91e63, 90), "Color", group= "Be-BB & Be-MB


Display Settings", inline= "Be-BB Colors")
be_bb_border_color = input.color(color.new(#e91e63, 70), "Border Color", group=
"Be-BB & Be-MB Display Settings", inline= "Be-BB Colors")
be_bb_text_color = input.color(color.new(#e91e63, 0), "Text Color", group= "Be-BB &
Be-MB Display Settings", inline= "Be-BB Colors")

var float[] high_points_arr = array.new_float(5)


var int[] high_index_arr = array.new_int(5)
var float[] low_points_arr = array.new_float(5)
var int[] low_index_arr = array.new_int(5)

var box[] bu_ob_boxes = array.new_box(5)


var box[] be_ob_boxes = array.new_box(5)
var box[] bu_bb_boxes = array.new_box(5)
var box[] be_bb_boxes = array.new_box(5)

to_up = high >= ta.highest(zigzag_len)


to_down = low <= ta.lowest(zigzag_len)

bktrend = 1
bktrend := nz(bktrend[1], 1)
bktrend := bktrend == 1 and to_down ? -1 : bktrend == -1 and to_up ? 1 : bktrend

last_trend_up_since = ta.barssince(to_up[1])
low_val = ta.lowest(nz(last_trend_up_since > 0 ? last_trend_up_since : 1, 1))
low_index = bar_index - ta.barssince(low_val == low)

last_trend_down_since = ta.barssince(to_down[1])
high_val = ta.highest(nz(last_trend_down_since > 0 ? last_trend_down_since : 1, 1))
high_index = bar_index - ta.barssince(high_val == high)

if ta.change(bktrend) != 0
if bktrend == 1
array.push(low_points_arr, low_val)
array.push(low_index_arr, low_index)
if bktrend == -1
array.push(high_points_arr, high_val)
array.push(high_index_arr, high_index)

f_get_high(ind) =>
[array.get(high_points_arr, array.size(high_points_arr) - 1 - ind),
array.get(high_index_arr, array.size(high_index_arr) - 1 - ind)]

f_get_low(ind) =>
[array.get(low_points_arr, array.size(low_points_arr) - 1 - ind),
array.get(low_index_arr, array.size(low_index_arr) - 1 - ind)]

f_delete_box(box_arr) =>
if delete_boxes
box.delete(array.shift(box_arr))
else
array.shift(box_arr)
0

[bkh0, bkh0i] = f_get_high(0)


[bkh1, bkh1i] = f_get_high(1)
[bkl0, bkl0i] = f_get_low(0)
[bkl1, bkl1i] = f_get_low(1)

if ta.change(bktrend) != 0 and msb_zigzag and switch_breaker


if bktrend == 1
line.new(bkh0i, bkh0, bkl0i, bkl0)
if bktrend == -1
line.new(bkl0i, bkl0, bkh0i, bkh0)

market = 1
market := nz(market[1], 1)
// market := market == 1 and close < bkl0 and low < bkl0 - math.abs(bkh0 - bkl0) *
fib_factor ? -1 : market == -1 and close > bkh0 and high > bkh0 + math.abs(bkh0 -
bkl0) * fib_factor ? 1 : market
last_bkl0 = ta.valuewhen(ta.change(market) != 0, bkl0, 0)
last_bkh0 = ta.valuewhen(ta.change(market) != 0, bkh0, 0)
market := last_bkl0 == bkl0 or last_bkh0 == bkh0 ? market : market == 1 and bkl0 <
bkl1 and bkl0 < bkl1 - math.abs(bkh0 - bkl1) * fib_factor ? -1 : market == -1 and
bkh0 > bkh1 and bkh0 > bkh1 + math.abs(bkh1 - bkl0) * fib_factor ? 1 : market

bu_ob_index = bar_index
bu_ob_index := nz(bu_ob_index[1], bar_index)
for i=bkh1i to bkl0i[zigzag_len]
index = bar_index - i
if open[index] > close[index]
bu_ob_index := bar_index[index]

bu_ob_since = bar_index - bu_ob_index

be_ob_index = bar_index
be_ob_index := nz(be_ob_index[1], bar_index)
for i=bkl1i to bkh0i[zigzag_len]
index = bar_index - i
if open[index] < close[index]
be_ob_index := bar_index[index]

be_ob_since = bar_index - be_ob_index

be_bb_index = bar_index
be_bb_index := nz(be_bb_index[1], bar_index)
for i=bkh1i - zigzag_len to bkl1i
index = bar_index - i
if open[index] > close[index]
be_bb_index := bar_index[index]

be_bb_since = bar_index - be_bb_index

bu_bb_index = bar_index
bu_bb_index := nz(bu_bb_index[1], bar_index)
for i=bkl1i - zigzag_len to bkh1i
index = bar_index - i
if open[index] < close[index]
bu_bb_index := bar_index[index]

bu_bb_since = bar_index - bu_bb_index

if ta.change(market) != 0 and switch_breaker


if market == 1
//line.new(bkh1i, bkh1, bkh0i, bkh1, color=color.new(#00e676,0),
width=1,style = line.style_dashed)
//label.new(int(math.avg(bkh1i, bkl0i)), bkh1, "MSB",
color=color.new(color.black, 100), style=label.style_label_down,
textcolor=color.new(#00e676,0), size=size.small)
bu_ob = box.new(bu_ob_index, high[bu_ob_since], bar_index + 10,
low[bu_ob_since], bgcolor=bu_ob_color, border_color=bu_ob_border_color, text="Bu-
OB", text_color=bu_ob_text_color, text_halign=text.align_right,
text_size=msbtext_size)
bu_bb = box.new(bu_bb_index, high[bu_bb_since], bar_index + 10,
low[bu_bb_since], bgcolor=bu_bb_color, border_color=bu_bb_border_color, text=bkl0 <
bkl1 ? "Bu-BB" : "Bu-MB", text_color=bu_bb_text_color,
text_halign=text.align_right, text_size=msbtext_size)
array.push(bu_ob_boxes, bu_ob)
array.push(bu_bb_boxes, bu_bb)
if market == -1
//line.new(bkl1i, bkl1, bkl0i, bkl1, color=color.new(#e91e63,0),
width=1,style = line.style_dashed)
//label.new(int(math.avg(bkl1i, bkh0i)), bkl1, "MSB",
color=color.new(color.black, 100), style=label.style_label_up,
textcolor=color.new(#e91e63,0), size=size.small)
be_ob = box.new(be_ob_index, high[be_ob_since], bar_index + 10,
low[be_ob_since], bgcolor=be_ob_color, border_color=be_ob_border_color, text="Be-
OB", text_color=be_ob_text_color, text_halign=text.align_right,
text_size=msbtext_size)
be_bb = box.new(be_bb_index, high[be_bb_since], bar_index + 10,
low[be_bb_since], bgcolor=be_bb_color, border_color=be_bb_border_color, text=bkh0 >
bkh1 ? "Be-BB" : "Be-MB", text_color=be_bb_text_color,
text_halign=text.align_right, text_size=msbtext_size)
array.push(be_ob_boxes, be_ob)
array.push(be_bb_boxes, be_bb)

for bull_ob in bu_ob_boxes


bottom = box.get_bottom(bull_ob)
top = box.get_top(bull_ob)
if close < bottom
f_delete_box(bu_ob_boxes)
else if close < top
alert("Price in the BU-OB zone")
else
box.set_right(bull_ob, bar_index + 10)

for bear_ob in be_ob_boxes


top = box.get_top(bear_ob)
bottom = box.get_bottom((bear_ob))
if close > top
f_delete_box(be_ob_boxes)
if close > bottom
alert("Price in the BE-OB zone")
else
box.set_right(bear_ob, bar_index + 10)

for bear_bb in be_bb_boxes


top = box.get_top(bear_bb)
bottom = box.get_bottom(bear_bb)
if close > top
f_delete_box(be_bb_boxes)
else if close > bottom
alert("Price in the BE-BB zone")
else
box.set_right(bear_bb, bar_index + 10)

for bull_bb in bu_bb_boxes


bottom = box.get_bottom(bull_bb)
top = box.get_top(bull_bb)
if close < bottom
f_delete_box(bu_bb_boxes)
else if close < top
alert("Price in the BU-BB zone")
else
box.set_right(bull_bb, bar_index + 10)

alertcondition(ta.change(market) != 0, "MSB", "MSB")

//------------------------------------------------------------------------------
//Liquidity Zones
//-----------------------------------------------------------------------------{
liqGrp = 'Liquidity Detection'
liqLen = input.int (7, title = 'Detection Length', minval = 3, maxval = 13,
inline = 'LIQ', group = liqGrp)
liqMar = 10 / input.float (6.9, 'Margin', minval = 4, maxval = 9, step = 0.1,
inline = 'LIQ', group = liqGrp)

liqBuy = input.bool (true, 'Buyside Liquidity Zones, Margin', inline = 'Buyside',


group = liqGrp)
marBuy = input.float(2, '', minval = 1.5, maxval = 10, step = .1, inline =
'Buyside', group = liqGrp)
cLIQ_B = input.color (color.new(#9598a1, 93), '', inline = 'Buyside', group =
liqGrp)

liqSel = input.bool (true, 'Sellside Liquidity Zones, Margin', inline = 'Sellside',


group = liqGrp)
marSel = input.float(2, '', minval = 1.5, maxval = 10, step = .1, inline =
'Sellside', group = liqGrp)
cLIQ_S = input.color (color.new(#9598a1, 93), '', inline = 'Sellside', group =
liqGrp)

lqVoid = input.bool (false, 'Liquidity Voids, Bullish', inline = 'void', group =


liqGrp)
cLQV_B = input.color (color.new(#4caf50, 0), '', inline = 'void', group = liqGrp)
cLQV_S = input.color (color.new(#f23645, 0), 'Bearish', inline = 'void', group =
liqGrp)
lqText = input.bool (false, 'Label', inline = 'void', group = liqGrp)

liqmode = input.string('Present', title = 'liqmode', options =['Present',


'Historical'], inline = 'MOD', group = liqGrp)
visLiq = input.int (3, ' # Visible Levels', minval = 1, maxval = 50, inline =
'MOD', group = liqGrp)

//-----------------------------------------------------------------------------}
//General Calculations
//-----------------------------------------------------------------------------{
maxSize = 50
atr10 = ta.atr(10)
//atr200 = ta.atr(200)
per = liqmode == '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 = ZZ.new(
array.new <int> (maxSize, 0),
array.new <int> (maxSize, 0),
array.new <float>(maxSize, na)
)
bar b = bar.new()

var liq[] b_liq_B = array.new<liq> (1, liq.new(box(na), box(na), box(na), false,


false, line(na), line(na)))
var liq[] b_liq_S = array.new<liq> (1, liq.new(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) =>
aZZ.d.unshift(_d), aZZ.x.unshift(_x), aZZ.y.unshift(_y), aZZ.d.pop(),
aZZ.x.pop(), aZZ.y.pop()

// @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 = ta.pivothigh(liqLen, 1)
pl = ta.pivotlow (liqLen, 1)

if ph and switch_bsl
dir := aZZ.d.get(0)
x1 := aZZ.x.get(0)
y1 := aZZ.y.get(0)
y2 := nz(b.h[1])

if dir < 1
aZZ.in_out(1, x2, y2)
else
if dir == 1 and ph > y1
aZZ.x.set(0, x2), aZZ.y.set(0, y2)

if per
count = 0
st_P = 0.
st_B = 0
minP = 0.
maxP = 10e6

for i = 0 to maxSize - 1
if aZZ.d.get(i) == 1
if aZZ.y.get(i) > ph + (atr10 / liqMar)
break
else
if aZZ.y.get(i) > ph - (atr10 / liqMar) and aZZ.y.get(i) < ph +
(atr10 / liqMar)
count += 1
st_B := aZZ.x.get(i)
st_P := aZZ.y.get(i)
if aZZ.y.get(i) > minP
minP := aZZ.y.get(i)
if aZZ.y.get(i) < maxP
maxP := aZZ.y.get(i)

if count > 2
getB = b_liq_B.get(0)

if st_B == getB.bx.get_left()
getB.bx.set_top(math.avg(minP, maxP) + (atr10 / liqMar))
getB.bx.set_rightbottom(b.i + 10, math.avg(minP, maxP) - (atr10 /
liqMar))
else
b_liq_B.unshift(
liq.new(
box.new(st_B, math.avg(minP, maxP) + (atr10 / liqMar), b.i + 10,
math.avg(minP, maxP) - (atr10 / liqMar), bgcolor=color(na),
border_color=color(na)),
box.new(na, na, na, na, bgcolor = color(na), border_color =
color(na)),
box.new(st_B, st_P, b.i + 10, st_P, text = 'Buyside liquidity',
text_size = size.small, text_halign = text.align_left, text_valign =
text.align_bottom, text_color = color.new(cLIQ_B, 25), bgcolor = color(na),
border_color = color(na)),
false,
false,
line.new(st_B , st_P, b.i - 1, st_P, color = color.new(cLIQ_B,
60)),
line.new(b.i - 1, st_P, na , st_P, color = color.new(cLIQ_B,
60), style = line.style_dotted))
)

alert('buyside liquidity level detected/updated for ' +


syminfo.ticker)

if b_liq_B.size() > visLiq


getLast = b_liq_B.pop()
getLast.bx.delete()
getLast.bxz.delete()
getLast.bxt.delete()
getLast.ln.delete()
getLast.lne.delete()
if pl and switch_bsl
dir := aZZ.d.get (0)
x1 := aZZ.x.get (0)
y1 := aZZ.y.get (0)
y2 := nz(b.l[1])

if dir > -1
aZZ.in_out(-1, x2, y2)
else
if dir == -1 and pl < y1
aZZ.x.set(0, x2), aZZ.y.set(0, y2)

if per
count = 0
st_P = 0.
st_B = 0
minP = 0.
maxP = 10e6

for i = 0 to maxSize - 1
if aZZ.d.get(i) == -1
if aZZ.y.get(i) < pl - (atr10 / liqMar)
break
else
if aZZ.y.get(i) > pl - (atr10 / liqMar) and aZZ.y.get(i) < pl +
(atr10 / liqMar)
count += 1
st_B := aZZ.x.get(i)
st_P := aZZ.y.get(i)
if aZZ.y.get(i) > minP
minP := aZZ.y.get(i)
if aZZ.y.get(i) < maxP
maxP := aZZ.y.get(i)

if count > 2
getB = b_liq_S.get(0)

if st_B == getB.bx.get_left()
getB.bx.set_top(math.avg(minP, maxP) + (atr10 / liqMar))
getB.bx.set_rightbottom(b.i + 10, math.avg(minP, maxP) - (atr10 /
liqMar))
else
b_liq_S.unshift(
liq.new(
box.new(st_B, math.avg(minP, maxP) + (atr10 / liqMar), b.i + 10,
math.avg(minP, maxP) - (atr10 / liqMar), bgcolor=color(na),
border_color=color(na)),
box.new(na, na, na, na, bgcolor=color(na),
border_color=color(na)),
box.new(st_B, st_P, b.i + 10, st_P, text = 'Sellside liquidity',
text_size = size.small, text_halign = text.align_left, text_valign =
text.align_top, text_color = color.new(cLIQ_S, 25), bgcolor=color(na),
border_color=color(na)),
false,
false,
line.new(st_B , st_P, b.i - 1, st_P, color = color.new(cLIQ_S,
60)),
line.new(b.i - 1, st_P, na , st_P, color = color.new(cLIQ_S,
60), style = line.style_dotted))
)

alert('sellside liquidity level detected/updated for ' +


syminfo.ticker)

if b_liq_S.size() > visLiq


getLast = b_liq_S.pop()
getLast.bx.delete()
getLast.bxz.delete()
getLast.bxt.delete()
getLast.ln.delete()
getLast.lne.delete()

for i = 0 to b_liq_B.size() - 1
x = b_liq_B.get(i)

if not x.brL
x.lne.set_x2(b.i)

if b.h > x.bx.get_top()


x.brL := true
x.brZ := true
alert('buyside liquidity level breached for ' + syminfo.ticker)

x.bxz.set_lefttop(b.i - 1, math.min(x.ln.get_y1() + marBuy * (atr10),


b.h))
x.bxz.set_rightbottom(b.i + 1, x.ln.get_y1())
x.bxz.set_bgcolor(color.new(cLIQ_B, liqBuy ? 73 : 100))

else if x.brZ
if b.l > x.ln.get_y1() - marBuy * (atr10) and b.h < x.ln.get_y1() + marBuy
* (atr10)
x.bxz.set_right(b.i + 1)
x.bxz.set_top(math.max(b.h, x.bxz.get_top()))
if liqBuy
x.lne.set_x2(b.i + 1)
else
x.brZ := false

for i = 0 to b_liq_S.size() - 1
x = b_liq_S.get(i)

if not x.brL
x.lne.set_x2(b.i)

if b.l < x.bx.get_bottom()


x.brL := true
x.brZ := true
alert('sellside liquidity level breached for ' + syminfo.ticker)

x.bxz.set_lefttop(b.i - 1, x.ln.get_y1())
x.bxz.set_rightbottom(b.i + 1, math.max(x.ln.get_y1() - marSel *
(atr10), b.l))
x.bxz.set_bgcolor(color.new(cLIQ_S, liqSel ? 73 : 100))

else if x.brZ
if b.l > x.ln.get_y1() - marSel * (atr10) and b.h < x.ln.get_y1() + marSel
* (atr10)
x.bxz.set_rightbottom(b.i + 1, math.min(b.l, x.bxz.get_bottom()))
if liqSel
x.lne.set_x2(b.i + 1)
else
x.brZ := false

if lqVoid and per


bull = b.l - b.h[2] > atr and b.l > b.h[2] and b.c[1] > b.h[2]
bear = b.l[2] - b.h > atr and b.h < b.l[2] and b.c[1] < b.l[2]

if bull
l = 13
if bull[1]
st = math.abs(b.l - b.l[1]) / l
for i = 0 to l - 1
array.push(b_liq_V, box.new(b.i - 2, b.l[1] + i * st, b.i, b.l[1] +
(i + 1) * st, border_color = na, bgcolor = color.new(cLQV_B, 90) ))
else
st = math.abs(b.l - b.h[2]) / l
for i = 0 to l - 1
if lqText and i == 0
array.push(b_liq_V, box.new(b.i - 2, b.h[2] + i * st, b.i,
b.h[2] + (i + 1) * st, text = 'Liquidity Void ', text_size = size.tiny,
text_halign = text.align_right, text_valign = text.align_bottom, text_color = na,
border_color = na, bgcolor = color.new(cLQV_B, 90) ))
else
array.push(b_liq_V, box.new(b.i - 2, b.h[2] + i * st, b.i,
b.h[2] + (i + 1) * st, border_color = na, bgcolor = color.new(cLQV_B, 90) ))

if bear
l = 13
if bear[1]
st = math.abs(b.h[1] - b.h) / l
for i = 0 to l - 1
array.push(b_liq_V, box.new(b.i - 2, b.h + i * st, b.i, b.h + (i +
1) * st, border_color = na, bgcolor = color.new(cLQV_S, 90) ))
else
st = math.abs(b.l[2] - b.h) / l
for i = 0 to l - 1
if lqText and i == l - 1
array.push(b_liq_V, box.new(b.i - 2, b.h + i * st, b.i, b.h +
(i + 1) * st, text = 'Liquidity Void ', text_size = size.tiny, text_halign =
text.align_right, text_valign = text.align_top, text_color = na, border_color = na,
bgcolor = color.new(cLQV_S, 90) ))
else
array.push(b_liq_V, box.new(b.i - 2, b.h + i * st, b.i, b.h +
(i + 1) * st, border_color = na, bgcolor = color.new(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 = math.avg(cb.get_bottom(), cb.get_top())

if math.sign(b.c[1] - ba) != math.sign(b.c - ba) or math.sign(b.c[1] -


ba) != math.sign(b.l - ba) or math.sign(b.c[1] - ba) != math.sign(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(color.new(color.gray, 25))

//-----------------------------------------------------------------------------}

// This source code is subject to the terms of the Mozilla Public License 2.0 at
https://mozilla.org/MPL/2.0/
// © Pulu_

//@version=5
// Pulu's Moving Averages
// Release version 1.68, date 2021-12-05
//indicator(title='Pulu\'s Moving Averages', shorttitle='PMA', overlay=true)

strRoundValue(num) =>
strv = ''
if num >= 100000
strv := str.tostring(num/1000, '#K')
else if (num < 100000) and (num >= 100)
strv := str.tostring(num, '#')
else if (num < 100) and (num >= 1)
strv := str.tostring(num, '#.##')
else if (num < 1) and (num >= 0.01)
strv := str.tostring(num, '#.####')
else if (num < 0.01) and (num >= 0.0001)
strv := str.tostring(num, '#.######')
else if (num < 0.0001) and (num >= 0.000001)
strv := str.tostring(num, '#.########')
(strv)

defaultFunction(func, src, len, alma_offst, alma_sigma) =>


has_len = false
ma = ta.swma(close)
if func == 'ALMA'
ma := ta.alma(src, len, alma_offst, alma_sigma)
has_len := true
has_len
else if func == 'EMA'
ma := ta.ema(src, len)
has_len := true
has_len
else if func == 'RMA'
ma := ta.rma(src, len)
has_len := true
has_len
else if func == 'SMA'
ma := ta.sma(src, len)
has_len := true
has_len
else if func == 'SWMA'
ma := ta.swma(src)
has_len := false
has_len
else if func == 'VWAP'
ma := ta.vwap(src)
has_len := false
has_len
else if func == 'VWMA'
ma := ta.vwma(src, len)
has_len := true
has_len
else if func == 'WMA'
ma := ta.wma(src, len)
has_len := true
has_len
[ma, has_len]

def_fn = input.string(title='Default moving average', defval='EMA',


options=['ALMA', 'EMA', 'RMA', 'SMA', 'SWMA', 'VWAP', 'VWMA', 'WMA'])

ma1_on = input.bool(inline='MA1', title='Enable moving average 1', defval=false)


ma2_on = input.bool(inline='MA2', title='Enable moving average 2', defval=true)
ma3_on = input.bool(inline='MA3', title='Enable moving average 3', defval=false)
ma4_on = input.bool(inline='MA4', title='Enable moving average 4', defval=true)
ma5_on = input.bool(inline='MA5', title='Enable moving average 5', defval=true)
ma6_on = input.bool(inline='MA6', title='Enable moving average 6', defval=false)
ma7_on = input.bool(inline='MA7', title='Enable moving average 7', defval=false)

ma1_fn = input.string(inline='MA1', title='', defval='default', options=['default',


'ALMA', 'EMA', 'RMA', 'SMA', 'SWMA', 'VWAP', 'VWMA', 'WMA'])
ma2_fn = input.string(inline='MA2', title='', defval='default', options=['default',
'ALMA', 'EMA', 'RMA', 'SMA', 'SWMA', 'VWAP', 'VWMA', 'WMA'])
ma3_fn = input.string(inline='MA3', title='', defval='default', options=['default',
'ALMA', 'EMA', 'RMA', 'SMA', 'SWMA', 'VWAP', 'VWMA', 'WMA'])
ma4_fn = input.string(inline='MA4', title='', defval='default', options=['default',
'ALMA', 'EMA', 'RMA', 'SMA', 'SWMA', 'VWAP', 'VWMA', 'WMA'])
ma5_fn = input.string(inline='MA5', title='', defval='default', options=['default',
'ALMA', 'EMA', 'RMA', 'SMA', 'SWMA', 'VWAP', 'VWMA', 'WMA'])
ma6_fn = input.string(inline='MA6', title='', defval='default', options=['default',
'ALMA', 'EMA', 'RMA', 'SMA', 'SWMA', 'VWAP', 'VWMA', 'WMA'])
ma7_fn = input.string(inline='MA7', title='', defval='default', options=['default',
'ALMA', 'EMA', 'RMA', 'SMA', 'SWMA', 'VWAP', 'VWMA', 'WMA'])

ma1_len = input.int(inline='MA1', title='', defval=8, minval=1)


ma2_len = input.int(inline='MA2', title='', defval=20, minval=1)
ma3_len = input.int(inline='MA3', title='', defval=30, minval=1)
ma4_len = input.int(inline='MA4', title='', defval=144, minval=1)
ma5_len = input.int(inline='MA5', title='', defval=169, minval=1)
ma6_len = input.int(inline='MA6', title='', defval=576, minval=1)
ma7_len = input.int(inline='MA7', title='', defval=676, minval=1)

ma1_clr = input.color(inline='MA1', title='', defval=color.new(color.fuchsia,70))


ma2_clr = input.color(inline='MA2', title='', defval=color.new(color.aqua,70))
ma3_clr = input.color(inline='MA3', title='', defval=color.new(color.yellow,70))
ma4_clr = input.color(inline='MA4', title='', defval=color.new(color.aqua,70))
ma5_clr = input.color(inline='MA5', title='', defval=color.new(color.white, 70))
ma6_clr = input.color(inline='MA6', title='', defval=color.new(color.green,70))
ma7_clr = input.color(inline='MA7', title='', defval=color.new(color.red,70))

ma1_len_indx = ma1_len - 1
ma2_len_indx = ma2_len - 1
ma3_len_indx = ma3_len - 1
ma4_len_indx = ma4_len - 1
ma5_len_indx = ma5_len - 1
ma6_len_indx = ma6_len - 1
ma7_len_indx = ma7_len - 1

// Moving average 1 other parameters


alma1_offst = input.float(group='MA1 other settings', inline='MA11', title='ALMA
offset', defval=0.85, minval=-1, maxval=1, step=0.01)
alma1_sigma = input.float(group='MA1 other settings', inline='MA11', title=',
sigma', defval=6, minval=0, maxval=100, step=0.01)
ma1_src = input.source(group='MA1 other settings', inline='MA12', title='Source',
defval=close)
ma1_plt_offst = input.int(group='MA1 other settings', inline='MA12', title=', plot
offset', defval=0, minval=-500, maxval=500)

// Moving average 2 other parameters


alma2_offst = input.float(group='MA2 other settings', inline='MA21', title='ALMA
Offset', defval=0.85, minval=-1, maxval=1, step=0.01)
alma2_sigma = input.float(group='MA2 other settings', inline='MA21', title='Sigma',
defval=6, minval=0, maxval=100, step=0.01)
ma2_src = input.source(group='MA2 other settings', inline='MA22', title='Source',
defval=close)
ma2_plt_offst = input.int(group='MA2 other settings', inline='MA22', title='Polt
offset', defval=0, minval=-500, maxval=500)

// Moving average 3 other parameters


alma3_offst = input.float(group='MA3 other settings', inline='MA31', title='ALMA
Offset', defval=0.85, minval=-1, maxval=1, step=0.01)
alma3_sigma = input.float(group='MA3 other settings', inline='MA31', title='Sigma',
defval=6, minval=0, maxval=100, step=0.01)
ma3_src = input.source(group='MA3 other settings', inline='MA32', title='Source',
defval=close)
ma3_plt_offst = input.int(group='MA3 other settings', inline='MA32', title='Plot
offset', defval=0, minval=-500, maxval=500)

// Moving average 4 other parameters


alma4_offst = input.float(group='MA4 other settings', inline='MA41', title='ALMA
Offset', defval=0.85, minval=-1, maxval=1, step=0.01)
alma4_sigma = input.float(group='MA4 other settings', inline='MA41', title='Sigma',
defval=6, minval=0, maxval=100, step=0.01)
ma4_src = input.source(group='MA4 other settings', inline='MA42', title='Source',
defval=close)
ma4_plt_offst = input.int(group='MA4 other settings', inline='MA42', title='Plot
offset', defval=0, minval=-500, maxval=500)

// Moving average 5 other parameters


alma5_offst = input.float(group='MA5 other settings', inline='MA51', title='ALMA
Offset', defval=0.85, minval=-1, maxval=1, step=0.01)
alma5_sigma = input.float(group='MA5 other settings', inline='MA51', title='Sigma',
defval=6, minval=0, maxval=100, step=0.01)
ma5_src = input.source(group='MA5 other settings', inline='MA52', title='Source',
defval=close)
ma5_plt_offst = input.int(group='MA5 other settings', inline='MA52', title='Plot
offset', defval=0, minval=-500, maxval=500)

// Moving average 6 other parameters


alma6_offst = input.float(group='MA6 other settings', inline='MA61', title='ALMA
Offset', defval=0.85, minval=-1, maxval=1, step=0.01)
alma6_sigma = input.float(group='MA6 other settings', inline='MA61', title='Sigma',
defval=6, minval=0, maxval=100, step=0.01)
ma6_src = input.source(group='MA6 other settings', inline='MA62', title='Source',
defval=close)
ma6_plt_offst = input.int(group='MA6 other settings', inline='MA62', title='Plot
offset', defval=0, minval=-500, maxval=500)

// Moving average 7 other parameters


alma7_offst = input.float(group='MA7 other settings', inline='MA71', title='ALMA
Offset', defval=0.85, minval=-1, maxval=1, step=0.01)
alma7_sigma = input.float(group='MA7 other settings', inline='MA71', title='Sigma',
defval=6, minval=0, maxval=100, step=0.01)
ma7_src = input.source(group='MA7 other settings', inline='MA72', title='Source',
defval=close)
ma7_plt_offst = input.int(group='MA7 other settings', inline='MA72', title='Plot
offset', defval=0, minval=-500, maxval=500)

// Background fills between MAs


fill_12_on = input.bool(group='Background fills between MAs', inline='FILL1',
title='MA1-2', defval=false)
fill_23_on = input.bool(group='Background fills between MAs', inline='FILL2',
title='MA2-3', defval=false)
fill_34_on = input.bool(group='Background fills between MAs', inline='FILL3',
title='MA3-4', defval=false)
fill_45_on = input.bool(group='Background fills between MAs', inline='FILL4',
title='MA4-5', defval=false)
fill_56_on = input.bool(group='Background fills between MAs', inline='FILL5',
title='MA5-6', defval=false)
fill_67_on = input.bool(group='Background fills between MAs', inline='FILL6',
title='MA6-7', defval=false)

fill_12_trans = input.int(group='Background fills between MAs', inline='FILL1',


title=', transparency', defval=90, minval=0, maxval=100)
fill_23_trans = input.int(group='Background fills between MAs', inline='FILL2',
title=', transparency', defval=90, minval=0, maxval=100)
fill_34_trans = input.int(group='Background fills between MAs', inline='FILL3',
title=', transparency', defval=90, minval=0, maxval=100)
fill_45_trans = input.int(group='Background fills between MAs', inline='FILL4',
title=', transparency', defval=90, minval=0, maxval=100)
fill_56_trans = input.int(group='Background fills between MAs', inline='FILL5',
title=', transparency', defval=90, minval=0, maxval=100)
fill_67_trans = input.int(group='Background fills between MAs', inline='FILL6',
title=', transparency', defval=90, minval=0, maxval=100)

// Initial moving averages


[ma1, ma1_has_len] = defaultFunction(def_fn, ma1_src, ma1_len, alma1_offst,
alma1_sigma)
[ma2, ma2_has_len] = defaultFunction(def_fn, ma2_src, ma2_len, alma2_offst,
alma2_sigma)
[ma3, ma3_has_len] = defaultFunction(def_fn, ma3_src, ma3_len, alma3_offst,
alma3_sigma)
[ma4, ma4_has_len] = defaultFunction(def_fn, ma4_src, ma4_len, alma4_offst,
alma4_sigma)
[ma5, ma5_has_len] = defaultFunction(def_fn, ma5_src, ma5_len, alma5_offst,
alma5_sigma)
[ma6, ma6_has_len] = defaultFunction(def_fn, ma6_src, ma6_len, alma6_offst,
alma6_sigma)
[ma7, ma7_has_len] = defaultFunction(def_fn, ma7_src, ma7_len, alma7_offst,
alma7_sigma)

if ma1_fn != 'default' // if MA1 does not use default function


if ma1_fn == 'ALMA'
ma1 := ta.alma(ma1_src, ma1_len, alma1_offst, alma1_sigma)
ma1_has_len := true
else if ma1_fn == 'EMA'
ma1 := ta.ema(ma1_src, ma1_len)
ma1_has_len := true
else if ma1_fn == 'RMA'
ma1 := ta.rma(ma1_src, ma1_len)
ma1_has_len := true
else if ma1_fn == 'SMA'
ma1 := ta.sma(ma1_src, ma1_len)
ma1_has_len := true
else if ma1_fn == 'SWMA'
ma1 := ta.swma(ma1_src)
ma1_has_len := false
else if ma1_fn == 'VWAP'
ma1 := ta.vwap(ma1_src)
ma1_has_len := false
else if ma1_fn == 'VWMA'
ma1 := ta.vwma(ma1_src, ma1_len)
ma1_has_len := true
else if ma1_fn == 'WMA'
ma1 := ta.wma(ma1_src, ma1_len)
ma1_has_len := true

if ma2_fn != 'default' // if MA2 does not use default function


if ma2_fn == 'ALMA'
ma2 := ta.alma(ma2_src, ma2_len, alma2_offst, alma2_sigma)
ma2_has_len := true
else if ma2_fn == 'EMA'
ma2 := ta.ema(ma2_src, ma2_len)
ma2_has_len := true
else if ma2_fn == 'RMA'
ma2 := ta.rma(ma2_src, ma2_len)
ma2_has_len := true
else if ma2_fn == 'SMA'
ma2 := ta.sma(ma2_src, ma2_len)
ma2_has_len := true
else if ma2_fn == 'SWMA'
ma2 := ta.swma(ma2_src)
ma2_has_len := false
else if ma2_fn == 'VWAP'
ma2 := ta.vwap(ma2_src)
ma2_has_len := false
else if ma2_fn == 'VWMA'
ma2 := ta.vwma(ma2_src, ma1_len)
ma2_has_len := true
else if ma2_fn == 'WMA'
ma2 := ta.wma(ma2_src, ma2_len)
ma2_has_len := true

if ma3_fn != 'default' // if MA3 does not use default function


if ma3_fn == 'ALMA'
ma3 := ta.alma(ma3_src, ma3_len, alma3_offst, alma3_sigma)
ma3_has_len := true
else if ma3_fn == 'EMA'
ma3 := ta.ema(ma3_src, ma3_len)
ma3_has_len := true
else if ma3_fn == 'RMA'
ma3 := ta.rma(ma3_src, ma3_len)
ma3_has_len := true
else if ma3_fn == 'SMA'
ma3 := ta.sma(ma3_src, ma3_len)
ma3_has_len := true
else if ma3_fn == 'SWMA'
ma3 := ta.swma(ma3_src)
ma3_has_len := false
else if ma3_fn == 'VWAP'
ma3 := ta.vwap(ma3_src)
ma3_has_len := false
else if ma3_fn == 'VWMA'
ma3 := ta.vwma(ma3_src, ma3_len)
ma3_has_len := true
else if ma3_fn == 'WMA'
ma3 := ta.wma(ma3_src, ma3_len)
ma3_has_len := true

if ma4_fn != 'default' // if MA4 does not use default function


if ma4_fn == 'ALMA'
ma4 := ta.alma(ma4_src, ma4_len, alma4_offst, alma4_sigma)
ma4_has_len := true
else if ma4_fn == 'EMA'
ma4 := ta.ema(ma4_src, ma4_len)
ma4_has_len := true
else if ma4_fn == 'RMA'
ma4 := ta.rma(ma4_src, ma4_len)
ma4_has_len := true
else if ma4_fn == 'SMA'
ma4 := ta.sma(ma4_src, ma4_len)
ma4_has_len := true
else if ma4_fn == 'SWMA'
ma4 := ta.swma(ma4_src)
ma4_has_len := false
else if ma4_fn == 'VWAP'
ma4 := ta.vwap(ma4_src)
ma4_has_len := false
else if ma4_fn == 'VWMA'
ma4 := ta.vwma(ma4_src, ma4_len)
ma4_has_len := true
else if ma4_fn == 'WMA'
ma4 := ta.wma(ma4_src, ma4_len)
ma4_has_len := true

if ma5_fn != 'default' // if MA5 does not use default function


if ma5_fn == 'ALMA'
ma5 := ta.alma(ma5_src, ma5_len, alma5_offst, alma5_sigma)
ma5_has_len := true
else if ma5_fn == 'EMA'
ma5 := ta.ema(ma5_src, ma5_len)
ma5_has_len := true
else if ma5_fn == 'RMA'
ma5 := ta.rma(ma5_src, ma5_len)
ma5_has_len := true
else if ma5_fn == 'SMA'
ma5 := ta.sma(ma5_src, ma5_len)
ma5_has_len := true
else if ma5_fn == 'SWMA'
ma5 := ta.swma(ma5_src)
ma5_has_len := false
else if ma5_fn == 'VWAP'
ma5 := ta.vwap(ma5_src)
ma5_has_len := false
else if ma5_fn == 'VWMA'
ma5 := ta.vwma(ma5_src, ma5_len)
ma5_has_len := true
else if ma5_fn == 'WMA'
ma5 := ta.wma(ma5_src, ma5_len)
ma5_has_len := true

if ma6_fn != 'default' // if MA6 does not use default function


if ma6_fn == 'ALMA'
ma6 := ta.alma(ma6_src, ma6_len, alma6_offst, alma6_sigma)
ma6_has_len := true
else if ma6_fn == 'EMA'
ma6 := ta.ema(ma6_src, ma6_len)
ma6_has_len := true
else if ma6_fn == 'RMA'
ma6 := ta.rma(ma6_src, ma6_len)
ma6_has_len := true
else if ma6_fn == 'SMA'
ma6 := ta.sma(ma6_src, ma6_len)
ma6_has_len := true
else if ma6_fn == 'SWMA'
ma6 := ta.swma(ma6_src)
ma6_has_len := false
else if ma6_fn == 'VWAP'
ma6 := ta.vwap(ma6_src)
ma6_has_len := false
else if ma6_fn == 'VWMA'
ma6 := ta.vwma(ma6_src, ma6_len)
ma6_has_len := true
else if ma6_fn == 'WMA'
ma6 := ta.wma(ma6_src, ma6_len)
ma6_has_len := true

if ma7_fn != 'default' // if MA7 does not use default function


if ma7_fn == 'ALMA'
ma7 := ta.alma(ma6_src, ma7_len, alma7_offst, alma7_sigma)
ma7_has_len := true
else if ma7_fn == 'EMA'
ma7 := ta.ema(ma7_src, ma7_len)
ma7_has_len := true
else if ma7_fn == 'RMA'
ma7 := ta.rma(ma7_src, ma7_len)
ma7_has_len := true
else if ma7_fn == 'SMA'
ma7 := ta.sma(ma7_src, ma7_len)
ma7_has_len := true
else if ma7_fn == 'SWMA'
ma7 := ta.swma(ma7_src)
ma7_has_len := false
else if ma7_fn == 'VWAP'
ma7 := ta.vwap(ma7_src)
ma7_has_len := false
else if ma7_fn == 'VWMA'
ma7 := ta.vwma(ma7_src, ma7_len)
ma7_has_len := true
else if ma7_fn == 'WMA'
ma7 := ta.wma(ma7_src, ma7_len)
ma7_has_len := true

// Plot MA curves
p1 = plot(series=ma1_on and switch_ema ? ma1 : na, color=ma1_clr, trackprice=false,
offset=ma1_plt_offst)
p2 = plot(series=ma2_on and switch_ema ? ma2 : na, color=ma2_clr, trackprice=false,
offset=ma2_plt_offst)
p3 = plot(series=ma3_on and switch_ema ? ma3 : na, color=ma3_clr, trackprice=false,
offset=ma3_plt_offst)
p4 = plot(series=ma4_on and switch_ema ? ma4 : na, color=ma4_clr, trackprice=false,
offset=ma4_plt_offst)
p5 = plot(series=ma5_on and switch_ema ? ma5 : na, color=ma5_clr, trackprice=false,
offset=ma5_plt_offst)
p6 = plot(series=ma6_on and switch_ema ? ma6 : na, color=ma6_clr, trackprice=false,
offset=ma6_plt_offst)
p7 = plot(series=ma7_on and switch_ema ? ma7 : na, color=ma7_clr, trackprice=false,
offset=ma7_plt_offst)

// Background fills between MAs


fill(p1, p2, color.new((ma1 > ma2 ? ma1_clr : ma2_clr), (ma1_on and ma2_on and
fill_12_on ? fill_12_trans : 100)))
fill(p2, p3, color.new((ma2 > ma3 ? ma2_clr : ma3_clr), (ma2_on and ma3_on and
fill_23_on ? fill_23_trans : 100)))
fill(p3, p4, color.new((ma3 > ma4 ? ma3_clr : ma4_clr), (ma3_on and ma4_on and
fill_34_on ? fill_34_trans : 100)))
fill(p4, p5, color.new((ma4 > ma5 ? ma4_clr : ma5_clr), (ma4_on and ma5_on and
fill_45_on ? fill_45_trans : 100)))
fill(p5, p6, color.new((ma5 > ma6 ? ma5_clr : ma6_clr), (ma5_on and ma6_on and
fill_56_on ? fill_56_trans : 100)))
fill(p6, p7, color.new((ma6 > ma7 ? ma6_clr : ma7_clr), (ma6_on and ma7_on and
fill_67_on ? fill_67_trans : 100)))

/////////////////////////////////////////////
/////////// Half Trend
////////////////////////////////////////////

ht_group = "██████ HalfTrend ██████"


amplitude = input(title='Amplitude', defval=2,group=ht_group)
channelDeviation = input(title='Channel Deviation', defval=2,group=ht_group)
showArrows = input(title='Show Arrows', defval=true,group=ht_group)
showChannels = input(title='Show Channels', defval=false,group=ht_group)

var int ht_trend = 0


var int nextTrend = 0
var float maxLowPrice = nz(low[1], low)
var float minHighPrice = nz(high[1], high)

var float ht_up = 0.0


var float ht_down = 0.0
float atrHigh = 0.0
float atrLow = 0.0
float arrowUp = na
float arrowDown = na

ht_atr2 = ta.atr(100) / 2
ht_dev = channelDeviation * ht_atr2
highPrice = high[math.abs(ta.highestbars(amplitude))]
lowPrice = low[math.abs(ta.lowestbars(amplitude))]
highma = ta.sma(high, amplitude)
lowma = ta.sma(low, amplitude)

if nextTrend == 1
maxLowPrice := math.max(lowPrice, maxLowPrice)

if highma < maxLowPrice and close < nz(low[1], low)


ht_trend := 1
nextTrend := 0
minHighPrice := highPrice
minHighPrice
else
minHighPrice := math.min(highPrice, minHighPrice)

if lowma > minHighPrice and close > nz(high[1], high)


ht_trend := 0
nextTrend := 1
maxLowPrice := lowPrice
maxLowPrice

if ht_trend == 0
if not na(ht_trend[1]) and ht_trend[1] != 0
ht_up := na(ht_down[1]) ? ht_down : ht_down[1]
arrowUp := ht_up - ht_atr2
arrowUp
else
ht_up := na(ht_up[1]) ? maxLowPrice : math.max(maxLowPrice, ht_up[1])
ht_up
atrHigh := ht_up + ht_dev
atrLow := ht_up - ht_dev
atrLow
else
if not na(ht_trend[1]) and ht_trend[1] != 1
ht_down := na(ht_up[1]) ? ht_up : ht_up[1]
arrowDown := ht_down + ht_atr2
arrowDown
else
ht_down := na(ht_down[1]) ? minHighPrice : math.min(minHighPrice,
ht_down[1])
ht_down
atrHigh := ht_down + ht_dev
atrLow := ht_down - ht_dev
atrLow

ht = ht_trend == 0 ? ht_up : ht_down

var color buyColor = color.blue


var color sellColor = color.red

htColor = ht_trend == 0 ? buyColor : sellColor


htPlot = plot(switch_halftrend ? ht : na, title='HalfTrend', linewidth=1,
color=color.new(htColor, 50))
///////////////////////////////////////////////////
//////// SUpply/Demand POI
//////////////////////////////////////////////////
// INDICATOR SETTINGS
poi_group = '████████ Supply/Demand Zone ████████'
swing_length = input.int(10, title = 'Swing High/Low Length', group = poi_group,
minval = 1, maxval = 50)
history_of_demand_to_keep = input.int(20, title = 'History To Keep', minval = 5,
maxval = 50, group = poi_group)
box_width = input.float(2.0, title = 'Supply/Demand Box Width', group = poi_group,
minval = 1, maxval = 10, step = 0.5)

// INDICATOR VISUAL SETTINGS


show_zigzag = input.bool(false, title = 'Show Zig Zag', group = 'Visual Settings',
inline = '1')
show_price_action_labels = input.bool(true, title = 'Show Price Action Labels',
group = 'Visual Settings', inline = '2')

supply_color = input.color(color.new(#EDEDED,70), title = 'Supply', group = 'Visual


Settings', inline = '3')
supply_outline_color = input.color(color.new(color.white,100), title = 'Outline',
group = 'Visual Settings', inline = '3')

demand_color = input.color(color.new(#00FFFF,70), title = 'Demand', group = 'Visual


Settings', inline = '4')
demand_outline_color = input.color(color.new(color.white,100), title = 'Outline',
group = 'Visual Settings', inline = '4')

poi_label_color = input.color(color.white, title = 'POI Label', group = 'Visual


Settings', inline = '7')

swing_type_color = input.color(color.black, title = 'Price Action Label', group =


'Visual Settings', inline = '8')
zigzag_color = input.color(color.new(#000000,0), title = 'Zig Zag', group = 'Visual
Settings', inline = '9')

//
//END SETTINGS
//

atrpoi = ta.atr(50)
//
//FUNCTIONS
//

// FUNCTION TO ADD NEW AND REMOVE LAST IN ARRAY


f_array_add_pop(array, new_value_to_add) =>
array.unshift(array, new_value_to_add)
array.pop(array)

// FUNCTION SWING H & L LABELS


f_sh_sl_labels(array, swing_type) =>

var string label_text = na


if swing_type == 1
if array.get(array, 0) >= array.get(array, 1)
label_text := 'HH'
else
label_text := 'LH'
label.new(bar_index - swing_length, array.get(array,0), text = label_text,
style=label.style_label_down, textcolor = swing_type_color, color =
color.new(swing_type_color, 100), size = size.tiny)

else if swing_type == -1
if array.get(array, 0) >= array.get(array, 1)
label_text := 'HL'
else
label_text := 'LL'
label.new(bar_index - swing_length, array.get(array,0), text = label_text,
style=label.style_label_up, textcolor = swing_type_color, color =
color.new(swing_type_color, 100), size = size.tiny)

// FUNCTION MAKE SURE SUPPLY ISNT OVERLAPPING


f_check_overlapping(new_poi, box_array, atrpoi) =>

atr_threshold = atrpoi * 2
okay_to_draw = true

for i = 0 to array.size(box_array) - 1
top = box.get_top(array.get(box_array, i))
bottom = box.get_bottom(array.get(box_array, i))
poi = (top + bottom) / 2

upper_boundary = poi + atr_threshold


lower_boundary = poi - atr_threshold

if new_poi >= lower_boundary and new_poi <= upper_boundary


okay_to_draw := false
break
else
okay_to_draw := true
okay_to_draw

// FUNCTION TO DRAW SUPPLY OR DEMAND ZONE


f_supply_demand(value_array, bn_array, box_array, label_array, box_type, atrpoi) =>

atr_buffer = atrpoi * (box_width / 10)


box_left = array.get(bn_array, 0)
box_right = bar_index

var float box_top = 0.00


var float box_bottom = 0.00
var float poi = 0.00

if box_type == 1
box_top := array.get(value_array, 0)
box_bottom := box_top - atr_buffer
poi := (box_top + box_bottom) / 2
else if box_type == -1
box_bottom := array.get(value_array, 0)
box_top := box_bottom + atr_buffer
poi := (box_top + box_bottom) / 2

okay_to_draw = f_check_overlapping(poi, box_array, atrpoi)


// okay_to_draw = true
//delete oldest box, and then create a new box and add it to the array
if box_type == 1 and okay_to_draw and switch_poi
box.delete( array.get(box_array, array.size(box_array) - 1) )
f_array_add_pop(box_array, box.new( left = box_left, top = box_top, right =
box_right, bottom = box_bottom, border_color = supply_outline_color,
bgcolor = supply_color, extend = extend.right, text = 'SUPPLY',
text_halign = text.align_center, text_valign = text.align_center, text_color =
poi_label_color, text_size = size.small, xloc = xloc.bar_index))

box.delete( array.get(label_array, array.size(label_array) - 1) )


f_array_add_pop(label_array, box.new( left = box_left, top = poi, right =
box_right, bottom = poi, border_color = color.new(poi_label_color,90),
bgcolor = color.new(poi_label_color,90), extend = extend.right, text =
'POI', text_halign = text.align_left, text_valign = text.align_center, text_color =
poi_label_color, text_size = size.small, xloc = xloc.bar_index))

else if box_type == -1 and okay_to_draw and switch_poi


box.delete( array.get(box_array, array.size(box_array) - 1) )
f_array_add_pop(box_array, box.new( left = box_left, top = box_top, right =
box_right, bottom = box_bottom, border_color = demand_outline_color,
bgcolor = demand_color, extend = extend.right, text = 'DEMAND',
text_halign = text.align_center, text_valign = text.align_center, text_color =
poi_label_color, text_size = size.small, xloc = xloc.bar_index))

box.delete( array.get(label_array, array.size(label_array) - 1) )


f_array_add_pop(label_array, box.new( left = box_left, top = poi, right =
box_right, bottom = poi, border_color = color.new(poi_label_color,90),
bgcolor = color.new(poi_label_color,90), extend = extend.right, text
= 'POI', text_halign = text.align_left, text_valign = text.align_center, text_color
= poi_label_color, text_size = size.small, xloc = xloc.bar_index))

// FUNCTION TO CHANGE SUPPLY/DEMAND TO A BOS IF BROKEN


f_sd_to_bos(box_array, bos_array, label_array, zone_type) =>

if zone_type == 1 and switch_poi


for i = 0 to array.size(box_array) - 1
level_to_break = box.get_top(array.get(box_array,i))
// if ta.crossover(close, level_to_break)
if close >= level_to_break
copied_box = box.copy(array.get(box_array,i))
f_array_add_pop(bos_array, copied_box)
mid = (box.get_top(array.get(box_array,i)) +
box.get_bottom(array.get(box_array,i))) / 2
box.set_top(array.get(bos_array,0), mid)
box.set_bottom(array.get(bos_array,0), mid)
box.set_extend( array.get(bos_array,0), extend.none)
box.set_right( array.get(bos_array,0), bar_index)
box.set_text( array.get(bos_array,0), '' )
box.set_text_color( array.get(bos_array,0), color.new(color.white,
0))
box.set_text_size( array.get(bos_array,0), size.small)
box.set_text_halign( array.get(bos_array,0), text.align_center)
box.set_text_valign( array.get(bos_array,0), text.align_center)
box.delete(array.get(box_array, i))
box.delete(array.get(label_array, i))
if zone_type == -1 and switch_poi
for i = 0 to array.size(box_array) - 1
level_to_break = box.get_bottom(array.get(box_array,i))
// if ta.crossunder(close, level_to_break)
if close <= level_to_break
copied_box = box.copy(array.get(box_array,i))
f_array_add_pop(bos_array, copied_box)
mid = (box.get_top(array.get(box_array,i)) +
box.get_bottom(array.get(box_array,i))) / 2
box.set_top(array.get(bos_array,0), mid)
box.set_bottom(array.get(bos_array,0), mid)
box.set_extend( array.get(bos_array,0), extend.none)
box.set_right( array.get(bos_array,0), bar_index)
box.set_text( array.get(bos_array,0), '' )
box.set_text_color( array.get(bos_array,0), color.new(color.white,
0))
box.set_text_size( array.get(bos_array,0), size.small)
box.set_text_halign( array.get(bos_array,0), text.align_center)
box.set_text_valign( array.get(bos_array,0), text.align_center)
box.delete(array.get(box_array, i))
box.delete(array.get(label_array, i))

// FUNCTION MANAGE CURRENT BOXES BY CHANGING ENDPOINT


f_extend_box_endpoint(box_array) =>

for i = 0 to array.size(box_array) - 1
box.set_right(array.get(box_array, i), bar_index + 100)

// CALCULATE SWING HIGHS & SWING LOWS


swing_high = ta.pivothigh(high, swing_length, swing_length)
swing_low = ta.pivotlow(low, swing_length, swing_length)

// ARRAYS FOR SWING H/L & BN


var swing_high_values = array.new_float(5,0.00)
var swing_low_values = array.new_float(5,0.00)

var swing_high_bns = array.new_int(5,0)


var swing_low_bns = array.new_int(5,0)

// ARRAYS FOR SUPPLY / DEMAND


var current_supply_box = array.new_box(history_of_demand_to_keep, na)
var current_demand_box = array.new_box(history_of_demand_to_keep, na)

// ARRAYS FOR SUPPLY / DEMAND POI LABELS


var current_supply_poi = array.new_box(history_of_demand_to_keep, na)
var current_demand_poi = array.new_box(history_of_demand_to_keep, na)

// ARRAYS FOR BOS


var supply_bos = array.new_box(5, na)
var demand_bos = array.new_box(5, na)
//
//END CALCULATIONS
//

// NEW SWING HIGH


if not na(swing_high)

//MANAGE SWING HIGH VALUES


f_array_add_pop(swing_high_values, swing_high)
f_array_add_pop(swing_high_bns, bar_index[swing_length])
if show_price_action_labels
f_sh_sl_labels(swing_high_values, 1)

f_supply_demand(swing_high_values, swing_high_bns, current_supply_box,


current_supply_poi, 1, atrpoi)

// NEW SWING LOW


else if not na(swing_low)

//MANAGE SWING LOW VALUES


f_array_add_pop(swing_low_values, swing_low)
f_array_add_pop(swing_low_bns, bar_index[swing_length])
if show_price_action_labels
f_sh_sl_labels(swing_low_values, -1)

f_supply_demand(swing_low_values, swing_low_bns, current_demand_box,


current_demand_poi, -1, atrpoi)

f_sd_to_bos(current_supply_box, supply_bos, current_supply_poi, 1)


f_sd_to_bos(current_demand_box, demand_bos, current_demand_poi, -1)

f_extend_box_endpoint(current_supply_box)
f_extend_box_endpoint(current_demand_box)

//@version=5
//indicator('Vector Candles', overlay=true, max_bars_back=300,max_boxes_count=500,
max_lines_count=500, max_labels_count=500)

//inputs
bool overridesym = input.bool(group='PVSRA', title='Override chart symbol?',
defval=false, inline='pvsra')
string pvsra_sym = input.symbol(group='PVSRA', title='', defval='INDEX:BTCUSD',
tooltip='You can use INDEX:BTCUSD or you can combine multiple feeds, for
example \'(BINANCE:BTCUSDT+COINBASE:BTCUSD)\'. Note that adding too many will slow
things down.', inline='pvsra')

// PVSRA
pvsra_security(sresolution, sseries) =>
request.security(overridesym ? pvsra_sym : syminfo.tickerid, sresolution,
sseries[barstate.isrealtime ? 1 : 0], barmerge.gaps_off, barmerge.lookahead_off)
pvsra_security_1 = pvsra_security('', volume)
pvsra_volume = overridesym == true ? pvsra_security_1 : volume
pvsra_security_2 = pvsra_security('', high)
pvsra_high = overridesym == true ? pvsra_security_2 : high
pvsra_security_3 = pvsra_security('', low)
pvsra_low = overridesym == true ? pvsra_security_3 : low
pvsra_security_4 = pvsra_security('', close)
pvsra_close = overridesym == true ? pvsra_security_4 : close
pvsra_security_5 = pvsra_security('', open)
pvsra_open = overridesym == true ? pvsra_security_5 : open
// The below math matches MT4 PVSRA indicator source
// average volume from last 10 candles
sum_1 = math.sum(pvsra_volume, 10)
sum_2 = math.sum(volume, 10)
av = overridesym == true ? sum_1 / 10 : sum_2 / 10
//climax volume on the previous candle
value2 = overridesym == true ? pvsra_volume * (pvsra_high - pvsra_low) : volume *
(high - low)
// highest climax volume of the last 10 candles
hivalue2 = ta.highest(value2, 10)
// VA value determines the bar color. va = 0: normal. va = 1: climax. va = 2:
rising
iff_1 = pvsra_volume >= av * 1.5 ? 2 : 0
iff_2 = pvsra_volume >= av * 2 or value2 >= hivalue2 ? 1 : iff_1
iff_3 = volume >= av * 1.5 ? 2 : 0
iff_4 = volume >= av * 2 or value2 >= hivalue2 ? 1 : iff_3
va = overridesym == true ? iff_2 : iff_4

// Bullish or bearish coloring


isBull = overridesym == true ? pvsra_close > pvsra_open : close > open

CUColor = color.lime // Climax up (bull) bull and bear both start with b so it
would be weird hence up down
CDColor = color.red // Climax down (bear)

AUColor = color.blue //Avobe average up (bull)


ADColor = color.fuchsia //Above average down (bear))

NUColor = #9b9b9b
NDColor = #414141

// candleColor =
iff(climax,iff(isBull,CUColor,CDColor),iff(aboveA,iff(isBull,AUColor,ADColor),iff(i
sBull,NUColor,NDColor)))
iff_5 = va == 2 ? AUColor : NUColor
iff_6 = va == 1 ? CUColor : iff_5
iff_7 = va == 2 ? ADColor : NDColor
iff_8 = va == 1 ? CDColor : iff_7
candleColor = isBull ? iff_6 : iff_8
barcolor(candleColor)
plotcandle(open, high, low, close, color = candleColor, wickcolor = candleColor,
bordercolor= candleColor, display = display.all)

///////////////////////////////////////////////////
//Turtle Soup
///////////////////////////////////////////////////
tsperiod = 20

high_value = ta.highest(high, tsperiod)


low_value = ta.lowest(low, tsperiod)

high_candle = high == high_value


low_candle = low == low_value

prev_high_value = ta.highest(high[1], tsperiod)


prev2_high_value = ta.highest(high[2], tsperiod)
prev3_high_value = ta.highest(high[3], tsperiod)
prev4_high_value = ta.highest(high[4], tsperiod)

prev_low_value = ta.lowest(low[1], tsperiod)


prev2_low_value = ta.lowest(low[2], tsperiod)
prev3_low_value = ta.lowest(low[3], tsperiod)
prev4_low_value = ta.lowest(low[4], tsperiod)

no_prev_high_candle = not (high[1] == prev_high_value or high[2] ==


prev2_high_value or high[3] == prev3_high_value or high[4] == prev4_high_value)
no_prev_low_candle = not (low[1] == prev_low_value or low[2] == prev2_low_value or
low[3] == prev3_low_value or low[4] == prev4_low_value)

plotshape(switch_ts and high_candle and no_prev_high_candle and no_prev_low_candle,


title="Turtle Soup", location=location.abovebar, color=color.green,
style=shape.cross, size=size.tiny)
plotshape(switch_ts and low_candle and no_prev_high_candle and no_prev_low_candle,
title="Turtle Soup", location=location.belowbar, color=color.red,
style=shape.cross, size=size.tiny)

You might also like