This indicator identifies Smart Money Concept (SMC) liquidity zones based on Order Block detection with volume confirmation. Active zones are drawn as colored rectangles that extend to the current bar, while broken zones are grayed out and trimmed to the bar where the breakout occurred.
The indicator detects two types of Order Blocks:
Bullish OB — The previous bar makes a lower low compared to two bars ago, the current bar closes above the previous bar’s high, and volume exceeds the 20-period average by a configurable multiplier (default 1.3x). This suggests institutional accumulation.
Bearish OB — The previous bar makes a higher high compared to two bars ago, the current bar closes below the previous bar’s low, and volume exceeds the threshold. This suggests institutional distribution.
When an OB is detected, the indicator stores the zone defined by the previous bar’s high and low. Up to 5 zones per type (bullish/bearish) are tracked simultaneously using a FIFO buffer — when a new zone is detected and the maximum is reached, the oldest zone is dropped.
Each zone is checked on every bar for invalidation:
Active zones are drawn with their original color (teal for bullish, red for bearish) and extend to the current bar. Broken zones are drawn in gray with reduced opacity, trimmed to the bar where the break occurred. This behavior can be toggled with the hideOld parameter.
Signal arrows mark the exact bar where each OB was detected — arrow up for bullish, arrow down for bearish.
maxZones — Maximum number of active zones per type, from 1 to 5. Default: 5.
hideOld — Set to 1 to display broken zones in gray (default). Set to 0 to hide them completely.
volMultiplier — Multiplier applied to the 20-period average volume to define what counts as anomalous volume. Default: 1.3.
showsig — show signals (arrows). Default: false.
//---------------------------------------------------------------//
// PRC_Clean Liquidity Heatmap [SMC]
// Adapted from PineScript (ALEKSDU) to ProBuilder
// version = 0
// Date: 24.03.2026
// Iván González @ www.prorealcode.com
// Sharing ProRealTime knowledge
//---------------------------------------------------------------//
defparam drawonlastbaronly = true
//---------------------------------------------------------------//
// --- Settings ---
//---------------------------------------------------------------//
maxZones = 5 // Max active zones per type BUY/SELL (1 to 5)
hideOld = 1 // 1 = gray out broken zones, 0 = hide them completely
volMultiplier = 1.3 // Anomalous volume multiplier
showsig = 0 // show signals (true / false)
//---------------------------------------------------------------//
// --- Volume Logic ---
//---------------------------------------------------------------//
avgVol = average[20](volume)
IF volume > avgVol * volMultiplier THEN
isHighVol = 1
ELSE
isHighVol = 0
ENDIF
//---------------------------------------------------------------//
// --- OB Detection ---
//---------------------------------------------------------------//
IF low[1] < low[2] AND close > high[1] AND isHighVol THEN
isBullOB = 1
ELSE
isBullOB = 0
ENDIF
IF high[1] > high[2] AND close < low[1] AND isHighVol THEN
isBearOB = 1
ELSE
isBearOB = 0
ENDIF
// ============================================================
// SIGNAL STORAGE ($arrays as read buffer)
// ============================================================
once bullSigCount = 0
once bearSigCount = 0
IF isBullOB THEN
$bullSigBar[bullSigCount] = barindex
$bullSigPrice[bullSigCount] = low - averagetruerange[14] * 0.3
bullSigCount = bullSigCount + 1
ENDIF
IF isBearOB THEN
$bearSigBar[bearSigCount] = barindex
$bearSigPrice[bearSigCount] = high + averagetruerange[14] * 0.3
bearSigCount = bearSigCount + 1
ENDIF
// ============================================================
// FIFO BULLISH ZONES (5 slots)
// Fields: Bar, Top, Bot, Active (1/0), BrokenBar
// ============================================================
once bullBar0 = 0
once bullTop0 = 0
once bullBot0 = 0
once bullActive0 = 0
once bullBrkBar0 = 0
once bullBar1 = 0
once bullTop1 = 0
once bullBot1 = 0
once bullActive1 = 0
once bullBrkBar1 = 0
once bullBar2 = 0
once bullTop2 = 0
once bullBot2 = 0
once bullActive2 = 0
once bullBrkBar2 = 0
once bullBar3 = 0
once bullTop3 = 0
once bullBot3 = 0
once bullActive3 = 0
once bullBrkBar3 = 0
once bullBar4 = 0
once bullTop4 = 0
once bullBot4 = 0
once bullActive4 = 0
once bullBrkBar4 = 0
once bullCount = 0
// ============================================================
// FIFO BEARISH ZONES (5 slots)
// ============================================================
once bearBar0 = 0
once bearTop0 = 0
once bearBot0 = 0
once bearActive0 = 0
once bearBrkBar0 = 0
once bearBar1 = 0
once bearTop1 = 0
once bearBot1 = 0
once bearActive1 = 0
once bearBrkBar1 = 0
once bearBar2 = 0
once bearTop2 = 0
once bearBot2 = 0
once bearActive2 = 0
once bearBrkBar2 = 0
once bearBar3 = 0
once bearTop3 = 0
once bearBot3 = 0
once bearActive3 = 0
once bearBrkBar3 = 0
once bearBar4 = 0
once bearTop4 = 0
once bearBot4 = 0
once bearActive4 = 0
once bearBrkBar4 = 0
once bearCount = 0
// ============================================================
// REGISTER NEW BULLISH OB
// ============================================================
IF isBullOB THEN
IF bullCount >= maxZones THEN
// FIFO shift
bullBar0 = bullBar1
bullTop0 = bullTop1
bullBot0 = bullBot1
bullActive0 = bullActive1
bullBrkBar0 = bullBrkBar1
bullBar1 = bullBar2
bullTop1 = bullTop2
bullBot1 = bullBot2
bullActive1 = bullActive2
bullBrkBar1 = bullBrkBar2
bullBar2 = bullBar3
bullTop2 = bullTop3
bullBot2 = bullBot3
bullActive2 = bullActive3
bullBrkBar2 = bullBrkBar3
bullBar3 = bullBar4
bullTop3 = bullTop4
bullBot3 = bullBot4
bullActive3 = bullActive4
bullBrkBar3 = bullBrkBar4
IF maxZones = 1 THEN
bullBar0 = barindex[1]
bullTop0 = high[1]
bullBot0 = low[1]
bullActive0 = 1
bullBrkBar0 = 0
ELSIF maxZones = 2 THEN
bullBar1 = barindex[1]
bullTop1 = high[1]
bullBot1 = low[1]
bullActive1 = 1
bullBrkBar1 = 0
ELSIF maxZones = 3 THEN
bullBar2 = barindex[1]
bullTop2 = high[1]
bullBot2 = low[1]
bullActive2 = 1
bullBrkBar2 = 0
ELSIF maxZones = 4 THEN
bullBar3 = barindex[1]
bullTop3 = high[1]
bullBot3 = low[1]
bullActive3 = 1
bullBrkBar3 = 0
ELSIF maxZones = 5 THEN
bullBar4 = barindex[1]
bullTop4 = high[1]
bullBot4 = low[1]
bullActive4 = 1
bullBrkBar4 = 0
ENDIF
ELSE
IF bullCount = 0 THEN
bullBar0 = barindex[1]
bullTop0 = high[1]
bullBot0 = low[1]
bullActive0 = 1
bullBrkBar0 = 0
ELSIF bullCount = 1 THEN
bullBar1 = barindex[1]
bullTop1 = high[1]
bullBot1 = low[1]
bullActive1 = 1
bullBrkBar1 = 0
ELSIF bullCount = 2 THEN
bullBar2 = barindex[1]
bullTop2 = high[1]
bullBot2 = low[1]
bullActive2 = 1
bullBrkBar2 = 0
ELSIF bullCount = 3 THEN
bullBar3 = barindex[1]
bullTop3 = high[1]
bullBot3 = low[1]
bullActive3 = 1
bullBrkBar3 = 0
ELSIF bullCount = 4 THEN
bullBar4 = barindex[1]
bullTop4 = high[1]
bullBot4 = low[1]
bullActive4 = 1
bullBrkBar4 = 0
ENDIF
bullCount = bullCount + 1
ENDIF
ENDIF
// ============================================================
// REGISTER NEW BEARISH OB
// ============================================================
IF isBearOB THEN
IF bearCount >= maxZones THEN
// FIFO shift
bearBar0 = bearBar1
bearTop0 = bearTop1
bearBot0 = bearBot1
bearActive0 = bearActive1
bearBrkBar0 = bearBrkBar1
bearBar1 = bearBar2
bearTop1 = bearTop2
bearBot1 = bearBot2
bearActive1 = bearActive2
bearBrkBar1 = bearBrkBar2
bearBar2 = bearBar3
bearTop2 = bearTop3
bearBot2 = bearBot3
bearActive2 = bearActive3
bearBrkBar2 = bearBrkBar3
bearBar3 = bearBar4
bearTop3 = bearTop4
bearBot3 = bearBot4
bearActive3 = bearActive4
bearBrkBar3 = bearBrkBar4
IF maxZones = 1 THEN
bearBar0 = barindex[1]
bearTop0 = high[1]
bearBot0 = low[1]
bearActive0 = 1
bearBrkBar0 = 0
ELSIF maxZones = 2 THEN
bearBar1 = barindex[1]
bearTop1 = high[1]
bearBot1 = low[1]
bearActive1 = 1
bearBrkBar1 = 0
ELSIF maxZones = 3 THEN
bearBar2 = barindex[1]
bearTop2 = high[1]
bearBot2 = low[1]
bearActive2 = 1
bearBrkBar2 = 0
ELSIF maxZones = 4 THEN
bearBar3 = barindex[1]
bearTop3 = high[1]
bearBot3 = low[1]
bearActive3 = 1
bearBrkBar3 = 0
ELSIF maxZones = 5 THEN
bearBar4 = barindex[1]
bearTop4 = high[1]
bearBot4 = low[1]
bearActive4 = 1
bearBrkBar4 = 0
ENDIF
ELSE
IF bearCount = 0 THEN
bearBar0 = barindex[1]
bearTop0 = high[1]
bearBot0 = low[1]
bearActive0 = 1
bearBrkBar0 = 0
ELSIF bearCount = 1 THEN
bearBar1 = barindex[1]
bearTop1 = high[1]
bearBot1 = low[1]
bearActive1 = 1
bearBrkBar1 = 0
ELSIF bearCount = 2 THEN
bearBar2 = barindex[1]
bearTop2 = high[1]
bearBot2 = low[1]
bearActive2 = 1
bearBrkBar2 = 0
ELSIF bearCount = 3 THEN
bearBar3 = barindex[1]
bearTop3 = high[1]
bearBot3 = low[1]
bearActive3 = 1
bearBrkBar3 = 0
ELSIF bearCount = 4 THEN
bearBar4 = barindex[1]
bearTop4 = high[1]
bearBot4 = low[1]
bearActive4 = 1
bearBrkBar4 = 0
ENDIF
bearCount = bearCount + 1
ENDIF
ENDIF
// ============================================================
// CHECK BROKEN ZONES (every bar)
// ============================================================
IF bullActive0 = 1 AND close < bullBot0 THEN
bullActive0 = 0
bullBrkBar0 = barindex
ENDIF
IF bullActive1 = 1 AND close < bullBot1 THEN
bullActive1 = 0
bullBrkBar1 = barindex
ENDIF
IF bullActive2 = 1 AND close < bullBot2 THEN
bullActive2 = 0
bullBrkBar2 = barindex
ENDIF
IF bullActive3 = 1 AND close < bullBot3 THEN
bullActive3 = 0
bullBrkBar3 = barindex
ENDIF
IF bullActive4 = 1 AND close < bullBot4 THEN
bullActive4 = 0
bullBrkBar4 = barindex
ENDIF
IF bearActive0 = 1 AND close > bearTop0 THEN
bearActive0 = 0
bearBrkBar0 = barindex
ENDIF
IF bearActive1 = 1 AND close > bearTop1 THEN
bearActive1 = 0
bearBrkBar1 = barindex
ENDIF
IF bearActive2 = 1 AND close > bearTop2 THEN
bearActive2 = 0
bearBrkBar2 = barindex
ENDIF
IF bearActive3 = 1 AND close > bearTop3 THEN
bearActive3 = 0
bearBrkBar3 = barindex
ENDIF
IF bearActive4 = 1 AND close > bearTop4 THEN
bearActive4 = 0
bearBrkBar4 = barindex
ENDIF
// ============================================================
// DRAW EVERYTHING (only on last bar update)
// ============================================================
IF islastbarupdate THEN
// --- SIGNAL ARROWS (from $arrays) ---
IF bullSigCount > 0 and showsig THEN
FOR i = 0 TO bullSigCount - 1
drawarrowup($bullSigBar[i], $bullSigPrice[i]) coloured(0,128,128)
NEXT
ENDIF
IF bearSigCount > 0 and showsig THEN
FOR i = 0 TO bearSigCount - 1
drawarrowdown($bearSigBar[i], $bearSigPrice[i]) coloured(255,0,0)
NEXT
ENDIF
// --- BULLISH ZONES (teal active / gray broken) ---
IF bullBar0 > 0 THEN
IF bullActive0 = 1 THEN
drawrectangle(bullBar0, bullTop0, barindex, bullBot0) coloured(0,128,128,180) bordercolor(0,128,128,0)
ELSIF hideOld = 1 THEN
drawrectangle(bullBar0, bullTop0, bullBrkBar0, bullBot0) coloured(128,128,128,30) bordercolor(128,128,128,0)
ENDIF
ENDIF
IF bullBar1 > 0 THEN
IF bullActive1 = 1 THEN
drawrectangle(bullBar1, bullTop1, barindex, bullBot1) coloured(0,128,128,180) bordercolor(0,128,128,0)
ELSIF hideOld = 1 THEN
drawrectangle(bullBar1, bullTop1, bullBrkBar1, bullBot1) coloured(128,128,128,30) bordercolor(128,128,128,0)
ENDIF
ENDIF
IF bullBar2 > 0 THEN
IF bullActive2 = 1 THEN
drawrectangle(bullBar2, bullTop2, barindex, bullBot2) coloured(0,128,128,180) bordercolor(0,128,128,0)
ELSIF hideOld = 1 THEN
drawrectangle(bullBar2, bullTop2, bullBrkBar2, bullBot2) coloured(128,128,128,30) bordercolor(128,128,128,0)
ENDIF
ENDIF
IF bullBar3 > 0 THEN
IF bullActive3 = 1 THEN
drawrectangle(bullBar3, bullTop3, barindex, bullBot3) coloured(0,128,128,180) bordercolor(0,128,128,0)
ELSIF hideOld = 1 THEN
drawrectangle(bullBar3, bullTop3, bullBrkBar3, bullBot3) coloured(128,128,128,30) bordercolor(128,128,128,0)
ENDIF
ENDIF
IF bullBar4 > 0 THEN
IF bullActive4 = 1 THEN
drawrectangle(bullBar4, bullTop4, barindex, bullBot4) coloured(0,128,128,180) bordercolor(0,128,128,0)
ELSIF hideOld = 1 THEN
drawrectangle(bullBar4, bullTop4, bullBrkBar4, bullBot4) coloured(128,128,128,30) bordercolor(128,128,128,0)
ENDIF
ENDIF
// --- BEARISH ZONES (red active / gray broken) ---
IF bearBar0 > 0 THEN
IF bearActive0 = 1 THEN
drawrectangle(bearBar0, bearTop0, barindex, bearBot0) coloured(255,0,0,180) bordercolor(255,0,0,0)
ELSIF hideOld = 1 THEN
drawrectangle(bearBar0, bearTop0, bearBrkBar0, bearBot0) coloured(128,128,128,30) bordercolor(128,128,128,0)
ENDIF
ENDIF
IF bearBar1 > 0 THEN
IF bearActive1 = 1 THEN
drawrectangle(bearBar1, bearTop1, barindex, bearBot1) coloured(255,0,0,180) bordercolor(255,0,0,0)
ELSIF hideOld = 1 THEN
drawrectangle(bearBar1, bearTop1, bearBrkBar1, bearBot1) coloured(128,128,128,30) bordercolor(128,128,128,0)
ENDIF
ENDIF
IF bearBar2 > 0 THEN
IF bearActive2 = 1 THEN
drawrectangle(bearBar2, bearTop2, barindex, bearBot2) coloured(255,0,0,180) bordercolor(255,0,0,0)
ELSIF hideOld = 1 THEN
drawrectangle(bearBar2, bearTop2, bearBrkBar2, bearBot2) coloured(128,128,128,30) bordercolor(128,128,128,0)
ENDIF
ENDIF
IF bearBar3 > 0 THEN
IF bearActive3 = 1 THEN
drawrectangle(bearBar3, bearTop3, barindex, bearBot3) coloured(255,0,0,180) bordercolor(255,0,0,0)
ELSIF hideOld = 1 THEN
drawrectangle(bearBar3, bearTop3, bearBrkBar3, bearBot3) coloured(128,128,128,30) bordercolor(128,128,128,0)
ENDIF
ENDIF
IF bearBar4 > 0 THEN
IF bearActive4 = 1 THEN
drawrectangle(bearBar4, bearTop4, barindex, bearBot4) coloured(255,0,0,180) bordercolor(255,0,0,0)
ELSIF hideOld = 1 THEN
drawrectangle(bearBar4, bearTop4, bearBrkBar4, bearBot4) coloured(128,128,128,30) bordercolor(128,128,128,0)
ENDIF
ENDIF
ENDIF
//---------------------------------------------------------------//
RETURN