- What we're trying to predict and what stays unchanged
- Our own Elo rating
- The real fixture list
- The Poisson distribution instead of a single result
- Why the favorite doesn't always win
- Why 100,000 simulations
- 100,000 seasons instead of one
- The projected table as an average of many scenarios
- Chances in individual matches
- The biggest advantage: we show uncertainty
- Why our method beats one manually assigned forecast
- The projected table vs. the current table
- How to read the predicted table
- The model doesn't predict the future — it shows probable scenarios
- Summary
A projected table shows what the final league standings might look like once all matches have been played. It is not, however, a simple prediction of upcoming results.
Instead of assuming the favorite wins every match and evenly matched teams split points, we use a probabilistic model that accounts for team strength, the actual fixture list, and the unpredictability of individual matches. For every match still to be played, we generate possible outcomes, then simulate the entire remaining season 100,000 times — each simulation can turn out differently. In one, the favorite wins. In another, it draws. In a third, it unexpectedly loses.
Only after running all the simulations do we average the results to get the predicted table. This is an important distinction: our table doesn't say "this is how the final standings will look," but rather "this is the average picture across a huge number of possible scenarios for the rest of the season."
What we're trying to predict and what stays unchanged
During the season, we know part of the future, but not all of it. We know how many points each team has earned so far, we know the results of matches already played, and we know which matches remain on the schedule. What we don't know is how many points each team will earn in its remaining matches — and that's the part of the season we try to simulate.
If a league has 20 teams, each playing 38 matches, then after 20 matchdays we already know the results of each team's first 20 games, but 18 games remain. We don't need to re-predict the first 20 matches, since they've already happened — their results are reality and remain unchanged. The model must therefore answer a specific question: what might happen in the remaining matches, and how will that affect the final table? To answer this, we rely on several components.
The projected table doesn't try to predict the past. If 10 matchdays have already been played, we know those results, and they are part of the actual season. That's why every simulation starts from the current state of the table: if Team A has 35 points, Team B has 32, and Team C has 29, each of them begins every simulation with exactly 35, 32, and 29 points respectively.
We don't re-randomize the results of matches already played — we simply add the points earned in the simulated matches yet to come. This means the projected table combines two elements: reality and probable future.
Our own Elo rating
The first and very important component of the model is our own Elo rating, which is used to determine the relative strength of teams. Every team has a rating that changes based on the results of its matches, letting us compare two teams before they even play. If one team has a significantly higher Elo rating than the other, the model treats it as the favorite; if the difference is small, the match is considered much more even.
This matters a great deal, because we don't want to predict future results based solely on a team's current position in the table. The current table tells us how many points a team has earned so far, but it doesn't necessarily reflect its current strength accurately. Two teams might both have 30 points, yet one could be clearly stronger according to our model. Likewise, a team with more points isn't automatically the favorite in its next match. The Elo rating thus provides a starting point for assessing the probability of each match's outcome.
Football is a sport where individual match results are highly variable. A stronger team can lose to a weaker one, a title contender can draw with a team near the bottom of the table, and a favorite can simply have an off day. That's why simply saying "Team A is better than Team B" isn't enough — we need to know how big the gap between the teams is, and how that gap should influence the probability of different outcomes. This is exactly where the Elo rating comes in.
The bigger the difference in strength between two teams, the higher the probability that the stronger team wins. That doesn't mean the weaker team gets zero chance, though — an upset is always possible.
Elo regression
We apply regression of Elo values toward the median to limit the influence of teams' short-term form on their longer-term rating. This is especially important for clubs that may, over a short period, go on a run of very good or very poor results. The Elo system itself reacts to every match played, so without an additional mechanism a team could hold a rating well away from the level typical for its league for a long time. Regression causes part of that deviation to fade gradually over time, and the club's rating slowly drifts back toward the median.
Regression is therefore not an extra adjustment applied after every match. Its effect depends primarily on how much time has passed since the team reached a given Elo level. After a match is played, the new result affects the rating according to the normal rules of the Elo system; later, as days go by, part of the deviation from the median is gradually damped. The longer a given level of performance goes unconfirmed, the stronger the regression effect. As a result, a short-lived burst of form doesn't stay in the system forever, but at the same time a team doesn't lose its earned rating the moment a good run ends.
This mechanism is particularly important when forecasting future competition. Its main purpose is to prevent a good start to the season from automatically translating into an extremely high probability of final success. For example, a favorite that wins its first few matches shouldn't be given a 90% chance of winning the league just because it played very well for a few weeks. Regression helps strike the right balance between current results and a more stable, long-term assessment of a team's strength. As a result, our projected tables don't overreact to short-term streaks of results, and the probabilities better reflect the level teams are expected to maintain later in the season.
The real fixture list
The second component of the model is the actual fixture list. This may seem obvious, but it matters enormously for the projected table. It's not enough to know that one team is stronger than another — we also need to know who each team will play in the rest of the season. A team might have a high Elo rating but face a very difficult run of fixtures ahead. Another team might have a slightly lower rating but mostly face lower-ranked opponents in the closing matchdays.
As a result, the fixture list can have a huge impact on the final standings. That's why our simulations don't invent a hypothetical set of matches — we use the real matches from the actual schedule. If Team A plays Team B in the next round, and Team C plays Team D, those are exactly the matches simulated. Every match matters, because the result of one game affects the point totals of two teams, and therefore their position in the final table.
The Elo rating isn't the only factor — two teams might have similar strength but very different fixture lists. Suppose Team A has very tough matches against the three strongest rivals left in the season, while Team B, in the same stretch, mostly faces mid-table and lower-table teams. Even if A and B have similar Elo ratings, their expected point totals can differ significantly. This is one reason the predicted table can be interesting even when the current table already looks fairly clear-cut.
The current table shows what has already happened. The projected table also accounts for what might still happen.
The Poisson distribution instead of a single result
You could build a very simple model: suppose Team A is stronger than Team B, so you write in a 2:0 result, move to the next match, and repeat the same logic. The problem is that such a model produces only one scenario.
If Team A actually has a 70% chance of winning, that doesn't mean it should win in 100% of our predictions — quite the opposite. If we want to correctly represent probability, the model must allow for the other possibilities too. Team A might win, might draw, but might also lose, and all of these possibilities should appear in the simulation at the appropriate frequency.
To generate match results, we use the Poisson distribution. For someone unfamiliar with statistics, the name might sound complicated, but the underlying idea is fairly simple. The Poisson distribution is a mathematical model used to describe the number of events that can occur within a given time interval, when we know the expected frequency of those events. In our case, the event in question is a goal.
We want to estimate how many goals a given team might score in a match. If the model estimates a team should score an average of about 1.8 goals, that doesn't mean we assign it exactly 1.8 goals — players obviously can't score 1.8 goals. Instead, we use a probability distribution that lets us generate different possible goal counts: 0, 1, 2, 3, 4, 5..., each with its own probability.
Imagine a match between two teams, where the model estimates that the home side should score an average of about 1.8 goals, and the away side 0.9 goals. That doesn't mean the predicted score is 1.8:0.9 — that would obviously be impossible. Instead, for each team we generate a probable number of goals.
The result could be 1:0, but just as easily 1:1, 2:0, 2:1, 0:0, or 3:1. A more surprising result could also appear. This is exactly why the Poisson distribution fits well for modeling goal counts in football — it lets us move from an expected value to an entire distribution of possible outcomes.
This distinction matters a lot. The model doesn't say: "Team A will win 2:0." Instead, it says: "Given the strength of both teams, there's a certain probability distribution over the possible outcomes of this match." As a result, a single simulation can produce one specific score — say, 2:0 — while in the next simulation it might be 1:1, in another 2:1, and in another 0:1.
Each of these outcomes is possible, though obviously not all with equal frequency. After running 100,000 simulations, we start to see the statistical picture of the full distribution of outcomes.
Why the favorite doesn't always win
This is one of the most important elements of our methodology. Imagine a match between a clear favorite and a very weak opponent. Looking only at the relative strength of the two teams, you might say: "The favorite is much better, let's just give them three points." But that's not a realistic way to model a season — even very strong teams drop points against weaker opponents.
If the model estimates the favorite has a 70% chance of winning, the remaining 30% can't simply vanish. As a simplification, imagine 10 such matches: the favorite wins 7 times, there are 2 draws, and the underdog wins once. Of course, in the actual model we don't just run ten trials and rigidly assume that exact split — this is just an illustration of the idea. With 100,000 simulations, similar probabilities are reflected across a huge number of different scenarios, which is why, in any single simulation, the favorite can lose. And that is correct behavior for the model, not a flaw.
If we assumed every team always performed exactly in line with its ranking, the projected table would be very predictable — the strongest teams would always earn three points against weaker ones, and evenly matched teams would always draw with each other. Football, however, is more complicated than that.
A match is a single event. One defensive error, a missed penalty, a red card, a great performance from the goalkeeper, or a fluke goal can completely change the result. We don't try to predict which specific upset will happen in reality — that can't be done with any real confidence. Instead, we account for the fact that upsets are statistically possible. That's a fundamental difference.
Suppose the team in first place plays a team fighting against relegation. The Elo rating clearly marks the leader as the favorite, and the model might calculate, for example:
- 75% — leader wins
- 15% — draw
- 10% — underdog wins
In a simple, single forecast, someone would probably just write in three points for the leader. We don't do that. In our simulations, around 75% of such scenarios will end in a win for the leader, but the other scenarios are possible too — in some simulations there's a draw, and in some the underdog wins. As a result, the final projected table doesn't assume an idealized world where every favorite always converts their advantage.
Imagine also that the leader has 10 remaining matches and is a clear favorite in every single one. You might think: "Since they're the favorite in every match, they'll probably win them all." That, however, isn't the right way to interpret probability. If each match has a high — but not 100% — probability of victory, then the probability of winning all of them is lower than the probability of winning any single one. A single upset is enough to reduce the final point total, and the simulations account for this effect automatically. That's why being the "favorite" in 10 separate matches doesn't automatically translate into 30 points.
If the model predicts that a favorite has a 70% chance of winning, we don't know in which specific match the remaining 30% will materialize. We can't say: "This particular match will be the upset" — the model only says that, across a large number of similar scenarios, upsets should occur with a certain frequency.
This is exactly why a large number of simulations matters so much. We're not trying to guess one specific future. We're trying to describe a whole set of possible futures.
Why 100,000 simulations
This is the most important part of the whole process. For every remaining match, the model determines the probability of different outcomes, then generates a specific result for that match. The entire process is then repeated many, many times.
Why exactly 100,000 simulations? From a purely methodological standpoint, 10,000 repetitions already gives a reliable picture and produces stable results. We chose 100,000 simulations, however, because our server can handle that many repetitions, and a larger number of simulations means random fluctuations matter less and less, making the results more averaged out. This matters especially when the differences between teams are small.
With only 1,000 simulations, regenerating the results — say, after a cache refresh — could make the predicted table look noticeably different. One batch of random draws might put a given team in 5th place, while the next batch puts it in 6th or 7th. A shift of one or two positions doesn't necessarily mean a real change in the forecast — it can simply be randomness caused by too few simulations.
With more than 10,000 repetitions, such random deviations are much smaller, and with 100,000 simulations the average result is even more stable. This doesn't mean 100,000 simulations will predict the future — it means we can estimate the outcome of our probabilistic model far more precisely, limiting the effect of randomness inherent in the sampling process itself.
In practice, 100,000 simulations is a compromise between result quality and technical feasibility. We don't need a million or ten million repetitions to get a useful result, while 100,000 gives us much greater stability than a small number of simulations — a workload the server can handle without issue.
Each simulation is a separate possible scenario for how the season ends. In one, favorites win most of their matches. In another, several upsets occur. In yet another, there might be a run of draws or unexpected wins by lower-ranked teams. This is exactly the key difference between probabilistic simulation and ordinary prediction.
The number of repetitions matters mainly for the stability of the result. With 1,000 simulations, the model can still provide useful information. The problem is that randomness in individual outcomes can have a fairly large effect on the final average — if the simulation is re-run after the cache expires, the random generator might produce a somewhat different set of results.
As a result, the projected table could shift by one or two positions, especially for teams that are very close to each other. This doesn't mean the model suddenly decided one team was much stronger. It can simply be the effect of randomness from too few repetitions.
With 10,000 simulations, the result becomes considerably more stable — you could consider that a large enough sample for a reliable picture. We go further, though, and run 100,000 simulations, because our infrastructure can handle it. More repetitions mean individual random outcomes have less and less influence on the average. In other words, the more simulations, the more averaged and stable the result becomes.
That said, the difference between 100,000 and 1,000,000 simulations won't be as large as the difference between 1,000 and 100,000 — as the number of repetitions grows, the benefit of each additional simulation diminishes. That's why 100,000 is, for us, a sensible point that provides very high stability without needlessly straining our infrastructure.
100,000 seasons instead of one
Imagine 10 matchdays remain. We could produce a single forecast: the favorite beats the bottom team, another favorite also wins, two similarly matched teams draw, and the home side wins its next match. We'd get one set of results and one final table — but how do we know that's the right scenario? We don't.
So instead of picking one scenario, we create 100,000 different scenarios. In one simulated season, the favorite earns three points; in another, it draws; in a third, it loses; and in yet another, it might win several matches in a row. Every such scenario affects the final table, and after 100,000 repetitions we can see what the average result looks like across the whole set of possible scenarios.
In the projected table, we don't analyze each match in isolation from the others. The result of one match affects the final point total of one team, while simultaneously denying points to its opponent. If a favorite loses to an underdog, the situation changes for both sides; if two teams competing for a European spot draw with each other, both lose the chance to pick up three points.
That's why we simulate the entire remainder of the competition, not just isolated individual matches — every generated version of the season leads to its own final table.
The projected table as an average of many scenarios
This leads to the most important conclusion: the projected table isn't a single forecast of the future — it's an averaged picture of 100,000 simulated seasons. If a team averages 67 points across our simulations, that doesn't mean the model believes it will definitely finish the season with exactly 67 points. In one simulation it might have 61 points, in another 64, in another 70, and in yet another 75.
After averaging across all scenarios, it might come out to around 67 points, which is why the numbers in the projected table should be read as expected values, not guaranteed outcomes.
This is another important feature of the simulation: the average may look different from any actual season. Suppose a given team finishes with different point totals across the 100,000 simulations. It might look something like this:
- 60 points — 10% of simulations
- 65 points — 20%
- 70 points — 30%
- 75 points — 25%
- 80 points — 15%
The average might come out to about 70 points, but that doesn't mean the model predicts exactly 70 points as the single most likely outcome. 70 points is the average across all scenarios.
Once all the simulations are complete, we can calculate, for each team, things like average points, average league position, and the probability of finishing in specific positions. The most important thing shown to users, though, is the projected table — the averaged result of all the simulations performed.
This lets us look at the season from a completely different angle. We're not just asking: "Who's in first place right now?" We can also ask: "What does the predicted picture of the whole season look like, once all remaining matches are accounted for?"
Chances in individual matches
Simulating the whole season also lets us show information about individual matches. For every unplayed match on the schedule, we present percentage chances for each outcome. For example:
- Home win — 55%
- Draw — 25%
- Away win — 20%
This is far more informative than simply naming one favorite. If we just wrote "Team A is the favorite," we wouldn't know by how much — 55% and 90% describe completely different situations. In both cases Team A is the favorite, but in the first match an upset is fairly likely, while in the second it's much less so.
It's also worth remembering that 70% doesn't mean "this team will definitely win." It means that, under the modeled conditions, that team's victory is expected more often than the other outcomes. If a team has a 70% chance of winning, there's still a 30% chance of something else happening, and it's precisely that remaining 30% that makes the simulations interesting.
In a single match, almost anything can happen. Only a large number of simulations lets us see how often each scenario should occur.
The biggest advantage: we show uncertainty
An ordinary predicted table can give the impression that the future is already known. For example:
- Team A — 82 pts
- Team B — 76 pts
- Team C — 71 pts
This looks like a concrete forecast. Our method has a different interpretation: if Team A averages 82 points, that doesn't mean the model considers 82 points a guaranteed result. It's the average across many possible futures.
This distinction matters a great deal, because it preserves information about uncertainty. In sport, uncertainty isn't a flaw in the model — it's part of reality, and the model should account for it.
Why our method beats one manually assigned forecast
The simplest method would look like this: find the favorite, give them the win, in an even match write in a draw, repeat for every match, and add up the points. That's quick and easy, but it also drastically oversimplifies reality.
Our method does something different. We determine team strength using our own Elo rating, pull the real fixture list, preserve every result already played, determine the probability of different outcomes for each remaining match, generate plausible results using the Poisson distribution, simulate the rest of the season 100,000 times, and then average the results of all the simulations. This means we never have to decide which specific matches will end in an upset — the model accounts for the possibility of different scenarios on its own.
Even when a single forecast looks perfectly reasonable, it is still just one scenario. We could produce a table where the best teams win most of their matches, weaker teams drop points, and evenly matched teams draw — a table that might look very realistic. The problem is that it's still just one of many possible scenarios, and we have no way of knowing why that particular scenario should be the correct one.
Running 100,000 simulations instead lets us see what happens when we allow for all the reasonable possibilities implied by the probabilities we've assigned.
Similarly, a single "most likely" table can be misleading. Suppose someone is building a forecast of the final table and has to assign a specific result to every match. For each match, they pick the most likely outcome: if the home team has a 45% chance of winning, 30% for a draw, and 25% for a loss, they write in a home win; if, in the next match, the away team has 45%, a draw is at 35%, and the home team at 20%, they write in an away win — and so on. At the end, they get one table.
The problem is that the single most likely outcome of each individual match doesn't necessarily add up to the most representative picture of the season as a whole. By always picking one outcome, you ignore all the other plausible scenarios. Simulation avoids this problem.
The projected table vs. the current table
It's worth stressing that the projected table isn't meant to replace the official standings. The current table shows the real, actual state of the competition, while the projected table answers a different question: what might the final state of the competition look like, once the remaining matches and their probable outcomes are taken into account? Both pieces of information are valuable, but for different reasons — the current table describes the present, while the projected table tries to describe a possible future.
Imagine a league where the leader has 50 points and the second-place team has 47. At first glance, the leader is in a strong position. But suppose the leader still has to play three very strong teams, while their rival has a much easier run of fixtures.
A simple forecast might say: "The leader has a three-point cushion, so they'll probably hold onto first place." The simulation, however, can paint a very different picture: in some scenarios, the leader holds their lead; in others, they drop points in tough matches; in others still, the second-place team takes advantage of its easier schedule and overtakes the leader.
The average across 100,000 simulations might show that the gap between the two teams at season's end is actually quite small. The current table and the projected table are answering two different questions.
How to read the predicted table
It's best not to treat it as a list of certain positions. If a team sits in first place with a high projected point total, that means it frequently achieved strong results across our simulations.
If two teams have very similar projected point totals, their final positions may be considerably more uncertain. A two-point gap in the average doesn't necessarily mean one team will "definitely" finish above the other — it may instead indicate that both teams are in a very similar situation, and the season's outcome depends on many possible scenarios.
The model doesn't predict the future — it shows probable scenarios
Football is probabilistic. No model knows the future results of matches. What we can do is estimate probabilities. That's exactly what we do: the Elo rating provides information about team strength, the fixture list tells us who will play whom, the match model lets us determine probable outcomes, and the Poisson distribution lets us generate plausible goal counts.
Then, 100,000 simulations let us combine all these elements into an enormous number of possible versions of how the season could end, and averaging the results produces the projected table.
This is probably the best way to summarize the whole methodology. We don't know what will happen in the remaining matches. Neither does any algorithm. What we can do is use the information available to build a probability model. Our Elo rating provides information about team strength, the real fixture list shows which matches remain, results so far determine the current state of the table, the Poisson distribution lets us generate plausible goal counts, and 100,000 simulations let us translate all these assumptions into an enormous number of possible versions of how the season ends. The projected table is then the averaged picture across all of these scenarios.
Summary
Our projected table is built in several stages. First, we use our own Elo rating to determine the relative strength of teams, and then we use the real fixture list, so that every simulation plays out exactly the matches that actually remain in the season.
We preserve all real results and start every simulation from the current state of the table, and we simulate the remaining matches 100,000 times, using a model based on the Poisson distribution. This distribution lets us model the number of goals scored by each team, so we're never limited to one predetermined result.
In every simulation, upsets can happen — the favorite might win, might draw, but might also lose. If they have a 70% chance of winning, that doesn't mean they win in every single simulation, and the remaining 30% probability must also be reflected in the results. This means we don't try to predict which specific upset will happen in reality — instead, we account for the possibility of many different upsets occurring across the whole season.
After running 100,000 simulations, we get 100,000 different final tables. The projected table is their averaged picture. In addition, for every unplayed match, we show the percentage chances of a home win, a draw, and an away win, so you can see how the model evaluates each individual match.
This is what makes our method different from simple prediction. We don't assume that every favorite will win every match, nor that every even match will end in a draw. We don't pick one scenario and present it as the future. Instead, we simulate 100,000 possible versions of the season and look at what their combined, averaged picture looks like.
That's exactly why the projected table is, first and foremost, a tool for analyzing probable scenarios — not a promise of what will actually happen on the pitch.