◆ New — Strategy Validator, Code Fixer & Prop Compliance Checker are live. Try one free →
Home / Indicators / Z-Score
Statistics indicator

Z-Score

A rolling statistical measure of how many standard deviations price sits from its recent mean.

Illustrative diagram — not live market data.

What it is

A z-score is a standard tool from statistics applied to a price chart: it expresses how far the current value of a series is from its rolling mean, measured in units of the rolling standard deviation. A z-score of +2 means price is two standard deviations above its recent average; 0 means price sits exactly at the average; −1.5 means one and a half standard deviations below it. On a chart it is computed over a fixed lookback window — for example the last 50 bars — so both the mean and the standard deviation update as each bar closes, and the z-score is plotted as an oscillator around zero. Traders use it to normalize 'how stretched is price right now?' into a scale that is comparable across instruments and timeframes, and it is the same construction that underlies Bollinger %B and pairs-trading spreads. A z-score is purely descriptive: it restates recent price behavior in standardized units and says nothing about what happens next. Interpreting z-score extremes as automatic reversal points imports an assumption (mean reversion) that the number itself does not contain. This is educational content, not financial advice, and all trading involves risk of loss.

How it works

The calculation has three steps, all over the same lookback window of n bars. First, compute the rolling mean of the source series (usually the close): the simple average of the last n values. Second, compute the rolling standard deviation of those same n values — the square root of the average squared deviation from the mean, which measures how dispersed the recent data is. Third, standardize: z = (current value − rolling mean) / rolling standard deviation. The division is what makes the output comparable across markets: a $5 move means something very different on a $50 stock than on a $5,000 index, but 'two standard deviations of its own recent behavior' is a like-for-like statement. The textbook interpretation — about 95% of observations within ±2, about 99.7% within ±3 — comes from the normal distribution, and this is where honesty matters: financial returns are not normally distributed. They exhibit fat tails and volatility clustering, so |z| > 3 events occur far more often than a normal table predicts, and precisely during the volatile episodes when the reading would matter most. The z-score arithmetic is always correct; the Gaussian probability language often attached to it is not. Also note both the mean and the standard deviation are themselves lagging, window-dependent estimates: change the lookback and every reading changes.

How traders read it

Common settings

A lookback of 20 to 100 bars on the closing price is typical; 20 matches the standard Bollinger Band window, while 50 or 100 gives a slower, smoother reading. Reference lines are usually drawn at ±1, ±2, and sometimes ±3. Shorter windows make both the mean and the standard deviation estimates noisier, so the z-score whips around more; longer windows are steadier but slower to reflect regime changes. There is no correct setting — the window defines what 'recent' means, and every choice is a trade-off you should test rather than assume.

Strengths

Pitfalls to watch

Pine v6 example

//@version=6
indicator("Rolling Z-Score", overlay = false)

length = input.int(50, "Lookback", minval = 2)
src    = input.source(close, "Source")

mean = ta.sma(src, length)
sd   = ta.stdev(src, length)
z    = sd != 0 ? (src - mean) / sd : na

plot(z, "Z-Score", color = color.teal)
hline(2,  "+2 SD", color = color.gray)
hline(0,  "Mean",  color = color.new(color.gray, 50))
hline(-2, "-2 SD", color = color.gray)

// Descriptive marker only — gated to confirmed bars so it cannot repaint
stretched = math.abs(z) > 2 and barstate.isconfirmed
plotshape(stretched, "Beyond 2 SD", style = shape.circle, location = location.top, color = color.orange, size = size.tiny)

Pro tip: Use the z-score as a normalizer, not an oracle: it is excellent for asking 'how unusual is this move relative to this instrument's own recent behavior?' and poor for predicting what follows. Before acting on any threshold, check how often your instrument historically stayed beyond it and for how long — on trending markets the answer is usually 'often, and for a while'. Keep the Gaussian intuition out of position sizing, because fat tails break it exactly when it matters. Educational only, not financial advice; all trading carries risk of loss.

Built an indicator from this? Run it through the Validator to catch look-ahead bias and repainting, or convert a strategy to Pine Script.

Educational only — not financial advice, not a recommendation to trade. No indicator is predictive; trading involves substantial risk of loss.

Catch the bug that compiles.Run auditGet Pro