Initial Balance Auction Intelligence

Category: Indicators By: Iván González Created: September 3, 2026, 9:26 AM
September 3, 2026, 9:26 AM
Indicators
0 Comments

Introduction

The Initial Balance is the high and the low of the first part of the session — classically the first hour. It is one of the oldest ideas in market profile, and it survives because it is the cheapest available summary of what the market agreed on before the day had an opinion.

What most tools do with it is draw two lines and mark the break. That is the least informative thing you can do with it, because a break is a single instant and the Initial Balance is not about instants. The question a market profile reader is actually asking is what happened next: did price close outside and stay outside, or did it stick a wick through and come straight back? Did it come back to the edge and hold, or come back through it? Did it try both sides and fail at both?

Those are five different days, and a breakout arrow cannot tell them apart.

Initial Balance Auction Intelligence, designed by dgtrd, is built around that second question. It slices the rest of the session into fixed auction windows and, at the close of each one, classifies what that window did with the two edges. The result is a state machine with eleven states and a running commentary in the corner of the chart, rather than a signal.

The Initial Balance

The opening window is defined by two clock times and tracked bar by bar: the highest high becomes IBH, the lowest low becomes IBL, and the midpoint IBM sits between them. Once the window closes, the three levels freeze and extend across the rest of the session until the next one starts.

Optionally the tool projects six more levels — at 0.5, 1.0 and 1.5 times the width of the Initial Balance, above IBH and below IBL. These are reference levels for range extension, not targets. A session that expands a full Initial Balance width beyond its own edge is a measurably different session from one that expands a quarter of it, and having the levels drawn saves you from measuring by eye.

The width itself is worth reading before anything else happens. A narrow Initial Balance means the opening auction settled fast, and a narrow one usually gets broken; a wide one means the market spent the first hour disagreeing loudly, and the rest of the day often stays inside it. The tool does not score this for you, but it draws it clearly enough to read.

The Auction Window

After the Initial Balance completes, the session is cut into windows of a fixed length — 5, 10, 15 or 30 minutes, 30 by default. Each window accumulates its own open, high, low and close, exactly as if it were a single candle of that duration, and it is evaluated once, when it closes.

This is the design decision that makes the whole thing work. Evaluating on every bar would produce a stream of contradictory readings as price wobbles around IBH; evaluating on a completed window forces the market to commit. A window that pokes above IBH and closes back inside has said something specific, and it can only say it once its close exists.

The consequence is a one-bar delay, and it is an honest one. The decision is taken on the first bar of the new window using only data from the window that just ended, and the mark it produces is drawn on the last bar of that finished window. Nothing that happens after can move it. The single exception is the Probing Above / Probing Below state, which reads the live bar and is labelled (live) in the panel precisely so you do not mistake it for a confirmed reading.

The Eleven States

The classification of each completed window is short enough to hold in your head.

Balanced — price is inside the Initial Balance and nothing has resolved.

Probing Above and Probing Below — price is currently outside one edge but no window has closed to confirm it. This is the live, tentative state.

Accepted Above and Accepted Below — a window closed beyond the edge. The auction has moved outside the Initial Balance. This is the state that arms a retest.

Failed Above and Failed Below — a window traded beyond the edge, by its open or by its extreme, and closed back inside. The excursion happened and was refused. This is the classic failed auction, and in profile terms it is a stronger statement than a break, because someone had to be there to reject it.

Two-Sided Auction — both edges were tested and neither held. Either both failures happened in the same window, or one happened after the other. The market has rejected the highs and the lows of the opening range, which is the signature of a rotational day.

Continuation — after an acceptance, price came back to the accepted edge, touched it, and the window still closed on the right side of it. The retest held.

Rejection — the same retest, but the window closed back through the level. The acceptance is undone.

Note how the retest logic behaves after a hold: it does not disarm. A held retest immediately arms the next one, so a session that trends can produce several Continuation marks in a row, one per touch of the edge that keeps working.

Conviction: Not Every Event Is Worth the Same

Every confirmed event is scored out of 100, from three independent pieces.

Where the window closed inside its own range is worth 40 points. This is the close location value: a window that closed on its high after probing above IBH is a very different animal from one that closed mid-range after doing the same thing. The score is taken in the direction that supports the reading, so a failure below IBL scores high when the window closed near its own high.

How far the window travelled outside the Initial Balance is worth 30 points, measured as a fraction of the Initial Balance width and capped at one full width. This is what separates a two-tick poke from a genuine excursion, and normalising it by the width of the range is what makes the number comparable between a quiet session and a violent one.

The retest is worth the remaining 30. A held retest scores the full amount; a failed one scores zero; an event that has not been retested yet is given 15 as a provisional value.

That score, plus a small bonus for how many windows the state has survived, becomes the Quality reading: Weak, Developing, Established or Strong. Note that a brand new acceptance cannot be Strong — the maturity bonus does not exist yet, by design. An acceptance has to survive to earn the label.

Failures are scored on a different scale, because what matters about a failure is not where it closed but how far it got before being rejected. An excursion of less than 0.3 Initial Balance widths is Weak, up to 0.7 Moderate, up to 1.2 High, and beyond that Violent. A Violent failure — price extended more than a full range width beyond the edge and still came back inside — is the single most informative event this tool produces.

Pressure Is Not Bias

The panel reports both, and they are allowed to disagree. That is the point.

Bias is the direction of the current event and nothing else. An Accepted Above reads Bullish; a Failed Above reads Bearish Pressure; a Two-Sided Auction reads Conflicted. It changes every time the state changes.

Pressure is a running total for the whole session, bounded to the range minus 100 to plus 100. An acceptance adds or subtracts 30, a failed auction 15 the other way, a held retest 20 with the trend, a rejected retest 20 against it. It does not decay and it resets only at the start of the next Initial Balance.

So a session that accepted above, held one retest, then failed twice on the way back down will show a Bearish bias — the last event was a failure — sitting on top of a still-positive Pressure, because the day as a whole has produced more upside evidence than downside. That disagreement is information. A Bearish bias on strongly positive Pressure is a pullback; the same bias on negative Pressure is a trend.

One thing Pressure is not: it is not order flow, it is not volume, and it is not a probability. It is a tally of auction events, weighted by how much each one is worth.

The Panel

Nine rows in the top right corner, updated on the last bar.

The header carries the two levels that matter, IBH and IBL. Then REGIME (Balanced, Rotational, Expansion, Failed Expansion or Trend Auction), BIAS, PHASE (the lifecycle: Balance, Probe, Acceptance, Retest, Expansion, Exhaustion), AUCTION (the raw state, with the (live) suffix when it is tentative), PRESSURE, QUALITY, NEXT and INVALID.

The last two are the operationally useful pair. NEXT says what has to happen for the reading to advance — a close over a specific price, a retest of a specific level with the current distance to it, or simply waiting. INVALID says what price kills the current reading. Both print actual numbers, not the names of the levels, so you can work from the panel without measuring anything.

The panel position is exposed as four inputs rather than being hard-coded, because how far a text row extends before it meets the price scale depends on your screen and on how many digits your instrument prints. If a row gets clipped, move the whole panel left with dashX and dashCol.

One Deliberate Silence

