πŸ— Spectrum Β· Architecture

How it's built β€” and why the harness layer makes the numbers trustworthy.

The system at a glance

two lanes: a research lane that grades ideas, a live lane that feeds the cockpit Β· πŸ“„ full whitepaper Β· πŸš€ AWS deployment guide
Polygon 10 years of daily bars SEC quarterly filings earnings-date proxy Adanos news sentiment Yahoo global indices BBCΒ·CNBCΒ·DW RSS headlines local cache data/bars/*.parquet Β· earnings_filings.json fetched live at cockpit build Adanos key stays in .env Β· Yahoo/RSS need no key factors.py β€” point-in-time factor panel close Β· advol_20 Β· mom_12_1 (+ 3-1 / 6-1 / 9-1 sweep columns) panel (date Γ— symbol) momentum.py β€” the walk-forward harness (the referee) signal at dβ‚€ uses only prices ≀ dβ‚€ β€” the week's return is what actually happened next 1 Β· top-80 liquid as of dβ‚€ 2 Β· rank by 12-1 momentum 3 Β· drop earnings ≀ 10d momentum ≀ 0 4 Β· hold top-3 for one week 5 Β· charge 5 bps Γ— turnover next Friday: dβ‚€ ← d₁, compound and repeat guardrails β€’ no look-ahead β€” every shift β‰₯ 0 β€’ survivorship-safe β€” delisted stay in β€’ full window shown, worst years too β€’ costs charged on every change β€’ pre-registered trials #1–17 β€’ cheat-detector control runs why: see the section below report card per run data/momentum.json equity curves Β· per-year Β· trades data/versions.json β€” the registry locked base Β· candidates Β· every trial numbered data/spectrum.db β€” history sentiment Β· news Β· quotes Β· account this week's top-3 store ⇄ read live feeds ops.py β€” operator layer (never places real orders) picks + the why Β· $40k paper tickets Β· world strip & marquee Β· morning/evening reports wa.me one-tap links (Twilio auto-send only if creds exist in .env) latest snapshot, read from spectrum.db api/server.py β€” FastAPI /api/ops Β· /api/momentum serve the newest DB snapshot (JSON files = export/fallback) Home β€” cockpit picks Β· world Β· track record Orders β€” account tickets Β· reports Β· trades Strategy rules Β· report card Architecture this page πŸ“² WhatsApp one-tap wa.me send one tap
Solid arrows are the research lane (cached, reproducible, graded by the harness). Dashed arrows are the live lane β€” news and world data fetched fresh when the cockpit is built; they color the display and the reports but never touch the backtest. The two lanes only meet at ops.py.

Inside the harness β€” what it actually does

momentum.py Β· the single choke-point every number passes through

What goes in: the point-in-time factor panel (one row per date Γ— symbol: closing price, 12-1 momentum, trailing dollar volume), SPY and QQQ closes for the benchmarks, and the SEC filing-date calendar for the earnings filter. Nothing else β€” no news, no opinions, no knobs.

What it does, every simulated Friday (the same loop for 451 weeks straight):

  1. Build that Friday's universe β€” the 80 most liquid names as measured that day. A stock that delisted in 2023 is still here in 2021; a stock that IPO'd in 2024 isn't here in 2020.
  2. Rank by 12-1 momentum using only prices up to that Friday (both shifts in the formula point backwards, so peeking is impossible by construction, not by care).
  3. Apply the two filters β€” drop anyone reporting earnings within 10 days; drop anyone whose own 12-month momentum is negative. A dropped slot stays in cash (the return math divides by 3 regardless, so an empty slot earns zero β€” no silent re-weighting).
  4. Hold the top 3 for one week and take whatever return actually happened.
  5. Charge costs on every change β€” 5 bps Γ— turnover, computed as the symmetric difference between this week's and last week's book (keep all 3 names β†’ pay nothing; swap one β†’ pay for the one that moved).

What comes out: the weekly net return stream β€” and everything else is derived from it: the equity curve, the report card (CAGR, Sharpe, drawdown, win %, profit factor…), the per-year and per-month splits, and the holdings log that becomes the trade episodes on the Orders tab. Each run's report card is also recorded in the history database, so the grade itself has a paper trail.

Why this layer is important: it is the only place returns are ever computed. The cockpit, the orders, the reports, the Strategy tab β€” all of them just read its output files. That gives you two guarantees: every idea ever tried was graded by the same referee (so numbers are comparable), and the live Friday picks come from the same code path that produced the 10-year backtest (so "backtest" and "live" cannot quietly drift apart).

Without the harnessWith it
Each experiment computes returns its own way β€” results aren't comparable, and bugs hide. One engine, one cost model, one universe rule. A better number means a better idea, not a different calculator.
Today's stock list gets tested on yesterday's market (survivorship + look-ahead creep in silently). Universe and signal are rebuilt as-of each Friday from past-only data β€” the lies are structurally impossible.
The live picks come from a script that "resembles" the backtest. The live book IS the last line of the backtest β€” current_holdings from the same run.
Ten variants get tried; the flattering one gets shown. Every attempt is a numbered trial in the registry; killed ideas stay killed.

Why does the harness layer exist?

because without a referee, every backtest flatters you

A backtest is a machine for lying to yourself. There are four classic ways it lies, and the harness is one layer whose only job is to make each of them structurally impossible rather than "avoided by being careful." That's why it sits between the data and every result β€” nothing reaches a dashboard or the registry without passing through it.

Lie #1 β€” peeking at the future (look-ahead bias)

The signal is close[tβˆ’21] / close[tβˆ’252] βˆ’ 1: both shifts point backwards, so the Friday ranking mathematically cannot contain anything after Friday. The week's return is then whatever actually happened next.

formation: tβˆ’252 β†’ tβˆ’21 (11 months) skipped month hold 1 wk Friday dβ‚€
Proof from this project: in Nov-2021 the ranking put SBNY (Signature Bank) at the top β€” and the backtest bought it, rode it, and later ate the collapse. An engine that could peek would have quietly skipped it. We also run deliberate "cheat detector" controls (a signal allowed to see one week ahead) to see what peeking looks like numerically β€” it produces absurd, unmistakable numbers, which is how we know the honest runs aren't doing it.

Lie #2 β€” forgetting the dead (survivorship bias)

If you backtest on today's index members, you only test companies that survived β€” a pre-filtered list of winners. The harness's universe is rebuilt as of each Friday from trailing dollar volume, over a name list that keeps the delisted (SIVB, FRC, TWTR, ATVI…) in history until the day they actually died.

Why it matters: momentum strategies love the stocks that later blow up β€” banks in 2021, meme names, leveraged growth. Drop the corpses from history and a top-3 momentum book looks meaningfully better than it really was.

Lie #3 β€” trading for free (ignoring costs)

Every change of the book is charged 5 bps Γ— turnover. A weekly top-3 book turns over a lot; the charge compounds against you exactly like the returns compound for you.

Proof from this project: a published VWAP trend strategy graded +21%/yr at the paper's zero-spread assumption β€” and βˆ’1.3%/yr the moment a 1-cent half-spread was charged. Thirteen intraday strategies were tested by this harness; at realistic costs, zero beat buy-and-hold. Costs were also part of why the graded 3-month momentum variant lost so badly: shorter windows churn the book more.

Lie #4 β€” trying ten things and keeping the winner (overfitting)

Every variant ever evaluated gets a trial number in the registry (#1–17 so far), hypotheses must come from literature before the run, the baseline is LOCKED, and a killed idea stays killed. Multiple testing can't hide, because the count is public.

Proof from this project: the "obvious" fix β€” go to cash when SPY is under its 200-day average β€” was tested and falsified twice: below-trend weeks were actually the book's best (66% win rate). Intuition said yes; the harness said no; the rule was never shipped. Same discipline the other way: showing the full 10-year window revealed the 5-year Sharpe of 1.77 was era-inflation (it's 0.94–1.13 over the decade) β€” flattering windows aren't allowed either.

How ideas are graded

the report card, the bars to clear, and the promotion ladder

Every idea gets the same report card, computed by the harness from its weekly net returns:

MetricWhat it answers
Annual return (CAGR)How fast the money compounds, net of costs.
Annual volatilityHow violently it swings on the way.
Sharpe ratioReturn per unit of pain β€” the headline grade for comparing ideas.
Max drawdownThe worst peak-to-trough loss you'd have lived through.
Hit rate & avg bps/weekHow often a week wins, and by how much on average.
Per-year (and per-month) splitsWhether one kind regime is hiding inside the average.

The bars an idea must clear β€” all of them, net of costs, over the FULL 10-year window: beat SPY and QQQ buy-and-hold (otherwise just buy the index), beat the incumbent base it wants to replace, and hold up in the year-by-year table (a strategy that made everything in one lucky era fails even with a pretty average).

The promotion ladder β€” every idea walks the same path, recorded in data/versions.json:

1 Β· PRE-REGISTER
literature source + trial #, before any run
2 Β· RUN
one config, the shared harness
3 Β· GRADE
report card vs the bars above
βœ– KILLED
stays killed β€” no re-litigating
β†’ CANDIDATE
must then win on forward data
β˜… PROMOTED
only with explicit approval

The actual ledger so far (full detail in data/versions.json; the code of retired strategies was removed in the 2026-09-06 cleanup β€” their graded records are retained):

What was gradedResultVerdict
12-1 signal on the top-3 book (trial #14) 47.2%/yr Β· Sharpe 1.13 Β· maxDD βˆ’41% β€” beat the older 5-day-skip variant on every metric β˜… PROMOTED β€” the live book
Formation windows 3-1 / 6-1 / 9-1 (trials #15–17) 14.5% / 42.6% / 43.2%/yr β€” all below the base, all with deeper drawdowns βœ– killed (12-1 stays)
Earnings-avoid filter (trials #9–10) Helps the 3-name book (rescues blowup weeks); hurts the diversified book kept β€” on the top-3 book only
200-day SMA "go to cash" gate Falsified twice β€” below-trend weeks were the book's best (66% win rate) βœ– killed (intuition lost to data)
13 intraday strategies (ORB, VWAP bands, UT Bot, pivots, gap fades…) 0 of 13 beat buy-and-hold at realistic costs βœ– killed Β· code removed
News-sentiment veto on the book Cannot be backtested honestly (scoring old news with today's knowledge peeks) retired with the multi-book cleanup

One Friday through the machine

live worked example β€” this is the current rebalance, not a mock
  1. Loading the live example…

Module map

what each file does
ModuleRoleWrites
factors.pyFetches/caches 10yr daily bars; builds the point-in-time panel β€” prices, liquidity, momentum columns (per-symbol shifts only).data/bars/*.parquet
momentum.pyThe harness: walk-forward loop, point-in-time universe, filters, turnover costs, per-year splits, trade episodes.data/momentum.json
store.pySQLite history database: every fetched value (sentiment, news, global quotes, picks, orders, account marks, report cards) is stored on each build and read back for trends and live-feed fallbacks.data/spectrum.db
ops.pyOperator layer: picks + why, $40k paper tickets, world strip, marquee, reports, WhatsApp links. Never places real orders.data/ops.json, data/reports/
api/server.pyFastAPI β€” serves the four tabs; /api/* reads the latest snapshot from the history database (JSON files are exports, used only as fallback). Responses carry served_from: "db" | "file".β€”
data/versions.jsonThe registry: v1 LOCKED, candidates, every trial numbered. Promotion needs explicit approval + forward validation.hand-audited