Zoltar is my computer program that predicts the results of NFL football games. The 2026 season will be starting soon.
One morning before work, I figured I’d look at the Las Vegas point spreads for last season (2025). Starting in 2020 (along with covid), Vegas point spreads started changing wildly from the opening values on Tuesday morning, to the closing values on early Sunday morning. This is caused by huge amounts of money being bet every week — in the billions of dollars. I used closing point spread values.
So, I fired up Zoltar and wrote a function like so (Zoltar uses the C# programming language):
static void AnalysisOfPointSpreads(
List listGameResults, string[] teamNamesShort)
{
int[] counts = new int[30];
for (int i = 0; i "lt" listGameResults.Count; ++i)
{
int week = listGameResults[i].week;
int homeID = listGameResults[i].homeID;
double homeSpread =
-1 * listGameResults[i].homeVegasMarginVictory;
if (Math.Abs(homeSpread) == 0.0) ++counts[0];
else if (Math.Abs(homeSpread) == 0.5) ++counts[1];
else if (Math.Abs(homeSpread) == 1.0) ++counts[2];
else if (Math.Abs(homeSpread) == 1.5) ++counts[3];
else if (Math.Abs(homeSpread) == 2.0) ++counts[4];
else if (Math.Abs(homeSpread) == 2.5) ++counts[5];
else if (Math.Abs(homeSpread) == 3.0) ++counts[6];
else if (Math.Abs(homeSpread) == 3.5) ++counts[7];
else if (Math.Abs(homeSpread) == 4.0) ++counts[8];
else if (Math.Abs(homeSpread) == 4.5) ++counts[9];
else if (Math.Abs(homeSpread) == 5.0) ++counts[10];
else if (Math.Abs(homeSpread) == 5.5) ++counts[11];
else if (Math.Abs(homeSpread) == 6.0) ++counts[12];
else if (Math.Abs(homeSpread) == 6.5) ++counts[13];
else if (Math.Abs(homeSpread) == 7.0) ++counts[14];
else if (Math.Abs(homeSpread) == 7.5) ++counts[15];
else if (Math.Abs(homeSpread) == 8.0) ++counts[16];
else if (Math.Abs(homeSpread) == 8.5) ++counts[17];
else if (Math.Abs(homeSpread) == 9.0) ++counts[18];
else if (Math.Abs(homeSpread) == 9.5) ++counts[19];
else if (Math.Abs(homeSpread) == 10.0) ++counts[20];
else if (Math.Abs(homeSpread) == 10.5) ++counts[21];
else if (Math.Abs(homeSpread) == 11.0) ++counts[22];
else if (Math.Abs(homeSpread) == 11.5) ++counts[23];
else if (Math.Abs(homeSpread) == 12.0) ++counts[24];
else if (Math.Abs(homeSpread) == 12.5) ++counts[25];
else if (Math.Abs(homeSpread) == 13.0) ++counts[26];
else if (Math.Abs(homeSpread) == 13.5) ++counts[27];
else if (Math.Abs(homeSpread) == 14.0) ++counts[28];
else ++counts[29];
}
for (int i = 0; i "lt" counts.Length; ++i)
{
Console.WriteLine(i + " " + counts[i]);
}
Console.ReadLine();
}
I scraped the console output and dropped the numbers into Excel, and then made a graph:
There were no huge surprises but a couple of minor surprises. The regular season had 17 games per team * 32 teams / 2 teams per game = 272 point spreads. The 4 most common point spreads were 3.0 (33 games), 2.5 (32 games), 1.0 (29 games), and 3.5 (28 games).
I was mildly surprised to see so many point spreads of 1.0 and 3.0 points, because even point spreads (without a .5) allow a betting push if the favored team covers the spread exactly. This doesn’t happen too often but it’s a real pain for bettors and sports books when it does happen.
On the graph, the 14.5 entry accounts for point spreads 14.5 and greater. These huge-point spread games happened 7 times, which is quite a bit more often than I can recall compared to previous seasons. The largest point spread was in the last week of the regular season, when the Denver Broncos were favored by 16.0 points over the Los Angeles Chargers.
The Broncos entered the game needing a win to clinch the AFC No. 1 seed and a first-round bye in the playoffs. So they were highly motivated and played their full roster of starters to try for a critical victory. On the other hand, the Chargers had already secured their playoff positioning and so they rested most starters to avoid injury.
The Broncos won by a score of 19-3 (exactly the point spread) and so any bet on that game was a push.
The point spread data analysis is where the difference between classical statistics and machine learning pops up. The graph analysis is classical statistics, and it’s up to a human to interpret the data in some way. On the other hand, machine learning would use this data to make specific predictions of some sort. For example, the point spreads of 2.0, 5.0, and 9.0 look anomalous in some way. If I had time, I’d do an analysis to predict the results of betting for those point spread values. But my morning time was up and it was time to go into work.

My football prediction system is named after the Zoltar fortune teller machine you can find in arcades. Fortune teller machines have been around for well over 100 years. Collectors pay large amounts of money for rare machines.
Left: This fortune teller machine features a grandma with a cat on her shoulder. The wax face is quite realistic. There are four known examples. The grandma’s hands and head move, and the cat moves, and a printed fortune card is given out. The clockwork mechanism came from Germany but the case and fortune card mechansim were added and the machine was distributed by the Exhibit Supply Company (ESCO) in approximately 1910 It is worth about $75,000.
Center: This “Grandmothers Predictions” machine, also known as the “Cleveland Grandma”, was manufactured by the William Gent Vending Company in about 1929. It’s worth about $25,000.
Right: This “Grandmother Prediction” machine was manufactured by the International Mutoscope Reel Company in about 1930. It’s worth about $10,000.


.NET Test Automation Recipes
Software Testing
SciPy Programming Succinctly
Keras Succinctly
R Programming
Visual Studio Live
Microsoft MLADS Conference
DevIntersection Conference
Machine Learning Week
Ai4 Conference
G2E Conference
iSC West Conference
You must be logged in to post a comment.