FVG Screener (Nephew_Sam_)
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © nephew_sam_

//@version=5
indicator('FVG Screener (Nephew_Sam_)', overlay=true)

// -------------------- INPUTS --------------------
var GRP1 = "Timeframes"
timeframe1 = input.timeframe('15', title='Timeframe 1', inline='1', group=GRP1)
timeframe1_l = input.string(title='', defval='15', inline='1', group=GRP1)
timeframe1_on = input.bool(true, '', inline='1', group=GRP1)

timeframe2 = input.timeframe('30', title='Timeframe 2', inline='2', group=GRP1)
timeframe2_l = input.string(title='', defval='30', inline='2', group=GRP1)
timeframe2_on = input.bool(true, '', inline='2', group=GRP1)

timeframe3 = input.timeframe('60', title='Timeframe 3', inline='3', group=GRP1)
timeframe3_l = input.string(title='', defval='H1', inline='3', group=GRP1)
timeframe3_on = input.bool(true, '', inline='3', group=GRP1)

timeframe4 = input.timeframe('240', title='Timeframe 4', inline='4', group=GRP1)
timeframe4_l = input.string(title='', defval='H4', inline='4', group=GRP1)
timeframe4_on = input.bool(true, '', inline='4', group=GRP1)

timeframe5 = input.timeframe('D', title='Timeframe 5', inline='5', group=GRP1)
timeframe5_l = input.string(title='', defval='D', inline='5', group=GRP1)
timeframe5_on = input.bool(false, '', inline='5', group=GRP1)


var GRP2 = "FVG settings"
fvgFill = input.string(title='Filled FVG Type', defval='Close', options=['Close', 'H/L'], group = GRP2)
maxBarsback = input.int(100, 'Max bars back to find FVGs ?', minval=10, maxval=500, group = GRP2, tooltip="This will look for FVG's x bars back. The higher the number, the slower the script will run.")

var GRP3 = "UI"
theme = input.string(title='Theme Mode', defval='Dark', options=['Dark', 'Light'], group = GRP3)
position = input.string(title='Table Position', defval='Top Right', options=['Top Right', 'Bottom Right', 'Top Left', 'Bottom Left'], group = GRP3)
// -------------------- INPUTS --------------------


// -------------------- functions and formulas --------------------
getMtfData(res, i=0) => 
    request.security(
      syminfo.tickerid,
      res,
      [
      close[i+1] < low[i+2] and high[i] < low[i+2], // Bearish FVG
      close[i+1] > high[i+2] and low[i] > high[i+2], // Bullish FVG
      open[i],   high[i],   low[i],   close[i],   time[i], bar_index[i],
      open[i+1], high[i+1], low[i+1], close[i+1], time[i+1], bar_index[i+1],
      open[i+2], high[i+2], low[i+2], close[i+2], time[i+2], bar_index[i+2]
      ],
      gaps=barmerge.gaps_off,
      lookahead=barmerge.lookahead_on
      )

addToArray(_array, _val) =>
    array.push(_array, _val)

removeFromArray(_array, _index) => array.remove(_array, _index)

isFvgFilled(type, old_bi, old_h, old_l, bi, h, l, c) => // bull/bear, open, high, low, close, bar_index, fvg bar index
    isOld = bi - old_bi > maxBarsback

    type == 'bull' ?
      isOld or (fvgFill == 'Close' ? c : l) <= old_h
      : 
      isOld or (fvgFill == 'Close' ? c : h) >= old_l

isPriceInsideFvg(type, old_h, old_l, h, l, c) =>
    type == 'bull' ?
      l < old_l and (fvgFill == 'Close' ? c : l) > old_h
      :
      h > old_h and (fvgFill == 'Close' ? c : h) < old_l
// -------------------- functions and formulas --------------------