There is a moment where the tool refuses to speak, and it is worth explaining because it looks like a missing signal.

At the instant the Initial Balance completes, no auction window of this session has closed yet. There is nothing to evaluate — the window buffer at that point still holds the last window of the previous session, and comparing yesterday’s closing half hour against today’s opening range produces a confident, completely meaningless reading. So the state machine stays in Balanced and waits for the first genuine window of the day to finish.

The same guard forces a fresh window to open at the exact bar the Initial Balance ends, rather than waiting for the next wall clock boundary. Without it, an opening range that does not line up with the auction grid — say a 45 minute range with 30 minute windows — would produce a first window made half of bars from inside the Initial Balance and half from outside. With the defaults the two coincide and nothing changes; with an unusual opening range it matters.

The Code

//----------------------------------------------
//PRC_Initial Balance Auction Intelligence by DGT
//version = 1
//02.09.2026
//Ivan Gonzalez @ www.prorealcode.com
//Concept and design: dgtrd (DGT)
//Sharing ProRealTime knowledge
//----------------------------------------------
// Overlay indicator. Marks the Initial Balance of the session (high, low and
// midpoint of an opening time window), projects reference levels at 0.5x, 1x
// and 1.5x its range, and then runs a state machine over fixed post-IB auction
// windows that classifies what the market does with those two edges:
// acceptance, failure, two-sided rotation, retest held or retest rejected.
// A corner panel reports regime, bias, phase, cumulative pressure, quality of
// the last confirmed event and what invalidates the current read.
//----------------------------------------------
DEFPARAM DRAWONLASTBARONLY = TRUE


// === 1. INITIAL BALANCE WINDOW ===
// Both times are HHMMSS and are read in the time YOUR platform displays.
// ProRealTime has no timezone conversion, so set them to the window you
// actually want on the chart you are looking at. Overnight windows are
// supported (ibStart > ibEnd).
ibStart  = 090000   // start of the initial balance window, included
ibEnd    = 103000   // end of the initial balance window, excluded
showMid  = 1        // 1 = plot the initial balance midpoint
showFill = 1        // 1 = shade the initial balance
showProj = 0        // 1 = plot the 0.5x / 1x / 1.5x range projections


// === 2. AUCTION INTELLIGENCE ===
auctionMin = 30     // auction window length in minutes: 5, 10, 15 or 30
showMarks  = 1      // 1 = draw the auction event marks on the price
showBoxes  = 0      // 1 = shade the auction windows that interact with the IB
showPanel  = 1      // 1 = draw the auction intelligence panel
maxMk      = 90     // how many event marks are kept on the chart
maxBx      = 60     // how many shaded auction windows are kept on the chart


// === 3. PANEL PLACEMENT (pixels from the top right corner) ===
dashX   = -380      // label column
dashCol = 170       // horizontal offset of the value column
dashY   = -25       // first row
rowH    = 20        // row height
dashDec = 2         // decimals used when the panel prints a price


// === 4. COLOURS ===
ibR   = 41          // initial balance lines
ibG   = 98
ibB   = 255
midR  = 120         // midpoint, labels and neutral readings
midG  = 123
midB  = 134
bullR = 0           // bullish acceptance / continuation
bullG = 137
bullB = 123
bearR = 229         // bearish acceptance / continuation
bearG = 57
bearB = 53
warnR = 230         // failed auctions, rejections and projections
warnG = 81
warnB = 0


//----------------------------------------------
// DERIVED CONSTANTS
//----------------------------------------------
pxDec = 100
IF dashDec = 0 THEN
   pxDec = 1
ELSIF dashDec = 1 THEN
   pxDec = 10
ELSIF dashDec = 3 THEN
   pxDec = 1000
ELSIF dashDec = 4 THEN
   pxDec = 10000
ELSIF dashDec >= 5 THEN
   pxDec = 100000
ENDIF


// Ring buffers carry one slot more than their useful capacity. With the market
// open the live bar is recomputed on every tick and arrays do not rewind, so a
// write coming from a tick that was later discarded must never fall inside the
// read window.
mkRing = maxMk + 1
bxRing = maxBx + 1


// The auction engine needs intraday bars that fit inside an auction window.
tfSec = gettimeframe
tfOK  = 0
IF tfSec >= 60 AND tfSec <= 1800 AND tfSec <= auctionMin * 60 THEN
   tfOK = 1
ENDIF


//----------------------------------------------
// SESSION ENGINE AND INITIAL BALANCE
//----------------------------------------------
// opentime is the OPENING time of the bar, which is the anchor that decides
// whether a bar belongs to the session window.
tNow = opentime
inIB = 0
IF ibStart < ibEnd THEN
   IF tNow >= ibStart AND tNow < ibEnd THEN
      inIB = 1
   ENDIF
ELSE
   IF tNow >= ibStart OR tNow < ibEnd THEN
      inIB = 1
   ENDIF
ENDIF
IF tfOK = 0 THEN
   inIB = 0
ENDIF


ONCE prevIn = 0
ibNew  = 0
ibDone = 0
IF inIB = 1 AND prevIn = 0 THEN
   ibNew = 1
ENDIF
IF inIB = 0 AND prevIn = 1 THEN
   ibDone = 1
ENDIF
prevIn = inIB


ONCE ibh = 0
ONCE ibl = 0
ONCE ibValid = 0
IF ibNew = 1 THEN
   ibh = high
   ibl = low
   ibValid = 1
ELSIF inIB = 1 AND ibValid = 1 THEN
   ibh = max(high, ibh)
   ibl = min(low, ibl)
ENDIF
ibMid = (ibh + ibl) / 2
ibW   = ibh - ibl


ONCE ibCompl = 0
IF ibNew = 1 THEN
   ibCompl = 0
ENDIF
IF ibDone = 1 THEN
   ibCompl = 1
ENDIF


// Plotted levels. The first bar of a new window is left empty on purpose so
// the previous session ends where it ended instead of being joined to the new
// one by a vertical line. Both series go blank together, so the shading is cut
// there too instead of bridging the gap.
IF ibValid = 1 AND ibNew = 0 THEN
   ibhLine = ibh
   iblLine = ibl
ELSE
   ibhLine = undefined
   iblLine = undefined
ENDIF
IF ibValid = 1 AND ibNew = 0 AND showMid = 1 THEN
   ibmLine = ibMid
ELSE
   ibmLine = undefined
ENDIF


IF showProj = 1 AND ibCompl = 1 THEN
   pUp1 = ibh + 0.5 * ibW
   pUp2 = ibh + 1.0 * ibW
   pUp3 = ibh + 1.5 * ibW
   pDn1 = ibl - 0.5 * ibW
   pDn2 = ibl - 1.0 * ibW
   pDn3 = ibl - 1.5 * ibW
ELSE
   pUp1 = undefined
   pUp2 = undefined
   pUp3 = undefined
   pDn1 = undefined
   pDn2 = undefined
   pDn3 = undefined
ENDIF


IF showFill = 1 THEN
   fillA = 20
ELSE
   fillA = 0
ENDIF
COLORBETWEEN(ibhLine, iblLine, ibR, ibG, ibB, fillA)


