This project aims to provide strength rankings for football teams in europe's biggest leagues using an elo algorithm and expected goals(xG) of games. Expected goals is a statistical method of quantifying a teams chance creation. Teams which create better chances and concede fewer chances than expected will increase in rating. This project aims to provide a more accurate measure of team strength than league tables or even expected points(xPts) tables by considering the strength of opponents and chance creation rather than goals scored.
Each teams strength rating is split into a defense and attack rating. When teams play against one another, the attack rating of one team is compared with the defense rating of the opponent to predict the chance creation(xG) output of the attacking team and vice versa.
The elo algorithm is implemented within python and interactive visualisations are created using the Altair package. Data is stored in a sqlite3 database. The webapp is built on the Flask Framework within python. Football data was scraped from understat and club badges taken from Luuk Hopman
Elo Model:
-
elo.py
- Contains a base EloStrategy class and StandardElo class which builds upon this
- StandardElo predict_result method takes two parameter ('threshold' (this is the average xG a team creates in a game) and 'exponent') and makes a prediction of home team xG based on home team attack rating and away team defense rating. Away team xG prediction is based on away team attack rating and home team defense rating
- StandardElo update_elo method takes 1 parameter (learning rate) and the xG result of a game.
- If the home team creates more xG than was predicted the home attack rating will increase and away team defense rating will decrease and vice versa.
- Scope for more advanced elo predict and update methods to be added by adapting base EloStrategy class
-
season.py
- Contains Team, Match, Gameweek and Season classes
- When simulating a season, a Season object is created containing Gameweeks, which contain Matches, in which 2 Teams play against each other
- Match objects use specified EloStrategy predict and update methods
- The Season simulate_season method goes through all completed games storing elo rankings in the elo_tracker datastructure after each game
- save_data_to_sql method saves the elo_tracker to a sqlite3 db 'elo.db'
- Season.loss() method allows you to calculate loss across the season according to a specified loss function
-
predict.py
- Contains a ShotDistribution and Predictor Class
- ShotDistribution takes an xG prediction and splits it into 'shots' using generate_shot_list method
- Predictor simulates the shot events of each team and stores the result. This is repeated many times to generate scoreline and win/draw/lose probabilites
- This can then return all games for the next gameweek
- Scope to add more advanced ShotDistribution classes
-
colours.py, badges.py, elo_chart.py
- Used to create interactive visualisations for webapp using altair
-
main.py
- contains a function to print future gameweek predictions for a given league
- also has a function to update the db and visualisations
Webapp:
Features a webpage for EPL, LaLiga, Serie A and Bundesliga
- app.py
- Uses flask framework to create webpages for each league with interactive line chart of elo rankings over current season and table containing most up to date ranking