Skip to content
← Engine v1

More portfolios and a backtest farm

1.2 · 28 Jul – 3 Aug · More portfolios and a backtest farm · see 1.8, the latest update

Update 1.2 added six portfolios, 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 · 1.2 · 28 July – 3 August 2026

Corporate actions and a backtest farm

The portfolios only trade 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 snapshotpaper ledgerfills · dividendsscreentrend screen + rankreconcilefatal if scale breaks3SCALE SOUNDpaper portfolios16 + 1 manualNEXT OPENfilldividends first4Monday experiment40 Mondays, frozen5backtest farmsame code, old barsreportscommitted to gitSOURCESSTOREDECIDEPROVE
fig. 1 — 1.2. ① 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 portfolio'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 portfolios 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 trading days. With thousands of rows per day, the mean-reversion portfolio's ten-day time stop fired after a single trading day. On the results table that looked like a weak strategy, not a bug. It now counts distinct dates.

Replaying the portfolios

The farm replays each portfolio'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 nightly run does. The first grid of 78 jobs drained the same day without a failure, and its answer was blunt: no stock-picking portfolio 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 portfolio has to beat an equal-weight basket of the same names, over years, before I treat it as more than noise. Update 1.2 closed with seven clean nightly runs 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
portfolios
16 with fixed rules + 1 manual
new portfolios
turtle breakout · stopped momentum · sector momentum · low vol · 52-week high · post-earnings drift
checks
actions fetch warns · reconcile stops the night
first reconcile
36 splits adjudicated · 1,839 dividends stored
backtest grid
78 jobs, drained the same day
exit
seven clean nightly runs, 24 July – 3 August

Ong Jun Xiong

SOFTWARE ENGINEER · SINGAPORE

ContactHobbiesArchiveNotesUI PackGitHubLinkedInSource

© 2026 Ong Jun Xiong