Smart Money Concepts V40
Smart Money Concepts V40
0
at https://mozilla.org/MPL/2.0/
// © DrunkXiao
//@version=5
//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)
//----------------------------------------}
//Internal Structure
//----------------------------------------{
show_internals = input(true, 'Show Internal Structure'
, group = 'Real Time Internal Structure'
, tooltip = SHOW_INTERNAL)
//Bear Structure
show_ibear = input.string('All', 'Bearish Structure'
, options = ['All', 'BOS', 'CHoCH']
, inline = 'ibear'
, 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')
//Bear Structure
show_bear = input.string('All', 'Bearish Structure'
, options = ['All', 'BOS', 'CHoCH']
, inline = 'bear'
, group = 'Real Time Swing Structure')
//Swings
show_swings = input(false, 'Show Swings Points'
, inline = 'swings'
, group = 'Real Time Swing Structure'
, tooltip = SHOW_SWING_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')
//----------------------------------------}
//EQH/EQL
//----------------------------------------{
show_eq = input(true, 'Equal High/Low'
, group = 'EQH/EQL'
, tooltip = SHOW_EQHL)
//----------------------------------------}
//Previous day/week high/low
//----------------------------------------{
//Daily
show_pdhl = input(false, 'Daily'
, inline = 'daily'
, group = 'Highs & Lows MTF')
//Weekly
show_pwhl = input(false, 'Weekly'
, inline = 'weekly'
, group = 'Highs & Lows MTF')
//Monthly
show_pmhl = input(false, 'Monthly'
, inline = 'monthly'
, group = 'Highs & Lows MTF')
//----------------------------------------}
//Premium/Discount zones
//----------------------------------------{
show_sd = input(false, 'Premium/Discount Zones'
, group = 'Premium & Discount Zones'
, tooltip = PED_ZONES)
atr = ta.atr(200)
cmean_range = ta.cum(high - low) / n
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)
[top, btm]
//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)
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)
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)
//Low
line.set_xy1(low_line, lx, ly)
line.set_xy2(low_line, ext, ly)
//-----------------------------------------------------------------------------}
//Global variables
//-----------------------------------------------------------------------------{
var trend = 0, var itrend = 0
//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
//Labels size
var internal_structure_lbl_size = internal_structure_size == 'Tiny'
? size.tiny
: internal_structure_size == 'Small'
? size.small
: size.normal
//Swings
[top, btm] = swings(length)
//-----------------------------------------------------------------------------}
//Pivot High
//-----------------------------------------------------------------------------{
var line extend_top = na
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])
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
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
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])
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
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)
//-----------------------------------------------------------------------------}
//Pivot High BOS/CHoCH
//-----------------------------------------------------------------------------{
//Filtering
var bull_concordant = true
if ifilter_confluence
bull_concordant := high - math.max(close, open) > math.min(close, open - low)
if itrend < 0
choch := true
bull_ichoch_alert := true
else
bull_ibos_alert := true
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
if trend < 0
choch := true
bull_choch_alert := true
else
bull_bos_alert := true
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)
if itrend > 0
choch := true
bear_ichoch_alert := true
else
bear_ibos_alert := true
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
if trend > 0
choch := true
bear_choch_alert := true
else
bear_bos_alert := true
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)
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 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)
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
////////////////////////////////////////////////////
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]
//-----------------------------------------------------------------------------}
//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)
label.set_xy(eq_lbl, n, avg)
//-----------------------------------------------------------------------------}
//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
//-----------------------------------------------------------------------------}
//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')
//Swing Structure
//alertcondition(bull_bos_alert, 'Bullish BOS', 'Internal Bullish BOS formed')
//alertcondition(bull_choch_alert, 'Bullish CHoCH', 'Internal Bullish CHoCH
formed')
//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')
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 conditiontype == 'None'
condition := true
condition2 := true
condition3 := true
condition4 := true
condition5 := true
condition6 := true
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)
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)
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 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)
// 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)
// 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
// 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)
// 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)
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
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]
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_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]
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]
//------------------------------------------------------------------------------
//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)
//-----------------------------------------------------------------------------}
//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
float o = open
float h = high
float l = low
float c = close
int i = bar_index
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 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()
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))
)
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))
)
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)
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)
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 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())
//-----------------------------------------------------------------------------}
// 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)
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
// 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)
/////////////////////////////////////////////
/////////// Half Trend
////////////////////////////////////////////
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 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
//
//END SETTINGS
//
atrpoi = ta.atr(50)
//
//FUNCTIONS
//
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)
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
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
for i = 0 to array.size(box_array) - 1
box.set_right(array.get(box_array, i), bar_index + 100)
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
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)
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