Quant from Scratch by QuantWright

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 notes

An 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.

The 5 closes–
Their average–

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.

Length (days)
Kind
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).

Day–
Fast − slow–
The rule is–
Crosses so far0

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?

The close isn't known until trading ends, so by the time you see the cross, that price has gone.
Once trading ends you see the cross, and the next open is your next chance to trade.
Nobody knows the day's lowest price until the day is over.
Same close assumes a price you couldn't be sure of getting: a backtest shortcut (lesson B2, Look-ahead bias). We test both; each fill is one more choice to count (next card).

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?

That adds the choices (6 + 2 + 2), but choices multiply.
That's 6 × 2 × 2, but a version needs a pair of lengths.
Each of the 6 lengths pairs with 5 others: 6 × 5 = 30, which counts each pair twice, so 15 pairs. Then 15 pairs × 2 kinds × 2 fills = 60 versions.

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.

Kind
Fast
Slow
Fill

–

This version–
Holding–
Long on–
Trades a year (each buy or sell is one trade)–

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.

Beat holding?
The best?
About the middle (30th of 60)?

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 preciseThe 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.

Costs
The best, against holding–
Its trades a year–
Beat holding–

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 preciseThe 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).

Your pick, 2015–2021–
Your pick, 2022–2024?
Its place of 60 in 2022–2024?

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 precise12 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.
Theory

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.

SMAt = (Ct + Ct−1 + … + Ct−n+1) ÷ n
EMAt = α × Ct + (1 − α) × EMAt−1,   α = 2 ÷ (n + 1)
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
Worked example: your 30 days

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.

Holds when
  • the closes are clean, in order, none missing;
  • the EMA has run a few times n days, so its starting value no longer matters.
Breaks when

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?

