Pine Script V5 Algorithmic Flow Free / Open Source

Liquidity Grab Engine

Overview

Retail liquidity does not sit randomly on the chart — it clusters. Stop-losses stack just beyond recognizable swing highs and lows. Breakout orders queue above session highs and below session lows, waiting for a level to break. That clustering is precisely what makes those levels attractive to market makers and institutional desks that need to execute size: engineering price just beyond a resting pool of orders — a "stop-hunt" or liquidity sweep — generates the fills and the volume required to move price in the opposite direction with minimal slippage.

The Liquidity Grab Engine isolates this behavior programmatically. It tracks confirmed swing structure and user-defined session ranges, flags the moment price wicks through one of these levels, and then checks whether that raid is followed by a close back on the original side — the distinction between a genuine liquidity grab and a confirmed breakout.

Features of This Indicator

How to Use

  1. Copy the script into TradingView's Pine Editor and click Add to Chart.
  2. Set the Liquidity Session input to match the window you want mapped — Asia, London, New York, or a fully custom range in exchange time.
  3. Watch for a "Liquidity Grab" label forming at a prior swing high/low or a mapped session high/low.
  4. Wait for the close back inside the raided level before treating it as a potential reversal trigger — the wick alone is not confirmation.
Pro Tip: The raid itself is not the signal — the close back inside the level is. The highest-probability reversals tend to occur when a liquidity grab coincides with an unmitigated Order Block or Fair Value Gap sitting in the same zone, since three independent structural signatures rarely align by coincidence.

The Pine Script V5 Code

liquidity-grab-engine.pine
//@version=5
indicator("Liquidity Grab Engine — Crypto Indicator Pro", shorttitle="Liq Grab [CIP]", overlay=true, max_lines_count=500, max_labels_count=500)

// ============================================================================
// LIQUIDITY GRAB ENGINE
// Detects structural stop-hunts (swing failure patterns) and session-based
// liquidity pool sweeps: instances where price raids a resting liquidity
// level -- a prior swing high/low or a session high/low -- before reversing
// and closing back on the opposite side. Confirms strictly on bar close.
// ============================================================================

// ---------------------------- INPUTS ----------------------------
swingLength   = input.int(10, "Swing Detection Length", minval=2, group="Market Structure",
     tooltip="Bars used on each side to confirm a valid swing high/low.")
sessionString = input.session("0000-0800", "Liquidity Session (Exchange Time)", group="Session Liquidity")
showSession   = input.bool(true, "Map Session High/Low Liquidity Pools", group="Session Liquidity")
bullColor     = color.new(color.teal, 0)
bearColor     = color.new(color.red, 0)

// ---------------------------- SWING STRUCTURE ----------------------------
swingHigh = ta.pivothigh(high, swingLength, swingLength)
swingLow  = ta.pivotlow(low, swingLength, swingLength)

var float lastSwingHigh  = na
var float lastSwingLow   = na
var bool  swingHighTaken = false   // tracks whether the current swing high has already been swept
var bool  swingLowTaken  = false

if not na(swingHigh)
    lastSwingHigh := swingHigh
    swingHighTaken := false
if not na(swingLow)
    lastSwingLow := swingLow
    swingLowTaken := false

// ---------------------------- STRUCTURAL LIQUIDITY GRAB (SWING FAILURE) ----------------------------
// Bearish grab: price wicks above the last swing high (liquidity raid) but closes back below it.
bearishGrab = not na(lastSwingHigh) and not swingHighTaken and high > lastSwingHigh and close < lastSwingHigh
// Bullish grab: price wicks below the last swing low (liquidity raid) but closes back above it.
bullishGrab = not na(lastSwingLow) and not swingLowTaken and low < lastSwingLow and close > lastSwingLow

if bearishGrab
    swingHighTaken := true
    line.new(bar_index[1], lastSwingHigh, bar_index, lastSwingHigh, color=bearColor, width=1, style=line.style_dashed)
    label.new(bar_index, high, "Liquidity Grab\n(Sell-Side Raid)", style=label.style_label_down, color=bearColor, textcolor=color.white, size=size.small)

if bullishGrab
    swingLowTaken := true
    line.new(bar_index[1], lastSwingLow, bar_index, lastSwingLow, color=bullColor, width=1, style=line.style_dashed)
    label.new(bar_index, low, "Liquidity Grab\n(Buy-Side Raid)", style=label.style_label_up, color=bullColor, textcolor=color.white, size=size.small)

// ---------------------------- SESSION LIQUIDITY POOL MAPPING ----------------------------
inSession = not na(time(timeframe.period, sessionString))

var float sessionHigh   = na
var float sessionLow    = na
var bool  sessHighTaken = false
var bool  sessLowTaken  = false

if inSession and not inSession[1]
    sessionHigh := high
    sessionLow  := low
    sessHighTaken := false
    sessLowTaken  := false
else if inSession
    sessionHigh := math.max(sessionHigh, high)
    sessionLow  := math.min(sessionLow, low)

// Draw the completed session range once the session closes
if showSession and not inSession and inSession[1] and not na(sessionHigh)
    line.new(bar_index - 1, sessionHigh, bar_index + 20, sessionHigh, color=color.new(color.orange, 30), width=1, extend=extend.right)
    line.new(bar_index - 1, sessionLow, bar_index + 20, sessionLow, color=color.new(color.orange, 30), width=1, extend=extend.right)

// Session liquidity sweeps are checked continuously, including outside the session window
if showSession and not na(sessionHigh) and not sessHighTaken and high > sessionHigh and close < sessionHigh
    sessHighTaken := true
    label.new(bar_index, high, "Session Liquidity Grab", style=label.style_label_down, color=color.orange, textcolor=color.white, size=size.small)

if showSession and not na(sessionLow) and not sessLowTaken and low < sessionLow and close > sessionLow
    sessLowTaken := true
    label.new(bar_index, low, "Session Liquidity Grab", style=label.style_label_up, color=color.orange, textcolor=color.white, size=size.small)

// ---------------------------- ALERTS ----------------------------
alertcondition(bearishGrab, title="Bearish Liquidity Grab", message="Sell-side liquidity swept — potential bearish reversal.")
alertcondition(bullishGrab, title="Bullish Liquidity Grab", message="Buy-side liquidity swept — potential bullish reversal.")
Risk Notice: This script is provided for educational and research purposes only and does not constitute financial advice. Always backtest on a demo account before any live deployment. See our full Institutional Risk Disclaimer for details.

03 Related Modules

PINE SCRIPT V5

Automated Order Blocks

Calculates institutional order accumulation zones with real-time market structure verification.

View Module
LIQUIDITY TARGETS

Fair Value Gaps (FVG)

Scans multi-timeframe price imbalances and liquidity delivery voids across asset feeds.

View Module
SCALPING MODULE

High-Frequency Scalper

A low-latency script tuned for rapid, algorithmic micro-execution.

View Module

04 Related Reading

How to Set Take-Profit Targets Using Liquidity Pools Instead of Guessing

Category: Technical Guides
Read Guide →

Inducement vs Liquidity Grab: Why You Keep Entering One Move Too Early

Category: Technical Guides
Read Guide →

Best Indicator to Catch Stop Hunts on Binance and Bybit Futures Before They Happen

Category: Risk Protocols
Read Guide →

How to Tell a Real Liquidity Grab From a Genuine Breakout

Category: Technical Guides
Read Guide →

The Real Reason Your Stop Loss Gets Hit One Tick Before Reversal

Category: Market Intelligence
Read Guide →