//----------------------------------------------
// AUCTION WINDOW CLOCK
//----------------------------------------------
// Auction windows sit on a wall clock grid. The end of the initial balance is
// forced to open a window as well, so the first evaluated auction never mixes
// bars taken from inside the IB with bars taken from outside it.
hhX    = floor(tNow / 10000)
mmX    = floor(tNow / 100) - hhX * 100
minDay = hhX * 60 + mmX
winId  = floor(minDay / auctionMin)


ONCE prevWin = -1
qChg = 0
IF winId <> prevWin OR ibDone = 1 THEN
   qChg = 1
ENDIF
prevWin = winId


ONCE qOpen  = 0
ONCE qHigh  = 0
ONCE qLow   = 0
ONCE qClose = 0
ONCE qStart = 0
ONCE qReady = 0


IF ibNew = 1 THEN
   qReady = 0
ENDIF


// The state machine reads the window that has just been completed, which is
// the value these variables held on the previous bar. qValid says whether that
// window belongs to THIS session: it is read before the reset below, which is
// what sets qReady.
smRun = 0
IF ibCompl = 1 AND qChg = 1 THEN
   smRun = 1
ENDIF
qValid = qReady


IF ibCompl = 1 AND qChg = 1 THEN
   qOpen  = open
   qHigh  = high
   qLow   = low
   qClose = close
   qStart = barindex
   qReady = 1
ELSIF ibCompl = 1 THEN
   qHigh  = max(high, qHigh)
   qLow   = min(low, qLow)
   qClose = close
ENDIF


qO = qOpen[1]
qH = qHigh[1]
qL = qLow[1]
qC = qClose[1]


//----------------------------------------------
// AUCTION STATE MACHINE
//----------------------------------------------
// stAuc  0 Building IB      1 Balanced          2 Probing Above
//        3 Probing Below    4 Accepted Above    5 Accepted Below
//        6 Failed Above     7 Failed Below      8 Two-Sided Auction
//        9 Continuation    10 Rejection
// accSide 0 none, 1 above, 2 below
ONCE stAuc     = 0
ONCE failAb    = 0
ONCE failBl    = 0
ONCE accSide   = 0
ONCE awaitRt   = 0
ONCE retestLvl = 0
ONCE convScore = 0
ONCE convValid = 0
ONCE convAcc   = 0
ONCE convExt   = 0
ONCE convRet   = 0
ONCE candles   = 0
ONCE hadCont   = 0
ONCE failExc   = 0
ONCE failExcOK = 0
ONCE press     = 0


IF ibNew = 1 THEN
   stAuc     = 0
   failAb    = 0
   failBl    = 0
   accSide   = 0
   awaitRt   = 0
   retestLvl = 0
   convScore = 0
   convValid = 0
   convAcc   = 0
   convExt   = 0
   convRet   = 0
   candles   = 0
   hadCont   = 0
   failExc   = 0
   failExcOK = 0
   press     = 0
ENDIF
IF ibDone = 1 THEN
   stAuc = 1
ENDIF


// Transition flags. They must be cleared on every bar or the marks and the
// pressure accumulator would fire again on bars where nothing happened.
becAA = 0
becAB = 0
becFA = 0
becFB = 0
becTS = 0
becCO = 0
becRJ = 0


// Live, unconfirmed excursion outside the initial balance.
IF ibCompl = 1 AND (stAuc = 1 OR stAuc = 6 OR stAuc = 7 OR stAuc = 8) THEN
   IF high > ibh THEN
      stAuc = 2
   ELSIF low < ibl THEN
      stAuc = 3
   ENDIF
ENDIF


IF smRun = 1 THEN
   stBefore  = stAuc
   convFires = 0
   probeUp   = 0
   scoreHi   = 0
   isRetest  = 0


   // qValid = 0 on the very first evaluation after the initial balance closes,
   // because no auction window of this session has completed yet. Reading the
   // window buffer there would compare the LAST WINDOW OF THE PREVIOUS SESSION
   // against today's IB levels.
   failBelow = 0
   IF qValid = 1 AND (qO < ibl OR qL < ibl) AND qC > ibl AND qC < ibh THEN
      failBelow = 1
   ENDIF
   failAbove = 0
   IF qValid = 1 AND (qO > ibh OR qH > ibh) AND qC > ibl AND qC < ibh THEN
      failAbove = 1
   ENDIF
   bullAcc = 0
   IF qValid = 1 AND qC > ibh THEN
      bullAcc = 1
   ENDIF
   bearAcc = 0
   IF qValid = 1 AND qC < ibl THEN
      bearAcc = 1
   ENDIF


   IF awaitRt = 1 THEN
      // While a retest is pending nothing else can be evaluated: an untouched
      // level simply leaves the state where it was.
      touched = 0
      IF qValid = 1 AND accSide = 1 AND qL <= retestLvl THEN
         touched = 1
      ENDIF
      IF qValid = 1 AND accSide = 2 AND qH >= retestLvl THEN
         touched = 1
      ENDIF
      IF touched = 1 THEN
         holds = 0
         IF accSide = 1 AND qC > retestLvl THEN
            holds = 1
         ENDIF
         IF accSide = 2 AND qC < retestLvl THEN
            holds = 1
         ENDIF
         convFires = 1
         isRetest  = 1
         IF holds = 1 THEN
            stAuc   = 9
            convRet = 30
            awaitRt = 1
         ELSE
            stAuc   = 10
            convRet = 0
            awaitRt = 0
         ENDIF
         IF accSide = 1 THEN
            scoreHi = holds
         ELSE
            scoreHi = 1 - holds
         ENDIF
      ENDIF
   ELSIF failBelow = 1 AND failAbove = 1 THEN
      failAb    = 1
      failBl    = 1
      stAuc     = 8
      convFires = 1
      isRetest  = 1
      convRet   = 15
      upEx      = qH - ibh
      dnEx      = ibl - qL
      IF dnEx > upEx THEN
         scoreHi = 1
      ELSE
         scoreHi = 0
      ENDIF
   ELSIF failBelow = 1 THEN
      failBl = 1
      IF failAb = 1 THEN
         stAuc = 8
      ELSE
         stAuc = 7
      ENDIF
      convFires = 1
      probeUp   = 0
      scoreHi   = 1
   ELSIF failAbove = 1 THEN
      failAb = 1
      IF failBl = 1 THEN
         stAuc = 8
      ELSE
         stAuc = 6
      ENDIF
      convFires = 1
      probeUp   = 1
      scoreHi   = 0
   ELSIF bullAcc = 1 THEN
      accSide   = 1
      awaitRt   = 1
      retestLvl = ibh
      stAuc     = 4
      convFires = 1
      probeUp   = 1
      scoreHi   = 1
   ELSIF bearAcc = 1 THEN
      accSide   = 2
      awaitRt   = 1
      retestLvl = ibl
      stAuc     = 5
      convFires = 1
      probeUp   = 0
      scoreHi   = 0
   ENDIF


   // Conviction = where the window closed inside its own range (40 points),
   // how far it travelled outside the IB (30 points) and the retest (30).
   IF convFires = 1 THEN
      qRng = qH - qL
      IF qRng > 0 THEN
         clv = (qC - qL) / qRng * 100
      ELSE
         clv = 50
      ENDIF
      IF scoreHi = 1 THEN
         convAcc = clv * 0.4
      ELSE
         convAcc = (100 - clv) * 0.4
      ENDIF
      IF isRetest = 0 THEN
         IF probeUp = 1 THEN
            excur = qH - ibh
         ELSE
            excur = ibl - qL
         ENDIF
         IF ibW > 0 THEN
            excRat  = max(excur / ibW, 0)
            convExt = min(excRat, 1) * 30
         ELSE
            excRat  = 0
            convExt = 15
         ENDIF
         convRet = 15
         IF failBelow = 1 OR failAbove = 1 THEN
            failExc = excRat
            IF ibW > 0 THEN
               failExcOK = 1
            ELSE
               failExcOK = 0
            ENDIF
         ENDIF
      ELSE
         convExt = 15
      ENDIF
      convScore = convAcc + convExt + convRet
      convValid = 1
   ENDIF


   IF stAuc <> stBefore THEN
      candles = 1
   ELSE
      candles = candles + 1
   ENDIF


   IF stAuc = 4 AND stBefore <> 4 THEN
      becAA = 1
   ENDIF
   IF stAuc = 5 AND stBefore <> 5 THEN
      becAB = 1
   ENDIF
   IF stAuc = 6 AND stBefore <> 6 THEN
      becFA = 1
   ENDIF
   IF stAuc = 7 AND stBefore <> 7 THEN
      becFB = 1
   ENDIF
   IF stAuc = 8 AND stBefore <> 8 THEN
      becTS = 1
   ENDIF
   IF stAuc = 9 AND stBefore <> 9 THEN
      becCO = 1
   ENDIF
   IF stAuc = 10 AND stBefore <> 10 THEN
      becRJ = 1
   ENDIF


   IF stAuc = 9 THEN
      hadCont = 1
   ENDIF


   // Only one transition flag can be set on a given window, so clamping once
   // at the end is identical to clamping after every increment.
   IF becAA = 1 THEN
      press = press + 30
   ENDIF
   IF becAB = 1 THEN
      press = press - 30
   ENDIF
   IF becFA = 1 THEN
      press = press - 15
   ENDIF
   IF becFB = 1 THEN
      press = press + 15
   ENDIF
   IF becCO = 1 THEN
      IF accSide = 1 THEN
         press = press + 20
      ELSE
         press = press - 20
      ENDIF
   ENDIF
   IF becRJ = 1 THEN
      IF accSide = 1 THEN
         press = press - 20
      ELSE
         press = press + 20
      ENDIF
   ENDIF
   press = max(-100, min(100, press))
