Level 4
10 min readLesson 23 of 43

Z-Score Normalization: Speaking One Language

Making every indicator comparable

The Comparison Problem

How do you compare RSI to funding rate? RSI ranges from 0 to 100. Funding rate might be -0.3% to +0.3%. Open interest could be 50,000 to 500,000 BTC-worth.

You can't directly compare these. Saying "RSI at 30 and funding at 0.1%" doesn't tell you which one is more extreme. Is RSI of 30 a bigger deal than funding of 0.1%? Depends on context.

This is the comparison problem, and z-score normalization solves it.

What Is a Z-Score?

A z-score tells you how many standard deviations a value is from its mean.

The formula is simple: z = (x - mean) / standard_deviation

If the current RSI is 30, the mean over your lookback period is 50, and the standard deviation is 10, then: z = (30 - 50) / 10 = -2.0

That -2.0 means the current RSI is 2 standard deviations below its average.

Now apply the same logic to funding rate. If current funding is 0.05%, mean is 0.02%, and standard deviation is 0.03%: z = (0.05 - 0.02) / 0.03 = 1.0

Now you can compare: RSI at -2.0 sigma is more extreme than funding at +1.0 sigma. You're speaking the same language.

Why Z-Scores Matter for Discovery

When you're combining indicators to find edges, you need a common scale. Consider this edge definition:

"Go LONG when funding z-score drops below -2 AND price is at a liquidation level AND DPO shows oversold."

Every condition uses z-scores. You can immediately tell that -2 means "two standard deviations below normal." The conditions are comparable and interpretable.

Without normalization, you'd have arbitrary thresholds that don't translate between indicators:

"Go LONG when funding < 0.01% AND price within 1% of liquidation AND DPO < -15."

What does DPO < -15 mean? Is that extreme? You have no intuition without knowing DPO's historical distribution.

Z-scores give you that intuition automatically.

Rolling Z-Scores for Live Trading

Here's a critical point: for live trading, you need rolling z-scores, not static ones.

A static z-score uses the mean and standard deviation from your entire historical dataset. That's fine for backtesting but problematic live—market conditions change, and what was "normal" in 2021 isn't normal in 2025.

Rolling z-scores recalculate the mean and standard deviation over a recent window. If your lookback is 30 days, you're asking: "How extreme is today's value compared to the last 30 days?"

This keeps your normalization adaptive. Volatility doubles? Your rolling standard deviation adjusts. New baseline for funding rate? Your rolling mean adjusts.

The implementation looks like this (conceptually):

  1. For each indicator, maintain a rolling window of values (e.g., last 720 hourly candles for 30 days)
  2. Calculate the mean and standard deviation of that window
  3. Z-score = (current_value - rolling_mean) / rolling_std

Your z-scores are always relative to recent market conditions.

Lookback Period Selection

How long should your lookback period be? This is one of the most important choices in z-score normalization.

Too Short (< 7 days):

  • Noisy—small sample means unstable statistics
  • Extreme moves look less extreme (recent memory)
  • High false positive rate

Too Long (> 90 days):

  • Slow to adapt to regime changes
  • Old data may not reflect current conditions
  • Real extremes get diluted

Sweet Spot (14-30 days typically):

  • Enough samples for stable statistics
  • Recent enough to reflect current regime
  • Balances sensitivity with stability

We typically use 20-30 day lookbacks for most indicators. But this isn't universal—some indicators benefit from longer or shorter windows. Test different periods during discovery.

Handling Edge Cases

Z-score normalization has a few gotchas:

Zero Standard Deviation: If an indicator is completely flat during your lookback, standard deviation is zero, and division fails. Handle this by setting z-score to 0 when standard deviation is below a threshold.

Non-Stationary Data: Some indicators trend over time (like total open interest growing as a market matures). Detrending before z-scoring can help, but adds complexity.

Heavy Tails: Financial data often has fatter tails than normal distributions. A z-score of -3 might happen more frequently than normal distribution math suggests. Don't assume 99.7% of values fall within ±3 sigma—they don't in crypto.

Outliers: Extreme events (flash crashes, massive squeezes) create outliers that distort rolling statistics. Some implementations use robust statistics (median/MAD instead of mean/std) to reduce outlier impact.

Example Transformations

Let's walk through normalizing three real indicators:

Funding Rate

  • Raw values: Range from -0.3% to +0.3%, typically clusters around 0.01%
  • After z-score: Centered around 0, extremes at ±3 or more
  • Interpretation: z > 2 means funding unusually high (longs paying heavily)

Open Interest Change

  • Raw values: Could be -10% to +10% daily change
  • After z-score: Tells you if today's OI change is unusual relative to recent OI changes
  • Interpretation: z > 2 means OI increasing faster than normal

CVD (Cumulative Volume Delta)

  • Raw values: Arbitrary units depending on exchange
  • After z-score: Tells you if buying/selling pressure is extreme relative to recent history
  • Interpretation: z < -2 means unusual selling pressure

After normalization, you can write rules like "funding_z > 2 AND cvd_z < -1"—both thresholds are on the same scale.

The Unified Indicator DataFrame

In practice, we maintain a unified dataframe where every indicator column has a corresponding z-score column:

timestampfundingfunding_zoioi_zcvdcvd_z...
...0.012%1.34500000.8-5000-2.1...

Discovery then operates on the z-score columns. Edge conditions are defined entirely in terms of z-score thresholds.

This standardization is why we can test millions of combinations programmatically—every indicator speaks the same language.

Key Takeaways

  1. Z-scores make different indicators comparable by measuring "extremeness" in standard deviations
  2. Use rolling z-scores for live trading to adapt to changing conditions
  3. Lookback period of 14-30 days usually works well, but test for your specific indicators
  4. Handle edge cases (zero std, outliers, non-stationarity)
  5. After normalization, all your edge conditions use a common scale

Z-score normalization is foundational infrastructure. Every lesson from here forward assumes your indicators are normalized. It's the common language that makes systematic edge discovery possible.