ZScore — Z-Score
תוכן זה אינו זמין עדיין בשפה שלך.
How many standard deviations the close sits from its rolling mean. The general-purpose mean-reversion primitive: every band is a special case of it.
Signature
ZScore(period, on=<source>)| Argument | Type | Required | Notes |
|---|---|---|---|
period |
int Param or literal | Yes | Lookback for the mean and standard deviation. Default 20, bounds 2–400. |
on= |
symbol, OHLCV field, or indicator | No | Source. Defaults to the trade symbol’s close. |
Formula
$$ z_t = \frac{C_t - \text{SMA}(C, n)_t}{\sigma(C, n)_t} $$
Population standard deviation over the same window as the mean.
Warmup
period bars; 0 until then. Also returns 0 on a perfectly flat window (zero standard
deviation) — a flat market reads as “at the mean”, not as an extreme.
Reading the value
z.valuez.value_at(1)z < -2z.crossed_above(0)Example
class ZReversion(Strategy): """Fade a two-sigma stretch; exit at the mean.""" period = Param(20, min=2, max=400) entry = Param(2.0, min=0.5, max=4.0) trade = Symbol() sizing = FixedCapital()
def execute(self): z = ZScore(self.period, on=self.trade) if z.value < -self.entry and self.trade.is_flat: self.buy(self.trade, reason=f"z {z.value:.2f}") if z.value > 0 and self.trade.is_long: self.sell(self.trade, self.trade.position, reason="Back at mean")Variants
ZScore(20, on=self.trade.volume) # volume z-score — unusual activity detectorNotes
- Standard statistics; the same standardisation Bollinger %B rescales.
- Proven by an assert-via-trade run on SPY daily (matched a strategy-side mean/σ reference to 1e-4 on every bar; zero alarm trades).
- Population (not sample) standard deviation, matching the platform’s
stddevand Bollinger convention; sample-σ implementations read ~2–5% smaller |z| at short windows.