Indicator · Pine Script v6 · On the chart

Fair Value Gaps

by lunarticktrading· code credited to gambcl

This overlay indicator marks fair value gaps and inverse fair value gaps as boxes on the price chart.

View on GitHub

GitHub stars7on the repository
Pine versionv6current
Lines of code216
Settings19inputs
LicenceNone statedfile: MPL-2.0
Last update2 weeks ago10 Oct 2026

Add It to Your TradingView Chart

  1. 1Copy the scriptPress Copy script above, or the copy button on the code below.
  2. 2Open the Pine EditorOpen a TradingView chart and choose Pine Editor at the bottom of the screen.
  3. 3Paste over the templateCreate a new indicator, select all of the template text and paste. Press Save and give it a name.
  4. 4Add it to the chartPress Add to chart, then adjust the settings with the gear icon next to its name.

Source Code

216 lines of Pine Script v6 from Fair Value Gaps.txt, published under MPL-2.0 (file header). Keep the author's credit and licence lines when you reuse it.

Fair Value Gaps.txt
// This Pine Script® code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © gambcl

//@version=6

var MAX_BOXES = 500

indicator("Fair Value Gaps", overlay=true, max_boxes_count = MAX_BOXES)


////////////////////////////////////////////////////////////////////////////////////////////////////
// Version History
////////////////////////////////////////////////////////////////////////////////////////////////////
// v1.1.0
// - Show optional border
// - Show optional 50% line
// - Show optional label
// v1.0.0
// - Initial release
////////////////////////////////////////////////////////////////////////////////////////////////////


////////////////////////////////////////////////////////////////////////////////
// Constants
////////////////////////////////////////////////////////////////////////////////

var FVG_GROUP = "FAIR VALUE GAPS"
var IFVG_GROUP = "INVERSE FAIR VALUE GAPS"
var DISPLAY_GROUP = "DISPLAY"
var DEVELOPER_GROUP = "DEVELOPER"


////////////////////////////////////////////////////////////////////////////////
// Enums
////////////////////////////////////////////////////////////////////////////////

enum Direction
    bullish
    bearish

enum FVGType
    FVG
    IFVG


////////////////////////////////////////////////////////////////////////////////
// Inputs
////////////////////////////////////////////////////////////////////////////////

FVGType i_fvg_mode = input.enum(FVGType.FVG, "Mode")

color i_bullish_fvg_color = input.color(color.green, "Bullish FVG", group = FVG_GROUP)
color i_bearish_fvg_color = input.color(color.red, "Bearish FVG", group = FVG_GROUP)

bool i_require_fvg_bars_same_direction = input.bool(false, "Require FVG bars same direction", tooltip = "Specifies if all three FVG bars must be in the same direction.", group = FVG_GROUP)

bool i_enable_max_length_bars = input.bool(true, "Max length", tooltip = "Maximum length of FVG in bars.", inline = "Max bars", group = FVG_GROUP)
int i_max_length_bars = input.int(20, "", minval = 1, inline = "Max bars", group = FVG_GROUP)

bool i_enable_min_fvg_size_ticks = input.bool(true, "Minimum size", tooltip = "Minimum size of the FVG in ticks.", inline = "Minimum size", group = FVG_GROUP)
int i_min_fvg_size_ticks = input.int(20, "", minval = 1, inline = "Minimum size", group = FVG_GROUP)

bool i_enable_max_fvg_size_ticks = input.bool(true, "Maximum size", tooltip = "Maximum size of the FVG in ticks.", inline = "Maximum size", group = FVG_GROUP)
int i_max_fvg_size_ticks = input.int(200, "", minval = 1, inline = "Maximum size", group = FVG_GROUP)

color i_bullish_ifvg_color = input.color(color.aqua, "Bullish IFVG", group = IFVG_GROUP)
color i_bearish_ifvg_color = input.color(color.fuchsia, "Bearish IFVG", group = IFVG_GROUP)

bool i_remove_obsolete_fvg = input.bool(true, "Remove obsolete FVG", group = IFVG_GROUP)

