Iván González

Trend Exhaustion & Continuation Map

Category: Indicators By: Iván González Created: October 28, 2026, 2:42 PM
October 28, 2026, 2:42 PM
Indicators
0 Comments
Trend Exhaustion & Continuation Map

Introduction

 

Most trend tools answer a single question: is the market going up or down? Trend Exhaustion & Continuation Map by BullByte asks a series of smaller ones, and keeps the answers apart. Has a directional leg actually started? Has it made real progress, measured with closes and not with wicks? Is the current pullback a normal giveback or the start of a failure? Did price reclaim a local reference after a meaningful pullback? Is the move running out of steam? Has the structure that protected the leg been lost?

A strong bar is not automatically a mature trend, an exhaustion warning is not a reversal, and a continuation event is not an instruction to buy. The indicator draws each of those events separately: boxes and markers on the price chart, and an oscillator panel with accepted progress, giveback and the current phase of the leg.

Theory Behind the Indicator

 

A movement scale instead of points. Every threshold is measured in units of typical movement: by default the median of the last 20 true ranges (on intraday charts, a bar that opens after a time gap only counts its own high-low range, so an overnight jump does not distort the scale). The alternative is the median of the absolute close-to-close moves. When a leg is born, the scale is frozen for the whole leg, so its thresholds do not drift in the middle of the move. The same settings work on a stock, an index or a currency pair.

Birth of a leg (DRIVE). A bullish leg starts only when four tests agree on the same bar:

  • the close is at least 0.85 scale units above the close 4 bars earlier;
  • the close clears the highest high of the previous 4 bars by 0.12 scale units;
  • the move is efficient: net displacement divided by the close-to-close path of those 4 bars is at least 0.32;
  • the bar closes up.

The bearish case is the mirror image. The lowest low of the 4 bars before the birth becomes the protected structure of the leg, and it does not move while the leg is alive.

Phases: DRIVE, FORMING, TREND. Progress is counted with closes only: a new accepted close is a close beyond the best close of the leg. The leg becomes FORMING when the best accepted close is 0.5 scale units beyond the birth close, and TREND at 2 scale units with at least 3 bars. Time alone never promotes a leg.

The pullback cycle. When the close falls 0.35 scale units below the best accepted close the leg enters GIVEBACK; a close back in the direction of the leg starts RECOVERY, and a new accepted close resumes the drive.

Continuation. After a pullback of at least 0.25 scale units from the best accepted close, a close above the high of the 2 previous bars is a long continuation trigger (the mirror for short). It does not need the TREND phase.

Exhaustion. A latched warning that needs two things: a giveback of 0.40 scale units in DRIVE (0.70 in FORMING or TREND), and either a failed extension (a wick beyond the best close that closes back inside) or 2 bars without new accepted progress. Once fired it stays on until the leg makes 0.75 scale units of new progress beyond the close where the warning appeared.

Structure failure. A close beyond the protected structure ends the leg. In the default Structure Confirmed mode, an opposite leg can replace it only if its drive also clears an extra 0.30 scale units of displacement, and after a failure only the opposite direction may start the next leg. Losing the structure ends the old direction; it does not promise a move the other way.

Balance. A range of the last 12 bars that is at least 2 scale units wide, inefficient (net move no more than 0.24 of the path) and with the close near its centre, for 4 bars in a row, is accepted as BALANCE. It is released by a close 0.10 scale units beyond the stored range, or by a new drive.

Session gaps. On intraday charts, when more than 3 bars of time pass between one close and the next open (an overnight gap on a stock, a weekend on a currency pair), the analysis starts a fresh segment: no level from the previous session is reused.

Key Features at a Glance

 

  • Leg detection that needs displacement, a structure break and efficiency at the same time.
  • DRIVE, FORMING and TREND phases based on accepted closes, not on time.
  • Pullback, recovery and continuation events, separate from the trend phase.
  • Latched exhaustion warnings that re-arm only after real new progress.
  • Protected structure anchored at the birth of the leg, and a dashed transition frame after a failure.
  • Balance detection for wide, inefficient, centred ranges.
  • Movement scale frozen at the birth of each leg, so the same settings work on any instrument.
  • Scanner with phase, scan state, exhaustion state, extension, giveback and last event.
  • Invisible event series in the panel, ready for ProRealTime alerts.

Two Indicators, One Engine

 

A ProBuilder indicator lives either on the price chart or in its own panel. This one needs both, so it comes as two indicators that run exactly the same engine:

  • Part 1, the panel (PRC_Trend Exhaustion & Continuation Map (panel)): accepted progress, giveback, phase track and the event series for alerts. Apply it in a new panel.
  • Part 2, the price chart (PRC_Trend Exhaustion & Continuation Map (price)): leg frames, phase bands, balance boxes, event markers and the scanner. Apply it on the price.

Both read the same settings block, so if you change a setting in one, change it in the other too.

How to Read the Indicator

 

On the price chart:

  • Solid green or red frame: the full high-low range of a bullish or bearish leg. Coloured bands inside it: the range built in each phase, light for DRIVE, medium for FORMING, dark for TREND.
  • Grey frame with a grey fill: accepted balance. The fill gets darker once the balance has lasted 8 bars.
  • Dashed grey frame: transition after a structure failure or a balance release, drawn after two neutral bars. The old direction is no longer active.
  • Circle under (over) a bar: birth of a bullish (bearish) leg. Cross: the protected structure was lost, at the level of the structure. Square: balance formed. Yellow diamond with a halo: exhaustion warning.
  • Scanner: PHASE (bullish, bearish or neutral), SCAN (direction and phase, balance or transition), EXHAUSTION (the latched warning or the state of the pullback cycle), EXTENSION from the birth close and GIVEBACK from the best accepted close, both in scale units, and the LAST EVENT.

In the panel:

  • Columns above zero: one per bar that made new accepted progress (or started a leg), coloured by phase. Their height is 100 x (1 - e^-x), where x is the new progress in scale units: about 63 for one unit, close to 100 for a big push. It is a bounded intensity, not a probability.
  • Grey field below zero: how far the close has given back from the best accepted close, on the same bounded scale.
  • Phase track near the bottom: a step line at -112 (DRIVE), -124 (FORMING), -136 (TREND) or -148 (BALANCE), coloured by direction and phase.
  • Diamonds: grey on top of a column for a progress milestone (each extra unit of progress), green or red on the zero line for a continuation trigger, yellow on the giveback field for an exhaustion warning.
  • Grey background: balance.

Practical Applications

 

  • Context before the setup: read where the leg is in its life (fresh drive, forming, mature trend, giveback, exhaustion) before acting on any signal.
  • Continuation entries: the continuation trigger marks a reclaim after a meaningful pullback inside an active leg. Combined with the phase, it separates pullbacks in a mature trend from pullbacks in a leg that has barely started.
  • Trade management: the exhaustion warning and the giveback field show when an open position starts losing the progress it made; the cross shows where the leg structure failed.
  • Range filter: balance boxes mark the areas where a directional system is likely to chop.

None of the events is an order: they describe what price did, not what it must do next.

Indicator Configuration

 

All thresholds are in units of the movement scale. Both indicators share these settings:

Segment boundaries and scale:

  • resetOnGap (default 1): 1 = start a fresh segment after a material intraday gap.
  • gapResetMultiple (default 3.0): size of a material gap, in chart bars (1.5 to 20).
  • scaleMode (default 0): 0 = median true range (gap-filtered), 1 = median close-to-close travel.
  • scaleLength (default 20): samples of the median (5 to 100).

Leg detection:

  • driveWindow (default 4), breakWindow (default 4), protectedWindow (default 4): bars of the displacement, of the breakout reference and of the protected structure.
  • birthMoveUnits (default 0.85), birthEfficiency (default 0.32), breakClearanceUnits (default 0.12): minimum displacement, efficiency and breakout margin of a birth.
  • reversalMode (default 0): 0 = Structure Confirmed (an opposite leg needs the protected structure to break), 1 = Early Displacement (a qualifying opposite drive replaces the leg at once, with more flips in a choppy market).
  • reversalBuffer (default 0.30): extra displacement required for an opposite leg in Structure Confirmed mode.

Phases, exhaustion and continuation:

  • formingUnits (default 0.50), trendUnits (default 2.0), minTrendBars (default 3).
  • driveExhaustionUnits (default 0.40), trendExhaustionUnits (default 0.70), failedAttemptBuffer (default 0.05), exhaustionStallBars (default 2), exhaustionRearmUnits (default 0.75).
  • triggerWindow (default 2), minPullbackUnits (default 0.25), givebackPhaseUnits (default 0.35), progressMilestoneUnits (default 1.0).

Balance:

  • balanceWindow (default 12), balanceEfficiency (default 0.24), balanceWidthUnits (default 2.0), balancePersistence (default 4), balanceBreakUnits (default 0.10), balanceMaturity (default 8).

Colours:

  • darkChart (default 0): 0 = colours tuned for the white background of ProRealTime, 1 = the original light palette, meant for dark charts.

Only in the panel: showPaneEvents (default 1) and showGiveback (default 1). Only on the price chart: keepSegments (default 100: about 4 boxes per unit, oldest removed first), showPriceEvents (default 1) and showDashboard (default 1).

Alerts. The panel returns six invisible series, all at 0 when nothing happens: Drive Birth Event (+1 bullish, -1 bearish), Phase Change Event (+2 / -2 forming, +3 / -3 trend), Continuation Event (+1 long, -1 short), Exhaustion Event (+1 in a bullish leg, -1 in a bearish leg), Structure Failure Event (+1 bullish structure lost, -1 bearish) and Balance Event (+1 formed, -1 released). Create a ProRealTime alert on the one you need.

The live bar. The last bar is recalculated on every tick, so its events are provisional until it closes: a birth circle, a phase change or a new box can appear and disappear while the bar is open. Every closed bar is final.

The Code

 

Part 1: the panel (apply it in a new panel)

//---------------------------------------------------------------
//PRC_Trend Exhaustion & Continuation Map (panel)
//version = 0
//22.10.2026
//Iván González @ www.prorealcode.com
//Author: BullByte
//Sharing ProRealTime knowledge
//---------------------------------------------------------------
//PART 1 of 2 - THE OSCILLATOR. Apply this one in its own panel.
//The companion indicator, PRC_Trend Exhaustion & Continuation Map (price),
//draws the leg boxes, the event markers and the scanner on the price chart.
//Both run the same state engine, so they always tell the same story.
//---------------------------------------------------------------
// --- Panel display
showPaneEvents = 1           // 1 = milestone, continuation and exhaustion diamonds in the panel
showGiveback = 1             // 1 = grey giveback field below zero
// ===================== INPUTS =====================
// Thresholds are measured in units of typical movement (the movement scale),
// so the same settings work on instruments with very different prices.
// --- Segment boundaries
resetOnGap = 1               // 1 = reset the active leg on a material intraday time gap (intraday charts only)
gapResetMultiple = 3.0       // gap threshold: interval between the prior close and the next open, in chart bars (1.5 to 20)
// --- Movement scale
scaleMode = 0                // 0 = Median True Range (gap-filtered), 1 = Median Close Travel
scaleLength = 20             // number of samples of the median (5 to 100)
// --- Leg detection
driveWindow = 4              // displacement window (3 to 15)
breakWindow = 4              // breakout reference window: prior bars whose high/low the close must clear (3 to 30)
birthMoveUnits = 0.85        // minimum net displacement to start a leg, in scale units
birthEfficiency = 0.32       // minimum directional efficiency (net move / close-to-close path)
protectedWindow = 4          // bars that set the protected structure anchored at the leg birth (2 to 12)
breakClearanceUnits = 0.12   // the close must clear the breakout level by this fraction of the scale
reversalMode = 0             // 0 = Structure Confirmed, 1 = Early Displacement
reversalBuffer = 0.30        // extra displacement required for an opposite leg in Structure Confirmed mode
// --- Phase transitions
formingUnits = 0.50          // accepted progress beyond the birth close required for FORMING
trendUnits = 2.0             // accepted progress beyond the birth close required for TREND
minTrendBars = 3             // minimum leg bars before TREND (2 to 12)
// --- Exhaustion
driveExhaustionUnits = 0.40  // giveback that flags a stall during DRIVE
trendExhaustionUnits = 0.70  // giveback that flags exhaustion during FORMING and TREND
failedAttemptBuffer = 0.05   // excursion beyond the best accepted close for the failed-extension route
exhaustionStallBars = 2      // alternative route: bars without new accepted progress (1 to 8)
exhaustionRearmUnits = 0.75  // new progress beyond the warning close required to re-arm the warning
// --- Continuation scan
triggerWindow = 2            // local reclaim reference: preceding bars whose high/low the close must clear (1 to 5)
minPullbackUnits = 0.25      // minimum pullback from the best accepted close
givebackPhaseUnits = 0.35    // distance from the best accepted close that starts GIVEBACK
progressMilestoneUnits = 1.0 // extra favourable progress between two milestone markers
// --- Balance
balanceWindow = 12           // balance observation window (5 to 30)
balanceEfficiency = 0.24     // maximum efficiency of a balance
balanceWidthUnits = 2.0      // minimum balance width, in scale units
balancePersistence = 4       // consecutive bars meeting the conditions before balance is accepted (2 to 10)
balanceBreakUnits = 0.10     // close beyond the stored balance boundary needed to release it
balanceMaturity = 8          // bars in balance before its fill gets darker (4 to 20)
// --- Colours
darkChart = 0                // 0 = colours tuned for the white ProRealTime background, 1 = original palette for dark charts
// ===================== STATE ENGINE (identical in both indicators) =====================
// Integer inputs kept inside the original ranges
gapMult = max(1.5, min(20, gapResetMultiple))
scaleLen = max(5, min(100, round(scaleLength)))
driveWin = max(3, min(15, round(driveWindow)))
breakWin = max(3, min(30, round(breakWindow)))
protWin = max(2, min(12, round(protectedWindow)))
trigWin = max(1, min(5, round(triggerWindow)))
balWin = max(5, min(30, round(balanceWindow)))
balPersist = max(2, min(10, round(balancePersistence)))
balMature = max(4, min(20, round(balanceMaturity)))
trendBarsMin = max(2, min(12, round(minTrendBars)))
stallBars = max(1, min(8, round(exhaustionStallBars)))
// TREND always needs a little more progress than FORMING
effTrendUnits = max(trendUnits, formingUnits + 0.1)
// Exact ties on a threshold (an extension of exactly 2.00 units, a giveback of exactly 0.35)
// count the way the rule is written (>=, <=), not the way floating-point rounding falls
epsU = 0.000000001           // tolerance in scale units
epsP = ticksize * 0.000001   // tolerance in price