α = 2 ÷ 10 = 0.2, so 0.2 × 55 + 0.8 × 50 = 11 + 40 = 51: a fifth of the way from 50 to 55.
α = 2 ÷ (9 + 1) = 0.2, so 0.2 × 55 + 0.8 × 50 = 11 + 40 = 51: it moves only a fifth of the way from 50 to 55.
Theory

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 = fastt − slowt
position after day t's close = long if dt > 0, else flat
cross up: dt−1 ≤ 0 and dt > 0; cross down: dt−1 > 0 and dt ≤ 0
lag of an n-day average ≈ (n − 1) ÷ 2 days
versions = choices × choices × …
pairs = k × (k − 1) ÷ 2
% a year, g: (1 + g)years = end ÷ start, so g = (end ÷ start)1 ÷ years − 1
the rule's gain on a day = the market's % change that day if the rule was already long, 0 if flat; around a trade, only the part after the fill counts (same close: from that close; next open: from the next day's open)
cost bill a year ≈ trades a year × cost per trade
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
Worked example

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.

Holds when
  • the lag formula: prices move in a steady trend.
Breaks when

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?

(41 − 1) ÷ 2 = 20 days: the middle of a 41-day window.
(41 − 1) ÷ 2 = 20 days: in a steady trend the average equals the middle close, 20 days back.

What this means for your test

Lesson E1's checklist, on a real idea. One at a time:

  1. Write the exact rule first.

    Name the kind, both lengths, the fill, long only or not, and the cost per trade.

Practice 1 of 4

A friend's spreadsheet

The situationCloses from Monday to Friday: 20, 22, 21, 24, 27. A friend's sheet says Friday's 3-day SMA is 22.8.

What should it be?

Hint: only the last 3 closes count.

(21 + 24 + 27) ÷ 3 = 72 ÷ 3 = 24.
Only Wednesday to Friday count: (21 + 24 + 27) ÷ 3 = 24.
Their 22.8 averages all five closes: that's the 5-day SMA.
Practice 2 of 4

"We tested it thoroughly"

The situationAn imagined trading course "tested the cross thoroughly": SMA and EMA, fast lengths 5, 8 or 13, slow lengths 21, 34, 55 or 89, long only or long and short.

How many versions is that?

Hint: every fast length is shorter than every slow one. Multiply the choices.

2 kinds × 3 fast × 4 slow × 2 directions = 48.
Choices multiply: 2 × 3 × 4 × 2 = 48.
Practice 3 of 4

Its yearly growth

The situationA friend's version turned 100 into 121 over 2 years.

What is that in % a year?

Hint: (121 ÷ 100)1 ÷ 2 − 1. A power of ½ is a square root.

√1.21 = 1.1, so 1.1 − 1 = 10% a year: 100 → 110 → 121.
√1.21 = 1.1, so 10% a year. Not 10.5% (21 ÷ 2): the second year grows from 110, not 100.
Practice 4 of 4

The course's best version

The situationThe course's best version of the 48 beat holding by 2% a year from 2015 to 2021: before costs, filled at the same close. No later years are shown.

Which question tells you the most?

It's the best of 48, before costs, at a shortcut fill. Only a run with costs on years it never saw shows how much was luck.
Winners can look good while costs and luck explain the result. Ask for a run with costs on years not used to pick it.
Those are the years it was picked on, with the same luck. Ask for a run with costs on years not used to pick it.
✓

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

Lesson notes

A moving-average cross is a rule built from two averages of recent closing prices: buy when the fast one rises above the slow one, sell when it falls back below. Every choice in it multiplies the versions you could test: 60 in the lesson. On the lesson's simulated market, built with no pattern to find, the best of the 60 came 47th of 60 on years it never saw. That is one simulated market; a real one needs its own test.

An average that moves

A day's last price is its close. A simple moving average (SMA) of length n is the average of the last n closes. In the lesson's 30 simulated days, the last five closes were 99.20, 99.33, 100.03, 100.46 and 99.62, so the 5-day SMA was 498.64 ÷ 5 = 99.73.

A longer average is smoother but later. Its lag, how far it trails the price, is about (n − 1) ÷ 2 days in a steady trend (prices moving by the same amount each day): 24.5 days for n = 50. The exponential moving average (EMA) counts the newest close most and older ones less, so a jump moves it more.

The cross

The rule uses a fast average (20 days here) and a slow one (50 days). When the fast one crosses above the slow one, buy; when it crosses back below, sell and wait. Fast above slow means recent prices are higher than the longer stretch's, a sign of a rise, so the rule bets it continues. Owning the market is being long, owning nothing is being flat, and the rule never goes short (selling what you don't own, a bet on a fall). In the lesson's simulated year, the averages crossed 4 times: 2 buys and 2 sells.

Which price does a trade get?

A backtest must say what price each trade gets, its fill. A cross is only known once today's close is in the average, so the fill is either that same close, or the next day's open, the first price when trading restarts. By the time you see the cross, that close has gone. Filling at it assumes a price you couldn't be sure of: a backtest shortcut. The lesson tests both fills, to count each as a choice and to see what the shortcut does.

How many versions?

Coding “the moving-average cross” means choosing the kind (SMA or EMA), two lengths and the fill. Each set of choices is a version. The lesson uses six lengths: 5, 10, 20, 50, 100 and 200 days. Any two make a pair, the shorter one fast. Each length pairs with 5 others: 6 × 5 = 30, which counts each pair twice, so 15 pairs. Then 15 pairs × 2 kinds × 2 fills = 60 versions (long only, so direction adds no choice).

Sixty versions against holding

On the simulated market, the lesson runs each version from late 2015 to the end of 2021 (6.2 years, used to choose a version; 2022 to 2024 kept unused). The comparison is holding: buying on day one, never selling. Results are in % a year, the steady yearly growth giving the same total, with no costs yet. Holding grew 6.3% a year.

In the lesson's simulation, only 2 of the 60 beat holding, and the second is the best one's pair filled at the same close: one idea, not two. The best, a 5-day and a 10-day SMA filled at the next open, grew 9.46% a year against holding's 6.32%: 3.14 percentage points of yearly growth more, about 3.1. But each day's move in this market 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 is likely to suit these six years by chance: its lead is mostly luck (lesson B7).

Add the bill