bool i_show_midline = input.bool(false, "Show 50% line", display = display.none, group = DISPLAY_GROUP)
bool i_show_border = input.bool(false, "Show border", display = display.none, group = DISPLAY_GROUP)
bool i_show_label = input.bool(false, "Show label", display = display.none, group = DISPLAY_GROUP)
int i_line_transparency = input.int(30, "Line Transparency", minval = 0, maxval = 100, display = display.none, group = DISPLAY_GROUP)
int i_bg_transparency = input.int(60, "Background Transparency", minval = 0, maxval = 100, display = display.none, group = DISPLAY_GROUP)

enum VersionEnum
    version = "v1.1.0"
    
VersionEnum i_version = input.enum(VersionEnum.version, "Version", display = display.none, group = DEVELOPER_GROUP)


////////////////////////////////////////////////////////////////////////////////
// Objects
////////////////////////////////////////////////////////////////////////////////

type FVG
    FVGType type
    Direction direction
    int start_bar_index
    float top
    float bottom
    bool active = true
    box fvg_box = na
    line mid_line = na


////////////////////////////////////////////////////////////////////////////////
// Methods
////////////////////////////////////////////////////////////////////////////////

method update_fvg_box(FVG self) =>
    if na(self.fvg_box)
        color border_color = color.new(self.direction == Direction.bullish ? i_bullish_fvg_color : i_bearish_fvg_color, i_line_transparency)
        color bg_color = color.new(self.direction == Direction.bullish ? i_bullish_fvg_color : i_bearish_fvg_color, i_bg_transparency)
        self.fvg_box := box.new(self.start_bar_index - 1, self.top, self.start_bar_index + 1, self.bottom, i_show_border ? border_color : color.new(border_color, 100), 1, line.style_solid, extend.none, xloc.bar_index, bg_color, i_show_label ? "FVG" : na, size.auto, border_color, text.align_center, text.align_center)
        if i_show_midline
            mid_price = (self.top + self.bottom) / 2.0
            self.mid_line := line.new(self.start_bar_index - 1, mid_price, self.start_bar_index + 1, mid_price, xloc.bar_index, extend.none, border_color, line.style_dashed, 1, true)

method delete_fvg(FVG self) =>
    if not na(self.fvg_box)
        box.delete(self.fvg_box)
        self.fvg_box := na
    if not na(self.mid_line)
        line.delete(self.mid_line)
        self.mid_line := na

method extend(FVG self, int right_bar_index) =>
    if self.active and not na(self.fvg_box)
        self.fvg_box.set_right(right_bar_index)
        if i_show_midline
            self.mid_line.set_x2(right_bar_index)
        if i_enable_max_length_bars and (right_bar_index - self.start_bar_index) == i_max_length_bars
            self.active := false

method invert(FVG self) =>
    if self.type == FVGType.FVG
        self.type := FVGType.IFVG
        self.direction := (self.direction == Direction.bullish) ? Direction.bearish : Direction.bullish
        color bg_color = color.new(self.direction == Direction.bullish ? i_bullish_ifvg_color : i_bearish_ifvg_color, i_bg_transparency)
        color border_color = color.new(self.direction == Direction.bullish ? i_bullish_ifvg_color : i_bearish_ifvg_color, i_line_transparency)
        self.fvg_box.set_bgcolor(bg_color)
        self.fvg_box.set_border_color(i_show_border ? border_color : color.new(border_color, 100))
        self.fvg_box.set_text_color(border_color)
        if i_show_midline
            self.mid_line.set_color(border_color)
        if i_show_label
            self.fvg_box.set_text("IFVG")


////////////////////////////////////////////////////////////////////////////////
// State
////////////////////////////////////////////////////////////////////////////////

var fvg_array = array.new<FVG>(MAX_BOXES)


////////////////////////////////////////////////////////////////////////////////
// Functions
////////////////////////////////////////////////////////////////////////////////

is_bullish(int bars_ago) =>
    close[bars_ago] > open[bars_ago]

is_bearish(int bars_ago) =>
    close[bars_ago] < open[bars_ago]