// State that persists from bar to bar
ONCE regime = 0          // +1 bullish leg, -1 bearish leg, 0 scanning or transition, 2 balance
ONCE transActive = 0
ONCE transBars = 0
ONCE transDir = 0        // after a structure failure, the only direction allowed to replace the leg
ONCE trendPhase = 0      // 1 DRIVE, 2 FORMING, 3 TREND
ONCE legPhase = 0        // 0 drive, 1 giveback, 2 recovery
ONCE legBars = 0
ONCE birthClose = 0
ONCE scaleAtBirth = 0
ONCE bestClose = 0
ONCE protLow = 0
ONCE protHigh = 0
ONCE pbActive = 0
ONCE pbExtreme = 0
ONCE pbRefClose = 0
ONCE barsSinceBest = 0
ONCE lastMilestone = 0
ONCE exLatched = 0
ONCE exRef = 0
ONCE exRefOk = 0
ONCE exStatus = 0        // 0 -, 1 CLEAR, 2 CLEARED, 3 DRIVE STALL, 4 EXHAUSTION WATCH, 5 STRUCTURE FAILED
ONCE lockBalHigh = 0
ONCE lockBalLow = 0
ONCE lastEvent = 0
ONCE balanceBars = 0
ONCE balanceAge = 0
ONCE barsInSeg = 0

// --- Gap handling: on intraday charts a material time gap starts a new segment
tfSec = GetTimeFrame
rawGap = 0
gapSec = 0
IF barindex > 0 THEN
   gapSec = max(0, opentimestamp - timestamp[1])
   IF tfSec < 86400 AND opentimestamp > timestamp[1] THEN
      rawGap = 1
   ENDIF
ENDIF
materialGap = 0
IF rawGap = 1 AND gapSec > tfSec * gapMult THEN
   materialGap = 1
ENDIF
segStart = 0
IF barindex = 0 OR (resetOnGap = 1 AND materialGap = 1) THEN
   segStart = 1
ENDIF

// --- Movement scale: median of the true range (a gap bar only counts its own high-low)
// or of the close-to-close travel (samples that span a gap are left out)
IF barindex = 0 OR rawGap = 1 THEN
   rangeS = high - low
ELSE
   rangeS = max(high - low, max(abs(high - close[1]), abs(low - close[1])))
ENDIF
rangeS = max(rangeS, ticksize)
travelOk = 0
travelS = 0
IF barindex > 0 AND rawGap = 0 THEN
   travelOk = 1
   travelS = max(abs(close - close[1]), ticksize)
ENDIF
medOk = 0
medV = 0
IF barindex >= scaleLen - 1 THEN
   nW = 0
   FOR jw = 0 TO scaleLen - 1 DO
      IF scaleMode = 1 THEN
         IF travelOk[jw] = 1 THEN
            $wq[nW] = travelS[jw]
            nW = nW + 1
         ENDIF
      ELSE
         $wq[nW] = rangeS[jw]
         nW = nW + 1
      ENDIF
   NEXT
   IF nW > 0 THEN
      // nearest-rank median: the ceil(N/2)-th smallest value (Wirth's selection)
      kSel = floor((nW + 1) / 2) - 1
      loQ = 0
      hiQ = nW - 1
      WHILE loQ < hiQ DO
         pvQ = $wq[kSel]
         iQ = loQ
         jQ = hiQ
         WHILE iQ <= jQ DO
            WHILE $wq[iQ] < pvQ DO
               iQ = iQ + 1
            WEND
            WHILE pvQ < $wq[jQ] DO
               jQ = jQ - 1
            WEND
            IF iQ <= jQ THEN
               tmpQ = $wq[iQ]
               $wq[iQ] = $wq[jQ]
               $wq[jQ] = tmpQ
               iQ = iQ + 1
               jQ = jQ - 1
            ENDIF
         WEND
         IF jQ < kSel THEN
            loQ = iQ
         ENDIF
         IF kSel < iQ THEN
            hiQ = jQ
         ENDIF
      WEND
      medV = $wq[kSel]
      medOk = 1
   ENDIF
ENDIF
// while the median warms up, the current bar range is used
IF medOk = 1 AND medV > ticksize + epsP THEN
   safeScale = medV
ELSE
   safeScale = rangeS
ENDIF
safeScale = max(safeScale, ticksize)

// --- Local references: completed bars only, never across the segment boundary
IF segStart = 1 THEN
   avail = 0
ELSE
   avail = barsInSeg
ENDIF
nBrk = min(breakWin, avail)
nPrt = min(protWin, avail)
nTrg = min(trigWin, avail)
nBal = min(balWin, avail)
nRef = max(max(nBrk, nPrt), max(nTrg, nBal))
runHi = 0
runLo = 0
brkHi = 0
brkLo = 0
prtHi = 0
prtLo = 0
trgHi = 0
trgLo = 0
balHi = 0
balLo = 0
IF nRef > 0 THEN
   FOR jr = 1 TO nRef DO
      IF jr = 1 THEN
         runHi = high[1]
         runLo = low[1]
      ELSE
         runHi = max(runHi, high[jr])
         runLo = min(runLo, low[jr])
      ENDIF
      IF jr = nBrk THEN
         brkHi = runHi
         brkLo = runLo
      ENDIF
      IF jr = nPrt THEN
         prtHi = runHi
         prtLo = runLo
      ENDIF
      IF jr = nTrg THEN
         trgHi = runHi
         trgLo = runLo
      ENDIF
      IF jr = nBal THEN
         balHi = runHi
         balLo = runLo
      ENDIF
   NEXT
ENDIF
// close-to-close path of the drive and balance windows
nDrvP = min(driveWin, avail)
nBalP = min(balWin, avail)
nPath = max(nDrvP, nBalP)
runPath = 0
drivePath = 0
balPath = 0
IF nPath > 0 THEN
   FOR jp = 0 TO nPath - 1 DO
      runPath = runPath + abs(close[jp] - close[jp + 1])
      IF jp + 1 = nDrvP THEN
         drivePath = runPath
      ENDIF
      IF jp + 1 = nBalP THEN
         balPath = runPath
      ENDIF
   NEXT
ENDIF

// --- Drive birth: displacement, a clear break of prior structure and efficiency must agree
driveNetOk = 0
driveNet = 0
IF avail >= driveWin THEN
   driveNetOk = 1
   driveNet = close - close[driveWin]
ENDIF
dirEff = 0
IF driveNetOk = 1 AND drivePath > ticksize + epsP THEN
   dirEff = driveNet / drivePath
ENDIF
birthNeed = max(driveWin, max(breakWin, protWin))
birthReady = 0
IF avail >= birthNeed AND driveNetOk = 1 AND drivePath > ticksize + epsP THEN
   birthReady = 1
ENDIF
clearance = safeScale * breakClearanceUnits
bullBirthRaw = 0
IF segStart = 0 AND birthReady = 1 AND nBrk > 0 AND close > brkHi + clearance + epsP AND driveNet >= safeScale * birthMoveUnits - epsP AND dirEff >= birthEfficiency - epsU AND close > open THEN
   bullBirthRaw = 1
ENDIF
bearBirthRaw = 0
IF segStart = 0 AND birthReady = 1 AND nBrk > 0 AND close < brkLo - clearance - epsP AND driveNet <= epsP - safeScale * birthMoveUnits AND dirEff <= epsU - birthEfficiency AND close < open THEN
   bearBirthRaw = 1
ENDIF
// opposite legs need a little more displacement in Structure Confirmed mode
bullRevRaw = 0
IF bullBirthRaw = 1 AND driveNet >= safeScale * (birthMoveUnits + reversalBuffer) - epsP THEN
   bullRevRaw = 1
ENDIF
bearRevRaw = 0
IF bearBirthRaw = 1 AND driveNet <= epsP - safeScale * (birthMoveUnits + reversalBuffer) THEN
   bearRevRaw = 1
ENDIF

// --- Balance: wide enough, inefficient, centred, for several bars in a row
balWidth = balHi - balLo
balMid = (balHi + balLo) * 0.5
balNetOk = 0
balNet = 0
IF avail >= balWin THEN
   balNetOk = 1
   balNet = abs(close - close[balWin])
ENDIF
balEff = 1.0
IF balNetOk = 1 AND balPath > ticksize + epsP THEN
   balEff = balNet / balPath
ENDIF
balanceRaw = 0
IF segStart = 0 AND avail >= balWin AND nBal > 0 AND balWidth >= safeScale * balanceWidthUnits - epsP AND balPath > ticksize + epsP AND balWidth > epsP AND abs(close - balMid) <= balWidth * 0.35 + epsP AND balEff <= balanceEfficiency + epsU THEN
   balanceRaw = 1
ENDIF
IF balanceRaw = 1 THEN
   curBalRun = balanceBars + 1
ELSE
   curBalRun = 0
ENDIF
balConfirmed = 0
IF curBalRun >= balPersist THEN
   balConfirmed = 1
ENDIF

// --- One-bar events
bullBirthEv = 0
bearBirthEv = 0
bullFailEv = 0
bearFailEv = 0
balBirthEv = 0
balReleaseEv = 0
bullFormEv = 0
bearFormEv = 0
bullTrendEv = 0
bearTrendEv = 0
bullContEv = 0
bearContEv = 0
exhaustEv = 0
milestoneEv = 0
bullFailPrice = 0
bearFailPrice = 0
exhaustPrice = 0
impulseOk = 0
impulse = 0

bullLost = 0
IF regime = 1 AND close < protLow THEN
   bullLost = 1
ENDIF
bearLost = 0
IF regime = -1 AND close > protHigh THEN
   bearLost = 1
ENDIF
IF reversalMode = 1 THEN
   bullOpp = bullBirthRaw
   bearOpp = bearBirthRaw
ELSE
   bullOpp = bullRevRaw
   bearOpp = bearRevRaw
ENDIF

IF segStart = 1 THEN
   regime = 0
   trendPhase = 0
   legPhase = 0
   legBars = 0
   pbActive = 0
   barsSinceBest = 0
   exLatched = 0
   exRefOk = 0
   exStatus = 0
   balanceBars = 0
   balanceAge = 0
   barsInSeg = 1
   transActive = 0
   transBars = 0
   transDir = 0
   IF materialGap = 1 AND resetOnGap = 1 THEN
      lastEvent = 1
   ENDIF
