← stefan ruffinibandolier / live run
paper · liveas of 2026-05-30Jun 2021May 2026benchmark SPYλ 1 · mutation off
LIVEforward paper track · frozen 2026-05-30 · first session pending

A live population of strategies, each on its own rung of the risk dial. A bandit moves the money toward whatever is beating the index, and prunes the rest.

Return vs SPY
+66.4pp
▲ beating
median 158% vs 91%; 20/20 seeds beat SPY
Sharpe
1.11 / 0.85
▲ beating
median of 20 seeds; worst seed 0.95
Max drawdown
-26.4% / -24.5%
▼ behind
median of 20 seeds; worst seed -30.9%
> growth of $1

Against the index, over five years

Left of the mint line is a simulated backtest (backfill): the frozen rules replayed on 2021 to launch, no real exposure. Right of it is live forward paper trading from the freeze date: same rules, real daily prices, growing every weekday, no money down. The gold line is the median across 20 random seeds; the shaded band is where the middle 80% of seeds land; gray dashed is SPY.

Bandolier (median of 20)seed range (10-90th pct)SPY
> capital allocation

Where the money actually sat

Each band is a strategy's share of the book at that rebalance, stacked from capital-preservation at the bottom to aggressive up top. Watch the bandit lean into whatever is working.

spy_hold(preservation)regime_defensive(preservation)mean_reversion(defensive)sma_crossover(balanced)momentum(aggressive)
> the experiment · evolving population

The strategies breed, mutate, and get culled

Same engine, mutation cranked up. A new agent is born roughly every month: re-dial a winner's risk, sweep its parameters, or blend two independent signals firing on one name. 53 births over five years. Each ribbon is an agent at its risk level, thickening with its share of the book; the triangles are births, colored by operator. It is a great thing to watch the population fan out across the spectrum, then concentrate back into the survivors. Whether all that motion actually pays is the honesty check below.

> hover a stream to inspect an agent
53 birthsredialsweepblend
ALL-INAGGRESSIVEBALANCEDDEFENSIVEPRESERVATIONRISK ▲spy_hold · preservation (risk 0.03)insider_cluster@r0.05 · preservation (risk 0.05)insider_cluster@r0.10 · preservation (risk 0.10)sma_crossover@r0.13 · preservation (risk 0.13)regime_defensive · preservation (risk 0.14)momentum@r0.15 · preservation (risk 0.15)mean_reversion@r0.15 · preservation (risk 0.15)insider_cluster@r0.16 · preservation (risk 0.16)momentum~swept#23@r0.20 · preservation (risk 0.20)momentum~swept · preservation (risk 0.20)sma_crossover@r0.28 · defensive (risk 0.28)mean_reversion · defensive (risk 0.36)insider_cluster@r0.40 · defensive (risk 0.40)insider_cluster@r0.41 · defensive (risk 0.41)mean_reversion@r0.41 · defensive (risk 0.41)sma_crossover@r0.44 · defensive (risk 0.44)sma_crossover · balanced (risk 0.46)sma_crossover~swept · balanced (risk 0.46)sma_crossover~swept · balanced (risk 0.46)sma_crossover~swept · balanced (risk 0.46)sma_crossover~swept · balanced (risk 0.46)sma_crossover~swept · balanced (risk 0.46)sma_crossover~swept · balanced (risk 0.46)sma_crossover~swept · balanced (risk 0.46)blend · balanced (risk 0.50)insider_cluster@r0.53 · balanced (risk 0.53)insider_cluster · balanced (risk 0.56)momentum~swept#23@r0.58 · balanced (risk 0.58)momentum@r0.69 · balanced (risk 0.69)sma_crossover@r0.70 · balanced (risk 0.70)insider_cluster@r0.72 · aggressive (risk 0.72)momentum · aggressive (risk 0.74)momentum~swept · aggressive (risk 0.74)insider_cluster@r0.86 · aggressive (risk 0.86)sma_crossover@r0.90 · all-in (risk 0.90)sma_crossover@r0.92 · all-in (risk 0.92)born: insider_cluster@r0.05 (redial)born: insider_cluster@r0.10 (redial)born: sma_crossover@r0.13 (redial)born: momentum@r0.15 (redial)born: mean_reversion@r0.15 (redial)born: insider_cluster@r0.16 (redial)born: momentum~swept#23@r0.20 (redial)born: momentum~swept (sweep)born: sma_crossover@r0.28 (redial)born: insider_cluster@r0.40 (redial)born: insider_cluster@r0.41 (redial)born: mean_reversion@r0.41 (redial)born: sma_crossover@r0.44 (redial)born: sma_crossover~swept (sweep)born: sma_crossover~swept (sweep)born: sma_crossover~swept (sweep)born: sma_crossover~swept (sweep)born: sma_crossover~swept (sweep)born: sma_crossover~swept (sweep)born: sma_crossover~swept (sweep)born: insider_cluster@r0.47 (redial)born: blend (blend)born: blend (blend)born: blend (blend)born: blend (blend)born: blend (blend)born: blend (blend)born: blend (blend)born: blend (blend)born: blend (blend)born: blend (blend)born: blend (blend)born: blend (blend)born: blend (blend)born: blend (blend)born: blend (blend)born: blend (blend)born: blend (blend)born: blend (blend)born: blend (blend)born: blend (blend)born: blend (blend)born: insider_cluster@r0.53 (redial)born: momentum~swept#23@r0.58 (redial)born: momentum@r0.69 (redial)born: sma_crossover@r0.70 (redial)born: insider_cluster@r0.72 (redial)born: momentum~swept (sweep)born: momentum~swept (sweep)born: insider_cluster@r0.86 (redial)born: sma_crossover@r0.90 (redial)born: blend#6@r0.91 (redial)born: sma_crossover@r0.92 (redial)20222023202420252026
> the honesty check · does evolution survive out of sample?
vs SPYin-sample (5y)out of sample (18mo)
static
the shipped config (the headline)
+66.4pp
+25.8pp
evolution on
mutation + cadence gene
+277.6pp
+15.2pp

