Big BotsResearch ← all reports

Momentum Research Log — 2026-06-19

A working log of the session: data-integrity fixes, a parameter sweep, a concentration/attribution check, a reframe of how the strategy will be used, the $5M liquidity rule, and a live shortlist webpage. Honest throughout — some of this is a result that says "not a validated edge", not a win.


0. Context: resumed after a dropped connection

Picked the thread back up by inspecting running processes and recently-modified files rather than guessing. The cross-sectional momentum backtest on the new 2,164-name US universe had completed; nothing was corrupted by the disconnect.

1. Data-integrity fix — the in-progress week

The original run's headline numbers leaned on a partial weekly bar dated 2026-06-21 (a Sunday two days in the future). Underlying daily data only ran through Wed 2026-06-17; the backtest treated that stub as a closed week.

Period PF before PF after Avg trade before after
OOS 2026 0.98 0.89 −0.16% −0.95%
Train 0.97 0.98

Honest read of the default config: profit factor < 1.0 everywhere → no edge after costs. The old +16% OOS headline was a couple of lucky months on top of a losing per-trade average.

2. Operational — DB lock & the cache

big_bots.db kept throwing "database is locked". Cause: exchange_universe.service (the OHLCV scheduler) holds a write lock; SQLite rollback-journal mode blocks even read-only readers during writes. No corruption — just contention.

3. Parameter sweep (momentum_sweep.py) — tuned on TRAIN only

225 configs (lookback × skip × top_n × regime gate), ranked by train profit factor; OOS looked at only afterward. Best-on-train shapes were classic "12-1" momentum (≈52w lookback, skip ≈1 month):

Lookback Skip Pos Gate Train PF Train ret OOS PF OOS ret
52w 4 5 off 3.98 +636% 1.78 +22%
39w 4 5 off 3.55 +566% 1.29 +27%
52w 1 8 breadth>0.6 1.92 +60% 2.74 +26%

138/225 configs beat PF 1.0 on train. But do not trust the absolute numbers — see §4. Full grid: momentum_sweep_results.csv.

4. Attribution (momentum_attribution.py) — the edge is 2–3 names ⚠️

For the low-drawdown config (52w/skip1/8/breadth>0.6) we attributed the equity curve to individual tickers:

The drivers are speculative micro-cap moonshots (quantum, drones, lottery biotech). Conclusion: the result is a handful of explosive winners, not a broad effect. On a survivor-only universe these names are over-represented by construction. Validation cannot correct for this because train and OOS draw from the same survivor universe.