ELSE
   barsInSeg = barsInSeg + 1
   balanceBars = curBalRun
   oldRegime = regime
   nextRegime = oldRegime
   IF oldRegime = 0 THEN
      // after a structure failure only the opposite direction may replace the failed leg
      IF transActive = 1 AND transDir <> 0 THEN
         IF transDir = 1 AND bullOpp = 1 THEN
            nextRegime = 1
         ELSIF transDir = -1 AND bearOpp = 1 THEN
            nextRegime = -1
         ELSIF balConfirmed = 1 THEN
            nextRegime = 2
         ENDIF
      ELSE
         IF bullBirthRaw = 1 THEN
            nextRegime = 1
         ELSIF bearBirthRaw = 1 THEN
            nextRegime = -1
         ELSIF balConfirmed = 1 THEN
            nextRegime = 2
         ENDIF
      ENDIF
   ELSIF oldRegime = 1 THEN
      IF bearOpp = 1 AND (reversalMode = 1 OR bullLost = 1) THEN
         nextRegime = -1
         IF bullLost = 1 THEN
            bullFailEv = 1
            bullFailPrice = protLow
         ENDIF
      ELSIF bullLost = 1 THEN
         nextRegime = 0
         bullFailEv = 1
         bullFailPrice = protLow
      ELSIF balConfirmed = 1 THEN
         nextRegime = 2
      ENDIF
   ELSIF oldRegime = -1 THEN
      IF bullOpp = 1 AND (reversalMode = 1 OR bearLost = 1) THEN
         nextRegime = 1
         IF bearLost = 1 THEN
            bearFailEv = 1
            bearFailPrice = protHigh
         ENDIF
      ELSIF bearLost = 1 THEN
         nextRegime = 0
         bearFailEv = 1
         bearFailPrice = protHigh
      ELSIF balConfirmed = 1 THEN
         nextRegime = 2
      ENDIF
   ELSIF oldRegime = 2 THEN
      balBreakUp = close > lockBalHigh + safeScale * balanceBreakUnits + epsP
      balBreakDn = close < lockBalLow - safeScale * balanceBreakUnits - epsP
      IF bullBirthRaw = 1 THEN
         nextRegime = 1
      ELSIF bearBirthRaw = 1 THEN
         nextRegime = -1
      ELSIF balBreakUp OR balBreakDn THEN
         nextRegime = 0
         balReleaseEv = 1
      ENDIF
   ENDIF

   IF nextRegime <> oldRegime THEN
      regime = nextRegime
      IF nextRegime = 1 THEN
         transActive = 0
         transBars = 0
         transDir = 0
         birthClose = close
         scaleAtBirth = safeScale
         bestClose = close
         protLow = prtLo
         pbActive = 0
         trendPhase = 1
         legPhase = 0
         legBars = 1
         barsSinceBest = 0
         lastMilestone = close
         exLatched = 0
         exRefOk = 0
         exStatus = 1
         bullBirthEv = 1
         impulse = 100 * (1 - exp(0 - max(0, (close - close[1]) / scaleAtBirth)))
         impulseOk = 1
         IF oldRegime = -1 THEN
            lastEvent = 2
         ELSIF oldRegime = 2 THEN
            lastEvent = 3
         ELSE
            lastEvent = 4
         ENDIF
         IF oldRegime = 2 THEN
            balReleaseEv = 1
         ENDIF
      ELSIF nextRegime = -1 THEN
         transActive = 0
         transBars = 0
         transDir = 0
         birthClose = close
         scaleAtBirth = safeScale
         bestClose = close
         protHigh = prtHi
         pbActive = 0
         trendPhase = 1
         legPhase = 0
         legBars = 1
         barsSinceBest = 0
         lastMilestone = close
         exLatched = 0
         exRefOk = 0
         exStatus = 1
         bearBirthEv = 1
         impulse = 100 * (1 - exp(0 - max(0, (close[1] - close) / scaleAtBirth)))
         impulseOk = 1
         IF oldRegime = 1 THEN
            lastEvent = 5
         ELSIF oldRegime = 2 THEN
            lastEvent = 6
         ELSE
            lastEvent = 7
         ENDIF
         IF oldRegime = 2 THEN
            balReleaseEv = 1
         ENDIF
      ELSIF nextRegime = 2 THEN
         transActive = 0
         transBars = 0
         transDir = 0
         lockBalHigh = balHi
         lockBalLow = balLo
         pbActive = 0
         trendPhase = 0
         legPhase = 0
         exLatched = 0
         exRefOk = 0
         exStatus = 0
         balBirthEv = 1
         IF oldRegime = 0 THEN
            lastEvent = 8
         ELSE
            lastEvent = 9
         ENDIF
      ELSE
         trendPhase = 0
         legPhase = 0
         pbActive = 0
         IF bullFailEv = 1 THEN
            exLatched = 1
            exStatus = 5
            lastEvent = 10
            transActive = 1
            transBars = 1
            transDir = -1
         ELSIF bearFailEv = 1 THEN
            exLatched = 1
            exStatus = 5
            lastEvent = 11
            transActive = 1
            transBars = 1
            transDir = 1
         ELSE
            exStatus = 0
            IF oldRegime = 2 THEN
               lastEvent = 12
               transActive = 1
               transBars = 1
               transDir = 0
            ENDIF
         ENDIF
      ENDIF
   ELSE
      regime = nextRegime
      IF regime = 0 AND transActive = 1 THEN
         transBars = transBars + 1
      ENDIF
      IF regime = 1 OR regime = -1 THEN
         legBars = legBars + 1
         phaseStart = trendPhase
         priorBest = bestClose
         madeNew = 0
         IF regime = 1 AND close > priorBest THEN
            madeNew = 1
         ENDIF
         IF regime = -1 AND close < priorBest THEN
            madeNew = 1
         ENDIF
         contTrig = 0
         // continuation: a meaningful pullback, then a close through a completed local reference
         IF pbActive = 1 THEN
            IF regime = 1 THEN
               candExt = min(pbExtreme, low)
            ELSE
               candExt = max(pbExtreme, high)
            ENDIF
            pbDepth = regime * (pbRefClose - candExt) / scaleAtBirth
            reclaim = 0
            IF regime = 1 AND nTrg > 0 AND close > trgHi THEN
               reclaim = 1
            ENDIF
            IF regime = -1 AND nTrg > 0 AND close < trgLo THEN
               reclaim = 1
            ENDIF
            IF pbDepth >= minPullbackUnits - epsU AND reclaim = 1 THEN
               contTrig = 1
               IF regime = 1 THEN
                  bullContEv = 1
                  lastEvent = 13
               ELSE
                  bearContEv = 1
                  lastEvent = 14
               ENDIF
               pbActive = 0
               legPhase = 0
            ELSE
               pbExtreme = candExt
               toward = 0
               IF regime = 1 AND close > close[1] THEN
                  toward = 1
               ENDIF
               IF regime = -1 AND close < close[1] THEN
                  toward = 1
               ENDIF
               IF legPhase = 1 AND toward = 1 THEN
                  legPhase = 2
                  IF madeNew = 0 THEN
                     lastEvent = 15
                  ENDIF
               ENDIF
            ENDIF
         ELSIF madeNew = 0 THEN
            adverse = 0
            IF regime = 1 AND close < close[1] THEN
               adverse = 1
            ENDIF
            IF regime = -1 AND close > close[1] THEN
               adverse = 1
            ENDIF
            IF adverse = 1 THEN
               pbActive = 1
               IF regime = 1 THEN
                  pbExtreme = low
               ELSE
                  pbExtreme = high
               ENDIF
               pbRefClose = bestClose
            ENDIF
         ENDIF
         // accepted progress uses closes, not wick-only extremes
         IF madeNew = 1 THEN
            IF pbActive = 1 AND contTrig = 0 THEN
               pbActive = 0
            ENDIF
            newExt = max(0, regime * (close - priorBest) / scaleAtBirth)
            impulse = 100 * (1 - exp(0 - newExt))
            impulseOk = 1
            IF regime * (close - lastMilestone) >= scaleAtBirth * progressMilestoneUnits - epsP THEN
               milestoneEv = 1
               lastMilestone = close
            ENDIF
            IF exLatched = 1 AND exRefOk = 1 THEN
               IF regime * (close - exRef) / scaleAtBirth >= exhaustionRearmUnits - epsU THEN
                  exLatched = 0
                  exRefOk = 0
                  exStatus = 2
                  lastEvent = 16
               ENDIF
            ENDIF
            bestClose = close
            barsSinceBest = 0
            IF legPhase <> 0 THEN
               legPhase = 0
               IF bullContEv = 0 AND bearContEv = 0 THEN
                  lastEvent = 17
               ENDIF
            ENDIF
         ELSE
            barsSinceBest = barsSinceBest + 1
            gbLocal = max(0, regime * (priorBest - close) / scaleAtBirth)
            IF contTrig = 0 AND legPhase = 0 AND gbLocal >= givebackPhaseUnits - epsU THEN
               legPhase = 1
               lastEvent = 18
            ENDIF
         ENDIF
         // FORMING and TREND are progress thresholds, not time-based labels
         extFromBirth = regime * (bestClose - birthClose) / scaleAtBirth
         IF trendPhase = 1 AND extFromBirth >= formingUnits - epsU THEN
            trendPhase = 2
            IF regime = 1 THEN
               bullFormEv = 1
               IF bullContEv = 0 AND bearContEv = 0 THEN
                  lastEvent = 19
               ENDIF
            ELSE
               bearFormEv = 1
               IF bullContEv = 0 AND bearContEv = 0 THEN
                  lastEvent = 20
               ENDIF
            ENDIF
         ELSIF trendPhase = 2 AND legBars >= trendBarsMin AND extFromBirth >= effTrendUnits - epsU THEN
            trendPhase = 3
            IF regime = 1 THEN
               bullTrendEv = 1
               IF bullContEv = 0 AND bearContEv = 0 THEN
                  lastEvent = 21
               ENDIF
            ELSE
               bearTrendEv = 1
               IF bullContEv = 0 AND bearContEv = 0 THEN
                  lastEvent = 22
               ENDIF
            ENDIF
         ENDIF
         // exhaustion is a latched warning: giveback plus a failed extension or a stall
         IF madeNew = 0 AND exLatched = 0 AND contTrig = 0 THEN
            curGb = max(0, regime * (priorBest - close) / scaleAtBirth)
            failedExt = 0
            IF regime = 1 AND high > priorBest + scaleAtBirth * failedAttemptBuffer + epsP AND close <= priorBest THEN
               failedExt = 1
            ENDIF
            IF regime = -1 AND low < priorBest - scaleAtBirth * failedAttemptBuffer - epsP AND close >= priorBest THEN
               failedExt = 1
            ENDIF
            IF phaseStart = 1 THEN
               thrGb = driveExhaustionUnits
            ELSE
               thrGb = trendExhaustionUnits
            ENDIF
            IF curGb >= thrGb - epsU AND (failedExt = 1 OR barsSinceBest >= stallBars) THEN
               exhaustEv = 1
               exLatched = 1
               exRef = priorBest
               exRefOk = 1
               IF phaseStart = 1 THEN
                  exStatus = 3
                  lastEvent = 23
               ELSE
                  exStatus = 4
                  lastEvent = 24
               ENDIF
               IF regime = 1 THEN
                  exhaustPrice = high
               ELSE
                  exhaustPrice = low
               ENDIF
            ENDIF
         ENDIF
         IF exStatus = 2 AND exhaustEv = 0 THEN
            exStatus = 1
         ENDIF
      ENDIF
   ENDIF
   IF regime = 2 THEN
      IF oldRegime = 2 THEN
         balanceAge = balanceAge + 1
      ELSE
         balanceAge = 1
      ENDIF
   ELSE
      balanceAge = 0
   ENDIF
ENDIF
// ===================== END OF STATE ENGINE =====================

// ===================== OSCILLATOR: ACCEPTED PROGRESS, GIVEBACK AND PHASE =====================
// Phase colours on the chart (light or dark background)
IF darkChart = 1 THEN
   bdR = 165
   bdG = 255
   bdB = 207
   bfR = 0
   bfG = 205
   bfB = 118
   sdR = 255
   sdG = 190
   sdB = 198
   yeR = 255
   yeG = 214
   yeB = 64
ELSE
   bdR = 36
   bdG = 168
   bdB = 118
   bfR = 0
   bfG = 150
   bfB = 86
   sdR = 236
   sdG = 104
   sdB = 124
   yeR = 196
   yeG = 128
   yeB = 0
