Skip to main content
Education
Contents
9 min read

Moving-average systems: filters, crossovers, and whipsaws

Use smoothing as a declared decision rule, not as proof that a trend exists.

A moving average smooths price; a system decides what to do with it

A moving average replaces a jagged series of observations with a smoother reference. For a 20-bar simple moving average, each of the last 20 completed prices receives equal weight. An exponential moving average gives more weight to recent observations and lets older information decay gradually.

That smoothing can make direction easier to describe, but the line is not a strategy. A strategy must still decide what comparison matters, when it is evaluated, what position follows, and how risk ends.

Three familiar designs are related but not interchangeable:

  • A price filter is positive when price is above its moving average.
  • A crossover is positive when a faster average is above a slower average.
  • A slope rule is positive when one average is rising.

On the same bar, price may be below a still-rising slow average while a fast average remains above it. Each rule is measuring a different combination of level, recent speed, and direction.

Smoothing always creates a trade-off

A fast filter reacts quickly to new prices. It can join a move earlier, but it also changes state whenever short-term noise crosses the reference. A slow filter ignores more noise and changes state less often, but it recognizes turns later.

That delay is not a software defect; it is the consequence of averaging past observations. Every attempt to reduce lag—shorter windows, heavier recent weights, adaptive parameters—also changes sensitivity to noise or introduces a new model.

Moving-average systems are therefore trend implementations, not independent evidence that trends exist. Their research value is that the rule is simple, observable, and capable of expressing a persistence thesis without forecasting an exact future price. Transparent historical tests exist for declared moving-average rules, but their results belong to those constructions and samples rather than to every crossover.

The rule choices that matter

ChoiceCommon variantsResearch consequence
InputClose, midpoint, typical price, or adjusted priceDetermines what is actually being smoothed
WeightingSimple or exponentialChanges lag, warm-up, and response to recent observations
TriggerPrice/average, fast/slow crossover, or slopeDefines the market state
BufferPercentage, volatility band, or persistence countReduces transitions but delays recognition
Decision timeCompleted bar or scheduled evaluationPrevents intrabar hindsight
PositionLong/flat, long/short, or scaledChanges directional and financing exposure
ExitReverse signal, neutral band, stop, or timeoutChanges whipsaw and tail behavior

The two window lengths in a crossover should also be understood as a ratio. A 10/20 crossover and a 100/200 crossover both compare a fast window half the length of the slow one, but they operate at very different horizons.

A crossover from observation to trade

Illustrative example. Assume a daily system with a 20-day exponential average and a 100-day exponential average:

  1. Both averages update only after the daily bar completes.
  2. The long state begins when the fast average closes at least 0.25% above the slow average. The short state begins at least 0.25% below it. Inside the buffer, the existing state is retained.
  3. A state change can be acted on only at the next modeled event.
  4. Exposure is fixed for the baseline. Volatility scaling is tested later as a separate design choice.
  5. The position closes or reverses only after the opposite buffered condition is known.

Illustrative example. Suppose the slow average is 100 and the fast average moves from 100.10 to 100.35. The positive distance is 0.35%, so the completed observation creates a long state. If the next modeled fill is 100.60, that—not 100.35—is the strategy’s entry reference.

Now suppose the averages repeatedly cross inside the 0.25% band. The strategy does nothing. That can reduce turnover, but it also means the result cannot be attributed to “the 20/100 crossover” alone; it is a buffered state machine.

How to study the filter rather than optimize a picture

Begin by comparing a price-versus-slow-average rule with a fast/slow crossover. Keep the execution time, position size, and costs identical. This reveals whether the extra fast average adds information or merely changes timing.

Next, use a small structured grid:

  • a few slow horizons representing short, medium, and long behavior;
  • fast windows expressed as stable fractions of the slow window;
  • no buffer, a small fixed buffer, and a volatility-scaled buffer; and
  • fixed exposure beside risk-scaled exposure.

Inspect transition count, time in market, average delay after major reversals, gross and net results, and drawdowns during sideways periods. A useful parameter surface should change gradually. One profitable island surrounded by failure is not a robust “best setting.”

Make warm-up explicit. A 200-day simple average cannot produce a valid reading after only 30 observations, and silently filling the missing period with a shorter window changes the rule.

Interpreting the result

A moving-average system is doing its job when its behavior matches the declared trade-off. A slow system should trade infrequently, lag turns, and retain long moves. A fast system should react earlier and incur more false transitions. Results that show the opposite deserve a data and timing audit.

Compare performance across trend and range-bound periods, but define those periods without using the strategy’s later P&L. Report long and short legs separately and check whether the system is mostly a long-market exposure.

The most persuasive evidence is not one historically famous pair of windows. It is coherent behavior across nearby filters, later samples, and realistic decision timing.

Why moving-average systems disappoint

  • Repeated crossings in a narrow range create whipsaw losses.
  • Faster filters can turn small price noise into expensive position changes.
  • Slow filters surrender part of both the beginning and end of a move.
  • Corporate-action errors or incorrect futures rolls can create false crosses.
  • A close-based signal cannot assume an execution before that close is known.
  • Changing simple to exponential weighting is a different rule, not a cosmetic chart setting.

Try it in Arizmic

Strategy composition

Build the premise with shipped signals

Turn moving averages into an explicit rule by deciding whether the strategy responds to a crossing event or an ongoing state, then add a separate filter for trend quality or volatility. The recipes make lag and whipsaw visible instead of treating the line itself as a trade.

These are starting structures, not presets or evidence of an edge. Choose one, replace the bracketed decisions, and keep the signal roles separate as you test it.

Composition 01

Crossover with directional-strength confirmation

Event-driven recipe
  • Moving-Average CrossTransition trigger
  • ADX/DMIWhipsaw filter
  • Wilder ATRRisk distance