The lesson charges 0.1% on every buy and every sell, each trade using the whole account. The best version makes about 26 trades a year, each buy or each sell counting as one (exactly 26.17). 26 trades × 0.1% ≈ 2.6% a year off its growth; worked exactly, 2.83 points (the working is in the second formula section). Holding pays 0.1% too, once, for its one buy: 0.02 points off its yearly growth. Its lead falls from 3.14 to 3.14 − 2.83 + 0.02 = 0.33, about 0.3% a year.

Years it never saw

The lesson kept 2022 to 2024 unused. Running a chosen version once on such years, with the same costs, is a held-out test. In the lesson's simulation, holding rose 32% in 2022 alone then stayed about level, and none of the five best versions after costs kept up. Part of that is the rise itself: a rule that sits out part of a climbing market usually trails holding. The sign of luck is the rank: the best of 60 on the years used to choose came 47th of 60, after costs, on the 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.

Formula: the two moving averages

The EMA 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.

SMAt = (Ct + Ct−1 + … + Ct−n+1) ÷ n
EMAt = α × Ct + (1 − α) × EMAt−1,   α = 2 ÷ (n + 1)
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
Worked example: the lesson's 30 days

SMA, n = 5: 498.64 ÷ 5 = 99.73.

EMA, n = 5: α = 2 ÷ 6 = ⅓. Yesterday's EMA, carried forward from the lesson's earlier days the same way, was 99.997; today's close is 99.62: ⅓ × 99.62 + ⅔ × 99.997 = 33.207 + 66.665 = 99.87.

Holds whenBreaks when

Bad or missing prices feed straight into the average (lesson B4, Data quality).

Formula: crosses, versions and % a year

