Skip to content

Repository files navigation

Control Group

A paper-trading app, and the earnings research behind it — in which twelve promising results were killed by their own controls and none survived.

That is the finding, not a disclaimer. Most public quant repositories publish strategies that worked. This one publishes the controls that killed them, the pre-registrations written before the outcomes were known, and a play that made money and still had no edge.

Everything here is paper trading. The trading base URL is hardcoded to paper-api.alpaca.markets, the UI proves it from the live endpoint rather than asserting it, and the one script that can place orders throws on startup if that URL is ever changed. There is no live-trading code path.


What is actually in here

A paper-trading interface (src/) — account state, equity curve, order entry, positions with P&L, open orders and fill history, plus a monthly multi-factor shadow strategy that trades on paper and reports its own results.

The research (scripts/, data/) — an earnings event study over 238 filing-anchored events across 8 symbols, an options study over 83 events with real historical option prices, and the machinery that produced both.


The results, stated honestly

Claim Raw After its control
Intraday lead–lag 71% accurate 65% for random signals (permutation)
Opening-range breakout +profitable −31% vs QQQ's +263% (benchmark)
Post-earnings drift +2.29%, t=3.58 +0.64%, t=1.20 (beta-adjusted)
Pre-event news → move size ρ = 0.432 ρ = 0.077 (within-symbol)
"Cheap straddle" price gate +30.6% modelled t = 0.16 on real option prices
Per-symbol cheapness (AVGO) +62% p = 0.080 vs best-of-8 under the null

Two things survive, and both were stated as nulls from the start:

  • Gap direction is unpredictable. Six pre-event price signals, 238 events, 45–53% against a 50% null.
  • Range compression forecasts move size, ρ = −0.261 — but it predicts the median, not the tail an option prices.

And one finding worth stealing regardless of what you think of the rest: SEC 8-K item 2.02 is not "earnings." It is "Results of Operations", which is broader. 34 of Tesla's 68 item-2.02 filings are quarterly vehicle delivery reports carrying byte-identical metadata — same items, same primaryDocDescription. Only the filing body distinguishes them. Roughly an eighth of the original sample was the wrong event type. See scripts/classify-filings.mjs.


Quick start

npm install
npm run dev

Then paste an Alpaca paper key pair into the app. Get one free at alpaca.markets — no funding required, and no live key will work here anyway. Keys are stored in your browser's localStorage and are never sent anywhere but Alpaca.

To run the research you also need market data cached locally:

export SEC_CONTACT_EMAIL="you@example.com"   # SEC requires a contact in the User-Agent
npm run ingest:yf && npm run classify:filings
npm run study:event

The method, in four rules

These were learned expensively and are the actual content of the project.

  1. Write the prediction down before the outcome, and never edit it after. Later learning gets appended, not merged upstream. A pre-registration whose claims can be revised once results arrive is not a pre-registration.
  2. A pooled statistic is never applied to an individual symbol without the within-symbol figure printed beside it. A ρ of 0.432 that becomes 0.077 within symbol was measuring which stock this is.
  3. A result selected as the best of N is tested against the distribution of best-of-N, never against zero.
  4. An effect that cannot be estimated from prior data alone is not tradeable, however real it is.

Full post-mortem of the one play that reached live paper trading: Blind Bracket Close-Out (rendered) · source. It made +$736 across two trades and had no edge — both winners are traced to causes the strategy never predicted.


What this is not

Not investment advice, not a strategy that works, and not a backtesting framework — for that, use something maintained. The sample sizes are small (83–238 events, 8–9 symbols), the option-price history starts 2024-01-18, and the daily-bar history mostly starts 2020, which is a bull-market-heavy window. Those limits are stated in the code next to the numbers they affect.

Split out of a private personal-finance tracker; the portfolio side, which reads real brokerage exports, stayed behind.

MIT licensed. Use the controls, ignore the conclusions, run your own.

About

A paper-trading app and the earnings research behind it, in which twelve promising results died to their own controls and none survived.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages