Skip to content
← Trading engine

More books and a backtest farm

v2 · 28 Jul – 3 Aug · More books and a backtest farm · see v6, the current engine →

v2 added six books, but the change that mattered was finding out the price history was wrong. Yahoo rewrites old prices after a split, the engine only re-fetched the last five days, and dividends were never stored.

Figure 01 · v2 · 28 July – 3 August 2026

Corporate actions and a backtest farm

The league only trades once the split and dividend reconcile passes.

  • Data
  • Orders
  • Next-open fill
  • Evidence
Yahoo barsdaily pricesYahoo actionssplits · dividendsNasdaq Tradersymbol list1STOOQ: STILL BLOCKEDDUCKDB · ONE WRITER2pricesrestated cachecorporate actionswatermarkeduniversedaily snapshotsim ledgerfills · dividendsscreenMinervini + RS rankreconcilefatal if scale breaks3SCALE SOUNDpaper league16 books + discretionaryOPEN T+1filldividends first4E1 experiment40 Mondays, frozen5backtest farmsame code, old barsreportscommitted to gitSOURCESSTOREDECIDEPROVE
fig. 1 — v2. ① Yahoo now supplies splits and dividends alongside bars. ② Prices are stored as a restated cache with a watermark. ③ A reconcile stage checks the price scale and stops the night if it is broken. ④ Dividends are credited before fills. ⑤ A forward experiment logs Monday returns, and the backtest farm replays each book's own code over past years.

What splits and missing dividends did

A five-day refetch leaves a permanent break in the series after a split, so books holding that stock showed crashes that never happened. Missing dividends were quieter. Dual momentum's cash hurdle is a Treasury-bill ETF, and without dividends it had become “beat zero”. On total return that ETF made +3.72% over twelve months against −0.09% on price alone, and EFA moved ahead of SPY, +18.19% to +17.47%.

The rules I wrote down

Prices are a cache of Yahoo's adjusted view, restated at the break found in the stored series. Fills are adjusted at the ex-date, because a fill before it really did execute at pre-split prices. Portfolio state is a pure function of fills and dividends, with dividends replayed first. Fetching new actions only warns, but the reconcile stage is fatal. The log puts the reason better than I can: “trading on a broken scale is strictly worse than skipping a night.”

A ten-day stop that fired after one

trading_days_between counted price rows instead of sessions. With thousands of rows per day, the mean-reversion book's ten-day time stop fired after a single session. On the league table that looked like a weak strategy, not a bug. It now counts distinct dates.

Replaying the books

The farm replays each book's live code over past windows on scratch copies of the store, so the live database stays read-only. Only the screen is vectorised for speed; the strategies run exactly as the league runs them. The first grid of 78 jobs drained the same day without a failure, and its answer was blunt: no stock-picking book beat its own equal-weight benchmark over any window of three years or more. The sample leans toward survivors, with 1,237 eligible names in 2011 against 3,873 today, and that caveat never went away.

That result set the bar for everything after it. A stock-picking book has to beat an equal-weight basket of the same names, over years, before I treat it as more than noise. v2 closed with seven clean nightlies in a row, from 24 July to 3 August.

dates
28 July – 3 August 2026
new data
Yahoo splits and dividends · 409,684 action rows
books
16 pre-registered + 1 discretionary
new books
turtle breakout · stopped momentum · sector momentum · low vol · 52-week high · PEAD
gate
actions fetch warns · reconcile is fatal
first reconcile
36 splits adjudicated · 1,839 dividends stored
backtest grid
78 jobs, drained the same day
exit
seven clean nightlies, 24 July – 3 August

Ong Jun Xiong

SOFTWARE ENGINEER · SINGAPORE

ContactHobbiesArchiveNotesUI PackGitHubLinkedInSource

© 2026 Ong Jun Xiong