Lo he publicado en la librería de indicadores: https://www.prorealcode.com/prorealtime-indicators/ranked-support-resistance-zones/
//--------------------------------------------------------//
// PRC_Ranked Support & Resistance Zones (by Zeiierman)
// version = 0
// 23.06.2026
// Ivan Gonzalez @ www.prorealcode.com
// Sharing ProRealTime knowledge
//--------------------------------------------------------//
defparam drawonlastbaronly = true
// ===== Inputs =====
visibleLimit = 8 // Show Top Zones (1..30)
storedLimit = 60 // Max Stored Zones
pivotSpan = 5 // Pivot Length
minSwingAtr = 0.15 // Min Pivot ATR displacement
absorbAtr = 0.55 // Absorb Similar Zones (ATR multiple)
zoneAtrWidth = 0.40 // Zone Width (ATR multiple)
volLen = 20 // Volume MA Length
trendLen = 50 // Trend EMA Length
breakAtr = 0.12 // Break Close Buffer (ATR multiple)
dirFilter = 0 // 0 = All, 1 = Support only, 2 = Resistance only
showBars = 1 // Show internal strength bars (1/0)
showText = 1 // Show zone label text (1/0)
maxLife = 450 // Zone max age in bars
// ===== Colors (R, G, B) =====
supR = 26
supG = 216
supB = 194
resR = 216
resG = 76
resB = 26
// ===== Core series =====
atrRaw = averagetruerange[14](close)
IF atrRaw <= 0 THEN
atr = pipsize * 10
ELSE
atr = atrRaw
ENDIF
volBase = average[volLen](volume)
trendBase = average[trendLen,1](close)
// ===== Accumulate confirmed pivots into parallel arrays (runs every bar) =====
// --- pivot HIGH -> resistance (dir = 1) ---
IF high < high[pivotSpan] AND highest[pivotSpan](high) < high[pivotSpan] AND high[pivotSpan] > highest[pivotSpan](high)[pivotSpan+1] THEN
pvH = high[pivotSpan]
locMaxH = max(high[pivotSpan-1], high[pivotSpan+1])
sqH = max((pvH - locMaxH) / atr, 0)
IF sqH >= minSwingAtr THEN
$zpx[npiv] = pvH
$zdir[npiv] = 1
$zbar[npiv] = barindex - pivotSpan
$zatr[npiv] = atr
IF volBase > 0 THEN
$zvol[npiv] = volume[pivotSpan] / volBase
ELSE
$zvol[npiv] = 1.0
ENDIF
IF pvH < trendBase THEN
$ztrend[npiv] = 1.0
ELSE
$ztrend[npiv] = 0.0
ENDIF
$zswing[npiv] = sqH
npiv = npiv + 1
ENDIF
ENDIF
// --- pivot LOW -> support (dir = -1) ---
IF low > low[pivotSpan] AND lowest[pivotSpan](low) > low[pivotSpan] AND low[pivotSpan] < lowest[pivotSpan](low)[pivotSpan+1] THEN
pvL = low[pivotSpan]
locMinL = min(low[pivotSpan-1], low[pivotSpan+1])
sqL = max((locMinL - pvL) / atr, 0)
IF sqL >= minSwingAtr THEN
$zpx[npiv] = pvL
$zdir[npiv] = -1
$zbar[npiv] = barindex - pivotSpan
$zatr[npiv] = atr
IF volBase > 0 THEN
$zvol[npiv] = volume[pivotSpan] / volBase
ELSE
$zvol[npiv] = 1.0
ENDIF
IF pvL > trendBase THEN
$ztrend[npiv] = 1.0
ELSE
$ztrend[npiv] = 0.0
ENDIF
$zswing[npiv] = sqL
npiv = npiv + 1
ENDIF
ENDIF
// ===== Heavy processing + drawing: only on the last bar =====
IF islastbarupdate THEN
// --- 1) Collect recent (non-expired) pivots into working arrays ---
nw = 0
IF npiv > 0 THEN
FOR p = npiv - 1 DOWNTO 0 DO
ageP = barindex - $zbar[p]
IF ageP <= maxLife AND nw < storedLimit THEN
half = zoneAtrWidth * $zatr[p] * 0.5
$wtop[nw] = $zpx[p] + half
$wbot[nw] = $zpx[p] - half
$wmid[nw] = $zpx[p]
$wdir[nw] = $zdir[p]
$wbar[nw] = $zbar[p]
$wvol[nw] = $zvol[p]
$wtrend[nw] = $ztrend[p]
$wswing[nw] = $zswing[p]
$walive[nw] = 1
nw = nw + 1
ENDIF
NEXT
ENDIF
// --- 2) Absorb overlapping same-side zones ---
IF nw > 1 THEN
FOR a = 0 TO nw - 2 DO
IF $walive[a] = 1 THEN
FOR b = a + 1 TO nw - 1 DO
IF $walive[b] = 1 THEN
IF $wdir[b] = $wdir[a] THEN
ovTop = min($wtop[a], $wtop[b])
ovBot = max($wbot[a], $wbot[b])
ov = max(ovTop - ovBot, 0)
wA = max($wtop[a] - $wbot[a], pipsize)
wB = max($wtop[b] - $wbot[b], pipsize)
smaller = min(wA, wB)
closeMid = abs($wmid[a] - $wmid[b]) <= absorbAtr * atr
bigOv = ov / smaller >= 0.35
IF closeMid OR bigOv THEN
$wtop[a] = max($wtop[a], $wtop[b])
$wbot[a] = min($wbot[a], $wbot[b])
$wmid[a] = ($wtop[a] + $wbot[a]) / 2
IF $wbar[b] < $wbar[a] THEN
$wbar[a] = $wbar[b]
ENDIF
$wvol[a] = max($wvol[a], $wvol[b])
$wtrend[a] = max($wtrend[a], $wtrend[b])
$wswing[a] = max($wswing[a], $wswing[b])
$walive[b] = 0
ENDIF
ENDIF
ENDIF
NEXT
ENDIF
NEXT
ENDIF
// --- 3) Per-zone history pass (mitigation, touches, broken) + score + strengths ---
nz = 0
IF nw > 0 THEN
FOR z = 0 TO nw - 1 DO
IF $walive[z] = 1 THEN
zTop = $wtop[z]
zBot = $wbot[z]
zMid = $wmid[z]
zDir = $wdir[z]
zWidth = max(zTop - zBot, pipsize)
zAge = barindex - $wbar[z]
breakBuf = breakAtr * atr
touches = 0.0
mitig = 0.0
broke = 0
life = zAge
IF life > maxLife THEN
life = maxLife
ENDIF
FOR j = 0 TO life - 1 DO
hiJ = high[j]
loJ = low[j]
clJ = close[j]
IF hiJ >= zBot AND loJ <= zTop THEN
touches = touches + 0.20
IF zDir = -1 THEN
fillD = zTop - loJ
ELSE
fillD = hiJ - zBot
ENDIF
fillR = fillD / zWidth
IF fillR < 0 THEN
fillR = 0
ENDIF
IF fillR > 1 THEN
fillR = 1
ENDIF
IF fillR > mitig THEN
mitig = fillR
ENDIF
ENDIF
IF zDir = -1 AND clJ < zBot - breakBuf THEN
broke = 1
ENDIF
IF zDir = 1 AND clJ > zTop + breakBuf THEN
broke = 1
ENDIF
NEXT
IF broke = 0 THEN
// ----- score (6 factors, same weights as the original) -----
sizeNorm = min(zWidth / atr, 1.0)
volNorm = min($wvol[z] / 2.0, 1.0)
swingNorm = min($wswing[z] / 1.5, 1.0)
touchNorm = min(touches / 4.0, 1.0)
ageNorm = min(zAge / 450, 1.0)
rawScore = sizeNorm*20.0 + volNorm*18.0 + $wtrend[z]*12.0 + swingNorm*28.0 + touchNorm*16.0 + 10.0
penalty = mitig*22.0 + ageNorm*10.0
sc = rawScore - penalty
IF sc > 100 THEN
sc = 100
ENDIF
IF sc < 0 THEN
sc = 0
ENDIF
// ----- strengths (bull% / bear% with the original's non-linear tiers) -----
IF sc >= 75 THEN
zoneSide = 72 + (sc - 75) * 1.12
ELSIF sc >= 45 THEN
zoneSide = 48 + (sc - 45) * 0.75
ELSE
zoneSide = sc * 1.05
ENDIF
zoneSide = zoneSide + $wtrend[z]*6.0
zoneSide = zoneSide - mitig*28.0
IF zoneSide > 100 THEN
zoneSide = 100
ENDIF
IF zoneSide < 0 THEN
zoneSide = 0
ENDIF
oppSide = 5.0 + mitig*65.0 + sc*0.08
IF oppSide > 100 THEN
oppSide = 100
ENDIF
IF zDir = -1 THEN
bullS = zoneSide
bearS = oppSide
ELSE
bullS = oppSide
bearS = zoneSide
ENDIF
// ----- store final zone -----
$ftop[nz] = zTop
$fbot[nz] = zBot
$fmid[nz] = zMid
$fdir[nz] = zDir
$fbar[nz] = $wbar[z]
$fscore[nz] = sc
$fbull[nz] = bullS
$fbear[nz] = bearS
$fmitig[nz] = mitig
nz = nz + 1
ENDIF
ENDIF
NEXT
ENDIF
// --- 4) Bubble sort final zones by score (descending) ---
IF nz > 1 THEN
FOR i = 0 TO nz - 2 DO
FOR k = 0 TO nz - i - 2 DO
IF $fscore[k] < $fscore[k+1] THEN
t1 = $ftop[k]
$ftop[k] = $ftop[k+1]
$ftop[k+1] = t1
t2 = $fbot[k]
$fbot[k] = $fbot[k+1]
$fbot[k+1] = t2
t3 = $fmid[k]
$fmid[k] = $fmid[k+1]
$fmid[k+1] = t3
t4 = $fdir[k]
$fdir[k] = $fdir[k+1]
$fdir[k+1] = t4
t5 = $fbar[k]
$fbar[k] = $fbar[k+1]
$fbar[k+1] = t5
t6 = $fscore[k]
$fscore[k] = $fscore[k+1]
$fscore[k+1] = t6
t7 = $fbull[k]
$fbull[k] = $fbull[k+1]
$fbull[k+1] = t7
t8 = $fbear[k]
$fbear[k] = $fbear[k+1]
$fbear[k+1] = t8
t9 = $fmitig[k]
$fmitig[k] = $fmitig[k+1]
$fmitig[k+1] = t9
ENDIF
NEXT
NEXT
ENDIF
// --- 5) Draw the top-K visible zones ---
rightX = barindex + 25
shown = 0
IF nz > 0 THEN
FOR z = 0 TO nz - 1 DO
passDir = 0
IF dirFilter = 0 THEN
passDir = 1
ENDIF
IF dirFilter = 1 AND $fdir[z] = -1 THEN
passDir = 1
ENDIF
IF dirFilter = 2 AND $fdir[z] = 1 THEN
passDir = 1
ENDIF
IF passDir = 1 AND shown < visibleLimit THEN
shown = shown + 1
IF $fdir[z] = -1 THEN
cr = supR
cg = supG
cb = supB
ELSE
cr = resR
cg = resG
cb = resB
ENDIF
leftX = $fbar[z]
zTop = $ftop[z]
zBot = $fbot[z]
zMid = ($ftop[z] + $fbot[z]) / 2
// zone body
DRAWRECTANGLE(leftX, zTop, rightX, zBot) COLOURED(cr, cg, cb, 150) FILLCOLOR(cr, cg, cb, 40)
// internal strength bars
IF showBars = 1 THEN
bullPct = round($fbull[z])
bearPct = round($fbear[z])
maxW = (rightX - leftX) * 0.82
bearW = round(maxW * bearPct / 100)
bullW = round(maxW * bullPct / 100)
// bear bar: upper half (top..mid)
DRAWRECTANGLE(leftX, zTop, leftX + bearW, zMid) COLOURED(resR, resG, resB, 0) FILLCOLOR(resR, resG, resB, 210)
// bull bar: lower half (mid..bot)
DRAWRECTANGLE(leftX, zMid, leftX + bullW, zBot) COLOURED(supR, supG, supB, 0) FILLCOLOR(supR, supG, supB, 210)
DRAWTEXT("#bearPct#%", leftX + bearW / 2, (zTop + zMid) / 2) COLOURED(255, 255, 255)
DRAWTEXT("#bullPct#%", leftX + bullW / 2, (zMid + zBot) / 2) COLOURED(255, 255, 255)
ENDIF
// zone label text (Strong / Weak / Mitigated)
IF showText = 1 THEN
IF $fdir[z] = -1 THEN
IF $fmitig[z] >= 0.75 THEN
DRAWTEXT("Mitigated Support", rightX, zMid) COLOURED(cr, cg, cb)
ELSIF $fbull[z] >= 70 THEN
DRAWTEXT("Strong Support", rightX, zMid) COLOURED(cr, cg, cb)
ELSIF $fbull[z] >= 45 THEN
DRAWTEXT("Support", rightX, zMid) COLOURED(cr, cg, cb)
ELSE
DRAWTEXT("Weak Support", rightX, zMid) COLOURED(cr, cg, cb)
ENDIF
ELSE
IF $fmitig[z] >= 0.75 THEN
DRAWTEXT("Mitigated Resistance", rightX, zMid) COLOURED(cr, cg, cb)
ELSIF $fbear[z] >= 70 THEN
DRAWTEXT("Strong Resistance", rightX, zMid) COLOURED(cr, cg, cb)
ELSIF $fbear[z] >= 45 THEN
DRAWTEXT("Resistance", rightX, zMid) COLOURED(cr, cg, cb)
ELSE
DRAWTEXT("Weak Resistance", rightX, zMid) COLOURED(cr, cg, cb)
ENDIF
ENDIF
ENDIF
ENDIF
NEXT
ENDIF
ENDIF
RETURN