5. Reframe — discretionary use (Jacques' direction)

Jacques: "It is all we have so lets carry on. I am not making an automated tool, I will still vet every trade myself." So: - Stop treating survivorship as a disqualifier; note it once, move on. - The strategy is an idea generator / weekly shortlist, not an automated edge. - Concentration is useful context for manual vetting (which 1–2 names to size). - (Saved to memory: discretionary-manual-vetting.)

6. Liquidity rule — $5M/day floor 🔒

Jacques flagged thin volume on some names. Added average daily dollar volume (ADDV) = mean(close×volume) over 13 weeks / 5. Hard rule: never display any name with ADDV < $5M/day (saved to memory: liquidity-floor-5m). At that floor only a couple of names (e.g. BVC at $0.2M) get cut; most top names are liquid.

7. Live webpage 🌐

momentum_publish.pyhttps://customsmartbots.com/research/momentum_live.html (pinned on the research index). - Top 30 momentum names above the $5M floor, regime banner, 13w trend in green/red, ADDV, last-updated stamp; styled to match existing reports. - Refresh: cron 02:30 SAST (UTC+2), Tue–Sat runs the publisher the morning after each US close (cache refresh → recompute → rewrite); Tue covers Mon's close … Sat covers Fri's. Browser also auto-refreshes hourly. (Was 23:30 Mon–Fri; moved to 02:30 for a safe post-close margin year-round.) - Reads the cache, so it never fights the live DB writer. - Note: page is public (same as existing reports). Can be gated/local-only on request.

Current state (as of this session)

8. Restyle — "Groovy Baby" theme (2026-06-20)

Jacques asked to match the live shortlist page to the Austin Powers theme on the main Big Bots homepage (/var/www/customsmartbots/index.html). - Reworked the generator (momentum_publish.py) only — the cron regenerates the page nightly, so styling lives in the source, not the HTML. CSS + a DECOR block (hypno spiral, rainbow waves, daisies/targets) + bubble-letter HERO ported from the homepage; same plum/cream palette and Bagel Fat One / Nunito / Fredoka / Pacifico / Space Mono fonts. - The data table stays fully legible: background decor runs at low opacity behind a cream "pop-card", positive/negative cells use a darker green/red that reads on cream. Regime banner is now a groovy tilted pill (acid=risk-on, orange=risk-off). - Re-rendered from weekly_cache.pkl (no live-DB touch); page 6.8K→15K, data unchanged (top names BW, CELC, LWLG… , regime RISK-OFF). Honours prefers- reduced-motion. Live: customsmartbots.com/research/momentum_live.html

9. Clickable TradingView charts on the live page (2026-06-20)

Jacques wanted to jump straight from a name on the shortlist to its chart. Added a TradingView deep-link on every ticker.

10. Golden-cross dashboard restyle — "Groovy Baby" (2026-06-20)

While we were theming the momentum page, Jacques asked for the daily golden/death-cross dashboard to get the same Austin Powers treatment so the whole research site looks of a piece.

What the dashboard is (pre-existing, unchanged this session): a daily scan of big_bots.db (ohlcv_snapshots) for SMA50 crossing SMA200 across all exchanges over a rolling 30-day window — golden cross (50 rises above 200) and death cross (50 falls below 200) reported separately. Each hit gets a 0–~10 strength score (relative volume + SMA50 slope + the gap between the two averages). Logic lives in golden_cross.py (built late May, untouched here).

What we changed (purely cosmetic, golden_cross_report.py): ported the same theme used on the momentum page — plum/cream palette, bubble-letter title, the Bagel Fat One / Nunito / Fredoka / Pacifico / Space Mono fonts, and the hypno spiral + wave + decor background at low opacity behind a legible card. No change to the scan, the scoring, or the data — verified the Jun-20 diff against the Jun-4 backup (golden_cross_report.bak_*.py) is CSS/markup only. The previous version is kept as that backup.

How it runs (also pre-existing, confirmed healthy): - golden_cross_report.timer → fires daily 04:00 SAST (Persistent=true, so a missed run catches up). Regenerates a self-contained page (data baked in, no backend) at /root/golden_cross_web/index.html and writes a dated JSON snapshot to …/archive/YYYY-MM-DD.json. - golden_cross_web.service serves the folder on :8800. - Archives are landing daily (latest 2026-06-24.json, today 04:06) — the timer is working.

Honest note: this was a presentation change only — it doesn't add any signal or research finding. Logged here so the trail matches what's on disk (the section above stopped at 07:32; the restyle landed 09:31 the same morning).

Files

momentum_engine.py (backtest + in-progress-week guard), momentum_sweep.py, momentum_attribution.py, momentum_now.py (CLI screen + shared compute()), momentum_publish.py (webpage), weekly_cache.pkl (close+volume cache), momentum_sweep_results.csv, tv_exchange.py + tv_exchange_map.json + build_tv_map.py (TradingView chart links). Universe: us_universe_clean.csv (2,164 names). Golden-cross dashboard: golden_cross.py (scan logic), golden_cross_report.py (page generator, restyled), golden_cross_web/ (output + dated JSON archive), served by golden_cross_web.service on :8800, generated daily by golden_cross_report.timer at 04:00 SAST.