ENDIF
// colour of the current direction and phase (grey outside a leg)
pcR = 132
pcG = 145
pcB = 160
IF regime = 1 THEN
   IF trendPhase = 1 THEN
      pcR = bdR
      pcG = bdG
      pcB = bdB
   ELSIF trendPhase = 2 THEN
      pcR = bfR
      pcG = bfG
      pcB = bfB
   ELSE
      pcR = 0
      pcG = 118
      pcB = 72
   ENDIF
ELSIF regime = -1 THEN
   IF trendPhase = 1 THEN
      pcR = sdR
      pcG = sdG
      pcB = sdB
   ELSIF trendPhase = 2 THEN
      pcR = 245
      pcG = 42
      pcB = 70
   ELSE
      pcR = 170
      pcG = 8
      pcB = 39
   ENDIF
ENDIF

// Accepted close extension: one column per birth or new accepted close
impulseV = 0
impulseA = 0
IF impulseOk = 1 THEN
   impulseV = impulse
   impulseA = 255
ENDIF

// Giveback: how far the close has given back from the best accepted close
gbOk = 0
gbInt = 0
IF regime = 1 AND scaleAtBirth > 0 THEN
   gbOk = 1
   gbInt = 0 - 100 * (1 - exp(0 - max(0, (max(bestClose, close) - close) / scaleAtBirth)))
ELSIF regime = -1 AND scaleAtBirth > 0 THEN
   gbOk = 1
   gbInt = 0 - 100 * (1 - exp(0 - max(0, (close - min(bestClose, close)) / scaleAtBirth)))
ENDIF
// the line and the field only join two bars that both have a value
gbA = 0
gbFillA = 0
IF showGiveback = 1 AND gbOk = 1 AND gbOk[1] = 1 THEN
   gbA = 255
   gbFillA = 56
ENDIF
zeroLine = 0
COLORBETWEEN(gbInt, zeroLine, 132, 145, 160, gbFillA)

// Phase track: DRIVE, FORMING, TREND or BALANCE, drawn as a step line
trackOk = 0
trackV = -150
IF regime = 1 OR regime = -1 THEN
   trackOk = 1
   IF trendPhase = 1 THEN
      trackV = -112
   ELSIF trendPhase = 2 THEN
      trackV = -124
   ELSE
      trackV = -136
   ENDIF
ELSIF regime = 2 THEN
   trackOk = 1
   trackV = -148
ENDIF
trackA = 0
IF trackOk = 1 AND trackOk[1] = 1 THEN
   trackA = 255
   // a change of level is drawn as a step: horizontal at the old level, then vertical
   IF trackV <> trackV[1] THEN
      trackA = 0
      DRAWSEGMENT(barindex - 1, trackV[1], barindex, trackV[1]) COLOURED(pcR, pcG, pcB, 255) STYLE(line, 5)
      DRAWSEGMENT(barindex, trackV[1], barindex, trackV) COLOURED(pcR, pcG, pcB, 255) STYLE(line, 5)
   ENDIF
ENDIF

// Pane event markers
IF showPaneEvents = 1 THEN
   IF milestoneEv = 1 THEN
      DRAWTEXT("◆", barindex, impulse) COLOURED(132, 145, 160, 255)
   ENDIF
   IF bullContEv = 1 THEN
      DRAWTEXT("◆", barindex, 0) COLOURED(bfR, bfG, bfB, 255)
   ENDIF
   IF bearContEv = 1 THEN
      DRAWTEXT("◆", barindex, 0) COLOURED(245, 42, 70, 255)
   ENDIF
   IF exhaustEv = 1 THEN
      DRAWTEXT("◆", barindex, gbInt) COLOURED(yeR, yeG, yeB, 255)
   ENDIF
ENDIF

// Balance shades the pane background
IF regime = 2 THEN
   BACKGROUNDCOLOR(132, 145, 160, 13)
ENDIF

// ===================== CONFIRMED EVENTS FOR ALERTS =====================
// Invisible series: create a ProRealTime alert on any of them (value at bar close).
evBirth = bullBirthEv - bearBirthEv                                          // +1 bullish drive birth, -1 bearish
evPhase = 2 * bullFormEv + 3 * bullTrendEv - 2 * bearFormEv - 3 * bearTrendEv // +-2 FORMING, +-3 TREND
evCont = bullContEv - bearContEv                                             // +1 long trigger, -1 short trigger
evExhaust = exhaustEv * regime                                               // +1 in a bullish leg, -1 in a bearish leg
evFailure = bullFailEv - bearFailEv                                          // +1 bullish structure failed, -1 bearish
evBalance = balBirthEv - balReleaseEv                                        // +1 balance formed, -1 balance released

RETURN impulseV COLOURED(pcR, pcG, pcB, impulseA) STYLE(histogram) AS "Accepted Close Extension", gbInt COLOURED(132, 145, 160, gbA) STYLE(line, 1) AS "Giveback Boundary", trackV COLOURED(pcR, pcG, pcB, trackA) STYLE(line, 5) AS "Leg Phase Track", 100 COLOURED(132, 145, 160, 33) STYLE(line, 1) AS "Drive Intensity Ceiling", 50 COLOURED(132, 145, 160, 26) STYLE(line, 1) AS "Drive Reference", 0 COLOURED(132, 145, 160, 158) STYLE(line, 1) AS "Drive Baseline", -50 COLOURED(132, 145, 160, 26) STYLE(line, 1) AS "Giveback Reference", -100 COLOURED(132, 145, 160, 33) STYLE(line, 1) AS "Giveback Intensity Ceiling", -150 COLOURED(132, 145, 160, 26) STYLE(line, 1) AS "Phase Track Base", evBirth COLOURED(0, 0, 0, 0) AS "Drive Birth Event", evPhase COLOURED(0, 0, 0, 0) AS "Phase Change Event", evCont COLOURED(0, 0, 0, 0) AS "Continuation Event", evExhaust COLOURED(0, 0, 0, 0) AS "Exhaustion Event", evFailure COLOURED(0, 0, 0, 0) AS "Structure Failure Event", evBalance COLOURED(0, 0, 0, 0) AS "Balance Event"

Part 2: the price chart (apply it on the price)

//---------------------------------------------------------------
//PRC_Trend Exhaustion & Continuation Map (price)
//version = 0
//22.10.2026
//Iván González @ www.prorealcode.com
//Author: BullByte
//Sharing ProRealTime knowledge
//---------------------------------------------------------------
//PART 2 of 2 - THE PRICE CHART. Apply this one ON the price.
//The companion indicator, PRC_Trend Exhaustion & Continuation Map (panel),
//plots the accepted progress, the giveback and the phase track in its own panel.
//Both run the same state engine, so they always tell the same story.
//---------------------------------------------------------------
defparam drawonlastbaronly = true
// --- Price chart display
keepSegments = 100           // historical drawing capacity: about 4 boxes per unit (10 to 180)
showPriceEvents = 1          // 1 = drive births, structure failures, balance and exhaustion markers
showDashboard = 1            // 1 = scanner in the top-right corner
// ===================== INPUTS =====================
// Thresholds are measured in units of typical movement (the movement scale),
// so the same settings work on instruments with very different prices.
// --- Segment boundaries
resetOnGap = 1               // 1 = reset the active leg on a material intraday time gap (intraday charts only)
gapResetMultiple = 3.0       // gap threshold: interval between the prior close and the next open, in chart bars (1.5 to 20)
// --- Movement scale
scaleMode = 0                // 0 = Median True Range (gap-filtered), 1 = Median Close Travel
scaleLength = 20             // number of samples of the median (5 to 100)
// --- Leg detection
driveWindow = 4              // displacement window (3 to 15)
breakWindow = 4              // breakout reference window: prior bars whose high/low the close must clear (3 to 30)
birthMoveUnits = 0.85        // minimum net displacement to start a leg, in scale units
birthEfficiency = 0.32       // minimum directional efficiency (net move / close-to-close path)
protectedWindow = 4          // bars that set the protected structure anchored at the leg birth (2 to 12)
breakClearanceUnits = 0.12   // the close must clear the breakout level by this fraction of the scale
reversalMode = 0             // 0 = Structure Confirmed, 1 = Early Displacement
reversalBuffer = 0.30        // extra displacement required for an opposite leg in Structure Confirmed mode
// --- Phase transitions
formingUnits = 0.50          // accepted progress beyond the birth close required for FORMING
trendUnits = 2.0             // accepted progress beyond the birth close required for TREND
minTrendBars = 3             // minimum leg bars before TREND (2 to 12)
// --- Exhaustion
driveExhaustionUnits = 0.40  // giveback that flags a stall during DRIVE
trendExhaustionUnits = 0.70  // giveback that flags exhaustion during FORMING and TREND
failedAttemptBuffer = 0.05   // excursion beyond the best accepted close for the failed-extension route
exhaustionStallBars = 2      // alternative route: bars without new accepted progress (1 to 8)
exhaustionRearmUnits = 0.75  // new progress beyond the warning close required to re-arm the warning
// --- Continuation scan
triggerWindow = 2            // local reclaim reference: preceding bars whose high/low the close must clear (1 to 5)
minPullbackUnits = 0.25      // minimum pullback from the best accepted close
givebackPhaseUnits = 0.35    // distance from the best accepted close that starts GIVEBACK
progressMilestoneUnits = 1.0 // extra favourable progress between two milestone markers
// --- Balance
balanceWindow = 12           // balance observation window (5 to 30)
balanceEfficiency = 0.24     // maximum efficiency of a balance
balanceWidthUnits = 2.0      // minimum balance width, in scale units
balancePersistence = 4       // consecutive bars meeting the conditions before balance is accepted (2 to 10)
balanceBreakUnits = 0.10     // close beyond the stored balance boundary needed to release it
balanceMaturity = 8          // bars in balance before its fill gets darker (4 to 20)
// --- Colours
darkChart = 0                // 0 = colours tuned for the white ProRealTime background, 1 = original palette for dark charts
// ===================== STATE ENGINE (identical in both indicators) =====================
// Integer inputs kept inside the original ranges
gapMult = max(1.5, min(20, gapResetMultiple))
scaleLen = max(5, min(100, round(scaleLength)))
driveWin = max(3, min(15, round(driveWindow)))
breakWin = max(3, min(30, round(breakWindow)))
protWin = max(2, min(12, round(protectedWindow)))
trigWin = max(1, min(5, round(triggerWindow)))
balWin = max(5, min(30, round(balanceWindow)))
balPersist = max(2, min(10, round(balancePersistence)))
balMature = max(4, min(20, round(balanceMaturity)))
trendBarsMin = max(2, min(12, round(minTrendBars)))
stallBars = max(1, min(8, round(exhaustionStallBars)))
// TREND always needs a little more progress than FORMING
effTrendUnits = max(trendUnits, formingUnits + 0.1)
// Exact ties on a threshold (an extension of exactly 2.00 units, a giveback of exactly 0.35)
// count the way the rule is written (>=, <=), not the way floating-point rounding falls
epsU = 0.000000001           // tolerance in scale units
epsP = ticksize * 0.000001   // tolerance in price

// State that persists from bar to bar
ONCE regime = 0          // +1 bullish leg, -1 bearish leg, 0 scanning or transition, 2 balance
ONCE transActive = 0
ONCE transBars = 0
ONCE transDir = 0        // after a structure failure, the only direction allowed to replace the leg
ONCE trendPhase = 0      // 1 DRIVE, 2 FORMING, 3 TREND
ONCE legPhase = 0        // 0 drive, 1 giveback, 2 recovery
ONCE legBars = 0
ONCE birthClose = 0
ONCE scaleAtBirth = 0
ONCE bestClose = 0
ONCE protLow = 0
ONCE protHigh = 0
ONCE pbActive = 0
ONCE pbExtreme = 0
ONCE pbRefClose = 0
ONCE barsSinceBest = 0
ONCE lastMilestone = 0
ONCE exLatched = 0
ONCE exRef = 0
ONCE exRefOk = 0
ONCE exStatus = 0        // 0 -, 1 CLEAR, 2 CLEARED, 3 DRIVE STALL, 4 EXHAUSTION WATCH, 5 STRUCTURE FAILED
ONCE lockBalHigh = 0
ONCE lockBalLow = 0
ONCE lastEvent = 0
ONCE balanceBars = 0
ONCE balanceAge = 0
ONCE barsInSeg = 0

// --- Gap handling: on intraday charts a material time gap starts a new segment
tfSec = GetTimeFrame
rawGap = 0
gapSec = 0
IF barindex > 0 THEN
   gapSec = max(0, opentimestamp - timestamp[1])
   IF tfSec < 86400 AND opentimestamp > timestamp[1] THEN
      rawGap = 1
   ENDIF
ENDIF
materialGap = 0
IF rawGap = 1 AND gapSec > tfSec * gapMult THEN
   materialGap = 1
ENDIF
segStart = 0
IF barindex = 0 OR (resetOnGap = 1 AND materialGap = 1) THEN
   segStart = 1
ENDIF

// --- Movement scale: median of the true range (a gap bar only counts its own high-low)
// or of the close-to-close travel (samples that span a gap are left out)
IF barindex = 0 OR rawGap = 1 THEN
   rangeS = high - low
ELSE
   rangeS = max(high - low, max(abs(high - close[1]), abs(low - close[1])))
ENDIF
rangeS = max(rangeS, ticksize)
travelOk = 0
travelS = 0
IF barindex > 0 AND rawGap = 0 THEN
   travelOk = 1
   travelS = max(abs(close - close[1]), ticksize)
ENDIF
medOk = 0
medV = 0
IF barindex >= scaleLen - 1 THEN
   nW = 0
   FOR jw = 0 TO scaleLen - 1 DO
      IF scaleMode = 1 THEN
         IF travelOk[jw] = 1 THEN
            $wq[nW] = travelS[jw]
            nW = nW + 1
         ENDIF
      ELSE
         $wq[nW] = rangeS[jw]
         nW = nW + 1
      ENDIF
   NEXT
   IF nW > 0 THEN
      // nearest-rank median: the ceil(N/2)-th smallest value (Wirth's selection)
      kSel = floor((nW + 1) / 2) - 1
      loQ = 0
      hiQ = nW - 1
      WHILE loQ < hiQ DO
         pvQ = $wq[kSel]
         iQ = loQ
         jQ = hiQ
         WHILE iQ <= jQ DO
            WHILE $wq[iQ] < pvQ DO
               iQ = iQ + 1
            WEND
            WHILE pvQ < $wq[jQ] DO
               jQ = jQ - 1
            WEND
            IF iQ <= jQ THEN
               tmpQ = $wq[iQ]
               $wq[iQ] = $wq[jQ]
               $wq[jQ] = tmpQ
               iQ = iQ + 1
               jQ = jQ - 1
            ENDIF
         WEND
         IF jQ < kSel THEN
            loQ = iQ
         ENDIF
         IF kSel < iQ THEN
            hiQ = jQ
         ENDIF
      WEND
      medV = $wq[kSel]
      medOk = 1
   ENDIF
ENDIF
// while the median warms up, the current bar range is used
IF medOk = 1 AND medV > ticksize + epsP THEN
   safeScale = medV
ELSE
   safeScale = rangeS
ENDIF
safeScale = max(safeScale, ticksize)

// --- Local references: completed bars only, never across the segment boundary
IF segStart = 1 THEN
   avail = 0
ELSE
   avail = barsInSeg
ENDIF
nBrk = min(breakWin, avail)
nPrt = min(protWin, avail)
nTrg = min(trigWin, avail)
nBal = min(balWin, avail)
nRef = max(max(nBrk, nPrt), max(nTrg, nBal))
runHi = 0
runLo = 0
brkHi = 0
brkLo = 0
prtHi = 0
prtLo = 0
trgHi = 0
trgLo = 0
balHi = 0
balLo = 0
IF nRef > 0 THEN
   FOR jr = 1 TO nRef DO
      IF jr = 1 THEN
         runHi = high[1]
         runLo = low[1]
      ELSE
         runHi = max(runHi, high[jr])
         runLo = min(runLo, low[jr])
      ENDIF
      IF jr = nBrk THEN
         brkHi = runHi
         brkLo = runLo
      ENDIF
      IF jr = nPrt THEN
         prtHi = runHi
         prtLo = runLo
      ENDIF
      IF jr = nTrg THEN
         trgHi = runHi
         trgLo = runLo
      ENDIF
      IF jr = nBal THEN
         balHi = runHi
         balLo = runLo
      ENDIF
   NEXT
ENDIF
// close-to-close path of the drive and balance windows
nDrvP = min(driveWin, avail)
nBalP = min(balWin, avail)
nPath = max(nDrvP, nBalP)
runPath = 0
drivePath = 0
balPath = 0
IF nPath > 0 THEN
   FOR jp = 0 TO nPath - 1 DO
      runPath = runPath + abs(close[jp] - close[jp + 1])
      IF jp + 1 = nDrvP THEN
         drivePath = runPath
      ENDIF
      IF jp + 1 = nBalP THEN
         balPath = runPath
      ENDIF
   NEXT
ENDIF

// --- Drive birth: displacement, a clear break of prior structure and efficiency must agree
driveNetOk = 0
driveNet = 0
IF avail >= driveWin THEN
   driveNetOk = 1
   driveNet = close - close[driveWin]
ENDIF
dirEff = 0
IF driveNetOk = 1 AND drivePath > ticksize + epsP THEN
   dirEff = driveNet / drivePath
ENDIF
birthNeed = max(driveWin, max(breakWin, protWin))
birthReady = 0
IF avail >= birthNeed AND driveNetOk = 1 AND drivePath > ticksize + epsP THEN
   birthReady = 1
ENDIF
clearance = safeScale * breakClearanceUnits
bullBirthRaw = 0
IF segStart = 0 AND birthReady = 1 AND nBrk > 0 AND close > brkHi + clearance + epsP AND driveNet >= safeScale * birthMoveUnits - epsP AND dirEff >= birthEfficiency - epsU AND close > open THEN
   bullBirthRaw = 1
ENDIF
bearBirthRaw = 0
IF segStart = 0 AND birthReady = 1 AND nBrk > 0 AND close < brkLo - clearance - epsP AND driveNet <= epsP - safeScale * birthMoveUnits AND dirEff <= epsU - birthEfficiency AND close < open THEN
   bearBirthRaw = 1
ENDIF
// opposite legs need a little more displacement in Structure Confirmed mode
bullRevRaw = 0
IF bullBirthRaw = 1 AND driveNet >= safeScale * (birthMoveUnits + reversalBuffer) - epsP THEN
   bullRevRaw = 1
ENDIF
bearRevRaw = 0
IF bearBirthRaw = 1 AND driveNet <= epsP - safeScale * (birthMoveUnits + reversalBuffer) THEN
   bearRevRaw = 1
ENDIF

// --- Balance: wide enough, inefficient, centred, for several bars in a row
balWidth = balHi - balLo
balMid = (balHi + balLo) * 0.5
balNetOk = 0
balNet = 0
IF avail >= balWin THEN
   balNetOk = 1
   balNet = abs(close - close[balWin])
ENDIF
balEff = 1.0
IF balNetOk = 1 AND balPath > ticksize + epsP THEN
   balEff = balNet / balPath
ENDIF
balanceRaw = 0
IF segStart = 0 AND avail >= balWin AND nBal > 0 AND balWidth >= safeScale * balanceWidthUnits - epsP AND balPath > ticksize + epsP AND balWidth > epsP AND abs(close - balMid) <= balWidth * 0.35 + epsP AND balEff <= balanceEfficiency + epsU THEN
   balanceRaw = 1
ENDIF
IF balanceRaw = 1 THEN
   curBalRun = balanceBars + 1
ELSE
   curBalRun = 0
ENDIF
balConfirmed = 0
IF curBalRun >= balPersist THEN
   balConfirmed = 1
ENDIF

// --- One-bar events
bullBirthEv = 0
bearBirthEv = 0
bullFailEv = 0
bearFailEv = 0
balBirthEv = 0
balReleaseEv = 0
bullFormEv = 0
bearFormEv = 0
bullTrendEv = 0
bearTrendEv = 0
bullContEv = 0
bearContEv = 0
exhaustEv = 0
milestoneEv = 0
bullFailPrice = 0
bearFailPrice = 0
exhaustPrice = 0
impulseOk = 0
impulse = 0

bullLost = 0
IF regime = 1 AND close < protLow THEN
   bullLost = 1
ENDIF
bearLost = 0
IF regime = -1 AND close > protHigh THEN
   bearLost = 1
ENDIF
IF reversalMode = 1 THEN
   bullOpp = bullBirthRaw
   bearOpp = bearBirthRaw
ELSE
   bullOpp = bullRevRaw
   bearOpp = bearRevRaw
ENDIF

IF segStart = 1 THEN
   regime = 0
   trendPhase = 0
   legPhase = 0
   legBars = 0
   pbActive = 0
   barsSinceBest = 0
   exLatched = 0
   exRefOk = 0
   exStatus = 0
   balanceBars = 0
   balanceAge = 0
   barsInSeg = 1
   transActive = 0
   transBars = 0
   transDir = 0
   IF materialGap = 1 AND resetOnGap = 1 THEN
      lastEvent = 1
   ENDIF
