Under the hood

Scrape, rate, forecast, publish. Every figure below is out-of-sample.

1.58Mboat-race rows
7,693regattas, 37 seasons
23,824sailors rated
212tests, CI on clean checkout

Pipeline

1 Scrapescraper.pyTechscore: results,rosters, entries2 Storebuild_db.pySQLite x2, women'stags, HS-to-collegelinks3 Ratetrain_pl_weekly.pyPlackett-Luce, teampooling; discipline +crew layers4 Forecastpredict_upcoming_lineups.pylineups, squads, MonteCarlo odds5 Publishgenerate_site.py120K+ static pages,Flask API6 Shiprefresh_f26.shchecks, rsync,restart, health checks

Accuracy

50%56%61%66%72%Coin flip50.0%Avg finish %65.3%Elo68.7%PL static68.8%PL weekly, pre-fix69.6%PL weekly (site)70.4%
Pairs of boats ordered correctly, 4 held-out seasons (~16,000 races). Championships: 72.4% (95% CI 71.6–73.3), 166 regattas.
50506060707080809090100100said 53%, happened 52%said 58%, happened 57%said 62%, happened 61%said 68%, happened 66%said 72%, happened 70%said 77%, happened 75%said 82%, happened 80%said 87%, happened 86%said 92%, happened 90%said 97%, happened 94%
Calibration. x: model said, y: happened (%). Under the dashed line = overconfident; honest to ~85%.

Squad model error (rating points, lower is better)

Singlehanded
0.00.20.40.60.8Calibrated (site)0.43Best-rated sails0.49Most likely squad0.55Pool average0.60
Match race
0.00.20.40.60.8Calibrated (site)0.44Best-rated sails0.62Most likely squad0.55Pool average0.57

Fitted before each season, tested on it. Exact driver named: 63% / 46%. Ratings are today's, so slightly optimistic.

Decisions

ProblemChangeEvidence
Trainer stopped before convergingrating increments + first-race prior, retuned on week-ahead forecasts69.6 → 70.4% pairwise
Newcomers have no historystart at school debut median, not league mean+3.5 pts on newcomer pairs
Races in a regatta are correlatedsimulate with regatta effect, drift, same-boat effectteam totals checked at every championship
Most likely squad is a poor rating forecastprice a calibrated, probability-weighted ratingerror 0.43 vs 0.55 (SH), 0.44 vs 0.55 (MR)
Strongest-event-first sent specialists to fleetstaff singlehanded / match race first0.9% of such drivers also sail fleet that week
Availability is uncertainMonte Carlo weekend, one sailor per boat, 2,000 draws80% interval shown per entry
Scraped data vs sourcere-scrape, compare boat by boat with Techscore0 dropped boats, all numeric fields match
Page and server must quote the same priceone snapping rule in Python and JSunit test compares both

Operations

Nightly pipelinegated deploy
Optional stagesfail soft
Page generatorsidempotent
Worker restartpkill lswsgi
Import-time threadsnone
Prices (Py = JS)tested

Limits