Fair Value Gap Finder
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © sonnyparlin

//@version=5
// 5/20/2023 4:00pm updated chart image

indicator("Fair Value Gap Finder", overlay = true)
useVolume = input.bool(true, "Use Volume to determine FVGs (Recommended)")
vr = input.int(2, "Volume must be X times average", step=1)
vl = input.int(20, "Volume moving average length", step=1)
ol = input.int(60, "Gap length", step=10)
emaLength = input.int(20, "EMA Length", step=1)
minGapSize = input.float(0.25, "Minimum Gap Size to show", step=0.01)
ob = volume[1] > ta.sma(volume[1], vl) * vr

sellFVGColor = input.color(color.new(color.red, 70))
buyFVGColor = input.color(color.new(color.green, 70))
buyFVGText = input.string("Buyers Fair Value Gap")
sellFVGText = input.string("Sellers Fair Value Gap")
textColor = input.color(color.new(color.black, 10))
sizeOption = input.string(title="Label Size",
     options=["Auto", "Huge", "Large", "Normal", "Small", "Tiny"],
     defval="Small")

labelSize = (sizeOption == "Huge") ? size.huge :
     (sizeOption == "Large") ? size.large :
     (sizeOption == "Small") ? size.small :
     (sizeOption == "Tiny") ? size.tiny :
     (sizeOption == "Auto") ? size.auto :
         size.normal

// initialize variables
ema = ta.ema(close, emaLength)
var buyVolume = 0.0
var sellVolume = 0.0
buyVolume := (high[1]==low[1]) ? 0 : volume[1] *  (close[1]-low[1])  / (high[1]-low[1])
sellVolume := (high[1]==low[1]) ? 0 : volume[1] * (high[1]-close[1]) / (high[1]-low[1])

if useVolume
    if ob and buyVolume > sellVolume and high[2] < low and low - high[2] > minGapSize and close[1] > ema
        box.new(bar_index, high[2], bar_index + ol, low, border_color = color.new(color.black,100), bgcolor = buyFVGColor, text=buyFVGText, text_color = textColor, text_size = labelSize, text_halign = text.align_right)

    if ob and buyVolume < sellVolume and low[2] > high and low[2] - high > minGapSize and close[1] < ema
        box.new(bar_index, low[2], bar_index + ol, high, border_color = color.new(color.black,100), bgcolor = sellFVGColor, text=sellFVGText, text_color = textColor, text_size = labelSize, text_halign = text.align_right)
else
    if high[2] < low and low - high[2] > minGapSize and close[1] > ema
        box.new(bar_index, high[2], bar_index + ol, low, border_color = color.new(color.black,100), bgcolor = buyFVGColor, text=buyFVGText, text_color = textColor, text_size = labelSize, text_halign = text.align_right)

    if low[2] > high and low[2] - high > minGapSize and close[1] < ema
        box.new(bar_index, low[2], bar_index + ol, high, border_color = color.new(color.black,100), bgcolor = sellFVGColor, text=sellFVGText, text_color = textColor, text_size = labelSize, text_halign = text.align_right)