Archive · As of polls closing, March 17, 2026 · March 17, 2026 A message from Ryan McCombRyan's message How it did →
Retrospective · IL-9 Democratic primary, March 17, 2026

How the forecast held up

In the winter of my sophomore year I built a forecast for the IL-9 Democratic primary, the first open race for this seat since 1998, and ran it every day until the polls closed on March 17. The rest of this site is preserved as it stood at that moment; this page is what came after, with the final forecast graded against the precinct returns, the two models set side by side, and the photos, press and people from the campaign.

Ryan McComb · Evanston, Illinois

Ryan, in a Polymarket hoodie and holding a laptop, answers a radio reporter holding a microphone.
Primary night, March 17. Answering a radio reporter’s questions in the Polymarket hoodie.
2.3 ptslargest miss on any candidate’s district share
72%of precinct winners called right, weighted by votes
77.2 / 77.3%Biss’s chance in the final model run and in the markets at poll close
63,378Kalshi and Manifold snapshots logged before the polls closed
Graded against the precinct returns

How it did

On the topline the precinct model did about as well as one could reasonably ask: no candidate finished more than 2.3 points from the published forecast, and the order at the top of the field, including the Biss-over-Abughazaleh call that was the only real suspense of the night, came out right. I would not oversell it, since some of that precision is the ordinary luck of errors that partly cancel, and the two smallest candidates finished in the opposite order from the forecast, but a six-way forecast built on polling this thin had no business being this close.

CandidateForecastResultMiss
Daniel Biss31.629.3+2.3
Kat Abughazaleh24.326.4−2.0
Laura Fine19.720.0−0.3
Mike Simmons9.07.2+1.8
Phil Andrew5.06.1−1.1
Bushra Amiwala6.05.1+0.9

The model saw the district too smoothly

Where it fell down is visible the moment the two maps sit side by side. The forecast placed almost every precinct close to each candidate’s district average, so in it Biss leads four precincts in five and Abughazaleh nearly all of the rest, every one of them in Chicago; the voters drew something far more fractured, with Abughazaleh carrying most of the Chicago precincts and two-thirds of McHenry County, where the model under-forecast her by about sixteen points, Fine winning about a quarter of suburban Cook, and Biss holding two-thirds of suburban Cook and three-quarters of Lake.

What the model drew

What the voters drew

Shade shows the leader’s margin. Hover or tap a precinct.

What I would do differently

I would discount thin market days far more aggressively and let the interval widen as liquidity falls, since some of the February swings were a handful of traders and little else. I would give the precinct model real geographic variance instead of letting it collapse toward the district mean, which is a modelling choice and not a data problem. And I would write it in something other than Stata: the general-election model at the bottom of this page is cleaner and far faster in about a sixth of the code.

January 30 to March 17

The two forecasts

The site ran two forecasts that never fed into each other. One read the race from prediction markets and updated every three minutes; the other built the race up from the ground, precinct by precinct, in Stata. Keeping them separate made the disagreements visible, which turned out to be the most useful thing about running both.

Model one · Markets

The live pulse

Every three minutes the site pulled contract prices from Kalshi and Manifold, blended them sixty-forty in Kalshi’s favour, and smoothed the result so that a single trader on a thin book could not throw the line around; candidates with no buy-side liquidity fell back to their last traded price rather than a meaningless midpoint.

One point every six hours. Hover or tap the chart for a date.

The markets opened with Biss at roughly two chances in three. The low came on February 10 and 11, when Fine traded near 32% and Biss fell to 52.5%; Abughazaleh peaked near 39% on March 11. By the time the polls closed the markets had Biss at 77% and Fine under 1%.

Model two · Precincts

The ground up

The precinct model gave each of the 436 precincts a baseline for every candidate from a 50/50 blend of age and ideology affinities, taken from the Data for Progress crosstabs, rescaled the district to a recency-weighted polling average, and then simulated the primary 100,000 times with shared polling error, lane correlations and a random turnout draw.

il9_model_v3.doStata
159* Weights from DFP crosstab Q3 (Vote Choice by Age)
161gen age_biss        = (pct_18_29*8)  + (pct_30_44*19) + (pct_45_64*18) + (pct_65plus*21)
162gen age_abughazaleh = (pct_18_29*30) + (pct_30_44*24) + (pct_45_64*18) + (pct_65plus*12)
163gen age_fine        = (pct_18_29*0)  + (pct_30_44*4)  + (pct_45_64*11) + (pct_65plus*16)
 
209gen composite_biss  = (age_biss + ideo_biss) / 2
Simulations per run
100,000
Variables per precinct (ACS and 2024 results)
79
Poll half-life
60 days
Weight on an opponent’s / own internal poll
0.3× / 0.15×
Systematic polling error (sd)
8 pts
Turnout draw
150k ± 22k

Where they finished

77.2%Biss, final model run (March 5)
77.3%Biss, markets at poll close
15.6 / 23.5%Abughazaleh, model / markets

The final run, frozen on March 5, gave Biss a 77.2% chance of winning, Abughazaleh 15.6% and Fine 7.2%. When the polls closed twelve days later the markets had Biss at 77.3%, so two models that shared no inputs ended the race within a tenth of a point of each other on the frontrunner, if not on who was chasing him.

March 17, 2026

Primary night

A laptop on a desk showing an Illinois results map, lit in red and blue.
Illinois results on the laptop, March 17.
Coverage

In the press

A local reporter tweeted about the site, Capitol Fax picked it up, and for about six weeks a surprising number of people in the district were checking a page I maintained from a lunch table at ETHS.

The lunch table

Thank you

This whole thing ran out of a lunch table at ETHS, where my friends sat every day while I talked about polling averages and precinct maps instead of anything normal, told me when something on the site looked off, and kept showing up anyway.

Sammy Jain, Teddy Gutstein, Ido Salant, John Spyrson and Nick Jackson

Thank you as well to Elle Zebala, who has been telling me exactly why my political theories are wrong since middle school; to Mr. Patel, my AP Gov teacher, and Julian Cronin; to Matthew Eadie, the local reporter whose tweet started all of this; and to my parents, who never once told me to stop, even on the night Railway deleted the entire data volume at three in the morning and I rebuilt it from CSV backups.

Downloads

The archive

The snapshot file holds all 71,196 snapshots the scraper wrote, through the afternoon of March 18. The 63,378 taken before the polls closed are the ones the rest of this site shows; the remainder are the morning after.

Coda · General election, November 3

The race that’s left

The primary was the hard part. The general is close to a formality in a district this blue, so the forecast for it is a deliberately small one I wrote in a single night: every precinct starts from its 2024 result and takes three shocks in each simulation, a national swing, a swing it shares with demographically similar precincts, and a little noise of its own, all applied in log-odds space so that the safest precincts move the least.

Biss’s median share of the two-party vote
73.9%
Daniel Biss (D) vs John Elleson (R)
71.3 to 76.280% interval
>99.9%of simulations won by Biss
≈287kexpected ballots

Election day: Tuesday, November 3, 2026.

1,200 of the 10,000 simulations, one dot each
Projected margin by precinct
R+D+ (deeper is bluer)

Built by Ryan McComb. Market data from Kalshi and Manifold; precinct returns for the March 17 primary as posted March 22. Inspired by Nate Silver, FiveThirtyEight and Galen Druke.