The active bot now runs three Kristjan Kullamägi daily-bar swing setups. Lance Breitstein's teaching survives as a discipline harness rather than a signal generator. Intraday Kullamägi experiments are research-only, and the earlier non-Kullamägi modules are preserved as research notes rather than active code.
Platform stack
| Layer | Choice | Why |
|---|---|---|
| Daily bars (universe scanner) | massive.com REST | Polygon-compatible API, ~5,300 US common stocks cached since 2010 |
| Intraday bars | Polygon Stocks Starter | 5y of 1-min history, no per-min cap, $29/mo |
| Earnings/catalyst cache | local cache + provider adapters | Still a promotion blocker until fail-closed coverage is complete |
| Broker — paper | Alpaca + IBKR Gateway | Both adapters wired in bot/lib/broker/ |
| Backtest runners | Pure Python, in-process | Daily-bar swing runner + 1-min intraday runner; no QC dependency |
| Dashboard | Vercel + static HTML | Human-facing cockpit — not the bot itself |
The three active strategies
| Setup | Trader | Side | Setup core |
|---|---|---|---|
kullamaggie_breakout_swing | Kristjan Kullamägi | Long | 30-100% prior leader run, 2-8wk tight base, rising 10-EMA, volume breakout, ADR ≥ 4 |
kullamaggie_episodic_pivot_swing | Kristjan Kullamägi | Long | 10%+ catalyst gap, dormant 3-6mo prior, ≥3× volume, close in upper half of range |
kullamaggie_parabolic_short_swing | Kristjan Kullamägi | Short | Large-cap or small-cap climax run, multiple up days, extended above 10-SMA, red bar break |
Universe pipeline (the rebuild's biggest fix)
Old version: each strategy module hardcoded a 25-40 ticker list. That's the dominant reason the original backtests lost money — mega-caps don't have ADR ≥ 4 and they aren't where Kullamägi-style breakouts actually live. New version:
~5,300 US common stocks (cached daily bars)
│
▼
universe_scanner.leader_universe(as_of)
- Cross-sectional percentile rank ROC over 1m / 3m / 6m
- Filter: top 15% on ≥ 2 of 3 timeframes (corpus's "simultaneously" rule)
- Apply: ADR ≥ 4, $5M dollar volume, above 50-SMA, no biotech
- Sort by composite score, take top N (200 for breakout, 300 for EP/short)
│
▼
Weekly rebalance — runner rebuilds on each Monday
│
▼
Strategy.scan() runs only on the week's leader pool
Discipline overlays (cross-cutting)
- Friday rule — no new entries on Fridays (corpus: Whos_Agent moderator validation).
- Earnings/catalyst gate — non-EP setups avoid nearby earnings once the cache is complete; EP must eventually require a verified catalyst.
- Theme cap — at most 2-3 concurrent positions per theme bucket (avoid the "all biotech blew up" pattern).
- Pure-trail exits by default — calendar partials at day 3-5 are opt-in. Three independent corpus studies (HackerTrader 64% CAGR, Whos_Agent E0, mxteo) showed they hurt returns.
- Breitstein discipline harness — prior-bar ratchet trail once a trade is in profit by the configured R threshold; intraday VWAP gate remains research-only.
- Mistake-filter overlay (cool-down after losses, daily loss cap, time-of-day guard) — research-only until the intraday runner is promoted.
- Borrow cost subtracted from short-side P&L (~3.6%/yr) — closes the live-vs-backtest gap on parabolic shorts.
Deliberately NOT automated
- Breitstein's A+ capitulation fades. Pure tape-reading; attempting to code it produces the canonical "bot shorts the bottom tick" disaster. His teaching is mechanized as the discipline harness instead.
- Hougaard's discretionary size-ups. His edge is psychological and execution-driven; the old ORB proxy is not active.
- Kullamägi's theme/sector pick. The corpus shows ~50% of his winners come from 1-2 dominant themes per period, identified by reading the tape. We approximate via the leader scan but don't have a real theme-momentum scorer yet.
System flow
┌─────────────────────────────────┐
│ DATA LAYER │
massive ────► │ - daily bars (5,300 stocks) │
polygon ────► │ - optional intraday research │
providers ───► │ - earnings/catalyst cache │
└────────────────┬────────────────┘
▼
┌─────────────────────────────────┐
│ UNIVERSE SCANNER │
│ (point-in-time, weekly) │
│ - top X% momentum on 1m/3m/6m │
│ - ADR ≥ 4, $5M dvol │
│ - exclude biotech, above 50SMA │
└────────────────┬────────────────┘
▼
┌─────────────────────────────────┐
│ REGIME GATE (SPY > 50SMA) │
│ longs blocked outside bull │
└────────────────┬────────────────┘
▼
┌────────── STRATEGY MODULES (3) ──────────────┐
│ Kullamägi: breakout, EP, parabolic-short │
└─────────────────┬────────────────────────────┘
▼
┌─────────────────────────────┐
│ DISCIPLINE OVERLAYS │
│ - Friday no-entry │
│ - Earnings/catalyst gates │
│ - Theme cap │
│ - Breitstein VWAP gate │ ← research-only intraday
│ - Breitstein prior-bar │ ← swing active
│ ratchet trail │
│ - Mistake filters │ ← intraday
└────────────┬────────────────┘
▼
┌────────────────────┐
│ BROKER ADAPTER │ → Alpaca / IBKR (paper)
└────────────────────┘
Promotion pipeline
A strategy doesn't reach live capital by decree. Three gates:
- Backtest vetting. Per-config YAML in
bot/backtests/configs_swing/defines CAGR / Sharpe / max-DD / profit-factor / min-trades thresholds.scripts/validate_promotions.pyadds OOS sample, top-winner dependency, and data-quality blockers. - Paper trading. Passed strategies run on Alpaca or IBKR paper for 90 days without intervention before live capital.
- Live capital. Starts at $10k per strategy. Expands only on evidence.
Current state of the three active strategies in the latest generated dashboard data:
- Kullamägi Breakout Swing — PF 1.554 IS / 1.138 OOS, 35.6% win rate, 59 trades.
- Kullamägi Episodic Pivot Swing — PF 0.833 IS / 2.414 OOS, 61.9% win rate, 21 trades; sample size and catalyst data are still blockers.
- Kullamägi Parabolic Short Swing — PF 0.697 IS / 1.761 OOS, 55.2% win rate, 87 trades; market-cap strict mode is still disabled.
None of the strategies is promoted to paper trading yet. The OOS numbers are interesting, but configured vetting still fails on return quality, sample size, or data completeness. This is a research bot until the promotion report clears.