ENDIF


//----------------------------------------------
// EVENT CAPTURE
//----------------------------------------------
// Everything that ends up on the chart is stored here and painted once, on the
// last bar. That is what lets a live panel and a history of event marks live in
// the same indicator: DRAWONLASTBARONLY clears the previous pass without
// erasing the marks, because they are repainted from the buffer every time.
ONCE nMk = 0
ONCE nBx = 0


// mkType 1 accepted above   2 accepted below   3 two-sided
//        4 failed above     5 failed below
//        6 continuation up  7 continuation down
//        8 rejection from above          9 rejection from below
IF showMarks = 1 AND smRun = 1 THEN
   mkType = 0
   IF becAA = 1 THEN
      mkType = 1
   ELSIF becAB = 1 THEN
      mkType = 2
   ELSIF becTS = 1 THEN
      mkType = 3
   ELSIF becFA = 1 THEN
      mkType = 4
   ELSIF becFB = 1 THEN
      mkType = 5
   ELSIF becCO = 1 THEN
      IF accSide = 1 THEN
         mkType = 6
      ELSE
         mkType = 7
      ENDIF
   ELSIF becRJ = 1 THEN
      IF accSide = 1 THEN
         mkType = 8
      ELSE
         mkType = 9
      ENDIF
   ENDIF
   IF mkType > 0 THEN
      // The decision uses the window that closed on the previous bar, so the
      // mark is anchored on that bar and its Y is frozen here. Reading high or
      // low inside the repaint would line every mark up with the last candle.
      offs = averagetruerange[14] * 0.6
      IF mkType = 1 OR mkType = 5 OR mkType = 6 OR mkType = 9 THEN
         mkYc = low[1] - offs
      ELSE
         mkYc = high[1] + offs
      ENDIF
      mkSlot = nMk MOD mkRing
      $mkX[mkSlot] = barindex - 1
      $mkY[mkSlot] = mkYc
      $mkK[mkSlot] = mkType
      nMk = nMk + 1
   ENDIF
ENDIF


// Auction windows that traded through IBH or IBL.
IF showBoxes = 1 AND smRun = 1 AND qValid = 1 THEN
   touchIB = 0
   IF (qH >= ibh AND qL <= ibh) OR (qH >= ibl AND qL <= ibl) THEN
      touchIB = 1
   ENDIF
   IF touchIB = 1 THEN
      bxSlot = nBx MOD bxRing
      $bxX1[bxSlot] = qStart[1]
      $bxX2[bxSlot] = barindex - 1
      $bxHi[bxSlot] = qH
      $bxLo[bxSlot] = qL
      $bxOp[bxSlot] = qO
      $bxCl[bxSlot] = qC
      nBx = nBx + 1
   ENDIF
ENDIF


//----------------------------------------------
// PANEL READINGS
//----------------------------------------------
// Every panel reading is resolved into a numeric code here, and turned into
// text further down by one DRAWTEXT branch per possible value.


// REGIME: -1 "-" 0 Balanced 1 Rotational 2 Expansion 3 Failed Expansion 4 Trend
regCode = 0
IF stAuc = 9 THEN
   regCode = 4
ELSIF stAuc = 10 THEN
   regCode = 3
ELSIF stAuc = 4 OR stAuc = 5 THEN
   regCode = 2
ELSIF stAuc = 8 THEN
   regCode = 1
ELSIF failAb = 1 AND failBl = 1 THEN
   regCode = 1
ELSIF stAuc = 6 OR stAuc = 7 THEN
   regCode = 1
ENDIF
IF stAuc = 0 THEN
   regCode = -1
ENDIF


// BIAS: -1 "-" 0 Balanced 1 Bullish 2 Bearish 3 Bull Pressure 4 Bear Pressure
//        5 Conflicted
biasCode = 0
IF stAuc = 4 THEN
   biasCode = 1
ELSIF stAuc = 5 THEN
   biasCode = 2
ELSIF stAuc = 6 THEN
   biasCode = 4
ELSIF stAuc = 7 THEN
   biasCode = 3
ELSIF stAuc = 8 THEN
   biasCode = 5
ELSIF stAuc = 9 THEN
   IF accSide = 1 THEN
      biasCode = 1
   ELSE
      biasCode = 2
   ENDIF
ELSIF stAuc = 10 THEN
   IF accSide = 1 THEN
      biasCode = 2
   ELSE
      biasCode = 1
   ENDIF
ENDIF
IF stAuc = 0 THEN
   biasCode = -1
ENDIF


