Efficiency Gaps
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © BobBasic

//@version=5
indicator("Efficiency Gaps", overlay=true, max_boxes_count=60, max_lines_count=60)

multi = input.float(0.01, "ATR Multiplier", 0.01, 1, step=0.01)
period = input.int(21, "ATR Period")
upbox_color = input.color(color.rgb(76, 175, 79, 95), "Box Up")
downbox_color = input.color(color.rgb(255, 82, 82, 95), "Box Down")
topline_color = input.color(color.rgb(76, 175, 79), "Top Line")
bottomline_color = input.color(color.rgb(255, 82, 82), "Bottom Line")

_atr = ta.atr(period)

var upboxes = array.new<box>()
var downboxes = array.new<box>()
var toplines = array.new<line>()
var bottomlines = array.new<line>()

if high[2] < low and (low - high[2]) > _atr * multi
    b = box.new(left=bar_index -2, bottom=high[2], right=bar_index, top=low, bgcolor=upbox_color, border_width=0, extend=extend.right)
    l = line.new(bar_index -2, high[2], bar_index, high[2], color=topline_color, extend=extend.right)
    array.push(upboxes, b)
    array.push(toplines, l)

if low[2] > high and (low[2] - high) > _atr * multi    
    b = box.new(left=bar_index - 2, top=low[2], right=bar_index, bottom=high, bgcolor=downbox_color, border_width=0, extend=extend.right)
    l = line.new(bar_index -2, low[2], bar_index, low[2], color=bottomline_color, extend=extend.right)
    array.push(downboxes, b)
    array.push(bottomlines, l)
    
for i = 0 to (array.size(upboxes) == 0 ? na : array.size(upboxes) - 1)
    b = array.get(upboxes, i)
    l = array.get(toplines, i)
    if box.get_bottom(b) >= close
        line.delete(l)
        box.delete(b)
    else if box.get_bottom(b) <= close and box.get_top(b) >= close
        box.set_top(b, close)   
    else    
        array.get(upboxes, i)
        array.get(toplines, i)
        
for i = 0 to (array.size(downboxes) == 0 ? na : array.size(downboxes) - 1)
    b = array.get(downboxes, i)
    l = array.get(bottomlines, i)
    if box.get_top(b) <= close
        line.delete(l)
        box.delete(b)
    else if box.get_top(b) >= close and box.get_bottom(b) <= close
        box.set_bottom(b, close)
    else
        array.get(downboxes, i)
        array.get(bottomlines, i)