// Get All OHLC Data
[tf1_bearish_fvg, tf1_bullish_fvg, tf1_o, tf1_h, tf1_l, tf1_c, tf1_t, tf1_bi, tf1_o1, tf1_h1, tf1_l1, tf1_c1, tf1_t1, tf1_bi1, tf1_o2, tf1_h2, tf1_l2, tf1_c2, tf1_t2, tf1_bi2] = getMtfData(timeframe1)
[tf2_bearish_fvg, tf2_bullish_fvg, tf2_o, tf2_h, tf2_l, tf2_c, tf2_t, tf2_bi, tf2_o1, tf2_h1, tf2_l1, tf2_c1, tf2_t1, tf2_bi1, tf2_o2, tf2_h2, tf2_l2, tf2_c2, tf2_t2, tf2_bi2] = getMtfData(timeframe2)
[tf3_bearish_fvg, tf3_bullish_fvg, tf3_o, tf3_h, tf3_l, tf3_c, tf3_t, tf3_bi, tf3_o1, tf3_h1, tf3_l1, tf3_c1, tf3_t1, tf3_bi1, tf3_o2, tf3_h2, tf3_l2, tf3_c2, tf3_t2, tf3_bi2] = getMtfData(timeframe3)
[tf4_bearish_fvg, tf4_bullish_fvg, tf4_o, tf4_h, tf4_l, tf4_c, tf4_t, tf4_bi, tf4_o1, tf4_h1, tf4_l1, tf4_c1, tf4_t1, tf4_bi1, tf4_o2, tf4_h2, tf4_l2, tf4_c2, tf4_t2, tf4_bi2] = getMtfData(timeframe4)
[tf5_bearish_fvg, tf5_bullish_fvg, tf5_o, tf5_h, tf5_l, tf5_c, tf5_t, tf5_bi, tf5_o1, tf5_h1, tf5_l1, tf5_c1, tf5_t1, tf5_bi1, tf5_o2, tf5_h2, tf5_l2, tf5_c2, tf5_t2, tf5_bi2] = getMtfData(timeframe5)

// -------------------- Save data to arrays --------------------
var tf1_bull_indexes = array.new_int(0)
var tf1_bull_highs = array.new_float(0)
var tf1_bull_lows = array.new_float(0)
var tf1_bear_indexes = array.new_int(0)
var tf1_bear_highs = array.new_float(0)
var tf1_bear_lows = array.new_float(0)

var tf2_bull_indexes = array.new_int(0)
var tf2_bull_highs = array.new_float(0)
var tf2_bull_lows = array.new_float(0)
var tf2_bear_indexes = array.new_int(0)
var tf2_bear_highs = array.new_float(0)
var tf2_bear_lows = array.new_float(0)

var tf3_bull_indexes = array.new_int(0)
var tf3_bull_highs = array.new_float(0)
var tf3_bull_lows = array.new_float(0)
var tf3_bear_indexes = array.new_int(0)
var tf3_bear_highs = array.new_float(0)
var tf3_bear_lows = array.new_float(0)

var tf4_bull_indexes = array.new_int(0)
var tf4_bull_highs = array.new_float(0)
var tf4_bull_lows = array.new_float(0)
var tf4_bear_indexes = array.new_int(0)
var tf4_bear_highs = array.new_float(0)
var tf4_bear_lows = array.new_float(0)

var tf5_bull_indexes = array.new_int(0)
var tf5_bull_highs = array.new_float(0)
var tf5_bull_lows = array.new_float(0)
var tf5_bear_indexes = array.new_int(0)
var tf5_bear_highs = array.new_float(0)
var tf5_bear_lows = array.new_float(0)

if timeframe1_on
    if tf1_bullish_fvg
        addToArray(tf1_bull_indexes, tf1_bi)
        addToArray(tf1_bull_highs, tf1_h2)
        addToArray(tf1_bull_lows, tf1_l)
    else if tf1_bearish_fvg
        addToArray(tf1_bear_indexes, tf1_bi)
        addToArray(tf1_bear_highs, tf1_h)
        addToArray(tf1_bear_lows, tf1_l2)

if timeframe2_on
    if tf2_bullish_fvg
        addToArray(tf2_bull_indexes, tf2_bi)
        addToArray(tf2_bull_highs, tf2_h2)
        addToArray(tf2_bull_lows, tf2_l)
    else if tf2_bearish_fvg
        addToArray(tf2_bear_indexes, tf2_bi)
        addToArray(tf2_bear_highs, tf2_h)
        addToArray(tf2_bear_lows, tf2_l2)

if timeframe3_on
    if tf3_bullish_fvg
        addToArray(tf3_bull_indexes, tf3_bi)
        addToArray(tf3_bull_highs, tf3_h2)
        addToArray(tf3_bull_lows, tf3_l)
    else if tf3_bearish_fvg
        addToArray(tf3_bear_indexes, tf3_bi)
        addToArray(tf3_bear_highs, tf3_h)
        addToArray(tf3_bear_lows, tf3_l2)