// A retest that is being touched right now, on the live bar.
liveRetest = 0
IF ibCompl = 1 AND awaitRt = 1 THEN
   IF accSide = 1 AND low <= retestLvl THEN
      liveRetest = 1
   ENDIF
   IF accSide = 2 AND high >= retestLvl THEN
      liveRetest = 1
   ENDIF
ENDIF


// PHASE: -1 "-" 0 Balance 1 Rotation 2 Probe 3 Acceptance 4 Expansion
//         5 Retest 6 Exhaustion
phCode = 0
IF liveRetest = 1 THEN
   phCode = 5
ELSIF stAuc = 8 THEN
   phCode = 1
ELSIF stAuc = 2 OR stAuc = 3 OR stAuc = 6 OR stAuc = 7 THEN
   phCode = 2
ELSIF stAuc = 4 OR stAuc = 5 THEN
   phCode = 3
ELSIF stAuc = 9 THEN
   phCode = 4
ELSIF stAuc = 10 THEN
   IF hadCont = 1 THEN
      phCode = 6
   ELSE
      phCode = 5
   ENDIF
ENDIF
IF stAuc = 0 THEN
   phCode = -1
ENDIF


// QUALITY: -1 "-" 0 Weak 1 Developing 2 Established 3 Strong 4 Moderate
//           5 High 6 Violent
aqCode = -1
IF convValid = 1 THEN
   aqScore = convScore + min(candles * 5, 20)
   IF candles <= 1 THEN
      IF aqScore < 40 THEN
         aqCode = 0
      ELSIF aqScore < 65 THEN
         aqCode = 1
      ELSE
         aqCode = 2
      ENDIF
   ELSE
      IF aqScore < 40 THEN
         aqCode = 0
      ELSIF aqScore < 65 THEN
         aqCode = 1
      ELSIF aqScore < 85 THEN
         aqCode = 2
      ELSE
         aqCode = 3
      ENDIF
   ENDIF
ENDIF


fqCode = -1
IF failExcOK = 1 THEN
   IF failExc < 0.3 THEN
      fqCode = 0
   ELSIF failExc < 0.7 THEN
      fqCode = 4
   ELSIF failExc < 1.2 THEN
      fqCode = 5
   ELSE
      fqCode = 6
   ENDIF
ENDIF


qualCode = -1
IF stAuc = 4 OR stAuc = 5 OR stAuc = 9 THEN
   qualCode = aqCode
ELSIF stAuc = 6 OR stAuc = 7 OR stAuc = 8 OR stAuc = 10 THEN
   qualCode = fqCode
ENDIF


// INVALIDATION: 0 "-" 1 close under IBH 2 close over IBL 3 close over IBH
//                4 close under IBL 5 acceptance on either side
invCode = 0
IF stAuc = 4 THEN
   invCode = 1
ELSIF stAuc = 5 THEN
   invCode = 2
ELSIF stAuc = 6 THEN
   invCode = 3
ELSIF stAuc = 7 THEN
   invCode = 4
ELSIF stAuc = 8 THEN
   invCode = 5
ELSIF stAuc = 9 THEN
   IF accSide = 1 THEN
      invCode = 1
   ELSE
      invCode = 2
   ENDIF
ELSIF stAuc = 10 THEN
   IF accSide = 1 THEN
      invCode = 3
   ELSE
      invCode = 4
   ENDIF
ENDIF


// NEXT: 0 await event 1 await IB 2 await probe 3 close over IBH
//        4 close under IBL 5 re-auction 6 await acceptance 10 pending retest
nxCode = 0
IF awaitRt = 1 THEN
   nxCode = 10
ELSIF stAuc = 0 THEN
   nxCode = 1
ELSIF stAuc = 1 THEN
   nxCode = 2
ELSIF stAuc = 2 THEN
   nxCode = 3
ELSIF stAuc = 3 THEN
   nxCode = 4
ELSIF stAuc = 6 OR stAuc = 7 OR stAuc = 10 THEN
   nxCode = 5
ELSIF stAuc = 8 THEN
   nxCode = 6
ENDIF


ibhTxt = round(ibh * pxDec) / pxDec
iblTxt = round(ibl * pxDec) / pxDec
rtTxt  = round(retestLvl * pxDec) / pxDec
dRtTxt = round(abs(close - retestLvl) * pxDec) / pxDec
IF invCode = 1 OR invCode = 3 THEN
   invTxt = ibhTxt
ELSE
   invTxt = iblTxt
ENDIF
prsTxt = round(abs(press))


