ProRealCode - Trading & Coding with ProRealTime™
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © pmk07
//
// Acknowledgements/Reference:
//
// @rumpypumpydumpy – Higher Order Pivots
// https://www.tradingview.com/v/x2LlRvBe/
//
// @MarkMiddleton2020 – Order Blocks
// https://www.tradingview.com/v/GecN34Qq/
//
//@version=5
indicator(title=’Order Blocks’, overlay=true)
bool pv2_sv = input.bool (true, title=’Plot 2nd order pivots’)
bool msb_sv = input.bool (true, title=’Plot MSB lines’)
bool box_sv = input.bool (true, title=’Plot Orderblocks’)
bool m_sv = input.bool (true, title=’Plot Breakerblocks’)
bool range_sv = input.bool (true, title=’Plot Range’)
bool range_eq_sv = input.bool (true, title=’Plot Range 0.5 Line’)
bool range_q_sv = input.bool (true, title=’Plot Range 0.25 and 0.75 Lines’)
bool log_sv = input.bool (true, title=’Use Log Scale’)
bool msb_a_sv = input.bool (true, title=’Alert MSB’)
bool ob_a_sv = input.bool (true, title=’Alert Orderblock test’)
bool bb_a_sv = input.bool (true, title=’Alert Breakerblock test’)
bool r_a_sv = input.bool (true, title=’Alert New Range’)
bool rt_a_sv = input.bool (true, title=’Alert Range test’)
color u_s = input.color (color.rgb(192, 192, 192, 80), title=’Untested Supply Color’)
color t_s = input.color (color.rgb(255, 0, 0, 80), title=’Tested Supply Color’)
color u_d = input.color (color.rgb(192, 192, 192, 80), title=’Untested Demand Color’)
color t_d = input.color (color.rgb(0, 255, 0, 80), title=’Tested Demand Color’)
color u_b = input.color (color.rgb(192, 192, 192, 80), title=’Untested Breaker Color’)
color t_b = input.color (color.new(color.blue, 80), title=’Tested Breaker Color’)
var float[] pvh1_price = array.new_float (30, na) // high
var int[] pvh1_time = array.new_int (30, na)
var float[] pvl1_price = array.new_float (30, na) // low
var int[] pvl1_time = array.new_int (30, na)
var float[] pvh2_price = array.new_float (10, na) // higher high
var int[] pvh2_time = array.new_int (10, na)
var float[] pvl2_price = array.new_float (10, na) // lower low
var int[] pvl2_time = array.new_int (10, na)
var float htcmrll_price = na // high that created most recent ll
var int htcmrll_time = na
var float ltcmrhh_price = na // low that created most recent hh
var int ltcmrhh_time = na
var box[] long_boxes = array.new_box() // orderblocks
var box[] short_boxes = array.new_box()
var box[] m_long_boxes = array.new_box() // breakerblocks
var box[] m_short_boxes = array.new_box()
var line[] bull_bos_lines = array.new_line() // MSB lines
var line[] bear_bos_lines = array.new_line()
var line[] range_h_lines = array.new_line() // Range lines
var line[] range_25_lines = array.new_line()
var line[] range_m_lines = array.new_line()
var line[] range_75_lines = array.new_line()
var line[] range_l_lines = array.new_line()
var label[] la_ph2 = array.new_label() // 2nd order pivots
var label[] la_pl2 = array.new_label()
var float temp_pv_0 = na
var float temp_pv_1 = na
var float temp_pv_2 = na
var int temp_time = na
var float last_range_h = na
var float last_range_l = na
var line range_m = na
var line range_25 = na
var line range_75 = na
var float box_top = na
var float box_bottom = na
var int h_a_time = 0
var int l_a_time = 0
var int mh_a_time = 0
var int ml_a_time = 0
var int rh_a_time = 0
var int rl_a_time = 0
bool pvh = high < high[1] and high[1] > high[2]
bool pvl = low > low[1] and low[1] < low[2]
int pv1_time = bar_index[1]
float pv1_high = high[1]
float pv1_low = low[1]
bool new_ph_2nd = false
bool new_pl_2nd = false
string alert = na
if barstate.isconfirmed
if pvh
array.pop(pvh1_price)
array.pop(pvh1_time)
array.unshift(pvh1_price, pv1_high)
array.unshift(pvh1_time, pv1_time)
if array.size(pvh1_price) > 2
temp_pv_0 := array.get(pvh1_price, 0)
temp_pv_1 := array.get(pvh1_price, 1)
temp_pv_2 := array.get(pvh1_price, 2)
if temp_pv_0 < temp_pv_1 and temp_pv_1 > temp_pv_2
array.pop(pvh2_price)
array.pop(pvh2_time)
array.unshift(pvh2_price, temp_pv_1)
array.unshift(pvh2_time, array.get(pvh1_time, 1))
new_ph_2nd := true
if temp_pv_1 > array.get(pvh2_price, 1)
for i = 0 to array.size(pvl2_time) – 1 by 1
temp_ltcmrhh_time = array.get(pvl2_time, i)
if temp_ltcmrhh_time < array.get(pvh2_time, 0)
ltcmrhh_price := array.get(pvl2_price, i)
ltcmrhh_time := temp_ltcmrhh_time
break
if temp_pv_0 < ltcmrhh_price
if msb_sv
array.push(bear_bos_lines, line.new(x1=ltcmrhh_time, y1=ltcmrhh_price, x2=bar_index, y2=ltcmrhh_price, color=color.green, width=2))
box_top := array.get(pvh2_price, 0)
box_bottom := math.max(low[bar_index - array.get(pvh2_time, 0)], low[bar_index - array.get(pvh2_time, 0) + 1])
array.push(short_boxes, box.new(left=array.get(pvh2_time, 0), top=box_top, right=bar_index, bottom=box_bottom, bgcolor= box_sv ? u_s : na , border_color=na, extend=extend.right))
if msb_a_sv
alert := alert + 'Bearish MSB @ ' + str.tostring(ltcmrhh_price) + '\n' + 'New Supply Zone : '+ str.tostring(box_top) + ' - ' + str.tostring(box_bottom) + '\n'
ltcmrhh_price := na
if pvl
array.pop(pvl1_price)
array.pop(pvl1_time)
array.unshift(pvl1_price, pv1_low)
array.unshift(pvl1_time, pv1_time)
if array.size(pvl1_price) > 2
temp_pv_0 := array.get(pvl1_price, 0)
temp_pv_1 := array.get(pvl1_price, 1)
temp_pv_2 := array.get(pvl1_price, 2)
if temp_pv_0 > temp_pv_1 and temp_pv_1 < temp_pv_2
array.pop(pvl2_price)
array.pop(pvl2_time)
array.unshift(pvl2_price, temp_pv_1)
array.unshift(pvl2_time, array.get(pvl1_time, 1))
new_pl_2nd := true
if temp_pv_1 < array.get(pvl2_price, 1)
for i = 0 to array.size(pvh2_time) - 1 by 1
temp_htcmrll_time = array.get(pvh2_time, i)
if temp_htcmrll_time < array.get(pvl2_time, 0)
htcmrll_price := array.get(pvh2_price, i)
htcmrll_time := temp_htcmrll_time
break
if temp_pv_0 > htcmrll_price
if msb_sv
array.push(bull_bos_lines, line.new(x1=htcmrll_time, y1=htcmrll_price, x2=bar_index, y2=htcmrll_price, color=color.red, width=2))
box_top := math.min(high[bar_index – array.get(pvl2_time, 0)], high[bar_index – array.get(pvl2_time, 0) + 1])
box_bottom := array.get(pvl2_price, 0)
array.push(long_boxes, box.new(left=array.get(pvl2_time, 0), top=box_top, right=bar_index, bottom=box_bottom, bgcolor= box_sv ? u_d : na, border_color=na, extend=extend.right))
if msb_a_sv
alert := alert + ‘Bullish MSB @ ‘ + str.tostring(htcmrll_price) + ‘\n’ + ‘New Demand Zone : ‘+ str.tostring(box_bottom) + ‘ – ‘ + str.tostring(box_top) + ‘\n’
htcmrll_price := na
if array.size(short_boxes) > 0
for i = array.size(short_boxes) – 1 to 0 by 1
tbox = array.get(short_boxes, i)
top = box.get_top(tbox)
bottom = box.get_bottom(tbox)
ago = box.get_left(tbox)
if array.get(pvh1_price, 0) > bottom
if box_sv
box.set_bgcolor(tbox, t_s)
if ob_a_sv and close < bottom
if array.get(pvh1_time, 0) != h_a_time
h_a_time := array.get(pvh1_time, 0)
alert := alert + 'Supply Zone Test @ ' + str.tostring(array.get(pvh1_price, 0)) + ' (age = ' + str.tostring(bar_index-ago) + ' bars) \n'
if array.get(pvl1_price, 0) > top
if m_sv
box.set_bgcolor(tbox, u_b)
array.push(m_long_boxes, tbox)
else
box.delete(tbox)
array.remove(short_boxes, i)
if msb_sv
line.delete(array.get(bear_bos_lines, i))
array.remove(bear_bos_lines, i)
if array.size(long_boxes) > 0
for i = array.size(long_boxes) – 1 to 0 by 1
lbox = array.get(long_boxes, i)
top = box.get_top(lbox)
bottom = box.get_bottom(lbox)
ago = box.get_left(lbox)
if array.get(pvl1_price, 0) < top
if box_sv
box.set_bgcolor(lbox, t_d)
if ob_a_sv and close > top
if array.get(pvl1_time, 0) != l_a_time
l_a_time := array.get(pvl1_time, 0)
alert := alert + ‘Demand Zone Test @ ‘ + str.tostring(array.get(pvl1_price, 0)) + ‘ (age = ‘ + str.tostring(bar_index-ago) + ‘ bars) \n’
if array.get(pvh1_price, 0) < bottom
if m_sv
box.set_bgcolor(lbox, u_b)
array.push(m_short_boxes, lbox)
else
box.delete(lbox)
array.remove(long_boxes, i)
if msb_sv
line.delete(array.get(bull_bos_lines, i))
array.remove(bull_bos_lines, i)
if array.size(m_short_boxes) > 0
for i = array.size(m_short_boxes) – 1 to 0 by 1
tbox = array.get(m_short_boxes, i)
top = box.get_top(tbox)
bottom = box.get_bottom(tbox)
ago = box.get_left(tbox)
if array.get(pvh1_price, 0) > bottom
box.set_bgcolor(tbox, t_b)
if bb_a_sv and close < bottom
if array.get(pvh1_time, 0) != mh_a_time
mh_a_time := array.get(pvh1_time, 0)
alert := alert + 'Breakerblock Test Up @ ' + str.tostring(array.get(pvh1_price, 0)) + ' (age = ' + str.tostring(bar_index-ago) + ' bars) \n'
if array.get(pvl1_price, 0) > top
box.delete(tbox)
array.remove(m_short_boxes, i)
if array.size(m_long_boxes) > 0
for i = array.size(m_long_boxes) – 1 to 0 by 1
lbox = array.get(m_long_boxes, i)
top = box.get_top(lbox)
bottom = box.get_bottom(lbox)
ago = box.get_left(lbox)
if array.get(pvl1_price, 0) < top
box.set_bgcolor(lbox, t_b)
if bb_a_sv and close > top
if array.get(pvl1_time, 0) != ml_a_time
ml_a_time := array.get(pvl1_time, 0)
alert := alert + ‘Breakerblock Test Down @ ‘ + str.tostring(array.get(pvl1_price, 0)) + ‘ (age = ‘ + str.tostring(bar_index-ago) + ‘ bars) \n’
if array.get(pvh1_price, 0) < bottom
box.delete(lbox)
array.remove(m_long_boxes, i)
if range_sv and (new_ph_2nd or new_pl_2nd) and (array.get(pvh2_price, 0) < array.get(pvh2_price, 1) and array.get(pvl2_price, 0) > array.get(pvl2_price, 1) and array.get(pvh2_price, 0) > array.get(pvl2_price, 1) and array.get(pvl2_price, 0) < array.get(pvh2_price, 1)) and (array.get(pvl2_price, 1) > nz(last_range_h) or na(last_range_l)? true : (array.get(pvh2_price, 1) < last_range_l))
temp_time := math.min(array.get(pvh2_time, 1), array.get(pvl2_time, 1))
last_range_h := array.get(pvh2_price, 1)
last_range_l := array.get(pvl2_price, 1)
temp_pv_0 := log_sv ? math.exp((math.log(last_range_h) + math.log(last_range_l))/2) : (last_range_h + last_range_l)/2
temp_pv_1 := log_sv ? math.exp((math.log(last_range_h) + math.log(temp_pv_0))/2) : (last_range_h + temp_pv_0)/2
temp_pv_2 := log_sv ? math.exp((math.log(last_range_l) + math.log(temp_pv_0))/2) : (last_range_l + temp_pv_0)/2
array.push(range_h_lines, line.new(x1=temp_time, y1=last_range_h, x2=bar_index, y2=last_range_h, color=color.gray, width=1, extend=extend.right))
array.push(range_l_lines, line.new(x1=temp_time, y1=last_range_l, x2=bar_index, y2=last_range_l, color=color.gray, width=1, extend=extend.right))
if range_eq_sv
array.push(range_m_lines, line.new(x1=temp_time, y1=temp_pv_0, x2=bar_index, y2=temp_pv_0, color=color.gray, width=1, extend=extend.right))
if range_q_sv
array.push(range_25_lines, line.new(x1=temp_time, y1=temp_pv_1, x2=bar_index, y2=temp_pv_1, style=line.style_dashed, color=color.gray, width=1, extend=extend.right))
array.push(range_75_lines, line.new(x1=temp_time, y1=temp_pv_2, x2=bar_index, y2=temp_pv_2, style=line.style_dashed, color=color.gray, width=1, extend=extend.right))
if r_a_sv
alert := alert + 'New Range : ' + str.tostring(last_range_h) + ' - ' + str.tostring(last_range_l) + '. Mean = ' + str.tostring(temp_pv_0) + '\n'
if array.size(range_h_lines) > 0
for i = array.size(range_h_lines) – 1 to 0 by 1
range_h = array.get(range_h_lines, i)
top = line.get_y1(range_h)
range_l = array.get(range_l_lines, i)
bottom = line.get_y1(range_l)
temp_time := line.get_x1(range_h)
if array.get(pvh1_price, 0) > top
if rt_a_sv and close < top
if array.get(pvh1_time, 0) != rh_a_time
rh_a_time := array.get(pvh1_time, 0)
alert := alert + 'Range High Test @ ' + str.tostring(array.get(pvh1_price, 0)) + ' \n'
if array.get(pvl1_price, 0) < bottom
if rt_a_sv and close > bottom
if array.get(pvl1_time, 0) != rl_a_time
rl_a_time := array.get(pvl1_time, 0)
alert := alert + ‘Range Low Test @ ‘ + str.tostring(array.get(pvl1_price, 0)) + ‘ \n’
if range_eq_sv
range_m := array.get(range_m_lines, i)
if range_q_sv
range_25 := array.get(range_25_lines, i)
range_75 := array.get(range_75_lines, i)
if array.get(pvh1_price, 0) < bottom or array.get(pvl1_price, 0) > top
line.delete(range_h)
array.remove(range_h_lines, i)
line.delete(range_l)
array.remove(range_l_lines, i)
if range_eq_sv
line.delete(range_m)
array.remove(range_m_lines, i)
if range_q_sv
line.delete(range_25)
array.remove(range_25_lines, i)
line.delete(range_75)
array.remove(range_75_lines, i)
last_range_h := na
last_range_l := na
if pv2_sv
if new_ph_2nd
array.push(la_ph2, label.new(x = array.get(pvh2_time, 0), y = array.get(pvh2_price, 0), xloc = xloc.bar_index, style = label.style_label_down, color = #770000FF, size = size.tiny))
if new_pl_2nd
array.push(la_pl2, label.new(x = array.get(pvl2_time, 0), y = array.get(pvl2_price, 0), xloc = xloc.bar_index, style = label.style_label_up, color = #007700FF, size = size.tiny))
alert := not na(alert) ? (alert + ‘Current price = ‘ + str.tostring(close) + ‘\n’) : na
exec = not na(alert) ? true : false
if exec==true
alert(alert, alert.freq_once_per_bar_close)
The information collected on this form is stored in a computer file by ProRealCode to create and access your ProRealCode profile. This data is kept in a secure database for the duration of the member's membership. They will be kept as long as you use our services and will be automatically deleted after 3 years of inactivity. Your personal data is used to create your private profile on ProRealCode. This data is maintained by SAS ProRealCode, 407 rue Freycinet, 59151 Arleux, France. If you subscribe to our newsletters, your email address is provided to our service provider "MailChimp" located in the United States, with whom we have signed a confidentiality agreement. This company is also compliant with the EU/Swiss Privacy Shield, and the GDPR. For any request for correction or deletion concerning your data, you can directly contact the ProRealCode team by email at privacy@prorealcode.com If you would like to lodge a complaint regarding the use of your personal data, you can contact your data protection supervisory authority.