This backtest uses a simplified model (opening spread + cumulative season win % as the only inputs). It does NOT replicate the live analysis approach we use on game pages, which includes current form, injury news, head-to-head matchup, pitcher/lineup data, and qualitative judgement.
This is the model we COULD build with what's in a free historical odds dataset. The live analyses are richer, but we have no way to backtest them retrospectively because we'd need to know what news existed BEFORE each game.
Bottom line: the result below is the test of a naive baseline, not the test of our actual approach. But the lessons it teaches are real.
Final bankroll after 4,615 bets
$49.03
Started $1,000 Β· Net profit β$950.97 Β· ROI β95.1%
π Headline Stats
Games considered
13,903
Bets placed
4,615
Wins
2,309
Losses
2,212
Pushes
94
Win rate
51.07%
Break-even at β110
52.38%
Max drawdown
96.3%
Total wagered
$27,797
Avg CLV
β4.68 pts
π Bankroll Trajectory
Bankroll over 4,615 bets. Starting line at $1,000. Bankroll dropped below $500 within the first 500 bets and never recovered.
π¬ What the Model Did
Data source
github.com/FinnedAI/sportsbookreview-scraper β pre-scraped NBA games 2011β2021 with opening/closing spreads, opening/closing totals, closing moneylines, per-quarter scores.
IF edge β₯ 2% AND EV > 0:
stake = min(0.02 Γ bankroll, 0.25 Γ Kelly Γ bankroll)
BET on spread at β110
Resolve via actual game margin
Sizing + gates
Edge threshold
β₯ 2% over fair market
EV gate
EV per $1 stake must be positive
Sizing
Quarter Kelly, capped at 2% of bankroll
Bet odds
Standard β110 (spread market)
Vig assumption
4.5% (single-side half = 2.25% adjustment)
π Why It Failed β The CLV Smoking Gun
Win rate of 51.07% versus break-even of 52.38% means we lost roughly 1.3 percentage points per bet to vig. At 4,615 bets, that compounds catastrophically.
But the leading indicator is CLV (Closing Line Value):
Avg CLV
β4.68 pts
Negative CLV bets
2,161
Neutral CLV bets
812
Positive CLV bets
1,642
Translation: When we took a bet, the closing line moved AWAY from us on average. Sharp money agreed with our pick less often than they agreed with the other side. The market was processing information faster than our simple record-based model.
This is the signal of an unsharp bettor. The CLV told us within the first 500 bets that the strategy was broken β long before bankroll hit zero.
π The 5 Lessons This Backtest Teaches
Lesson 1 β A simple model is a money pit. Adding "team record" as a signal to a market-derived prior produced a strategy that lost 95% of bankroll over 4,615 bets. The market already prices in records. Layering them back in just adds noise.
Lesson 2 β Win rate at 51% is meaningfully losing. 51% sounds "close to 50/50" but you need 52.4% to break even on β110 bets. The 1.4-point gap is the vig.
Lesson 3 β CLV is the leading indicator. Within ~500 bets we had clear negative CLV. We didn't need to wait for the full bankroll loss to know the strategy was broken. Track CLV in real time on live bets.
Lesson 4 β Quarter Kelly + 2% cap saved us from ruin. Even with a losing model, sizing prevented total wipeout in early bets. Bankroll ended at $49, not $0. Full Kelly would have busted within months.
Lesson 5 β Our LIVE analyses include nuance this backtest doesn't. Form trends, injuries, matchup tactics, lineup news β those aren't in the historical dataset. The simplified model failing here doesn't prove our live picks fail. But it DOES prove that simple statistical models aren't enough on their own.
π Per-Season Breakdown
Season
Games
2011
1,074 (lockout-shortened)
2012
1,314
2013
1,319
2014
1,311
2015
1,316
2016
1,309
2017
1,312
2018
1,312
2019
1,143 (COVID-shortened)
2020
1,171 (COVID-shortened)
2021
1,322
Total
13,903
π What Comes Next
The backtest validates everything the methodology page warned about:
Beating the market is hard. The market is genuinely efficient.
A 51% win rate is a LOSING strategy at standard juice.
CLV detects strategy failure faster than bankroll does.
Sizing prevents catastrophe even when the model is wrong.
For our live picks:
Track CLV on every actual bet placed
If avg CLV stays negative across 30+ live bets, the live analysis isn't beating the market either β recalibrate
If avg CLV is positive, the qualitative inputs (current form, injuries, matchup) ARE adding value above the simple model
This is the test we need to actually run with real money or paper trades over the coming months
This backtest is the floor. Our live analysis should beat it. If our live analysis just matches it, we're no better than a record-based model β and that loses money. Track CLV religiously.
π¦ Reproduce This
Backtest script lives at /bets/learn/backtest-script.js.
To re-run: clone github.com/FinnedAI/sportsbookreview-scraper, set NBA_DATA env to the path of data/nba_archive_10Y.json, run with Node.js.