Iván González

Liquidity Master

Category: Indicators By: Iván González Created: October 23, 2026, 3:42 PM
October 23, 2026, 3:42 PM
Indicators
0 Comments
Liquidity Master

Introduction

 

Resting orders are not placed at random. Stops sit just beyond the last swing high and just below the last swing low, and the orders that stopped a push leave a long wick behind them. None of this shows up in an order book you can see from a chart, but all of it leaves a trace in the candles.

Liquidity Master by SimpleAlgoAI reads those traces and turns them into a depth ladder drawn beside price. Every confirmed swing adds a pool of stops past it, every rejection wick adds the orders that absorbed it, and each pool stays on the ladder until price trades through it or it fades with age. What remains is stacked into rows: bids below price in one colour, offers above price in another, and the longer the row, the more liquidity is estimated to be resting there. The biggest row on each side becomes a named wall with a dotted line back across the chart, and a panel keeps score of how the walls on this chart have behaved when price reached them.

Theory Behind the Indicator

 

Two kinds of pool. When a swing high is confirmed (a bar higher than the bars on each side of it, 4 by default), a pool of buy stops is added in the band from the swing high to three quarters of an ATR above it; a swing low adds a pool of sell stops in the band below it. A rejection wick at least 0.45 ATR long becomes a pool too: the wick itself is where the orders that absorbed the push were resting. Swing pools weigh 1.6; wick pools weigh 0.5 times the volume of the bar relative to its 50-bar average (capped at 4), or 0.5 on instruments without volume.

Spent as price trades through. On every closed bar each pool above price is eaten into up to that bar’s high, and each pool below price down to that bar’s low. Only the part of the zone that price has not reached is still counted, and once price has crossed the whole zone the pool is gone. A level that price has already visited is no longer drawn as liquidity.

Ageing. Orders get pulled. A pool loses half of its weight every 300 bars and is dropped after four half-lives. At most 400 pools are kept; when a new one arrives with the list full, the oldest goes.

The ladder. The ladder covers the price range of the last 300 bars plus a margin, cut into 80 rows on a fixed price grid (the rows do not slide with every tick). Each pool spreads its remaining weight over the rows it overlaps, in proportion to the overlap. The rows are smoothed once with their neighbours and scaled so that the biggest row has full width. The ladder is relative: it shows where liquidity is thick and where it is thin, not how many contracts are there.

The walls. The biggest row at least 0.3 ATR above the close is the sell wall, and the biggest row at least 0.3 ATR below it is the buy wall. The nearest row holding at least 30% of the biggest one is the first pool in the way on each side, which is not always the wall.

The record. Every 10 bars the walls are noted (a wall must hold at least half of the biggest row to count). When price reaches a noted wall a test starts. A close half an ATR through the wall means it broke; a close half an ATR back from it means it held; a test without a verdict after 60 bars is dropped. The last 10 verdicts are kept. The rule is symmetric, so on a chart where walls mean nothing the score drifts around 5 out of 10.

Everything is built from closed bars only: the bar in progress spends and adds nothing until it closes. On the live bar the ladder and the walls follow the close, which decides which rows are above and below price, and the record changes only when a bar closes.

Key Features at a Glance

 

  • Resting liquidity estimated from swing stops and rejection wicks, weighted by volume and age.
  • Pools spent as price trades through them, so the ladder only shows what is still in the way.
  • A depth ladder of 80 rows over the last bars or in the empty space to the right of price.
  • Sell and buy walls with a dotted line, a soft halo and their price.
  • A panel with both walls, the balance of liquidity above and below price, the record of the last 10 wall tests and a one-line reading.
  • A companion indicator, Liquidity Master Alerts, to set alerts on the four events: sell wall reached, buy wall reached, wall held and wall broke.

How to Read the Indicator

 

  • Thick rows are where price is expected to slow down; thin stretches are where it can move fast. A ladder that is thick below and thin above describes a market with a floor and no ceiling in reach.
  • The walls are the first places where a rally (sell wall) or a drop (buy wall) should be tested. The panel gives their distance in ATRs: a wall 0.4 ATR away matters now, one 7 ATR away is background.
  • Balance gives the share of resting liquidity below and above price. Above 58% on one side the panel calls that side the thicker one.
  • Walls here is the score of the last 10 tests. A high score means walls on this chart have been respected lately; a low one means they tend to get run, and a wall is more of a target than a barrier.
  • Read sums it up in one line: which pool is the first thing in the way, whether it is the wall itself, which side is thicker, or that a test is in progress.

Practical Applications

 

  • Fading the walls: on a chart whose walls hold most of their tests, a first touch of a wall with thin liquidity behind price is a natural place to look for a reversal.
  • Targets: on a chart where walls tend to break, the wall on the other side is a target rather than an obstacle.
  • Stops: a stop placed just beyond a thick row sits behind the liquidity that should slow price down; a stop inside a thin stretch has nothing in front of it.
  • Context for breakouts: a breakout through a wall into a thin part of the ladder has room to run until the next thick row.

Indicator Configuration

 

Liquidity:

  • pivIn (default 4, 2 to 20): bars on each side of a swing high or low. Lower it for more pools, raise it for only the bigger swings.
  • wickIn (default 0.45, 0.2 to 2): a wick at least this many ATRs long becomes a pool.
  • halfIn (default 300, 50 to 3000): half of a pool’s weight is gone after this many bars.
  • lookIn (default 1500, 300 to 4000): the pools, walls and record are computed on the most recent bars only.

Ladder:

  • posIn (default 0): 0 draws the ladder over the last bars, like a volume profile; 1 draws it in the empty space to the right of price, which needs right margin on the chart.
  • widthIn (default 30, 10 to 100): width of the ladder in bars.
  • spanIn (default 300, 50 to 2000): the ladder covers the price range of this many bars plus a margin. Match it to the bars you keep on screen.
  • rowsIn (default 80, 20 to 100): number of rows.
  • themeIn (default 1): 1 = Mint and Pink, 2 = Ice, 3 = Custom with the colours in cBidR/G/B and cAskR/G/B.
  • bright (default 3, 1 to 5): brightness of the rows.
  • showWalls, showNames, showPrice, showPanel (default 1): wall lines, wall names, price tag (only when the ladder sits right of price) and panel.
  • panelPos (default 2): 1 top left, 2 top right, 3 bottom left, 4 bottom right. On the left the panel usually sits over the candles, and ProRealTime draws the candles and the wall lines on top of it, so the left corners only suit an empty part of the chart.
  • panelSize (default 2): 1 small, 2 normal, 3 large.
  • nameOff (default 20): the wall names are centred this many bars left of the ladder’s widest row, just off their line (above the sell wall, below the buy wall). Raise it if they touch the rows when you zoom far out.

The rules behind the pools and the record are fixed in the code: the stop zone of three quarters of an ATR, the weights, the refresh every 10 bars, the half-ATR verdicts and the 60-bar limit on a test.

On a dark chart background the default colours work as they are; on a white background the Custom theme with darker colours makes the rows easier to read. The wall names take a darker shade of their side’s colour whenever it is too light to read on white, so they read on both backgrounds. The panel draws its own solid dark background with bold text, so it reads on both too.

Alerts. ProRealTime alerts can only read the values an indicator returns, and Liquidity Master only draws. For alerts, add the second indicator, Liquidity Master Alerts, in its own panel below the chart, with the same pivIn, wickIn, halfIn, lookIn, spanIn and rowsIn as Liquidity Master, so both map the same walls. It returns four bars: Sell wall reached, Buy wall reached, Wall held and Wall broke, worth 1 on the bar right after the event and 0 otherwise. Create the alert on the one you want with the condition “crosses over 0.5”. The bars only mark the events while the chart stays open: when the chart is reloaded, the past values are 0.

The Code

 

//-----------------------------------------------------------------------
//PRC_Liquidity Master
//version = 0
//22.10.2026
//Iván González @ www.prorealcode.com
//Author: SimpleAlgoAI
//Sharing ProRealTime knowledge
//-----------------------------------------------------------------------
defparam drawonlastbaronly = true

// ===================== INPUTS =====================
// --- Liquidity ---
pivIn = 4           // swing strength: a swing needs this many lower highs / higher lows on each side (2 to 20)
wickIn = 0.45       // wick rejection: a wick at least this many ATRs long becomes a pool (0.2 to 2)
halfIn = 300        // liquidity ages out: half of a pool is gone after this many bars (50 to 3000)
lookIn = 1500       // bars to compute: the engine runs on the most recent bars only (300 to 4000)
// --- Ladder ---
posIn = 0           // ladder sits: 0 = over the last bars, 1 = right of price (needs right margin on the chart)
widthIn = 30        // ladder width, in bars (10 to 100)
spanIn = 300        // the ladder covers the price range of this many recent bars, plus a margin (50 to 2000)
rowsIn = 80         // rows (20 to 100)
themeIn = 1         // colours: 1 = Mint and Pink, 2 = Ice, 3 = Custom (the six values below)
cBidR = 0
cBidG = 255
cBidB = 163
cAskR = 255
cAskG = 61
cAskB = 113
bright = 3          // brightness (1 to 5)
showWalls = 1       // 1 = wall lines
showNames = 1       // 1 = wall names
showPrice = 1       // 1 = price tag (only shown when the ladder sits right of price)
showPanel = 1       // 1 = panel
panelPos = 2        // panel position: 1 = top left, 2 = top right, 3 = bottom left, 4 = bottom right
panelSize = 2       // panel size: 1 = small, 2 = normal, 3 = large
nameOff = 20        // wall names: the text is centred this many bars left of the ladder's widest row

// ===================== FIXED RULES =====================
maxEv = 400         // pools kept at once
maxRows = 100       // ladder rows available
zoneATR = 0.75      // stops sit within three quarters of an ATR past a swing
pivW = 1.6          // weight of the stops past a swing
wickW = 0.5         // weight of a rejection wick, times its relative volume
refreshEvery = 10   // bars between wall refreshes for the record
keepRec = 10        // wall tests remembered
brokeATR = 0.5      // a close this far past a wall breaks it
heldATR = 0.5       // a close this far back from a wall means it held
testBars = 60       // a test is dropped after this many bars without a verdict
lineBack = 150      // how far the wall lines reach back
wallAt = 0.5        // a wall must hold at least this share of the biggest row to be tracked

pivN = max(2, min(20, round(pivIn)))
wickK = max(0.2, min(2, wickIn))
halfN = max(50, min(3000, round(halfIn)))
lookN = max(300, min(4000, round(lookIn)))
widN = max(10, min(100, round(widthIn)))
spanN = max(50, min(2000, round(spanIn)))
nrow = min(max(20, min(100, round(rowsIn))), maxRows)
brightN = max(1, min(5, round(bright)))
brightMul = 0.4 + 0.2 * brightN

// Colours: bids (below price) and offers (above price)
IF themeIn = 2 THEN
   bidR = 125
   bidG = 211
   bidB = 252
   askR = 196
   askG = 181
   askB = 253
ELSIF themeIn = 3 THEN
   bidR = cBidR
   bidG = cBidG
   bidB = cBidB
   askR = cAskR
   askG = cAskG
   askB = cAskB
ELSE
   bidR = 0
   bidG = 255
   bidB = 163
   askR = 255
   askG = 61
   askB = 113
ENDIF
// Wall names: they sit straight on the chart, with no box behind them. A side colour too light to
// read on a white background (the mint, the Ice theme) is darkened just enough, to a contrast of
// 4 to 1 against white; a colour that already reads is kept
lumB = 0.2126 * pow(bidR / 255, 2.2) + 0.7152 * pow(bidG / 255, 2.2) + 0.0722 * pow(bidB / 255, 2.2)
kB = 1
IF lumB > 0.2125 THEN
   kB = pow(0.2125 / lumB, 1 / 2.2)
