Skip to content
Open RaamTrade

MADeviation — MA Deviation

The signed distance between price and its simple moving average, in price units. Positive means price is above the average, negative means below.

MADeviation is the identifier a strategy writes; MA Deviation is the label the chart’s indicator picker shows. Single value — .value is the only accessor.

Signature

MADeviation(period, on=<source>)
Argument Type Required Notes
period int Param or literal Yes Length of the moving average. Default 20, bounds 2–200.
on= symbol, OHLCV field, or indicator No Source. Defaults to the trade symbol’s close.

Formula

$$ \text{MADeviation}t = \text{close}t - \frac{1}{N} \sum{i=0}^{N-1} \text{close}{t-i} $$

No scaling, no floor, no absolute value — just the subtraction. The result is in the source’s units, which is why it is unbounded and instrument-specific.

Warmup

period bars. Before the window fills the indicator returns 0, which on this scale reads as “price is exactly on its average”. A strategy never observes it (execute() waits until every indicator is ready); it is what the chart plots on the leading bars.

Reading the value

dev.value # price units, signed
dev.value_at(1)
dev > 0 # price above its average
dev.crossed_above(0) # the bar price reclaims the average
dev.value / self.trade.close * 100 # the same thing as a percentage

Example

class DeviationFade(Strategy):
"""Fade price when it stretches too far below its own average."""
period = Param(20, min=2, max=200)
trade = Symbol()
sizing = FixedCapital()
def execute(self):
dev = MADeviation(self.period, on=self.trade)
self.stop_loss(3.0)
stretch = dev.value / self.trade.close * 100
if stretch < -3 and self.trade.is_flat:
self.buy(self.trade, reason=f"Price {stretch:.1f}% under its average")
if stretch > 0 and self.trade.is_long:
self.sell(self.trade, self.trade.position, reason="Back at the average")

Notes

  • Unbounded and price-scaled. dev.value > 2 means something entirely different on a $15 stock and a $5,000 index. Normalize by price, as the example does — or use TrendIntensity, which is this measure already divided by the average.
  • The sign alone is a complete trend filter: dev > 0 is exactly close > SMA(period). Everything the sign can tell you, an SMA comparison tells you too; the magnitude is what this indicator adds.
  • It is the raw material of a band system — SMA ± k · StdDev is BollingerBands, and dev.value is the numerator of the position inside those bands.
  • Useful chained: SMA(5, on=dev) smooths the stretch into something closer to a slow oscillator.