Skip to content
Open RaamTrade

Skewness

Asymmetry of the return distribution over the window. Negative skew means the left tail is longer — the crash-risk direction, and the shape most equity indices actually have.

Signature

Skewness(period, on=<source>)
Argument Type Required Notes
period int Param or literal Yes Return window. Default 60, bounds 3–400.
on= symbol, OHLCV field, or indicator No Source. Defaults to the trade symbol’s close.

Formula

$$ \text{skew} = \frac{m_3}{m_2^{3/2}}, \quad m_k = \frac{1}{n}\sum_i (r_i - \bar{r})^k $$

on log returns. Population moments, no small-sample correction.

Warmup

period + 1 bars; 0 until then.

Reading the value

sk.value
sk.value < -0.5

Example

class SkewGuard(Strategy):
"""Reduce exposure when the return distribution turns sharply left-tailed."""
trade = Symbol()
sizing = FixedCapital()
def execute(self):
sk = Skewness(60, on=self.trade)
sma = SMA(50, on=self.trade)
if sk.value > -0.5 and self.trade.close > sma.value and self.trade.is_flat:
self.buy(self.trade, reason=f"Skew {sk.value:.2f}")
if sk.value < -1.0 and self.trade.is_long:
self.sell(self.trade, self.trade.position, reason="Left tail heavy")

Notes

  • Proven by an assert-via-trade run on SPY daily (matched a strategy-side moment computation to 1e-3 on every bar; zero alarm trades).
  • Skewness on 60 daily bars is a noisy estimate — read the sign and large moves, not small changes.
  • Population moments (divided by n) over log returns; pandas_ta’s skew() applies the sample, bias-corrected formula to the price series, so the two never agree.