HTML report · a method test on simulated data
Ranking the Marathon Majors by course difficulty
How much time does a marathon course cost a runner compared with Berlin? Race results have no true answer to check a method against, so this project builds one. src/build_data.py simulates a top-100 elite field for the six World Marathon Majors from 2015 to 2024 and adds a fixed penalty to every finish on each course: Berlin 0, Chicago 12, Tokyo 28, London 35, New York 85 and Boston 105 seconds. Three ranking methods then try to recover those numbers.
The within-runner paired comparison recovers every planted penalty to within 7.3 seconds: Boston +101.0, New York +77.7, London +30.7, Tokyo +21.0, Chicago +11.4. The weather-normalized top-10 average is within 11.1 seconds. The grade-adjusted energy-cost model, which reads only the course elevation profiles, puts Boston 89 seconds faster than Berlin.
1. The simulated field
The build script draws 400 men and 400 women with a fixed flat-course ability, sends 150 of each to every race (weighted toward the faster athletes), and gives each a finish time of ability plus course penalty plus a weather penalty plus normal noise with a 90-second standard deviation. The top 100 per gender are kept: 10,800 results over 54 editions, with 2020 left out. Race-day weather is a hand-entered table of temperature, humidity and wind per edition. Athlete names are combinations of real elite first and last names with a number attached; they are not real people's results.
2. The three methods
Grade-adjusted (Minetti)
Integrates the Minetti et al. (2002) energy cost of running over each course, treated as 40% climbing at its average up-grade, 40% descending and 20% flat, plus small penalties for grades over 1.5% and for many turns. It uses no race results. Boston's 136 m net descent makes it score faster than flat.
Within-runner paired
For every athlete who ran two different Majors within 18 months, divide each time by its race's weather multiplier and take the difference. Least squares fits one offset per course with Berlin fixed at zero; 2,000 bootstrap resamples give 95% intervals of about ±2 seconds.
Weather-normalized top-10 average
Each edition's top-10 average per gender, divided by a heat, humidity and wind multiplier after Maughan (2010) and El Helou et al. (2012), averaged over years and anchored to Berlin.
3. What the methods found
The paired estimate is below the planted value on every course, by 0.6 s (Chicago) to 7.3 s (New York). Only Chicago's interval contains its planted value, so the shortfall is a bias in the method on this data. The code doesn't test where it comes from.
4. The composite index
Each method's offset becomes a factor on a 7,800-second (2:10) reference, and the three are weighted:
| Rank | Course | Planted (s) | Grade-adj. (s) | Paired (s) | Top-10 (s) | CDI | CDI as s |
|---|---|---|---|---|---|---|---|
| 1 | Boston | 105 | −89.4 | +101.0 | +100.1 | 1.0092 | +72.1 |
| 2 | New York | 85 | +15.4 | +77.7 | +80.3 | 1.0089 | +69.3 |
| 3 | London | 35 | +3.6 | +30.7 | +29.7 | 1.0034 | +26.3 |
| 4 | Tokyo | 28 | −16.7 | +21.0 | +16.9 | 1.0018 | +13.9 |
| 5 | Chicago | 12 | −3.5 | +11.4 | +11.4 | 1.0012 | +9.2 |
| 6 | Berlin | 0 | 0 | 0 | 0 | 1.0000 | 0 |
The composite puts Boston (1.0092) barely ahead of New York (1.0089). The grade-adjusted method's negative Boston value pulls Boston's composite down to 72 seconds over Berlin, against 101 from the paired fit alone.
5. Sensitivity
Three variations: drop the grade-adjusted method, restrict the paired fit to men's pairs with both times under 2:10, and replace Minetti with a simpler gain-and-loss elevation model. The first two keep the order. The third moves New York to 1.0166, above Boston at 1.0131.
6. Sydney and Cape Town
The two extra courses have elevation profiles but no simulated results, so only the grade-adjusted method scores them.
7. What this doesn't show
None of these numbers measures an actual course. The test is also easier than race data would be: the weather correction uses the same curve that generated the times, and the simulation has no pacing strategy, no fatigue tied to where the hills fall, and no difference in who races where. The simulation has no elevation term, so the gap between the grade-adjusted column and the planted one says nothing about whether the Minetti model is right about Boston itself. Course profiles are hand-entered, and the 40/40/20 split is a rough stand-in for a segment-by-segment integration.
Code, data and the notebook are at github.com/lyhjeremy/marathon-majors-course-difficulty. python src/build_data.py then python src/analysis.py reproduce every number here.