Thales
methodology & verdicts

Research, honestly

Most quantitative trading research you can find online shows you its winners. This page works the other way: it lists the rules that make results trustworthy, and then every idea we built that failed — because a research process that cannot show you its dead ends is indistinguishable from luck.

The backtest is a falsification engine, not an optimizer.

Historical simulation is only trusted here to KILL ideas. A good backtest makes an idea eligible for live paper trading; it is never treated as a prediction of profit. The strongest force in quantitative research is self-deception, and this rule is the main defense.

Rules are written before results exist.

Pass/fail criteria — including the December go-live gate and each experiment's test battery — are written down and frozen before the data that will judge them arrives. Deciding the rules after seeing the outcome is how every fake track record in this industry gets made.

Tests run on survivorship-free data.

Backtests here include the stocks that later went bankrupt or were delisted — the ones most datasets quietly forget. Including the corpses typically makes results substantially worse, and substantially more honest.

Headline numbers ship with their asterisks.

Example, applied to our own flagship: the momentum backtest's headline is the LUCKIEST of eight calendar start-date variants — across all eight, the average result is roughly zero. We publish that spread alongside the headline, because a number without its luck estimate is advertising, not research.

A negative control runs live.

One sleeve trades daily under a strategy our tests rejected, with a covenant that it can never be promoted. If it quietly wins, our tests are broken. No result from the other sleeves is fully trusted unless the control behaves as expected.

the journal

Every research document, published as written

The live research journal: every internal research document, published verbatim (credential identifiers redacted, count shown) by the same automated daily export that publishes the trading record. Nothing here is published by hand; a document committed to the repository appears on the next daily cycle, and a tested completeness invariant guarantees none is silently missing.

