f1-strategy.
The pit loss is a myth
An end-to-end analysis of 15 Formula 1 seasons (366,508 timed laps, 12,881 pit stops) that derives pit-loss and undercut models from timing data alone, and shows that the rule the pit wall leans on does not predict anything.
366,508
timed laps · 327 races · 15 seasons
0.52 → 0.82
ROC-AUC: pit-loss rule vs gap + tyre age, out of sample
62% → 6.6%
undercut conversion, under 1.5 s gap vs beyond 3 s
57
tests · Python and SQL cross-checks agree
Demo · interactive replay
The gap decides it.
Pick the gap to the car ahead before the stop. The archive says how often the undercut converted, and what the pit-wall rule would have called.
Gap before the stop
1,528 measured pairs, rival responded
Converted
Gap < 0.5 s
62.3%
n = 53 · 95% Wilson interval 48.8% to 74.1%
Every bin here clears that test, so the rule calls all of them. That is why it scores ROC-AUC 0.52 while gap plus tyre age reaches 0.82 on races the model never saw.
Binned from the same 1,528 undercut pairs the notebook plots, rival responded within five laps. The pit-wall rule labels all four bins as on, which is the point: it does not separate them.
Undercut Success by Gap
Pit Loss Distribution
Model Performance
Undercut Success by Circuit
Team Decision Quality





Tech Stack
The brief · problem → approach → result
01 / The problem
Formula 1 teams call an undercut on when the gap to the car ahead is smaller than the time a pit stop costs. It is the pit-wall shorthand, and nobody runs it against the archive to see whether it actually predicts anything.
02 / The approach
Take the public Formula 1 timing archive (366,508 laps across 15 seasons) and estimate the pit loss at every circuit from lap times alone. Then test the rule out of sample against what actually decided each move, and model the next stop one lap ahead.
03 / The result
The pit-loss rule scores ROC-AUC 0.52, no better than a coin flip, while gap and tyre offset reach 0.82 on seasons the model never saw. Nearly half of the undercuts teams attempted were long shots that converted 6% of the time. The whole thing ships as a tested pipeline: 57 tests, Parquet and SQLite storage, and two results computed twice to prove Python and SQL agree.
The Pipeline
Ingest
CC0 Ergast archive
Validate
24 quality checks
Model
pit loss & undercut
Predict
stop one lap ahead
Cross-check
Python & SQL agree
A Python package ingests the CC0 Ergast-lineage archive, validates it (surfacing three genuine data defects, including 810 pit-stop durations published as lap times), and builds stint, pit-event and cohort tables into Parquet and SQLite. Two of the questions are answered twice, once in Python and once in SQL window functions, so the two implementations can be shown to agree.
What It Answers
Pit Loss per Circuit
Estimated what a stop costs from timing data alone: (in-lap + out-lap) minus two times recent clean pace. Median green-flag pit loss lands at 21.5 seconds across 36 circuits, and a second implementation in SQL window functions agrees on every one of them.
When the Undercut Works
The pit-wall shorthand says an undercut is on when the gap is smaller than the pit loss. It turns out to be uninformative: once the rival stops too, both cars pay the loss and it cancels. What decides the move is the gap plus the tyre offset, converting 62% of the time from under 1.5 seconds and 6.6% beyond three.
Predicting Stops One Lap Ahead
A leakage-safe model (features to lap N, label at N+1, split by race) ranks the next stop at ROC-AUC 0.80. It is a ranking model, not an alarm: PR-AUC 0.136 is the honest number, and the notebook reports the precision-recall trade-off alongside it.
Built To Be Checked
Every derivation validated twice
- 0157 tests cover the pit-loss, stint and undercut derivations.
- 02Stint reconstruction: 0 disagreeing laps of 366,508 between Python and SQL.
- 03Circuit pit loss: the SQL reimplementation agrees on all 36 circuits.
- 04A synthetic fixture with an injected 15 s loss is recovered exactly.
What the model cannot say
A ranking model, not an alarm
The stop-prediction model ranks well (ROC-AUC 0.80) but PR-AUC 0.136 is the honest number: at the default threshold it catches 1.3% of stops.
Why circuits differ
Monaco converts 7% of its undercuts and Bahrain 49%, yet a circuit's own pit loss does not order that table (rho = -0.30, p = 0.19).
Observational, not chosen
A low-odds attempt can be forced by a rival's stop or the weather rather than picked freely, and the notebook says so.
Built on the CC0 Ergast/Jolpica timing archive. The notebook, not a README, is the single source of truth: dataset, method, findings, limitations and the reproduce path all live in one place.
Technology Architecture
f1-strategy-analytics/
├── src/ # python package (pipeline + models)
│ ├── pipeline.py # ingest, validate, build tables
│ ├── metrics.py # pit-loss & undercut estimators
│ └── ...
├── sql/ # second implementation, in SQL
│ ├── 01_stint_reconstruction.sql
│ └── 02_circuit_pit_loss.sql
├── tests/ # 57 tests over the derivations
├── notebooks/
│ └── analysis.ipynb # the single notebook: story + figures
├── reports/
│ ├── findings_summary.md # every number, with provenance
│ └── figures/ # 16 figures
└── requirements.txt