if timeframe4_on
    if tf4_bullish_fvg
        addToArray(tf4_bull_indexes, tf4_bi)
        addToArray(tf4_bull_highs, tf4_h2)
        addToArray(tf4_bull_lows, tf4_l)
    else if tf4_bearish_fvg
        addToArray(tf4_bear_indexes, tf4_bi)
        addToArray(tf4_bear_highs, tf4_h)
        addToArray(tf4_bear_lows, tf4_l2)

if timeframe5_on   
    if tf5_bullish_fvg
        addToArray(tf5_bull_indexes, tf5_bi)
        addToArray(tf5_bull_highs, tf5_h2)
        addToArray(tf5_bull_lows, tf5_l)
    else if tf5_bearish_fvg
        addToArray(tf5_bear_indexes, tf5_bi)
        addToArray(tf5_bear_highs, tf5_h)
        addToArray(tf5_bear_lows, tf5_l2)
// -------------------- Save data to arrays --------------------


// -------------------- Delete filled fvgs --------------------
// Timeframe 1
if timeframe1_on
    if array.size(tf1_bull_indexes) > 0
        for i = array.size(tf1_bull_indexes)-1 to 0
            if isFvgFilled('bull', array.get(tf1_bull_indexes,i), array.get(tf1_bull_highs,i), array.get(tf1_bull_lows,i), tf1_bi, tf1_h, tf1_l, tf1_c)
                removeFromArray(tf1_bull_indexes, i)
                removeFromArray(tf1_bull_highs, i)
                removeFromArray(tf1_bull_lows, i)       
    if array.size(tf1_bear_indexes) > 0
        for i = array.size(tf1_bear_indexes)-1 to 0
            if isFvgFilled('bear', array.get(tf1_bear_indexes,i), array.get(tf1_bear_highs,i), array.get(tf1_bear_lows,i), tf1_bi, tf1_h, tf1_l, tf1_c)
                removeFromArray(tf1_bear_indexes, i)
                removeFromArray(tf1_bear_highs, i)
                removeFromArray(tf1_bear_lows, i)
            
// Timeframe 2
if timeframe2_on
    if array.size(tf2_bull_indexes) > 0
        for i = array.size(tf2_bull_indexes)-1 to 0
            if isFvgFilled('bull', array.get(tf2_bull_indexes,i), array.get(tf2_bull_highs,i), array.get(tf2_bull_lows,i), tf2_bi, tf2_h, tf2_l, tf2_c)
                removeFromArray(tf2_bull_indexes, i)
                removeFromArray(tf2_bull_highs, i)
                removeFromArray(tf2_bull_lows, i)       
    if array.size(tf2_bear_indexes) > 0
        for i = array.size(tf2_bear_indexes)-1 to 0
            if isFvgFilled('bear', array.get(tf2_bear_indexes,i), array.get(tf2_bear_highs,i), array.get(tf2_bear_lows,i), tf2_bi, tf2_h, tf2_l, tf2_c)
                removeFromArray(tf2_bear_indexes, i)
                removeFromArray(tf2_bear_highs, i)
                removeFromArray(tf2_bear_lows, i)

// Timeframe 3
if timeframe3_on
    if array.size(tf3_bull_indexes) > 0
        for i = array.size(tf3_bull_indexes)-1 to 0
            if isFvgFilled('bull', array.get(tf3_bull_indexes,i), array.get(tf3_bull_highs,i), array.get(tf3_bull_lows,i), tf3_bi, tf3_h, tf3_l, tf3_c)
                removeFromArray(tf3_bull_indexes, i)
                removeFromArray(tf3_bull_highs, i)
                removeFromArray(tf3_bull_lows, i)       
    if array.size(tf3_bear_indexes) > 0
        for i = array.size(tf3_bear_indexes)-1 to 0
            if isFvgFilled('bear', array.get(tf3_bear_indexes,i), array.get(tf3_bear_highs,i), array.get(tf3_bear_lows,i), tf3_bi, tf3_h, tf3_l, tf3_c)
                removeFromArray(tf3_bear_indexes, i)
                removeFromArray(tf3_bear_highs, i)
                removeFromArray(tf3_bear_lows, i)

