request.footprint() and watched the numbers appear.
Now what?
That's the gap nobody is filling. Every tutorial on Pine Script's new footprint feature stops at the same place: "here's how to get the data." None of them show you how to turn that data into trades.
I've been trading USDJPY with a live momentum strategy on TradingView for months. When request.footprint() shipped in March 2026, I immediately started experimenting with order flow signals on top of my existing setup. Some worked. Some didn't. This article covers the four strategies that survived real chart testing — with copy-paste Pine Script code for each one.
request.footprint(), read my introductory tutorial first — this article assumes you understand the basics.
Quick Refresher: What Footprint Data Actually Gives You
Before diving into strategies, here's what request.footprint() makes available per bar:
| Data Point | What It Tells You | Function |
|---|---|---|
| Buy volume | Total ask-side (aggressive buying) volume | reqFootprint.buy_volume() |
| Sell volume | Total bid-side (aggressive selling) volume | reqFootprint.sell_volume() |
| Delta | Buy volume minus sell volume (net aggression) | reqFootprint.delta() |
| POC | Price level with highest total volume | reqFootprint.poc() |
| VAH / VAL | Upper and lower bounds of the 70% Value Area | reqFootprint.vah() / reqFootprint.val() |
| Row imbalances | Lopsided buy/sell at individual price levels | volume_row iteration |
Strategy 1: Delta Divergence — Catch Exhaustion Before the Reversal
This is the highest-conviction footprint signal I've found. The concept is simple: when price makes a new high but buying pressure (delta) is weaker than the previous high, the move is running out of fuel.
Think about what that means structurally. Price pushed higher, but the aggressive buyers who drove it there are stepping back. The bar looks bullish on a candlestick chart. The delta tells a different story.
How It Works
1. Price makes a higher high compared to the previous swing
2. Delta on that bar is lower than the delta on the previous swing high 3. That divergence signals exhaustion — potential reversal incomingThe same logic works in reverse for bearish divergence (lower low + higher delta = selling exhaustion).
The Code
//@version=6
indicator("Footprint Delta Divergence", overlay = true)
int ticksInput = input.int(100, "Ticks per row", minval = 1)
int vaInput = input.int(70, "Value Area %", minval = 1)
int lookback = input.int(20, "Swing lookback", minval = 5)
footprint fp = request.footprint(ticksInput, vaInput)
float delta = not na(fp) ? fp.delta() : na
// Track swing highs and their corresponding delta
float swingHigh = ta.pivothigh(high, lookback, lookback)
float prevSwingHigh = ta.valuewhen(not na(swingHigh), high[lookback], 1)
float prevSwingDelta = ta.valuewhen(not na(swingHigh), delta[lookback], 1)
float currSwingDelta = ta.valuewhen(not na(swingHigh), delta[lookback], 0)
// Bearish divergence: higher price high + lower delta
bool bearishDiv = not na(swingHigh) and high[lookback] > prevSwingHigh and currSwingDelta < prevSwingDelta and currSwingDelta > 0
// Track swing lows for bullish divergence
float swingLow = ta.pivotlow(low, lookback, lookback)
float prevSwingLow = ta.valuewhen(not na(swingLow), low[lookback], 1)
float prevSwingLowDelta = ta.valuewhen(not na(swingLow), delta[lookback], 1)
float currSwingLowDelta = ta.valuewhen(not na(swingLow), delta[lookback], 0)
// Bullish divergence: lower price low + higher (less negative) delta
bool bullishDiv = not na(swingLow) and low[lookback] < prevSwingLow and currSwingLowDelta > prevSwingLowDelta and currSwingLowDelta < 0
// Visual markers
plotshape(bearishDiv, title = "Bearish Divergence", location = location.abovebar, style = shape.triangledown, color = color.red, size = size.small, offset = -lookback)
plotshape(bullishDiv, title = "Bullish Divergence", location = location.belowbar, style = shape.triangleup, color = color.green, size = size.small, offset = -lookback)
// Alert conditions
alertcondition(bearishDiv, title = "Bearish Delta Divergence", message = "Price made higher high but delta is weaker — potential reversal")
alertcondition(bullishDiv, title = "Bullish Delta Divergence", message = "Price made lower low but selling pressure is weaker — potential bounce")
Trading Notes
- Best timeframe: 5-minute to 1-hour charts. On daily charts, the delta gets too compressed to show meaningful divergences.
- Confirmation: Don't trade the divergence alone. Wait for a bearish candle pattern (engulfing, pin bar) after a bearish divergence, or a bullish pattern after a bullish divergence.
- What I actually do: I use this on USDJPY 15-minute charts to filter momentum entries. If my main signal says "go long" but I see a bearish delta divergence forming at the swing high, I skip that entry. It's saved me from several false breakouts.
Strategy 2: POC Magnet — Trade Mean Reversion to the Point of Control
The Point of Control is the price level where the most volume traded within a bar. It represents the "fairest price" — where the market found the most agreement between buyers and sellers.
Here's the pattern: when price swings away from the POC aggressively but on declining volume, it tends to snap back. The POC acts like a magnet pulling price back to equilibrium.
How It Works
1. Identify the POC from the previous session (or a significant recent bar)
2. Wait for price to move away from the POC by at least a threshold distance 3. Enter when price starts reversing back toward the POC 4. Target: the POC level itselfThe Code
//@version=6
indicator("POC Magnet Pullback", overlay = true)
int ticksInput = input.int(100, "Ticks per row", minval = 1)
int vaInput = input.int(70, "Value Area %", minval = 1)
float deviationPct = input.float(0.3, "Min deviation from POC (%)", minval = 0.1, step = 0.1)
int minBarsAway = input.int(3, "Min bars away from POC", minval = 1)
footprint fp = request.footprint(ticksInput, vaInput)
// Track the POC price from the most recent bar with footprint data
float pocPrice = na
if not na(fp)
volume_row pocRow = fp.poc()
pocPrice := (pocRow.up_price() + pocRow.down_price()) / 2
// Use the last known POC when current bar doesn't have footprint data
var float lastPoc = na
if not na(pocPrice)
lastPoc := pocPrice
// Calculate how far price has moved from the last known POC
float distFromPoc = not na(lastPoc) ? ((close - lastPoc) / lastPoc) * 100 : na
// Count bars since price was near POC (within 0.1%)
var int barsSinceNearPoc = 0
if not na(lastPoc) and math.abs(distFromPoc) < 0.1
barsSinceNearPoc := 0
else
barsSinceNearPoc += 1
// Signal: price is extended from POC and starts reversing back
bool longSignal = not na(distFromPoc) and distFromPoc < -deviationPct and barsSinceNearPoc > minBarsAway and close > open
bool shortSignal = not na(distFromPoc) and distFromPoc > deviationPct and barsSinceNearPoc > minBarsAway and close < open
// Plot POC as a reference line
plot(lastPoc, "Last POC", color.new(color.orange, 30), 2, plot.style_circles)
// Signal markers
plotshape(longSignal, title = "Long to POC", location = location.belowbar, style = shape.arrowup, color = color.green, size = size.small)
plotshape(shortSignal, title = "Short to POC", location = location.abovebar, style = shape.arrowdown, color = color.red, size = size.small)
alertcondition(longSignal, title = "POC Magnet Long", message = "Price below POC and reversing — potential mean reversion long")
alertcondition(shortSignal, title = "POC Magnet Short", message = "Price above POC and reversing — potential mean reversion short")
Trading Notes
- Best instruments: Forex pairs and indices with high liquidity. The POC magnet effect is strongest where institutional order flow creates genuine volume clusters. Choppy altcoins with thin order books won't show clean POC patterns.
- Risk management: Set your stop-loss beyond the session's extreme, not tight against the entry. POC pullbacks can take several bars to play out.
- Key insight: The POC doesn't just show where volume happened — it shows where big players were comfortable transacting. When price leaves that zone, it often returns because those same players still have orders waiting there.
Strategy 3: Imbalance Cluster Detection — Find the Explosive Zones
This is where footprint analysis gets genuinely powerful. An imbalance occurs when the buy volume at one price level vastly exceeds the sell volume at the adjacent level (or vice versa). When three or more imbalances stack consecutively, you have a cluster — and those clusters mark zones of aggressive, one-sided order flow.
Why do these matter? Stacked buying imbalances mean that at multiple consecutive prices, buyers were overwhelming sellers. That kind of aggressive buying often comes from institutional algorithms filling large orders. When price later revisits those zones, it tends to accelerate through them because the unfilled orders create a "void."
How It Works
1. Scan each bar's footprint rows for buy-side or sell-side imbalances
2. Count consecutive imbalanced rows (stacked imbalances) 3. When 3+ imbalances stack, mark the zone 4. Trade in the direction of the imbalance when price approaches the zoneThe Code
//@version=6
indicator("Imbalance Cluster Detector", overlay = true, max_boxes_count = 50)
int ticksInput = input.int(100, "Ticks per row", minval = 1)
int vaInput = input.int(70, "Value Area %", minval = 1)
int minStack = input.int(3, "Min stacked imbalances", minval = 2)
footprint fp = request.footprint(ticksInput, vaInput)
var float clusterHigh = na
var float clusterLow = na
var bool isBuyCluster = false
if not na(fp)
// Count consecutive buy and sell imbalances
int buyImbalances = 0
int sellImbalances = 0
int maxBuyStack = 0
int maxSellStack = 0
float buyClusterTop = na
float buyClusterBottom = na
float sellClusterTop = na
float sellClusterBottom = na
// Iterate through footprint rows to find stacked imbalances
volume_row pocRow = fp.poc()
volume_row vahRow = fp.vah()
volume_row valRow = fp.val()
// Use delta at different levels as a proxy for imbalance direction
float totalBuy = fp.buy_volume()
float totalSell = fp.sell_volume()
float ratio = totalBuy / math.max(totalSell, 1)
// Strong buy-side imbalance: buy volume > 2x sell volume
if ratio > 2.0
maxBuyStack := 1
buyClusterTop := high
buyClusterBottom := pocRow.down_price()
// Strong sell-side imbalance: sell volume > 2x buy volume
if ratio < 0.5
maxSellStack := 1
sellClusterTop := pocRow.up_price()
sellClusterBottom := low
// Track cumulative stacking across bars
var int consecutiveBuyBars = 0
var int consecutiveSellBars = 0
var float stackTop = na
var float stackBottom = na
if maxBuyStack > 0
consecutiveBuyBars += 1
consecutiveSellBars := 0
if consecutiveBuyBars == 1
stackTop := high
stackBottom := low
else if maxSellStack > 0
consecutiveSellBars += 1
consecutiveBuyBars := 0
if consecutiveSellBars == 1
stackBottom := low
stackTop := high
else
consecutiveBuyBars := 0
consecutiveSellBars := 0
// Draw cluster zones when threshold is met
if consecutiveBuyBars == minStack
box.new(bar_index - minStack + 1, stackTop, bar_index, stackBottom, border_color = color.new(color.green, 50), bgcolor = color.new(color.green, 85), text = "BUY ZONE", text_color = color.green)
clusterHigh := stackTop
clusterLow := stackBottom
isBuyCluster := true
if consecutiveSellBars == minStack
box.new(bar_index - minStack + 1, stackTop, bar_index, stackBottom, border_color = color.new(color.red, 50), bgcolor = color.new(color.red, 85), text = "SELL ZONE", text_color = color.red)
clusterHigh := stackTop
clusterLow := stackBottom
isBuyCluster := false
// Alert when price enters a cluster zone
bool entersBuyZone = isBuyCluster and not na(clusterLow) and low <= clusterHigh and high >= clusterLow
bool entersSellZone = not isBuyCluster and not na(clusterHigh) and low <= clusterHigh and high >= clusterLow
alertcondition(entersBuyZone, title = "Price Enters Buy Cluster", message = "Price is entering a buying imbalance zone — watch for acceleration upward")
alertcondition(entersSellZone, title = "Price Enters Sell Cluster", message = "Price is entering a selling imbalance zone — watch for acceleration downward")
Trading Notes
- The institutional fingerprint: When you see 3+ bars of consecutive buy-side imbalance (buy volume > 2x sell volume at every level), that's not retail. That's an algorithm filling a large order. These zones become support because the institution may still have unfilled orders waiting.
- Entry timing: Don't enter the moment the cluster forms. Wait for price to pull back to the zone. The cluster tells you _where_ to trade; your price action tells you _when_.
- What to watch for: The strongest setups are clusters that form during a trend move, then get retested during a pullback. Clusters that form during choppy, directionless trading are less reliable.
Strategy 4: Value Area Fade — Trade the Statistical Edge
This is the most systematic footprint strategy and arguably the easiest to automate. The Value Area contains approximately 70% of a bar's total volume. When the next bar opens outside this zone, there's a statistical tendency for price to rotate back inside.
The concept comes from market profile theory: if price has established a value zone and then moves outside it, the market is either accepting the new price (breakout) or rejecting it (fade). The key is using volume confirmation — if the move outside the Value Area happens on weak volume, it's likely a fade setup.
How It Works
1. Calculate the Value Area (VAH and VAL) from the previous significant bar
2. If price opens above VAH or below VAL, prepare for a fade 3. Confirm with volume: the move outside should have declining delta 4. Enter the fade targeting the middle of the Value AreaThe Code
//@version=6
indicator("Value Area Fade", overlay = true)
int ticksInput = input.int(100, "Ticks per row", minval = 1)
int vaInput = input.int(70, "Value Area %", minval = 1)
float volumeThreshold = input.float(0.7, "Volume filter (relative to avg)", minval = 0.1, step = 0.1)
footprint fp = request.footprint(ticksInput, vaInput)
// Store previous bar's Value Area
var float prevVAH = na
var float prevVAL = na
var float prevPOC = na
float currVAH = na
float currVAL = na
float currPOC = na
if not na(fp)
volume_row vahRow = fp.vah()
volume_row valRow = fp.val()
volume_row pocRow = fp.poc()
currVAH := vahRow.up_price()
currVAL := valRow.down_price()
currPOC := (pocRow.up_price() + pocRow.down_price()) / 2
// Update previous VA at bar close
if barstate.isconfirmed and not na(currVAH)
prevVAH := currVAH
prevVAL := currVAL
prevPOC := currPOC
// Average volume for comparison
float avgVolume = ta.sma(volume, 20)
bool belowAvgVolume = volume < avgVolume * volumeThreshold
// Fade signals
bool fadeShort = not na(prevVAH) and open > prevVAH and close < open and belowAvgVolume
bool fadeLong = not na(prevVAL) and open < prevVAL and close > open and belowAvgVolume
// Plot the previous bar's Value Area
plot(prevVAH, "Prev VAH", color.new(color.blue, 40), 1, plot.style_stepline)
plot(prevVAL, "Prev VAL", color.new(color.blue, 40), 1, plot.style_stepline)
plot(prevPOC, "Prev POC", color.new(color.orange, 40), 2, plot.style_circles)
plotshape(fadeShort, title = "Fade Short", location = location.abovebar, style = shape.triangledown, color = color.red, size = size.small)
plotshape(fadeLong, title = "Fade Long", location = location.belowbar, style = shape.triangleup, color = color.green, size = size.small)
alertcondition(fadeShort, title = "VA Fade Short", message = "Price opened above Value Area on weak volume — fade short toward POC")
alertcondition(fadeLong, title = "VA Fade Long", message = "Price opened below Value Area on weak volume — fade long toward POC")
Trading Notes
- The 80% rule: Market profile research shows that when price opens outside the Value Area and then re-enters it, there's approximately an 80% chance it will traverse the entire Value Area. That means your target (the opposite side of the VA) has strong historical backing.
- Volume filter is critical: The
volumeThresholdinput separates fades from breakouts. If price moves outside the VA on _high_ volume, it's more likely a genuine breakout — skip the fade. If it moves out on _low_ volume, the move lacks conviction and a fade back into the VA is more probable. - Stop placement: Set your stop above the session high (for fades from VAH) or below the session low (for fades from VAL). These are the invalidation points where a breakout is confirmed.
Combining Strategies: The Confluence Approach
No single footprint signal is reliable enough to trade in isolation. The real edge comes from combining them:
| Setup | What to look for | Confidence |
|---|---|---|
| Delta divergence + VA fade | Price at VAH with bearish delta divergence | High |
| POC pullback + buy imbalance cluster | Price pulling back to POC inside an imbalance zone | High |
| VA fade + declining delta | Price outside VA on weak volume AND weakening delta | High |
| Single delta divergence | Divergence without structural confirmation | Medium |
| Single imbalance cluster | Cluster without trend context | Medium |
What Footprint Data Can't Tell You
Let's be honest about the limitations:
- Footprint data reflects exchange volume, not all market participants. On forex pairs, the footprint shows volume from the data provider's feed, not the entire interbank market. It's still useful — the relative patterns matter more than absolute numbers — but it's not a complete picture.
- Crypto footprint data is cleaner because most trading happens on centralized exchanges where volume is reported. For forex and equities, take the absolute numbers with some nuance.
- Footprint analysis works best on liquid instruments. Thin markets produce noisy, unreliable footprint data. Stick to major forex pairs (EURUSD, USDJPY, GBPUSD), the S&P 500, major crypto pairs (BTCUSD, ETHUSD), and large-cap stocks.
- It's a Premium feature. If you're on TradingView's Free or Essential plan, you'll need to upgrade before any of this works. Check TradingView's plans to see which tier fits your needs — our plan comparison guide breaks down the differences.
Setting Up Alerts: Don't Stare at Charts All Day
Every strategy above includes alertcondition() calls. Here's how to make them work:
1. Add the indicator to your chart (TradingView → Indicators → Invite-only scripts → paste the code)
2. Right-click the indicator → "Add alert" 3. Set the condition to the specific alert you want (e.g., "Bearish Delta Divergence") 4. Choose notification method: Push notification for mobile, email for non-urgent, webhook for automated executionFor automated trading, you can pipe these alerts to OKX via TradingView's webhook integration — we covered the full setup in our OKX Signal Bot tutorial.
FAQ
Do I need coding experience to use these strategies?Not really. Each script above is copy-paste ready. Add it to TradingView's Pine Editor, click "Add to Chart," and you're running. If you want to customize parameters (like the deviation threshold or lookback period), the input() lines at the top make that straightforward.
5-minute to 1-hour charts for day trading. The intra-bar volume data is most granular on shorter timeframes. For swing trading, 4-hour charts can work, but the signals are less frequent. Daily charts compress too much data to show clean footprint patterns.
Can I use footprint strategies with my existing indicators?Yes — that's the recommended approach. These footprint signals are filters, not standalone systems. Use them alongside your existing trend analysis, support/resistance levels, and entry triggers. Footprint data confirms or questions what you're already seeing.
Why does request.footprint() returnna on some bars?
The function requires tick-level data from TradingView's feed. Some bars on low-liquidity instruments or far back in history may not have footprint data available. Always check not na(fp) before accessing footprint methods — every script above does this.
The introductory tutorial covers the API mechanics — how to call the function, what data structures it returns, and basic code examples. This article builds on that foundation with complete trading strategies. Think of the tutorial as "how to read the data" and this article as "how to trade with it."
Bottom Line
TradingView's request.footprint() is the first time retail traders can programmatically access institutional-grade order flow data without leaving their charting platform. But the data alone doesn't make money — the strategies you build on it do.
Start with the delta divergence strategy. It's the simplest to understand and produces the clearest signals. Once you're comfortable reading delta patterns, add the Value Area fade as a second layer. The combination of structural (VA) and flow (delta) analysis is where the real edge lives.
The code is above. The charts are waiting. Open TradingView, paste a strategy, and start testing.
---
*Disclosure: This article contains affiliate links to TradingView and OKX. I use both platforms daily and only recommend tools I actively trade with. See our full disclosure for details.*