RAGBAZRAGBAZ
navigate
home pricing products school docs konsonans ai governance
modules
overview cellular forensics trading
school

Reading the Tape

SMA, Bollinger bands, RSI, volume & volatility — from intuition to executable BAZ.HFT rules

On the typography. Like its sibling modules, this page keeps its Tufte CSS conventions — a narrow measure, numbered sidenotes, a wide right margin for glosses — reflowed onto the RAGBAZ token sheet. Every chart below is live: it is drawn in your browser from a synthetic price tape you control. Terms carry a margin gloss and link to the glossary. Markets print a stream of numbers — price, volume, time — and every trading idea ever written is a way of reading that stream. This module builds the five classic instruments for reading it (moving averages, Bollinger bands, RSI, volume, volatility), shows the two opposite temperaments a strategy can have (riding the waves and trading the noise), and then writes both temperaments as real, compilable BAZ.HFT rules — the same files the BAZ trading stack executes.

A moving average is a memory. A Bollinger band is a tolerance. RSI is a speedometer. Volume is a show of hands. Volatility is the weather. Strategies are just sentences built from these five words.

1 · The two moods of a market

Regime — a stretch of time in which the market keeps one statistical personality: trending (returns correlate positively) or mean-reverting (they correlate negatively). Most strategy failures are regime mismatches, not bad indicators. Zoom into any price chart and you will find two personalities taking turns. Sometimes price goes somewhere: buyers (or sellers) stay in charge for hours and each step tends to continue the last one — a trend. The rest of the time price goes nowhere: it oscillates around a fair value, overshooting and snapping back — chop, or noise. The tragedy of trading is that the best strategy for one mood is close to the worst for the other. A trend-follower gets whipsawed to death in chop; a mean-reverter steps in front of every breakout in a trend.

All the charts in this module share one synthetic tape. Choose its mood here — every widget below redraws from the same series, so you can watch each indicator succeed and fail as the regime changes.

The tape shared by every chart

2 · Moving averages: price with a memory

SMA. The simple moving average over the last N closes: μN(t) = (1/N) Σi=0..N−1 close(t−i). Bigger N → smoother and slower. BAZ.HFT spells it μ(state.close), computed by Palantir over a ring buffer of the last N bars. The rawest question about a price is “is it higher or lower than it used to be?” A simple moving average answers it by averaging the last N closes: today against the smoothed memory of recent days. Keep two memories — a short one that reacts fast and a long one that barely moves — and their relationship becomes a trend detector: when the fast average climbs above the slow one, recent prices are beating older prices, which is the definition of “going up”.

Golden / death cross. Trader slang for the fast SMA crossing above (golden) or below (death) the slow SMA. The names come from daily charts (50/200); the mechanics are identical at 15-minute scale with 9/21. The moments the two averages cross are the classic entry signals. Try dragging the windows: short windows produce many early, noisy crosses; long windows produce few, late, reliable ones. There is no setting that is both early and reliable — that trade-off is the entire game.

Short / long SMA μ(fast) vs μ(slow)

3 · Riding the waves: trend following

A wave-rider assumes the current move will continue and wants to be aboard for the middle of it — missing the start, leaving before the end, but capturing the body. The temperament: enter rarely, hold long, take a wide stop, because the one big move pays for the several small failures. Here is the idea as a complete, compilable BAZ.HFT strategy — this exact file lives in the dialect’s example set:

#pragma dialect glither.hft ; fold first-match
#pragma version 2.0-beta

/// # BAZ.CX: Riding the Waves
/// Trend following momentum on BTC/USDT.
/// SMA cross confirmation + RSI momentum filter.
/// Wide stops at -3%; every signal timestamped to backlog.

state wave_fast =
  bars | window = 9
       | timeframe = 15m
       | tracks = [ close ]

state wave_slow =
  bars | window = 21
       | timeframe = 15m
       | tracks = [ close ]

state wave_rsi =
  bars | window = 14
       | timeframe = 15m
       | tracks = [ close ]

rule golden_cross_long =
  tick | μ(wave_fast.close) > μ(wave_slow.close)
       | rsi(wave_rsi.close) > 60.0
  => transact market_buy
       on    fill  into position(target = μ(wave_slow.close))
       after 4h   market_close_all (reason = trend_exit)
  then_log backlog