dt = fastt − slowt
position after day t's close = long if dt > 0, else flat
cross up: dt−1 ≤ 0 and dt > 0; cross down: dt−1 > 0 and dt ≤ 0
lag of an n-day average ≈ (n − 1) ÷ 2 days
versions = choices × choices × …
pairs = k × (k − 1) ÷ 2
% a year, g: (1 + g)years = end ÷ start, so g = (end ÷ start)1 ÷ years − 1
the rule's gain on a day = the market's % change that day if the rule was already long, 0 if flat; around a trade, only the part after the fill counts (same close: from that close; next open: from the next day's open)
cost bill a year ≈ trades a year × cost per trade
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
Worked example

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.

Holds whenBreaks when

Prices jump around: the averages can cross back and forth within weeks, each cross a trade that pays costs.

One more worked example

Made-up round numbers

Closes on days 1 to 6: 50, 48, 47, 49, 53, 55. Fast: 2-day SMA. Slow: 4-day SMA, which first exists on day 4.

Day 4: fast (47 + 49) ÷ 2 = 48; slow (50 + 48 + 47 + 49) ÷ 4 = 48.5; d = −0.5: flat.

Day 5: fast (49 + 53) ÷ 2 = 51; slow (48 + 47 + 49 + 53) ÷ 4 = 49.25; d = +1.75. It was ≤ 0 and is now above 0: a cross up. The buy fills at the open of day 6.

Trying the lengths 2, 4, 8 and 16 gives 4 × 3 ÷ 2 = 6 pairs, and 6 × 2 kinds × 2 fills = 24 versions.

Common mistakes

Check yourself

  1. Five closes: 30, 33, 32, 35, 38. What is the 3-day SMA on the last day?
    Answer

    Only the last 3 closes count: (32 + 35 + 38) ÷ 3 = 105 ÷ 3 = 35.

  2. A 9-day EMA was 40 yesterday, and today's close is 45. What is today's 9-day EMA?
    Answer

    α = 2 ÷ (n + 1) = 2 ÷ 10 = 0.2. EMA = 0.2 × 45 + 0.8 × 40 = 9 + 32 = 41.

  3. A test uses SMA and EMA, fast lengths 10 or 20, slow lengths 50, 100 or 200, and both fills, long only. How many versions?
    Answer

    Choices multiply: 2 kinds × 2 fast × 3 slow × 2 fills = 24.

  4. A version turned 100 into 144 in 2 years. What is that in % a year?
    Answer

    (end ÷ start)1 ÷ years − 1 = 1.44½ − 1 = 1.2 − 1 = 0.2, so 20% a year: 100 → 120 → 144.

  5. In the lesson's simulation, the best of 60 versions led holding by 3.14 points a year before costs and came 47th of 60 on years it never saw. What does that suggest, and what does it not settle?
    Answer

    It suggests the lead was mostly luck: each day's move on this market doesn't depend on past prices, so with 60 versions one suits the choosing years by chance. It does not settle it alone: one three-year window on one simulated market is a single check, and a real market needs its own test.

Try it yourself

The rule, written before the code. Two moving averages of the daily close, fast length f shorter than slow length s, the same kind (SMA, or EMA with α = 2 ÷ (n + 1), started from the SMA of the first n closes). At each close, long if fast − slow is above 0, flat otherwise; never short. Fill at that close, or at the next open. 0.1% of the price per buy and per sell, or no costs. Compared with buying at the first test close and holding, which pays 0.1% once.

Run the script. Every number in this lesson comes from one Python script (below) on SimMarket, the course's simulated market. Add a seventh length, or a long-and-short switch, and watch the version count and the best result move.

By hand. In a spreadsheet with closes in column B: the 5-day SMA in C6 is =AVERAGE(B2:B6), copied down. A 5-day EMA in D6 starts as =C6, and D7 is =B7/3+D6*2/3 (α = ⅓), copied down.

Written by QuantWright from the published definitions of the simple and exponential moving averages (the formulas only). No code from TradingView, LuxAlgo or other indicator scripts.

About QuantWright

QuantWright, which publishes this course, sells backtesting software. Its backtests include costs (commission, slippage, next-bar fills), and every result shows its code, data window, data source and costs. Its Honesty Score counts every distinct version your account has tested on that market in the last 30 days, so trying 50 variations does not make the best one look good. A held-out test re-runs the chosen strategy once over years kept out of sight; run it again in the same study and the product says it no longer counts. quantwright.com

The script needs simmarket.py, the course's simulated market, in the same folder.

The code behind every number (Python, SimMarket seed 20261109)
Loading…

Going further: 60 versions aren't 60 separate tries

Lesson B7 counted coins that ignore each other. These 60 versions don't. A version and its twin with the other fill hold the market on almost the same days: their daily results have a correlation of 0.992 (1 would mean they move in lockstep, 0 not at all). The SMA and EMA of the same pair: 0.884. Any two of the 60, on average: 0.722, mostly because every version owns the same market whenever it is long.

So the 60 versions add less luck than 60 coins would, and the best of them is less inflated than the best of 60 coins. Less, not none: the best version (SMA 5 and 10, filled at the next open) still led every other version on the choosing years and came 47th of 60 on the held-out ones, after costs. Corrections built for related versions come in lesson B12 (The Sharpe ratio, and its error bar).

For the preciseMarket: SimMarket Market 1, seed 20261109, effect=False (no planted pattern), daily bars. First decision at the close of 9 Oct 2015 (the 200th day). Choosing years: that close to 31 Dec 2021 (6.23 calendar years); held-out: to 31 Dec 2024 (3.00 years); each version carries its position across 2022. % a year = exp(sum of daily log returns)1 ÷ years − 1, years = calendar days ÷ 365.25; "more than holding" is a difference in percentage points. Fill at the next open: the night before the open earns the old position, the day after it the new one. Costs: a factor (1 − 0.001) per buy or sell on the day the new position starts. Holding: bought at the first test close; after costs it pays 0.1% once, for its one buy (6.32% a year becomes 6.30%). Before costs, 2 of 60 beat holding (median −5.2 points); after costs, 2 of 60 (median −5.5). Best before costs: SMA 5/10 next open, 9.46% a year against holding's 6.32%, 26.2 trades a year, long on 52% of days. After costs on 2022–2024: 0.61% a year against holding's 10.00%, 47th of 60. Correlations: of daily net returns over the choosing years, averaged over the 30 close/open twins, the 30 SMA/EMA twins and all 1,770 pairs.

Honest notes

Where this comes from