Z-Score -- Standard Score
Contents
Overview
Z-Score measures how many standard deviations the current price is from its rolling mean. The formula is: Z = (price - mean) / standard_deviation, where both the mean and standard deviation are calculated over the last N closing prices.
The result translates raw price into a universal, dimensionless scale. A Z-Score of -2 means the current price is 2 standard deviations below the recent average -- statistically, this puts it in approximately the bottom 2.5% of the recent price distribution (assuming normality). A Z-Score of +2 means the opposite: price is in the top 2.5%.
This universality is what makes Z-Score powerful. Unlike ATR or RSTD, where thresholds must be recalibrated for every asset and timeframe, Z-Score thresholds are asset-agnostic. A Z-Score of -2 means "statistically cheap relative to recent history" whether you are trading BTC at $60,000 or SOL at $150. This makes Z-Score one of the most portable indicators for mean-reversion strategies -- you write the logic once, and it works across any pair.
Format
zscore_{period}
The period defines the lookback window used to calculate both the rolling mean and the rolling standard deviation.
| Example | Period | Use Case |
|---|---|---|
zscore_20 | 20 | Standard -- responsive to recent deviations, good for intraday mean reversion |
zscore_50 | 50 | Slower -- captures deviations from a longer-term average, fewer false signals |
zscore_100 | 100 | Long-term -- identifies major statistical outliers, best for swing/position trading |
Period range: 5 to 500.
Value range: Typically -4 to +4 (theoretically unbounded). 0 = price is exactly at its rolling mean. Negative = below mean. Positive = above mean.
Understanding Z-Score Values
Z-Score values are normalized and universal. The same thresholds apply across all assets and timeframes, which is a major advantage over price-denominated indicators like ATR and RSTD.
| Z-Score Range | Statistical Meaning | Trading Interpretation |
|---|---|---|
| > +3.0 | Top ~0.1% -- extreme outlier | Extremely overbought. Price has deviated far above the mean. High risk of reversion. |
| +2.0 to +3.0 | Top ~2.5% | Overbought. Statistically expensive. Mean-reversion sell zone. |
| +1.0 to +2.0 | Above average | Moderately elevated. Price is above the mean but within a normal range. |
| -1.0 to +1.0 | Within 1 standard deviation | Normal range. ~68% of prices fall here. No strong signal. |
| -2.0 to -1.0 | Below average | Moderately depressed. Price is below the mean but within a normal range. |
| -3.0 to -2.0 | Bottom ~2.5% | Oversold. Statistically cheap. Mean-reversion buy zone. |
| < -3.0 | Bottom ~0.1% -- extreme outlier | Extremely oversold. Price has deviated far below the mean. High probability of reversion. |
These statistical percentages assume a normal distribution. Crypto price returns have fat tails -- Z-Scores of -3 or -4 occur more frequently than a normal distribution would predict. This actually works in favor of mean-reversion strategies: the extremes are more common, giving you more trading opportunities, and the reversion tendency still holds.
Understanding Operators with Z-Score
Z-Score is primarily a mean-reversion indicator. It tells you when price has deviated "too far" from its recent average. The operators let you define what "too far" means for your strategy.
> (Greater Than) -- State-Based
What it does: The trigger is true on every candle where Z-Score is above the threshold.
On the chart: Price is elevated relative to its recent mean. The higher the Z-Score, the more statistically extended the price is. This trigger stays active for as long as the Z-Score remains above the threshold.
[[actions.triggers]]
indicator = "zscore_20"
operator = ">"
target = "2.0"
timeframe = "1h"
Typical use: "Price is statistically overbought -- consider taking profit or selling." When Z-Score exceeds +2.0, price is in the top ~2.5% of its recent range. For mean-reversion strategies, this is a sell or exit signal.
< (Less Than) -- State-Based
What it does: The trigger is true on every candle where Z-Score is below the threshold.
On the chart: Price is depressed relative to its recent mean. The more negative the Z-Score, the more statistically cheap the price is. This trigger stays active for as long as Z-Score remains below the threshold.
[[actions.triggers]]
indicator = "zscore_20"
operator = "<"
target = "-2.0"
timeframe = "1h"
Typical use: "Price is statistically oversold -- consider buying." When Z-Score drops below -2.0, price is in the bottom ~2.5% of its recent range. This is the classic mean-reversion buy signal. The assumption is that price will revert toward the mean.
cross_above -- Event-Based
What it does: Fires once, at the exact candle where Z-Score transitions from below the threshold to above it. The previous candle had Z-Score <= the target, and the current candle has Z-Score > the target.
[[actions.triggers]]
indicator = "zscore_20"
operator = "cross_above"
target = "0"
timeframe = "1h"
Typical use: Detect the moment price crosses back above the mean (Z-Score crosses above 0). In a mean-reversion strategy, this can signal that the reversion is complete -- price has returned to "normal." Also useful for detecting the moment price transitions into overbought territory (crossing above +2.0).
cross_below -- Event-Based
What it does: Fires once, at the exact candle where Z-Score transitions from above the threshold to below it. The previous candle had Z-Score >= the target, and the current candle has Z-Score < the target.
[[actions.triggers]]
indicator = "zscore_20"
operator = "cross_below"
target = "-2.0"
timeframe = "1h"
Typical use: Detect the exact moment price enters the oversold zone. Unlike < which stays active the entire time Z-Score is below -2.0, cross_below fires only at the transition -- ensuring you enter once per dip rather than on every candle during an extended decline.
= (Equal) -- Not Recommended for Z-Score
Why: Z-Score produces floating-point values that are rarely exactly equal to any specific number. Use > or < instead.
- Use
<with a negative target (e.g., -2.0) for mean-reversion buy entries. This is the most common Z-Score operator. - Use
>with a positive target (e.g., +1.0 or +2.0) for mean-reversion exits or overbought detection. - Use
cross_belowto enter once per dip (fires at the moment of transition, not on every candle). - Use
cross_aboveto detect the moment price returns to the mean (exit signal).
TOML Examples
Mean Reversion at Statistical Extreme
The classic Z-Score trade: buy when price drops to 2 standard deviations below the mean. This is a statistically rare event (~2.5% of the time under normal assumptions), and prices tend to revert toward the mean. Add a trend filter to avoid catching falling knives in a downtrend.
[[actions]]
type = "open_long"
amount = "100 USDC"
[[actions.triggers]]
indicator = "zscore_20"
operator = "<"
target = "-2.0"
timeframe = "1h"
[[actions.triggers]]
indicator = "sma_50"
operator = ">"
target = "sma_200"
timeframe = "1d"
Exit When Mean Reversion Completes
Close the position when Z-Score crosses back above +1.0 -- price has not only returned to the mean but has moved one standard deviation above it. This captures the full reversion move plus some continuation.
[[actions]]
type = "close_long"
amount = "100%"
[[actions.triggers]]
indicator = "zscore_20"
operator = "cross_above"
target = "1.0"
timeframe = "1h"
Z-Score with Trend Filter
Buy statistically cheap price levels, but only when the broader trend supports it. The Z-Score provides the entry timing (price is 2.5 standard deviations below the mean), while the EMA crossover confirms the macro trend is bullish. This prevents mean-reversion entries during sustained downtrends.
[[actions]]
type = "open_long"
amount = "150 USDC"
[[actions.triggers]]
indicator = "zscore_50"
operator = "<"
target = "-2.5"
timeframe = "1h"
[[actions.triggers]]
indicator = "ema_21"
operator = ">"
target = "ema_55"
timeframe = "1d"
[[actions.triggers]]
indicator = "rsi_14"
operator = "<"
target = "40"
timeframe = "1h"
Multi-Timeframe Z-Score Confluence
Enter only when Z-Score is oversold on BOTH the hourly and 4-hour timeframes. When two timeframes agree that price is statistically cheap, the mean-reversion signal is much stronger than a single-timeframe reading.
[[actions]]
type = "open_long"
amount = "200 USDC"
[[actions.triggers]]
indicator = "zscore_20"
operator = "<"
target = "-2.0"
timeframe = "1h"
[[actions.triggers]]
indicator = "zscore_20"
operator = "<"
target = "-1.5"
timeframe = "4h"
Tips
Z-Score assumes price will revert to the mean. In a strong trend (sustained rally or crash), price can stay at extreme Z-Score levels for extended periods. A Z-Score of -3 during a capitulation crash may go to -4, -5, or worse before reverting. Always combine Z-Score with a trend filter (e.g., SMA crossover, EMA direction) to avoid mean-reverting against the dominant trend.
Unlike ATR or RSTD where you need different thresholds for every asset, Z-Score thresholds work the same everywhere. A Z-Score of -2 means "bottom 2.5% of recent prices" whether you are trading BTC, ETH, SOL, or any other pair. This makes Z-Score strategies highly portable -- write once, deploy on any asset.
The most natural way to use Z-Score is as a complete mean-reversion system: enter at one extreme, exit at the opposite extreme or at the mean. For example, enter long when zscore_20 < -2.0 and exit when zscore_20 > 1.0. This creates a symmetric strategy that captures the full reversion move.
Z-Score divides the deviation from the mean by the rolling standard deviation (RSTD). This normalization is what makes the thresholds universal. If you want to understand why a Z-Score is extreme, look at the RSTD: if RSTD is very low (squeeze), even a small price move creates a large Z-Score. If RSTD is high, it takes a much bigger move to reach the same Z-Score level.