A production-ready FastAPI application that predicts Premier League match outcomes using Elo ratings and machine learning.
- Real-time predictions for upcoming Premier League matches
- Elo rating system tracking team strength over time
- Machine learning model (multinomial logistic regression) for probability predictions
- Beautiful web dashboard with dark mode support
- REST API for programmatic access
- PostgreSQL for persistent data storage
- One-click deployment to Render
- Python 3.11+
- PostgreSQL database
- Football-data.org API token (free tier available)
-
Clone the repository
git clone https://github.com/yourusername/kickoffai.git cd kickoffai -
Create virtual environment
python -m venv venv source venv/bin/activate # On Windows: venv\Scripts\activate
-
Install dependencies
pip install -r requirements.txt
-
Configure environment
cp .env.example .env # Edit .env with your settings -
Run database migrations
alembic upgrade head
-
Start the server
uvicorn app.main:app --reload
-
Open the dashboard Navigate to http://localhost:8000
-
Sync data and train model
- Click "Sync Data" to fetch matches from football-data.org
- Click "Retrain Model" to train the prediction model
GET /healthReturns server status and version.
Response:
{
"status": "ok",
"time": "2025-01-26T12:00:00.000Z",
"version": "1.0.0"
}POST /api/syncFetches latest Premier League data from football-data.org.
Response:
{
"status": "completed",
"teams_synced": 20,
"matches": {
"matches_upserted": 380,
"new_matches": 10,
"updated_matches": 370
}
}POST /api/trainTrains the prediction model on historical data.
Response:
{
"status": "completed",
"model_id": 1,
"dataset_size": 760,
"metrics": {
"logloss": 0.9823,
"brier": 0.2156,
"train_accuracy": 0.52,
"test_accuracy": 0.48
}
}GET /api/predictions?days_ahead=14Returns predictions for upcoming matches.
Parameters:
days_ahead(optional): Number of days to look ahead (1-90, default: 14)
Response:
{
"predictions": [
{
"match_id": 12345,
"home_team": {
"id": 57,
"name": "Arsenal",
"short_name": "ARS"
},
"away_team": {
"id": 65,
"name": "Manchester City",
"short_name": "MCI"
},
"utc_date": "2025-01-28T15:00:00Z",
"probabilities": {
"home": 0.32,
"draw": 0.28,
"away": 0.40
},
"explanation": "Man City rated 85 Elo higher; Arsenal in better recent form",
"confidence": "medium"
}
],
"count": 10,
"model_info": {
"trained_at": "2025-01-26T10:00:00Z",
"logloss": 0.9823
}
}GET /api/matches/{match_id}Returns detailed information about a specific match.
GET /api/teamsReturns all Premier League teams with their current Elo ratings.
GET /api/modelReturns information about the current prediction model.
-
Fork/clone this repository to your GitHub account
-
Create a Render account at render.com
-
Connect your repository
- Go to Render Dashboard → New → Blueprint
- Select your repository
- Render will detect
render.yamlautomatically
-
Set environment variables
FOOTBALL_DATA_TOKEN: Your football-data.org API token
-
Deploy
- Click "Apply" to create the services
- Wait for deployment to complete
-
Initialize the application
# After deployment, sync data and train model via API curl -X POST https://your-app.onrender.com/api/sync curl -X POST https://your-app.onrender.com/api/train
- Create a PostgreSQL database on Render
- Create a Web Service with:
- Build Command:
pip install -r requirements.txt && alembic upgrade head - Start Command:
uvicorn app.main:app --host 0.0.0.0 --port $PORT
- Build Command:
- Set environment variables:
DATABASE_URL: From your Render PostgreSQLFOOTBALL_DATA_TOKEN: Your API tokenAPP_ENV:production
kickoffai/
├── app/
│ ├── __init__.py # App version
│ ├── main.py # FastAPI application
│ ├── api.py # API routes
│ ├── db.py # Database configuration
│ ├── models.py # SQLAlchemy models
│ ├── crud.py # Database operations
│ ├── services/
│ │ ├── football_data.py # football-data.org client
│ │ ├── elo.py # Elo rating system
│ │ ├── features.py # Feature engineering
│ │ ├── train.py # ML model training
│ │ └── predict.py # Prediction service
│ ├── templates/
│ │ ├── base.html # Base template
│ │ └── index.html # Dashboard template
│ └── static/
│ ├── styles.css # CSS styles
│ └── app.js # Frontend JavaScript
├── alembic/
│ ├── env.py # Alembic configuration
│ └── versions/ # Database migrations
├── tests/
│ ├── test_elo.py # Elo system tests
│ ├── test_features.py # Feature tests
│ └── test_predict.py # Prediction tests
├── alembic.ini # Alembic config
├── requirements.txt # Python dependencies
├── render.yaml # Render deployment config
├── .env.example # Environment template
└── README.md # This file
| Column | Type | Description |
|---|---|---|
| id | Integer | football-data.org team ID |
| name | String | Full team name |
| short_name | String | 3-letter abbreviation |
| crest_url | String | Team crest image URL |
| Column | Type | Description |
|---|---|---|
| id | Integer | football-data.org match ID |
| utc_date | DateTime | Match kickoff time (UTC) |
| status | String | SCHEDULED, FINISHED, etc. |
| home_team_id | Integer | Home team foreign key |
| away_team_id | Integer | Away team foreign key |
| home_score | Integer | Home team goals (nullable) |
| away_score | Integer | Away team goals (nullable) |
| season | String | Season year (e.g., "2024") |
| matchday | Integer | Matchday number |
| Column | Type | Description |
|---|---|---|
| id | Integer | Primary key |
| team_id | Integer | Team foreign key |
| as_of_date | DateTime | Rating timestamp |
| elo | Float | Elo rating value |
| Column | Type | Description |
|---|---|---|
| id | Integer | Primary key |
| trained_at | DateTime | Training timestamp |
| dataset_size | Integer | Number of training samples |
| logloss | Float | Log loss metric |
| brier | Float | Brier score metric |
| model_blob | Binary | Serialized model |
- Elo ratings: Home and away team Elo, difference
- Recent form: Last 5 matches points per game
- Goals: Goals for/against per match
- Home/Away specific form: Performance at home/away venues
- Multinomial Logistic Regression
- Outputs probabilities for Home Win, Draw, Away Win
- Probabilities are normalized to sum to 1
- Log Loss: Measures probability calibration
- Brier Score: Average squared error of predictions
- Accuracy: Percentage of correct predictions
pytest tests/ -v- Fork the repository
- Create a feature branch
- Make your changes
- Run tests
- Submit a pull request
MIT License - see LICENSE file for details.
- football-data.org for the Premier League data API
- Render for hosting