HTF Raid Indicator.pine
Copy
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © Professeur_X
//@version=5
indicator("HTF Raid Indicator", overlay=true, max_boxes_count = 500, max_bars_back = 3000, max_lines_count = 500)
// GLOBAL PARAMETERS AND FUNCTIONS
// [
array_limit = 200, max_line_back = 200
f_time_to_bi(_time) => ta.valuewhen(time == _time, bar_index, 0)
// ]
// MULTIMEFRAME CANDLE
// [
// Parameters [
i_htf = input.timeframe('60', "Timeframe")
i_trans = 85
var arr_candles = array.new_string(10)
// ]
// Functions [
f_htf_ohlc(_htf) =>
// [
var htf_o = 0.
var htf_h = 0.
var htf_l = 0.
htf_c = close
var htf_ox = 0.
var htf_hx = 0.
var htf_lx = 0.
var htf_cx = 0.
if ta.change(time(_htf))
htf_ox := htf_o
htf_o := open
htf_hx := htf_h
htf_h := high
htf_lx := htf_l
htf_l := low
htf_cx := htf_c[1]
htf_cx
else
htf_h := math.max(high, htf_h)
htf_l := math.min(low, htf_l)
htf_l
[htf_ox, htf_hx, htf_lx, htf_cx, htf_o, htf_h, htf_l, htf_c]
// ]
f_process_candles(_trans, _btransp, _width) =>
// [
time_x11 = ta.valuewhen(ta.change(time(i_htf)), time, 1)
time_x1 = ta.valuewhen(ta.change(time(i_htf)), time, 0)
offset = math.round(ta.change(time))
time_x2 = 2 * time_x1 - time_x11
[O1, H1, L1, C1, O0, H0, L0, C0] = f_htf_ohlc(i_htf)
cond_new_bar = false, end_time = int(na)
color0 = O0 < C0 ? color.new(#388e3c , _trans) : color.new(#d32f2f , _trans)
color01 = O0 < C0 ? color.new(#388e3c , _btransp) : color.new(#d32f2f , _btransp)
color1 = O1 < C1 ? color.new(#388e3c , _trans) : color.new(#d32f2f , _trans)
color11 = O1 < C1 ? color.new(#388e3c , _btransp) : color.new(#d32f2f , _btransp)
var box hl = na
var box oc = na
var line e = na
if ta.change(time(i_htf))
end_time := box.get_right(oc)
box.delete(hl)
box.delete(oc)
line.delete(e)
box.new(time_x11, H1, time_x1 - offset, L1, color11, _width, line.style_dotted, extend.none, xloc.bar_time, color1)
box.new(time_x11, O1, time_x1 - offset, C1, color11, _width, line.style_solid , extend.none, xloc.bar_time, color1)
hl := box.new(time_x1, H0, time_x2 - offset, L0, color01, _width, line.style_dotted, extend.none, xloc.bar_time, color0)
oc := box.new(time_x1, O0, time_x2 - offset, C0, color01, _width, line.style_solid , extend.none, xloc.bar_time, color0)
cond_new_bar := true
true
else
end_time := box.get_right(oc)
box.set_top(hl, H0)
box.set_bottom(hl, L0)
box.set_bgcolor(hl, color0)
box.set_border_color(hl, color01)
box.set_top(oc, math.max(O0, C0))
box.set_bottom(oc, math.min(O0, C0))
box.set_bgcolor(oc, color0)
box.set_border_color(oc, color01)
true
// time_x1 : Start of current Candle
// time_x1 - offset : End of 2 Previous Candle
_open = O0, _prev_open = O1
_close = C0, _prev_close = C1
_high = H0, _prev_high = H1
_low = L0, _prev_low = L1
_start_time = time_x11, _end_time = end_time
// Return OHLC and time value of the previous (confirmed) bar
[cond_new_bar, _prev_open, _prev_high, _prev_low, _prev_close, _start_time, _end_time]
// ]
f_add_mtf_candle(_open, _high, _low, _close, _start_time, _end_time) =>
// [
dir = _open < _close ? "up" : _open > _close ? "down" : "neutral"
_text = "#" + "|" + dir + "|" + str.tostring(_open) + "|" + str.tostring(_high) + "|" + str.tostring(_low) + "|" + str.tostring(_close) +
"|" + str.tostring(_start_time) + "|" + str.tostring(_end_time)
if array.size(arr_candles) >= 10
array.pop(arr_candles)
array.unshift(arr_candles, _text)
else
array.unshift(arr_candles, _text)
// ]
f_decode_mtf_candle(_text) =>
// [
txt_array = str.split(_text, "|")
if array.size(txt_array) == 8
_dir = str.tonumber( array.get(txt_array, 1) )
_open = str.tonumber( array.get(txt_array, 2) )
_high = str.tonumber( array.get(txt_array, 3) )
_low = str.tonumber( array.get(txt_array, 4) )
_close = str.tonumber( array.get(txt_array, 5) )
_start_time = str.tonumber( array.get(txt_array, 6) )
_end_time = str.tonumber( array.get(txt_array, 7) )
[_open, _high, _low, _close, _start_time, _end_time]
// ]
f_get_mtf(_val, _inx) =>
// [
_text = array.get(arr_candles, _inx)
[_open, _high, _low, _close, _start_time, _end_time] = f_decode_mtf_candle(_text)
if _val == "open"
_open
else if _val == "high"
_high
else if _val == "low"
_low
else if _val == "close"
_close
else if _val == "start"
_start_time
else if _val == "end"
_end_time
// ]
// ]
// Store Candles after confirmation [
[new_bar, mtf_open, mtf_high, mtf_low, mtf_close, mtf_start_time, mtf_end_time] = f_process_candles(100, 100, 1)
bi_mtf_start_time = f_time_to_bi(mtf_start_time), bi_mtf_end_time = f_time_to_bi(mtf_end_time)
if new_bar
f_add_mtf_candle(mtf_open, mtf_high, mtf_low, mtf_close, bi_mtf_start_time, bi_mtf_end_time)
// ]
// ]
// FRACTALS
// [
var arr_up_fractal = array.new_string(array_limit)
var arr_dn_fractal = array.new_string(array_limit)
// Functions and Conditions [
f_mtf_fractal_up() =>
// [
fractal_lback = 2 // Lookback period for Fractals
f_get_mtf("high", 2)
val_8 = f_get_mtf("high", 8) // val_8 --- high[fractal_lback + 6] -> high[8] // 8
val_7 = f_get_mtf("high", 7) // val_7 --- high[fractal_lback + 5] -> high[7] // 7
val_6 = f_get_mtf("high", 6) // val_6 --- high[fractal_lback + 4] -> high[6] // 6
val_5 = f_get_mtf("high", 5) // val_5 --- high[fractal_lback + 3] -> high[5] // 5
val_4 = f_get_mtf("high", 4) // val_4 --- high[fractal_lback + 2] -> high[4] // 4
val_3 = f_get_mtf("high", 3) // val_3 --- high[fractal_lback + 1] -> high[3] // 3
val_2 = f_get_mtf("high", 2) // val_2 --- high[fractal_lback + 0] -> high[2] // 2
val_1 = f_get_mtf("high", 1) // val_1 --- high[fractal_lback - 1] -> high[1] // 1
val_0 = f_get_mtf("high", 0) // val_0 --- high[fractal_lback - 2] -> high[0] // 0
cond_up_fractal = val_4 < val_2 and val_3 < val_2 and val_1 < val_2
and high[fractal_lback - 2] < val_2 or val_5 < val_2 and val_4 < val_2
and val_3 == val_2 and val_1 < val_2 and high[fractal_lback - 2] < val_2
or val_6 < val_2 and val_5 < val_2 and val_4 == val_2
and val_3 <= val_2 and val_1 < val_2 and high[fractal_lback - 2] < val_2
or val_7 < val_2 and val_6 < val_2 and val_5 == val_2
and val_4 == val_2 and val_3 <= val_2 and val_1 < val_2
and high[fractal_lback - 2] < val_2 or val_8 < val_2 and val_7 < val_2
and val_6 == val_2 and val_5 <= val_2 and val_4 == val_2
and val_3 <= val_2 and val_1 < val_2 and high[fractal_lback - 2] < val_2
cond_up_fractal
// ]
f_mtf_fractal_dn() =>
// [
fractal_lback = 2 // Lookback period for Fractals
f_get_mtf("low", 2)
val_8 = f_get_mtf("low", 8) // val_8 --- low[fractalx_lback + 6] -> low[8] // 8
val_7 = f_get_mtf("low", 7) // val_7 --- low[fractalx_lback + 5] -> low[7] // 7
val_6 = f_get_mtf("low", 6) // val_6 --- low[fractalx_lback + 4] -> low[6] // 6
val_5 = f_get_mtf("low", 5) // val_5 --- low[fractalx_lback + 3] -> low[5] // 5
val_4 = f_get_mtf("low", 4) // val_4 --- low[fractalx_lback + 2] -> low[4] // 4
val_3 = f_get_mtf("low", 3) // val_3 --- low[fractalx_lback + 1] -> low[3] // 3
val_2 = f_get_mtf("low", 2) // val_2 --- low[fractalx_lback - 0] -> low[2] // 2
val_1 = f_get_mtf("low", 1) // val_1 --- low[fractalx_lback - 1] -> low[1] // 1
val_0 = f_get_mtf("low", 0) // val_0 --- low[fractalx_lback - 2] -> low[0] // 0
cond_dn_fractal = val_4 > val_2 and val_3 > val_2 and val_1> val_2
and val_0 > val_2 or val_5 > val_2 and val_4 > val_2
and val_3 == val_2 and val_1> val_2 and val_0 > val_2
or val_6 > val_2 and val_5 > val_2 and val_4 == val_2
and val_3 >= val_2 and val_1> val_2 and val_0 > val_2
or val_7 > val_2 and val_6 > val_2 and val_5 == val_2
and val_4 == val_2 and val_3 >= val_2 and val_1> val_2
and val_0 > val_2 or val_8 > val_2 and val_7 > val_2
and val_6 == val_2 and val_5 >= val_2 and val_4 == val_2
and val_3 >= val_2 and val_1> val_2 and val_0 > val_2
cond_dn_fractal
// ]
f_add_fractal(_type, val_HL, _bi ) =>
// [
_text = "#" + "|" + str.tostring(val_HL) + "|" + str.tostring(_bi)
if _type == "up"
// Store in Bull Array
if array.size(arr_up_fractal) >= array_limit
array.pop(arr_up_fractal)
array.unshift(arr_up_fractal, _text)
else
array.unshift(arr_up_fractal, _text)
else if _type == "down"
// Store in Bear Array
if array.size(arr_dn_fractal) >= array_limit
array.pop(arr_dn_fractal)
array.unshift(arr_dn_fractal, _text)
else
array.unshift(arr_dn_fractal, _text)
// ]
f_decode_fractal_arr(_text) =>
// [
txt_array = str.split(_text, "|")
if array.size(txt_array) == 3
val = str.tonumber( array.get(txt_array, 1) )
bi = int( str.tonumber( array.get(txt_array, 2) ) )
[val, bi]
// ]
// ]
if new_bar and f_mtf_fractal_up() // Up Fractal
_bi = f_get_mtf("start", 2)
val_H = f_get_mtf("high", 2)
f_add_fractal("up", val_H, _bi )
if new_bar and f_mtf_fractal_dn() // Up Fractal
_bi = f_get_mtf("start", 2)
val_L = f_get_mtf("low", 2)
f_add_fractal("down", val_L, _bi )
// ]
// ZIGZAG
// [
prd = 2
bool newbar = ta.change(time(i_htf)) != 0
showzigzag = true
upcol= color.lime, dncol= color.maroon
tf_bi = ta.valuewhen(newbar, bar_index, prd - 1)
len = bar_index - tf_bi + 1
float ph = na, float pl = na
ph := ta.highestbars(high, nz(len, 1)) == 0 ? high : na
pl := ta.lowestbars(low, nz(len, 1)) == 0 ? low : na
var dir = 0
iff_1 = pl and na(ph) ? -1 : dir
dir := ph and na(pl) ? 1 : iff_1
var max_array_size = 50
var zigzag = array.new_float(0)
oldzigzag = array.copy(zigzag)
add_to_zigzag(value, bindex) =>
array.unshift(zigzag, bindex)
array.unshift(zigzag, value)
if array.size(zigzag) > max_array_size
array.pop(zigzag)
array.pop(zigzag)
update_zigzag(value, bindex) =>
if array.size(zigzag) == 0
add_to_zigzag(value, bindex)
else
if dir == 1 and value > array.get(zigzag, 0) or dir == -1 and value < array.get(zigzag, 0)
array.set(zigzag, 0, value)
array.set(zigzag, 1, bindex)
0.
var arr_up_zigzag = array.new_string(array_limit)
var arr_dn_zigzag = array.new_string(array_limit)
// Functions for Raid Dectection
f_add_zigzag(_type, val_HL, _bi ) =>
// [
_text = "#" + "|" + str.tostring(val_HL) + "|" + str.tostring(_bi)
if _type == "up"
// Store in Bull Array
if array.size(arr_up_zigzag) >= array_limit
array.pop(arr_up_zigzag)
array.unshift(arr_up_zigzag, _text)
else
array.unshift(arr_up_zigzag, _text)
else if _type == "down"
// Store in Bear Array
if array.size(arr_dn_zigzag) >= array_limit
array.pop(arr_dn_zigzag)
array.unshift(arr_dn_zigzag, _text)
else
array.unshift(arr_dn_zigzag, _text)
// ]
// Calculations {
bool dirchanged = dir != dir[1]
if ph or pl
if dirchanged
add_to_zigzag(dir == 1 ? ph : pl, bar_index)
else
update_zigzag(dir == 1 ? ph : pl, bar_index)
val_zig_h = fixnan(ph), val_zig_l = fixnan(pl)
count_ph = ta.valuewhen(ph, bar_index, 0)
count_pl = ta.valuewhen(pl, bar_index, 0)
if pl and dirchanged // New High
f_add_zigzag("up", val_zig_h, count_ph )
if ph and dirchanged // New Low
f_add_zigzag("down", val_zig_l, count_pl )
// }
// // Plot Zigzag {
// if showzigzag and array.size(zigzag) >= 4 and array.size(oldzigzag) >= 4
// var line zzline = na
// if array.get(zigzag, 0) != array.get(oldzigzag, 0) or array.get(zigzag, 1) != array.get(oldzigzag, 1)
// if array.get(zigzag, 2) == array.get(oldzigzag, 2) and array.get(zigzag, 3) == math.round(array.get(oldzigzag, 3))
// line.delete(zzline)
// zzline := line.new(x1=math.round(array.get(zigzag, 1)), y1=array.get(zigzag, 0), x2=math.round(array.get(zigzag, 3)), y2=array.get(zigzag, 2), color=dir == 1 ? upcol : dncol, width=2)
// zzline
// if not showzigzag and array.size(zigzag) >= 6
// var line zzline = na
// line.delete(zzline)
// zzline := line.new(x1=math.round(array.get(zigzag, 3)), y1=array.get(zigzag, 2), x2=math.round(array.get(zigzag, 5)), y2=array.get(zigzag, 4), color=dir == 1 ? upcol : dncol, width=2, style=line.style_dotted)
// zzline
// // }
// ]
// RETRACEMENT BAR
// [
// Parameters [
var arr_bull_bars = array.new_string(array_limit)
var arr_bear_bars = array.new_string(array_limit)
cond_hm_bull_bar() =>
[_open, _high, _low, _close, _start_time, _end_time] = f_decode_mtf_candle(array.get(arr_candles, 0))
high_limit = _high - ( .45 * (_high - _low) )
( _open <= high_limit ) and ( _close <= high_limit )
cond_hm_bear_bar() =>
[_open, _high, _low, _close, _start_time, _end_time] = f_decode_mtf_candle(array.get(arr_candles, 0))
low_limit = _low + ( .45 * (_high - _low) )
( _open >= low_limit ) and ( _close >= low_limit )
// ]
f_add_hm_bar(_type, val_HL, _bi ) =>
// [
_text = "#" + "|" + str.tostring(val_HL) + "|" + str.tostring(_bi)
if _type == "bull"
// Store in Bull Array
if array.size(arr_bull_bars) >= array_limit
array.pop(arr_bull_bars)
array.unshift(arr_bull_bars, _text)
else
array.unshift(arr_bull_bars, _text)
else if _type == "bear"
// Store in Bear Array
if array.size(arr_bear_bars) >= array_limit
array.pop(arr_bear_bars)
array.unshift(arr_bear_bars, _text)
else
array.unshift(arr_bear_bars, _text)
// ]
f_decode_hm_arr(_text) =>
// [
txt_array = str.split(_text, "|")
if array.size(txt_array) == 3
val = str.tonumber( array.get(txt_array, 1) )
bi = int( str.tonumber( array.get(txt_array, 2) ) )
[val, bi]
// ]
f_remove_index(_source, _arr) =>
// [
if array.size(_source) > 0
for i = 0 to array.size(_source) - 1
array.remove(_arr, array.get(_source, i) )
// ]
f_scan_bull_break() =>
// [
remove_txt = array.new_int()
if array.size(arr_bull_bars) > 0
for i = 0 to array.size(arr_bull_bars) - 1
// Scan through all available IRB bars to see if current candle breaks out of any
[val , bi] = f_decode_hm_arr( array.get(arr_bull_bars, i) )
if close > val
// Add to Broken Levels -> to be plotted
f_add_hm_bar("broken bull", val, bi )
array.unshift(remove_txt, i)
f_remove_index(remove_txt, arr_bull_bars)
// ]
f_scan_bear_break() =>
// [
remove_txt = array.new_int()
if array.size(arr_bear_bars) > 0
for i = 0 to array.size(arr_bear_bars) - 1
// Scan through all available IRB bars to see if current candle breaks out of any
[val , bi] = f_decode_hm_arr( array.get(arr_bear_bars, i) )
if close < val
// Add to Broken Levels -> to be plotted
f_add_hm_bar("broken bear", val, bi )
array.unshift(remove_txt, i)
f_remove_index(remove_txt, arr_bear_bars)
// ]
// Add New Retracement Bars into Array [
if new_bar and cond_hm_bull_bar() // Bullish IRB
_bi = f_get_mtf("start", 0)
val_H = f_get_mtf("high", 0)
f_add_hm_bar("bull", val_H, _bi )
if cond_hm_bear_bar() // Bearsih IRB
_bi = f_get_mtf("start", 0)
val_L = f_get_mtf("low", 0)
f_add_hm_bar("bear", val_L, _bi )
// ]
// ]
// RAIDS
// [
// Pivot Method Combination
use_pivot_fractal = input.bool(true, "Fractals", inline="frac_irb_zig", group="Pivot Method Detection")
use_pivot_irb = input.bool(true, "Retracement Bar", inline="frac_irb_zig", group="Pivot Method Detection")
use_pivot_zigzag = input.bool(true, "Zigzag", inline="frac_irb_zig", group="Pivot Method Detection")
arr_raid_up = array.new_string() // For Bearish Raid
arr_raid_dn = array.new_string() // For Bullish Raid
f_add_raid(_type, val_HL, _bi ) =>
// [
_text = "#" + "|" + str.tostring(val_HL) + "|" + str.tostring(_bi)
if _type == "up"
// Store in Raided Up Fractal
array.unshift(arr_raid_up, _text)
else if _type == "down"
// Store in Raided Down Fractal
array.unshift(arr_raid_dn, _text)
// ]
f_scan_raid_up() =>
// [
[_open, _high, _low, _close, _start_time, _end_time] = f_decode_mtf_candle(array.get(arr_candles, 0))
if use_pivot_fractal
remove_txt = array.new_int()
if array.size(arr_up_fractal) > 0
for i = 0 to array.size(arr_up_fractal) - 1
[val , bi] = f_decode_fractal_arr( array.get(arr_up_fractal, i) )
if (_high > val) and (_close < val)
// Add to Broken Levels -> to be plotted
f_add_raid("up", val, bi )
array.unshift(remove_txt, i)
else if _close > val
array.unshift(remove_txt, i)
f_remove_index(remove_txt, arr_up_fractal)
if use_pivot_zigzag
remove_txt = array.new_int()
if array.size(arr_up_zigzag) > 0
for i = 0 to array.size(arr_up_zigzag) - 1
[val , bi] = f_decode_fractal_arr( array.get(arr_up_zigzag, i) )
if (_high > val) and (_close < val)
// Add to Broken Levels -> to be plotted
f_add_raid("up", val, bi )
array.unshift(remove_txt, i)
else if _close > val
array.unshift(remove_txt, i)
f_remove_index(remove_txt, arr_up_zigzag)
if use_pivot_irb
remove_txt = array.new_int()
if array.size(arr_bull_bars) > 0
for i = 0 to array.size(arr_bull_bars) - 1
// Scan through all available IRB bars to see if current candle breaks out of any
[val , bi] = f_decode_hm_arr( array.get(arr_bull_bars, i) )
if (_high > val) and (_close < val)
// Add to Broken Levels -> to be plotted
f_add_raid("up", val, bi )
array.unshift(remove_txt, i)
else if _close > val
// Add to Broken Levels -> to be plotted
array.unshift(remove_txt, i)
f_remove_index(remove_txt, arr_bull_bars)
// ]
f_scan_raid_dn() =>
// [
[_open, _high, _low, _close, _start_time, _end_time] = f_decode_mtf_candle(array.get(arr_candles, 0))
if use_pivot_fractal
remove_txt = array.new_int()
if array.size(arr_dn_fractal) > 0
for i = 0 to array.size(arr_dn_fractal) - 1
[val , bi] = f_decode_fractal_arr( array.get(arr_dn_fractal, i) )
if (_low <val) and (_close > val )
// Add to Broken Levels -> to be plotted
f_add_raid("down", val, bi )
array.unshift(remove_txt, i)
else if _close < val
array.unshift(remove_txt, i)
f_remove_index(remove_txt, arr_dn_fractal)
if use_pivot_zigzag
remove_txt = array.new_int()
if array.size(arr_dn_zigzag) > 0
for i = 0 to array.size(arr_dn_zigzag) - 1
[val , bi] = f_decode_fractal_arr( array.get(arr_dn_zigzag, i) )
if (_low <val) and (_close > val )
// Add to Broke_n Levels -> to be plotted
f_add_raid("down", val, bi )
array.unshift(remove_txt, i)
else if _close < val
array.unshift(remove_txt, i)
f_remove_index(remove_txt, arr_dn_zigzag)
if use_pivot_irb
remove_txt = array.new_int()
if array.size(arr_bear_bars) > 0
for i = 0 to array.size(arr_bear_bars) - 1
// Scan through all available IRB bars to see if current candle breaks out of any
[val , bi] = f_decode_hm_arr( array.get(arr_bear_bars, i) )
if (_low < val) and (_close > val )
// Add to Broken Levels -> to be plotted
f_add_raid("down", val, bi )
array.unshift(remove_txt, i)
else if _close < val
// Add to Broken Levels -> to be plotted
array.unshift(remove_txt, i)
f_remove_index(remove_txt, arr_bear_bars)
// ]
cond_bull_raid = false
cond_bear_raid = false
// Scan for Raids [
f_scan_raid_up()
f_scan_raid_dn()
// ]
// Plot Raided Pivots [
if array.size(arr_raid_up) > 0 // For Bullish Breakout
for i = 0 to array.size(arr_raid_up) - 1
[val , bi] = f_decode_fractal_arr( array.get(arr_raid_up, i) )
// if bar_index - bi <= max_line_back
// line.new(x1 = bar_index, y1 = val, x2 = bi, y2 = val, xloc=xloc.bar_index, color = color.yellow, style = line.style_dotted)
cond_bull_raid := true
if array.size(arr_raid_dn) > 0 // For Bearish Breakout
for i = 0 to array.size(arr_raid_dn) - 1
[val , bi] = f_decode_fractal_arr( array.get(arr_raid_dn, i) )
// if bar_index - bi <= max_line_back
// line.new(x1 = bar_index, y1 = val, x2 = bi, y2 = val, xloc=xloc.bar_index, color = #FF0000, style = line.style_dotted)
cond_bear_raid := true
// ]
// Plot Raid Labels
plotshape(cond_bull_raid, style=shape.triangledown, location=location.abovebar, color=#FF0000, title = "Bullish Raid", size=size.auto)
plotshape(cond_bear_raid, style=shape.triangleup, location=location.belowbar, color=#00FF00, title = "Bearish Raid", size=size.auto)
// ]
// PLOTS
// [
bgcolor(color.new(#000000, 50), editable=false)
barcolor(cond_bull_raid ? #FF0000 : cond_bear_raid ? #00FF00 : #FFFFFF, editable=false)
// ]
Show all 677 lines