An order block is only useful while it is unmitigated — a demand or supply zone price has not yet traded through. The hard part is not drawing it, it is catching the moment price comes back to it. Flipping through hundreds of charts to find the one instrument currently reacting inside a live order block does not scale.
This ProScreener does it in a single pass. It returns the instruments whose latest candle is retesting a live order block — the demand zones that act as support and the supply zones that act as resistance — exactly the boxes drawn by the KN Support Resistance OB indicator. That indicator draws the two-tier (internal + swing) order-block map on the chart; this screener filters the whole universe and brings back only the names sitting inside a zone right now.
It is deliberately a screener of the live zone, not of the break that creates it. A break-of-structure scan would return the bar where the block is born — price already far from the level. This one filters what you actually see on the chart: price reacting inside a zone that is still alive.
In this indicator, support and resistance are order blocks, not horizontal lines:
A retest of demand is the natural place to look for longs; a retest of supply, for shorts. The mode input picks which side you want (or both).
For each live block the screener checks whether the current candle has actually entered the zone:
[bot, top] and the close holds above the bottom (low <= top AND close >= bot) — price dipped into support and did not break it.high >= bot AND close <= top).A block stays live until it is mitigated (price trades through it), with the same High/Low vs Close choice as the indicator.
The detection mirrors the indicator: LuxAlgo leg pivots at two lengths (internal 5, swing 50), and a block is born when the close breaks an uncrossed pivot. But ProScreener does not allow (a) defparam, (b) indexing user variables with [n], or (c) a loop-variable offset on native series (high[i] with i from a loop). So three things change versus the indicator:
parsedLow (with its parsedHigh) for the bullish candidate and a running highest parsedHigh for the bearish one. When the pivot breaks, that running extreme is the block. This closely approximates the indicator’s backward “best-candidate” loop, only differing on the length bars between a pivot forming and being confirmed.prev variables instead of legSwing[1] / legInternal[1], and crosses over rewritten as close > level AND close[1] <= level (the only [1] is on close, a native series — allowed).MAXZ slots, swept for mitigation by fixed index, replacing the last-bar repaint of the indicator.cumTR[1] accumulator); ATR is the indicator’s default anyway.-1 when the nearest zone is support (demand, below), 1 when it is resistance (supply, above).proxATR = 100 (no proximity filter) the screener returns every instrument with an active order-block retest. Load the indicator on three or four of the results: price should sit inside a live box. If they line up, detection is aligned.proxATR to 0.5–1.0 to keep only the names genuinely pressed into the zone, and sort by Dist OB % ascending.mode = 1 for demand retests (longs at support), mode = 2 for supply retests (shorts at resistance), mode = 0 for both.useInternal = 0 keeps just the swing order blocks — the more significant zones, less noise.//----------------------------------------------
//SCR_KN Support Resistance OB - Screener SOPORTES
//Filtra valores en retest de un order block de demanda vivo
//version = 0
//Ivan Gonzalez @ www.prorealcode.com
//Sharing ProRealTime knowledge
//----------------------------------------------
// Geometria del OB por tracking incremental (running min/max).
// === INPUTS ===
internalLength = 5 // Internal Structure Length (>= 2)
swingLength = 50 // Swing Structure Length (>= 10)
obMitigation = 0 // 1 = Close, 0 = High/Low
useInternal = 1 // 1 = internos + swing, 0 = solo swing
mode = 1 // 1 = solo soportes (demanda). 2 = resistencias, 0 = ambos
proxATR = 100 // retest a <= proxATR*ATR(14) (100 = sin filtro)
atrLen = 200 // ATR del filtro de volatilidad (bajar en PRT Complete)
MAXZ = 20
// === ATR ===
atr = averagetruerange[atrLen](close)
atr14 = averagetruerange[14](close)
// === parsed high/low (swap alta volatilidad LuxAlgo) ===
if (high - low) >= 2 * atr then
pHigh = low
pLow = high
else
pHigh = high
pLow = low
endif
// === STATE INIT ===
if barindex = 0 then
prevLegSwing = 0
prevLegInternal = 0
swingHighLevel = 0
swingLowLevel = 0
internalHighLevel = 0
internalLowLevel = 0
swingHighCrossed = 1
swingLowCrossed = 1
internalHighCrossed = 1
internalLowCrossed = 1
sBullLow = low
sBullHigh = high
sBearHigh = high
sBearLow = low
iBullLow = low
iBullHigh = high
iBearHigh = high
iBearLow = low
obPtr = 0
endif
// === SWING LEG ===
if barindex <= swingLength then
legSwing = 0
elsif high[swingLength] > highest[swingLength](high) then
legSwing = 0
elsif low[swingLength] < lowest[swingLength](low) then
legSwing = 1
else
legSwing = prevLegSwing
endif
if legSwing <> prevLegSwing then
if legSwing = 1 then
swingLowLevel = low[swingLength]
swingLowCrossed = 0
sBearHigh = pHigh
sBearLow = pLow
else
swingHighLevel = high[swingLength]
swingHighCrossed = 0
sBullLow = pLow
sBullHigh = pHigh
endif
endif
// === INTERNAL LEG ===
if barindex <= internalLength then
legInternal = 0
elsif high[internalLength] > highest[internalLength](high) then
legInternal = 0
elsif low[internalLength] < lowest[internalLength](low) then
legInternal = 1
else
legInternal = prevLegInternal
endif
if legInternal <> prevLegInternal then
if legInternal = 1 then
internalLowLevel = low[internalLength]
internalLowCrossed = 0
iBearHigh = pHigh
iBearLow = pLow
else
internalHighLevel = high[internalLength]
internalHighCrossed = 0
iBullLow = pLow
iBullHigh = pHigh
endif
endif
// === TRACKING DE CANDIDATOS ===
if swingHighCrossed = 0 then
if pLow < sBullLow then
sBullLow = pLow
sBullHigh = pHigh
endif
endif
if swingLowCrossed = 0 then
if pHigh > sBearHigh then
sBearHigh = pHigh
sBearLow = pLow
endif
endif
if internalHighCrossed = 0 then
if pLow < iBullLow then
iBullLow = pLow
iBullHigh = pHigh
endif
endif
if internalLowCrossed = 0 then
if pHigh > iBearHigh then
iBearHigh = pHigh
iBearLow = pLow
endif
endif
// === ROTURAS -> PUSH OB (buffer circular) ===
if swingHighCrossed = 0 then
if close > swingHighLevel and close[1] <= swingHighLevel then
swingHighCrossed = 1
$obTop[obPtr] = sBullHigh
$obBot[obPtr] = sBullLow
$obBias[obPtr] = 1
$obAct[obPtr] = 1
obPtr = obPtr + 1
if obPtr >= MAXZ then
obPtr = 0
endif
endif
endif
if swingLowCrossed = 0 then
if close < swingLowLevel and close[1] >= swingLowLevel then
swingLowCrossed = 1
$obTop[obPtr] = sBearHigh
$obBot[obPtr] = sBearLow
$obBias[obPtr] = -1
$obAct[obPtr] = 1
obPtr = obPtr + 1
if obPtr >= MAXZ then
obPtr = 0
endif
endif
endif
if useInternal = 1 then
if internalHighCrossed = 0 then
if internalHighLevel <> swingHighLevel then
if close > internalHighLevel and close[1] <= internalHighLevel then
internalHighCrossed = 1
$obTop[obPtr] = iBullHigh
$obBot[obPtr] = iBullLow
$obBias[obPtr] = 1
$obAct[obPtr] = 1
obPtr = obPtr + 1
if obPtr >= MAXZ then
obPtr = 0
endif
endif
endif
endif
endif
if useInternal = 1 then
if internalLowCrossed = 0 then
if internalLowLevel <> swingLowLevel then
if close < internalLowLevel and close[1] >= internalLowLevel then
internalLowCrossed = 1
$obTop[obPtr] = iBearHigh
$obBot[obPtr] = iBearLow
$obBias[obPtr] = -1
$obAct[obPtr] = 1
obPtr = obPtr + 1
if obPtr >= MAXZ then
obPtr = 0
endif
endif
endif
endif
endif
// === MITIGACION ===
if obMitigation = 1 then
mitBear = close
mitBull = close
else
mitBear = high
mitBull = low
endif
for i = 0 to MAXZ - 1 do
if $obAct[i] = 1 then
if $obBias[i] = -1 then
if mitBear > $obTop[i] then
$obAct[i] = 0
endif
else
if mitBull < $obBot[i] then
$obAct[i] = 0
endif
endif
endif
next
// === RETEST: la vela actual toca algun OB vivo ===
matchBull = 0
matchBear = 0
haveDist = 0
minDist = 0
nearBias = 0
for i = 0 to MAXZ - 1 do
if $obAct[i] = 1 then
obT = $obTop[i]
obB = $obBot[i]
obMid = (obT + obB) / 2
if $obBias[i] = 1 then
if low <= obT and close >= obB then
matchBull = matchBull + 1
d = abs(close - obMid)
if haveDist = 0 or d < minDist then
minDist = d
nearBias = -1
haveDist = 1
endif
endif
else
if high >= obB and close <= obT then
matchBear = matchBear + 1
d = abs(close - obMid)
if haveDist = 0 or d < minDist then
minDist = d
nearBias = 1
haveDist = 1
endif
endif
endif
endif
next
// === MODE + PROXIMIDAD ===
matchAny = 0
if mode = 0 and (matchBull > 0 or matchBear > 0) then
matchAny = 1
endif
if mode = 1 and matchBull > 0 then
matchAny = 1
endif
if mode = 2 and matchBear > 0 then
matchAny = 1
endif
if atr14 > 0 then
distAtr = minDist / atr14
else
distAtr = 0
endif
if close > 0 then
minDistPct = minDist / close * 100
else
minDistPct = 0
endif
prevLegSwing = legSwing
prevLegInternal = legInternal
SCREENER[matchAny = 1 and haveDist = 1 and distAtr <= proxATR](minDistPct AS "Dist OB %", nearBias AS "R1 S-1")