FVG Sniper [JOAT]═══ FVG SNIPER ═══
A complete Fair Value Gap engine that finds price imbalances, grades their quality, tracks how they fill, mitigate and invert, and then paints a full trade blueprint the moment a clean setup fires. One gap is spotlighted as the strongest, and every signal arrives with entry, three targets, a stop, and colored risk/reward zones — no arrows, no clutter.
▎ WHAT IT DOES
FVG Sniper detects three-candle fair value gaps (imbalances), scores each one from 0–10, and monitors its life cycle: how much of the gap has been filled, whether it has been mitigated (wick-tapped through), and whether price has closed fully through it to flip its role into an Inverted FVG (IFVG) . When a graded gap produces a rejection or an IFVG flip that agrees with the higher-timeframe bias, it draws a structured trade plan and reports the whole picture in a dashboard.
▎ HOW IT WORKS
• Gap detection — a bullish gap forms when the current low sits above the high from two bars back; a bearish gap forms when the current high sits below the low from two bars back.
• Quality filters — each candidate must clear a minimum gap size (as a multiple of ATR ) and a minimum displacement body ratio on the impulse candle, so tiny or weak imbalances are ignored.
• Grade (0–10) — blends gap size, the displacement range of the middle candle, and relative volume into a single score. Only gaps at or above your minimum grade may fire a signal.
• Fill & mitigation — the engine tracks the running extreme inside each gap to compute a live fill percentage, and marks a gap mitigated once a wick fully traverses it.
• Inversion (IFVG) — when price closes fully through a gap, its role flips; the box restyles to a dashed amber accent and the flip is logged.
• Signals — two sources you can mix or isolate: Rejection (price retraces into a live gap and reacts back out with a directional close) and IFVG Flip (a mitigated gap is closed through, confirming continuation).
• HTF bias filter — an optional higher-timeframe EMA bias must agree with the signal direction before it is allowed.
• Trade model — on a fresh signal it sets entry at close, a stop either gap-protected (just beyond the triggering gap boundary) or ATR-based, with risk clamped between a floor and a cap. Targets TP1/TP2/TP3 are placed at your chosen R multiples.
• Non-repainting — all detection, scoring and signals evaluate on confirmed (closed) bars only, and the HTF request uses no lookahead.
▎ HOW TO USE IT
• Trade in the direction of the BUY / SELL pill. The stars and score on the pill show the grade of the gap that triggered it.
• The entry line (chrome), dashed stop , and TP1/TP2/TP3 lines map the plan directly on the chart; level labels on the right print exact prices and R values.
• The green zone is the target/reward area from entry to TP3; the red zone is the risk area between entry and stop — a fast visual read of the trade's R:R.
• A single ★ spotlight tags only the strongest active gap, so you always know the best imbalance in view.
• Use live gaps as decision zones: watch the fill % of the nearest gap, and treat an IFVG flip as a shift in short-term control.
• When a trade closes, a result label prints the outcome (TP hit, stop, or exit at R) so completed setups stay readable.
• Combine with your own structure, session and news context — the gap engine locates the where , you confirm the when .
▎ KEY SETTINGS
• Engine — enable bullish/bearish detection, choose the signal source (Rejection, IFVG Flip, or both), and cap how many gaps stay visible plus their lifetime and box extension.
• Filters — ATR length, minimum gap size, minimum displacement body ratio, minimum grade, the HTF bias filter (timeframe + EMA length), and whether a directional rejection close is required.
• Trade Model — stop basis (Gap-Protected vs ATR), stop buffer/distance, risk floor and cap, TP1–TP3 in R, max trade duration, zone projection, and how many completed trades to keep.
• Visuals — toggle gap boxes, midline, hide-mitigated declutter, grade spotlight, IFVG styling, signal pills, zone boxes, lines, level and result labels, zone-reader candle coloring, optional VWAP + σ bands, and all colors/transparency/sizes.
• Dashboard — show/hide, position, text size, and dark or light panel.
▎ DASHBOARD
The on-chart panel reports: HTF bias, count of active bullish and bearish gaps, the nearest gap price and its fill %, the strongest gap's star grade, the last IFVG flip (with bar age), the active signal, any live trade with its entry, and running totals of bullish / bearish / inverted gaps detected.
▎ ALERTS
• BUY signal
• SELL signal
• Bullish IFVG Flip (inversion up)
• Bearish IFVG Flip (inversion down)
▎ NOTES
• Works on all timeframes and all assets — indices, forex, crypto, stocks, futures.
• Signals and drawings are computed on closed bars, so they do not repaint after the bar confirms.
• Object caps and hide-mitigated / declutter toggles keep the chart clean even on long histories.
• Any on-chart result labels reflect historical signals only and are illustrative, not a performance guarantee.
For research and education only. This is not financial advice. No indicator can predict the future, and past behavior does not guarantee future results — always manage your own risk.
Made with passion by JackOfAllTrades ⚡
Indicator