rule death_cross_short =
  tick | μ(wave_fast.close) < μ(wave_slow.close)
       | rsi(wave_rsi.close) < 40.0
  => transact market_sell
       on    fill  into position(target = μ(wave_slow.close))
       after 4h   market_close_all (reason = trend_exit)
  then_log backlog

rule wave_take_profit =
  position | position.unrealized_pnl >= 0.08
  => market_close_all (reason = momentum_target_hit)
  then_log backlog

rule wave_stop_loss =
  position | position.unrealized_pnl <= -0.03
  => market_close_all (reason = trend_reversal_stop)
  then_log backlog
dialects/glither.hft/examples/riding_the_waves.glith — verbatim from the BAZ.HFT dialect examples. state blocks declare ring-buffered bar windows; rule blocks are guard | conditions => action pipelines; fold first-match means the first rule whose conditions hold wins the tick.

Reading a rule. tick | A | B => transact … reads: on every tick, if A and B hold, transact. on fill into position(…) arms the position with a target; after 4h market_close_all is a time fence; then_log backlog writes the signed evidence record. Four rules, one temperament. The two entry rules demand agreement: the SMA cross says “the trend flipped” and the RSI filter (>60 for longs, <40 for shorts) says “with conviction” — filtering out the limp crosses that happen inside chop. The exits encode wave-rider psychology exactly: take profit at +8%, stop out at −3%, and if neither happens the 4-hour fence closes the ride. Watch it work — and watch what the same file does to a choppy tape:

Strategy sim: riding the waves toy fill model

4 · Bollinger bands: a corridor of normal

Bands. Over the last N closes take the mean μ and standard deviation σ = √((1/N)Σ(close−μ)²). The bands are μ ± kσ, classically N=20, k=2. In BAZ.HFT: bbands_lower(s.close, dev = 2.5), bbands_mid, bbands_upper. Wrap the moving average in a measure of how much price usually wobbles and you get Bollinger bands: a center line (the 20-bar mean) with an envelope k standard deviations either side. For a layman: a rubber corridor around the recent average. Price inside the corridor is business as usual; price poking outside it is statistically stretched — roughly a 2-in-100 event per bar at k=2 if returns were well-behaved (they aren’t, which is why practitioners widen to 2.5 for entries).

The corridor breathes: it tightens when the market is calm and balloons when it panics. That width is itself a signal — a squeeze (very narrow bands) often precedes a violent move, because quiet markets attract the orders that end them.

Bollinger bands μ ± kσ

5 · RSI: the speedometer

RSI (Wilder, 1978). Split the last N bar-to-bar changes into gains and losses, smooth each (Wilder’s smoothing: avg ← (avg·(N−1) + new)/N), form RS = avgGain/avgLoss, then RSI = 100 − 100/(1+RS). All gains → 100; all losses → 0; a balanced market idles near 50. The relative strength index compresses recent price action into a single dial from 0 to 100: how much of the recent movement was up versus down. Above 70 the market has been climbing almost without breathing — “overbought”; below 30 it has been falling the same way — “oversold”. Two opposite readings of the dial correspond exactly to our two temperaments: the wave-rider treats a high RSI as confirmation (the move has momentum, join it), the noise-trader treats an extreme RSI as exhaustion (the move has overrun, fade it). Same number, opposite bets — the regime decides who is right.

RSI 0–100 momentum dial

6 · Volume: the show of hands

Volume confirmation. In BAZ.HFT the noise strategy demands volume(s.volume) > μ(s.volume) — the current bar’s volume above its own 20-bar average — before it will fade an extreme. An extreme on thin volume is a rumour; on heavy volume it is a vote. Price says what happened; volume says how many participants made it happen. A price poking out of the Bollinger corridor on trickle volume is a few small orders wandering in an empty room — it means little and reverts easily. The same poke on a surge of volume is a crowd event: real money disagreed about value. Nearly every robust signal on this page becomes more honest when you require volume to second the motion; that is exactly the volume(…) > μ(…) clause in the strategies.

Volume with μ(volume) reference

7 · Volatility: the weather report

Realized volatility. Take log returns r(t) = ln(close(t)/close(t−1)), their rolling standard deviation over N bars, and scale by √(bars per year) to annualize. Volatility clusters: calm follows calm, storm follows storm (Mandelbrot, 1963) — which is why yesterday’s weather is a usable forecast. Volatility is the size of the market’s typical step, regardless of direction — the weather in which every other signal operates. It sets the two numbers no strategy can ignore: how wide the stop must be (a stop inside the market’s ordinary wobble is a donation) and how large the position may be (risk a fixed fraction, so double the weather means half the size). The wave strategy’s −3% stop and the noise strategy’s −0.8% stop are not style choices — they are the same rule quoted in two different climates: 15-minute swells versus 1-minute ripples.

