StdDev — Rolling Standard Deviation
Standard deviation of the input over the last N bars. The volatility primitive.
Signature
StdDev(period, on=<source>)| Argument | Type | Required | Notes |
|---|---|---|---|
period |
int Param or literal | Yes | Lookback. |
on= |
symbol, OHLCV field, or indicator | No | Source. Defaults to the trade symbol’s close. |
Formula
$$ \bar{x} = \frac{1}{N} \sum_{i=0}^{N-1} \text{close}{t-i}, \qquad \text{StdDev} = \sqrt{\frac{1}{N} \sum{i=0}^{N-1} (\text{close}_{t-i} - \bar{x})^2} $$
Population standard deviation (divide-by-N), not sample. Returns 0 until the period-bar window is full.
Warmup
period bars.
Reading the value
sd.valuesd > some_thresholdExample — Bollinger Bands
class BollingerBounce(Strategy): """Mean reversion on Bollinger Band touches.""" period = Param(20, min=10, max=50) num_std = Param(2, min=1, max=3) trade = Symbol() sizing = FixedCapital()
def execute(self): sma = SMA(self.period, on=self.trade) sd = StdDev(self.period, on=self.trade)
lower = sma.value - self.num_std * sd.value upper = sma.value + self.num_std * sd.value
self.stop_loss(3.0)
if self.trade.close < lower and self.trade.is_flat: self.buy(self.trade, reason="Touch lower band")
if self.trade.close > upper and self.trade.is_long: self.sell(self.trade, self.trade.position, reason="Touch upper band")Notes
- StdDev is unbounded — values scale with the source. To compare across instruments, normalize by price (
sd.value / self.trade.close). - Want the classic bands directly? Use the built-in
BollingerBands— theSMA + StdDevcomposition above is the same math, useful when you need custom band logic. - For volatility regimes (“am I in a calm or noisy market?”), compare current StdDev to historical: e.g. is
sd.value > sd.value_at(20)?