remove_inactive_fvg() =>
    clean_fvg_array = array.new<FVG>(MAX_BOXES)
    if fvg_array.size() > 0 
        for i = 0 to (fvg_array.size() - 1)
            curr_fvg = fvg_array.get(i)
            if not na(curr_fvg)
                if curr_fvg.type == FVGType.FVG and not curr_fvg.active
                    // Found obsolete FVG, remove its box and do NOT add to result array.
                    curr_fvg.delete_fvg()
                else
                    clean_fvg_array.shift()
                    clean_fvg_array.push(curr_fvg)
    clean_fvg_array


////////////////////////////////////////////////////////////////////////////////
// Entry Signals
////////////////////////////////////////////////////////////////////////////////


if barstate.isnew and bar_index > 2
    // Update/extend existing active FVGs
    for i = 0 to fvg_array.size() - 1
        curr_fvg = fvg_array.get(i)
        // Only process active FVGs
        if not na(curr_fvg) and curr_fvg.active
            // Extend active FVGs
            curr_fvg.extend(bar_index - 1)
            // Check to see if active FVG has been breached
            if curr_fvg.type == FVGType.FVG
                if (curr_fvg.direction == Direction.bullish and close[1] < curr_fvg.bottom) or (curr_fvg.direction == Direction.bearish and close[1] > curr_fvg.top)
                    if i_fvg_mode == FVGType.IFVG
                        curr_fvg.invert()
                        alert((curr_fvg.direction == Direction.bullish ? "Bullish" : "Bearish") +  " IFVG created")
                    else
                        curr_fvg.active := false
    // Cleanup obsolete FVGs
    if i_fvg_mode == FVGType.IFVG and fvg_array.size() > 0 and i_remove_obsolete_fvg
        fvg_array := remove_inactive_fvg()

    // Check for new bullish FVGs
    FVG new_fvg = na
    bullish_fvg_size_ticks = (low[1] - high[3]) / syminfo.mintick
    if is_bullish(2) and ((not i_enable_min_fvg_size_ticks) or (i_enable_min_fvg_size_ticks and bullish_fvg_size_ticks >= i_min_fvg_size_ticks)) and ((not i_enable_max_fvg_size_ticks) or (i_enable_max_fvg_size_ticks and bullish_fvg_size_ticks <= i_max_fvg_size_ticks)) and ((not i_require_fvg_bars_same_direction) or (i_require_fvg_bars_same_direction and is_bullish(3) and is_bullish(1)))
        new_fvg := FVG.new(FVGType.FVG, Direction.bullish, bar_index[2], low[1], high[3])
    // Check for new bearish FVGs
    bearish_fvg_size_ticks = (low[3] - high[1]) / syminfo.mintick
    if is_bearish(2) and ((not i_enable_min_fvg_size_ticks) or (i_enable_min_fvg_size_ticks and bearish_fvg_size_ticks >= i_min_fvg_size_ticks)) and ((not i_enable_max_fvg_size_ticks) or (i_enable_max_fvg_size_ticks and bearish_fvg_size_ticks <= i_max_fvg_size_ticks)) and ((not i_require_fvg_bars_same_direction) or (i_require_fvg_bars_same_direction and is_bearish(3) and is_bearish(1)))
        new_fvg := FVG.new(FVGType.FVG, Direction.bearish, bar_index[2], low[3], high[1])

    // Remove oldest FVG before drawing new one
    if not na(new_fvg)
        alert((new_fvg.direction == Direction.bullish ? "Bullish" : "Bearish") +  " FVG created")
        dead_fvg = fvg_array.shift()
        if not na(dead_fvg)
            dead_fvg.delete_fvg()
        fvg_array.push(new_fvg)
        new_fvg.update_fvg_box()

Overview

A mode switch selects standard gaps or inverse gaps, with separate bullish and bearish colors. Optional filters require the three gap bars to share one direction, limit how long a gap stays, and drop gaps outside a minimum or maximum size in ticks. Obsolete gaps can be removed. Display options add a 50 percent midline, a border, and a label, and set line and background transparency. It does not generate trade entries or exits.

Details

Published by

lunarticktrading on GitHub

Code credit

gambcl, as written in the script's header

Draws

On the price chart

Markets

Any symbol

Timeframes

Any timeframe

Risk Notes

No repainting, lookahead or stacked entries were found in its code or README. That says nothing about how well it works: test it first.