Rolling volatility σ of returns, 20-bar

8 · Trading the noise: mean reversion

The opposite temperament. In chop, every excursion is a mistake that the market corrects; a noise-trader’s job is to sell the overshoot and buy the undershoot — fade the move — and to be gone in seconds. Where the wave-rider wanted one big win to pay for many small losses, the noise-trader collects many small wins and must therefore forbid the one big loss: tight stops, short timeouts, and a demand that volume confirm each extreme. Again as a real dialect example, verbatim:

#pragma dialect glither.hft ; fold first-match
#pragma version 2.0-beta

/// # BAZ.CX: Trading from Noise
/// Mean reversion scalping on BTC/USDT.
/// Entries at extreme RSI + Bollinger Band touch with volume confirmation.
/// Tight stops at -0.8% P&L; every signal timestamped to backlog.

state noise_rsi =
  bars | window = 14
       | timeframe = 1m
       | tracks = [ close ]

state noise_bb =
  bars | window = 20
       | timeframe = 1m
       | tracks = [ close, volume ]

rule rsi_oversold_reversal =
  tick | rsi(noise_rsi.close) < 25.0
       | tick.close < bbands_lower(noise_bb.close, dev = 2.5)
       | volume(noise_bb.volume) > μ(noise_bb.volume)
  => transact market_buy
       on    fill  into position(target = bbands_mid(noise_bb.close))
       after 30s   market_close_all (reason = mean_reversion_timeout)
  then_log backlog

rule rsi_overbought_reversal =
  tick | rsi(noise_rsi.close) > 75.0
       | tick.close > bbands_upper(noise_bb.close, dev = 2.5)
       | volume(noise_bb.volume) > μ(noise_bb.volume)
  => transact market_sell
       on    fill  into position(target = bbands_mid(noise_bb.close))
       after 30s   market_close_all (reason = mean_reversion_timeout)
  then_log backlog

rule noise_stop_loss =
  position | position.unrealized_pnl <= -0.008
  => market_close_all (reason = noise_vol_stop)
  then_log backlog

rule noise_take_profit =
  position | position.unrealized_pnl >= 0.015
  => market_close_all (reason = mean_reversion_target_hit)
  then_log backlog
dialects/glither.hft/examples/trading_from_noise.glith — three conditions must agree before an entry: the RSI dial pinned (<25 or >75), price outside the 2.5σ corridor, and volume above its average. The position’s target is the band midline — the strategy literally bets on the return to normal.

The asymmetry. Wave: stop −3%, target +8%, few trades — pays on the ratio. Noise: stop −0.8%, target +1.5%, many trades — pays on the hit-rate. Neither survives in the other’s regime; both log every decision to the backlog so you can prove which regime you were actually in. Run it on the shared tape. On choppy, entries appear at the band-edges and resolve to the midline; flip the tape to trending and watch the same rules bleed — each “overshoot” it fades keeps going, and only the tight stop keeps the damage survivable. That contrast, not any single indicator, is the lesson of this module.

Strategy sim: trading the noise toy fill model

9 · Composing your own: a squeeze breakout

The five instruments compose. Here is a third temperament written from the same vocabulary — a breakout rule that waits for the corridor to stretch, requires the crowd to show up, and asks the dial for momentum. It fires far less often than either example above, which is precisely its virtue:

#pragma dialect glither.hft ; fold first-match
#pragma version 2.0-beta

/// # BAZ.CX: Squeeze Breakout
/// Volume-confirmed Bollinger breakout with momentum agreement.

state box =
  bars | window = 20
       | timeframe = 5m
       | tracks = [ close, volume ]

state box_rsi =
  bars | window = 14
       | timeframe = 5m
       | tracks = [ close ]

rule squeeze_breakout_long =
  tick | tick.close > bbands_upper(box.close, dev = 2.0)
       | volume(box.volume) > μ(box.volume)
       | rsi(box_rsi.close) > 55.0
  => transact market_buy
       on    fill  into position(target = μ(box.close))
       after 2h   market_close_all (reason = breakout_expiry)
  then_log backlog

rule breakout_stop =
  position | position.unrealized_pnl <= -0.015
  => market_close_all (reason = failed_breakout)
  then_log backlog