ENDIF
nbR = round(bidR * kB)
nbG = round(bidG * kB)
nbB = round(bidB * kB)
lumA = 0.2126 * pow(askR / 255, 2.2) + 0.7152 * pow(askG / 255, 2.2) + 0.0722 * pow(askB / 255, 2.2)
kA = 1
IF lumA > 0.2125 THEN
   kA = pow(0.2125 / lumA, 1 / 2.2)
ENDIF
naR = round(askR * kA)
naG = round(askG * kA)
naB = round(askB * kA)
// Panel ink: light text, drawn on the panel's own dark background
inkR = 209
inkG = 212
inkB = 220

// ===================== INPUTS TO THE ENGINE (every bar) =====================
// ATR(14) and the slow ATR(50) for the ladder geometry; the bar range until they exist
atr14 = averagetruerange[14](close)
IF barindex >= 13 THEN
   atrV = atr14
ELSE
   atrV = high - low
ENDIF
atrV = max(atrV, ticksize)
atr50 = averagetruerange[50](close)
IF barindex >= 49 THEN
   atrGV = atr50
ELSE
   atrGV = atrV
ENDIF
atrGV = max(atrGV, ticksize)
// Volume against its 50-bar average (1 when the instrument has no volume)
vAvg = average[50](volume)
vRel = 1
IF barindex >= 49 THEN
   IF vAvg > 0 THEN
      vRel = min(volume / vAvg, 4)
   ENDIF
ENDIF
// Swing high / low confirmed this bar: the bar pivN bars back, higher (lower) than the pivN bars
// on its right and at least as high (low) as the pivN bars on its left (on a flat top the most
// recent bar of the plateau is the swing)
hhR = highest[pivN](high)
llR = lowest[pivN](low)
phF = 0
phP = 0
plF = 0
plP = 0
IF barindex >= 2 * pivN THEN
   candH = high[pivN]
   IF candH > hhR AND candH >= hhR[pivN + 1] THEN
      phF = 1
      phP = candH
   ENDIF
   candL = low[pivN]
   IF candL < llR AND candL <= llR[pivN + 1] THEN
      plF = 1
      plP = candL
   ENDIF
ENDIF
// Ladder grid: the range of the last spanN bars plus a margin, on rows of a fixed price step
hhSp = highest[spanN](high)
llSp = lowest[spanN](low)
spanOk = 0
IF barindex >= spanN - 1 THEN
   spanOk = 1
ENDIF
marg = max(1.5 * atrGV, 0.08 * (hhSp - llSp))
stepV = max(round(((hhSp - llSp + 2 * marg) / nrow) / ticksize) * ticksize, ticksize)
baseV = floor((llSp - marg) / stepV) * stepV

// ===================== THE ENGINE (last bar) =====================
// The pools, the walls and the record are rebuilt from the last lookN bars, once per new bar and
// only from CLOSED bars: the live bar spends and adds nothing until it closes. The result is kept
// in arrays, because arrays are not rewound between ticks the way scalar variables are.
IF barindex = 0 THEN
   $runAt[0] = 0 - 1
ENDIF