Data: OHLCV Bars

View configuration and complete rule

Moving-Average Cross

Transition trigger

Moving-Average Cross exposes both the persistent spread and the exact bars where its sign changes.

Configure

fast_window · [fast window]
Control short-horizon responsiveness.
slow_window · [slow window]
Define the slower trend reference.

Use the output

cross_up
Trigger a candidate long only when cross_up is true.
cross_down
Trigger a candidate short or long exit only when cross_down is true.
spread
Require [spread buffer] if the design needs confirmation beyond a zero crossing.

ADX/DMI

Whipsaw filter

ADX/DMI can reject crosses that occur without meaningful directional strength and can verify that the direction agrees with the proposed side.

Configure

window · [ADX window]
Measure strength over a horizon distinct from the fast average.

Use the output

adx
Require ADX at or above [minimum strength].
plus_di
For a long, require +DI above -DI.
minus_di
For a short, require -DI above +DI.

Wilder ATR

Risk distance

ATR supplies a volatility-aware risk distance without changing the crossover’s direction.

Configure

window · [ATR window]
Estimate current movement at the intended holding scale.

Use the output

atr
Use [ATR multiple] times ATR for the initial risk distance and unit sizing.

Assemble the rule

Entry
After bar completion, take a fresh cross only when ADX and DMI confirm the proposed direction.
Exit
Exit on the opposite cross, [ATR protection rule], or [maximum holding rule].
Decision time
The crossing event belongs to the completed bar; any order decision starts on the next eligible event.
Sizing
Derive units from the ATR risk distance and [risk budget], with a hard exposure cap.

Useful variations

  • Compare an immediate cross with one- and two-bar spread confirmation.
  • Remove the ADX gate to measure the trade-off between lower turnover and missed early trends.
  • Test nearby fast/slow pairs while holding the ratio between windows approximately stable.

Keep in view

ADX confirmation adds delay to an already lagging rule. It may improve apparent outcomes simply by skipping trades, so compare like-for-like exposure and trade opportunity.

Composition 02

Persistent EMA state with slope and volatility regime

State-driven recipe
  • EMADirectional state
  • Moving-Average SlopeDirection-quality check
  • Volatility RegimeRisk-state gate

Data: OHLCV Bars

View configuration and complete rule

EMA

Directional state

The EMA spread stays positive or negative between crossings, which makes it suitable for a persistent exposure rule.

Configure

fast_window · [fast EMA window]
Set the responsive trend estimate.
slow_window · [slow EMA window]
Set the broader reference and keep it above the fast window.

Use the output

spread
Hold long while spread is above [positive buffer], short while below [negative buffer], and otherwise flat.

Moving-Average Slope

Direction-quality check

Slope checks whether the smoothed level is actually rising or falling rather than merely remaining on one side after an old crossover.

Configure

window · [slope average window]
Choose which trend level is being differentiated.
slope_lookback · [slope comparison span]
Control how much change is required before the slope is meaningful.

Use the output

slope
Require slope above [positive threshold] for long or below [negative threshold] for short.

Volatility Regime

Risk-state gate

Volatility Regime can keep the persistent trend rule out of states where the declared execution and risk assumptions no longer apply.

Configure

high_z_threshold · [high-volatility threshold]
Define the state in which exposure is reduced or blocked.
low_z_threshold · [low-volatility threshold]
Define the low-volatility state separately from normal conditions.

Use the output

volatility_regime
Apply [normal/low/high regime policy] without using the regime label as direction.

Assemble the rule

Entry
Enter when the EMA spread and slope agree and the volatility state is eligible.
Exit
Exit when spread returns inside the neutral buffer, slope loses agreement, or the volatility policy forces de-risking.
Decision time
Evaluate state only on completed bars and apply any change at the next permitted decision event.
Sizing
Use [fixed or volatility-aware sizing] with the same cap across every window comparison.

Useful variations

  • Compare zero-spread state with a symmetric neutral buffer.
  • Require slope agreement at entry only versus throughout the position.
  • Treat high volatility as flat in one variant and reduced size in another.

Keep in view

EMA spread and moving-average slope are related transformations of the same prices. Agreement can reduce noise, but it is not independent evidence and may increase lag materially.

Ask the AI Companion

Draft this strategy

Strategy draft

Turn a moving-average crossover idea into a simple draft with each choice explained in ordinary language.

I want to use moving averages to trade meaningful changes in direction in [instrument]. Recommend a sensible starting setup, including the type of moving-average rule, the timeframe, and how responsive the averages should be, and then build that strategy for me. Include appropriate filtering and risk controls, and explain how your design balances responding to a new trend against reacting to ordinary price noise.

Extend it in Marimo

Study review

Begin from a retained Study so crossover candidates and parameter neighborhoods remain traceable.

Show how event-driven and state-driven moving-average rules trade off lag, state duration, and clustered whipsaw.

Bring in
engine-reported averages, spreads, crossing flags, ADX/DMI, slope, ATR, and volatility state, decision and fill timestamps, positions, turnover, costs, and candidate identifiers
Build
price-and-average chart with decision-time cross markers, spread, slope, and strength alignment timeline, whipsaw-cluster table with state duration, turnover, and net outcomes

Interpretation: Inspect whether a slower or more filtered rule genuinely handles ranges better or merely trades less and enters later. Compare exposure time as well as return statistics.

Value origin: Averages, signal outputs, orders, fills, costs, and retained results are engine-reported. Whipsaw clusters, lag intervals, and custom state-duration summaries are notebook-derived.

With Companion: Ask Companion for a reviewed cell set that preserves event timestamps and compares the displayed recipes, then inspect and explicitly apply the diff.

Further reading