Here is a translation of an indicator requested by @ciccarelli-franco
//-------------------------------------------------//
// PRC_Market Cycle Projection Engine
// Adapted from PineScript [AleksDU]
// version = 0
// 30.03.2026
// Iván González @ www.prorealcode.com
// Sharing ProRealTime knowledge
//-------------------------------------------------//
defparam drawonlastbaronly = true
// === INPUTS ===
cycleLen = 50 // Cycle lookback (bars)
showZones = 1 // Show cycle zones (1=yes)
showLevels = 1 // Show key S/R levels (1=yes)
srLookback = 30 // S/R pivot lookback
levelExt = 30 // Extend levels (bars)
showProj = 1 // Show projection (1=yes)
projLen = 100 // Projection bars
projMode = 1 // 0=Cycle Average, 1=Last Cycle, 2=ATR Multiple
showDash = 1 // Show Dashboard (1=yes)
// ================================================================
// MODULE A: CYCLE DETECTION
// ================================================================
// --- ATR ---
atr14 = averagetruerange[14](close)
atrSlow = averagetruerange[cycleLen](close)
// --- Cycle Range ---
cycleHigh = highest[cycleLen](high)
cycleLow = lowest[cycleLen](low)
cycleRange = cycleHigh - cycleLow
cycleMid = (cycleHigh + cycleLow) / 2
// --- Linear Regression Slope (manual, per bar) ---
// i=0 oldest, i=N-1 current → positive slope = uptrend
sumIY = 0
sumCloseN = 0
FOR i = 0 TO cycleLen - 1 DO
sumIY = sumIY + i * close[cycleLen - 1 - i]
sumCloseN = sumCloseN + close[cycleLen - 1 - i]
NEXT
sumI = cycleLen * (cycleLen - 1) / 2
sumII = cycleLen * (cycleLen - 1) * (2 * cycleLen - 1) / 6
lrDenom = cycleLen * sumII - sumI * sumI
IF lrDenom <> 0 THEN
lrSlope = (cycleLen * sumIY - sumI * sumCloseN) / lrDenom
ELSE
lrSlope = 0
ENDIF
// --- Normalized slope ---
lrSlopeNorm = lrSlope / max(atr14, 0.0001)
// --- Volatility state ---
atrRatio = atr14 / max(atrSlow, 0.0001)
isExpanding = (atrRatio > 1.1)
isContracting = (atrRatio < 0.85)
// --- Volume state ---
volSMA = average[20](volume)
volRising = (volume > volSMA * 1.2)
volFalling = (volume < volSMA * 0.8)
// --- Price position (0=bottom, 1=top) ---
pricePos = (close - cycleLow) / max(cycleRange, 0.0001)
// ================================================================
// PHASE CLASSIFICATION
// 1=Accumulation, 2=Markup, 3=Distribution, 4=Markdown, 5=Transition
// ================================================================
phase = 5
IF lrSlopeNorm > 0.1 AND isExpanding THEN
phase = 2
ELSIF lrSlopeNorm < -0.1 AND isExpanding THEN
phase = 4
ELSIF lrSlopeNorm >= -0.1 AND lrSlopeNorm <= 0.1 AND pricePos < 0.4 THEN
phase = 1
ELSIF lrSlopeNorm >= -0.1 AND lrSlopeNorm <= 0.1 AND pricePos >= 0.4 THEN
phase = 3
ENDIF
// Phase colors
IF phase = 1 THEN
rPh = 0
gPh = 188
bPh = 212
ELSIF phase = 2 THEN
rPh = 0
gPh = 230
bPh = 118
ELSIF phase = 3 THEN
rPh = 255
gPh = 152
bPh = 0
ELSIF phase = 4 THEN
rPh = 255
gPh = 82
bPh = 82
ELSE
rPh = 124
gPh = 77
bPh = 255
ENDIF
// ================================================================
// PHASE CHANGE DETECTION + ZONE STORAGE
// ================================================================
once prevPhase = 0
once phaseStartBar = 0
once phaseHi = high
once phaseLo = low
once zoneCnt = 0
phaseChanged = (phase <> prevPhase AND prevPhase <> 0)
IF phaseChanged THEN
// Store ending phase as a zone (FIFO of 6)
IF zoneCnt < 6 THEN
FOR k = zoneCnt DOWNTO 1 DO
$zStart[k] = $zStart[k - 1]
$zEnd[k] = $zEnd[k - 1]
$zHi[k] = $zHi[k - 1]
$zLo[k] = $zLo[k - 1]
$zPh[k] = $zPh[k - 1]
NEXT
zoneCnt = zoneCnt + 1
ELSE
FOR k = 5 DOWNTO 1 DO
$zStart[k] = $zStart[k - 1]
$zEnd[k] = $zEnd[k - 1]
$zHi[k] = $zHi[k - 1]
$zLo[k] = $zLo[k - 1]
$zPh[k] = $zPh[k - 1]
NEXT
ENDIF
zmid = (phaseHi + phaseLo) / 2
$zStart[0] = phaseStartBar
$zEnd[0] = barindex
$zHi[0] = zmid + atr14 * 1.5
$zLo[0] = zmid - atr14 * 1.5
$zPh[0] = prevPhase
// Reset for new phase
prevPhase = phase
phaseStartBar = barindex
phaseHi = high
phaseLo = low
ELSE
IF prevPhase = 0 THEN
prevPhase = phase
phaseStartBar = barindex
ENDIF
IF high > phaseHi THEN
phaseHi = high
ENDIF
IF low < phaseLo THEN
phaseLo = low
ENDIF
ENDIF
phaseDuration = barindex - phaseStartBar
// ================================================================
// BAR COLORING (every bar)
// ================================================================
drawcandle(open, high, low, close) coloured(rPh, gPh, bPh)
// ================================================================
// MODULE B: S/R LEVELS (pivot tracking, every bar)
// ================================================================
once phCnt = 0
once plCnt = 0
isPH = 0
IF barindex >= 2 * srLookback + 1 THEN
IF high[srLookback] = highest[2 * srLookback + 1](high) THEN
isPH = 1
ENDIF
ENDIF
isPL = 0
IF barindex >= 2 * srLookback + 1 THEN
IF low[srLookback] = lowest[2 * srLookback + 1](low) THEN
isPL = 1
ENDIF
ENDIF
// Store last 5 pivots (FIFO)
IF isPH THEN
IF phCnt < 5 THEN
FOR k = phCnt DOWNTO 1 DO
$phVal[k] = $phVal[k - 1]
$phBar[k] = $phBar[k - 1]
NEXT
phCnt = phCnt + 1
ELSE
FOR k = 4 DOWNTO 1 DO
$phVal[k] = $phVal[k - 1]
$phBar[k] = $phBar[k - 1]
NEXT
ENDIF
$phVal[0] = high[srLookback]
$phBar[0] = barindex - srLookback
ENDIF
IF isPL THEN
IF plCnt < 5 THEN
FOR k = plCnt DOWNTO 1 DO
$plVal[k] = $plVal[k - 1]
$plBar[k] = $plBar[k - 1]
NEXT
plCnt = plCnt + 1
ELSE
FOR k = 4 DOWNTO 1 DO
$plVal[k] = $plVal[k - 1]
$plBar[k] = $plBar[k - 1]
NEXT
ENDIF
$plVal[0] = low[srLookback]
$plBar[0] = barindex - srLookback
ENDIF
// ================================================================
// MODULE C: PROJECTION
// ================================================================
projUp = (phase = 1 OR phase = 4)
projAmpl = 0
IF projMode = 0 THEN
projAmpl = atrSlow * sqrt(cycleLen) * 0.4
ELSIF projMode = 1 THEN
projAmpl = cycleRange * 0.75
ELSE
projAmpl = atr14 * 30
ENDIF
// ================================================================
// DRAWING (last bar only)
// ================================================================
IF islastbarupdate THEN
// --- Cycle Zones ---
IF showZones AND zoneCnt > 0 THEN
FOR z = 0 TO zoneCnt - 1 DO
zPh = $zPh[z]
IF zPh = 1 THEN
rZ = 0
gZ = 188
bZ = 212
ELSIF zPh = 2 THEN
rZ = 0
gZ = 230
bZ = 118
ELSIF zPh = 3 THEN
rZ = 255
gZ = 152
bZ = 0
ELSIF zPh = 4 THEN
rZ = 255
gZ = 82
bZ = 82
ELSE
rZ = 124
gZ = 77
bZ = 255
ENDIF
drawrectangle($zStart[z], $zHi[z], $zEnd[z], $zLo[z]) coloured(rZ, gZ, bZ, 200) fillcolor(rZ, gZ, bZ, 30)
NEXT
ENDIF
// --- S/R Levels ---
IF showLevels THEN
// Pivot resistances
IF phCnt > 0 THEN
FOR i = 0 TO phCnt - 1 DO
drawsegment($phBar[i], $phVal[i], barindex + levelExt, $phVal[i]) coloured(255, 82, 82, 160) style(dottedline, 1)
NEXT
ENDIF
// Pivot supports
IF plCnt > 0 THEN
FOR i = 0 TO plCnt - 1 DO
drawsegment($plBar[i], $plVal[i], barindex + levelExt, $plVal[i]) coloured(0, 230, 118, 160) style(dottedline, 1)
NEXT
ENDIF
// Cycle High / Low / Mid
drawsegment(barindex - cycleLen, cycleHigh, barindex + levelExt, cycleHigh) coloured(255, 82, 82) style(line, 2)
drawtext("Cycle High", barindex + levelExt + 3, cycleHigh+0.25*atr14) coloured(255, 82, 82)
drawsegment(barindex - cycleLen, cycleLow, barindex + levelExt, cycleLow) coloured(0, 230, 118) style(line, 2)
drawtext("Cycle Low", barindex + levelExt + 3, cycleLow-0.25*atr14) coloured(0, 230, 118)
drawsegment(barindex - cycleLen, cycleMid, barindex + levelExt, cycleMid) coloured(124, 77, 255, 160) style(dottedline, 1)
drawtext("Mid", barindex + levelExt + 3, cycleMid) coloured(124, 77, 255)
ENDIF
// --- Projection ---
IF showProj THEN
IF projUp THEN
ep = close + projAmpl
rA = 0
gA = 230
bA = 118
ELSE
ep = close - projAmpl
rA = 255
gA = 82
bA = 82
ENDIF
// Main line
drawsegment(barindex, close, barindex + projLen, ep) coloured(rA, gA, bA) style(line, 3)
// Upper/lower bounds
drawsegment(barindex, close + atr14 * 3, barindex + projLen, ep + atr14 * 3) coloured(rA, gA, bA, 160) style(dottedline, 1)
drawsegment(barindex, close - atr14 * 3, barindex + projLen, ep - atr14 * 3) coloured(rA, gA, bA, 160) style(dottedline, 1)
// Label with %
projPct = round(projAmpl / close * 1000) / 10
IF projUp THEN
drawtext("+#projPct#%", barindex + projLen + 6, ep) coloured(rA, gA, bA)
ELSE
drawtext("-#projPct#%", barindex + projLen + 6, ep) coloured(rA, gA, bA)
ENDIF
ENDIF
// --- Dashboard ---
IF showDash THEN
// Phase name
IF phase = 1 THEN
drawtext("Phase: Accumulation", -200, -20) anchor(topright, xshift, yshift) coloured(0, 188, 212)
ELSIF phase = 2 THEN
drawtext("Phase: Markup", -200, -20) anchor(topright, xshift, yshift) coloured(0, 230, 118)
ELSIF phase = 3 THEN
drawtext("Phase: Distribution", -200, -20) anchor(topright, xshift, yshift) coloured(255, 152, 0)
ELSIF phase = 4 THEN
drawtext("Phase: Markdown", -200, -20) anchor(topright, xshift, yshift) coloured(255, 82, 82)
ELSE
drawtext("Phase: Transition", -200, -20) anchor(topright, xshift, yshift) coloured(124, 77, 255)
ENDIF
// Duration
drawtext("Duration: #phaseDuration# bars", -200, -40) anchor(topright, xshift, yshift) coloured(200, 200, 200)
// Strength
cycleStr = round(abs(pricePos - 0.5) * 200)
drawtext("Strength: #cycleStr#/100", -200, -60) anchor(topright, xshift, yshift) coloured(200, 200, 200)
// Position %
posPct = round(pricePos * 100)
drawtext("Position: #posPct#%", -200, -80) anchor(topright, xshift, yshift) coloured(200, 200, 200)
// Volatility
IF isExpanding THEN
drawtext("Volatility: Expanding", -200, -100) anchor(topright, xshift, yshift) coloured(255, 152, 0)
ELSIF isContracting THEN
drawtext("Volatility: Contracting", -200, -100) anchor(topright, xshift, yshift) coloured(0, 188, 212)
ELSE
drawtext("Volatility: Normal", -200, -100) anchor(topright, xshift, yshift) coloured(150, 150, 150)
ENDIF
// Projection
IF projUp THEN
drawtext("Projection: Upward #projPct#%", -200, -120) anchor(topright, xshift, yshift) coloured(0, 230, 118)
ELSE
drawtext("Projection: Downward #projPct#%", -200, -120) anchor(topright, xshift, yshift) coloured(255, 82, 82)
ENDIF
ENDIF
ENDIF
RETURN
The indicator’s logic includes a part that colors the bars. To do this, I’ve created a new indicator.
//-------------------------------------------------//
// PRC_Market Cycle Bar Color
// Companion to PRC_Market Cycle Projection Engine
// version = 0
// 30.03.2026
// Iván González @ www.prorealcode.com
// Sharing ProRealTime knowledge
//-------------------------------------------------//
// === INPUTS ===
cycleLen = 50 // Cycle lookback (bars)
// === CYCLE DETECTION ===
atr14 = averagetruerange[14]
atrSlow = averagetruerange[cycleLen]
cycleHigh = highest[cycleLen](high)
cycleLow = lowest[cycleLen](low)
cycleRange = cycleHigh - cycleLow
// Linear Regression Slope
sumIY = 0
sumCloseN = 0
FOR i = 0 TO cycleLen - 1 DO
sumIY = sumIY + i * close[cycleLen - 1 - i]
sumCloseN = sumCloseN + close[cycleLen - 1 - i]
NEXT
sumI = cycleLen * (cycleLen - 1) / 2
sumII = cycleLen * (cycleLen - 1) * (2 * cycleLen - 1) / 6
lrDenom = cycleLen * sumII - sumI * sumI
IF lrDenom <> 0 THEN
lrSlope = (cycleLen * sumIY - sumI * sumCloseN) / lrDenom
ELSE
lrSlope = 0
ENDIF
lrSlopeNorm = lrSlope / max(atr14, 0.0001)
atrRatio = atr14 / max(atrSlow, 0.0001)
isExpanding = (atrRatio > 1.1)
pricePos = (close - cycleLow) / max(cycleRange, 0.0001)
// Phase classification
IF lrSlopeNorm > 0.1 AND isExpanding THEN
drawcandle(open, high, low, close) coloured(0, 230, 118)
ELSIF lrSlopeNorm < -0.1 AND isExpanding THEN
drawcandle(open, high, low, close) coloured(255, 82, 82)
ELSIF lrSlopeNorm >= -0.1 AND lrSlopeNorm <= 0.1 AND pricePos < 0.4 THEN
drawcandle(open, high, low, close) coloured(0, 188, 212)
ELSIF lrSlopeNorm >= -0.1 AND lrSlopeNorm <= 0.1 AND pricePos >= 0.4 THEN
drawcandle(open, high, low, close) coloured(255, 152, 0)
ELSE
drawcandle(open, high, low, close) coloured(124, 77, 255)
ENDIF
RETURN