A clean test: turn the evolving population on and stress it across seeds, in sample versus a held-out 18 months it never saw. In sample it looks unbeatable, +278pp vs the static system at +66pp. Out of sample that edge is a mirage: +15pp, actually behind leaving the population static at +26pp. Best in sample, worst out of sample, is the textbook overfit signature. That is why evolution ships off by default and the live track is the static core up top.

> evolution log
  • >2021-06redialmomentum@r0.15← from momentumpreservation
  • >2021-07sweepsma_crossover~swept← from sma_crossover
  • >2021-08blendblend← from sma_crossover + regime_defensive
  • >2021-09redialsma_crossover@r0.28← from sma_crossoverdefensive
  • >2021-10sweepsma_crossover~swept← from sma_crossover
  • >2021-11blendblend← from momentum + sma_crossover
  • >2021-12redialmomentum@r0.69← from momentumbalanced
  • >2022-01sweepsma_crossover~swept← from sma_crossover
  • >2022-02blendblend← from sma_crossover + insider_cluster
  • >2022-03redialsma_crossover@r0.90← from sma_crossoverall-in
  • >2022-04sweepsma_crossover~swept← from sma_crossover
  • >2022-04blendblend← from sma_crossover + insider_cluster
  • >2022-05redialsma_crossover@r0.13← from sma_crossoverpreservation
  • >2022-06sweepsma_crossover~swept← from sma_crossover
  • >2022-07blendblend← from sma_crossover + insider_cluster
  • >2022-08redialsma_crossover@r0.44← from sma_crossoverdefensive
  • >2022-09sweepsma_crossover~swept← from sma_crossover
  • >2022-10blendblend← from sma_crossover + insider_cluster
  • >2022-11redialsma_crossover@r0.70← from sma_crossoverbalanced
  • >2022-12sweepsma_crossover~swept← from sma_crossover
  • >2023-01blendblend← from sma_crossover + insider_cluster
  • >2023-02redialsma_crossover@r0.92← from sma_crossoverall-in
  • >2023-03sweepmomentum~swept← from momentum
  • >2023-03blendblend← from momentum~swept#23 + insider_cluster
  • >2023-04redialmomentum~swept#23@r0.20← from momentum~swept#23preservation
  • >2023-04retiresma_crossover~sweptretired
  • >2023-05sweepmomentum~swept← from momentum~swept#23@r0.20#25preservation
  • >2023-05retiresma_crossover@r0.92retired
  • >2023-06blendblend← from momentum~swept#23 + insider_cluster
  • >2023-06retiremomentum@r0.69retired
  • >2023-07redialmomentum~swept#23@r0.58← from momentum~swept#23balanced
  • >2023-07retiresma_crossover~sweptretired
  • >2023-09blendblend← from insider_cluster + blend#6
  • >2023-09retiremomentum~sweptretired
  • >2023-10redialinsider_cluster@r0.86← from insider_clusteraggressive
  • >2023-10retiremomentum~swept#23@r0.58retired
  • >2023-12blendblend← from insider_cluster + blend#6
  • >2023-12retiremomentum~sweptretired
  • >2024-01redialinsider_cluster@r0.53← from insider_clusterbalanced
  • >2024-01retiremomentum~swept#23@r0.20retired
  • >2024-03blendblend← from insider_cluster + blend#6
  • >2024-03retiresma_crossover~sweptretired
  • >2024-03redialinsider_cluster@r0.05← from insider_clusterpreservation
  • >2024-03retiresma_crossover@r0.13retired
  • >2024-05blendblend← from insider_cluster + blend#6
  • >2024-05retiresma_crossover~sweptretired
  • >2024-06redialinsider_cluster@r0.16← from insider_clusterpreservation
  • >2024-06retiresma_crossover~sweptretired
  • >2024-08blendblend← from insider_cluster + blend#6
  • >2024-08retiremomentum@r0.15retired
  • >2024-09redialmean_reversion@r0.15← from mean_reversionpreservation
  • >2024-09retiresma_crossover~sweptretired
  • >2024-11blendblend← from insider_cluster + blend#6
  • >2024-11retireblendretired
  • >2024-12redialinsider_cluster@r0.40← from insider_clusterdefensive
  • >2024-12retiresma_crossover~sweptretired
  • >2025-01blendblend← from insider_cluster + blend#6
  • >2025-01retiremean_reversion@r0.15retired
  • >2025-02redialinsider_cluster@r0.10← from insider_clusterpreservation
  • >2025-02retiresma_crossover@r0.90retired
  • >2025-04blendblend← from insider_cluster + blend#6
  • >2025-04retiresma_crossover@r0.70retired
  • >2025-05redialinsider_cluster@r0.72← from insider_clusteraggressive
  • >2025-05retiresma_crossover@r0.44retired
  • >2025-07blendblend← from insider_cluster + blend#6
  • >2025-07retiresma_crossover@r0.28retired
  • >2025-08redialinsider_cluster@r0.47← from insider_clusterbalanced
  • >2025-08retireblendretired
  • >2025-10blendblend← from mean_reversion + insider_cluster
  • >2025-10retireinsider_cluster@r0.47retired
  • >2025-11redialmean_reversion@r0.41← from mean_reversiondefensive
  • >2025-11retireblendretired
  • >2026-01blendblend← from insider_cluster + blend#6
  • >2026-01retiremean_reversion@r0.41retired
  • >2026-01redialinsider_cluster@r0.41← from insider_clusterdefensive
  • >2026-01retireblendretired
  • >2026-03blendblend← from blend#6 + momentum
  • >2026-03retireinsider_cluster@r0.86retired
  • >2026-04redialblend#6@r0.91← from blend#6all-in
  • >2026-04retireinsider_cluster@r0.72retired
  • >2026-05sweepmomentum~swept← from momentum
  • >2026-05retireinsider_cluster@r0.53retired
