Testing Popular Ideas · Lesson 2
Moving-average crosses
The easiest popular idea to code, and the 60 versions of it (one full set of choices each) hiding inside.
Know the basics? Read the lesson notesAn average that moves
Each dot is one day's close (its last price) in a simulated market. The prices are made up, with no pattern: each day's move is random, with a slow tendency to rise (its drift). A 5-day moving average is the average of the last 5 closes. Each day the oldest drops out and the newest comes in, so the average moves. Slide to the last day.
30 days of closes and their 5-day average (simulated)
Shaded: the 5 days being averaged. Orange: the average so far.
Last day: (99.20 + 99.33 + 100.03 + 100.46 + 99.62) ÷ 5 = 498.64 ÷ 5 = 99.73. It is smoother than the price: each jump is shared with four other days.
How long, and what kind
A moving average has a length, n: how many days it averages. Longer is smoother but later: a 50-day average turns well after the price does. That delay is its lag: about (n − 1) ÷ 2 days for a plain average (the middle of its window): 24.5 days for 50.
It also has a kind. The plain average is the simple moving average, SMA for short: every day counts the same. The exponential moving average, EMA, counts the newest close most and older ones less, so a jump moves it more. Try a length of 200, then 50, then switch to EMA.
One year of closes and one moving average (simulated)
Grey: the close. Orange: the moving average.
Longer means smoother and later; the EMA hugs the newest prices a little more. Both settings must be chosen before a rule exists.
The cross
The rule uses two averages: a fast one (here 20 days) and a slow one (here 50). When the fast one crosses above the slow one, buy. When it crosses back below, sell and wait.
Why: fast above slow means recent prices are higher than the longer stretch's, a sign of a rise, so the rule bets it continues. Fast below slow: the rule steps out.
Owning the market is being long; owning nothing, flat. It never goes short (selling what you don't own, betting on a fall). Press play.
20-day and 50-day SMAs, one year (simulated)
Orange: fast. Dotted: slow. Shaded: long (from day one, as fast starts above slow). Bottom: fast minus slow. A different stretch of the market from the last card's. Vertical lines: crosses (orange buy, black sell).
4 crosses: 2 buys and 2 sells, each a day fast minus slow passes through zero. Both averages lag, so a cross comes after the price has turned.
When does the rule trade?
A backtest runs a rule over past prices. It has to say what price each trade gets, its fill: the close that made the signal (the cross that says buy or sell), or the next day's open, the first price when trading restarts. The cross is only known once today's close is in the average. Which price can a trader actually get after that?
How many versions?
Coding "the moving-average cross" means picking the kind (SMA or EMA), two lengths and the fill (same close or next open). Each set of picks is a version. Take six common lengths: 5, 10, 20, 50, 100 and 200 days. Any two make a pair, the shorter one fast. How many versions is that?
Run one version
One version runs on the simulated market from late 2015 to the end of 2021 (6.2 years: the years we use to choose a version, with 2022–2024 kept unused for later), against holding: buying on day one and never selling. Results are in % a year: the steady yearly growth giving the same total. No costs yet. The figure can show any of the 15 pairs. Try three versions.
One version against holding, 2015–2021 (simulated)
Account from 100. Flat stretches: out of the market, in cash. Dotted: holding.
–
This market rises over time (holding grew 6.3% a year). A version that sits out part of the time usually misses some of that rise; the next screen shows how often.
All 60 at once
All 60 versions, same six years, no costs. How many beat holding? Remember that sitting out part of a rising market usually costs. Guess, then show them.
60 versions: % a year minus holding's (simulated)
One bar per version, best on the left. Above the line: beat holding.
That looks like a find. But each day's move here doesn't depend on past prices, so a rule can only be in or out of the rise, never predict it. Try 60 versions and one will suit these six years by chance, so the best one's lead is mostly luck (lesson B7, The best of many).
For the precise
The best made 9.46% a year against holding's 6.32%: 3.14 points more. Second, +2.89: the same pair filled at the same close, so here the shortcut fill came out slightly worse.Add the bill
Every buy and sell costs something (lesson A16, Costs). Here: 0.1% on every buy and on every sell (for the gap between buying and selling prices, the broker's fee, and the price slipping as you trade), each trade using the whole account. Turn costs on.
The same 60 versions, after costs (simulated)
Same order as before: best before costs on the left. Dark ticks: before costs.
The best version makes about 26 trades a year (13 buys, 13 sells). 26 trades × 0.1% ≈ 2.6% a year off its growth (exactly, 2.8 points; the working is in Theory). Its lead falls from 3.1% a year to about 0.3%. The only other version still ahead is the same pair with the other fill: one idea, not two.
For the precise
The lead is 3.14 before costs and 3.14 − 2.83 + 0.02 = 0.33 after: costs take 2.83 off its growth and 0.02 off holding's, for its one buy.Years it never saw
We kept 2022–2024 aside, unused. Running the chosen version once on such years, charging the same costs, is a held-out test. Pick one of the five best after costs, then run it.
The five best after costs, then three held-out years (simulated)
Tiles: lead over holding, 2015–2021. Lines are numbered like the tiles (orange: your pick; dotted: holding).
Holding rose 32% in 2022 alone, then stayed about level, and none of the five kept up. Part of that is the rise itself: a rule that sits out part of a climbing market trails holding. The sign of luck is the rank: the best of 60 on the years used to choose came 47th of 60 on years it never saw. One three-year window can't settle it alone, and this is our coded rule on a simulated market; a real market needs its own test.
For the precise
12 of the 60 versions beat holding on 2022–2024, after costs. All 12 had trailed holding on 2015–2021, where they ranked 11th to 58th.The two moving averages
The simple moving average is the average of the last n closes. The exponential moving average is a running average: each day it moves a fixed share α of the way from its old value to the new close. The newest close weighs α, the one before α(1 − α), then α(1 − α)²: shrinking by the same factor each day, hence "exponential".
Why α = 2 ÷ (n + 1)? It makes the EMA's prices as old, on average, as an n-day SMA's, (n − 1) ÷ 2 days, though it reacts faster to a jump.
- Ct
- the close on day t; Ct−1 the day before
- n
- the length, in days
- α
- the newest close's share in the EMA (the Greek letter alpha)
- EMAt−1
- yesterday's EMA; the very first one is the SMA of the first n closes
SMA, n = 5: 498.64 ÷ 5 = 99.73.
EMA, n = 5: α = 2 ÷ 6 = ⅓. Yesterday's EMA, carried forward from the earlier days the same way, was 99.997; today's close is 99.62: ⅓ × 99.62 + ⅔ × 99.997 = 33.207 + 66.665 = 99.87.
- the closes are clean, in order, none missing;
- the EMA has run a few times n days, so its starting value no longer matters.
Bad or missing prices feed straight into the average (lesson B4, Data quality).
Try it. A 9-day EMA was 50 yesterday, and today's close is 55. What is today's 9-day EMA?
Crosses, versions and % a year
Write fast − slow as d. The rule is long when d is above zero and flat otherwise; a crossover is a day d passes through zero. Each average lags: in a steady trend (prices moving by the same amount each day), an n-day SMA equals the price (n − 1) ÷ 2 days ago, the middle of its window. So crosses come after the turn.
Choices multiply into versions, and % a year turns a total into steady yearly growth.
- dt
- fast average minus slow average on day t
- ≤, ≈
- "equal to or below"; "about"
- k
- how many lengths you choose from
- end, start
- the account at the end and the start; years is the test's length
Cross: yesterday d = −0.3, today +0.2: buy. Lag of a 20-day SMA: (20 − 1) ÷ 2 = 9.5 days.
Versions: 6 lengths make 6 × 5 ÷ 2 = 15 pairs; 2 kinds × 15 × 2 fills = 60 (long only, so direction adds no choice).
% a year: 100 grows to 140 in 4 years: 1.40.25 − 1 ≈ 8.8% a year. The power 0.25 is 1 ÷ 4 years; a calculator's xy key does it.
Cost bill: 26 trades × 0.1% ≈ 2.6% a year is the rough size. Exactly: each trade multiplies the account by 1 − 0.1% = 0.999, and the best version made 26.17 trades a year, so a year of costs multiplies it by 0.99926.17 = 0.97416. It grew 9.46% a year before costs, so after them: 1.0946 × 0.97416 − 1 = 6.63%. Costs take 9.46 − 6.63 = 2.83, about 2.8 points off yearly growth.
- the lag formula: prices move in a steady trend.
Prices jump around: the averages can cross back and forth within weeks, each cross a trade that pays costs.
Try it. In a steady trend, how many days does a 41-day SMA lag behind the price?
What this means for your test
Lesson E1's checklist, on a real idea. One at a time:
- Write the exact rule first.
Name the kind, both lengths, the fill, long only or not, and the cost per trade.
- Count every version, charge every trade.
60 versions here; on a market with no pattern, like this one, the best of 60 is mostly luck. A busy version pays the bill often.
- Beat holding, then hold out years.
On a rising market, a rule that sits out must beat holding. Then run your one chosen version, once, on unused years.
A friend's spreadsheet
What should it be?
Hint: only the last 3 closes count.
"We tested it thoroughly"
How many versions is that?
Hint: every fast length is shorter than every slow one. Multiply the choices.
Its yearly growth
What is that in % a year?
Hint: (121 ÷ 100)1 ÷ 2 − 1. A power of ½ is a square root.
The course's best version
Which question tells you the most?
Lesson done
A moving average is the average of the last n closes; a cross is the day a fast one passes a slow one. Every choice multiplies the versions: 60 here. On a simulated market with no pattern to find, the best of 60 shrank after costs and came 47th of 60 on years it never saw. That is one simulated market; a real one needs its own test.
Key ideas
- SMA
- the average of the last n closes
- EMA
- a running average that moves a share α of the way to each new close
- Lag
- how far an average trails the price
- Crossover
- a day fast minus slow passes through zero: up buys, down sells
- Version
- one full set of choices, tested separately
Formulas
EMAt = αCt + (1 − α) EMAt−1, α = 2 ÷ (n + 1) · lag ≈ (n − 1) ÷ 2
pairs = k(k − 1) ÷ 2 · % a year = (end ÷ start)1 ÷ years − 1