Moving Averages: SMA and EMA
Two lines, one question: when you put a simple and an exponential moving average of the same length on the same chart, what exactly are you looking at when they differ? This lesson answers that, gives you the AmiBroker syntax that catches most beginners out, and shows the one experiment that makes the difference between the two visible rather than theoretical.
What a moving average measures
Section titled “What a moving average measures”A simple moving average over n bars is the arithmetic mean of the last n values. Nothing
more. At every bar it adds the newest value, drops the value that fell out of the window, and
divides by n. Each of the n bars carries exactly the same weight, 1/n, and every bar
older than the window carries a weight of zero.
An exponential moving average never drops anything. It is recursive: each new value is a
blend of the current bar and the previous output. AmiBroker documents this shape explicitly
on the AMA page, where the adaptive average is defined as
output[i] = factor[i] * input[i] + ( 1 - factor[i] ) * output[i-1], and its own example uses
2 / ( n + 1 ) as the factor — the standard exponential smoothing constant. Because the
previous output already contains a fraction of the output before it, every bar the average
has ever seen still contributes something. The contribution just decays geometrically.
The weight each past bar carries, for a 5-bar window
| Bar | now | 1 back | 2 back | 3 back | 4 back | 5 back | 10 back |
|---|---|---|---|---|---|---|---|
Simple average | 0.20 | 0.20 | 0.20 | 0.20 | 0.20 | 0.00 | 0.00 |
Weighted average | 0.33 | 0.27 | 0.20 | 0.13 | 0.07 | 0.00 | 0.00 |
Exponential average | 0.33 | 0.22 | 0.15 | 0.10 | 0.07 | 0.04 | 0.01 |
Three things follow directly from that table, and they are the whole of the practical difference.
The simple average has a hard edge. A single extreme bar affects the line identically for n
bars and then vanishes from it completely, which produces a visible jolt on the day the
extreme bar leaves the window — a movement in the line caused by something that happened n
bars ago, not by today.
The exponential average has no edge. Old data fades rather than falling off, so there is no drop-out jolt, but there is also no point at which you can say “this line no longer knows about that crash”.
And for the same nominal period, the exponential average puts more weight on the newest bars, so it responds sooner. Sooner is not the same as better. It responds sooner to noise as well.
How traders commonly read them
Section titled “How traders commonly read them”The three standard readings, stated as what people say rather than as findings:
- Direction. A rising average is read as an uptrend, a falling one as a downtrend.
- Position. Price above the average is read as strength, below as weakness.
- Crossings. Price crossing the average, or a fast average crossing a slow one, is read as a change of state. That is the subject of the next lesson.
Notice that the first two are close to being definitions rather than claims. If “uptrend” means “the 200-bar average is rising”, then saying “the trend is up because the 200-bar average is rising” tells you nothing you did not already say. It becomes a claim only when you attach something to it — that returns after such bars differ from returns after other bars, for instance — and then it becomes testable.
Common misuse
Section titled “Common misuse”Switching to EMA because it is “faster”. It is faster in exactly the sense that a shorter simple average is faster, and it pays the same price: more turns, more of which reverse. If you want a faster line you have two dials — length and weighting — and both cost the same currency.
Comparing average values between instruments. A moving average is in the units of its input. “The average is 148” is meaningless across symbols. The distance from price to the average, divided by price or by ATR, is comparable. The raw level is not.
Judging an average on the left edge of the chart. More on this in a moment; it is important enough to have its own section.
Reading a crossover on a chart of an instrument you chose because the crossover worked. This is the most common one and the hardest to see in yourself. Part 30 gives it its proper name, selection bias.
Limitations built into the construction
Section titled “Limitations built into the construction”A moving average cannot distinguish a genuine directional move from a slow drift with noise on top, because both produce a sloping line. It cannot tell you anything about the quality of a move — participation, volatility, whether the move is happening in one gap or over thirty bars — because it only ever sees one number per bar.
And it produces a line during a sideways range that looks exactly like a trend line during a trend, only shorter. The eye reads the shape; the arithmetic makes no such distinction.
One average, two regimes
- Close
- MA(Close, 20)
Notice what the average does not do at bar 41. It does not signal the change. It cannot: it is an average of the last twenty closes, and twenty bars after the regime changed it is still partly made of the old one. The flattening you can see is a description of a change that finished happening some time ago.
Warm-up, Null and the exponential seed
Section titled “Warm-up, Null and the exponential seed”AmiBroker documents MA()’s warm-up precisely, and the official tutorial shows it: for
MA( Close, 3 ) the first two bars are Null, and the first number appears on the third bar.
In general a periods-bar simple average is Null for the first periods - 1 bars, and
those Nulls propagate — the same tutorial shows Buy = Cond1 AND Cond2 inheriting them.
The exponential average is trickier, and this is where numbers stop matching between
platforms. AmiBroker’s author states on the EMA page that EMA is initialised from a
simple moving average of the same length, deliberately, to match another package’s output.
So the recursion does not start from the first close; it starts from an SMA value at bar n,
and every value afterwards carries a fading memory of that seed.
The DEMA page states the practical consequence in a form you can measure: a hand-built
2 * EMA( C, len ) - EMA( EMA( C, len ), len ) and the built-in DEMA( C, len ) do not
converge until roughly 2 * len bars after the EMA-based curve starts — about 6 * len bars
from the beginning of the data.
Displaying a moving average in AmiBroker
Section titled “Displaying a moving average in AmiBroker”There are two routes, and it is worth doing both once.
Without writing code. Open Window -> Charts, find the moving average entry in the tree,
and double-click it. AmiBroker inserts a new pane and opens the Parameters dialog for the
indicator you just added. To put the average on top of the price instead, drag its name
from the Charts tree onto the price pane rather than double-clicking.
The Parameters dialog is where you set the period, the price field, the colour and the style.
You reach it later with a right-click on the pane, or Ctrl+R. AmiBroker stores those values
per chart pane, which is why the same formula can look different in two panes.
By applying a formula. Open Analysis -> Formula Editor, paste the code, type a name into
the Formula Name field, and press Apply Indicator. The toolbar button is Check syntax;
the same action is Tools -> Verify syntax on the menu, which is worth knowing because
searching the menus for “Check syntax” finds nothing.
Writing them in AFL
Section titled “Writing them in AFL”Both functions take the array and the period, and neither has a documented default:
Fragment — not a complete formula
Fast = MA( Close, 20 ); // simple average of the last 20 closesSlow = EMA( Close, 50 ); // exponential average, period 50VolAvg = MA( Volume, 50 ); // any array, not just priceTwo more documented details worth carrying:
MA accepts a time-variant period — the second argument may itself be an array, so the
window can change bar by bar. The EMA page makes no such statement, so do not assume it;
for a smoothing factor that varies per bar, AMA is the documented tool.
ma, rsi and cci are function names, and AmiBroker’s language reference states that user
identifiers cannot duplicate them. ma = MA( Close, 20 ); will not compile. Name your
variables after what they mean instead — Trend, FastAvg, VolumeBaseline.
A formula that makes the difference visible
Section titled “A formula that makes the difference visible”Reading about weighting schemes is not the same as watching one line pull away from another. This formula puts a simple and an exponential average of the same length on the chart, plus the gap between them as a percentage of price.
Complete runnable AFL
// ma-response-comparison.afl// Part 6 - Moving Averages: SMA and EMA//// Draws price with a simple and an exponential moving average of the SAME// length, plus the gap between them, so that the only thing you are looking at// is the effect of the weighting scheme.//// Assumptions declared up front:// - Daily bars on a liquid instrument with several years of history.// - MA() returns Null for the first MaPeriod-1 bars, and EMA() is seeded from// a simple average at bar MaPeriod, so the far left of the chart is// warm-up and tells you nothing. Scroll away from it before judging.// - Both averages are taken on Close. Changing the input changes the meaning// of everything below.
_SECTION_BEGIN( "SMA vs EMA" );
// One period drives BOTH averages on purpose. Comparing a 20-bar SMA against a// 50-bar EMA would only tell you about length, which is not the question here.MaPeriod = Param( "Averaging period", 20, 2, 200, 1 );
// MA() and EMA() each require the array AND the period. Neither has a// documented default, so MA( 20 ) is an error rather than a 20-bar average.SimpleAvg = MA( Close, MaPeriod );ExpAvg = EMA( Close, MaPeriod );
// The gap between the two averages, expressed as a percentage of price so it// stays readable when the price level changes over the years. The gap widens// only when the newest bars in the window differ from the older ones.GapPercent = 100 * ( ExpAvg - SimpleAvg ) / Close;
Plot( Close, "Close", colorDefault, styleCandle );Plot( SimpleAvg, "SMA(" + MaPeriod + ")", colorBlue, styleLine | styleThick );Plot( ExpAvg, "EMA(" + MaPeriod + ")", colorRed, styleLine | styleThick );
// Drawn on its own scale so it cannot squash the price axis. The documented// minvalue / maxvalue arguments apply to styleOwnScale plots only, which is// exactly what this is.Plot( GapPercent, "EMA - SMA (% of close)", colorGrey40, styleLine | styleOwnScale | styleNoLabel, -10, 10 );
_SECTION_END();How it works. One Param drives both averages, which is the entire design decision: if
the two averages had different lengths, any difference you saw would be a difference of
length and would tell you nothing about weighting. The two averages are computed with MA
and EMA on Close. The gap is expressed as a percentage of the closing price so that it
stays readable when the price level changes by a factor of ten over a decade. The gap is
drawn with styleOwnScale, whose documented minvalue and maxvalue arguments — the fifth
and sixth arguments of Plot — are the only place those two arguments do anything.
Expected result. A candlestick chart with a blue simple average, a red exponential average, and a thin grey line near the bottom. In a quiet, directionless stretch the two averages sit almost on top of each other and the grey line hugs zero. When a sustained move begins, the red line separates from the blue one in the direction of the move, and the grey line pushes away from zero. When the move ends, the red line crosses back through the blue one before the blue one has finished turning.
Test it. Set the period to 2. Both averages should now sit almost on the price bars, and the gap should be tiny — with a two-bar window there is barely any weighting to differ about. Then set it to 200 and scroll to the start of the symbol’s history: the blue line should be absent for the first 199 bars while the red line, seeded from a simple average, appears around bar 200 and then drifts as the seed washes out. Both behaviours are what the documentation says should happen, which is a reasonable check that you are reading the chart correctly.
Common errors. If you get “Error 5: too few arguments”, you have written MA( 20 )
somewhere. If both lines look identical at every period, check that you passed the same
MaPeriod variable to both and did not hard-code a number in one of them. If the grey line
flattens the price bars into a stripe, the styleOwnScale flag has been lost from the last
Plot call.
Extension. Add a third average using WMA( Close, MaPeriod ), which AmiBroker documents
as giving weight n to the newest bar, n-1 to the one before, down to 1. It should sit
between the other two most of the time. Predict where it will sit before you plot it, then
check whether you were right.
Turning this into a testable question
Section titled “Turning this into a testable question”“Price above the 200-day average means the trend is up” is a definition. Here is a version that could be false:
Over the last fifteen years, on the symbols in my watch list, the distribution of 20-day forward returns measured on bars where the close was above its 200-day simple average differs materially from the distribution measured on all other bars.
That statement names a universe, a period, a condition, a measurement and a horizon. It can come out either way. It still has serious problems — the watch list is probably made of survivors, fifteen years is one sample of market history, and “materially” needs a number — and those problems are exactly what the final lesson of this part is about. Do not build the test yet. Notice instead how much had to be specified before the sentence became checkable at all.
A simple moving average weights the last n bars equally and everything else at zero; an
exponential average weights the newest bar most and never quite forgets anything. That single
difference produces everything else: the drop-out jolt in one, the seed sensitivity in the
other, the earlier response of the exponential line and the extra turns that come with it.
In AmiBroker both functions require the array and the period, MA is Null for the first
periods - 1 bars, and EMA is seeded from a simple average, so the early part of any
recursive line is contaminated for far longer than its nominal period.
Check your understanding
Sources for this lesson
8 verified · checked 2026-08-31
- 01AFL Function Reference — MAamibroker.com/guide/afl/ma.html2026-08-31
- 02AFL Function Reference — EMA§ Author comment on initialisationamibroker.com/guide/afl/ema.html2026-08-31
- 03AFL Function Reference — WMAamibroker.com/guide/afl/wma.html2026-08-31
- 04AFL Function Reference — DEMA§ Convergence with an EMA-composed equivalentamibroker.com/guide/afl/dema.html2026-08-31
- 05AFL Function Reference — AMAamibroker.com/guide/afl/ama.html2026-08-31
- 06AFL Function Reference — Plotamibroker.com/guide/afl/plot.html2026-08-31
- 07AmiBroker User's Guide — Understanding how AFL language worksamibroker.com/guide/h_understandafl.html2026-08-31
- 08AmiBroker User's Guide — Creating indicators by drag-and-dropamibroker.com/guide/h_dragdrop.html2026-08-31
Every technical claim on this page was checked against the official AmiBroker documentation on the date shown. Where the course disagrees with folklore, the source is how you can tell which one to trust.