IF islastbarupdate THEN
   doEng = 0
   IF $runAt[0] <> barindex THEN
      doEng = 1
   ENDIF
   IF doEng = 1 THEN
      nEv = 0
      tSide = 0
      tP = 0
      tBar = 0
      wUpOk = 0
      wUpV = 0
      wDnOk = 0
      wDnV = 0
      nRec = 0
      $eng[0] = 0
      $eng[1] = 0
      $eng[2] = 0
      jStart = min(lookN - 1, barindex)
   ELSE
      nEv = $eng[0]
      jStart = 0
   ENDIF

   FOR j = jStart DOWNTO 0 DO
      bi = barindex - j
      hj = high[j]
      lj = low[j]
      cj = close[j]
      aj = atrV[j]
      bStep = stepV[j]
      bBase = baseV[j]
      bOk = spanOk[j]
      doBuild = 0
      IF j >= 1 THEN
         // 1. price trading through a pool spends it, and old pools are gone
         IF nEv > 0 THEN
            k = 0
            FOR i = 0 TO nEv - 1 DO
               gone = 0
               IF bi - $evBar[i] > 4 * halfN THEN
                  gone = 1
               ENDIF
               IF $evSide[i] = 1 THEN
                  ext = max($evExt[i], hj)
                  IF ext >= $evP1[i] THEN
                     gone = 1
                  ENDIF
               ELSE
                  ext = min($evExt[i], lj)
                  IF ext <= $evP0[i] THEN
                     gone = 1
                  ENDIF
               ENDIF
               IF gone = 0 THEN
                  $evSide[k] = $evSide[i]
                  $evP0[k] = $evP0[i]
                  $evP1[k] = $evP1[i]
                  $evW[k] = $evW[i]
                  $evBar[k] = $evBar[i]
                  $evExt[k] = ext
                  k = k + 1
               ENDIF
            NEXT
            nEv = k
         ENDIF
         // 2. new pools: the stops past a swing that just confirmed, and the orders in a rejection wick
         oj = open[j]
         FOR q = 1 TO 4 DO
            qOk = 0
            IF q = 1 THEN
               IF phF[j] = 1 THEN
                  IF hhR[j] < phP[j] + zoneATR * aj THEN
                     qOk = 1
                     qSide = 1
                     qP0 = phP[j]
                     qP1 = phP[j] + zoneATR * aj
                     qW = pivW
                     qBar = bi - pivN
                     qExt = max(hhR[j], phP[j])
                  ENDIF
               ENDIF
            ELSIF q = 2 THEN
               IF plF[j] = 1 THEN
                  IF llR[j] > plP[j] - zoneATR * aj THEN
                     qOk = 1
                     qSide = -1
                     qP0 = plP[j] - zoneATR * aj
                     qP1 = plP[j]
                     qW = pivW
                     qBar = bi - pivN
                     qExt = min(llR[j], plP[j])
                  ENDIF
               ENDIF
            ELSIF q = 3 THEN
               IF hj - max(oj, cj) >= wickK * aj THEN
                  qOk = 1
                  qSide = 1
                  qP0 = max(oj, cj)
                  qP1 = hj
                  qW = wickW * vRel[j]
                  qBar = bi
                  qExt = max(oj, cj)
               ENDIF
            ELSE
               IF min(oj, cj) - lj >= wickK * aj THEN
                  qOk = 1
                  qSide = -1
                  qP0 = lj
                  qP1 = min(oj, cj)
                  qW = wickW * vRel[j]
                  qBar = bi
                  qExt = min(oj, cj)
               ENDIF
            ENDIF
            IF qOk = 1 THEN
               // at most maxEv pools: the oldest one goes
               IF nEv >= maxEv THEN
                  FOR i = 1 TO nEv - 1 DO
                     $evSide[i - 1] = $evSide[i]
                     $evP0[i - 1] = $evP0[i]
                     $evP1[i - 1] = $evP1[i]
                     $evW[i - 1] = $evW[i]
                     $evBar[i - 1] = $evBar[i]
                     $evExt[i - 1] = $evExt[i]
                  NEXT
                  nEv = nEv - 1
               ENDIF
               $evSide[nEv] = qSide
               $evP0[nEv] = qP0
               $evP1[nEv] = qP1
               $evW[nEv] = qW
               $evBar[nEv] = qBar
               $evExt[nEv] = qExt
               nEv = nEv + 1
            ENDIF
         NEXT
         // 3. every refreshEvery bars, name the walls for the record
         IF (bi MOD refreshEvery) = 0 AND nEv >= 15 THEN
            doBuild = 1
         ENDIF
      ELSE
         // the live bar: the ladder that is drawn
         doBuild = 1
      ENDIF

      IF doBuild = 1 THEN
         // Resting liquidity per row: each pool's remaining zone spread over the rows it overlaps,
         // weighted by its age; then smoothed once with the neighbours
         FOR r = 0 TO nrow - 1 DO
            $rowS[r] = 0
         NEXT
         IF nEv > 0 AND bOk = 1 THEN
            FOR i = 0 TO nEv - 1 DO
               IF $evSide[i] = 1 THEN
                  a0 = max($evP0[i], $evExt[i])
                  a1 = $evP1[i]
               ELSE
                  a0 = $evP0[i]
                  a1 = min($evP1[i], $evExt[i])
               ENDIF
               IF a1 > a0 THEN
                  wq = $evW[i] * pow(0.5, (bi - $evBar[i]) / halfN)
                  r0 = max(floor((a0 - bBase) / bStep), 0)
                  r1 = min(floor((a1 - bBase) / bStep), nrow - 1)
                  IF r1 >= r0 THEN
                     FOR r = r0 TO r1 DO
                        lo = bBase + r * bStep
                        ov = min(a1, lo + bStep) - max(a0, lo)
                        IF ov > 0 THEN
                           $rowS[r] = $rowS[r] + wq * ov / (a1 - a0)
                        ENDIF
                     NEXT
                  ENDIF
               ENDIF
            NEXT
         ENDIF
         peak = 0
         prv = $rowS[0]
         FOR r = 0 TO nrow - 1 DO
            cur = $rowS[r]
            IF r < nrow - 1 THEN
               nxt = $rowS[r + 1]
            ELSE
               nxt = cur
            ENDIF
            sm = 0.25 * prv + 0.5 * cur + 0.25 * nxt
            prv = cur
            $rowS[r] = sm
            peak = max(peak, sm)
         NEXT
         // The walls: the biggest row on each side at least 0.3 ATR from price; also the nearest
         // real pool on each side and the liquidity on each side
         upOk = 0
         upP = 0
         upT = 0
         dnOk = 0
         dnP = 0
         dnT = 0
         nUpOk = 0
         nUpP = 0
         nDnOk = 0
         nDnP = 0
         sumUp = 0
         sumDn = 0
         IF peak > 0 THEN
            FOR r = 0 TO nrow - 1 DO
               mid = bBase + (r + 0.5) * bStep
               tq = $rowS[r] / peak
               IF mid >= cj + 0.3 * aj THEN
                  sumUp = sumUp + tq
                  IF tq > upT THEN
                     upT = tq
                     upP = mid
                     upOk = 1
                  ENDIF
                  IF tq >= 0.3 AND nUpOk = 0 THEN
                     nUpOk = 1
                     nUpP = mid
                  ENDIF
               ELSIF mid <= cj - 0.3 * aj THEN
                  sumDn = sumDn + tq
                  IF tq > dnT THEN
                     dnT = tq
                     dnP = mid
                     dnOk = 1
                  ENDIF
                  IF tq >= 0.3 THEN
                     nDnOk = 1
                     nDnP = mid
                  ENDIF
               ENDIF
            NEXT
         ENDIF
      ENDIF

      IF j >= 1 THEN
         IF doBuild = 1 THEN
            wUpOk = 0
            IF upOk = 1 AND upT >= wallAt THEN
               wUpOk = 1
               wUpV = upP
            ENDIF
            wDnOk = 0
            IF dnOk = 1 AND dnT >= wallAt THEN
               wDnOk = 1
               wDnV = dnP
            ENDIF
         ENDIF
         // 4. a wall gets tested when price reaches it: it held if price backs off, it broke if
         // price closes through
         IF tSide = 0 THEN
            IF wUpOk = 1 AND hj >= wUpV - bStep / 2 THEN
               tSide = 1
               tP = wUpV
               tBar = bi
               wUpOk = 0
            ELSIF wDnOk = 1 AND lj <= wDnV + bStep / 2 THEN
               tSide = -1
               tP = wDnV
               tBar = bi
               wDnOk = 0
            ENDIF
         ELSE
            brk = 0
            hld = 0
            IF tSide = 1 THEN
               IF cj > tP + brokeATR * aj THEN
                  brk = 1
               ENDIF
               IF cj <= tP - heldATR * aj THEN
                  hld = 1
               ENDIF
            ELSE
               IF cj < tP - brokeATR * aj THEN
                  brk = 1
               ENDIF
               IF cj >= tP + heldATR * aj THEN
                  hld = 1
               ENDIF
            ENDIF
            IF brk = 1 OR hld = 1 THEN
               // the last keepRec verdicts: 1 the wall held, 0 it broke
               IF nRec >= keepRec THEN
                  FOR i = 1 TO nRec - 1 DO
                     $rec[i - 1] = $rec[i]
                  NEXT
                  nRec = nRec - 1
               ENDIF
               IF brk = 1 THEN
                  $rec[nRec] = 0
               ELSE
                  $rec[nRec] = 1
               ENDIF
               nRec = nRec + 1
               tSide = 0
            ELSIF bi - tBar > testBars THEN
               tSide = 0
            ENDIF
         ENDIF
         IF j = 1 THEN
            $eng[0] = nEv
            $eng[1] = tSide
            $eng[2] = nRec
         ENDIF
      ENDIF
   NEXT
   $runAt[0] = barindex

   // ===================== THE LADDER =====================
   IF posIn = 1 THEN
      xR = barindex + 2 + widN
   ELSE
      xR = barindex
   ENDIF
   xL = xR - widN
   IF peak > 0 THEN
      FOR r = 0 TO nrow - 1 DO
         tq = $rowS[r] / peak
         y0 = bBase + r * bStep
         y1 = y0 + bStep
         IF (y0 + y1) / 2 >= close THEN
            cR = askR
            cG = askG
            cB = askB
         ELSE
            cR = bidR
            cG = bidG
            cB = bidB
         ENDIF
         wd = max(round(widN * tq), 1)
         IF tq >= 0.03 THEN
            trp = round(82 - 65 * pow(tq, 1.2) * brightMul)
            IF posIn = 1 THEN
               trp = min(max(trp, 10), 90)
            ELSE
               trp = min(max(trp, 32), 90)
            ENDIF
            alphaV = round(255 * (100 - trp) / 100)
            DRAWRECTANGLE(xR - wd, y1 - bStep * 0.07, xR, y0 + bStep * 0.07) COLOURED(cR, cG, cB, 0) FILLCOLOR(cR, cG, cB, alphaV)
         ENDIF
         // a soft glow behind the rows that hold more than half of the biggest one
         IF tq > 0.5 THEN
            trp = round(100 - 14 * tq * brightMul)
            alphaV = round(255 * (100 - trp) / 100)
            DRAWRECTANGLE(xR - wd - 1, y1 + bStep * 0.2, xR, y0 - bStep * 0.2) COLOURED(cR, cG, cB, 0) FILLCOLOR(cR, cG, cB, alphaV)
         ENDIF
      NEXT
   ENDIF
   IF bOk = 1 THEN
      DRAWSEGMENT(xR + 1, bBase, xR + 1, bBase + nrow * bStep) COLOURED(42, 46, 57, 255) STYLE(line, 1)
   ENDIF

   // Prices as the chart shows them
   IF ticksize >= 1 THEN
      pxU = round(upP)
      pxD = round(dnP)
      pxC = round(close)
   ELSIF ticksize >= 0.01 THEN
      pxU = round(upP * 100) / 100
      pxD = round(dnP * 100) / 100
      pxC = round(close * 100) / 100
   ELSE
      pxU = round(upP / ticksize) * ticksize
      pxD = round(dnP / ticksize) * ticksize
      pxC = round(close / ticksize) * ticksize
   ENDIF

   // The walls: a dotted line back across the chart, with a soft halo
   xW = max(0, barindex - lineBack)
   IF showWalls = 1 AND upOk = 1 THEN
      DRAWSEGMENT(xW, upP, xR, upP) COLOURED(askR, askG, askB, 255) STYLE(dottedline, 1)
      DRAWSEGMENT(xW, upP, xR, upP) COLOURED(askR, askG, askB, 71) STYLE(line, 3)
      DRAWSEGMENT(xW, upP, xR, upP) COLOURED(askR, askG, askB, 36) STYLE(line, 5)
   ENDIF
   IF showWalls = 1 AND dnOk = 1 THEN
      DRAWSEGMENT(xW, dnP, xR, dnP) COLOURED(bidR, bidG, bidB, 255) STYLE(dottedline, 1)
      DRAWSEGMENT(xW, dnP, xR, dnP) COLOURED(bidR, bidG, bidB, 71) STYLE(line, 3)
      DRAWSEGMENT(xW, dnP, xR, dnP) COLOURED(bidR, bidG, bidB, 36) STYLE(line, 5)
   ENDIF
   // The names sit by the wall lines, left of the ladder's widest row and just off the line
   // (above the sell wall, below the buy wall): with no box behind them they would not read
   // over the rows or across the dots
   xN = xL - 1 - nameOff
   yN = nrow * bStep * 0.016
   IF showNames = 1 AND upOk = 1 THEN
      DRAWTEXT("sell wall #pxU#", xN, upP + yN, SansSerif, standard, 12) COLOURED(naR, naG, naB, 255)
   ENDIF
   IF showNames = 1 AND dnOk = 1 THEN
      DRAWTEXT("buy wall #pxD#", xN, dnP - yN, SansSerif, standard, 12) COLOURED(nbR, nbG, nbB, 255)
   ENDIF
   IF showPrice = 1 AND posIn = 1 THEN
      DRAWTEXT("#pxC#", xR + 6, close, SansSerif, standard, 10) COLOURED(42, 46, 57, 255)
   ENDIF

   // ===================== PANEL =====================
   IF showPanel = 1 THEN
      // Distances in ATRs, one decimal
      dUpT = 0
      dDnT = 0
      IF upOk = 1 THEN
         dUpT = round((upP - close) / aj * 10) / 10
      ENDIF
      IF dnOk = 1 THEN
         dDnT = round((close - dnP) / aj * 10) / 10
      ENDIF
      nUpD = 0
      nDnD = 0
      IF nUpOk = 1 THEN
         nUpD = (nUpP - close) / aj
      ENDIF
      IF nDnOk = 1 THEN
         nDnD = (close - nDnP) / aj
      ENDIF
      nUpT = round(nUpD * 10) / 10
      nDnT = round(nDnD * 10) / 10
      // Balance: share of the resting liquidity below price
      total = sumUp + sumDn
      IF total > 0 THEN
         shDn = sumDn / total * 100
      ELSE
         shDn = 50
      ENDIF
      shDnT = round(shDn)
      shUpT = round(100 - shDn)
      // The record
      nRecP = $eng[2]
      heldP = 0
      IF nRecP > 0 THEN
         FOR i = 0 TO nRecP - 1 DO
            heldP = heldP + $rec[i]
         NEXT
      ENDIF
      // Which text each row reads
      IF upOk = 1 THEN
         IF upT >= 0.999 THEN
            v1 = 2
         ELSE
            v1 = 1
         ENDIF
      ELSE
         v1 = 0
      ENDIF
      IF dnOk = 1 THEN
         IF dnT >= 0.999 THEN
            v2 = 2
         ELSE
            v2 = 1
         ENDIF
      ELSE
         v2 = 0
      ENDIF
      IF total = 0 THEN
         v3 = 0
      ELSE
         v3 = 1
      ENDIF
      IF nRecP = 0 THEN
         v4 = 0
      ELSIF nRecP = 1 THEN
         v4 = 1
      ELSE
         v4 = 2
      ENDIF
      nearUp = 0
      IF nUpOk = 1 THEN
         IF nDnOk = 0 OR nUpD <= nDnD THEN
            nearUp = 1
         ENDIF
      ENDIF
      nearWall = 0
      IF nearUp = 1 THEN
         IF upOk = 1 AND abs(nUpP - upP) < bStep THEN
            nearWall = 1
         ENDIF
      ELSE
         IF dnOk = 1 AND nDnOk = 1 AND abs(nDnP - dnP) < bStep THEN
            nearWall = 1
         ENDIF
      ENDIF
      thick = 0
      IF shDn >= 58 THEN
         thick = 1
      ELSIF shDn <= 42 THEN
         thick = 2
      ENDIF
      IF $eng[1] = 1 THEN
         v5 = 1
      ELSIF $eng[1] = -1 THEN
         v5 = 2
      ELSIF total = 0 THEN
         v5 = 3
      ELSIF nUpOk = 0 AND nDnOk = 0 THEN
         v5 = 4
      ELSIF nearUp = 1 THEN
         v5 = 6 - nearWall
      ELSE
         v5 = 8 - nearWall
      ENDIF
      // Colours of each row
      IF v1 = 0 THEN
         c1R = inkR
         c1G = inkG
         c1B = inkB
      ELSE
         c1R = askR
         c1G = askG
         c1B = askB
      ENDIF
      IF v2 = 0 THEN
         c2R = inkR
         c2G = inkG
         c2B = inkB
      ELSE
         c2R = bidR
         c2G = bidG
         c2B = bidB
      ENDIF
      IF shDn >= 58 THEN
         c3R = bidR
         c3G = bidG
         c3B = bidB
      ELSIF shDn <= 42 THEN
         c3R = askR
         c3G = askG
         c3B = askB
      ELSE
         c3R = inkR
         c3G = inkG
         c3B = inkB
      ENDIF
      IF nearUp = 1 THEN
         c5R = askR
         c5G = askG
         c5B = askB
      ELSE
         c5R = bidR
         c5G = bidG
         c5B = bidB
      ENDIF
      // Text size and geometry: a monospaced font, so every character is chW pixels wide
      IF panelSize = 1 THEN
         pz = 10
      ELSIF panelSize = 3 THEN
         pz = 15
      ELSE
         pz = 12
      ENDIF
      chW = pz * 0.62
      rowH = pz + 8
      padX = 8
      padY = 4
      // Decimals the chart shows for a price
      IF ticksize >= 1 THEN
         pDec = 0
      ELSIF ticksize >= 0.01 THEN
         pDec = 3
      ELSE
         tkq = ticksize
         pDec = 1
         WHILE tkq < 0.9999999 AND pDec < 11 DO
            tkq = tkq * 10
            pDec = pDec + 1
         WEND
      ENDIF
      // How many characters each number takes on screen (digits, thousands separators, decimals and
      // the space ProRealTime prints after an interpolated number)
      $nv[0] = pxC
      $nv[1] = pxU
      $nv[2] = pxD
      $nv[3] = dUpT
      $nv[4] = dDnT
      $nv[5] = nUpT
      $nv[6] = nDnT
      $nv[7] = shDnT
      $nv[8] = shUpT
      $nv[9] = heldP
      $nv[10] = nRecP
      FOR q = 0 TO 10 DO
         vq = abs($nv[q])
         dq = 1
         WHILE vq >= 10 DO
            vq = vq / 10
            dq = dq + 1
         WEND
         lq = dq + floor((dq - 1) / 3) + 1
         IF $nv[q] < 0 THEN
            lq = lq + 1
         ENDIF
         IF q <= 2 THEN
            lq = lq + pDec
         ELSIF q <= 6 THEN
            lq = lq + 2
         ENDIF
         $nl[q] = lq
      NEXT
      // Length of the text each row reads
      len0 = 0 + $nl[0]
      IF v1 = 0 THEN
         len1 = 21
      ELSIF v1 = 1 THEN
         len1 = 11 + $nl[1] + $nl[3]
      ELSIF v1 = 2 THEN
         len1 = 43 + $nl[1] + $nl[3]
      ENDIF
      IF v2 = 0 THEN
         len2 = 21
      ELSIF v2 = 1 THEN
         len2 = 11 + $nl[2] + $nl[4]
      ELSIF v2 = 2 THEN
         len2 = 43 + $nl[2] + $nl[4]
      ENDIF
      IF v3 = 0 THEN
         len3 = 18
      ELSIF v3 = 1 THEN
         len3 = 52 + $nl[7] + $nl[8]
      ENDIF
      IF v4 = 0 THEN
         len4 = 18
      ELSIF v4 = 1 THEN
         len4 = 27 + $nl[9] + $nl[10]
      ELSIF v4 = 2 THEN
         len4 = 28 + $nl[9] + $nl[10]
      ENDIF
      IF v5 = 1 THEN
         len5 = 63
      ELSIF v5 = 2 THEN
         len5 = 62
      ELSIF v5 = 3 THEN
         len5 = 25
      ELSIF v5 = 4 THEN
         len5 = 38
      ELSIF v5 = 5 AND thick = 0 THEN
         len5 = 49 + $nl[5]
      ELSIF v5 = 5 AND thick = 1 THEN
         len5 = 76 + $nl[5]
      ELSIF v5 = 5 AND thick = 2 THEN
         len5 = 76 + $nl[5]
      ELSIF v5 = 6 AND thick = 0 THEN
         len5 = 72 + $nl[5] + $nl[3]
      ELSIF v5 = 6 AND thick = 1 THEN
         len5 = 99 + $nl[5] + $nl[3]
      ELSIF v5 = 6 AND thick = 2 THEN
         len5 = 99 + $nl[5] + $nl[3]
      ELSIF v5 = 7 AND thick = 0 THEN
         len5 = 48 + $nl[6]
      ELSIF v5 = 7 AND thick = 1 THEN
         len5 = 75 + $nl[6]
      ELSIF v5 = 7 AND thick = 2 THEN
         len5 = 75 + $nl[6]
      ELSIF v5 = 8 AND thick = 0 THEN
         len5 = 71 + $nl[6] + $nl[4]
      ELSIF v5 = 8 AND thick = 1 THEN
         len5 = 98 + $nl[6] + $nl[4]
      ELSIF v5 = 8 AND thick = 2 THEN
         len5 = 98 + $nl[6] + $nl[4]
      ENDIF
      maxL = max(max(max(len0, len1), max(len2, len3)), max(len4, len5))
      pW = 16 * chW + maxL * chW + 2 * chW + 4 * padX
      pH = 6 * rowH + 2 * padY
      // The panel sits in its corner, clear of the price scale on the right and, on the left, of the
      // chart's legend bar (top) and of the platform's mark and news icons (bottom)
      IF panelPos = 1 THEN
         pL = 10
         pT = 0 - 40
      ELSIF panelPos = 3 THEN
         pL = 10
         pT = 40 + pH
      ELSIF panelPos = 4 THEN
         pL = 0 - 85 - pW
         pT = 12 + pH
      ELSE
         pL = 0 - 85 - pW
         pT = 0 - 12
      ENDIF
      // Names aligned left, values aligned right
      yR0 = pT - padY - rowH * 0.5
      xV0 = pL + pW - padX - len0 * chW / 2
      yR1 = pT - padY - rowH * 1.5
      xV1 = pL + pW - padX - len1 * chW / 2
      yR2 = pT - padY - rowH * 2.5
      xV2 = pL + pW - padX - len2 * chW / 2
      yR3 = pT - padY - rowH * 3.5
      xV3 = pL + pW - padX - len3 * chW / 2
      yR4 = pT - padY - rowH * 4.5
      xV4 = pL + pW - padX - len4 * chW / 2
      yR5 = pT - padY - rowH * 5.5
      xV5 = pL + pW - padX - len5 * chW / 2
      // The panel, drawn in the chosen corner
      IF panelPos = 1 THEN
         DRAWRECTANGLE(pL, pT, pL + pW, pT - pH) ANCHOR(TOPLEFT, XSHIFT, YSHIFT) COLOURED(38, 43, 56, 255) FILLCOLOR(38, 43, 56, 255)
         DRAWTEXT("LIQUIDITY MASTER", pL + padX + 8 * chW, yR0, monospaced, bold, pz) ANCHOR(TOPLEFT, XSHIFT, YSHIFT) COLOURED(209, 212, 220, 255)
         DRAWTEXT("#pxC#", xV0, yR0, monospaced, bold, pz) ANCHOR(TOPLEFT, XSHIFT, YSHIFT) COLOURED(209, 212, 220, 153)
         DRAWTEXT("Sell wall", pL + padX + 4.5 * chW, yR1, monospaced, bold, pz) ANCHOR(TOPLEFT, XSHIFT, YSHIFT) COLOURED(209, 212, 220, 153)
         IF v1 = 0 THEN
            DRAWTEXT("No wall on the ladder", xV1, yR1, monospaced, bold, pz) ANCHOR(TOPLEFT, XSHIFT, YSHIFT) COLOURED(c1R, c1G, c1B, 255)
         ELSIF v1 = 1 THEN
            DRAWTEXT("#pxU#· #dUpT#ATR above", xV1, yR1, monospaced, bold, pz) ANCHOR(TOPLEFT, XSHIFT, YSHIFT) COLOURED(c1R, c1G, c1B, 255)
         ELSIF v1 = 2 THEN
            DRAWTEXT("#pxU#· #dUpT#ATR above, the biggest pool on the ladder", xV1, yR1, monospaced, bold, pz) ANCHOR(TOPLEFT, XSHIFT, YSHIFT) COLOURED(c1R, c1G, c1B, 255)
         ENDIF
         DRAWTEXT("Buy wall", pL + padX + 4 * chW, yR2, monospaced, bold, pz) ANCHOR(TOPLEFT, XSHIFT, YSHIFT) COLOURED(209, 212, 220, 153)
         IF v2 = 0 THEN
            DRAWTEXT("No wall on the ladder", xV2, yR2, monospaced, bold, pz) ANCHOR(TOPLEFT, XSHIFT, YSHIFT) COLOURED(c2R, c2G, c2B, 255)
         ELSIF v2 = 1 THEN
            DRAWTEXT("#pxD#· #dDnT#ATR below", xV2, yR2, monospaced, bold, pz) ANCHOR(TOPLEFT, XSHIFT, YSHIFT) COLOURED(c2R, c2G, c2B, 255)
         ELSIF v2 = 2 THEN
            DRAWTEXT("#pxD#· #dDnT#ATR below, the biggest pool on the ladder", xV2, yR2, monospaced, bold, pz) ANCHOR(TOPLEFT, XSHIFT, YSHIFT) COLOURED(c2R, c2G, c2B, 255)
         ENDIF
         DRAWTEXT("Balance", pL + padX + 3.5 * chW, yR3, monospaced, bold, pz) ANCHOR(TOPLEFT, XSHIFT, YSHIFT) COLOURED(209, 212, 220, 153)
         IF v3 = 0 THEN
            DRAWTEXT("Nothing mapped yet", xV3, yR3, monospaced, bold, pz) ANCHOR(TOPLEFT, XSHIFT, YSHIFT) COLOURED(c3R, c3G, c3B, 255)
         ELSIF v3 = 1 THEN
            DRAWTEXT("#shDnT#% of the resting liquidity sits below price, #shUpT#% above", xV3, yR3, monospaced, bold, pz) ANCHOR(TOPLEFT, XSHIFT, YSHIFT) COLOURED(c3R, c3G, c3B, 255)
         ENDIF
         DRAWTEXT("Walls here", pL + padX + 5 * chW, yR4, monospaced, bold, pz) ANCHOR(TOPLEFT, XSHIFT, YSHIFT) COLOURED(209, 212, 220, 153)
         IF v4 = 0 THEN
            DRAWTEXT("No wall tested yet", xV4, yR4, monospaced, bold, pz) ANCHOR(TOPLEFT, XSHIFT, YSHIFT) COLOURED(209, 212, 220, 255)
         ELSIF v4 = 1 THEN
            DRAWTEXT("Walls held #heldP#of the last #nRecP#test", xV4, yR4, monospaced, bold, pz) ANCHOR(TOPLEFT, XSHIFT, YSHIFT) COLOURED(209, 212, 220, 255)
         ELSIF v4 = 2 THEN
            DRAWTEXT("Walls held #heldP#of the last #nRecP#tests", xV4, yR4, monospaced, bold, pz) ANCHOR(TOPLEFT, XSHIFT, YSHIFT) COLOURED(209, 212, 220, 255)
         ENDIF
         DRAWTEXT("Read", pL + padX + 2 * chW, yR5, monospaced, bold, pz) ANCHOR(TOPLEFT, XSHIFT, YSHIFT) COLOURED(209, 212, 220, 153)
         IF v5 = 1 THEN
            DRAWTEXT("Testing the sell wall now, a close 0.5 ATR through it breaks it", xV5, yR5, monospaced, bold, pz) ANCHOR(TOPLEFT, XSHIFT, YSHIFT) COLOURED(255, 255, 255, 255)
         ELSIF v5 = 2 THEN
            DRAWTEXT("Testing the buy wall now, a close 0.5 ATR through it breaks it", xV5, yR5, monospaced, bold, pz) ANCHOR(TOPLEFT, XSHIFT, YSHIFT) COLOURED(255, 255, 255, 255)
         ELSIF v5 = 3 THEN
            DRAWTEXT("Waiting for swings to map", xV5, yR5, monospaced, bold, pz) ANCHOR(TOPLEFT, XSHIFT, YSHIFT) COLOURED(c5R, c5G, c5B, 255)
         ELSIF v5 = 4 THEN
            DRAWTEXT("Thin on both sides, nothing in the way", xV5, yR5, monospaced, bold, pz) ANCHOR(TOPLEFT, XSHIFT, YSHIFT) COLOURED(c5R, c5G, c5B, 255)
         ELSIF v5 = 5 AND thick = 0 THEN
            DRAWTEXT("Sell wall #nUpT#ATR above is the first thing in the way", xV5, yR5, monospaced, bold, pz) ANCHOR(TOPLEFT, XSHIFT, YSHIFT) COLOURED(c5R, c5G, c5B, 255)
         ELSIF v5 = 5 AND thick = 1 THEN
            DRAWTEXT("Sell wall #nUpT#ATR above is the first thing in the way, the thicker side is below", xV5, yR5, monospaced, bold, pz) ANCHOR(TOPLEFT, XSHIFT, YSHIFT) COLOURED(c5R, c5G, c5B, 255)
         ELSIF v5 = 5 AND thick = 2 THEN
            DRAWTEXT("Sell wall #nUpT#ATR above is the first thing in the way, the thicker side is above", xV5, yR5, monospaced, bold, pz) ANCHOR(TOPLEFT, XSHIFT, YSHIFT) COLOURED(c5R, c5G, c5B, 255)
         ELSIF v5 = 6 AND thick = 0 THEN
            DRAWTEXT("Offers #nUpT#ATR above are the first thing in the way, the sell wall is #dUpT#ATR up", xV5, yR5, monospaced, bold, pz) ANCHOR(TOPLEFT, XSHIFT, YSHIFT) COLOURED(c5R, c5G, c5B, 255)
         ELSIF v5 = 6 AND thick = 1 THEN
            DRAWTEXT("Offers #nUpT#ATR above are the first thing in the way, the sell wall is #dUpT#ATR up, the thicker side is below", xV5, yR5, monospaced, bold, pz) ANCHOR(TOPLEFT, XSHIFT, YSHIFT) COLOURED(c5R, c5G, c5B, 255)
         ELSIF v5 = 6 AND thick = 2 THEN
            DRAWTEXT("Offers #nUpT#ATR above are the first thing in the way, the sell wall is #dUpT#ATR up, the thicker side is above", xV5, yR5, monospaced, bold, pz) ANCHOR(TOPLEFT, XSHIFT, YSHIFT) COLOURED(c5R, c5G, c5B, 255)
         ELSIF v5 = 7 AND thick = 0 THEN
            DRAWTEXT("Buy wall #nDnT#ATR below is the first thing in the way", xV5, yR5, monospaced, bold, pz) ANCHOR(TOPLEFT, XSHIFT, YSHIFT) COLOURED(c5R, c5G, c5B, 255)
         ELSIF v5 = 7 AND thick = 1 THEN
            DRAWTEXT("Buy wall #nDnT#ATR below is the first thing in the way, the thicker side is below", xV5, yR5, monospaced, bold, pz) ANCHOR(TOPLEFT, XSHIFT, YSHIFT) COLOURED(c5R, c5G, c5B, 255)
         ELSIF v5 = 7 AND thick = 2 THEN
            DRAWTEXT("Buy wall #nDnT#ATR below is the first thing in the way, the thicker side is above", xV5, yR5, monospaced, bold, pz) ANCHOR(TOPLEFT, XSHIFT, YSHIFT) COLOURED(c5R, c5G, c5B, 255)
         ELSIF v5 = 8 AND thick = 0 THEN
            DRAWTEXT("Bids #nDnT#ATR below are the first thing in the way, the buy wall is #dDnT#ATR down", xV5, yR5, monospaced, bold, pz) ANCHOR(TOPLEFT, XSHIFT, YSHIFT) COLOURED(c5R, c5G, c5B, 255)
         ELSIF v5 = 8 AND thick = 1 THEN
            DRAWTEXT("Bids #nDnT#ATR below are the first thing in the way, the buy wall is #dDnT#ATR down, the thicker side is below", xV5, yR5, monospaced, bold, pz) ANCHOR(TOPLEFT, XSHIFT, YSHIFT) COLOURED(c5R, c5G, c5B, 255)
         ELSIF v5 = 8 AND thick = 2 THEN
            DRAWTEXT("Bids #nDnT#ATR below are the first thing in the way, the buy wall is #dDnT#ATR down, the thicker side is above", xV5, yR5, monospaced, bold, pz) ANCHOR(TOPLEFT, XSHIFT, YSHIFT) COLOURED(c5R, c5G, c5B, 255)
         ENDIF
      ELSIF panelPos = 3 THEN
         DRAWRECTANGLE(pL, pT, pL + pW, pT - pH) ANCHOR(BOTTOMLEFT, XSHIFT, YSHIFT) COLOURED(38, 43, 56, 255) FILLCOLOR(38, 43, 56, 255)
         DRAWTEXT("LIQUIDITY MASTER", pL + padX + 8 * chW, yR0, monospaced, bold, pz) ANCHOR(BOTTOMLEFT, XSHIFT, YSHIFT) COLOURED(209, 212, 220, 255)
         DRAWTEXT("#pxC#", xV0, yR0, monospaced, bold, pz) ANCHOR(BOTTOMLEFT, XSHIFT, YSHIFT) COLOURED(209, 212, 220, 153)
         DRAWTEXT("Sell wall", pL + padX + 4.5 * chW, yR1, monospaced, bold, pz) ANCHOR(BOTTOMLEFT, XSHIFT, YSHIFT) COLOURED(209, 212, 220, 153)
         IF v1 = 0 THEN
            DRAWTEXT("No wall on the ladder", xV1, yR1, monospaced, bold, pz) ANCHOR(BOTTOMLEFT, XSHIFT, YSHIFT) COLOURED(c1R, c1G, c1B, 255)
         ELSIF v1 = 1 THEN
            DRAWTEXT("#pxU#· #dUpT#ATR above", xV1, yR1, monospaced, bold, pz) ANCHOR(BOTTOMLEFT, XSHIFT, YSHIFT) COLOURED(c1R, c1G, c1B, 255)
         ELSIF v1 = 2 THEN
            DRAWTEXT("#pxU#· #dUpT#ATR above, the biggest pool on the ladder", xV1, yR1, monospaced, bold, pz) ANCHOR(BOTTOMLEFT, XSHIFT, YSHIFT) COLOURED(c1R, c1G, c1B, 255)
         ENDIF
         DRAWTEXT("Buy wall", pL + padX + 4 * chW, yR2, monospaced, bold, pz) ANCHOR(BOTTOMLEFT, XSHIFT, YSHIFT) COLOURED(209, 212, 220, 153)
         IF v2 = 0 THEN
            DRAWTEXT("No wall on the ladder", xV2, yR2, monospaced, bold, pz) ANCHOR(BOTTOMLEFT, XSHIFT, YSHIFT) COLOURED(c2R, c2G, c2B, 255)
         ELSIF v2 = 1 THEN
            DRAWTEXT("#pxD#· #dDnT#ATR below", xV2, yR2, monospaced, bold, pz) ANCHOR(BOTTOMLEFT, XSHIFT, YSHIFT) COLOURED(c2R, c2G, c2B, 255)
         ELSIF v2 = 2 THEN
            DRAWTEXT("#pxD#· #dDnT#ATR below, the biggest pool on the ladder", xV2, yR2, monospaced, bold, pz) ANCHOR(BOTTOMLEFT, XSHIFT, YSHIFT) COLOURED(c2R, c2G, c2B, 255)
         ENDIF
         DRAWTEXT("Balance", pL + padX + 3.5 * chW, yR3, monospaced, bold, pz) ANCHOR(BOTTOMLEFT, XSHIFT, YSHIFT) COLOURED(209, 212, 220, 153)
         IF v3 = 0 THEN
            DRAWTEXT("Nothing mapped yet", xV3, yR3, monospaced, bold, pz) ANCHOR(BOTTOMLEFT, XSHIFT, YSHIFT) COLOURED(c3R, c3G, c3B, 255)
         ELSIF v3 = 1 THEN
            DRAWTEXT("#shDnT#% of the resting liquidity sits below price, #shUpT#% above", xV3, yR3, monospaced, bold, pz) ANCHOR(BOTTOMLEFT, XSHIFT, YSHIFT) COLOURED(c3R, c3G, c3B, 255)
         ENDIF
         DRAWTEXT("Walls here", pL + padX + 5 * chW, yR4, monospaced, bold, pz) ANCHOR(BOTTOMLEFT, XSHIFT, YSHIFT) COLOURED(209, 212, 220, 153)
         IF v4 = 0 THEN
            DRAWTEXT("No wall tested yet", xV4, yR4, monospaced, bold, pz) ANCHOR(BOTTOMLEFT, XSHIFT, YSHIFT) COLOURED(209, 212, 220, 255)
         ELSIF v4 = 1 THEN
            DRAWTEXT("Walls held #heldP#of the last #nRecP#test", xV4, yR4, monospaced, bold, pz) ANCHOR(BOTTOMLEFT, XSHIFT, YSHIFT) COLOURED(209, 212, 220, 255)
         ELSIF v4 = 2 THEN
            DRAWTEXT("Walls held #heldP#of the last #nRecP#tests", xV4, yR4, monospaced, bold, pz) ANCHOR(BOTTOMLEFT, XSHIFT, YSHIFT) COLOURED(209, 212, 220, 255)
         ENDIF
         DRAWTEXT("Read", pL + padX + 2 * chW, yR5, monospaced, bold, pz) ANCHOR(BOTTOMLEFT, XSHIFT, YSHIFT) COLOURED(209, 212, 220, 153)
         IF v5 = 1 THEN
            DRAWTEXT("Testing the sell wall now, a close 0.5 ATR through it breaks it", xV5, yR5, monospaced, bold, pz) ANCHOR(BOTTOMLEFT, XSHIFT, YSHIFT) COLOURED(255, 255, 255, 255)
         ELSIF v5 = 2 THEN
            DRAWTEXT("Testing the buy wall now, a close 0.5 ATR through it breaks it", xV5, yR5, monospaced, bold, pz) ANCHOR(BOTTOMLEFT, XSHIFT, YSHIFT) COLOURED(255, 255, 255, 255)
         ELSIF v5 = 3 THEN
            DRAWTEXT("Waiting for swings to map", xV5, yR5, monospaced, bold, pz) ANCHOR(BOTTOMLEFT, XSHIFT, YSHIFT) COLOURED(c5R, c5G, c5B, 255)
         ELSIF v5 = 4 THEN
            DRAWTEXT("Thin on both sides, nothing in the way", xV5, yR5, monospaced, bold, pz) ANCHOR(BOTTOMLEFT, XSHIFT, YSHIFT) COLOURED(c5R, c5G, c5B, 255)
         ELSIF v5 = 5 AND thick = 0 THEN
            DRAWTEXT("Sell wall #nUpT#ATR above is the first thing in the way", xV5, yR5, monospaced, bold, pz) ANCHOR(BOTTOMLEFT, XSHIFT, YSHIFT) COLOURED(c5R, c5G, c5B, 255)
         ELSIF v5 = 5 AND thick = 1 THEN
            DRAWTEXT("Sell wall #nUpT#ATR above is the first thing in the way, the thicker side is below", xV5, yR5, monospaced, bold, pz) ANCHOR(BOTTOMLEFT, XSHIFT, YSHIFT) COLOURED(c5R, c5G, c5B, 255)
         ELSIF v5 = 5 AND thick = 2 THEN
            DRAWTEXT("Sell wall #nUpT#ATR above is the first thing in the way, the thicker side is above", xV5, yR5, monospaced, bold, pz) ANCHOR(BOTTOMLEFT, XSHIFT, YSHIFT) COLOURED(c5R, c5G, c5B, 255)
         ELSIF v5 = 6 AND thick = 0 THEN
            DRAWTEXT("Offers #nUpT#ATR above are the first thing in the way, the sell wall is #dUpT#ATR up", xV5, yR5, monospaced, bold, pz) ANCHOR(BOTTOMLEFT, XSHIFT, YSHIFT) COLOURED(c5R, c5G, c5B, 255)
         ELSIF v5 = 6 AND thick = 1 THEN
            DRAWTEXT("Offers #nUpT#ATR above are the first thing in the way, the sell wall is #dUpT#ATR up, the thicker side is below", xV5, yR5, monospaced, bold, pz) ANCHOR(BOTTOMLEFT, XSHIFT, YSHIFT) COLOURED(c5R, c5G, c5B, 255)
         ELSIF v5 = 6 AND thick = 2 THEN
            DRAWTEXT("Offers #nUpT#ATR above are the first thing in the way, the sell wall is #dUpT#ATR up, the thicker side is above", xV5, yR5, monospaced, bold, pz) ANCHOR(BOTTOMLEFT, XSHIFT, YSHIFT) COLOURED(c5R, c5G, c5B, 255)
         ELSIF v5 = 7 AND thick = 0 THEN
            DRAWTEXT("Buy wall #nDnT#ATR below is the first thing in the way", xV5, yR5, monospaced, bold, pz) ANCHOR(BOTTOMLEFT, XSHIFT, YSHIFT) COLOURED(c5R, c5G, c5B, 255)
         ELSIF v5 = 7 AND thick = 1 THEN
            DRAWTEXT("Buy wall #nDnT#ATR below is the first thing in the way, the thicker side is below", xV5, yR5, monospaced, bold, pz) ANCHOR(BOTTOMLEFT, XSHIFT, YSHIFT) COLOURED(c5R, c5G, c5B, 255)
         ELSIF v5 = 7 AND thick = 2 THEN
            DRAWTEXT("Buy wall #nDnT#ATR below is the first thing in the way, the thicker side is above", xV5, yR5, monospaced, bold, pz) ANCHOR(BOTTOMLEFT, XSHIFT, YSHIFT) COLOURED(c5R, c5G, c5B, 255)
         ELSIF v5 = 8 AND thick = 0 THEN
            DRAWTEXT("Bids #nDnT#ATR below are the first thing in the way, the buy wall is #dDnT#ATR down", xV5, yR5, monospaced, bold, pz) ANCHOR(BOTTOMLEFT, XSHIFT, YSHIFT) COLOURED(c5R, c5G, c5B, 255)
         ELSIF v5 = 8 AND thick = 1 THEN
            DRAWTEXT("Bids #nDnT#ATR below are the first thing in the way, the buy wall is #dDnT#ATR down, the thicker side is below", xV5, yR5, monospaced, bold, pz) ANCHOR(BOTTOMLEFT, XSHIFT, YSHIFT) COLOURED(c5R, c5G, c5B, 255)
         ELSIF v5 = 8 AND thick = 2 THEN
            DRAWTEXT("Bids #nDnT#ATR below are the first thing in the way, the buy wall is #dDnT#ATR down, the thicker side is above", xV5, yR5, monospaced, bold, pz) ANCHOR(BOTTOMLEFT, XSHIFT, YSHIFT) COLOURED(c5R, c5G, c5B, 255)
         ENDIF
      ELSIF panelPos = 4 THEN
         DRAWRECTANGLE(pL, pT, pL + pW, pT - pH) ANCHOR(BOTTOMRIGHT, XSHIFT, YSHIFT) COLOURED(38, 43, 56, 255) FILLCOLOR(38, 43, 56, 255)
         DRAWTEXT("LIQUIDITY MASTER", pL + padX + 8 * chW, yR0, monospaced, bold, pz) ANCHOR(BOTTOMRIGHT, XSHIFT, YSHIFT) COLOURED(209, 212, 220, 255)
         DRAWTEXT("#pxC#", xV0, yR0, monospaced, bold, pz) ANCHOR(BOTTOMRIGHT, XSHIFT, YSHIFT) COLOURED(209, 212, 220, 153)
         DRAWTEXT("Sell wall", pL + padX + 4.5 * chW, yR1, monospaced, bold, pz) ANCHOR(BOTTOMRIGHT, XSHIFT, YSHIFT) COLOURED(209, 212, 220, 153)
         IF v1 = 0 THEN
            DRAWTEXT("No wall on the ladder", xV1, yR1, monospaced, bold, pz) ANCHOR(BOTTOMRIGHT, XSHIFT, YSHIFT) COLOURED(c1R, c1G, c1B, 255)
         ELSIF v1 = 1 THEN
            DRAWTEXT("#pxU#· #dUpT#ATR above", xV1, yR1, monospaced, bold, pz) ANCHOR(BOTTOMRIGHT, XSHIFT, YSHIFT) COLOURED(c1R, c1G, c1B, 255)
         ELSIF v1 = 2 THEN
            DRAWTEXT("#pxU#· #dUpT#ATR above, the biggest pool on the ladder", xV1, yR1, monospaced, bold, pz) ANCHOR(BOTTOMRIGHT, XSHIFT, YSHIFT) COLOURED(c1R, c1G, c1B, 255)
         ENDIF
         DRAWTEXT("Buy wall", pL + padX + 4 * chW, yR2, monospaced, bold, pz) ANCHOR(BOTTOMRIGHT, XSHIFT, YSHIFT) COLOURED(209, 212, 220, 153)
         IF v2 = 0 THEN
            DRAWTEXT("No wall on the ladder", xV2, yR2, monospaced, bold, pz) ANCHOR(BOTTOMRIGHT, XSHIFT, YSHIFT) COLOURED(c2R, c2G, c2B, 255)
         ELSIF v2 = 1 THEN
            DRAWTEXT("#pxD#· #dDnT#ATR below", xV2, yR2, monospaced, bold, pz) ANCHOR(BOTTOMRIGHT, XSHIFT, YSHIFT) COLOURED(c2R, c2G, c2B, 255)
         ELSIF v2 = 2 THEN
            DRAWTEXT("#pxD#· #dDnT#ATR below, the biggest pool on the ladder", xV2, yR2, monospaced, bold, pz) ANCHOR(BOTTOMRIGHT, XSHIFT, YSHIFT) COLOURED(c2R, c2G, c2B, 255)
         ENDIF
         DRAWTEXT("Balance", pL + padX + 3.5 * chW, yR3, monospaced, bold, pz) ANCHOR(BOTTOMRIGHT, XSHIFT, YSHIFT) COLOURED(209, 212, 220, 153)
         IF v3 = 0 THEN
            DRAWTEXT("Nothing mapped yet", xV3, yR3, monospaced, bold, pz) ANCHOR(BOTTOMRIGHT, XSHIFT, YSHIFT) COLOURED(c3R, c3G, c3B, 255)
         ELSIF v3 = 1 THEN
            DRAWTEXT("#shDnT#% of the resting liquidity sits below price, #shUpT#% above", xV3, yR3, monospaced, bold, pz) ANCHOR(BOTTOMRIGHT, XSHIFT, YSHIFT) COLOURED(c3R, c3G, c3B, 255)
         ENDIF
         DRAWTEXT("Walls here", pL + padX + 5 * chW, yR4, monospaced, bold, pz) ANCHOR(BOTTOMRIGHT, XSHIFT, YSHIFT) COLOURED(209, 212, 220, 153)
         IF v4 = 0 THEN
            DRAWTEXT("No wall tested yet", xV4, yR4, monospaced, bold, pz) ANCHOR(BOTTOMRIGHT, XSHIFT, YSHIFT) COLOURED(209, 212, 220, 255)
         ELSIF v4 = 1 THEN
            DRAWTEXT("Walls held #heldP#of the last #nRecP#test", xV4, yR4, monospaced, bold, pz) ANCHOR(BOTTOMRIGHT, XSHIFT, YSHIFT) COLOURED(209, 212, 220, 255)
         ELSIF v4 = 2 THEN
            DRAWTEXT("Walls held #heldP#of the last #nRecP#tests", xV4, yR4, monospaced, bold, pz) ANCHOR(BOTTOMRIGHT, XSHIFT, YSHIFT) COLOURED(209, 212, 220, 255)
         ENDIF
         DRAWTEXT("Read", pL + padX + 2 * chW, yR5, monospaced, bold, pz) ANCHOR(BOTTOMRIGHT, XSHIFT, YSHIFT) COLOURED(209, 212, 220, 153)
         IF v5 = 1 THEN
            DRAWTEXT("Testing the sell wall now, a close 0.5 ATR through it breaks it", xV5, yR5, monospaced, bold, pz) ANCHOR(BOTTOMRIGHT, XSHIFT, YSHIFT) COLOURED(255, 255, 255, 255)
         ELSIF v5 = 2 THEN
            DRAWTEXT("Testing the buy wall now, a close 0.5 ATR through it breaks it", xV5, yR5, monospaced, bold, pz) ANCHOR(BOTTOMRIGHT, XSHIFT, YSHIFT) COLOURED(255, 255, 255, 255)
         ELSIF v5 = 3 THEN
            DRAWTEXT("Waiting for swings to map", xV5, yR5, monospaced, bold, pz) ANCHOR(BOTTOMRIGHT, XSHIFT, YSHIFT) COLOURED(c5R, c5G, c5B, 255)
         ELSIF v5 = 4 THEN
            DRAWTEXT("Thin on both sides, nothing in the way", xV5, yR5, monospaced, bold, pz) ANCHOR(BOTTOMRIGHT, XSHIFT, YSHIFT) COLOURED(c5R, c5G, c5B, 255)
         ELSIF v5 = 5 AND thick = 0 THEN
            DRAWTEXT("Sell wall #nUpT#ATR above is the first thing in the way", xV5, yR5, monospaced, bold, pz) ANCHOR(BOTTOMRIGHT, XSHIFT, YSHIFT) COLOURED(c5R, c5G, c5B, 255)
         ELSIF v5 = 5 AND thick = 1 THEN
            DRAWTEXT("Sell wall #nUpT#ATR above is the first thing in the way, the thicker side is below", xV5, yR5, monospaced, bold, pz) ANCHOR(BOTTOMRIGHT, XSHIFT, YSHIFT) COLOURED(c5R, c5G, c5B, 255)
         ELSIF v5 = 5 AND thick = 2 THEN
            DRAWTEXT("Sell wall #nUpT#ATR above is the first thing in the way, the thicker side is above", xV5, yR5, monospaced, bold, pz) ANCHOR(BOTTOMRIGHT, XSHIFT, YSHIFT) COLOURED(c5R, c5G, c5B, 255)
         ELSIF v5 = 6 AND thick = 0 THEN
            DRAWTEXT("Offers #nUpT#ATR above are the first thing in the way, the sell wall is #dUpT#ATR up", xV5, yR5, monospaced, bold, pz) ANCHOR(BOTTOMRIGHT, XSHIFT, YSHIFT) COLOURED(c5R, c5G, c5B, 255)
         ELSIF v5 = 6 AND thick = 1 THEN
            DRAWTEXT("Offers #nUpT#ATR above are the first thing in the way, the sell wall is #dUpT#ATR up, the thicker side is below", xV5, yR5, monospaced, bold, pz) ANCHOR(BOTTOMRIGHT, XSHIFT, YSHIFT) COLOURED(c5R, c5G, c5B, 255)
         ELSIF v5 = 6 AND thick = 2 THEN
            DRAWTEXT("Offers #nUpT#ATR above are the first thing in the way, the sell wall is #dUpT#ATR up, the thicker side is above", xV5, yR5, monospaced, bold, pz) ANCHOR(BOTTOMRIGHT, XSHIFT, YSHIFT) COLOURED(c5R, c5G, c5B, 255)
         ELSIF v5 = 7 AND thick = 0 THEN
            DRAWTEXT("Buy wall #nDnT#ATR below is the first thing in the way", xV5, yR5, monospaced, bold, pz) ANCHOR(BOTTOMRIGHT, XSHIFT, YSHIFT) COLOURED(c5R, c5G, c5B, 255)
         ELSIF v5 = 7 AND thick = 1 THEN
            DRAWTEXT("Buy wall #nDnT#ATR below is the first thing in the way, the thicker side is below", xV5, yR5, monospaced, bold, pz) ANCHOR(BOTTOMRIGHT, XSHIFT, YSHIFT) COLOURED(c5R, c5G, c5B, 255)
         ELSIF v5 = 7 AND thick = 2 THEN
            DRAWTEXT("Buy wall #nDnT#ATR below is the first thing in the way, the thicker side is above", xV5, yR5, monospaced, bold, pz) ANCHOR(BOTTOMRIGHT, XSHIFT, YSHIFT) COLOURED(c5R, c5G, c5B, 255)
         ELSIF v5 = 8 AND thick = 0 THEN
            DRAWTEXT("Bids #nDnT#ATR below are the first thing in the way, the buy wall is #dDnT#ATR down", xV5, yR5, monospaced, bold, pz) ANCHOR(BOTTOMRIGHT, XSHIFT, YSHIFT) COLOURED(c5R, c5G, c5B, 255)
         ELSIF v5 = 8 AND thick = 1 THEN
            DRAWTEXT("Bids #nDnT#ATR below are the first thing in the way, the buy wall is #dDnT#ATR down, the thicker side is below", xV5, yR5, monospaced, bold, pz) ANCHOR(BOTTOMRIGHT, XSHIFT, YSHIFT) COLOURED(c5R, c5G, c5B, 255)
         ELSIF v5 = 8 AND thick = 2 THEN
            DRAWTEXT("Bids #nDnT#ATR below are the first thing in the way, the buy wall is #dDnT#ATR down, the thicker side is above", xV5, yR5, monospaced, bold, pz) ANCHOR(BOTTOMRIGHT, XSHIFT, YSHIFT) COLOURED(c5R, c5G, c5B, 255)
         ENDIF
      ELSE
         DRAWRECTANGLE(pL, pT, pL + pW, pT - pH) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT) COLOURED(38, 43, 56, 255) FILLCOLOR(38, 43, 56, 255)
         DRAWTEXT("LIQUIDITY MASTER", pL + padX + 8 * chW, yR0, monospaced, bold, pz) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT) COLOURED(209, 212, 220, 255)
         DRAWTEXT("#pxC#", xV0, yR0, monospaced, bold, pz) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT) COLOURED(209, 212, 220, 153)
         DRAWTEXT("Sell wall", pL + padX + 4.5 * chW, yR1, monospaced, bold, pz) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT) COLOURED(209, 212, 220, 153)
         IF v1 = 0 THEN
            DRAWTEXT("No wall on the ladder", xV1, yR1, monospaced, bold, pz) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT) COLOURED(c1R, c1G, c1B, 255)
         ELSIF v1 = 1 THEN
            DRAWTEXT("#pxU#· #dUpT#ATR above", xV1, yR1, monospaced, bold, pz) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT) COLOURED(c1R, c1G, c1B, 255)
         ELSIF v1 = 2 THEN
            DRAWTEXT("#pxU#· #dUpT#ATR above, the biggest pool on the ladder", xV1, yR1, monospaced, bold, pz) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT) COLOURED(c1R, c1G, c1B, 255)
         ENDIF
         DRAWTEXT("Buy wall", pL + padX + 4 * chW, yR2, monospaced, bold, pz) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT) COLOURED(209, 212, 220, 153)
         IF v2 = 0 THEN
            DRAWTEXT("No wall on the ladder", xV2, yR2, monospaced, bold, pz) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT) COLOURED(c2R, c2G, c2B, 255)
         ELSIF v2 = 1 THEN
            DRAWTEXT("#pxD#· #dDnT#ATR below", xV2, yR2, monospaced, bold, pz) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT) COLOURED(c2R, c2G, c2B, 255)
         ELSIF v2 = 2 THEN
            DRAWTEXT("#pxD#· #dDnT#ATR below, the biggest pool on the ladder", xV2, yR2, monospaced, bold, pz) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT) COLOURED(c2R, c2G, c2B, 255)
         ENDIF
         DRAWTEXT("Balance", pL + padX + 3.5 * chW, yR3, monospaced, bold, pz) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT) COLOURED(209, 212, 220, 153)
         IF v3 = 0 THEN
            DRAWTEXT("Nothing mapped yet", xV3, yR3, monospaced, bold, pz) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT) COLOURED(c3R, c3G, c3B, 255)
         ELSIF v3 = 1 THEN
            DRAWTEXT("#shDnT#% of the resting liquidity sits below price, #shUpT#% above", xV3, yR3, monospaced, bold, pz) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT) COLOURED(c3R, c3G, c3B, 255)
         ENDIF
         DRAWTEXT("Walls here", pL + padX + 5 * chW, yR4, monospaced, bold, pz) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT) COLOURED(209, 212, 220, 153)
         IF v4 = 0 THEN
            DRAWTEXT("No wall tested yet", xV4, yR4, monospaced, bold, pz) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT) COLOURED(209, 212, 220, 255)
         ELSIF v4 = 1 THEN
            DRAWTEXT("Walls held #heldP#of the last #nRecP#test", xV4, yR4, monospaced, bold, pz) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT) COLOURED(209, 212, 220, 255)
         ELSIF v4 = 2 THEN
            DRAWTEXT("Walls held #heldP#of the last #nRecP#tests", xV4, yR4, monospaced, bold, pz) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT) COLOURED(209, 212, 220, 255)
         ENDIF
         DRAWTEXT("Read", pL + padX + 2 * chW, yR5, monospaced, bold, pz) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT) COLOURED(209, 212, 220, 153)
         IF v5 = 1 THEN
            DRAWTEXT("Testing the sell wall now, a close 0.5 ATR through it breaks it", xV5, yR5, monospaced, bold, pz) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT) COLOURED(255, 255, 255, 255)
         ELSIF v5 = 2 THEN
            DRAWTEXT("Testing the buy wall now, a close 0.5 ATR through it breaks it", xV5, yR5, monospaced, bold, pz) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT) COLOURED(255, 255, 255, 255)
         ELSIF v5 = 3 THEN
            DRAWTEXT("Waiting for swings to map", xV5, yR5, monospaced, bold, pz) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT) COLOURED(c5R, c5G, c5B, 255)
         ELSIF v5 = 4 THEN
            DRAWTEXT("Thin on both sides, nothing in the way", xV5, yR5, monospaced, bold, pz) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT) COLOURED(c5R, c5G, c5B, 255)
         ELSIF v5 = 5 AND thick = 0 THEN
            DRAWTEXT("Sell wall #nUpT#ATR above is the first thing in the way", xV5, yR5, monospaced, bold, pz) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT) COLOURED(c5R, c5G, c5B, 255)
         ELSIF v5 = 5 AND thick = 1 THEN
            DRAWTEXT("Sell wall #nUpT#ATR above is the first thing in the way, the thicker side is below", xV5, yR5, monospaced, bold, pz) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT) COLOURED(c5R, c5G, c5B, 255)
         ELSIF v5 = 5 AND thick = 2 THEN
            DRAWTEXT("Sell wall #nUpT#ATR above is the first thing in the way, the thicker side is above", xV5, yR5, monospaced, bold, pz) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT) COLOURED(c5R, c5G, c5B, 255)
         ELSIF v5 = 6 AND thick = 0 THEN
            DRAWTEXT("Offers #nUpT#ATR above are the first thing in the way, the sell wall is #dUpT#ATR up", xV5, yR5, monospaced, bold, pz) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT) COLOURED(c5R, c5G, c5B, 255)
         ELSIF v5 = 6 AND thick = 1 THEN
            DRAWTEXT("Offers #nUpT#ATR above are the first thing in the way, the sell wall is #dUpT#ATR up, the thicker side is below", xV5, yR5, monospaced, bold, pz) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT) COLOURED(c5R, c5G, c5B, 255)
         ELSIF v5 = 6 AND thick = 2 THEN
            DRAWTEXT("Offers #nUpT#ATR above are the first thing in the way, the sell wall is #dUpT#ATR up, the thicker side is above", xV5, yR5, monospaced, bold, pz) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT) COLOURED(c5R, c5G, c5B, 255)
         ELSIF v5 = 7 AND thick = 0 THEN
            DRAWTEXT("Buy wall #nDnT#ATR below is the first thing in the way", xV5, yR5, monospaced, bold, pz) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT) COLOURED(c5R, c5G, c5B, 255)
         ELSIF v5 = 7 AND thick = 1 THEN
            DRAWTEXT("Buy wall #nDnT#ATR below is the first thing in the way, the thicker side is below", xV5, yR5, monospaced, bold, pz) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT) COLOURED(c5R, c5G, c5B, 255)
         ELSIF v5 = 7 AND thick = 2 THEN
            DRAWTEXT("Buy wall #nDnT#ATR below is the first thing in the way, the thicker side is above", xV5, yR5, monospaced, bold, pz) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT) COLOURED(c5R, c5G, c5B, 255)
         ELSIF v5 = 8 AND thick = 0 THEN
            DRAWTEXT("Bids #nDnT#ATR below are the first thing in the way, the buy wall is #dDnT#ATR down", xV5, yR5, monospaced, bold, pz) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT) COLOURED(c5R, c5G, c5B, 255)
         ELSIF v5 = 8 AND thick = 1 THEN
            DRAWTEXT("Bids #nDnT#ATR below are the first thing in the way, the buy wall is #dDnT#ATR down, the thicker side is below", xV5, yR5, monospaced, bold, pz) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT) COLOURED(c5R, c5G, c5B, 255)
         ELSIF v5 = 8 AND thick = 2 THEN
            DRAWTEXT("Bids #nDnT#ATR below are the first thing in the way, the buy wall is #dDnT#ATR down, the thicker side is above", xV5, yR5, monospaced, bold, pz) ANCHOR(TOPRIGHT, XSHIFT, YSHIFT) COLOURED(c5R, c5G, c5B, 255)
         ENDIF
      ENDIF
   ENDIF