// Timeframe 4
if timeframe4_on
    if array.size(tf4_bull_indexes) > 0
        for i = array.size(tf4_bull_indexes)-1 to 0
            if isFvgFilled('bull', array.get(tf4_bull_indexes,i), array.get(tf4_bull_highs,i), array.get(tf4_bull_lows,i), tf4_bi, tf4_h, tf4_l, tf4_c)
                removeFromArray(tf4_bull_indexes, i)
                removeFromArray(tf4_bull_highs, i)
                removeFromArray(tf4_bull_lows, i)       
    if array.size(tf4_bear_indexes) > 0
        for i = array.size(tf4_bear_indexes)-1 to 0
            if isFvgFilled('bear', array.get(tf4_bear_indexes,i), array.get(tf4_bear_highs,i), array.get(tf4_bear_lows,i), tf4_bi, tf4_h, tf4_l, tf4_c)
                removeFromArray(tf4_bear_indexes, i)
                removeFromArray(tf4_bear_highs, i)
                removeFromArray(tf4_bear_lows, i)

// Timeframe 5
if timeframe5_on
    if array.size(tf5_bull_indexes) > 0
        for i = array.size(tf5_bull_indexes)-1 to 0
            if isFvgFilled('bull', array.get(tf5_bull_indexes,i), array.get(tf5_bull_highs,i), array.get(tf5_bull_lows,i), tf5_bi, tf5_h, tf5_l, tf5_c)
                removeFromArray(tf5_bull_indexes, i)
                removeFromArray(tf5_bull_highs, i)
                removeFromArray(tf5_bull_lows, i)       
    if array.size(tf5_bear_indexes) > 0
        for i = array.size(tf5_bear_indexes)-1 to 0
            if isFvgFilled('bear', array.get(tf5_bear_indexes,i), array.get(tf5_bear_highs,i), array.get(tf5_bear_lows,i), tf5_bi, tf5_h, tf5_l, tf5_c)
                removeFromArray(tf5_bear_indexes, i)
                removeFromArray(tf5_bear_highs, i)
                removeFromArray(tf5_bear_lows, i)
// -------------------- Delete filled fvgs --------------------

// label.new(bar_index, high, str.tostring(array.size(tf1_bull_indexes)))

// -------------------- Check if inside fvg --------------------
tf1_inside_bull = false
tf1_inside_bear = false

tf2_inside_bull = false
tf2_inside_bear = false

tf3_inside_bull = false
tf3_inside_bear = false

tf4_inside_bull = false
tf4_inside_bear = false

tf5_inside_bull = false
tf5_inside_bear = false

// timeframe 1
if timeframe1_on
    if array.size(tf1_bull_indexes) > 0
        for i = array.size(tf1_bull_indexes)-1 to 0
            if isPriceInsideFvg('bull', array.get(tf1_bull_highs,i), array.get(tf1_bull_lows,i), tf1_h, tf1_l, tf1_c)
                tf1_inside_bull := true
    if array.size(tf1_bear_indexes) > 0
        for i = array.size(tf1_bear_indexes)-1 to 0
            if isPriceInsideFvg('bear', array.get(tf1_bear_highs,i), array.get(tf1_bear_lows,i), tf1_h, tf1_l, tf1_c)
                tf1_inside_bear := true

// timeframe 2
if timeframe2_on
    if array.size(tf2_bull_indexes) > 0
        for i = array.size(tf2_bull_indexes)-1 to 0
            if isPriceInsideFvg('bull', array.get(tf2_bull_highs,i), array.get(tf2_bull_lows,i), tf2_h, tf2_l, tf2_c)
                tf2_inside_bull := true
    if array.size(tf2_bear_indexes) > 0
        for i = array.size(tf2_bear_indexes)-1 to 0
            if isPriceInsideFvg('bear', array.get(tf2_bear_highs,i), array.get(tf2_bear_lows,i), tf2_h, tf2_l, tf2_c)
                tf2_inside_bear := true

// timeframe 3
if timeframe3_on
    if array.size(tf3_bull_indexes) > 0
        for i = array.size(tf3_bull_indexes)-1 to 0
            if isPriceInsideFvg('bull', array.get(tf3_bull_highs,i), array.get(tf3_bull_lows,i), tf3_h, tf3_l, tf3_c)
                tf3_inside_bull := true
    if array.size(tf3_bear_indexes) > 0
        for i = array.size(tf3_bear_indexes)-1 to 0
            if isPriceInsideFvg('bear', array.get(tf3_bear_highs,i), array.get(tf3_bear_lows,i), tf3_h, tf3_l, tf3_c)
                tf3_inside_bear := true