//----------------------------------------------
// RENDER
//----------------------------------------------
IF islastbarupdate THEN


   IF showBoxes = 1 THEN
      nBxD = min(nBx, maxBx)
      IF nBxD > 0 THEN
         stBox = (nBx - nBxD) MOD bxRing
         FOR iBox = 0 TO nBxD - 1 DO
            sBox = (stBox + iBox) MOD bxRing
            IF $bxCl[sBox] > $bxOp[sBox] THEN
               bxR = bullR
               bxG = bullG
               bxB = bullB
            ELSE
               bxR = bearR
               bxG = bearG
               bxB = bearB
            ENDIF
            DRAWRECTANGLE($bxX1[sBox], $bxLo[sBox], $bxX2[sBox], $bxHi[sBox]) COLOURED(bxR, bxG, bxB, 0) FILLCOLOR(bxR, bxG, bxB, 30)
            DRAWRECTANGLE($bxX1[sBox], min($bxOp[sBox], $bxCl[sBox]), $bxX2[sBox], max($bxOp[sBox], $bxCl[sBox])) COLOURED(bxR, bxG, bxB, 0) FILLCOLOR(bxR, bxG, bxB, 60)
         NEXT
      ENDIF
   ENDIF


   IF showMarks = 1 THEN
      nMkD = min(nMk, maxMk)
      IF nMkD > 0 THEN
         stMrk = (nMk - nMkD) MOD mkRing
         FOR iMrk = 0 TO nMkD - 1 DO
            sMrk = (stMrk + iMrk) MOD mkRing
            kMrk = $mkK[sMrk]
            IF kMrk = 1 THEN
               DRAWTEXT("▲", $mkX[sMrk], $mkY[sMrk], SansSerif, Bold, 12) COLOURED(bullR, bullG, bullB)
            ELSIF kMrk = 2 THEN
               DRAWTEXT("▼", $mkX[sMrk], $mkY[sMrk], SansSerif, Bold, 12) COLOURED(bearR, bearG, bearB)
            ELSIF kMrk = 3 THEN
               DRAWTEXT("■", $mkX[sMrk], $mkY[sMrk], SansSerif, Bold, 11) COLOURED(midR, midG, midB)
            ELSIF kMrk = 4 OR kMrk = 5 THEN
               DRAWTEXT("✕", $mkX[sMrk], $mkY[sMrk], SansSerif, Bold, 12) COLOURED(warnR, warnG, warnB)
            ELSIF kMrk = 6 THEN
               DRAWTEXT("●", $mkX[sMrk], $mkY[sMrk], SansSerif, Bold, 12) COLOURED(bullR, bullG, bullB)
            ELSIF kMrk = 7 THEN
               DRAWTEXT("●", $mkX[sMrk], $mkY[sMrk], SansSerif, Bold, 12) COLOURED(bearR, bearG, bearB)
            ELSIF kMrk = 8 THEN
               DRAWTEXT("▼", $mkX[sMrk], $mkY[sMrk], SansSerif, Bold, 12) COLOURED(warnR, warnG, warnB)
            ELSIF kMrk = 9 THEN
               DRAWTEXT("▲", $mkX[sMrk], $mkY[sMrk], SansSerif, Bold, 12) COLOURED(warnR, warnG, warnB)
            ENDIF
         NEXT
      ENDIF
   ENDIF


   IF showPanel = 1 THEN
      vx = dashX + dashCol
      y1 = dashY
      y2 = dashY - rowH
      y3 = dashY - rowH * 2
      y4 = dashY - rowH * 3
      y5 = dashY - rowH * 4
      y6 = dashY - rowH * 5
      y7 = dashY - rowH * 6
      y8 = dashY - rowH * 7
      y9 = dashY - rowH * 8


      IF tfOK = 0 THEN
         DRAWTEXT("IB AUCTION", dashX, y1, SansSerif, Bold, 10) COLOURED(warnR, warnG, warnB) ANCHOR(topright, xshift, yshift)
         DRAWTEXT("Needs an intraday timeframe", vx, y2, SansSerif, Standard, 10) COLOURED(warnR, warnG, warnB) ANCHOR(topright, xshift, yshift)
         DRAWTEXT("no larger than the auction window", vx, y3, SansSerif, Standard, 10) COLOURED(warnR, warnG, warnB) ANCHOR(topright, xshift, yshift)
      ELSE
         DRAWTEXT("IB AUCTION", dashX, y1, SansSerif, Bold, 10) COLOURED(midR, midG, midB) ANCHOR(topright, xshift, yshift)
         DRAWTEXT("IBH #ibhTxt#  IBL #iblTxt#", vx, y1, SansSerif, Standard, 10) COLOURED(ibR, ibG, ibB) ANCHOR(topright, xshift, yshift)


         DRAWTEXT("REGIME", dashX, y2, SansSerif, Standard, 10) COLOURED(midR, midG, midB) ANCHOR(topright, xshift, yshift)
         IF regCode = -1 THEN
            DRAWTEXT("-", vx, y2, SansSerif, Bold, 10) COLOURED(midR, midG, midB) ANCHOR(topright, xshift, yshift)
         ELSIF regCode = 0 THEN
            DRAWTEXT("Balanced", vx, y2, SansSerif, Bold, 10) COLOURED(midR, midG, midB) ANCHOR(topright, xshift, yshift)
         ELSIF regCode = 1 THEN
            DRAWTEXT("Rotational", vx, y2, SansSerif, Bold, 10) COLOURED(midR, midG, midB) ANCHOR(topright, xshift, yshift)
         ELSIF regCode = 2 THEN
            DRAWTEXT("Expansion", vx, y2, SansSerif, Bold, 10) COLOURED(midR, midG, midB) ANCHOR(topright, xshift, yshift)
         ELSIF regCode = 3 THEN
            DRAWTEXT("Failed Expansion", vx, y2, SansSerif, Bold, 10) COLOURED(warnR, warnG, warnB) ANCHOR(topright, xshift, yshift)
         ELSE
            DRAWTEXT("Trend Auction", vx, y2, SansSerif, Bold, 10) COLOURED(midR, midG, midB) ANCHOR(topright, xshift, yshift)
         ENDIF


         IF biasCode = 1 THEN
            bcR = bullR
            bcG = bullG
            bcB = bullB
         ELSIF biasCode = 2 THEN
            bcR = bearR
            bcG = bearG
            bcB = bearB
         ELSIF biasCode = 3 OR biasCode = 4 THEN
            bcR = warnR
            bcG = warnG
            bcB = warnB
         ELSE
            bcR = midR
            bcG = midG
            bcB = midB
         ENDIF
         DRAWTEXT("BIAS", dashX, y3, SansSerif, Standard, 10) COLOURED(midR, midG, midB) ANCHOR(topright, xshift, yshift)
         IF biasCode = -1 THEN
            DRAWTEXT("-", vx, y3, SansSerif, Bold, 10) COLOURED(bcR, bcG, bcB) ANCHOR(topright, xshift, yshift)
         ELSIF biasCode = 0 THEN
            DRAWTEXT("Balanced", vx, y3, SansSerif, Bold, 10) COLOURED(bcR, bcG, bcB) ANCHOR(topright, xshift, yshift)
         ELSIF biasCode = 1 THEN
            DRAWTEXT("Bullish", vx, y3, SansSerif, Bold, 10) COLOURED(bcR, bcG, bcB) ANCHOR(topright, xshift, yshift)
         ELSIF biasCode = 2 THEN
            DRAWTEXT("Bearish", vx, y3, SansSerif, Bold, 10) COLOURED(bcR, bcG, bcB) ANCHOR(topright, xshift, yshift)
         ELSIF biasCode = 3 THEN
            DRAWTEXT("Bull Pressure", vx, y3, SansSerif, Bold, 10) COLOURED(bcR, bcG, bcB) ANCHOR(topright, xshift, yshift)
         ELSIF biasCode = 4 THEN
            DRAWTEXT("Bear Pressure", vx, y3, SansSerif, Bold, 10) COLOURED(bcR, bcG, bcB) ANCHOR(topright, xshift, yshift)
         ELSE
            DRAWTEXT("Conflicted", vx, y3, SansSerif, Bold, 10) COLOURED(bcR, bcG, bcB) ANCHOR(topright, xshift, yshift)
         ENDIF


         DRAWTEXT("PHASE", dashX, y4, SansSerif, Standard, 10) COLOURED(midR, midG, midB) ANCHOR(topright, xshift, yshift)
         IF phCode = -1 THEN
            DRAWTEXT("-", vx, y4, SansSerif, Bold, 10) COLOURED(midR, midG, midB) ANCHOR(topright, xshift, yshift)
         ELSIF phCode = 0 THEN
            DRAWTEXT("Balance", vx, y4, SansSerif, Bold, 10) COLOURED(midR, midG, midB) ANCHOR(topright, xshift, yshift)
         ELSIF phCode = 1 THEN
            DRAWTEXT("Rotation", vx, y4, SansSerif, Bold, 10) COLOURED(midR, midG, midB) ANCHOR(topright, xshift, yshift)
         ELSIF phCode = 2 THEN
            DRAWTEXT("Probe", vx, y4, SansSerif, Bold, 10) COLOURED(midR, midG, midB) ANCHOR(topright, xshift, yshift)
         ELSIF phCode = 3 THEN
            DRAWTEXT("Acceptance", vx, y4, SansSerif, Bold, 10) COLOURED(midR, midG, midB) ANCHOR(topright, xshift, yshift)
         ELSIF phCode = 4 THEN
            DRAWTEXT("Expansion", vx, y4, SansSerif, Bold, 10) COLOURED(midR, midG, midB) ANCHOR(topright, xshift, yshift)
         ELSIF phCode = 5 THEN
            DRAWTEXT("Retest", vx, y4, SansSerif, Bold, 10) COLOURED(midR, midG, midB) ANCHOR(topright, xshift, yshift)
         ELSE
            DRAWTEXT("Exhaustion", vx, y4, SansSerif, Bold, 10) COLOURED(warnR, warnG, warnB) ANCHOR(topright, xshift, yshift)
         ENDIF


         DRAWTEXT("AUCTION", dashX, y5, SansSerif, Standard, 10) COLOURED(midR, midG, midB) ANCHOR(topright, xshift, yshift)
         IF stAuc = 0 THEN
            DRAWTEXT("Building IB", vx, y5, SansSerif, Bold, 10) COLOURED(midR, midG, midB) ANCHOR(topright, xshift, yshift)
         ELSIF stAuc = 1 THEN
            DRAWTEXT("Balanced", vx, y5, SansSerif, Bold, 10) COLOURED(midR, midG, midB) ANCHOR(topright, xshift, yshift)
         ELSIF stAuc = 2 THEN
            DRAWTEXT("Probing Above (live)", vx, y5, SansSerif, Bold, 10) COLOURED(midR, midG, midB) ANCHOR(topright, xshift, yshift)
         ELSIF stAuc = 3 THEN
            DRAWTEXT("Probing Below (live)", vx, y5, SansSerif, Bold, 10) COLOURED(midR, midG, midB) ANCHOR(topright, xshift, yshift)
         ELSIF stAuc = 4 THEN
            DRAWTEXT("Accepted Above", vx, y5, SansSerif, Bold, 10) COLOURED(bullR, bullG, bullB) ANCHOR(topright, xshift, yshift)
         ELSIF stAuc = 5 THEN
            DRAWTEXT("Accepted Below", vx, y5, SansSerif, Bold, 10) COLOURED(bearR, bearG, bearB) ANCHOR(topright, xshift, yshift)
         ELSIF stAuc = 6 THEN
            DRAWTEXT("Failed Above", vx, y5, SansSerif, Bold, 10) COLOURED(warnR, warnG, warnB) ANCHOR(topright, xshift, yshift)
         ELSIF stAuc = 7 THEN
            DRAWTEXT("Failed Below", vx, y5, SansSerif, Bold, 10) COLOURED(warnR, warnG, warnB) ANCHOR(topright, xshift, yshift)
         ELSIF stAuc = 8 THEN
            DRAWTEXT("Two-Sided", vx, y5, SansSerif, Bold, 10) COLOURED(midR, midG, midB) ANCHOR(topright, xshift, yshift)
         ELSIF stAuc = 9 THEN
            DRAWTEXT("Continuation", vx, y5, SansSerif, Bold, 10) COLOURED(bcR, bcG, bcB) ANCHOR(topright, xshift, yshift)
         ELSE
            DRAWTEXT("Rejection", vx, y5, SansSerif, Bold, 10) COLOURED(warnR, warnG, warnB) ANCHOR(topright, xshift, yshift)
         ENDIF


         IF press > 10 THEN
            pcR = bullR
            pcG = bullG
            pcB = bullB
         ELSIF press < -10 THEN
            pcR = bearR
            pcG = bearG
            pcB = bearB
         ELSE
            pcR = midR
            pcG = midG
            pcB = midB
         ENDIF
         DRAWTEXT("PRESSURE", dashX, y6, SansSerif, Standard, 10) COLOURED(midR, midG, midB) ANCHOR(topright, xshift, yshift)
         IF stAuc = 0 THEN
            DRAWTEXT("-", vx, y6, SansSerif, Bold, 10) COLOURED(pcR, pcG, pcB) ANCHOR(topright, xshift, yshift)
         ELSIF press > 10 THEN
            DRAWTEXT("BUY #prsTxt#", vx, y6, SansSerif, Bold, 10) COLOURED(pcR, pcG, pcB) ANCHOR(topright, xshift, yshift)
         ELSIF press < -10 THEN
            DRAWTEXT("SELL #prsTxt#", vx, y6, SansSerif, Bold, 10) COLOURED(pcR, pcG, pcB) ANCHOR(topright, xshift, yshift)
         ELSE
            DRAWTEXT("NEUTRAL", vx, y6, SansSerif, Bold, 10) COLOURED(pcR, pcG, pcB) ANCHOR(topright, xshift, yshift)
         ENDIF


         DRAWTEXT("QUALITY", dashX, y7, SansSerif, Standard, 10) COLOURED(midR, midG, midB) ANCHOR(topright, xshift, yshift)
         IF qualCode = -1 THEN
            DRAWTEXT("-", vx, y7, SansSerif, Bold, 10) COLOURED(midR, midG, midB) ANCHOR(topright, xshift, yshift)
         ELSIF qualCode = 0 THEN
            DRAWTEXT("Weak", vx, y7, SansSerif, Bold, 10) COLOURED(midR, midG, midB) ANCHOR(topright, xshift, yshift)
         ELSIF qualCode = 1 THEN
            DRAWTEXT("Developing", vx, y7, SansSerif, Bold, 10) COLOURED(midR, midG, midB) ANCHOR(topright, xshift, yshift)
         ELSIF qualCode = 2 THEN
            DRAWTEXT("Established", vx, y7, SansSerif, Bold, 10) COLOURED(midR, midG, midB) ANCHOR(topright, xshift, yshift)
         ELSIF qualCode = 3 THEN
            DRAWTEXT("Strong", vx, y7, SansSerif, Bold, 10) COLOURED(midR, midG, midB) ANCHOR(topright, xshift, yshift)
         ELSIF qualCode = 4 THEN
            DRAWTEXT("Moderate", vx, y7, SansSerif, Bold, 10) COLOURED(midR, midG, midB) ANCHOR(topright, xshift, yshift)
         ELSIF qualCode = 5 THEN
            DRAWTEXT("High", vx, y7, SansSerif, Bold, 10) COLOURED(midR, midG, midB) ANCHOR(topright, xshift, yshift)
         ELSE
            DRAWTEXT("Violent", vx, y7, SansSerif, Bold, 10) COLOURED(warnR, warnG, warnB) ANCHOR(topright, xshift, yshift)
         ENDIF


         DRAWTEXT("NEXT", dashX, y8, SansSerif, Standard, 10) COLOURED(midR, midG, midB) ANCHOR(topright, xshift, yshift)
         IF nxCode = 10 THEN
            DRAWTEXT("Retest #rtTxt# (d #dRtTxt#)", vx, y8, SansSerif, Bold, 10) COLOURED(midR, midG, midB) ANCHOR(topright, xshift, yshift)
         ELSIF nxCode = 1 THEN
            DRAWTEXT("Await IB", vx, y8, SansSerif, Bold, 10) COLOURED(midR, midG, midB) ANCHOR(topright, xshift, yshift)
         ELSIF nxCode = 2 THEN
            DRAWTEXT("Await probe", vx, y8, SansSerif, Bold, 10) COLOURED(midR, midG, midB) ANCHOR(topright, xshift, yshift)
         ELSIF nxCode = 3 THEN
            DRAWTEXT("Close over #ibhTxt#", vx, y8, SansSerif, Bold, 10) COLOURED(midR, midG, midB) ANCHOR(topright, xshift, yshift)
         ELSIF nxCode = 4 THEN
            DRAWTEXT("Close under #iblTxt#", vx, y8, SansSerif, Bold, 10) COLOURED(midR, midG, midB) ANCHOR(topright, xshift, yshift)
         ELSIF nxCode = 5 THEN
            DRAWTEXT("Re-auction", vx, y8, SansSerif, Bold, 10) COLOURED(midR, midG, midB) ANCHOR(topright, xshift, yshift)
         ELSIF nxCode = 6 THEN
            DRAWTEXT("Await acceptance", vx, y8, SansSerif, Bold, 10) COLOURED(midR, midG, midB) ANCHOR(topright, xshift, yshift)
         ELSE
            DRAWTEXT("Await event", vx, y8, SansSerif, Bold, 10) COLOURED(midR, midG, midB) ANCHOR(topright, xshift, yshift)
         ENDIF


         DRAWTEXT("INVALID", dashX, y9, SansSerif, Standard, 10) COLOURED(midR, midG, midB) ANCHOR(topright, xshift, yshift)
         IF invCode = 0 THEN
            DRAWTEXT("-", vx, y9, SansSerif, Bold, 10) COLOURED(midR, midG, midB) ANCHOR(topright, xshift, yshift)
         ELSIF invCode = 1 OR invCode = 4 THEN
            DRAWTEXT("Close under #invTxt#", vx, y9, SansSerif, Bold, 10) COLOURED(warnR, warnG, warnB) ANCHOR(topright, xshift, yshift)
         ELSIF invCode = 2 OR invCode = 3 THEN
            DRAWTEXT("Close over #invTxt#", vx, y9, SansSerif, Bold, 10) COLOURED(warnR, warnG, warnB) ANCHOR(topright, xshift, yshift)
         ELSE
            DRAWTEXT("Acceptance either side", vx, y9, SansSerif, Bold, 10) COLOURED(warnR, warnG, warnB) ANCHOR(topright, xshift, yshift)
         ENDIF
      ENDIF
   ENDIF