ELSE
   barsInSeg = barsInSeg + 1
   balanceBars = curBalRun
   oldRegime = regime
   nextRegime = oldRegime
   IF oldRegime = 0 THEN
      // after a structure failure only the opposite direction may replace the failed leg
      IF transActive = 1 AND transDir <> 0 THEN
         IF transDir = 1 AND bullOpp = 1 THEN
            nextRegime = 1
         ELSIF transDir = -1 AND bearOpp = 1 THEN
            nextRegime = -1
         ELSIF balConfirmed = 1 THEN
            nextRegime = 2
         ENDIF
      ELSE
         IF bullBirthRaw = 1 THEN
            nextRegime = 1
         ELSIF bearBirthRaw = 1 THEN
            nextRegime = -1
         ELSIF balConfirmed = 1 THEN
            nextRegime = 2
         ENDIF
      ENDIF
   ELSIF oldRegime = 1 THEN
      IF bearOpp = 1 AND (reversalMode = 1 OR bullLost = 1) THEN
         nextRegime = -1
         IF bullLost = 1 THEN
            bullFailEv = 1
            bullFailPrice = protLow
         ENDIF
      ELSIF bullLost = 1 THEN
         nextRegime = 0
         bullFailEv = 1
         bullFailPrice = protLow
      ELSIF balConfirmed = 1 THEN
         nextRegime = 2
      ENDIF
   ELSIF oldRegime = -1 THEN
      IF bullOpp = 1 AND (reversalMode = 1 OR bearLost = 1) THEN
         nextRegime = 1
         IF bearLost = 1 THEN
            bearFailEv = 1
            bearFailPrice = protHigh
         ENDIF
      ELSIF bearLost = 1 THEN
         nextRegime = 0
         bearFailEv = 1
         bearFailPrice = protHigh
      ELSIF balConfirmed = 1 THEN
         nextRegime = 2
      ENDIF
   ELSIF oldRegime = 2 THEN
      balBreakUp = close > lockBalHigh + safeScale * balanceBreakUnits + epsP
      balBreakDn = close < lockBalLow - safeScale * balanceBreakUnits - epsP
      IF bullBirthRaw = 1 THEN
         nextRegime = 1
      ELSIF bearBirthRaw = 1 THEN
         nextRegime = -1
      ELSIF balBreakUp OR balBreakDn THEN
         nextRegime = 0
         balReleaseEv = 1
      ENDIF
   ENDIF

   IF nextRegime <> oldRegime THEN
      regime = nextRegime
      IF nextRegime = 1 THEN
         transActive = 0
         transBars = 0
         transDir = 0
         birthClose = close
         scaleAtBirth = safeScale
         bestClose = close
         protLow = prtLo
         pbActive = 0
         trendPhase = 1
         legPhase = 0
         legBars = 1
         barsSinceBest = 0
         lastMilestone = close
         exLatched = 0
         exRefOk = 0
         exStatus = 1
         bullBirthEv = 1
         impulse = 100 * (1 - exp(0 - max(0, (close - close[1]) / scaleAtBirth)))
         impulseOk = 1
         IF oldRegime = -1 THEN
            lastEvent = 2
         ELSIF oldRegime = 2 THEN
            lastEvent = 3
         ELSE
            lastEvent = 4
         ENDIF
         IF oldRegime = 2 THEN
            balReleaseEv = 1
         ENDIF
      ELSIF nextRegime = -1 THEN
         transActive = 0
         transBars = 0
         transDir = 0
         birthClose = close
         scaleAtBirth = safeScale
         bestClose = close
         protHigh = prtHi
         pbActive = 0
         trendPhase = 1
         legPhase = 0
         legBars = 1
         barsSinceBest = 0
         lastMilestone = close
         exLatched = 0
         exRefOk = 0
         exStatus = 1
         bearBirthEv = 1
         impulse = 100 * (1 - exp(0 - max(0, (close[1] - close) / scaleAtBirth)))
         impulseOk = 1
         IF oldRegime = 1 THEN
            lastEvent = 5
         ELSIF oldRegime = 2 THEN
            lastEvent = 6
         ELSE
            lastEvent = 7
         ENDIF
         IF oldRegime = 2 THEN
            balReleaseEv = 1
         ENDIF
      ELSIF nextRegime = 2 THEN
         transActive = 0
         transBars = 0
         transDir = 0
         lockBalHigh = balHi
         lockBalLow = balLo
         pbActive = 0
         trendPhase = 0
         legPhase = 0
         exLatched = 0
         exRefOk = 0
         exStatus = 0
         balBirthEv = 1
         IF oldRegime = 0 THEN
            lastEvent = 8
         ELSE
            lastEvent = 9
         ENDIF
      ELSE
         trendPhase = 0
         legPhase = 0
         pbActive = 0
         IF bullFailEv = 1 THEN
            exLatched = 1
            exStatus = 5
            lastEvent = 10
            transActive = 1
            transBars = 1
            transDir = -1
         ELSIF bearFailEv = 1 THEN
            exLatched = 1
            exStatus = 5
            lastEvent = 11
            transActive = 1
            transBars = 1
            transDir = 1
         ELSE
            exStatus = 0
            IF oldRegime = 2 THEN
               lastEvent = 12
               transActive = 1
               transBars = 1
               transDir = 0
            ENDIF
         ENDIF
      ENDIF
   ELSE
      regime = nextRegime
      IF regime = 0 AND transActive = 1 THEN
         transBars = transBars + 1
      ENDIF
      IF regime = 1 OR regime = -1 THEN
         legBars = legBars + 1
         phaseStart = trendPhase
         priorBest = bestClose
         madeNew = 0
         IF regime = 1 AND close > priorBest THEN
            madeNew = 1
         ENDIF
         IF regime = -1 AND close < priorBest THEN
            madeNew = 1
         ENDIF
         contTrig = 0
         // continuation: a meaningful pullback, then a close through a completed local reference
         IF pbActive = 1 THEN
            IF regime = 1 THEN
               candExt = min(pbExtreme, low)
            ELSE
               candExt = max(pbExtreme, high)
            ENDIF
            pbDepth = regime * (pbRefClose - candExt) / scaleAtBirth
            reclaim = 0
            IF regime = 1 AND nTrg > 0 AND close > trgHi THEN
               reclaim = 1
            ENDIF
            IF regime = -1 AND nTrg > 0 AND close < trgLo THEN
               reclaim = 1
            ENDIF
            IF pbDepth >= minPullbackUnits - epsU AND reclaim = 1 THEN
               contTrig = 1
               IF regime = 1 THEN
                  bullContEv = 1
                  lastEvent = 13
               ELSE
                  bearContEv = 1
                  lastEvent = 14
               ENDIF
               pbActive = 0
               legPhase = 0
            ELSE
               pbExtreme = candExt
               toward = 0
               IF regime = 1 AND close > close[1] THEN
                  toward = 1
               ENDIF
               IF regime = -1 AND close < close[1] THEN
                  toward = 1
               ENDIF
               IF legPhase = 1 AND toward = 1 THEN
                  legPhase = 2
                  IF madeNew = 0 THEN
                     lastEvent = 15
                  ENDIF
               ENDIF
            ENDIF
         ELSIF madeNew = 0 THEN
            adverse = 0
            IF regime = 1 AND close < close[1] THEN
               adverse = 1
            ENDIF
            IF regime = -1 AND close > close[1] THEN
               adverse = 1
            ENDIF
            IF adverse = 1 THEN
               pbActive = 1
               IF regime = 1 THEN
                  pbExtreme = low
               ELSE
                  pbExtreme = high
               ENDIF
               pbRefClose = bestClose
            ENDIF
         ENDIF
         // accepted progress uses closes, not wick-only extremes
         IF madeNew = 1 THEN
            IF pbActive = 1 AND contTrig = 0 THEN
               pbActive = 0
            ENDIF
            newExt = max(0, regime * (close - priorBest) / scaleAtBirth)
            impulse = 100 * (1 - exp(0 - newExt))
            impulseOk = 1
            IF regime * (close - lastMilestone) >= scaleAtBirth * progressMilestoneUnits - epsP THEN
               milestoneEv = 1
               lastMilestone = close
            ENDIF
            IF exLatched = 1 AND exRefOk = 1 THEN
               IF regime * (close - exRef) / scaleAtBirth >= exhaustionRearmUnits - epsU THEN
                  exLatched = 0
                  exRefOk = 0
                  exStatus = 2
                  lastEvent = 16
               ENDIF
            ENDIF
            bestClose = close
            barsSinceBest = 0
            IF legPhase <> 0 THEN
               legPhase = 0
               IF bullContEv = 0 AND bearContEv = 0 THEN
                  lastEvent = 17
               ENDIF
            ENDIF
         ELSE
            barsSinceBest = barsSinceBest + 1
            gbLocal = max(0, regime * (priorBest - close) / scaleAtBirth)
            IF contTrig = 0 AND legPhase = 0 AND gbLocal >= givebackPhaseUnits - epsU THEN
               legPhase = 1
               lastEvent = 18
            ENDIF
         ENDIF
         // FORMING and TREND are progress thresholds, not time-based labels
         extFromBirth = regime * (bestClose - birthClose) / scaleAtBirth
         IF trendPhase = 1 AND extFromBirth >= formingUnits - epsU THEN
            trendPhase = 2
            IF regime = 1 THEN
               bullFormEv = 1
               IF bullContEv = 0 AND bearContEv = 0 THEN
                  lastEvent = 19
               ENDIF
            ELSE
               bearFormEv = 1
               IF bullContEv = 0 AND bearContEv = 0 THEN
                  lastEvent = 20
               ENDIF
            ENDIF
         ELSIF trendPhase = 2 AND legBars >= trendBarsMin AND extFromBirth >= effTrendUnits - epsU THEN
            trendPhase = 3
            IF regime = 1 THEN
               bullTrendEv = 1
               IF bullContEv = 0 AND bearContEv = 0 THEN
                  lastEvent = 21
               ENDIF
            ELSE
               bearTrendEv = 1
               IF bullContEv = 0 AND bearContEv = 0 THEN
                  lastEvent = 22
               ENDIF
            ENDIF
         ENDIF
         // exhaustion is a latched warning: giveback plus a failed extension or a stall
         IF madeNew = 0 AND exLatched = 0 AND contTrig = 0 THEN
            curGb = max(0, regime * (priorBest - close) / scaleAtBirth)
            failedExt = 0
            IF regime = 1 AND high > priorBest + scaleAtBirth * failedAttemptBuffer + epsP AND close <= priorBest THEN
               failedExt = 1
            ENDIF
            IF regime = -1 AND low < priorBest - scaleAtBirth * failedAttemptBuffer - epsP AND close >= priorBest THEN
               failedExt = 1
            ENDIF
            IF phaseStart = 1 THEN
               thrGb = driveExhaustionUnits
            ELSE
               thrGb = trendExhaustionUnits
            ENDIF
            IF curGb >= thrGb - epsU AND (failedExt = 1 OR barsSinceBest >= stallBars) THEN
               exhaustEv = 1
               exLatched = 1
               exRef = priorBest
               exRefOk = 1
               IF phaseStart = 1 THEN
                  exStatus = 3
                  lastEvent = 23
               ELSE
                  exStatus = 4
                  lastEvent = 24
               ENDIF
               IF regime = 1 THEN
                  exhaustPrice = high
               ELSE
                  exhaustPrice = low
               ENDIF
            ENDIF
         ENDIF
         IF exStatus = 2 AND exhaustEv = 0 THEN
            exStatus = 1
         ENDIF
      ENDIF
   ENDIF
   IF regime = 2 THEN
      IF oldRegime = 2 THEN
         balanceAge = balanceAge + 1
      ELSE
         balanceAge = 1
      ENDIF
   ELSE
      balanceAge = 0
   ENDIF
ENDIF
// ===================== END OF STATE ENGINE =====================

// ===================== PRICE CONTEXT ENVELOPES AND PHASE BANDS =====================
// Every box lives in arrays (left, right, top, bottom, type, direction, phase). The
// boxes are only written by plain assignment at an index held in a scalar counter, so
// the open candle can be recalculated on every tick without piling up copies.
ONCE actKind = 0
ONCE actKey = -999
ONCE hasCont = 0
ONCE hasFill = 0
ONCE contIdx = 0
ONCE fillIdx = 0
ONCE grpFirst = 0
ONCE nBox = 0
ONCE nGrp = 0
ONCE legTop = 0
ONCE legBot = 0
ONCE phTop = 0
ONCE phBot = 0
ONCE nMk = 0

balVisPh = 0
IF regime = 2 THEN
   IF balanceAge >= balMature THEN
      balVisPh = 3
   ELSE
      balVisPh = 2
   ENDIF
ENDIF
// 3 = dashed transition frame, drawn after two confirmed neutral bars
IF regime = 0 AND transActive = 1 AND transBars >= 2 THEN
   visKind = 3
ELSE
   visKind = regime
ENDIF
visPhase = 0
IF regime = 1 OR regime = -1 THEN
   visPhase = trendPhase
ELSIF regime = 2 THEN
   visPhase = balVisPh
ENDIF
visKey = 0
IF visKind = 1 THEN
   visKey = 10 + visPhase
ELSIF visKind = -1 THEN
   visKey = -10 - visPhase
ELSIF visKind = 2 THEN
   visKey = 2
ELSIF visKind = 3 THEN
   visKey = 3
ENDIF

closeCtx = 0
IF segStart = 1 OR (hasCont = 1 AND visKind <> actKind) THEN
   closeCtx = 1
ENDIF
// a finished leg, balance or transition: freeze its outer frame and its bands as one group
IF closeCtx = 1 AND hasCont = 1 THEN
   $bR[contIdx] = barindex
   IF hasFill = 1 THEN
      $bR[fillIdx] = barindex
   ENDIF
   $gFirst[nGrp] = grpFirst
   $gSize[nGrp] = nBox - grpFirst
   nGrp = nGrp + 1
   hasCont = 0
   hasFill = 0
   actKind = 0
   actKey = -999
ENDIF
IF hasCont = 1 AND visKind = actKind AND visKind <> 0 THEN
   // the outer frame keeps the full high-low range of the leg or balance
   legTop = max(legTop, high)
   legBot = min(legBot, low)
   $bR[contIdx] = barindex + 1
   $bT[contIdx] = legTop
   $bB[contIdx] = legBot
   IF visKind = 1 OR visKind = -1 THEN
      IF visKey <> actKey THEN
         // new phase: freeze the previous band and start a new one
         IF hasFill = 1 THEN
            $bR[fillIdx] = barindex
         ENDIF
         phTop = high
         phBot = low
         inset = min(ticksize, max((phTop - phBot) * 0.005, 0))
         $bL[nBox] = barindex
         $bR[nBox] = barindex + 1
         $bT[nBox] = phTop - inset
         $bB[nBox] = phBot + inset
         $bTy[nBox] = 1
         $bK[nBox] = visKind
         $bP[nBox] = visPhase
         fillIdx = nBox
         hasFill = 1
         nBox = nBox + 1
         actKey = visKey
      ELSIF hasFill = 1 THEN
         phTop = max(phTop, high)
         phBot = min(phBot, low)
         inset = min(ticksize, max((phTop - phBot) * 0.005, 0))
         $bR[fillIdx] = barindex + 1
         $bT[fillIdx] = phTop - inset
         $bB[fillIdx] = phBot + inset
      ENDIF
   ELSIF visKind = 2 AND hasFill = 1 THEN
      phTop = legTop
      phBot = legBot
      inset = min(ticksize, max((legTop - legBot) * 0.005, 0))
      $bR[fillIdx] = barindex + 1
      $bT[fillIdx] = legTop - inset
      $bB[fillIdx] = legBot + inset
      $bP[fillIdx] = balVisPh
   ENDIF