// timeframe 4
if timeframe4_on
    if array.size(tf4_bull_indexes) > 0
        for i = array.size(tf4_bull_indexes)-1 to 0
            if isPriceInsideFvg('bull', array.get(tf4_bull_highs,i), array.get(tf4_bull_lows,i), tf4_h, tf4_l, tf4_c)
                tf4_inside_bull := true
    if array.size(tf4_bear_indexes) > 0
        for i = array.size(tf4_bear_indexes)-1 to 0
            if isPriceInsideFvg('bear', array.get(tf4_bear_highs,i), array.get(tf4_bear_lows,i), tf4_h, tf4_l, tf4_c)
                tf4_inside_bear := true

// timeframe 5
if timeframe5_on
    if array.size(tf5_bull_indexes) > 0
        for i = array.size(tf5_bull_indexes)-1 to 0
            if isPriceInsideFvg('bull', array.get(tf5_bull_highs,i), array.get(tf5_bull_lows,i), tf5_h, tf5_l, tf5_c)
                tf5_inside_bull := true
    if array.size(tf5_bear_indexes) > 0
        for i = array.size(tf5_bear_indexes)-1 to 0
            if isPriceInsideFvg('bear', array.get(tf5_bear_highs,i), array.get(tf5_bear_lows,i), tf5_h, tf5_l, tf5_c)
                tf5_inside_bear := true
// -------------------- Check if inside fvg --------------------



// -------------------- Plot table --------------------
_label(_val) => _val ? " " : " "
_color(_val, _type) => _val ? _type == 'bull' ? color.lime : color.red : color.new(color.red, 100)

_color1 = theme == "Dark" ? color.white : color.black
_position = switch position
    "Top Left" => position.top_left
    "Top Right" => position.top_right
    "Bottom Left" => position.bottom_left
    => position.bottom_right

var table _table = table.new(_position, 3, 6, frame_width = 2, frame_color = _color1, border_color = _color1, border_width = 1)

if barstate.islast
    table.cell(_table, 0, 0, "Period", text_color=_color1)
    table.cell(_table, 1, 0, "Bear", text_color=_color1)
    table.cell(_table, 2, 0, "Bull", text_color=_color1)

    // Timeframe 1
    if timeframe1_on
        table.cell(_table, 0, 1, timeframe1_l, text_color=_color1)
        table.cell(_table, 1, 1, _label(tf1_inside_bear), bgcolor=_color(tf1_inside_bear, 'bear'))
        table.cell(_table, 2, 1, _label(tf1_inside_bull), bgcolor=_color(tf1_inside_bull, 'bull'))

    // Timeframe 2
    if timeframe2_on
        table.cell(_table, 0, 2, timeframe2_l, text_color=_color1)
        table.cell(_table, 1, 2, _label(tf2_inside_bear), bgcolor=_color(tf2_inside_bear, 'bear'))
        table.cell(_table, 2, 2, _label(tf2_inside_bull), bgcolor=_color(tf2_inside_bull, 'bull'))

    // Timeframe 3
    if timeframe3_on
        table.cell(_table, 0, 3, timeframe3_l, text_color=_color1)
        table.cell(_table, 1, 3, _label(tf3_inside_bear), bgcolor=_color(tf3_inside_bear, 'bear'))
        table.cell(_table, 2, 3, _label(tf3_inside_bull), bgcolor=_color(tf3_inside_bull, 'bull'))

    // Timeframe 4
    if timeframe4_on
        table.cell(_table, 0, 4, timeframe4_l, text_color=_color1)
        table.cell(_table, 1, 4, _label(tf4_inside_bear), bgcolor=_color(tf4_inside_bear, 'bear'))
        table.cell(_table, 2, 4, _label(tf4_inside_bull), bgcolor=_color(tf4_inside_bull, 'bull'))
    
    // Timeframe 5
    if timeframe5_on
        table.cell(_table, 0, 5, timeframe5_l, text_color=_color1)
        table.cell(_table, 1, 5, _label(tf5_inside_bear), bgcolor=_color(tf5_inside_bear, 'bear'))
        table.cell(_table, 2, 5, _label(tf5_inside_bull), bgcolor=_color(tf5_inside_bull, 'bull'))
// -------------------- Plot table --------------------