ENDIF


RETURN ibhLine AS "IBH" COLOURED(ibR, ibG, ibB) STYLE(line, 2), iblLine AS "IBL" COLOURED(ibR, ibG, ibB) STYLE(line, 2), ibmLine AS "IBM" COLOURED(midR, midG, midB) STYLE(dottedline, 1), pUp1 AS "IB +0.5R" COLOURED(warnR, warnG, warnB) STYLE(dottedline, 1), pUp2 AS "IB +1.0R" COLOURED(warnR, warnG, warnB) STYLE(dottedline, 1), pUp3 AS "IB +1.5R" COLOURED(warnR, warnG, warnB) STYLE(dottedline, 1), pDn1 AS "IB -0.5R" COLOURED(warnR, warnG, warnB) STYLE(dottedline, 1), pDn2 AS "IB -1.0R" COLOURED(warnR, warnG, warnB) STYLE(dottedline, 1), pDn3 AS "IB -1.5R" COLOURED(warnR, warnG, warnB) STYLE(dottedline, 1)

Settings

ibStart (093000) and ibEnd (103000) — the opening window, in HHMMSS, read in the time your platform displays. This is the single most important setting and the easiest one to get wrong: if your broker shows a US index in European time, the New York open is not at 09:30 on your chart. Set them to the window you actually see. Overnight windows work: if ibStart is greater than ibEnd the window wraps across midnight.