The same clause the noise strategy used to fade a band-break (tick.close > bbands_upper) here becomes the reason to join it — the difference is one RSI comparison and a regime opinion. Vocabulary is cheap; the temperament is the strategy.

10 · From this page to production: CX, Palantir, Luna

Everything you just manipulated by hand has a permanent seat in the BAZ trade-signal stack. The division of labour:

   exchange feeds                    the numbers            the decisions              the humans
 ┌────────────────┐   ticks &   ┌──────────────────┐  WS   ┌──────────────────┐      ┌──────────────────┐
 │     BAZ.CX     │───candles──▶│   BAZ.Palantir   │──────▶│     BAZ.Luna     │      │     backlog      │
 │ market-data    │   (:8000)   │ validates rules  │stream │ CodeMirror 6     │      │ Ed25519-signed   │
 │ subscriptions  │             │ ring buffers     │       │ notebook,        │      │ monetary audit   │
 │ per symbol     │             │ SMA/BB/RSI/vol   │       │ candlestick      │      │ receipts, one    │
 └────────────────┘             │ enrichment       │       │ charts, backlog  │      │ per transact     │
                                └──────────────────┘       │ viewer           │      └──────────────────┘
                                        ▲                  └──────────────────┘              ▲
                                        │ compiled WASM strategy                             │
                                ┌──────────────────┐                                         │
                                │     BAZ.HFT      │─────────────────────────────────────────┘
                                │ glither.hft      │   every fill emits a signed receipt
                                │ compiler         │
                                └──────────────────┘
The BAZ trade-signal stack. The state blocks in a strategy are provisioning instructions for Palantir’s ring buffers; the indicator calls are requests against its enrichment engine; the then_log backlog clauses land as signed receipts that Luna renders.

← ragbaz product

The stack this module teaches against is the BAZ Trade Signal Stack — glither.hft compiler with signed receipts, Palantir orchestration, Luna frontend. open prospectus →

11 · Glossary

tick
One market update — the newest trade or quote. Strategies here are evaluated on every tick.
bar / candle
All the ticks of one time slice summarized as open, high, low, close (and volume). A “15m bar” compresses fifteen minutes.
timeframe
The bar size a state window is built from — the strategies above use 1m, 5m and 15m.
SMA / μ
Simple moving average: the mean of the last N closes. The market’s short-term memory.
golden / death cross
Fast SMA crossing above / below the slow SMA — the classic trend-flip signal.
Bollinger bands
A corridor of “normal”: the 20-bar mean ± k standard deviations. Touches mark statistically stretched prices.
squeeze
Unusually narrow bands — a calm that often precedes a violent move.
σ (standard deviation)
The typical size of the wobble around the average; the yardstick the bands are built from.
RSI
Relative strength index, 0–100: how one-sided recent movement has been. >70 overbought, <30 oversold.
volume
How much was actually traded in a bar — the number of hands behind the price move.
volatility
The size of the market’s typical step, direction-blind. Sets stop widths and position sizes.
regime
The market’s current statistical personality: trending or mean-reverting (chop).
trend following
“Riding the waves” — betting the current move continues. Few trades, wide stops, big targets.
mean reversion
“Trading the noise” — betting the overshoot snaps back. Many trades, tight stops, small targets.
fade
To trade against the most recent move — selling the spike, buying the dip.
whipsaw
Being repeatedly stopped out as chop crosses your signals back and forth. The trend-follower’s tax in the wrong regime.
long / short
A position that profits when price rises / falls. market_buy opens longs, market_sell shorts.
stop loss / take profit
Exit rules on the position’s unrealized P&L: the pre-committed loss you accept, the win you bank.
P&L
Profit and loss. position.unrealized_pnl is the open position’s current fraction gained or lost.
slippage
The gap between the price a signal saw and the price the fill got. The toy model on this page pretends it is zero; production must not.
glither.hft
The BAZ.HFT strategy dialect: state windows + guarded rule pipelines, compiled to WASM. fold first-match = first matching rule wins the tick.
ring buffer
A fixed-size window that forgets the oldest entry as each new one arrives — how Palantir stores every state block.
backlog
The append-only record of every signal and fill, each entry Ed25519-signed — the strategy’s audit trail, browsable in Luna.
Ed25519 receipt
A digital signature attached to each transaction record, proving origin and integrity of the monetary audit trail.