> methodology · honest caveats

What this proves, and what it does not

> backfill vs live

Be clear which is which. Everything up to the freeze date is a backtest: the rules replayed on history, no real exposure. That is backfill. From the freeze date forward it is live paper trading, the same frozen rules on real daily prices, updated every weekday, no money at risk yet. The badge up top and the mint line on the chart mark the seam.

> how it was tested

The backtest is five years on a small US universe, long only, weekly rebalance, with real transaction costs baked in. A Thompson-sampling bandit moves capital toward whatever is beating the index on a risk-adjusted basis, with a hard drawdown circuit breaker underneath.

> where it earns trust

The headline is seed-robust, not one lucky run: across 20 random seeds, 20 of 20 beat SPY, median +66pp, Sharpe 1.11 vs the index 0.85. The honest weakness: drawdown runs a touch deeper than SPY on the median, about -26% vs -25%. This is not a free lunch on risk.

> the alt-data arms

There is an insider-cluster arm in the validated backtest: long names where several insiders filed buys. A politician-trade arm exists in the code but rides the bench, since congress disclosures lag a month-plus and the feed is noisy, so it has not earned its slot. Either way these scraped sources revise over time, so the alt-data sits out of the live headline. The live track is the price-based core, the part I reproduce exactly.

> what I am not claiming

This is a young live track, not a proven edge. Deflated-Sharpe math and a long forward run are the next bar. Until those clear, the evolving population stays opt-in and off. No margin, no options yet, no promises.