ENDIF

RETURN

The Code: Liquidity Master Alerts

 

//-----------------------------------------------------------------------
//PRC_Liquidity Master Alerts
//version = 0
//22.10.2026
//Iván González @ www.prorealcode.com
//Author: SimpleAlgoAI
//Sharing ProRealTime knowledge
//-----------------------------------------------------------------------

// ===================== INPUTS =====================
// --- Liquidity ---
pivIn = 4           // swing strength: a swing needs this many lower highs / higher lows on each side (2 to 20)
wickIn = 0.45       // wick rejection: a wick at least this many ATRs long becomes a pool (0.2 to 2)
halfIn = 300        // liquidity ages out: half of a pool is gone after this many bars (50 to 3000)
lookIn = 1500       // bars to compute: the engine runs on the most recent bars only (300 to 4000)
// --- Ladder ---
spanIn = 300        // the ladder covers the price range of this many recent bars, plus a margin (50 to 2000)
rowsIn = 80         // rows (20 to 100)

// ===================== FIXED RULES =====================
maxEv = 400         // pools kept at once
maxRows = 100       // ladder rows available
zoneATR = 0.75      // stops sit within three quarters of an ATR past a swing
pivW = 1.6          // weight of the stops past a swing
wickW = 0.5         // weight of a rejection wick, times its relative volume
refreshEvery = 10   // bars between wall refreshes for the record
keepRec = 10        // wall tests remembered
brokeATR = 0.5      // a close this far past a wall breaks it
heldATR = 0.5       // a close this far back from a wall means it held
testBars = 60       // a test is dropped after this many bars without a verdict
wallAt = 0.5        // a wall must hold at least this share of the biggest row to be tracked

