Skip to content

EWMAC Ensemble

Exponentially Weighted Moving Average Crossover. An ensemble of four EMA speed pairs that produces a continuous forecast, combined into a single blended signal.

How it works

EWMAC measures the difference between a fast EMA and a slow EMA, scaled by volatility to produce a normalized forecast:

raw_forecast = (EMA_fast - EMA_slow) / ATR_vol

A positive forecast means the fast average is above the slow average (bullish momentum). A negative forecast means the reverse.

Unlike a binary long/short signal, EWMAC produces a continuous value. Stronger crossovers yield stronger signals, which feed into position sizing.

Speed pairs

The ensemble runs four fast/slow EMA combinations:

PairFast EMASlow EMACharacter
1832Fast, responsive
21664Medium-fast
332128Medium-slow
464256Slow, stable

Each pair generates its own forecast independently.

Forecast scaling and combination

Raw forecasts from each speed pair have different magnitudes. Before combining, each is scaled using an expanding-mean of absolute values so the long-run mean target is 10 (Carver's convention). The ensemble forecast is the average of all four scaled forecasts:

ensemble_forecast = mean(scaled_forecast_1, ..., scaled_forecast_4)

The final forecast is clamped to [-20, +20] to prevent extreme values from dominating sizing. A signal is emitted on the bar where the discretised direction changes — not on every bar.

ATR is EMA-smoothed (not SMA). EMAs are first-value-seeded. Expanding-mean scaling uses running totals of |raw|, not a static denominator. These arithmetic choices are deliberate — they match the archived monolith byte-for-byte, preserving the backtest=live invariant.

Performance

MetricValue
Validated timeframes6h, 4h, 2h, 1h
Mean Sharpe0.90
Multi-asset validatedBTC, ETH, SOL

Stop loss

EWMAC has no natural built-in stop level. An ATR-based trailing stop is used:

Stop = Entry - N * ATR(period)

The stop trails behind the position using a Chandelier-style calculation from the highest high since entry.

When it works well

  • Trending markets at intraday timeframes: 1h–6h is the sweet spot where trends are clean enough for MA crossovers.
  • Multiple speed pairs smooth noise: any single pair gets whipsawed in choppy conditions. The ensemble averages across speeds.
  • Continuous forecast enables nuanced sizing: position size scales with conviction instead of all-in/all-out.

When it struggles

  • Ranging markets: all four pairs oscillate around zero, generating small costs from frequent adjustments.
  • Very high timeframes (D1+): the slow pairs need many bars to compute. Supertrend works better here.
  • Sharp V-reversals: moving averages lag. A sudden reversal means the ensemble is slow to flip.

Origins

EWMAC is a core system in Rob Carver's Systematic Trading and Leveraged Trading. It is one of the most widely studied trend-following signals in the systematic trading literature.

Implementation

Source: gordon-strategy/src/engines/ewmac/mod.rs

Ported byte-for-byte from the archived monolith. FMA and f64::midpoint are deliberately avoided — they change rounding behaviour and would silently break byte-parity. The fixture-driven parity tests live in src/engines/ewmac/tests.rs.

  • Supertrend — complementary strategy for higher timeframes (8h–D1)
  • Adding a Strategy — promotion flow from implementation to production

Gordon — keep compounding without blowing up