[JL] Fractals ATR Block
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © Jesse.Lau

//@version=5
indicator("[JL] Fractals ATR Block", shorttitle="[JL] FAB", format=format.price, precision=0, overlay=true)
show_fractals = input(true, "Show Fractals", group="Show")
show_atrs = input(true, "Show ATR breaks", group="Show")
show_blocks = input(false, "Show blocks", group="Show")


n = input.int(title="Fractals Periods", defval=1, minval=1)
roclevel = input.float(title="ROC Break Level", defval=2.0, minval=0)

rocup = (close - ta.lowest(n+1))/(open[2*n]-ta.lowest(n+1))
rocdn = (ta.highest(n+1)-close)/(ta.highest(n+1)-open[2*n])

atrPeriod = input(200, "ATR Length")
atrlevel = input.float(title="ATR Break Level", defval=1.5, minval=0)
ATR = ta.atr(atrPeriod)


atrup = (close - low)/ATR[1]
atrdn = (high -close)/ATR[1]


// UpFractal
bool upflagDownFrontier = true
bool upflagUpFrontier0 = true
bool upflagUpFrontier1 = true
bool upflagUpFrontier2 = true
bool upflagUpFrontier3 = true
bool upflagUpFrontier4 = true

for i = 1 to n
    upflagDownFrontier := upflagDownFrontier and (high[n-i] < high[n])
    upflagUpFrontier0 := upflagUpFrontier0 and (high[n+i] < high[n])
    upflagUpFrontier1 := upflagUpFrontier1 and (high[n+1] <= high[n] and high[n+i + 1] < high[n])
    upflagUpFrontier2 := upflagUpFrontier2 and (high[n+1] <= high[n] and high[n+2] <= high[n] and high[n+i + 2] < high[n])
    upflagUpFrontier3 := upflagUpFrontier3 and (high[n+1] <= high[n] and high[n+2] <= high[n] and high[n+3] <= high[n] and high[n+i + 3] < high[n])
    upflagUpFrontier4 := upflagUpFrontier4 and (high[n+1] <= high[n] and high[n+2] <= high[n] and high[n+3] <= high[n] and high[n+4] <= high[n] and high[n+i + 4] < high[n])
flagUpFrontier = upflagUpFrontier0 or upflagUpFrontier1 or upflagUpFrontier2 or upflagUpFrontier3 or upflagUpFrontier4

upFractal = (upflagDownFrontier and flagUpFrontier)


// downFractal
bool downflagDownFrontier = true
bool downflagUpFrontier0 = true
bool downflagUpFrontier1 = true
bool downflagUpFrontier2 = true
bool downflagUpFrontier3 = true
bool downflagUpFrontier4 = true

for i = 1 to n
    downflagDownFrontier := downflagDownFrontier and (low[n-i] > low[n])
    downflagUpFrontier0 := downflagUpFrontier0 and (low[n+i] > low[n])
    downflagUpFrontier1 := downflagUpFrontier1 and (low[n+1] >= low[n] and low[n+i + 1] > low[n])
    downflagUpFrontier2 := downflagUpFrontier2 and (low[n+1] >= low[n] and low[n+2] >= low[n] and low[n+i + 2] > low[n])
    downflagUpFrontier3 := downflagUpFrontier3 and (low[n+1] >= low[n] and low[n+2] >= low[n] and low[n+3] >= low[n] and low[n+i + 3] > low[n])
    downflagUpFrontier4 := downflagUpFrontier4 and (low[n+1] >= low[n] and low[n+2] >= low[n] and low[n+3] >= low[n] and low[n+4] >= low[n] and low[n+i + 4] > low[n])
flagDownFrontier = downflagUpFrontier0 or downflagUpFrontier1 or downflagUpFrontier2 or downflagUpFrontier3 or downflagUpFrontier4

downFractal = (downflagDownFrontier and flagDownFrontier)

if show_atrs and atrup >  atrlevel
    label.new(x=bar_index, y=na,text= "AB"+str.tostring(atrup, '##.##'), //ATR BREAK
         color=color.lime, 
         textcolor=color.black,size=size.small,
         style=label.style_label_up, yloc=yloc.belowbar)

    
if show_atrs and atrdn >  atrlevel
    label.new(x=bar_index, y=na, text= "AB"+str.tostring(atrdn, '##.##'), //ATR BREAK
         color=color.red, 
         textcolor=color.white,size=size.small,
         style=label.style_label_down, yloc=yloc.abovebar)

if downFractal and rocup > roclevel and show_fractals
    label.new(x=bar_index-n, y=na, text="FR"+str.tostring(rocup, '##.##'), //Fractal ROC
         color=color.lime, 
         textcolor=color.black, size=size.small,
         style=label.style_label_up, yloc=yloc.belowbar)

if upFractal and rocdn > roclevel and show_fractals
    label.new(x=bar_index-n, y=na, text="FR"+str.tostring(rocdn, '##.##'), //Fractal ROC
         color=color.red, 
         textcolor=color.white, size=size.small,
         style=label.style_label_down, yloc=yloc.abovebar)


var box upBox = na
var box downBox = na

if show_atrs and atrup > atrlevel and show_blocks
    if not na(upBox)
        box.delete(upBox)
    upBox := box.new(left=bar_index-1, top=high[1], right=bar_index, bottom=low[1], border_color=color.lime, border_width=1, border_style=line.style_solid, bgcolor=color.new(color.lime, 50) ,extend=extend.right)

if show_atrs and atrdn > atrlevel and show_blocks 
    if not na(downBox)
        box.delete(downBox)
    downBox := box.new(left=bar_index-1, top=high[1], right=bar_index, bottom=low[1], border_color=color.red, border_width=1, border_style=line.style_solid, bgcolor=color.new(color.red, 50), extend=extend.right)


var box upBoxf = na
var box downBoxf = na
lowest_low_2n = ta.lowest(low, 2*n)
highest_hihg_2n = ta.highest(high, 2*n)
if downFractal and rocup > roclevel and show_fractals and show_blocks
    if not na(upBoxf)
        box.delete(upBoxf)
    upBoxf := box.new(left=bar_index-2*n, top=highest_hihg_2n[n+1], right=bar_index, bottom=lowest_low_2n[n+1], border_color=color.lime, border_width=1, border_style=line.style_solid, bgcolor=color.new(color.lime, 50) ,extend=extend.right)

if upFractal and rocdn > roclevel and show_fractals and show_blocks 
    if not na(downBoxf)
        box.delete(downBoxf)
    downBoxf := box.new(left=bar_index-2*n, top=highest_hihg_2n[n+1], right=bar_index, bottom=lowest_low_2n[n+1], border_color=color.red, border_width=1, border_style=line.style_solid, bgcolor=color.new(color.red, 50), extend=extend.right)