VRD-1 — `VRPRunResult` has no `run_date`, so the exit-4 de-risking escalation silently degrades on the option sleeve: every failed CLOSE reads as NEW, every sessionliving docTRG-1 — the triage prompt mirror still names the OWNER as the gate-holder and omits the new dismissed/ sweep duty, four days before that sweep is the mechanism discharging three separate handoversliving docDISMISSED — capture bid/ask/sizes/quote-timestamp at order-submit time as a new forward streamliving docDISMISSED — SV-1 — the state schema version is un-bumpable on the two rewrite-in-place filesliving docSTAMP-3 — #132's pre-open→previous-day rule inverts for current-state captures (shortability), and three stamp sites still judge the UTC dateliving docSTAMP-2 — the trading path shares STAMP-1's UTC-date defect: a midnight-crossing delayed run consumes the NEXT session's idempotency slot, the real session is silently skipped, and the no-run canary reads greenliving docSTAMP-1 — the capture writers use the runner's UTC date as BOTH the trading-day stamp and the idempotency keyliving docsmallcap-skew-capture — extending the option skew/chains/term capture from Russell 1000 to small caps: considered and REJECTEDliving docSKW-4 — the skew store serves 2,068 rows stamped on non-sessions (two NYSE holidays and a Saturday) through a reader with no trading-day filter, and per-name coverage is unmeasured: GHC and NVR have zero rows in 62 capture days and no instrument would say soliving docSKW-3 — the backup firing silently replaces in-session term-structure rows with post-close quotes stamped `healed=False`: the skew job's second-firing idempotency has a per-stream hole, and capture-QA cannot see itliving docDISMISSED — SKW-2 — the skew capture sends dash-class symbols Alpaca rejects; four names have never captured a rowliving docSKW-1 — the fourth Alpaca client has no request deadline: the skew-capture cron can still hang foreverliving docSHR-1 — an UNLISTED mode of the clone hazard, which `git fetch` cannot detect: a shared working tree moved under CONCURRENT READERS. It happened in this run, to this run's own chair, inside the run reviewing #259living docSCR-1 — the scout half's 8-week cadence criterion fired on 2026-10-12 and changed no instruction text; its only record was a marker file each run overwritesliving docSCOUT — the steward's decision panel as a forward capture (withheld alert → classification → act → latency, as an owned daily stream)living docDISMISSED — SAC-1 — census of trading-path persist sites: "state advanced or keyed without regard to run outcome"living docRWG-1 — the runaway-order guard: phantom turnover-blend base on a HALT, and a blocked drawdown liquidationliving docRSN-1 — capture-resession's counters (the safety check of a destructive rewrite) mis-report in three reachable cases, and the schema pin can silently drop `captured_at` from an owned capture fileliving docDISMISSED — RPL-1 — the marketable-limit market-replace is the one order path outside the safety chokepointliving docDISMISSED — RDR-1 — a reopen condition filed in `queue/dismissed/` has no reader on its date; considered as a governance row and REJECTED on buildability and slot costliving docDISMISSED — RCX-1 — `portfolio reconcile` reports local corruption as "broker unreachable" and exits 0, and the comment saying that was fixed describes a mechanism that cannot workliving docRAD-1 — "a file exists" is the unit for every capture count, and one of the 45 sessions feeding the options_iv_term retire-or-keep criterion is a 33-row stub; the evaluator that will read them does not exist yet, so the input-set question gets decided after the data is inliving docQSL-1 — every shipped item in `research/queue/built/` still reads `status: open`, in the repo and on the public siteliving docPLB-1 — the placebo's C5 beta companion reads the FROZEN research store, which by design ends before the live window begins, so it has never computed and never can; a working live-SPY loader already exists three modules away and documents this exact trapliving docPIT-1 — the pit snapshotter greens while producing nothing (or garbage that permanently occupies its slot): three silent shapes, bleeding under the displaced-cron regimeliving docDISMISSED — PC-1 — ceiling on the cap-explained book (owner policy)living docOSR-1 — 130 market replacements were REJECTED by the broker after the local log recorded them ACCEPTED, and no channel can see a broker-side terminal rejection: the order log is write-once at submit, the digest counts local `failed` only, reconcile compares ID setsliving dococc-open-interest — per-series option open interest from OCC (a non-Alpaca free source): considered and REJECTEDliving docDISMISSED — OAD-1 — nothing says what a routine OUTAGE does to a dated condition that matured while the routine was dark, and the one rule that exists is conditioned on a declaration nobody can make retroactivelyliving docNOL-1 — the owner's one email cuts every `NEEDS-OWNER:` decision at 240 characters in both renderers, and `ops/STEWARD.md` mandates the recommendation and the deadline in exactly the positions the cut removes: today's digest carried 5 asks and 0 recommendations, and it is the only digest that will ever carry themliving docDISMISSED — MEM-1 — the `memory/` directory does not exist in the repoliving docDISMISSED — LCK-1 — the CI lock is version-pinned but hash-lessliving docLAB-3 (folded with LAB-4) — the lab's committed study YAML is not pinned to the ledger's recorded spec, and the vault's alpha ladder is not drawn from the declared budgetliving docLAB-1 — a broken import in a hypothesis-lab test fail-closes all three trading sleeves, and the marker convention that is supposed to prevent exactly this cannotliving docDISMISSED — snapshot risk-off flag records intent=False on a corrupt kill-switch state file (fail-open in the vol sample)living docKSP-1 — the kill-switch day erases the sizer's memory of the crash: the crash holding period never reaches the Kelly ledger (the validated engine books it), and the risk-off flag every later vol estimate trusts is recorded intent, not the observed bookliving docKBM-1 — dismissed: a dateless Kelly snapshot would silently skip booking forever (unreachable via any current writer)living docintraday-shortability-sample — a second, different-hour sample of the borrow-flag panel to capture intraday ETB→HTB onset: considered and REJECTEDliving docIGD-1 — five guards that exist and cannot fire: a bool-returning call wrapped in an unreachable `except` with the return discarded — at the ONE submit site outside the safety gate, the mid-run halt, and three alert emails; the test that "pins" the first one teaches a mock a failure no broker has; a run whose orders all failed exits 0living docDISMISSED — HIRE-1 — headcount as a new data dimension: does hiring growth survive on this apparatus?living docDISMISSED — GAP-1 — six permanent capture-days are lost inside the clean-clock window and gauge G4 claims they are machine-checkedliving docFRZ-1 — the B4 and B5 pins say they are append-only "like the December memo"; the December memo is enforced by a hash test and these two are enforced by nothing, while the auto-merge guard grades an in-place edit of either as ALLOWliving docFOS-3 — the new exit-4 escalation can be masked by yesterday's failed BUY, and its only test reads the source as text: the one exposure-left-on alarm has two ways to stay silentliving docDISMISSED — FOS-2 — FOS-1's NEW-vs-STANDING split reaches the per-sleeve digest but not THE fleet emailliving docFOS-1 — a per-symbol failed-order streak is indistinguishable from a one-off failure: AVB has failed 9 consecutive sessions, six of them the EMERGENCY-EXIT path, and no channel escalatesliving docFIN-4 — every gate asks "is this real?" and none asks "is this better than the free version?": the benchmark is SPY, and no criterion anywhere requires beating a passive momentum ETFliving docFIN-3 — the OOS monitor's verdict vocabulary cannot say "computable but uninformative", so it printed OK the day the sample crossed 60 while live Sharpe was -1.33living docFIN-2 — capacity.py studies the ceiling and nothing studies the FLOOR: no gate says how small an account may be before the traded book stops being the validated bookliving docDISMISSED — FIN-1 — nothing owns sizing when half-Kelly and the vol targeter disagreeliving docDISMISSED — F2-REOPEN — the fleet email's queue-count parserliving docEXQ-1 — one invalid symbol dumps the ENTIRE order batch to market orders (live momentum exposed; contaminates the December TCA gate)living docERN-1 — the earnings-date-as-EXPECTED panel: scout run 1's one PROVISIONAL kill, migrated out of the frozen archive so its tripwire is visible to `ls`living docDISMISSED — DSP-2 — PR #193's named cause for the VRP dispatch stall is falsified by its own tableliving docDISMISSED — DSP-1 — the Mac dispatch layer half-failed on three consecutive sessions and no machine noticed; considered as a loudness row and REJECTEDliving docDLV-1 — a steward record whose PR is unmerged when Friday's digest gathers loses its `NEEDS-OWNER:` lines from EVERY digest, permanently: the window is exactly one Friday wide and there is no restatement duty. #260 is unmerged today, and one of the two asks it carries is the mitigation for a trading-stopperliving docDGX-1 — the new weekly-email gate is blind to alarms the digest's own renderer prints: a failed VRP close, a corrupt option-position file, and "no readable beacon" all read as a quiet dayliving docDISMISSED — CUT-1 — the cutover's gate reports an unreachable box as a postponed gate, so an uncurable failure is retried seven more times; considered as a loudness row and REJECTED on scope and self-retirementliving doccron-delay-capture — capturing GitHub-Actions cron-delay telemetry as a forward stream: considered and REJECTEDliving docCQA-3 — no failing check reads `captured_at`, so two whole skew-capture days taken after the close passed every gate — and the rule that would disqualify them has been awaiting your countersign since the day the field was bornliving docDISMISSED — CQA-2 — capture-qa reads only the latest file, so a missing today-file fails nothing and a failing stream mails under another stream's nameliving docCNT-1 — the go-live gate progress PUBLISHED on thales.report is one ahead of what the gate's own evaluator computesliving docDISMISSED — CLK-1 — two dated criteria mature with no evaluator, and neither is on the NORTHSTAR §6 calendarliving docBTB-1 — "0 of 889 Russell-1000 names hard-to-borrow" is false at its own registration date (the true count was 2), and it is the stated basis for two pinned design decisions in three registered documents, one of them hash-frozenliving docBGS-1 — moving the digest to the Windows box gated six jobs behind a new one-minute job, and four detectors that lived inside those jobs have no box-side equivalent; #251's new tests assert what was added and are blind, by construction, to every one of the four removalsliving docBCN-1 — the liveness beacon is gated on job SUCCESS in five workflows, so a post-trade *reporting* failure withholds the *"did it run"* signalliving docDISMISSED — B4-NOTCH — the skew stream's calendar notch, and the ≥400-row floor it put in questionliving docDISMISSED — AUTO-APPROVE — pre-register which classes the machine may approve without the ownerliving docAMG-5 — the new sanctioned-move guard (47e8e73) fails OPEN three ways; one lets an unrecognized git file-status write into the owner's approval gateliving docAMG-4 — the records auto-merge workflow judges a PR by the PR's OWN copy of the guard, so its "can never widen itself" claim is circularliving docDISMISSED — AMG-3 — the fenced-real-gate / plain-decoy self-approval in the records auto-merge guardliving docA4S-1 — the A4 days-to-cover vacuity gate has been built, merged, pre-registered and returns-free since 2026-08-01, and nobody has run it: the memo assigns it to "the operator", which is not an actor this system hasliving docRESEARCH_QUEUE.md — FROZEN ARCHIVE (2026-08-21)living docRESEARCH_AUDIT_LOG.md — the pipeline's own measurement seriesliving docThales Research Notebook3 redactedliving docThe hypothesis labliving docqueue/approvedliving docqueue/builtliving docqueue/dismissedliving docqueue/openliving docThales Research Notebook1 redactedliving docNORTHSTAR.md — The Self-Improvement Charterliving doc`--since=<today>` is a liveness query that cannot see todayOct 21, 2026A routine read its own stale clone as a trading outageOct 20, 2026Steward 2026-10-20 — trading was clean (all five box jobs on time), but a research routine told you at 15:02Z that no sleeve had traded; that was false; three PRs merged by hand, one held for a correctionOct 20, 2026The gap alarm ended by timeout, not by resolutionOct 19, 2026Steward 2026-10-19 — GitHub Actions is out of free minutes again, but the Windows box traded all three sleeves and ran the digest and the capture on its own; with auto-merge down I merged six PRs by hand after testing them; one correction to my Friday report; four asks for youOct 19, 20262026-10-16 — the owner's one email asked for four answers he had already given, and an alarm that crashed was reported as a security breachOct 16, 2026Steward 2026-10-16 — the Windows box missed its second slot this week (today's option capture), so GitHub took it two hours after the close and, under the rule you signed Thursday, the day does not count; one digest fix tested and held for Monday; one alarm fix parked for youOct 16, 20262026-10-15 — the first day of a six-routine outage read as "7/7 reporting on schedule"Oct 15, 20262026-10-15 — six routines went dark, and the alarm was addressed to one of themOct 15, 2026Steward 2026-10-15 — back after four dark days; the four decisions at the top of tomorrow's email are already answered (you ruled on them today in #240); one fix merged; three new asksOct 15, 20262026-10-09 — the cutover landed, and the one email arrived cutOct 9, 2026Steward 2026-10-09 — trading moved onto the Windows box and ran cleanly; two fixes merged, one held for Monday; four decisions re-sent because today's email cut them offOct 9, 2026The delegation silenced two channels it depends on (daily audit, 2026-10-08)Oct 8, 2026Steward 2026-10-08 — the Friday-report bug is fixed, the VRP twin fix is merged, and the queue key is used for the first time; the tbx-win cutover has still not happened and gives up on 10-16Oct 8, 2026Steward 2026-10-07 — first run (interactive, with the owner present): 6 PRs merged, 3 closed, 1 held; the delegation itself lands with this PROct 7, 20262026-10-05 — the in-session skew dispatch did not fire, and by design nothing could say soOct 5, 2026Equity ledgers: every healed day held the previous day's close (found and repaired 2026-10-02)Oct 2, 20262026-09-29 — the VRP dispatch stall: 18 days measured (the lead named here was wrong)Sep 29, 2026Research panel — run 30 (Tuesday 2026-09-29)Sep 29, 2026Panel run 29 — 2026-09-28Sep 28, 2026Hypothesis lab — what to test next, and how (deep research, 2026-09-28)Sep 28, 2026The escalation channel had no retry — found on day 5 of the billing outageSep 25, 20262026-09-21 — GitHub refused every job in the repo over billing; nothing traded, and nothing said soSep 21, 2026Two of the VRP forward gate's reported numbers were wrong (daily audit 2026-09-18)Sep 18, 2026The reconcile false-drift at the window edge (2026-09-15, corrected 2026-09-16)Sep 15, 20262026-09-14 — the dark-routine exception could never fireSep 14, 2026DRAFT for countersign — NORTHSTAR §9, the project's own retire criterionSep 10, 2026Maintainer verification — external financial review, 2026-09-09Sep 9, 2026Thales — an outside financial readSep 9, 2026Thales — design review against first principlesSep 5, 20262026-09-05 — External design review (r2): maintainer-side verificationSep 5, 20262026-09-02 — Deep self-audit (interactive, fresh-context)Sep 2, 20262026-08-31 — The displaced-cron regime: three days of trading after the closeAug 31, 2026Design review — thalesAug 29, 20262026-08-29 — External design review: maintainer-side verificationAug 29, 20262026-08-21 — meanrev clearing-day churn: the RWG-1 leg-2 measurementAug 21, 2026Routine self-sustainment audit — the loops did not close (2026-08-08)Aug 8, 20262026-08-07 — the skew capture lost a day and gained a contaminated oneAug 7, 20262026-08-06 — the day the fleet flew blind, and nobody was toldAug 6, 20262026-08-04 — the live momentum book has been 24% larger than its design, silentlyAug 4, 2026VRP v2 — pre-registered spec (FROZEN AT COMMIT, 2026-08-01)Aug 1, 2026Quant panel - suggestions report (2026-08-01)Aug 1, 2026VRP pessimistic twin — same-snapshot fix (panel A1) — 2026-08-01Aug 1, 2026External design review (2026-08-01) — archived with ground-truth correctionsAug 1, 2026December governance package — DRAFT (2026-08-01)Aug 1, 2026Bounding the Stateful-Purge Leak — Pre-Registration (2026-08-01)Aug 1, 2026Null Calibration of the Falsification Engine — Pre-Registration (2026-08-01)Aug 1, 2026C1 — Go-live leverage diff: cap gross exposure, not the scalarAug 1, 2026Turn-of-Month Forward Attribution — Pin (pre-registered 2026-08-01, panel item B5)Aug 1, 2026Skew Stream — Pinned Activation Test (pre-registered 2026-08-01, panel item B4)Aug 1, 2026Adjusted-opens audit — 2026-08-01Aug 1, 2026A4 — Publication-lagged days-to-cover exclusion battery (pre-registration)Aug 1, 2026Short-flow → short-interest nowcast — ONE-SHOT FALSIFICATION (panel A3, 2026-08-01)Aug 1, 2026VRP decision-fidelity amendment — 2026-07-25Jul 25, 2026Micro-cap momentum battery — PRE-REGISTRATION v1 (2026-07-22)Jul 22, 2026Micro/small-cap momentum — data feasibility scoping (2026-07-21)Jul 21, 2026December Gate — Interpretation Memo (pre-registered 2026-07-13)Jul 13, 2026Multi-Sleeve Platform — SPEC (pre-registered 2026-07-05)Jul 5, 2026OOS Degradation Monitor — Power & Detection-Latency Study (2026-05-30)May 30, 2026Capacity & Stress-Execution Realism — 2026-05-30May 30, 2026Apparatus Readiness — 2026-05-30 AFK session indexMay 30, 2026Post-Refresh Fundamentals-Signal Test ProtocolMay 29, 2026Execution-Fidelity Fix Spec — unify backtest & live constructionMay 29, 20262026-04-06 Research NotesApr 6, 2026