pivN = max(2, min(20, round(pivIn)))
wickK = max(0.2, min(2, wickIn))
halfN = max(50, min(3000, round(halfIn)))
lookN = max(300, min(4000, round(lookIn)))
spanN = max(50, min(2000, round(spanIn)))
nrow = min(max(20, min(100, round(rowsIn))), maxRows)

// ===================== INPUTS TO THE ENGINE (every bar) =====================
// ATR(14) and the slow ATR(50) for the ladder geometry; the bar range until they exist
atr14 = averagetruerange[14](close)
IF barindex >= 13 THEN
   atrV = atr14
ELSE
   atrV = high - low
ENDIF
atrV = max(atrV, ticksize)
atr50 = averagetruerange[50](close)
IF barindex >= 49 THEN
   atrGV = atr50
ELSE
   atrGV = atrV
ENDIF
atrGV = max(atrGV, ticksize)
// Volume against its 50-bar average (1 when the instrument has no volume)
vAvg = average[50](volume)
vRel = 1
IF barindex >= 49 THEN
   IF vAvg > 0 THEN
      vRel = min(volume / vAvg, 4)
   ENDIF
ENDIF
// Swing high / low confirmed this bar: the bar pivN bars back, higher (lower) than the pivN bars
// on its right and at least as high (low) as the pivN bars on its left (on a flat top the most
// recent bar of the plateau is the swing)
hhR = highest[pivN](high)
llR = lowest[pivN](low)
phF = 0
phP = 0
plF = 0
plP = 0
IF barindex >= 2 * pivN THEN
   candH = high[pivN]
   IF candH > hhR AND candH >= hhR[pivN + 1] THEN
      phF = 1
      phP = candH
   ENDIF
   candL = low[pivN]
   IF candL < llR AND candL <= llR[pivN + 1] THEN
      plF = 1
      plP = candL
   ENDIF