Settings

The inputs you can change from the gear icon on the chart. Defaults are the author's.

SettingTypeDefaultVariable
ModeenumFVGType.FVGi_fvg_mode
Bullish FVGcolorcolor.greeni_bullish_fvg_color
Bearish FVGcolorcolor.redi_bearish_fvg_color
Require FVG bars same directionboolfalsei_require_fvg_bars_same_direction
Max lengthbooltruei_enable_max_length_bars
i_max_length_barsint20i_max_length_bars
Minimum sizebooltruei_enable_min_fvg_size_ticks
i_min_fvg_size_ticksint20i_min_fvg_size_ticks
Maximum sizebooltruei_enable_max_fvg_size_ticks
i_max_fvg_size_ticksint200i_max_fvg_size_ticks
Bullish IFVGcolorcolor.aquai_bullish_ifvg_color
Bearish IFVGcolorcolor.fuchsiai_bearish_ifvg_color
Show all 19 settings
SettingTypeDefaultVariable
Remove obsolete FVGbooltruei_remove_obsolete_fvg
Show 50% lineboolfalsei_show_midline
Show borderboolfalsei_show_border
Show labelboolfalsei_show_label
Line Transparencyint30i_line_transparency
Background Transparencyint60i_bg_transparency
VersionenumVersionEnum.versioni_version
Third-party code. ForexR did not write, test or endorse this script, and the summary above was generated automatically from its code and README. Indicators describe the past, and a strategy's backtest can look better than live trading, especially when a script repaints. Check it in the Strategy Tester and on a demo account before you rely on it.

Similar Pine Scripts

ICT Equal Highs and Lows

by ArunKBhaskar
575 stars

This overlay indicator finds pivot highs and lows on the price chart and compares the last two highs and the last two lows. When the percentage difference between a pair is below the Equal HL threshold, it treats them as equal levels and draws a box. Left and

Indicator v5 SMC / ICT / price actionSupport & resistance
Updated 1 year ago · MPL-2.0 GitHub repository of ICT Equal Highs and Lows

DE-tracker

by Allen1212
303 stars

This indicator plots labels on the TradingView price chart to mark ARK Invest's buy and sell trades for the DE stock. Buy transactions appear in green with X1 or X2 multipliers showing the number of ARK ETFs involved on the same day; sells appear in red. The m

Indicator v4 Support & resistanceSMC / ICT / price action
Updated 2 years ago · None stated GitHub repository of DE-tracker

This Pine Script indicator plots a ZigZag on the price chart. It identifies reversal points when price moves more than a set percentage from the last pivot. The script calculates forecasts using zigzag data and labels detected geometric patterns including harm

Indicator v4 TrendSupport & resistance

Golden Bullet Strategy

by TradersPost
228 stars

The Golden Bullet Strategy is an overlay signal indicator based on Smart Money Concepts and time-based liquidity models. It identifies liquidity sweeps of a designated reference session range during a specified hunt window. It then confirms Market Structure Sh

Indicator v6 SMC / ICT / price actionSessions & time
Updated 3 months ago · None stated GitHub repository of Golden Bullet Strategy

Open Source Fractal

by cantolab
183 stars

This indicator implements the Fractal Model concept to plot market structure shifts, liquidity sweeps, and Change in State of Delivery (CISD) levels. It overlays custom higher-timeframe candle previews, open prices, and time markers directly on the price chart

Indicator v6 SMC / ICT / price actionSupport & resistance
Updated 2 months ago · MIT GitHub repository of Open Source Fractal

Swing Failure Signals

by Ganador1
154 stars

This indicator calculates pivot highs and pivot lows to detect liquidity sweeps and Swing Failure Patterns. It identifies when price breaks past recent key swing highs or lows within a configurable historical window, then looks for a quick reversal or change i

Indicator v6 SMC / ICT / price actionSupport & resistance
Updated 2 months ago · Apache-2.0 GitHub repository of Swing Failure Signals

More SMC / ICT scripts

Related on ForexR

Trade Your Charts With a Regulated Broker

Compare brokers that connect to TradingView, with spreads, minimum deposits and leverage side by side.

Compare brokers