These are internal working documents — experiment pre-registrations, incident write-ups, verdicts including nulls — shipped verbatim by the same automated daily export that publishes the trading record. Machine-readable index: /data/research.json.

the kill list

Built, tested, dead

Every strategy idea this platform built and tested, with the honest verdict. Publishing failures is the point: a research process that only shows winners is indistinguishable from luck. Verdicts come from pre-registered statistical gates (overfitting probability, out-of-sample tests on survivorship-free data), not from taste. Much of this list was built, tested, and killed by the AI agent that operates the platform, during overnight research sessions run under the same pre-registered rules.

Machine-learning trade filter (random forest meta-labeling)2026-05Killed

Overfitting probability measured at 100% with price-only features — the model memorized the past instead of learning anything. Disabled in config; would only be revisited with fundamentally new input data.

Residual momentum (factor-neutralized ranking)2026-05Killed

Worked mechanically exactly as the literature describes — and cost about 1.7% of annual return in practice. An idea can be real and still not worth its price.

Value sleeve (cheap-stock tilt)2026-05Killed

Added no robustness benefit on the overfitting tests. Removed.

Quality, accruals, asset-growth and low-volatility tilts2026-05Killed

Every classic fundamental tilt was built and tested; none survived the honest evaluation harness. The conclusion — published price+fundamental signals on US large caps are exhausted — is now a standing research rule here.