ELSIF visKind <> 0 AND segStart = 0 THEN
   // a new context starts on this bar
   legTop = high
   legBot = low
   phTop = high
   phBot = low
   $bL[nBox] = barindex
   $bR[nBox] = barindex + 1
   $bT[nBox] = high
   $bB[nBox] = low
   $bTy[nBox] = 0
   $bK[nBox] = visKind
   $bP[nBox] = 0
   contIdx = nBox
   grpFirst = nBox
   hasCont = 1
   nBox = nBox + 1
   IF visKind = 3 THEN
      hasFill = 0
   ELSE
      inset = min(ticksize, max((phTop - phBot) * 0.005, 0))
      $bL[nBox] = barindex
      $bR[nBox] = barindex + 1
      $bT[nBox] = phTop - inset
      $bB[nBox] = phBot + inset
      $bTy[nBox] = 1
      $bK[nBox] = visKind
      IF visKind = 2 THEN
         $bP[nBox] = balVisPh
      ELSE
         $bP[nBox] = visPhase
      ENDIF
      fillIdx = nBox
      hasFill = 1
      nBox = nBox + 1
   ENDIF
   actKind = visKind
   actKey = visKey
ELSE
   actKind = visKind
   actKey = -999
ENDIF

// ===================== PRICE-CHART EVENTS =====================
// 1 bullish drive birth, 2 bearish drive birth, 3 bullish structure failure,
// 4 bearish structure failure, 5 balance formed, 6 exhaustion watch
IF bullBirthEv = 1 THEN
   $mkB[nMk] = barindex
   $mkT[nMk] = 1
   $mkY[nMk] = low
   nMk = nMk + 1
ENDIF
IF bearBirthEv = 1 THEN
   $mkB[nMk] = barindex
   $mkT[nMk] = 2
   $mkY[nMk] = high
   nMk = nMk + 1
ENDIF
IF bullFailEv = 1 THEN
   $mkB[nMk] = barindex
   $mkT[nMk] = 3
   $mkY[nMk] = bullFailPrice
   nMk = nMk + 1
ENDIF
IF bearFailEv = 1 THEN
   $mkB[nMk] = barindex
   $mkT[nMk] = 4
   $mkY[nMk] = bearFailPrice
   nMk = nMk + 1
ENDIF
IF balBirthEv = 1 THEN
   $mkB[nMk] = barindex
   $mkT[nMk] = 5
   $mkY[nMk] = high
   nMk = nMk + 1
ENDIF
IF exhaustEv = 1 THEN
   $mkB[nMk] = barindex
   $mkT[nMk] = 6
   $mkY[nMk] = exhaustPrice
   nMk = nMk + 1
ENDIF

