FVG w/ Fibs [QuantVue]
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © QuantVue

//@version=5
indicator("FVG w/ Fibs [QuantVue]", overlay = true, max_boxes_count = 250, max_lines_count = 500)

//----------settings----------//
bullCol         = input.color(color.new(color.lime,85), 'Bullish Color', inline = '1')
bearCol         = input.color(color.new(color.red,85), 'Bearish Color', inline = '1')
minGap          = input.float(.1, 'Minimum FVG %', minval = .01, step = .01, inline = '2')
tooLongBool     = input.bool(true, 'Stop Drawing Box After', inline = '3')
tooLong         = input.int(60, ' ', inline = '3')
removeOld       = input.bool(true, 'Hide Boxes That Are Too Long', inline = '4')

var g1 = 'Filled Gaps'
mitType         = input.string('Close', 'Mitigation Type', ['Close', 'Wicks'], group = g1, inline = '1')
removeFilled    = input.bool(true, 'Remove Filled Gaps', group = g1, inline = '2')
filledBorder    = input.bool(true, 'Changed Filled FVG Box Border', group = g1, inline = '3') 
borderStyle     =  input.string('Dashed', 'Filled Border ', options = ['Dotted', 'Dashed', 'Solid'],  inline = '4', group = g1)
borderCol       = input.color(color.gray, ' ', inline = '4', group = g1)

var g2 = 'Fibs'
show_50     = input.bool(true, '', inline = 'Level1', group = g2)
value_50    = input.float(0.5, '', inline = 'Level1', group = g2)
color_50    = input.color(#c2c5ce, '', inline = 'Level1', group = g2)
style_50    = input.string('Solid', ' ', options = ['Dotted', 'Dashed', 'Solid'],  inline = 'Level1', group = g2)
show_618    = input.bool(true, '', inline = 'Level2', group = g2)
value_618   = input.float(0.618, '', inline = 'Level2', group = g2)
color_618   = input.color(#00ccff, '', inline = 'Level2', group = g2)
style_618   = input.string('Solid', ' ', options = ['Dotted', 'Dashed', 'Solid'],  inline = 'Level2', group = g2)

var g3 = 'Clean Up'
activeBoxes = input.int(20, 'Maximum Number of Gaps to Update', group = g3, inline = '1')

//----------udt----------//
type FVG
    box b
    bool a = true
    bool bull = true
    line f
    line s

//----------variables----------//
var bearFvg = array.new<FVG>()
var bullFvg = array.new<FVG>()

//----------methods----------//
method switcher(string this)=>
    switch this
        'Dashed' => line.style_dashed
        'Dotted' => line.style_dotted
        'Solid' => line.style_solid

method run(array<FVG> this)=>
    for [idx,fvg] in this 
        src = mitType == 'Close' ? close : fvg.bull ? low : high
        if fvg.a
            fvg.b.set_right(bar_index)
            fvg.f.set_x2(bar_index)
            fvg.s.set_x2(bar_index) 
            if fvg.b.get_right() - fvg.b.get_left() > tooLong and tooLongBool
                fvg.a := false
                if removeOld 
                    fvg.b.delete()
                    fvg.f.delete()
                    fvg.s.delete()
            if (src <= fvg.b.get_bottom() and barstate.isconfirmed and fvg.bull) or (src >= fvg.b.get_top() and barstate.isconfirmed and not fvg.bull) 
                fvg.a := false 
                alert(fvg.bull ? 'Bullish FVG Filled' : 'Bearish FVG Filled', alert.freq_once_per_bar_close) 
                if filledBorder 
                    fvg.b.set_border_color(borderCol) 
                    fvg.b.set_border_style(borderStyle.switcher()) 
                if removeFilled 
                    fvg.b.delete()
                    fvg.f.delete()
                    fvg.s.delete()
        if not fvg.a
            this.remove(idx)

//----------conditions & calculations----------//
bullishFVG  = low > high[2] and close[1] > high[2] and ((low - high[2]) / high[2] * 100) >= minGap
bearishFVG  = high < low[2] and close[1] < low[2] and ((low[2] - high) / high * 100) >= minGap
fiddy       = bullishFVG ? low - value_50 * (low - high[2]) : high + value_50 * (low[2] - high)
sixOneEight = bullishFVG ? low - value_618 * (low - high[2]) : high + value_618 * (low[2] - high)

//----------find fvgs and store data----------//
if bullishFVG
    if bullFvg.size() > activeBoxes -1
        bullFvg.pop()
        bullFvg.unshift(FVG.new(box.new(bar_index[2], low, bar_index, high[2], bullCol, bgcolor = bullCol), f = show_50 ? line.new(bar_index[2], fiddy, bar_index, fiddy, style = style_50.switcher(), color= color_50) : na, s = show_618 ? line.new(bar_index[2], sixOneEight, bar_index, sixOneEight, style = style_618.switcher(), color = color_618) : na))
    else
        bullFvg.unshift(FVG.new(box.new(bar_index[2], low, bar_index, high[2], bullCol, bgcolor = bullCol), f = show_50  ? line.new(bar_index[2], fiddy, bar_index, fiddy, style = style_50.switcher(), color= color_50) : na, s = show_618  ? line.new(bar_index[2], sixOneEight, bar_index, sixOneEight, style = style_618.switcher(), color = color_618) : na))
if bearishFVG
    if bearFvg.size() > activeBoxes -1
        bearFvg.pop()
        bearFvg.unshift(FVG.new(box.new(bar_index[2], low[2], bar_index + 1, high, bearCol, bgcolor = bearCol),bull = false, f = show_50  ? line.new(bar_index[2], fiddy, bar_index, fiddy, style = style_50.switcher(), color = color_50) : na, s = show_618  ? line.new(bar_index[2], sixOneEight, bar_index, sixOneEight, style = style_618.switcher(), color = color_618) : na))
    else
        bearFvg.unshift(FVG.new(box.new(bar_index[2], low[2], bar_index + 1, high, bearCol, bgcolor = bearCol),bull = false, f = show_50  ? line.new(bar_index[2], fiddy, bar_index, fiddy, style = style_50.switcher(), color = color_50) : na, s = show_618  ? line.new(bar_index[2], sixOneEight, bar_index, sixOneEight, style = style_618.switcher(), color = color_618) : na))

//----------run the code----------//
bearFvg.run()
bullFvg.run()