ENDIF
// Ladder grid: the range of the last spanN bars plus a margin, on rows of a fixed price step
hhSp = highest[spanN](high)
llSp = lowest[spanN](low)
spanOk = 0
IF barindex >= spanN - 1 THEN
   spanOk = 1
ENDIF
marg = max(1.5 * atrGV, 0.08 * (hhSp - llSp))
stepV = max(round(((hhSp - llSp + 2 * marg) / nrow) / ticksize) * ticksize, ticksize)
baseV = floor((llSp - marg) / stepV) * stepV

// ===================== THE ENGINE (last bar) =====================
// The pools, the walls and the record are rebuilt from the last lookN bars, once per new bar and
// only from CLOSED bars: the live bar spends and adds nothing until it closes. The result is kept
// in arrays, because arrays are not rewound between ticks the way scalar variables are.
IF barindex = 0 THEN
   $runAt[0] = 0 - 1
ENDIF

IF islastbarupdate THEN
   doEng = 0
   IF $runAt[0] <> barindex THEN
      doEng = 1
   ENDIF
   IF doEng = 1 THEN
      nEv = 0
      tSide = 0
      tP = 0
      tBar = 0
      wUpOk = 0
      wUpV = 0
      wDnOk = 0
      wDnV = 0
      nRec = 0
      $eng[0] = 0
      $eng[1] = 0
      $eng[2] = 0
      $eng[3] = 0
      $eng[4] = 0
      $eng[5] = 0
      $eng[6] = 0
      jStart = min(lookN - 1, barindex)
   ELSE
      nEv = $eng[0]
      jStart = 0
   ENDIF

   FOR j = jStart DOWNTO 0 DO
      bi = barindex - j
      hj = high[j]
      lj = low[j]
      cj = close[j]
      aj = atrV[j]
      bStep = stepV[j]
      bBase = baseV[j]
      bOk = spanOk[j]
      doBuild = 0
      evRU = 0
      evRD = 0
      evWH = 0
      evWB = 0
      IF j >= 1 THEN
         // 1. price trading through a pool spends it, and old pools are gone
         IF nEv > 0 THEN
            k = 0
            FOR i = 0 TO nEv - 1 DO
               gone = 0
               IF bi - $evBar[i] > 4 * halfN THEN
                  gone = 1
               ENDIF
               IF $evSide[i] = 1 THEN
                  ext = max($evExt[i], hj)
                  IF ext >= $evP1[i] THEN
                     gone = 1
                  ENDIF
               ELSE
                  ext = min($evExt[i], lj)
                  IF ext <= $evP0[i] THEN
                     gone = 1
                  ENDIF
               ENDIF
               IF gone = 0 THEN
                  $evSide[k] = $evSide[i]
                  $evP0[k] = $evP0[i]
                  $evP1[k] = $evP1[i]
                  $evW[k] = $evW[i]
                  $evBar[k] = $evBar[i]
                  $evExt[k] = ext
                  k = k + 1
               ENDIF
            NEXT
            nEv = k
         ENDIF
         // 2. new pools: the stops past a swing that just confirmed, and the orders in a rejection wick
         oj = open[j]
         FOR q = 1 TO 4 DO
            qOk = 0
            IF q = 1 THEN
               IF phF[j] = 1 THEN
                  IF hhR[j] < phP[j] + zoneATR * aj THEN
                     qOk = 1
                     qSide = 1
                     qP0 = phP[j]
                     qP1 = phP[j] + zoneATR * aj
                     qW = pivW
                     qBar = bi - pivN
                     qExt = max(hhR[j], phP[j])
                  ENDIF
               ENDIF
            ELSIF q = 2 THEN
               IF plF[j] = 1 THEN
                  IF llR[j] > plP[j] - zoneATR * aj THEN
                     qOk = 1
                     qSide = -1
                     qP0 = plP[j] - zoneATR * aj
                     qP1 = plP[j]
                     qW = pivW
                     qBar = bi - pivN
                     qExt = min(llR[j], plP[j])
                  ENDIF
               ENDIF
            ELSIF q = 3 THEN
               IF hj - max(oj, cj) >= wickK * aj THEN
                  qOk = 1
                  qSide = 1
                  qP0 = max(oj, cj)
                  qP1 = hj
                  qW = wickW * vRel[j]
                  qBar = bi
                  qExt = max(oj, cj)
               ENDIF
            ELSE
               IF min(oj, cj) - lj >= wickK * aj THEN
                  qOk = 1
                  qSide = -1
                  qP0 = lj
                  qP1 = min(oj, cj)
                  qW = wickW * vRel[j]
                  qBar = bi
                  qExt = min(oj, cj)
               ENDIF
            ENDIF
            IF qOk = 1 THEN
               // at most maxEv pools: the oldest one goes
               IF nEv >= maxEv THEN
                  FOR i = 1 TO nEv - 1 DO
                     $evSide[i - 1] = $evSide[i]
                     $evP0[i - 1] = $evP0[i]
                     $evP1[i - 1] = $evP1[i]
                     $evW[i - 1] = $evW[i]
                     $evBar[i - 1] = $evBar[i]
                     $evExt[i - 1] = $evExt[i]
                  NEXT
                  nEv = nEv - 1
               ENDIF
               $evSide[nEv] = qSide
               $evP0[nEv] = qP0
               $evP1[nEv] = qP1
               $evW[nEv] = qW
               $evBar[nEv] = qBar
               $evExt[nEv] = qExt
               nEv = nEv + 1
            ENDIF
         NEXT
         // 3. every refreshEvery bars, name the walls for the record
         IF (bi MOD refreshEvery) = 0 AND nEv >= 15 THEN
            doBuild = 1
         ENDIF
      ELSE
         // the live bar: the ladder that is drawn
         doBuild = 1
      ENDIF

      IF doBuild = 1 THEN
         // Resting liquidity per row: each pool's remaining zone spread over the rows it overlaps,
         // weighted by its age; then smoothed once with the neighbours
         FOR r = 0 TO nrow - 1 DO
            $rowS[r] = 0
         NEXT
         IF nEv > 0 AND bOk = 1 THEN
            FOR i = 0 TO nEv - 1 DO
               IF $evSide[i] = 1 THEN
                  a0 = max($evP0[i], $evExt[i])
                  a1 = $evP1[i]
               ELSE
                  a0 = $evP0[i]
                  a1 = min($evP1[i], $evExt[i])
               ENDIF
               IF a1 > a0 THEN
                  wq = $evW[i] * pow(0.5, (bi - $evBar[i]) / halfN)
                  r0 = max(floor((a0 - bBase) / bStep), 0)
                  r1 = min(floor((a1 - bBase) / bStep), nrow - 1)
                  IF r1 >= r0 THEN
                     FOR r = r0 TO r1 DO
                        lo = bBase + r * bStep
                        ov = min(a1, lo + bStep) - max(a0, lo)
                        IF ov > 0 THEN
                           $rowS[r] = $rowS[r] + wq * ov / (a1 - a0)
                        ENDIF
                     NEXT
                  ENDIF
               ENDIF
            NEXT
         ENDIF
         peak = 0
         prv = $rowS[0]
         FOR r = 0 TO nrow - 1 DO
            cur = $rowS[r]
            IF r < nrow - 1 THEN
               nxt = $rowS[r + 1]
            ELSE
               nxt = cur
            ENDIF
            sm = 0.25 * prv + 0.5 * cur + 0.25 * nxt
            prv = cur
            $rowS[r] = sm
            peak = max(peak, sm)
         NEXT
         // The walls: the biggest row on each side at least 0.3 ATR from price; also the nearest
         // real pool on each side and the liquidity on each side
         upOk = 0
         upP = 0
         upT = 0
         dnOk = 0
         dnP = 0
         dnT = 0
         nUpOk = 0
         nUpP = 0
         nDnOk = 0
         nDnP = 0
         sumUp = 0
         sumDn = 0
         IF peak > 0 THEN
            FOR r = 0 TO nrow - 1 DO
               mid = bBase + (r + 0.5) * bStep
               tq = $rowS[r] / peak
               IF mid >= cj + 0.3 * aj THEN
                  sumUp = sumUp + tq
                  IF tq > upT THEN
                     upT = tq
                     upP = mid
                     upOk = 1
                  ENDIF
                  IF tq >= 0.3 AND nUpOk = 0 THEN
                     nUpOk = 1
                     nUpP = mid
                  ENDIF
               ELSIF mid <= cj - 0.3 * aj THEN
                  sumDn = sumDn + tq
                  IF tq > dnT THEN
                     dnT = tq
                     dnP = mid
                     dnOk = 1
                  ENDIF
                  IF tq >= 0.3 THEN
                     nDnOk = 1
                     nDnP = mid
                  ENDIF
               ENDIF
            NEXT
         ENDIF
      ENDIF

      IF j >= 1 THEN
         IF doBuild = 1 THEN
            wUpOk = 0
            IF upOk = 1 AND upT >= wallAt THEN
               wUpOk = 1
               wUpV = upP
            ENDIF
            wDnOk = 0
            IF dnOk = 1 AND dnT >= wallAt THEN
               wDnOk = 1
               wDnV = dnP
            ENDIF
         ENDIF
         // 4. a wall gets tested when price reaches it: it held if price backs off, it broke if
         // price closes through
         IF tSide = 0 THEN
            IF wUpOk = 1 AND hj >= wUpV - bStep / 2 THEN
               tSide = 1
               tP = wUpV
               tBar = bi
               wUpOk = 0
               evRU = 1
            ELSIF wDnOk = 1 AND lj <= wDnV + bStep / 2 THEN
               tSide = -1
               tP = wDnV
               tBar = bi
               wDnOk = 0
               evRD = 1
            ENDIF
         ELSE
            brk = 0
            hld = 0
            IF tSide = 1 THEN
               IF cj > tP + brokeATR * aj THEN
                  brk = 1
               ENDIF
               IF cj <= tP - heldATR * aj THEN
                  hld = 1
               ENDIF
            ELSE
               IF cj < tP - brokeATR * aj THEN
                  brk = 1
               ENDIF
               IF cj >= tP + heldATR * aj THEN
                  hld = 1
               ENDIF
            ENDIF
            IF brk = 1 OR hld = 1 THEN
               // the last keepRec verdicts: 1 the wall held, 0 it broke
               IF nRec >= keepRec THEN
                  FOR i = 1 TO nRec - 1 DO
                     $rec[i - 1] = $rec[i]
                  NEXT
                  nRec = nRec - 1
               ENDIF
               IF brk = 1 THEN
                  $rec[nRec] = 0
                  evWB = 1
               ELSE
                  $rec[nRec] = 1
                  evWH = 1
               ENDIF
               nRec = nRec + 1
               tSide = 0
            ELSIF bi - tBar > testBars THEN
               tSide = 0
            ENDIF
         ENDIF
         IF j = 1 THEN
            $eng[0] = nEv
            $eng[1] = tSide
            $eng[2] = nRec
            $eng[3] = evRU
            $eng[4] = evRD
            $eng[5] = evWH
            $eng[6] = evWB
         ENDIF
      ENDIF
   NEXT
   $runAt[0] = barindex
ENDIF

// ===================== ALERTS =====================
// Add this indicator in its own panel, under a chart with Liquidity Master, and give it the same
// pivIn, wickIn, halfIn, lookIn, spanIn and rowsIn, so both map the same walls. An alert can only
// read the series returned below: they carry the four events of the bar that just closed
// (1 = it happened), read on the live bar; 0 on every other bar.
aRU = 0
aRD = 0
aWH = 0
aWB = 0
IF islastbarupdate THEN
   aRU = $eng[3]
   aRD = $eng[4]
   aWH = $eng[5]
   aWB = $eng[6]
ENDIF

RETURN aRU COLOURED(255, 61, 113) STYLE(histogram) AS "Sell wall reached", aRD COLOURED(0, 255, 163) STYLE(histogram) AS "Buy wall reached", aWH COLOURED(125, 211, 252) STYLE(histogram) AS "Wall held", aWB COLOURED(255, 180, 60) STYLE(histogram) AS "Wall broke"

Download
Filename: PRC_Liquidity-Master.itf
Downloads: 9
Iván González
Iván González Legend
As an architect of digital worlds, my own description remains a mystery. Think of me as an undeclared variable, existing somewhere in the code.
Author’s Profile

Comments

ProRealCode ProRealCode
Loading...