Graduated index-hedge overlay (scaling into SPY in stress)2026-05Killed

A return drag: about −1% annualized in walk-forward testing, losing in 0 of 5 test windows. Protection that costs more than the crashes it softens.

A faster variant of the flagship's signal2026-05Not shipped

Worsened the overfitting probability in both test modes. The incumbent stayed.

A three-parameter variant of the flagship2026-05Not shipped

Looked better on the headline number, but the verdict flipped depending on how the test data was partitioned — the signature of a fragile result. Investigated, documented, not shipped.

Tranching (staggering the rebalance across the month)Jun 10, 2026Killed

Killed by its own pre-registered gate before launch. Its useful by-product survived: a diagnostic that measures how much of any backtest headline is start-date luck — now run against our own numbers.

Corporate-insider trading signal (SEC Form 4 filings)Jun 10, 2026Killed

A perfect null: after building the full data pipeline, insider filings predicted nothing at all in our universe. The cleanest kind of kill.

Short-horizon mean reversionJul 5, 2026Repurposed

Rejected by its pre-registered test battery — then deliberately deployed live anyway as the negative control, under a covenant that it can never be promoted. If our rejected strategy quietly wins, our tests are broken. It trades every day to keep that check honest.

Micro-cap reversal program (v1)Jul 22, 2026Killed

A month of data engineering (point-in-time small-cap universe, delisted-stock recovery, realistic cost model), then one hash-frozen test battery allowed to run exactly once. It failed: out-of-sample Sharpe −0.30, negative even at half the estimated trading costs. Killed without appeal; any v2 requires a brand-new pre-registration.

Learning-to-rank stock selection (LambdaRank)2026-05Paused

No honest gain over the simple momentum ranking to date. Archived, not deleted — would be revisited only with genuinely new input data.

Congressional-trading data (as a signal source)Jul 25, 2026Killed

Evaluated during a data-sourcing deep-research pass: since the 2012 disclosure law, politicians' disclosed stock picks slightly underperform. A famous signal that died the moment it became famous.

still standing

What survived

The configuration running in production today.

What survived every gate and runs in production today is a single trend-following configuration on large-cap US equities, wrapped in layered risk controls: diversification-aware weighting, conservative sizing, volatility targeting, and a hard drawdown stop. The exact signal and parameters stay in the private repository — what we publish is every output it produces, every day, and the honest scorecard including its caveats.