auctionMin (30) — the length of each auction window in minutes. Thirty is the practical default: it confirms slowly enough to mean something and fast enough to be useful. Dropping to 5 gives many more events of much lower individual quality, which is occasionally what you want on a fast instrument and usually is not. The chart timeframe must fit inside the window.

showMid (1), showFill (1) — the midpoint line and the shading of the range.

showProj (0) — the six projection levels at 0.5, 1 and 1.5 range widths. Off by default because they clutter a chart that already has three lines on it; turn them on when you are working a day that has clearly left the range.

showMarks (1) — the event marks on the price. A triangle for acceptance, a cross for a failed auction, a square for a two-sided auction, a dot for a held retest, and an inverted triangle in the failure colour for a rejected one.

showBoxes (0) — shades every completed auction window that traded through IBH or IBL. It is the most literal way to see the tool working, and it is off by default because on a long history it is a lot of drawing.

maxMk (90) and maxBx (60) — how many marks and shaded windows are kept on the chart. Lower them if the chart feels heavy.

dashX (-380), dashCol (170), dashY (-25), rowH (20) — panel geometry in pixels from the top right corner. dashX places the label column, dashCol is the offset to the value column, dashY the first row and rowH the row spacing.

dashDec (2) — how many decimals the panel prints for prices. Raise it on forex, drop it to 0 on an index future.

Colours — ibR/G/B for the Initial Balance lines, midR/G/B for the midpoint and neutral text, bullR/G/B and bearR/G/B for directional readings and warnR/G/B for failures, rejections and projections. They are mid-tones rather than saturated primaries so that they hold their contrast on both a white and a dark chart.

Notes and Limitations

It needs an intraday timeframe that fits inside an auction window. Below 1 minute or above 30 the tool switches off and the panel says so. With 30 minute windows, anything from 1 to 30 minutes works; with 5 minute windows you need a 5 minute chart or faster.

The clock is your platform’s clock. There is no timezone conversion anywhere in the tool, which is a feature as much as a limitation: what you set is what you see. It does mean that if you change broker, or if your platform switches between winter and summer time differently from the exchange, you have to revisit ibStart and ibEnd.

A session with no bars inside the window is skipped. On a holiday half day, or on an instrument that has not started trading when the window opens, no new Initial Balance forms and the previous session’s levels stay on the chart. That is usually what you want; it is worth knowing it is what happens.

Acceptance is a close, not a touch. This is what makes the readings stable and it is also why the tool will sometimes look slow. Price can spend twenty minutes above IBH and the state will still read Probing Above until a window closes there. If you want the earlier read, shorten auctionMin — and accept that you are buying speed with confirmation.

The state machine describes, it does not predict. Every reading in the panel is a statement about what has already happened. Trend Auction does not mean the trend continues; it means the retest of an accepted edge has held so far, and INVALID tells you the price at which that stops being true. Read it as a running description of the auction, which is what it is.

Pressure never decays. An acceptance from the first window of the afternoon still counts as much at the close as it did at the time. Over a long session that makes Pressure a genuine session-level summary, but it also means an early violent event can hold the reading in one direction for hours. The Bias row exists to tell you what is happening now.

Conclusion

The transferable idea here is the auction window itself. Almost every opening range tool evaluates on the bar — the bar that closes above the level, the bar that breaks it — and the bar is an arbitrary unit that has nothing to do with how the auction actually works. Grouping bars into fixed windows and forcing a single classification per window costs very little code and removes most of the noise, because it makes the market commit before it is allowed to speak.

The second idea worth taking is the separation of the last event from the running total. Any state machine can tell you where it is. Keeping a bounded tally of everything that got you there, and displaying it next to the current state so that the two can visibly disagree, turns a classifier into something you can actually reason with.

Concept and design by dgtrd (DGT).

Download
Filename: PRC_Initial-Balance-Auction.itf
Downloads: 13
Iván González Legend
Currently debugging life, so my bio is on hold. Check back after the next commit for an update.
Author’s Profile

Comments

Logo Logo
Loading...