// ===================== DRAWING (last bar) =====================
IF islastbarupdate THEN
   // chart colours (light or dark background)
   IF darkChart = 1 THEN
      bdR = 165
      bdG = 255
      bdB = 207
      bfR = 0
      bfG = 205
      bfB = 118
      sdR = 255
      sdG = 190
      sdB = 198
      yeR = 255
      yeG = 214
      yeB = 64
      fbR = 66
      fbG = 220
      fbB = 151
   ELSE
      bdR = 36
      bdG = 168
      bdB = 118
      bfR = 0
      bfG = 150
      bfB = 86
      sdR = 236
      sdG = 104
      sdB = 124
      yeR = 196
      yeG = 128
      yeB = 0
      fbR = 20
      fbG = 166
      fbB = 104
   ENDIF

   // History budget: the newest finished groups that fit, oldest removed first
   maxObj = min(460, max(40, round(keepSegments) * 4))
   firstBox = 0
   IF nGrp > 0 THEN
      usedObj = 0
      firstGrp = nGrp
      FOR gq = nGrp - 1 DOWNTO 0 DO
         IF usedObj + $gSize[gq] <= maxObj THEN
            usedObj = usedObj + $gSize[gq]
            firstGrp = gq
         ELSE
            BREAK
         ENDIF
      NEXT
      IF firstGrp < nGrp THEN
         firstBox = $gFirst[firstGrp]
      ELSE
         lastG = nGrp - 1
         firstBox = $gFirst[lastG] + $gSize[lastG]
      ENDIF
   ENDIF
   IF nBox > firstBox THEN
      FOR bq = firstBox TO nBox - 1 DO
         bxL = $bL[bq]
         bxR = $bR[bq]
         bxT = $bT[bq]
         bxB = $bB[bq]
         bxK = $bK[bq]
         bxP = $bP[bq]
         IF $bTy[bq] = 0 THEN
            // outer frame: solid for a leg or a balance, dashed for a transition
            IF bxK = 1 THEN
               DRAWRECTANGLE(bxL, bxT, bxR, bxB) COLOURED(fbR, fbG, fbB, 255) FILLCOLOR(16, 23, 32, 0)
            ELSIF bxK = -1 THEN
               DRAWRECTANGLE(bxL, bxT, bxR, bxB) COLOURED(255, 77, 99, 255) FILLCOLOR(16, 23, 32, 0)
            ELSIF bxK = 2 THEN
               DRAWRECTANGLE(bxL, bxT, bxR, bxB) COLOURED(132, 145, 160, 255) FILLCOLOR(16, 23, 32, 0)
            ELSE
               DRAWRECTANGLE(bxL, bxT, bxR, bxB) COLOURED(132, 145, 160, 255) STYLE(dottedline2, 1) FILLCOLOR(16, 23, 32, 0)
            ENDIF
         ELSE
            // inner band: one per DRIVE, FORMING or TREND phase; grey for a balance
            IF bxK = 2 THEN
               fR = 132
               fG = 145
               fB = 160
               IF bxP = 3 THEN
                  fA = 61
               ELSE
                  fA = 36
               ENDIF
            ELSIF bxK = 1 THEN
               IF bxP = 1 THEN
                  fR = bdR
                  fG = bdG
                  fB = bdB
                  fA = 54
               ELSIF bxP = 2 THEN
                  fR = bfR
                  fG = bfG
                  fB = bfB
                  fA = 59
               ELSE
                  fR = 0
                  fG = 118
                  fB = 72
                  fA = 66
               ENDIF
            ELSE
               IF bxP = 1 THEN
                  fR = sdR
                  fG = sdG
                  fB = sdB
                  fA = 54
               ELSIF bxP = 2 THEN
                  fR = 245
                  fG = 42
                  fB = 70
                  fA = 59
               ELSE
                  fR = 170
                  fG = 8
                  fB = 39
                  fA = 66
               ENDIF
            ENDIF
            DRAWRECTANGLE(bxL, bxT, bxR, bxB) COLOURED(fR, fG, fB, 0) FILLCOLOR(fR, fG, fB, fA)
         ENDIF
      NEXT
   ENDIF

   // Event markers: circle = drive birth, cross = protected structure lost,
   // square = balance formed, yellow diamond with halo = exhaustion watch
   IF showPriceEvents = 1 AND nMk > 0 THEN
      FOR mq = 0 TO nMk - 1 DO
         mkX = $mkB[mq]
         mkY = $mkY[mq]
         mkT = $mkT[mq]
         IF mkT = 1 THEN
            DRAWPOINT(mkX, mkY, 2) COLOURED(bdR, bdG, bdB, 255)
         ELSIF mkT = 2 THEN
            DRAWPOINT(mkX, mkY, 2) COLOURED(sdR, sdG, sdB, 255)
         ELSIF mkT = 3 THEN
            DRAWTEXT("✕", mkX, mkY) COLOURED(170, 8, 39, 255)
         ELSIF mkT = 4 THEN
            DRAWTEXT("✕", mkX, mkY) COLOURED(0, 118, 72, 255)
         ELSIF mkT = 5 THEN
            DRAWTEXT("■", mkX, mkY) COLOURED(132, 145, 160, 255)
         ELSE
            DRAWPOINT(mkX, mkY, 3) COLOURED(yeR, yeG, yeB, 31)
            DRAWPOINT(mkX, mkY, 3) COLOURED(yeR, yeG, yeB, 97)
            DRAWTEXT("◆", mkX, mkY) COLOURED(yeR, yeG, yeB, 255)
         ENDIF
      NEXT
   ENDIF

   // ===================== SCANNER =====================
   // Fixed in the top-right corner (the corner of ANCHOR cannot be a variable).
   // The original shows the latest event as a tooltip of SCAN: here it is the last row.
   IF showDashboard = 1 THEN
      xR = -90
      x3 = xR - 70
      x2 = x3 - 85
      x1 = x2 - 65
      x0 = x1 - 90
      c0X = (x0 + x1) / 2
      c1X = (x1 + x2) / 2
      c2X = (x2 + x3) / 2
      c3X = (x3 + xR) / 2
      mX = (x1 + xR) / 2
      hX = (x0 + xR) / 2
      // frame and header
      DRAWRECTANGLE(x0, -10, xR, -130) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT) COLOURED(132, 145, 160, 115) FILLCOLOR(16, 23, 32, 255)
      DRAWRECTANGLE(x0, -10, xR, -30) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT) COLOURED(132, 145, 160, 41) FILLCOLOR(29, 40, 52, 255)
      DRAWTEXT("SCANNER", hX, -20, sansserif, bold, 10) COLOURED(235, 241, 247, 255) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT)

      // row 1: PHASE (confirmed direction)
      IF regime = 1 THEN
         vR = 0
         vG = 205
         vB = 118
      ELSIF regime = -1 THEN
         vR = 245
         vG = 42
         vB = 70
      ELSE
         vR = 132
         vG = 145
         vB = 160
      ENDIF
      DRAWRECTANGLE(x0, -30, x1, -50) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT) COLOURED(132, 145, 160, 41) FILLCOLOR(16, 23, 32, 0)
      DRAWRECTANGLE(x1, -30, xR, -50) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT) COLOURED(132, 145, 160, 41) FILLCOLOR(vR, vG, vB, 51)
      DRAWTEXT("PHASE", c0X, -40, sansserif, standard, 9) COLOURED(151, 165, 181, 255) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT)
      IF regime = 1 THEN
         DRAWTEXT("BULLISH", mX, -40, sansserif, standard, 9) COLOURED(vR, vG, vB, 255) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT)
      ELSIF regime = -1 THEN
         DRAWTEXT("BEARISH", mX, -40, sansserif, standard, 9) COLOURED(vR, vG, vB, 255) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT)
      ELSE
         DRAWTEXT("NEUTRAL", mX, -40, sansserif, standard, 9) COLOURED(vR, vG, vB, 255) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT)
      ENDIF

      // row 2: SCAN (direction and phase, or balance / transition)
      sR = 132
      sG = 145
      sB = 160
      IF regime = 1 THEN
         IF trendPhase = 1 THEN
            sR = 165
            sG = 255
            sB = 207
         ELSIF trendPhase = 2 THEN
            sR = 0
            sG = 205
            sB = 118
         ELSE
            sR = 0
            sG = 118
            sB = 72
         ENDIF
      ELSIF regime = -1 THEN
         IF trendPhase = 1 THEN
            sR = 255
            sG = 190
            sB = 198
         ELSIF trendPhase = 2 THEN
            sR = 245
            sG = 42
            sB = 70
         ELSE
            sR = 170
            sG = 8
            sB = 39
         ENDIF
      ENDIF
      DRAWRECTANGLE(x0, -50, x1, -70) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT) COLOURED(132, 145, 160, 41) FILLCOLOR(16, 23, 32, 0)
      DRAWRECTANGLE(x1, -50, xR, -70) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT) COLOURED(132, 145, 160, 41) FILLCOLOR(sR, sG, sB, 46)
      DRAWTEXT("SCAN", c0X, -60, sansserif, standard, 9) COLOURED(151, 165, 181, 255) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT)
      IF regime = 1 THEN
         IF trendPhase = 1 THEN
            DRAWTEXT("BULLISH DRIVE", mX, -60, sansserif, standard, 9) COLOURED(sR, sG, sB, 255) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT)
         ELSIF trendPhase = 2 THEN
            DRAWTEXT("BULLISH FORMING", mX, -60, sansserif, standard, 9) COLOURED(sR, sG, sB, 255) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT)
         ELSE
            DRAWTEXT("BULLISH TREND", mX, -60, sansserif, standard, 9) COLOURED(sR, sG, sB, 255) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT)
         ENDIF
      ELSIF regime = -1 THEN
         IF trendPhase = 1 THEN
            DRAWTEXT("BEARISH DRIVE", mX, -60, sansserif, standard, 9) COLOURED(sR, sG, sB, 255) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT)
         ELSIF trendPhase = 2 THEN
            DRAWTEXT("BEARISH FORMING", mX, -60, sansserif, standard, 9) COLOURED(sR, sG, sB, 255) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT)
         ELSE
            DRAWTEXT("BEARISH TREND", mX, -60, sansserif, standard, 9) COLOURED(sR, sG, sB, 255) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT)
         ENDIF
      ELSIF regime = 2 THEN
         DRAWTEXT("BALANCE", mX, -60, sansserif, standard, 9) COLOURED(sR, sG, sB, 255) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT)
      ELSIF transActive = 1 THEN
         DRAWTEXT("TRANSITION · SCANNING", mX, -60, sansserif, standard, 9) COLOURED(sR, sG, sB, 255) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT)
      ELSE
         DRAWTEXT("SCANNING", mX, -60, sansserif, standard, 9) COLOURED(sR, sG, sB, 255) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT)
      ENDIF

      // row 3: EXHAUSTION (latched warning, or the state of the pullback cycle)
      // eTx: 0 -, 1 status, 2 PULLBACK ACTIVE, 3 GIVEBACK, 4 RECOVERY, 5 NONE, 6 BALANCE
      eTx = 0
      eR = 151
      eG = 165
      eB = 181
      IF regime = 1 OR regime = -1 THEN
         IF exLatched = 1 THEN
            eTx = 1
            IF exStatus = 5 THEN
               eR = 170
               eG = 8
               eB = 39
            ELSE
               eR = 255
               eG = 214
               eB = 64
            ENDIF
         ELSIF pbActive = 1 THEN
            eTx = 2
            eR = 132
            eG = 145
            eB = 160
         ELSIF legPhase = 1 THEN
            eTx = 3
            eR = 132
            eG = 145
            eB = 160
         ELSIF legPhase = 2 THEN
            eTx = 4
            eR = sR
            eG = sG
            eB = sB
         ELSE
            eTx = 5
         ENDIF
      ELSIF exStatus = 5 THEN
         eTx = 1
         eR = 170
         eG = 8
         eB = 39
      ELSIF regime = 2 THEN
         eTx = 6
         eR = 132
         eG = 145
         eB = 160
      ENDIF
      DRAWRECTANGLE(x0, -70, x1, -90) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT) COLOURED(132, 145, 160, 41) FILLCOLOR(16, 23, 32, 0)
      DRAWRECTANGLE(x1, -70, xR, -90) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT) COLOURED(132, 145, 160, 41) FILLCOLOR(eR, eG, eB, 41)
      DRAWTEXT("EXHAUSTION", c0X, -80, sansserif, standard, 9) COLOURED(151, 165, 181, 255) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT)
      IF eTx = 1 THEN
         IF exStatus = 1 THEN
            DRAWTEXT("CLEAR", mX, -80, sansserif, standard, 9) COLOURED(eR, eG, eB, 255) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT)
         ELSIF exStatus = 2 THEN
            DRAWTEXT("CLEARED", mX, -80, sansserif, standard, 9) COLOURED(eR, eG, eB, 255) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT)
         ELSIF exStatus = 3 THEN
            DRAWTEXT("DRIVE STALL", mX, -80, sansserif, standard, 9) COLOURED(eR, eG, eB, 255) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT)
         ELSIF exStatus = 4 THEN
            DRAWTEXT("EXHAUSTION WATCH", mX, -80, sansserif, standard, 9) COLOURED(eR, eG, eB, 255) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT)
         ELSIF exStatus = 5 THEN
            DRAWTEXT("STRUCTURE FAILED", mX, -80, sansserif, standard, 9) COLOURED(eR, eG, eB, 255) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT)
         ELSE
            DRAWTEXT("-", mX, -80, sansserif, standard, 9) COLOURED(eR, eG, eB, 255) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT)
         ENDIF
      ELSIF eTx = 2 THEN
         DRAWTEXT("PULLBACK ACTIVE", mX, -80, sansserif, standard, 9) COLOURED(eR, eG, eB, 255) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT)
      ELSIF eTx = 3 THEN
         DRAWTEXT("GIVEBACK", mX, -80, sansserif, standard, 9) COLOURED(eR, eG, eB, 255) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT)
      ELSIF eTx = 4 THEN
         DRAWTEXT("RECOVERY", mX, -80, sansserif, standard, 9) COLOURED(eR, eG, eB, 255) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT)
      ELSIF eTx = 5 THEN
         DRAWTEXT("NONE", mX, -80, sansserif, standard, 9) COLOURED(eR, eG, eB, 255) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT)
      ELSIF eTx = 6 THEN
         DRAWTEXT("BALANCE", mX, -80, sansserif, standard, 9) COLOURED(eR, eG, eB, 255) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT)
      ELSE
         DRAWTEXT("-", mX, -80, sansserif, standard, 9) COLOURED(eR, eG, eB, 255) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT)
      ENDIF

      // row 4: EXTENSION from the birth close and GIVEBACK from the best accepted close,
      // both in units of the movement scale frozen at the leg birth
      DRAWRECTANGLE(x0, -90, x1, -110) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT) COLOURED(132, 145, 160, 41) FILLCOLOR(16, 23, 32, 0)
      DRAWRECTANGLE(x1, -90, x2, -110) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT) COLOURED(132, 145, 160, 41) FILLCOLOR(16, 23, 32, 0)
      DRAWRECTANGLE(x2, -90, x3, -110) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT) COLOURED(132, 145, 160, 41) FILLCOLOR(16, 23, 32, 0)
      DRAWRECTANGLE(x3, -90, xR, -110) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT) COLOURED(132, 145, 160, 41) FILLCOLOR(16, 23, 32, 0)
      DRAWTEXT("EXTENSION", c0X, -100, sansserif, standard, 9) COLOURED(151, 165, 181, 255) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT)
      DRAWTEXT("GIVEBACK", c2X, -100, sansserif, standard, 9) COLOURED(151, 165, 181, 255) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT)
      IF regime = 1 OR regime = -1 THEN
         extU = regime * (close - birthClose) / scaleAtBirth
         gbU = max(0, regime * (bestClose - close) / scaleAtBirth)
         extV = round(extU * 100) / 100
         gbV = round(gbU * 100) / 100
         IF extU < 0 THEN
            xtR = 170
            xtG = 8
            xtB = 39
         ELSE
            xtR = sR
            xtG = sG
            xtB = sB
         ENDIF
         DRAWTEXT("#extV#×", c1X, -100, sansserif, standard, 9) COLOURED(xtR, xtG, xtB, 255) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT)
         IF gbU > 0 THEN
            DRAWTEXT("#gbV#×", c3X, -100, sansserif, standard, 9) COLOURED(132, 145, 160, 255) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT)
         ELSE
            DRAWTEXT("#gbV#×", c3X, -100, sansserif, standard, 9) COLOURED(151, 165, 181, 255) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT)
         ENDIF
      ELSE
         DRAWTEXT("-", c1X, -100, sansserif, standard, 9) COLOURED(132, 145, 160, 255) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT)
         DRAWTEXT("-", c3X, -100, sansserif, standard, 9) COLOURED(151, 165, 181, 255) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT)
      ENDIF

      // row 5: latest confirmed event
      DRAWRECTANGLE(x0, -110, x1, -130) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT) COLOURED(132, 145, 160, 41) FILLCOLOR(16, 23, 32, 0)
      DRAWRECTANGLE(x1, -110, xR, -130) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT) COLOURED(132, 145, 160, 41) FILLCOLOR(16, 23, 32, 0)
      DRAWTEXT("LAST EVENT", c0X, -120, sansserif, standard, 9) COLOURED(151, 165, 181, 255) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT)
      IF lastEvent = 1 THEN
         DRAWTEXT("INTRADAY GAP RESET", mX, -120, sansserif, standard, 9) COLOURED(235, 241, 247, 255) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT)
      ELSIF lastEvent = 2 THEN
         DRAWTEXT("BULLISH REVERSAL", mX, -120, sansserif, standard, 9) COLOURED(235, 241, 247, 255) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT)
      ELSIF lastEvent = 3 THEN
         DRAWTEXT("BALANCE BREAK UP", mX, -120, sansserif, standard, 9) COLOURED(235, 241, 247, 255) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT)
      ELSIF lastEvent = 4 THEN
         DRAWTEXT("BULLISH DRIVE", mX, -120, sansserif, standard, 9) COLOURED(235, 241, 247, 255) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT)
      ELSIF lastEvent = 5 THEN
         DRAWTEXT("BEARISH REVERSAL", mX, -120, sansserif, standard, 9) COLOURED(235, 241, 247, 255) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT)
      ELSIF lastEvent = 6 THEN
         DRAWTEXT("BALANCE BREAK DOWN", mX, -120, sansserif, standard, 9) COLOURED(235, 241, 247, 255) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT)
      ELSIF lastEvent = 7 THEN
         DRAWTEXT("BEARISH DRIVE", mX, -120, sansserif, standard, 9) COLOURED(235, 241, 247, 255) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT)
      ELSIF lastEvent = 8 THEN
         DRAWTEXT("BALANCE FORMED", mX, -120, sansserif, standard, 9) COLOURED(235, 241, 247, 255) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT)
      ELSIF lastEvent = 9 THEN
         DRAWTEXT("LEG ENTERED BALANCE", mX, -120, sansserif, standard, 9) COLOURED(235, 241, 247, 255) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT)
      ELSIF lastEvent = 10 THEN
         DRAWTEXT("BULL STRUCTURE FAILED", mX, -120, sansserif, standard, 9) COLOURED(235, 241, 247, 255) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT)
      ELSIF lastEvent = 11 THEN
         DRAWTEXT("BEAR STRUCTURE FAILED", mX, -120, sansserif, standard, 9) COLOURED(235, 241, 247, 255) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT)
      ELSIF lastEvent = 12 THEN
         DRAWTEXT("BALANCE RELEASED", mX, -120, sansserif, standard, 9) COLOURED(235, 241, 247, 255) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT)
      ELSIF lastEvent = 13 THEN
         DRAWTEXT("LONG CONTINUATION TRIGGER", mX, -120, sansserif, standard, 9) COLOURED(235, 241, 247, 255) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT)
      ELSIF lastEvent = 14 THEN
         DRAWTEXT("SHORT CONTINUATION TRIGGER", mX, -120, sansserif, standard, 9) COLOURED(235, 241, 247, 255) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT)
      ELSIF lastEvent = 15 THEN
         DRAWTEXT("RECOVERY DEVELOPING", mX, -120, sansserif, standard, 9) COLOURED(235, 241, 247, 255) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT)
      ELSIF lastEvent = 16 THEN
         DRAWTEXT("EXHAUSTION CLEARED BY PROGRESS", mX, -120, sansserif, standard, 9) COLOURED(235, 241, 247, 255) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT)
      ELSIF lastEvent = 17 THEN
         DRAWTEXT("ACCEPTED PROGRESS RESUMED", mX, -120, sansserif, standard, 9) COLOURED(235, 241, 247, 255) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT)
      ELSIF lastEvent = 18 THEN
         DRAWTEXT("GIVEBACK STARTED", mX, -120, sansserif, standard, 9) COLOURED(235, 241, 247, 255) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT)
      ELSIF lastEvent = 19 THEN
         DRAWTEXT("BULLISH FORMING", mX, -120, sansserif, standard, 9) COLOURED(235, 241, 247, 255) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT)
      ELSIF lastEvent = 20 THEN
         DRAWTEXT("BEARISH FORMING", mX, -120, sansserif, standard, 9) COLOURED(235, 241, 247, 255) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT)
      ELSIF lastEvent = 21 THEN
         DRAWTEXT("BULLISH TREND", mX, -120, sansserif, standard, 9) COLOURED(235, 241, 247, 255) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT)
      ELSIF lastEvent = 22 THEN
         DRAWTEXT("BEARISH TREND", mX, -120, sansserif, standard, 9) COLOURED(235, 241, 247, 255) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT)
      ELSIF lastEvent = 23 THEN
         DRAWTEXT("DRIVE STALL", mX, -120, sansserif, standard, 9) COLOURED(235, 241, 247, 255) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT)
      ELSIF lastEvent = 24 THEN
         DRAWTEXT("EXHAUSTION WATCH", mX, -120, sansserif, standard, 9) COLOURED(235, 241, 247, 255) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT)
      ELSE
         DRAWTEXT("Waiting for valid history", mX, -120, sansserif, standard, 9) COLOURED(235, 241, 247, 255) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT)
      ENDIF
   ENDIF
ENDIF

RETURN

Download
Filename: PRC_Trend-Exhaustion_panel.itf
Downloads: 10
Download
Filename: PRC_Trend-Exhaustion_price.itf
Downloads: 9
Iván González
Iván González Legend
I usually let my code do the talking, which explains why my bio is as empty as a newly created file. Bio to be initialized...
Author’s Profile

Comments

ProRealCode ProRealCode
Loading...