// This work is licensed under a Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.
0)
https://creativecommons.org/licenses/by-nc-sa/4.0/
// © LuxAlgo
//@version=5
indicator("Smart Money Concepts [LuxAlgo]", "Smart Money Concepts [LuxAlgo]"
, overlay = true
, max_labels_count = 200
, max_lines_count = 200
, max_boxes_count = 200
, max_bars_back = 200)
//-----------------------------------------------------------------------------{
//Constants
//-----------------------------------------------------------------------------{
plotma=plot(ta.ema(close,200),color=color.green,linewidth=2)
//vwap
O_PERIOD1 = 'Session'
O_PERIOD2 = 'Week'
//#region ——————————— <inputs> {
i_src = input.source (hlc3, 'Source' )
i_period = input.string (O_PERIOD1, 'Period' ,
options = [O_PERIOD1, O_PERIOD2])
//i_rangeLen = input.float (0.618, 'Range Length' )
i_millisDay = 86400000
i_daysInWeek = 7
//#endregion }
dwmBarTime = timeframe.isdwm ? time : time('D')
if na(dwmBarTime)
dwmBarTime := nz(dwmBarTime[1])
dwmBarTime
var periodStart = time - time
f_makeMondayZero(_dayOfWeek) =>
(_dayOfWeek + 5) % 7
f_isMidnight(_t) =>
hour(_t) == 0 and minute(_t) == 0
f_isSameDay(_t1, _t2) =>
dayofmonth(_t1) == dayofmonth(_t2) and month(_t1) == month(_t2) and year(_t1) == year(_t2)
f_isOvernight() =>
not(f_isMidnight(dwmBarTime) or request.security(syminfo.tickerid, 'D', f_isSameDay(time, time_close),
lookahead = barmerge.lookahead_on))
f_tradingDayStart(_t) =>
_y = year(_t)
_m = month(_t)
_d = dayofmonth(_t)
timestamp(_y, _m, _d, 0, 0)
f_numDaysBetween(_time1, _time2) =>
_y1 = year(_time1)
_m1 = month(_time1)
_d1 = dayofmonth(_time1)
_y2 = year(_time2)
_m2 = month(_time2)
_d2 = dayofmonth(_time2)
_diff = math.abs(timestamp('GMT', _y1, _m1, _d1, 0, 0) - timestamp('GMT', _y2, _m2, _d2, 0, 0))
_diff / i_millisDay
f_tradingDay = f_isOvernight() ? f_tradingDayStart(dwmBarTime + i_millisDay) : f_tradingDayStart(dwmBarTime)
f_isNewPeriod() =>
_isNew = false
if f_tradingDay != nz(f_tradingDay[1])
if i_period == 'Session'
_isNew := na(f_tradingDay[1]) or f_tradingDay > f_tradingDay[1]
_isNew
if i_period == 'Week'
_isNew := f_makeMondayZero(dayofweek(periodStart)) + f_numDaysBetween(periodStart, f_tradingDay) >=
i_daysInWeek
_isNew
_isNew
//#endregion }
//#region ——————————— <calculations> {
//<set initial values>
sumSrc = float(na)
sumVol = float(na)
sumSrc := nz(sumSrc[1], 0)
sumVol := nz(sumVol[1], 0)
if f_isNewPeriod()
periodStart := f_tradingDay
sumSrc := 0.0
sumVol := 0.0
sumVol
if not na(i_src) and not na(volume)
sumSrc += i_src * volume
sumVol += volume
sumVol
vwapLine = sumSrc / sumVol
vwapDir = sumVol > i_src and i_src > vwapLine ? 1 :
sumVol > i_src and i_src < vwapLine ? -1 : 0
// <color>
c_vwap = vwapDir == 0 ? color.orange :
vwapDir == 1 ? color.green :
vwapDir == -1 ? color.red : na
// --------- Plot
plot(
vwapLine,
title = 'VWAP',
linewidth = 2,
color = c_vwap)
color TRANSP_CSS = #ffffff00
//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(#089981, ''
, 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(#f23645, ''
, 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('Tiny', '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(#089981, ''
, 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(#f23645, ''
, inline = 'bear'
, group = 'Real Time Swing Structure')
swing_structure_size = input.string('Small', '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(#3179f5, 80), 'Internal Bullish OB'
, group = 'Order Blocks')
ibear_ob_css = input.color(color.new(#f77c80, 80), 'Internal Bearish OB'
, group = 'Order Blocks')
bull_ob_css = input.color(color.new(#1848cc, 80), 'Bullish OB'
, group = 'Order Blocks')
bear_ob_css = input.color(color.new(#b22833, 80), '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')
//----------------------------------------}
//Fair Value Gaps
//----------------------------------------{
show_fvg = input(false, 'Fair Value Gaps'
, group = 'Fair Value Gaps'
, tooltip = SHOW_FVG)
fvg_auto = input(true, "Auto Threshold"
, group = 'Fair Value Gaps'
, tooltip = AUTO_FVG)
fvg_tf = input.timeframe('', "Timeframe"
, group = 'Fair Value Gaps'
, tooltip = FVG_TF)
bull_fvg_css = input.color(color.new(#00ff68, 70), 'Bullish FVG'
, group = 'Fair Value Gaps')
bear_fvg_css = input.color(color.new(#ff0008, 70), 'Bearish FVG'
, group = 'Fair Value Gaps')
fvg_extend = input.int(1, "Extend FVG"
, minval = 0
, group = 'Fair Value Gaps'
, tooltip = EXTEND_FVG)
//----------------------------------------}
//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 Gaps
//-----------------------------------------------------------------------------{
var bullish_fvg_max = array.new_box(0)
var bullish_fvg_min = array.new_box(0)
var bearish_fvg_max = array.new_box(0)
var bearish_fvg_min = array.new_box(0)
float bullish_fvg_avg = na
float bearish_fvg_avg = na
bullish_fvg_cnd = false
bearish_fvg_cnd = false
[src_c1, src_o1, src_h, src_l, src_h2, src_l2] =
request.security(syminfo.tickerid, fvg_tf, get_ohlc())
if show_fvg
delta_per = (src_c1 - src_o1) / src_o1 * 100
change_tf = timeframe.change(fvg_tf)
threshold = fvg_auto ? ta.cum(math.abs(change_tf ? delta_per : 0)) / n * 2
:0
//FVG conditions
bullish_fvg_cnd := src_l > src_h2
and src_c1 > src_h2
and delta_per > threshold
and change_tf
bearish_fvg_cnd := src_h < src_l2
and src_c1 < src_l2
and -delta_per > threshold
and change_tf
//FVG Areas
if bullish_fvg_cnd
array.unshift(bullish_fvg_max, box.new(n-1, src_l, n + fvg_extend, math.avg(src_l, src_h2)
, border_color = bull_fvg_css
, bgcolor = bull_fvg_css))
array.unshift(bullish_fvg_min, box.new(n-1, math.avg(src_l, src_h2), n + fvg_extend, src_h2
, border_color = bull_fvg_css
, bgcolor = bull_fvg_css))
if bearish_fvg_cnd
array.unshift(bearish_fvg_max, box.new(n-1, src_h, n + fvg_extend, math.avg(src_h, src_l2)
, border_color = bear_fvg_css
, bgcolor = bear_fvg_css))
array.unshift(bearish_fvg_min, box.new(n-1, math.avg(src_h, src_l2), n + fvg_extend, src_l2
, border_color = bear_fvg_css
, bgcolor = bear_fvg_css))
for bx in bullish_fvg_min
if low < box.get_bottom(bx)
box.delete(bx)
box.delete(array.get(bullish_fvg_max, array.indexof(bullish_fvg_min, bx)))
for bx in bearish_fvg_max
if high > box.get_top(bx)
box.delete(bx)
box.delete(array.get(bearish_fvg_min, array.indexof(bearish_fvg_max, bx)))
//-----------------------------------------------------------------------------}
//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')
//-----------------------------------------------------------------------------}
var int TYPE_UP = 1
var int TYPE_DOWN = -1
var string LINE_WIDTH1_STR = "Width 1"
var string LINE_WIDTH2_STR = "Width 2"
_get_width(string str_input) =>
switch str_input // {string:int}
LINE_WIDTH1_STR => 1
LINE_WIDTH2_STR => 2
// ----------------------------------------------------------------------------
// Settings:
// {
var string GROUP_FRACT = "Fractals"
var int n1 = input.int(10, title="Fractal Period", minval=2, group=GROUP_FRACT)
var color col_hl = input.color(color.blue, title="Plot:", inline="plot_low", group=GROUP_FRACT)
var bool show_hl = input.bool(true, title="HL", inline="plot_low", group=GROUP_FRACT)
var color col_ll = input.color(color.gray, title=", Plot:", inline="plot_low", group=GROUP_FRACT)
var bool show_ll = input.bool(false, title="LL", inline="plot_low", group=GROUP_FRACT)
var color col_lh = input.color(color.red, title="Plot:", inline="plot_high", group=GROUP_FRACT)
var bool show_lh = input.bool(true, title="LH", inline="plot_high", group=GROUP_FRACT)
var color col_hh = input.color(color.gray, title=", Plot:", inline="plot_high", group=GROUP_FRACT)
var bool show_hh = input.bool(false, title="HH", inline="plot_high", group=GROUP_FRACT)
var string GROUP_ATL = "Auto trendlines"
var string subgroup1 = "recent line"
var color ln_col_recent = input.color(color.new(color.purple, 0), title="Recent Line", group=GROUP_ATL,
inline=subgroup1)
var int lnwidth_recent = _get_width(input.string(LINE_WIDTH1_STR, options=[LINE_WIDTH1_STR,
LINE_WIDTH2_STR], title="", inline=subgroup1, group=GROUP_ATL))
var string subgroup2 = "historical line"
var color ln_col_prev = input.color(color.new(color.gray, 50), title="Historical Line", group=GROUP_ATL,
inline=subgroup2)
var int lnwidth_prev = _get_width(input.string(LINE_WIDTH1_STR, options=[LINE_WIDTH1_STR,
LINE_WIDTH2_STR], title="", inline=subgroup2, group=GROUP_ATL))
var int max_tl = input.int(1, title="Max pair of lines", maxval=250, minval=1, group=GROUP_ATL)*2
var string _str_extend = input.string("Right", options=["Right", "Both ways"], title="Which way to extend lines",
group=GROUP_ATL)
var string str_extend = _str_extend == "Both ways" ? extend.both : extend.right
var bool show_crosses = input.bool(false, title="Show crosses", tooltip="Instances when closing price of a bar has
crossed lower/upper trendlines", group=GROUP_ATL)
// }
// ----------------------------------------------------------------------------
// Fractal UDT and other relevant data structures:
// Handle fractals and trendlines associated with them
// {
type fractal
int up_or_down = na // either TYPE_UP or TYPE_DOWN
int xloc = na
float yloc = na
int xloc_parent = na
float yloc_parent = na
var fractal[] arr_fract = array.new<fractal>() // Can be used for multiple purposes such as:
// (a) connecting trendlines but added condition to skip X no. of fractals in between
// (b) create a zigzag, since knowing foo.parent's x and y
// ... possibilities are endless
var line[] arr_ln_up = array.new_line() // Array of lines, newest elements inserted to front
var line[] arr_ln_dn = array.new_line()
// @function init_fractal() returns instance of fractal that has been init'ed
init_fractal(int fract_type, int xloc, float yloc, int xparent, float yparent)=>
f = fractal.new()
f.up_or_down := fract_type
f.xloc := xloc
f.yloc := yloc
f.xloc_parent := xparent
f.yloc_parent := yparent
ln = line.new(xloc, yloc, xparent, yparent, xloc.bar_index, str_extend, color=ln_col_recent, style=line.style_dashed,
width=lnwidth_recent)
if f.up_or_down == TYPE_UP
array.unshift(arr_ln_up, ln)
else if f.up_or_down == TYPE_DOWN
array.unshift(arr_ln_dn, ln)
array.unshift(arr_fract, f)
f // <- return
// @function drop_and_roll(new fractal) returns void
// Clean up: Drop oldest trendlines, change colors for previous trendline
drop_and_roll(fractal f) =>
arr_ln = f.up_or_down == TYPE_UP ? arr_ln_up : f.up_or_down == TYPE_DOWN ? arr_ln_dn : na
if array.size(arr_ln) > 1
line.set_color(array.get(arr_ln, 1), ln_col_prev)
line.set_width(array.get(arr_ln, 1), lnwidth_prev)
while array.size(arr_ln) > math.floor(max_tl/2)
line.delete(array.pop(arr_ln))
// @function draw_trendline() returns void
draw_trendline(fract_type, x2, y2, x1, y1) =>
f = init_fractal(fract_type, x2, y2, x1, y1)
drop_and_roll(f)
// } end of handle for fractals
// ----------------------------------------------------------------------------
// Fractals, implemented using ta.pivot high && low
// ----------------------------------------------------------------------------
// A Fractal is always a Pivot H/L (but a Pivot H/L is not always a Fractal):
float ph = ta.pivothigh(n1, n1)[1], bool upfract = not na(ph)
float pl = ta.pivotlow(n1, n1)[1], bool downfract = not na(pl)
alertcondition(not na(ph) or not na(pl), title="New trendline formed", message="New trendline formed")
// Pointers -> Recent fractals
// {
var float recent_dn1 = na, var int i_recent_dn1 = na
var float recent_up1 = na, var int i_recent_up1 = na
var float recent_dn2 = na, var int i_recent_dn2 = na
var float recent_up2 = na, var int i_recent_up2 = na
if downfract
recent_dn2:=recent_dn1, i_recent_dn2 := i_recent_dn1
recent_dn1:=low[n1+1], i_recent_dn1 := bar_index-n1-1
draw_trendline(TYPE_DOWN, i_recent_dn2, recent_dn2, i_recent_dn1, recent_dn1)
if upfract
recent_up2:=recent_up1, i_recent_up2 := i_recent_up1
recent_up1:=high[n1+1], i_recent_up1 := bar_index-n1-1
draw_trendline(TYPE_UP, i_recent_up2, recent_up2, i_recent_up1, recent_up1)
// }
// Plotting fractals
bool hh = upfract and recent_up1 > recent_up2 ? high[n1+1] : na
bool lh = upfract and recent_up1 < recent_up2 ? high[n1+1] : na
bool hl = downfract and recent_dn1 > recent_dn2 ? low[n1+1] : na
bool ll = downfract and recent_dn1 < recent_dn2 ? low[n1+1] : na
//plotshape(show_hh and hh, style=shape.circle, size=size.tiny, offset=-n1-1, title="HH", text="HH",
location=location.abovebar, textcolor=col_hh, color=na, editable=false)
//plotshape(show_lh and lh, style=shape.circle, size=size.tiny, offset=-n1-1, title="LH", text="LH",
location=location.abovebar, textcolor=col_lh, color=na, editable=false)
//plotshape(show_ll and ll, style=shape.circle, size=size.tiny, offset=-n1-1, title="LL", text="LL",
location=location.belowbar, textcolor=col_ll, color=na, editable=false)
//plotshape(show_hl and hl, style=shape.circle, size=size.tiny, offset=-n1-1, title="HL", text="HL",
location=location.belowbar, textcolor=col_hl, color=na, editable=false)
// ----------------------------------------------------------------------------
// Finding crosses between closing price & pair of most recent trendlines
// ----------------------------------------------------------------------------
// @function get_slope()
get_slope(xA, yA, xB, yB) =>
(yB - yA) / (xB - xA)
// Solving for price at current x (bar_index), given two pairs of fractals with x values < bar_index.
float m_dn = get_slope(i_recent_dn1, recent_dn1, i_recent_dn2, recent_dn2)
float y_dn = (m_dn * bar_index) + recent_dn1 - (m_dn * i_recent_dn1)
float m_up = get_slope(i_recent_up1, recent_up1, i_recent_up2, recent_up2)
float y_up = (m_up * bar_index) + recent_up1 - (m_up * i_recent_up1)
// Plotting crosses
bool cross_upper = ta.cross(close, y_up)
bool cross_lower = ta.cross(close, y_dn)
//plotshape(show_crosses and cross_upper, title = "Crossed upper trendline", style = shape.xcross, location =
location.belowbar, color = color.new(color = color.blue, transp = 50), size = size.small)
//plotshape(show_crosses and cross_lower, title = "Crossed lower trendline", style = shape.xcross, location =
location.abovebar, color = color.new(color = color.red, transp = 50), size = size.small)
alertcondition(cross_upper or cross_lower, title="Upper/lower trendline crossed", message="Upper/lower trendline
crossed")
Periods = input(title="ATR Period", defval=10)
src = input(hl2, title="Source")
Multiplier = input.float(title="ATR Multiplier", step=0.1, defval=3.0)
changeATR= input.bool(title="Change ATR Calculation Method ?", defval=true)
showsignals = input.bool(title="Show Buy/Sell Signals ?", defval=true)
highlighting = input.bool(title="Highlighter On/Off ?", defval=true)
atr2 = ta.sma(ta.tr, Periods)
atr3= changeATR ? ta.atr(Periods) : atr2
up=src-(Multiplier*atr3)
up1 = nz(up[1],up)
up := close[1] > up1 ? math.max(up,up1) : up
dn=src+(Multiplier*atr3)
dn1 = nz(dn[1], dn)
dn := close[1] < dn1 ? math.min(dn, dn1) : dn
trenda = 1
trenda := nz(trenda[1], trenda)
trenda := trenda == -1 and close > dn1 ? 1 : trenda == 1 and close < up1 ? -1 : trenda
upPlot = plot(trenda == 1 ? up : na, title="Up Trend", style=plot.style_linebr, linewidth=2, color=color.rgb(62, 206,
67))
buySignal = trenda == 1 and trenda[1] == -1
plotshape(buySignal ? up : na, title="UpTrend Begins", location=location.absolute, style=shape.circle, size=size.tiny,
color=color.green, transp=0)
plotshape(buySignal and showsignals ? up : na, title="Buy", text="Buy", location=location.absolute,
style=shape.labelup, size=size.tiny, color=color.green, textcolor=color.white, transp=0)
dnPlot = plot(trenda == 1 ? na : dn, title="Down Trend", style=plot.style_linebr, linewidth=2, color=color.red)
sellSignal = trenda == -1 and trenda[1] == 1
plotshape(sellSignal ? dn : na, title="DownTrend Begins", location=location.absolute, style=shape.circle,
size=size.tiny, color=color.red, transp=0)
plotshape(sellSignal and showsignals ? dn : na, title="Sell", text="Sell", location=location.absolute,
style=shape.labeldown, size=size.tiny, color=color.red, textcolor=color.white, transp=0)
mPlot = plot(ohlc4, title="", style=plot.style_circles, linewidth=0)
longFillColor = highlighting ? (trenda == 1 ? color.green : color.white) : color.white
shortFillColor = highlighting ? (trenda == -1 ? color.red : color.white) : color.white
// Configuration
i_ma_type = input.string('EMA', title = 'Moving Average Type', options = ['SMA', 'EMA', 'WMA', 'RMA', 'McGinley'],
group = 'RSI Trailing Stop [UAlgo]')
f_rsi_lower = input.float(40, title = 'RSI Lower Bound', inline = 'rsi_bounds', group = 'RSI Trailing Stop [UAlgo]', minval
= 0, maxval = 100)
f_rsi_upper = input.float(60, title = 'RSI Upper Bound', inline = 'rsi_bounds', group = 'RSI Trailing Stop [UAlgo]', minval
= 0, maxval = 100)
b_show_midline = input.bool(false, title = 'Show Midline', inline = 'display', group = 'RSI Trailing Stop [UAlgo]')
b_color_candles = input.bool(false, title = 'Color Candles', inline = 'display', group = 'RSI Trailing Stop [UAlgo]')
// Moving Average Functions
f_sma(_src, _length) =>
ta.sma(_src, _length)
f_ema(_src, _length) =>
ta.ema(_src, _length)
f_wma(_src, _length) =>
ta.wma(_src, _length)
f_rma(_src, _length) =>
ta.rma(_src, _length)
f_mcginley(_src, _length) =>
var float md = na
md := na(md[1]) ? _src : md[1] + (_src - md[1]) / (0.6 * _length * math.pow(_src / md[1], 4))
md
// Function to select Moving Average
f_get_ma(_type, _src, _length) =>
switch _type
'SMA' => f_sma(_src, _length)
'EMA' => f_ema(_src, _length)
'WMA' => f_wma(_src, _length)
'RMA' => f_rma(_src, _length)
'McGinley' => f_mcginley(_src, _length)
// Calculate indicator values
f_calculate_bounds(float _ma, float _range, float _upper, float _lower) =>
float upper_bound = _ma + (_upper - 50) / 10 * _range
float lower_bound = _ma - (50 - _lower) / 10 * _range
[upper_bound, lower_bound]
f_volatility = ta.atr(27)
f_ma_base = f_get_ma(i_ma_type, ohlc4, 27)
[f_upper_bound, f_lower_bound] = f_calculate_bounds(f_ma_base, f_volatility, f_rsi_upper, f_rsi_lower)
// Determine market state
var bool is_bullish = false
var bool is_bearish = false
bool bull_signal = false
bool bear_signal = false
if ta.crossover(ohlc4, f_upper_bound)
bull_signal := not is_bullish
is_bullish := true
is_bearish := false
is_bearish
if ta.crossunder(close, f_lower_bound)
bear_signal := not is_bearish
is_bullish := false
is_bearish := true
is_bearish
// Plotting
plot(f_lower_bound, color = is_bullish ? #1ae5fb : na, linewidth = 2)
plot(f_upper_bound, color = is_bearish ? #f236e2 : na, linewidth = 2)
plot(b_show_midline ? f_ma_base : na, color = color.new(color.gray, 70), linewidth = 2)
plotshape(bull_signal ? f_lower_bound : na, style = shape.triangleup, location = location.absolute, color =
color.rgb(63, 240, 43), size = size.small)
plotshape(bear_signal ? f_upper_bound : na, style = shape.triangledown, location = location.absolute, color =
color.rgb(246, 31, 236), size = size.small)
f_candle_color = b_color_candles ? is_bullish ? #089981 : #f23645 : na
barcolor(f_candle_color)
// Alerts
f_generate_alert(bool _condition, string _message) =>
if _condition
alert(_message + syminfo.tickerid + ' on ' + timeframe.period + ' chart', freq = alert.freq_once_per_bar_close)
f_generate_alert(bull_signal, 'Bullish Signal: ')
f_generate_alert(bear_signal, 'Bearish Signal: ')
alertcondition(bull_signal, title = 'Bullish Signal', message = 'Bullish signal detected!')
alertcondition(bear_signal, title = 'Bearish Signal', message = 'Bearish signal detected!')
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © ajithcpas
//@version=5
AUTO = "Auto"
DAILY = "Daily"
WEEKLY = "Weekly"
MONTHLY = "Monthly"
QUARTERLY = "Quarterly"
HALF_YEARLY = "Half-yearly"
YEARLY = "Yearly"
TRADITIONAL = "Traditional"
FIBONACCI = "Fibonacci"
CLASSIC = "Classic"
CAMARILLA = "Camarilla"
// Input fields
kind = input.string(title="Type", defval="Traditional", options=[TRADITIONAL, FIBONACCI, CLASSIC, CAMARILLA])
cpr_time_frame = input.string(title="CPR Timeframe", defval=AUTO, options=[AUTO, DAILY, WEEKLY, MONTHLY,
QUARTERLY, HALF_YEARLY, YEARLY])
look_back = input.int(title="Number of CPR Back", defval=2, minval=1, maxval=5000)
is_daily_based = input.bool(title="Use Daily-based Values", defval=true, tooltip="When this option is unchecked, CPR
will use intraday data while calculating on intraday charts. If Extended Hours are displayed on the chart, they will be
taken into account during the CPR level calculation. If intraday OHLC values are different from daily-based values
(normal for stocks), the CPR levels will also differ.")
show_labels = input.bool(title="Show Labels", defval=true, group="labels")
show_prices = input.bool(title="Show Prices", defval=true, group="labels")
position_labels = input.string("Right", "Labels Position", options=["Left", "Right"], group="labels")
line_width = input.int(title="Line Width", defval=1, minval=1, maxval=100, group="labels")
var arr_time = array.new_int()
var p = array.new_float()
var tp = array.new_float()
var bp = array.new_float()
cpr_show = input.bool(true, "", inline="CPR", group="CPR levels")
cpr_color = input.color(color.purple, "CPR", inline="CPR", group="CPR levels")
var SR_COLOR = #FB8C00
sr_show = input.bool(false, "Show SR Levels", inline="Show SR Levels", group="CPR levels")
hist_sr_show = input.bool(false, "Show Historical SR Levels", inline="Show SR Levels", group="CPR levels")
var r0_5 = array.new_float()
var s0_5 = array.new_float()
s0_5_show = input.bool(true, "", inline="S0.5/R0.5", group="CPR levels")
s0_5_color = input.color(SR_COLOR, "S0.5", inline="S0.5/R0.5" , group="CPR levels")
r0_5_show = input.bool(true, "", inline="S0.5/R0.5", group="CPR levels")
r0_5_color = input.color(SR_COLOR, "R0.5", inline="S0.5/R0.5", group="CPR levels")
var r1 = array.new_float()
var s1 = array.new_float()
s1_show = input.bool(true, "", inline="S1/R1", group="CPR levels")
s1_color = input.color(SR_COLOR, "S1", inline="S1/R1" , group="CPR levels")
r1_show = input.bool(true, "", inline="S1/R1", group="CPR levels")
r1_color = input.color(SR_COLOR, "R1", inline="S1/R1", group="CPR levels")
var r1_5 = array.new_float()
var s1_5 = array.new_float()
s1_5_show = input.bool(true, "", inline="S1.5/R1.5", group="CPR levels")
s1_5_color = input.color(SR_COLOR, "S1.5", inline="S1.5/R1.5" , group="CPR levels")
r1_5_show = input.bool(true, "", inline="S1.5/R1.5", group="CPR levels")
r1_5_color = input.color(SR_COLOR, "R1.5", inline="S1.5/R1.5", group="CPR levels")
var r2 = array.new_float()
var s2 = array.new_float()
s2_show = input.bool(true, "", inline="S2/R2", group="CPR levels")
s2_color = input.color(SR_COLOR, "S2", inline="S2/R2", group="CPR levels")
r2_show = input.bool(true, "", inline="S2/R2", group="CPR levels")
r2_color = input.color(SR_COLOR, "R2", inline="S2/R2", group="CPR levels")
var r2_5 = array.new_float()
var s2_5 = array.new_float()
s2_5_show = input.bool(true, "", inline="S2.5/R2.5", group="CPR levels")
s2_5_color = input.color(SR_COLOR, "S2.5", inline="S2.5/R2.5" , group="CPR levels")
r2_5_show = input.bool(true, "", inline="S2.5/R2.5", group="CPR levels")
r2_5_color = input.color(SR_COLOR, "R2.5", inline="S2.5/R2.5", group="CPR levels")
var r3 = array.new_float()
var s3 = array.new_float()
s3_show = input.bool(true, "", inline="S3/R3", group="CPR levels")
s3_color = input.color(SR_COLOR, "S3", inline="S3/R3", group="CPR levels")
r3_show = input.bool(true, "", inline="S3/R3", group="CPR levels")
r3_color = input.color(SR_COLOR, "R3", inline="S3/R3", group="CPR levels")
var r3_5 = array.new_float()
var s3_5 = array.new_float()
s3_5_show = input.bool(true, "", inline="S3.5/R3.5", group="CPR levels")
s3_5_color = input.color(SR_COLOR, "S3.5", inline="S3.5/R3.5" , group="CPR levels")
r3_5_show = input.bool(true, "", inline="S3.5/R3.5", group="CPR levels")
r3_5_color = input.color(SR_COLOR, "R3.5", inline="S3.5/R3.5", group="CPR levels")
var r4 = array.new_float()
var s4 = array.new_float()
s4_show = input.bool(true, "", inline="S4/R4", group="CPR levels")
s4_color = input.color(SR_COLOR, "S4", inline="S4/R4", group="CPR levels")
r4_show = input.bool(true, "", inline="S4/R4", group="CPR levels")
r4_color = input.color(SR_COLOR, "R4", inline="S4/R4", group="CPR levels")
var r4_5 = array.new_float()
var s4_5 = array.new_float()
s4_5_show = input.bool(true, "", inline="S4.5/R4.5", group="CPR levels")
s4_5_color = input.color(SR_COLOR, "S4.5", inline="S4.5/R4.5" , group="CPR levels")
r4_5_show = input.bool(true, "", inline="S4.5/R4.5", group="CPR levels")
r4_5_color = input.color(SR_COLOR, "R4.5", inline="S4.5/R4.5", group="CPR levels")
var r5 = array.new_float()
var s5 = array.new_float()
s5_show = input.bool(true, "", inline="S5/R5", group="CPR levels")
s5_color = input.color(SR_COLOR, "S5", inline="S5/R5", group="CPR levels")
r5_show = input.bool(true, "", inline="S5/R5", group="CPR levels")
r5_color = input.color(SR_COLOR, "R5", inline="S5/R5", group="CPR levels")
dev_cpr_show = input.bool(true, "", inline="Dev CPR", group="Developing CPR levels")
dev_cpr_color = input.color(color.teal, "Dev CPR", inline="Dev CPR", group="Developing CPR levels")
var dev_r1 = array.new_float()
var dev_s1 = array.new_float()
dev_s1_show = input.bool(true, "", inline="S1/R1", group="Developing CPR levels")
dev_s1_color = input.color(SR_COLOR, "S1", inline="S1/R1" , group="Developing CPR levels")
dev_r1_show = input.bool(true, "", inline="S1/R1", group="Developing CPR levels")
dev_r1_color = input.color(SR_COLOR, "R1", inline="S1/R1", group="Developing CPR levels")
extend_dev_cpr_line = input.bool(false, "", inline="extend", group="Developing CPR levels")
dev_cpr_line_days = input.int(title="Extend line by days", defval=1, minval=1, maxval=10, inline="extend",
group="Developing CPR levels", tooltip="Enable this when the Dev CPR lines are not visible(i.e. there is a trading
holiday in upcoming session).")
check_holidays = input.bool(true, "Check NSE/BSE holidays", group="Developing CPR levels", tooltip="Enable this
when the Dev CPR lines are not visible(i.e. there is a trading holiday in upcoming session).")
pivotX_open = float(na)
pivotX_open := nz(pivotX_open[1], open)
pivotX_high = float(na)
pivotX_high := nz(pivotX_high[1], high)
pivotX_low = float(na)
pivotX_low := nz(pivotX_low[1], low)
pivotX_prev_open = float(na)
pivotX_prev_open := nz(pivotX_prev_open[1])
pivotX_prev_high = float(na)
pivotX_prev_high := nz(pivotX_prev_high[1])
pivotX_prev_low = float(na)
pivotX_prev_low := nz(pivotX_prev_low[1])
pivotX_prev_close = float(na)
pivotX_prev_close := nz(pivotX_prev_close[1])
get_pivot_resolution() =>
resolution = "M"
if cpr_time_frame == AUTO
if timeframe.isintraday
resolution := timeframe.multiplier <= 15 ? "D" : "W"
else if timeframe.isdaily
resolution := "M"
else if timeframe.isweekly
resolution := "6M"
else
resolution := "12M"
else if cpr_time_frame == DAILY
resolution := "D"
else if cpr_time_frame == WEEKLY
resolution := "W"
else if cpr_time_frame == MONTHLY
resolution := "M"
else if cpr_time_frame == QUARTERLY
resolution := "3M"
else if cpr_time_frame == HALF_YEARLY
resolution := "6M"
else if cpr_time_frame == YEARLY
resolution := "12M"
resolution
var lines = array.new_line()
var labels = array.new_label()
draw_line(i, pivot, col, line_style=line.style_solid) =>
line aLine = na
if array.size(arr_time) > 1
aLine := line.new(array.get(arr_time, i), array.get(pivot, i), array.get(arr_time, i + 1), array.get(pivot, i), color=col,
xloc=xloc.bar_time, width=line_width, style=line_style)
array.push(lines, aLine)
aLine
draw_label(i, y, txt, txt_color) =>
if show_labels or show_prices
display_text = ""
if show_labels and show_prices and txt != ''
display_text := str.format(" {0} - {1}", txt, math.round_to_mintick(y))
else if show_labels and txt != ''
display_text := " " + txt
else
display_text := str.format(" {0}", math.round_to_mintick(y))
x = position_labels == "Left" ? array.get(arr_time, i) : array.get(arr_time, i + 1)
array.push(labels, label.new(x=x, y=y, text=display_text, textcolor=txt_color, style=label.style_none,
color=#00000000, xloc=xloc.bar_time))
traditional() =>
pivotX_Median = (pivotX_prev_high + pivotX_prev_low + pivotX_prev_close) / 3
_r1 = pivotX_Median * 2 - pivotX_prev_low
_s1 = pivotX_Median * 2 - pivotX_prev_high
_r2 = pivotX_Median + 1 * (pivotX_prev_high - pivotX_prev_low)
_s2 = pivotX_Median - 1 * (pivotX_prev_high - pivotX_prev_low)
_r3 = pivotX_Median * 2 + (pivotX_prev_high - 2 * pivotX_prev_low)
_s3 = pivotX_Median * 2 - (2 * pivotX_prev_high - pivotX_prev_low)
_r4 = pivotX_Median * 3 + (pivotX_prev_high - 3 * pivotX_prev_low)
_s4 = pivotX_Median * 3 - (3 * pivotX_prev_high - pivotX_prev_low)
_r5 = pivotX_Median * 4 + (pivotX_prev_high - 4 * pivotX_prev_low)
_s5 = pivotX_Median * 4 - (4 * pivotX_prev_high - pivotX_prev_low)
array.push(r0_5, (pivotX_Median + _r1) / 2)
array.push(s0_5, (pivotX_Median + _s1) / 2)
array.push(r1, _r1)
array.push(s1, _s1)
array.push(r1_5, (_r1 + _r2) / 2)
array.push(s1_5, (_s1 + _s2) / 2)
array.push(r2, _r2)
array.push(s2, _s2)
array.push(r2_5, (_r2 + _r3) / 2)
array.push(s2_5, (_s2 + _s3) / 2)
array.push(r3, _r3)
array.push(s3, _s3)
array.push(r3_5, (_r3 + _r4) / 2)
array.push(s3_5, (_s3 + _s4) / 2)
array.push(r4, _r4)
array.push(s4, _s4)
array.push(r4_5, (_r4 + _r5) / 2)
array.push(s4_5, (_s4 + _s5) / 2)
array.push(r5, _r5)
array.push(s5, _s5)
fibonacci() =>
pivotX_Median = (pivotX_prev_high + pivotX_prev_low + pivotX_prev_close) / 3
pivot_range = pivotX_prev_high - pivotX_prev_low
array.push(r1, pivotX_Median + 0.382 * pivot_range)
array.push(s1, pivotX_Median - 0.382 * pivot_range)
array.push(r2, pivotX_Median + 0.618 * pivot_range)
array.push(s2, pivotX_Median - 0.618 * pivot_range)
array.push(r3, pivotX_Median + 1 * pivot_range)
array.push(s3, pivotX_Median - 1 * pivot_range)
classic() =>
pivotX_Median = (pivotX_prev_high + pivotX_prev_low + pivotX_prev_close) / 3
pivot_range = pivotX_prev_high - pivotX_prev_low
array.push(r1, pivotX_Median * 2 - pivotX_prev_low)
array.push(s1, pivotX_Median * 2 - pivotX_prev_high)
array.push(r2, pivotX_Median + 1 * pivot_range)
array.push(s2, pivotX_Median - 1 * pivot_range)
array.push(r3, pivotX_Median + 2 * pivot_range)
array.push(s3, pivotX_Median - 2 * pivot_range)
array.push(r4, pivotX_Median + 3 * pivot_range)
array.push(s4, pivotX_Median - 3 * pivot_range)
camarilla() =>
pivotX_Median = (pivotX_prev_high + pivotX_prev_low + pivotX_prev_close) / 3
pivot_range = pivotX_prev_high - pivotX_prev_low
array.push(r1, pivotX_prev_close + pivot_range * 1.1 / 12.0)
array.push(s1, pivotX_prev_close - pivot_range * 1.1 / 12.0)
array.push(r2, pivotX_prev_close + pivot_range * 1.1 / 6.0)
array.push(s2, pivotX_prev_close - pivot_range * 1.1 / 6.0)
array.push(r3, pivotX_prev_close + pivot_range * 1.1 / 4.0)
array.push(s3, pivotX_prev_close - pivot_range * 1.1 / 4.0)
array.push(r4, pivotX_prev_close + pivot_range * 1.1 / 2.0)
array.push(s4, pivotX_prev_close - pivot_range * 1.1 / 2.0)
r5_val = pivotX_prev_high / pivotX_prev_low * pivotX_prev_close
array.push(r5, r5_val)
array.push(s5, 2 * pivotX_prev_close - r5_val)
calc_pivot() =>
pivotX_Median = (pivotX_prev_high + pivotX_prev_low + pivotX_prev_close) / 3
pivotX_Bottom = (pivotX_prev_high + pivotX_prev_low) / 2
pivotX_Top = pivotX_Median * 2 - pivotX_Bottom
if pivotX_Bottom > pivotX_Top
temp = pivotX_Bottom
pivotX_Bottom := pivotX_Top
pivotX_Top := temp
array.push(p, pivotX_Median)
array.push(tp, pivotX_Top)
array.push(bp, pivotX_Bottom)
if kind == TRADITIONAL
traditional()
else if kind == FIBONACCI
fibonacci()
else if kind == CLASSIC
classic()
else if kind == CAMARILLA
camarilla()
resolution = get_pivot_resolution()
calc_high(prev, curr) =>
if na(prev) or na(curr)
nz(prev, nz(curr, na))
else
math.max(prev, curr)
calc_low(prev, curr) =>
if not na(prev) and not na(curr)
math.min(prev, curr)
else
nz(prev, nz(curr, na))
[sec_open, sec_high, sec_low, prev_sec_open, prev_sec_high, prev_sec_low, prev_sec_close, prev_sec_time] =
request.security(syminfo.tickerid, resolution, [open, high, low, open[1], high[1], low[1], close[1], time[1]], lookahead
= barmerge.lookahead_on)
sec_open_gaps_on = request.security(syminfo.tickerid, resolution, open, gaps = barmerge.gaps_on, lookahead =
barmerge.lookahead_on)
var is_change = false
var uses_current_bar = false
var change_time = int(na)
is_time_change = ta.change(time(resolution)) != 0
if is_time_change
change_time := time
var start_time = time
without_time_change = barstate.islast and array.size(arr_time) == 0
is_can_calc_pivot = (not uses_current_bar and is_time_change) or (uses_current_bar and not
na(sec_open_gaps_on)) or without_time_change
enough_bars_for_calculate = prev_sec_time >= start_time or is_daily_based
if is_can_calc_pivot and enough_bars_for_calculate
if array.size(arr_time) == 0 and is_daily_based
pivotX_prev_open := prev_sec_open[1]
pivotX_prev_high := prev_sec_high[1]
pivotX_prev_low := prev_sec_low[1]
pivotX_prev_close := prev_sec_close[1]
pivotX_open := sec_open[1]
pivotX_high := sec_high[1]
pivotX_low := sec_low[1]
array.push(arr_time, start_time)
calc_pivot()
if is_daily_based
pivotX_prev_open := prev_sec_open
pivotX_prev_high := prev_sec_high
pivotX_prev_low := prev_sec_low
pivotX_prev_close := prev_sec_close
pivotX_open := sec_open
pivotX_high := sec_high
pivotX_low := sec_low
else
pivotX_prev_high := pivotX_high
pivotX_prev_low := pivotX_low
pivotX_prev_open := pivotX_open
pivotX_prev_close := close[1]
pivotX_open := open
pivotX_high := high
pivotX_low := low
if barstate.islast and not is_change and array.size(arr_time) > 0 and not without_time_change
array.set(arr_time, array.size(arr_time) - 1, change_time)
else if without_time_change
array.push(arr_time, start_time)
else
array.push(arr_time, nz(change_time, time))
calc_pivot()
if array.size(arr_time) > look_back
if array.size(arr_time) > 0
array.shift(arr_time)
if array.size(p) > 0 and cpr_show
array.shift(p)
if array.size(tp) > 0 and cpr_show
array.shift(tp)
if array.size(bp) > 0 and cpr_show
array.shift(bp)
if sr_show or hist_sr_show
if array.size(r0_5) > 0 and r0_5_show
array.shift(r0_5)
if array.size(s0_5) > 0 and s0_5_show
array.shift(s0_5)
if array.size(r1) > 0 and r1_show
array.shift(r1)
if array.size(s1) > 0 and s1_show
array.shift(s1)
if array.size(r1_5) > 0 and r1_5_show
array.shift(r1_5)
if array.size(s1_5) > 0 and s1_5_show
array.shift(s1_5)
if array.size(r2) > 0 and r2_show
array.shift(r2)
if array.size(s2) > 0 and s2_show
array.shift(s2)
if array.size(r2_5) > 0 and r2_5_show
array.shift(r2_5)
if array.size(s2_5) > 0 and s2_5_show
array.shift(s2_5)
if array.size(r3) > 0 and r3_show
array.shift(r3)
if array.size(s3) > 0 and s3_show
array.shift(s3)
if array.size(r3_5) > 0 and r3_5_show
array.shift(r3_5)
if array.size(s3_5) > 0 and s3_5_show
array.shift(s3_5)
if array.size(r4) > 0 and r4_show
array.shift(r4)
if array.size(s4) > 0 and s4_show
array.shift(s4)
if array.size(r4_5) > 0 and r4_5_show
array.shift(r4_5)
if array.size(s4_5) > 0 and s4_5_show
array.shift(s4_5)
if array.size(r5) > 0 and r5_show
array.shift(r5)
if array.size(s5) > 0 and s5_show
array.shift(s5)
is_change := true
else if not is_daily_based
pivotX_high := math.max(pivotX_high, high)
pivotX_low := math.min(pivotX_low, low)
if barstate.islast and not is_daily_based and array.size(arr_time) == 0
runtime.error("Not enough intraday data to calculate CPR. Lower the CPR Timeframe or turn on the 'Use Daily-
based Values' option in the indicator settings.")
if barstate.islast and array.size(arr_time) > 0 and is_change
is_change := false
array.push(arr_time, time_close(resolution))
for i = 0 to array.size(lines) - 1
if array.size(lines) > 0
line.delete(array.shift(lines))
if array.size(labels) > 0
label.delete(array.shift(labels))
for i = 0 to array.size(arr_time) - 2
if array.size(p) > 0 and cpr_show
draw_line(i, p, cpr_color)
if array.size(tp) > 0 and array.size(bp) > 0 and cpr_show
tp_line = draw_line(i, tp, cpr_color)
bp_line = draw_line(i, bp, cpr_color)
linefill.new(tp_line, bp_line, color.new(cpr_color, 70))
j = array.size(arr_time) - 2
for i = 0 to j
if (hist_sr_show and i < j) or (sr_show and i == j)
if array.size(r0_5) > 0 and r0_5_show
draw_line(i, r0_5, r0_5_color, line.style_dashed)
draw_label(i, array.get(r0_5, i), "R0.5", r0_5_color)
if array.size(s0_5) > 0 and s0_5_show
draw_line(i, s0_5, s0_5_color, line.style_dashed)
draw_label(i, array.get(s0_5, i), "S0.5", s0_5_color)
if array.size(r1) > 0 and r1_show
draw_line(i, r1, r1_color)
draw_label(i, array.get(r1, i), "R1", r1_color)
if array.size(s1) > 0 and s1_show
draw_line(i, s1, s1_color)
draw_label(i, array.get(s1, i), "S1", s1_color)
if array.size(r1_5) > 0 and r1_5_show
draw_line(i, r1_5, r1_5_color, line.style_dashed)
draw_label(i, array.get(r1_5, i), "R1.5", r1_5_color)
if array.size(s1_5) > 0 and s1_5_show
draw_line(i, s1_5, s1_5_color, line.style_dashed)
draw_label(i, array.get(s1_5, i), "S1.5", s1_5_color)
if array.size(r2) > 0 and r2_show
draw_line(i, r2, r2_color)
draw_label(i, array.get(r2, i), "R2", r2_color)
if array.size(s2) > 0 and s2_show
draw_line(i, s2, s2_color)
draw_label(i, array.get(s2, i), "S2", s2_color)
if array.size(r2_5) > 0 and r2_5_show
draw_line(i, r2_5, r2_5_color, line.style_dashed)
draw_label(i, array.get(r2_5, i), "R2.5", r2_5_color)
if array.size(s2_5) > 0 and s2_5_show
draw_line(i, s2_5, s2_5_color, line.style_dashed)
draw_label(i, array.get(s2_5, i), "S2.5", s2_5_color)
if array.size(r3) > 0 and r3_show
draw_line(i, r3, r3_color)
draw_label(i, array.get(r3, i), "R3", r3_color)
if array.size(s3) > 0 and s3_show
draw_line(i, s3, s3_color)
draw_label(i, array.get(s3, i), "S3", s3_color)
if array.size(r3_5) > 0 and r3_5_show
draw_line(i, r3_5, r3_5_color, line.style_dashed)
draw_label(i, array.get(r3_5, i), "R3.5", r3_5_color)
if array.size(s3_5) > 0 and s3_5_show
draw_line(i, s3_5, s3_5_color, line.style_dashed)
draw_label(i, array.get(s3_5, i), "S3.5", s3_5_color)
if array.size(r4) > 0 and r4_show
draw_line(i, r4, r4_color)
draw_label(i, array.get(r4, i), "R4", r4_color)
if array.size(s4) > 0 and s4_show
draw_line(i, s4, s4_color)
draw_label(i, array.get(s4, i), "S4", s4_color)
if array.size(r4_5) > 0 and r4_5_show
draw_line(i, r4_5, r4_5_color, line.style_dashed)
draw_label(i, array.get(r4_5, i), "R4.5", r4_5_color)
if array.size(s4_5) > 0 and s4_5_show
draw_line(i, s4_5, s4_5_color, line.style_dashed)
draw_label(i, array.get(s4_5, i), "S4.5", s4_5_color)
if array.size(r5) > 0 and r5_show
draw_line(i, r5, r5_color)
draw_label(i, array.get(r5, i), "R5", r5_color)
if array.size(s5) > 0 and s5_show
draw_line(i, s5, s5_color)
draw_label(i, array.get(s5, i), "S5", s5_color)
i = array.size(arr_time) - 2
if array.size(p) > 0 and cpr_show
draw_label(i, array.get(p, i), "CPR", cpr_color)
if array.size(tp) > 0 and cpr_show
draw_label(i, array.get(tp, i), "", cpr_color)
if array.size(bp) > 0 and cpr_show
draw_label(i, array.get(bp, i), "", cpr_color)
isHoliday(_date) =>
is_holiday = (_date == timestamp(2024, 12, 25, 15, 30) or _date == timestamp(2025, 02, 26, 15, 30) or _date ==
timestamp(2025, 03, 14, 15, 30) or _date == timestamp(2025, 03, 31, 15, 30) or _date == timestamp(2025, 04, 10,
15, 30) or _date == timestamp(2025, 04, 14, 15, 30) or _date == timestamp(2025, 04, 18, 15, 30) or _date ==
timestamp(2025, 05, 01, 15, 30) or _date == timestamp(2025, 08, 15, 15, 30) or _date == timestamp(2025, 08, 27,
15, 30) or _date == timestamp(2025, 10, 02, 15, 30) or _date == timestamp(2025, 10, 21, 15, 30) or _date ==
timestamp(2025, 10, 22, 15, 30) or _date == timestamp(2025, 11, 05, 15, 30) or _date == timestamp(2025, 12, 25,
15, 30))
is_holiday
getDevEndTime() =>
ONE_DAY = 1000 * 60 * 60 * 24
var dev_end_time = 0
if resolution == "D"
dev_end_time := time_close(resolution) + ONE_DAY
else if resolution == "W"
dev_end_time := time_close(resolution) + (ONE_DAY * 7)
else if resolution == "M"
dev_end_time := time_close(resolution) + (ONE_DAY * 30)
else if resolution == "6M"
dev_end_time := time_close(resolution) + (ONE_DAY * 30 * 6)
else
dev_end_time := time_close(resolution) + (ONE_DAY * 30 * 12)
while dayofweek(dev_end_time) == dayofweek.saturday or dayofweek(dev_end_time) == dayofweek.sunday or
(check_holidays and isHoliday(dev_end_time))
dev_end_time := dev_end_time + ONE_DAY
if extend_dev_cpr_line
dev_end_time := dev_end_time + (ONE_DAY * dev_cpr_line_days)
dev_end_time
drawLineAndLabel(_price, _line_color, _text, _text_color) =>
var dev_start_time = 0
dev_start_time := time_close(resolution)
var dev_end_time = 0
dev_end_time := getDevEndTime()
_aLine = line.new(x1=dev_start_time, y1=_price, x2=dev_end_time, y2=_price, xloc=xloc.bar_time,
color=_line_color, width=line_width)
line.delete(_aLine[1])
if show_labels or show_prices
display_text = ""
if show_labels and show_prices and _text != ''
display_text := str.format(" {0} - {1}", _text, math.round_to_mintick(_price))
else if show_labels and _text != ''
display_text := " " + _text
else
display_text := str.format(" {0}", math.round_to_mintick(_price))
_aLabel = label.new(dev_end_time, _price, xloc=xloc.bar_time, text=display_text, textcolor=_text_color,
style=label.style_none)
label.delete(_aLabel[1])
_aLine
[curr_high, curr_low, curr_close] = request.security(syminfo.tickerid, resolution, [high, low, close], lookahead =
barmerge.lookahead_on)
dpp = (curr_high + curr_low + curr_close) / 3.0
if dev_cpr_show
dbc = (curr_high + curr_low) / 2.0
dtc = (dpp * 2) - dbc
dtp_line = drawLineAndLabel(dtc > dbc? dtc : dbc, dev_cpr_color, '', dev_cpr_color)
drawLineAndLabel(dpp, dev_cpr_color, "Dev CPR", dev_cpr_color)
dbp_line = drawLineAndLabel(dbc < dtc? dbc : dtc, dev_cpr_color, '', dev_cpr_color)
linefill.new(dtp_line, dbp_line, color.new(dev_cpr_color, 70))
if dev_r1_show
_dev_r1 = dpp * 2 - curr_low
if kind == FIBONACCI
_dev_r1 := dpp + 0.382 * (curr_high - curr_low)
drawLineAndLabel(_dev_r1, dev_r1_color, "Dev R1", dev_r1_color)
if dev_s1_show
_dev_s1 = dpp * 2 - curr_high
if kind == FIBONACCI
_dev_s1 := dpp - 0.382 * (curr_high - curr_low)
drawLineAndLabel(_dev_s1, dev_s1_color, "Dev S1", dev_s1_color)