Indicator

PD ArraysHi all!
This indicator is based on my indicator 'Order blocks' () that will show you order blocks (OB) found by the indicator or the once that are in alignment with the current trend.
This indicator will, however, not only show you order blocks but it will also find fair value gaps (FVG). Order blocks and fair value gaps are popular and a big part of inner circle trading (ICT). The true power lies in that the indicator will give you alerts and show you labels for retest ('R'), false breakouts ('FB') and breakouts ('B'). This is possible through my library 'Touched' (). The possibilities of interactions in the form of breakouts allows for the findings of broken order blocks and fair value gaps. That means that this indicator allows the showing of zones that are before the CHoCH/CHoCH+ and has flipped function. So a support becomes resistance and vice versa. These zones are popular and are called breaker blocks (BB, a flipped order block) and inversion fair value gap (IFVG, a flipped fair value gap). If a broken order block is before a BOS (instead of a CHoCH/CHoCH+) it's called a mitigation block (MB) instead of a breaker block, but it has the same function.
So, broken order blocks are called breaker blocks (BB) if they're before a change of character (CHoCH/CHoCH+) and mitigation blocks (MB) if they're before a break of structure (BOS).
Broken fair value gaps are called inversion fair value gaps (IFVG). The following zones will be displayed by the indicator:
• Fair value gaps
• Inversion fair value gaps
• Order blocks
• Breaker blocks
• Mitigation blocks
The trend is based on price action that creates change of characters (CHoCH/CHoCH+) and break of structures (BOS). This is based on pivots/swings with your set length for left and right and is possible through my script 'PriceAction' (). The market structure will be displayed with solid lines and a label showing the type (CHoCH/CHoCH+/BOS).
2 things can invalidate a zone and cause it to disappear;
• broken by price or
• a CHoCH/CHoCH+ appears to start a new trend.
I.e. a bullish zone (OB/FVG/BB/MB/IFVG) will disappear upon the closing price being lower than the zone's low or a bearish CHoCH/CHoCH+ happens. A bullish BB/MB/IFVG means a bearish OB/FVG that has been broken by price and is now bullish.
I've tried to make the ability to find zones to be on a different timeframe than chart (like in my script 'Order blocks') but I have not found it to be reliable yet, so the zones are found on the chart's timeframe. I will keep working on making it more reliable, but for now it's only possible to find them on the chart's timeframe.
The default settings will show you all zones (OB/FVG) and their broken version (BB/MB/IFVG). If the trend is bullish it will show bullish OBs and bullish FVGs and bearish OBs/FVGs that are broken and now are bullish (BB/MB/IFVG), and vice versa. OBs and FVGs will be displayed as soon as they are found, IFVGs when it's broken by price and BBs/MBs upon the next structural break (CHoCH/CHoCH+/BOS). All zones within a CHoCH/CHoCH+ (from the high/low pivot that's broken to when it's broken by price) will be kept to be take action on by the script's code. They're hidden until they make sense regarding to the new trend that's determined by the 'PriceAction' library.
Settings
• Keep history
Check this if you want old zones to be kept (from previous trends). They are removed if they are broken or a CHoCH/CHoCH+ appears.
PD ARRAYS
• Fair value gaps
Show fair value gaps or not.
• Inversion fair value gaps
Show inversion fair value gaps or not.
• Order blocks
Show order blocks or not.
• Breaker blocks
Show breaker blocks or not.
• Mitigation blocks
Show mitigation blocks or not.
FAIR VALUE GAPS
• Consecutive rising/falling
The candles in the reaction must consecutivly rise or fall (the 'hl2' must be rising/falling).
• Force strong
If this is enabled it will force the FVG middle candle to have a higher/lower 'hl2' (middle of the entire candle) than the first candle's high.
• Hide consecutive zones
If multiple fair value gaps are found after each other only the first one will be found by the indicator.
• Minimum size
A factor of the Average True Range (of length 14) that the size of the fair value gap must have.
ORDER BLOCKS
• Reaction
A factor of the Average True Range (of length 14) that the total reaction must have. A higher value will create fewer zones with a bigger reaction. And check the checkbox if you want the limit to be displayed.
• Take out
The bar that start the reaction must take out the previous bar high/low (liquidity sweep).
• Consecutive rising/falling
The candles in the reaction must consecutivly rise or fall.
• Fair value gap
The middle bar in the order block must create a fair value gap.
• Hide consecutive zones
If multiple order blocks are found after each other only the first one will be found by the indicator.
DISPLAY
• Bull
The color for bullish zones (OB or FVG). This is the color before a breakout from the price, if it's broken by price once its a bearish zone instead.
• Bear
The color for bearish zones (OB or FVG). This is the color before a breakout from the price, if it's broken by price once its a bullish zone instead.
MARKET STRUCTURE
• Enable
If zones found should follow market structure or not. This is automatically enabled if 'Current trend' is true.
• Pivot
Set the length of pivots and check if they should be shown or not.
• Font size
Set the font size of market structure text.
ALERT
• Retests
Enable alerts for retest.
• False breakouts
Enable alerts for false breakouts.
• Breakouts
Enable alerts for breakouts.
Examples
Below will be some examples of how the indicator behaves. All the examples are with the default settings but only the example zone is visible.
• This demonstrates a retest of an inversion fair value gap after a CHoCH+. After price goes higher (after that support) price retests later IFVGs and goes even higher.
• Shows the lowest bullish fair value gap that's retested two times and goes higher. On the journey of higher prices more FVGs are retested/has false breakouts and price goes higher.
• Shows a bearish order block (at the top) that's retested and price goes lower.
• Shows a bearish breaker block that has two retests and a false breakout. The origin is a bullish order block that's now (after price has broken it) a bearish breaker block. After that resistance price goes lower.
• Shows a retest of a bullish mitigation block (that's a broken bearish order block).
The code for finding these PD Arrays are extracted to my library 'PDArrays' ().
I hope that this indicator will help you in your trading and I've been trying to make an indicator like this for a very long time. Many new tries, a lot of time spent and lots of lines of code I managed to make one that I think is good enough!
If you have any findings of unexpected behavior or feature of, feel free to reach out!
Best of luck trading! Indicator

PDArraysLibrary "PDArrays"
Hi all!
This library will help you to draw fair value gaps and order blocks and their broken version; breaker blocks, mitigation blocks and inversion fair value gaps.
It does not contain any example code, but I will create an indicator called 'PD Arrays' that uses this library.
Best of luck trading!
Remove(zones, settings)
Removes the zone in 'zones.Remove' and its visuals. The visuals will be kept if 'settings.KeepHistoryZones' is true.
Parameters:
zones (Zones) : The current zone.
settings (Settings) : Set all values in this parameter to define the settings for the zones.
Interactions(zones, settings, trend)
Sets the interactions (retests\false breakouts\breakouts) from the library 'Touched'.
Parameters:
zones (array)
settings (Settings) : set all values in this parameter to define the settings for the order block creation.
trend (int) : the market structure trend that's used for the integrations direction. 1 = bullish, -1 = bearish, 0 = both.
HiddenInteractions(zones, settings, marketStructureInfo, trend)
Sets the hidden interactions (only breakouts) from the library 'Touched'.
Parameters:
zones (Zones)
settings (Settings) : set all values in this parameter to define the settings for the order block creation.
marketStructureInfo (MarketStructureInfo) : The state of market structure needed.
trend (int) : the market structure trend that's used for the integrations direction. 1 = bullish, -1 = bearish, 0 = both.
Pivots(settings)
Creates pivots (high and low) to be used for order block creation.
Parameters:
settings (Settings) : set all values in this parameter to define the settings for the order block creation.
Returns: a tuple containing two pivot values (high and low) or 'na'
OrderBlock(settings, pivotHigh, pivotLow)
Creates an order block if one is found according to the settings parameter.
Parameters:
settings (Settings) : set all values in this parameter to define the settings for the order block creation.
pivotHigh (float) : The high pivot to use.
pivotLow (float) : The low pivot to use.
Returns: a Zone object if an order block is found, na otherwise
FairValueGap(settings)
Creates a fair value gap if one is found according to the settings parameter.
Parameters:
settings (Settings) : set all values in this parameter to define the settings for the fair value gap creation.
Returns: a Zone object if a fair value gap is found, na otherwise
SetBarIndex(zone)
Sets the 'BarIndex' value of the 'zone' object according to 'zone.ChartBaseTime'.
Parameters:
zone (Zone) : The 'Zone' object to set the bar index on.
MarketStructureZones(marketStructureInfo, foundZones, zones, priceAction, settings)
Creates/draws zones (order blocks and fair value gaps) depending on the current market structure from the price action.
Parameters:
marketStructureInfo (MarketStructureInfo) : The infirmation about the market structure from the price action.
foundZones (array) : All zones (order blocks and fair value gaps) to take action on.
zones (Zones) : The 'Zones' object that holds the current context.
priceAction (PriceAction type from mickes/PriceAction/5) : The 'PriceAction.PriceAction' object from the library 'PriceAction'.
settings (Settings) : set all values in this parameter to define the settings for the fair value gap creation.
Visual
Holds the visual elements or the zone.
Fields:
Boxes (array) : All the visual boxes.
Lines (array) : All the visual lines.
Labels (array) : All the visual labels.
Zone
Holds the values for visuals for the zone and to handle interactions (retests, false breakouts and breakouts).
Fields:
BaseTimeClose (series int) : The time close for the start of the zone.
FoundTimeClose (series int) : The time close for the zone when it's found.
ChartBaseTime (series int) : The time for the start of the zone according to the chart bar.
High (series float) : The maximimum price of the zone.
Low (series float) : The minimum price of the zone.
ReactionLimit (series float) : Set a factor (%) of the Average True Range (of length 14) that the total reaction must have.
TouchedZone (Zone type from mickes/Touched/17) : Zone object that will be created and sent to the library 'Touched'.
Visual (Visual) : An object that holds the visual elements for the zone.
SourceTimeframeSeconds (series int) : The 'timeframe.in_seconds' for the zone.
Direction (series int) : Defines if the found zone is bullish (1) or bearish (-1).
LatestRetestBarIndex (series int) : The latest 'bar_index' for a retest.
LatestFalseBreakoutBarIndex (series int) : The latest 'bar_index' for a false breakout.
LatestBreakoutBarIndex (series int) : The latest 'bar_index' for a breakout.
BarIndex (series int) : The chart's timeeframe 'bar_index'.
OriginType (series Type) : The 'Type' for the origin (order block or fair value gap).
Type (series Type) : The type of the zone.
Visible (series bool) : If the zone is drawn and not removed or re-drawn.
Zones
Holds the values for the charts zones.
Fields:
Zones (array) : The currently active zones.
Removes (array) : Reprsents the zones that will be replaced.
HiddenZones (array) : The currently hidden zones.
OrderBlockSettings
The settings specific for order block creation.
Fields:
TakeOut (series bool) : If the bas candle needs to be higher\lower than the previous candle (liquidity sweep\grab).
FairValueGap (series bool) : If there needs o be a fair value gap between the first and the last (third) candle of the order block.
ConsecutiveRisingOrFalling (series bool) : The candles in the reaction must consecutivly rise or fall (the 'hl2' must be rising/falling).
ReactionFactor (series float) : A factor of the Average True Range (of length 14) that the total reaction must have. A higher value will create fewer zones with a bigger reaction. And check the checkbox if you want the limit to be displayed.
ShowReaction (series bool) : Show a solid line for the reaction limit.
HideConsecutiveZones (series bool) : If multiple order blocks are found after each other only the first one will be found by the indicator.
FairValueGapSettings
The settings specific for fair value gap creation.
Fields:
ConsecutiveRisingOrFalling (series bool) : The candles in the reaction must consecutivly rise or fall (the 'hl2' must be rising/falling).
Strong (series bool) : If this is enabled it will force the FVG middle candle to have a higher/lower 'hl2' (middle of the entire candle) than the first candle's high.
HideConsecutiveZones (series bool) : If multiple order blocks are found after each other only the first one will be found by the indicator.
MinimumSizeFactor (series float) : A factor of the Average True Range (of length 14) that the size of the fair value gap must have.
Settings
The settings for the creation of order blocks and fair value gaps. You will need to set all the containing values in here.
Fields:
KeepHistoryZones (series bool) : Set to true if you want removed (from previous trend) zones to be displayed.
Bull (series color) : The color of bullish zones.
Bear (series color) : The color of bearish zones.
CreateCreationZone (series bool) : Set to true if you want a box with a border to be drawn at the creation of the zone. This is usefull when the zones comes from a higher timeframe, but not from a lower. If this is false the 'Draw()' function will start at 'time - time_close'.
AlertRetests (series bool) : Enable if you want alerts to fire when the 'Touched' library signals that a retest of the order block has occured.
AlertFalseBreakouts (series bool) : Enable if you want alerts to fire when the 'Touched' library signals that a false breakout of the order block has occured.
AlertBreakouts (series bool) : Enable if you want alerts to fire when the 'Touched' library signals that a breakout of the order block has occured.
AlertMessageFormat (series string) : Set the format of the fired alert uppon 'Touched' library signals. Need to be in the format of '{0} on order block from ...' where '{0}' is replaced with 'retest', 'false breakout' or 'breakout'.
Types (array) : All types that should be displayed.
FairValueGapSettings (FairValueGapSettings) : The settings for the creation of fair value gaps.
OrderBlockSettings (OrderBlockSettings) : The settings for the creation of order blocks.
MarketStructurePivot
Pivot The 'PriceAction.Pivot' for the market structure.
Fields:
BrokenBarIndex (series int)
Pivot (Pivot type from mickes/PriceAction/5)
MarketStructureInfo
Holds the needed market structure pivots needed for this library.
Fields:
LatestBreakOfStructure (MarketStructurePivot) : The latest break of structure (BOS) found by the 'PriceAction' library.
LatestChangeOfCharacter (MarketStructurePivot) : The latest change of character (CHoCH\CHoCH+) found by the 'PriceAction' library. Library

Indicator

Volumetric Inverse Fair Value Gap (VIFVG) [UAlgo]Volumetric Inverse Fair Value Gap is an imbalance analysis tool that tracks the full lifecycle of a Fair Value Gap and then focuses on what happens after that gap fails. Instead of stopping at the initial gap detection, the script stores qualifying bullish and bearish FVGs, waits for price to invalidate them from the opposite side, and then converts those failed imbalances into active Inverse Fair Value Gaps.
The main idea is rooted in role reversal. A bullish Fair Value Gap may initially represent an area of inefficiency below price, but if price later trades through that gap in the opposite direction, the same zone can flip into a bearish inverse area. The same logic applies in reverse for bearish gaps that later fail to the upside. This script automates that transition and keeps the resulting IFVG visible on the chart as long as it remains active.
What makes this version more distinctive is the volumetric overlay inside the inverse zone. Once an IFVG is created, the script attaches three internal metrics to it. The first estimates bullish participation, the second estimates bearish participation, and the third measures relative volume strength using percentile rank. These values are then displayed inside the box as horizontal progress bars, turning the IFVG into both a structural level and a compact participation summary.
The indicator also supports a ghost box that preserves the original FVG location from the moment it was created until the moment it became inverse. This gives the user a clearer narrative of how the imbalance formed and where the role reversal occurred. Combined with the active box, the result is a visually informative workflow for traders who want to study failed imbalances, structure flips, and how strong the inversion candle was when the role change happened.
In practical use, the script can help identify zones where a former inefficiency has turned into a reaction area, while also showing whether the inversion event carried more bullish pressure, more bearish pressure, or unusually strong participation relative to recent volume history.
🔹 Features
🔸 Fair Value Gap Detection With ATR Filtering
The script first detects classic three candle FVG structures, then filters them using a minimum gap size expressed in ATR units. This helps reduce noise and removes smaller gaps that may be less meaningful.
🔸 Strict and Non Strict Detection Modes
Strict mode requires actual wick separation between the first and third candle. Non strict mode allows close based confirmation instead. This gives the user control over how precise the gap definition should be.
🔸 Pending FVG Lifecycle Tracking
Detected FVGs are not immediately turned into inverse zones. They are first stored as pending gaps and monitored until price later crosses them in the opposite direction.
🔸 Automatic FVG to IFVG Conversion
When price invalidates a pending gap from the opposite side, the script creates a new Inverse Fair Value Gap object and begins tracking it as an active zone.
🔸 Ghost Box Support
The original FVG can be preserved visually as a dashed ghost box from the creation time of the imbalance to the inversion time. This makes it easier to see the original gap and the later role reversal event together.
🔸 Volumetric Breakdown Inside the IFVG
Each active inverse gap includes three stacked internal bars:
estimated bullish participation,
estimated bearish participation,
and relative strength.
This gives the zone more context than a normal box alone.
🔸 Participation Estimation From Candle Anatomy
Bullish and bearish participation are estimated from the inversion candle’s structure and volume. This creates a practical volume split model that helps describe how the inversion occurred.
🔸 Strength Metric From Volume Percentile Rank
The script measures how strong the inversion candle’s volume is relative to the last one hundred bars. This is displayed as a separate strength bar inside the IFVG.
🔸 Live Box Expansion
As long as an IFVG remains active, its container extends forward in time. The internal volumetric bars and text labels are updated continuously so the zone remains clear and readable.
🔸 Automatic Invalidation
A bullish IFVG is removed if price closes below its bottom. A bearish IFVG is removed if price closes above its top. This keeps the display focused on still valid inverse zones.
🔸 Controlled History Size
The script limits how many active IFVGs remain on the chart. Older ones are removed once the display exceeds the selected history count.
🔹 Calculations
1) Defining the Pending Gap and Active IFVG Objects
type PendingFVG
float top
float btm
bool is_bull_gap
bool processed
int created_time
type IFVG
int start_time
int origin_time
float top
float btm
bool is_bull_ifvg
float pct_bull
float pct_bear
float pct_strength
box container
box ghost_box
box bg_bull
box bar_bull
box bg_bear
box bar_bear
box bg_str
box bar_str
label lbl_bull
label lbl_bear
label lbl_str
bool active
This is the structural foundation of the script.
A PendingFVG stores an imbalance that has been detected but has not yet inverted. It contains the gap boundaries, whether the original gap was bullish or bearish, whether it has already been processed into an inverse gap, and the time when it was created.
An IFVG stores the full active inverse gap state. In addition to the price boundaries and direction, it also stores the three internal metrics, the container box, the optional ghost box, the internal background and progress bars, the labels, and the active state.
So the script is not just drawing boxes. It is managing two linked object lifecycles:
pending FVGs,
and active inverse FVGs.
2) ATR Filter for Gap Significance
float atr_val = ta.atr(14)
The ATR value is used as the script’s minimum significance filter.
Instead of accepting every visible gap, the script compares gap size against a fraction of ATR. This is useful because a fixed price threshold would behave very differently across markets and timeframes, while ATR gives a volatility aware reference.
So ATR acts as the noise filter that decides whether a newly found gap deserves to be tracked.
3) Estimating Bullish and Bearish Participation
calc_metrics(float o, float h, float l, float c, float v) =>
float rng = h - l
float buy_v = 0.0
if rng == 0
buy_v := v * 0.5
else
if c >= o
buy_v := v * ((math.abs(c - o) + (math.min(o, c) - l)) / rng)
else
buy_v := v * ((h - math.max(o, c)) / rng)
float sell_v = v - buy_v
float total = buy_v + sell_v
float p_bull = total > 0 ? buy_v / total : 0
float p_bear = total > 0 ? sell_v / total : 0
float p_str = ta.percentrank(v, 100) / 100.0
This function is one of the most important parts of the whole script.
Its goal is to turn one candle into three interpretable metrics:
bullish share,
bearish share,
and strength.
First, the script measures the candle range. If the candle has zero range, volume is split evenly.
If the candle has a real range, the script estimates buying pressure differently depending on candle direction.
For bullish candles, buy volume is influenced by the candle body plus the lower section of the candle.
For bearish candles, buy volume is approximated from the remaining upper section.
The result is not true exchange level aggressor volume, but it is a practical candle anatomy based estimate of how much of the inversion bar behaved more like buying versus selling.
Then the script converts those raw buy and sell estimates into proportions:
p_bull
and
p_bear
Finally, it calculates p_str using the percentile rank of current volume over the last one hundred bars. That means the strength value is not just raw volume. It describes how relatively strong the inversion candle was compared with recent history.
4) Reading the Current Candle Metrics
= calc_metrics(open, high, low, close, volume)
This line applies the volumetric function to the current bar.
These three values are later attached to a new IFVG at the moment of inversion. So each active inverse gap inherits the participation and strength profile of the candle that caused the role reversal.
That is important conceptually. The internal bars inside the IFVG are not random decorations. They represent the inversion event itself.
5) Detecting Bullish and Bearish FVGs
bool bull_cond = strict_mode ? (low > high ) : (close > high )
bool bear_cond = strict_mode ? (high < low ) : (close < low )
This block defines the actual Fair Value Gap logic.
In strict mode:
a bullish gap exists only when the current low is above the high from two bars ago,
and a bearish gap exists only when the current high is below the low from two bars ago.
That means actual wick separation is required.
In non strict mode:
the script relaxes this and allows close based confirmation instead.
So the user can choose whether the script should only accept clean wick gaps or allow a softer close based definition.
6) Measuring the Gap Size
float gap_size = 0.0
if bull_cond and close > open
gap_size := low - high
if bear_cond and close < open
gap_size := low - high
bool is_significant = gap_size >= (atr_val * fvg_threshold_atr)
Once a candidate FVG is found, the script measures how large the gap actually is.
For bullish gaps, the size is the distance between the current low and the high from two bars ago.
For bearish gaps, the size is the distance between the low from two bars ago and the current high.
The script also adds a candle direction filter on the middle bar:
bullish gaps require the middle candle to be bullish,
and bearish gaps require the middle candle to be bearish.
Finally, the measured gap must be at least as large as:
ATR × threshold
This removes smaller gaps that may simply be noise.
7) Storing a Pending FVG
if is_significant
PendingFVG p = PendingFVG.new()
p.created_time := time
p.processed := false
if bull_cond
p.is_bull_gap := true
p.top := low
p.btm := high
else
p.is_bull_gap := false
p.top := low
p.btm := high
array.push(pending_fvgs, p)
If the gap is significant, the script stores it as a pending FVG.
The gap is not drawn yet as an inverse zone. Instead, it is placed into the pending list with:
its direction,
its boundaries,
its creation time,
and a flag showing it has not yet been processed.
This is important because an FVG only becomes an IFVG after it fails. The pending list is the waiting room for that future role reversal.
8) Detecting the Inversion Event
if array.size(pending_fvgs) > 0
for i = array.size(pending_fvgs) - 1 to 0
PendingFVG p = array.get(pending_fvgs, i)
if not p.processed
bool inverted = false
bool to_bull = false
if not p.is_bull_gap and close > p.top
inverted := true
to_bull := true
if p.is_bull_gap and close < p.btm
inverted := true
to_bull := false
This is the core IFVG transition logic.
A pending bearish FVG becomes a bullish IFVG if price closes above its top.
A pending bullish FVG becomes a bearish IFVG if price closes below its bottom.
That is the actual role reversal event. Price has invalidated the original imbalance from the opposite side, so the gap flips into an inverse form.
The to_bull flag determines the direction of the new inverse zone.
9) Creating the IFVG Object
if inverted
IFVG obj = IFVG.new()
obj.start_time := time
obj.origin_time := p.created_time
obj.top := p.top
obj.btm := p.btm
obj.is_bull_ifvg := to_bull
obj.pct_bull := curr_p_bull
obj.pct_bear := curr_p_bear
obj.pct_strength := curr_p_str
obj.active := true
obj.create_drawings()
array.push(active_ifvgs, obj)
p.processed := true
Once inversion is confirmed, the script creates the active IFVG.
The new object inherits:
the original FVG boundaries,
the original creation time,
the inversion start time,
and the new inverse direction.
It also stores:
the bullish participation percentage,
the bearish participation percentage,
and the strength percentage from the inversion candle.
So the IFVG is a structural object with a built in event profile. It tells the user not only where the failed gap is located, but also what the inversion bar looked like in participation terms.
10) Creating the Ghost Box and Main Container
if show_ghost
this.ghost_box := box.new(
left=this.origin_time,
top=this.top,
right=this.start_time,
bottom=this.btm,
border_color=color.new(c_border, 20),
border_width=1,
border_style=line.style_dashed,
bgcolor=c_ghost,
xloc=xloc.bar_time
)
this.container := box.new(
left=this.start_time,
top=this.top,
right=time,
bottom=this.btm,
border_color=c_border,
border_width=1,
bgcolor=color(na),
xloc=xloc.bar_time
)
This is the first part of the IFVG drawing engine.
If ghost mode is enabled, the script draws a dashed box from the original FVG creation time to the inversion time. This visually represents the original gap before it failed.
Then it creates the main IFVG container box starting from the inversion time and extending to the current bar.
So the chart can show both:
where the original gap existed,
and where the inverse zone now lives.
11) Building the Internal Volumetric Bar Areas
this.bg_bull := box.new(this.start_time, this.top, time, this.top, border_width=0, bgcolor=c_bg_dark, xloc=xloc.bar_time)
this.bar_bull := box.new(this.start_time, this.top, this.start_time, this.top, border_width=0, bgcolor=c_bull_bar, xloc=xloc.bar_time)
this.bg_bear := box.new(this.start_time, this.top, time, this.top, border_width=0, bgcolor=c_bg_dark, xloc=xloc.bar_time)
this.bar_bear := box.new(this.start_time, this.top, this.start_time, this.top, border_width=0, bgcolor=c_bear_bar, xloc=xloc.bar_time)
this.bg_str := box.new(this.start_time, this.top, time, this.top, border_width=0, bgcolor=c_bg_dark, xloc=xloc.bar_time)
this.bar_str := box.new(this.start_time, this.top, this.start_time, this.top, border_width=0, bgcolor=c_str_bar, xloc=xloc.bar_time)
Inside every IFVG, the script creates three horizontal rows.
Each row has:
a dark background box,
and a colored progress bar box.
The three rows represent:
bullish participation,
bearish participation,
and strength.
Initially these boxes are created with minimal size. Their real geometry is set later during updates.
So the IFVG is designed as a mini information panel embedded directly inside the zone.
12) Slicing the IFVG Into Three Metric Rows
float total_h = this.top - this.btm
float h_slice = total_h / 3
float y1 = this.top
float y2 = this.top - h_slice
float y3 = this.top - 2 * h_slice
float y4 = this.btm
This block divides the IFVG vertically into three equal sections.
The full height of the box is measured, then split into thirds:
the first slice for bullish participation,
the second slice for bearish participation,
the third slice for strength.
This makes the internal visualization clean and consistent regardless of zone height.
13) Converting Percentages Into Horizontal Width
int now = time
int dur = now - this.start_time
if dur <= 0
dur := timeframe.in_seconds() * 1000
int w_bull = math.round(dur * this.pct_bull)
int w_bear = math.round(dur * this.pct_bear)
int w_str = math.round(dur * this.pct_strength)
This is how the script turns percentages into visible progress bars.
The available horizontal width is the elapsed time from the IFVG start to the current bar. That duration becomes the maximum usable width.
Then each stored metric is multiplied by that duration:
bullish percentage controls the bullish bar width,
bearish percentage controls the bearish bar width,
strength percentage controls the strength bar width.
So the internal bars behave like proportion meters stretched across the live duration of the zone.
14) Updating the Bull, Bear, and Strength Bars
this.bg_bull.set_left(this.start_time)
this.bg_bull.set_right(now)
this.bg_bull.set_top(y1)
this.bg_bull.set_bottom(y2)
this.bar_bull.set_left(this.start_time)
this.bar_bull.set_right(this.start_time + w_bull)
this.bar_bull.set_top(y1)
this.bar_bull.set_bottom(y2)
this.bg_bear.set_left(this.start_time)
this.bg_bear.set_right(now)
this.bg_bear.set_top(y2)
this.bg_bear.set_bottom(y3)
this.bar_bear.set_left(this.start_time)
this.bar_bear.set_right(this.start_time + w_bear)
this.bar_bear.set_top(y2)
this.bar_bear.set_bottom(y3)
this.bg_str.set_left(this.start_time)
this.bg_str.set_right(now)
this.bg_str.set_top(y3)
this.bg_str.set_bottom(y4)
this.bar_str.set_left(this.start_time)
this.bar_str.set_right(this.start_time + w_str)
this.bar_str.set_top(y3)
this.bar_str.set_bottom(y4)
These blocks physically place the three metric layers inside the IFVG.
Each background row spans the full current width of the active zone.
Each colored bar spans only the proportional amount determined by the stored metric.
So if bullish participation is high, the bullish bar stretches farther across its row. If strength is low, the strength bar remains shorter.
This gives the zone an at a glance internal profile.
15) Updating the Text Labels
this.lbl_bull.set_xy(center_x, mid_bull)
this.lbl_bull.set_text(str.format("Bull: {0}%", math.round(this.pct_bull * 100)))
this.lbl_bear.set_xy(center_x, mid_bear)
this.lbl_bear.set_text(str.format("Bear: {0}%", math.round(this.pct_bear * 100)))
this.lbl_str.set_xy(center_x, mid_str)
this.lbl_str.set_text(str.format("Str: {0}%", math.round(this.pct_strength * 100)))
The script also prints the numerical values inside the three rows.
Each label is placed at the center of its row and updated with the rounded percentage value.
So the user sees both:
the visual bar length,
and the exact stored percentage.
This makes the IFVG readable even when box width is large or when color alone is not enough.
16) IFVG Invalidation Logic
bool broken = false
if this.is_bull_ifvg and close < this.btm
broken := true
if not this.is_bull_ifvg and close > this.top
broken := true
if broken
this.active := false
this.remove()
An active IFVG only remains valid while price stays on the correct side of its structure.
For bullish IFVG:
if close falls below the bottom, the zone is broken.
For bearish IFVG:
if close rises above the top, the zone is broken.
When that happens, the IFVG is marked inactive and all associated objects are deleted.
So the indicator is not just drawing inverse gaps indefinitely. It actively monitors whether they continue to behave as valid reaction zones.
17) Display Limit Management
while array.size(active_ifvgs) > show_last_n
IFVG d = array.shift(active_ifvgs)
d.remove()
This final block controls how many IFVGs remain visible.
If the number of active inverse gaps exceeds the selected display limit, the oldest one is removed from the front of the array and all of its drawings are deleted.
This keeps the chart focused on the most recent inverse gaps and prevents excessive visual clutter. Indicator

Indicator

Indicator
