SlickBet ⚽: Soccer Betting Screener by SlickML🧞
🧠 Philosophy
SlickBet ⚽ screens soccer matches via the Livescore API, scores each fixture with a 12-factor statistical model (form, venue, xG, odds, and more), and ranks betting opportunities — including safer double-chance picks.
Same SlickML spirit: prototype fast 🏎, keep axes clear, and measure with backtests 🔎.
fixtures × model × filters × backtest × export
✨ Features
- 📅 Multi-day screening — next N days of fixtures
- 📊 12-factor model — form, position, home, H2H, odds, goals, venue form, defense, momentum, match stats, xG, reliability
- 🎲 Double chance — 1X / X2 / 12 with confidence grades
- 🌍 League coverage — major & minor Europe, Asia, Americas
- 📈 Backtesting — historical accuracy + API response cache
- 🔧 Hyperparameter tuning — search weights on cached data
- 📄 PDF / JSON export — shareable reports and CLI scripting
🛠 Installation
Install Python >=3.10,<3.14 and uv, then:
git clone https://github.com/slickml/slick-bet.git
cd slick-bet
uv sync --locked --all-extras --all-groups
Task runner is Poe the Poet (same idea as slick-tune). Install once:
uv tool install poethepoet
poe greet
⚙️ Configuration
Set Livescore API credentials:
export LIVESCORE_API_KEY="your_api_key"
export LIVESCORE_API_SECRET="your_api_secret"
📌 Quick Start
# Screen all leagues for tomorrow (top 20)
poe run-all --days=1 --top=20
# Major European leagues only
poe run-major
# Backtest all leagues for 1 week
poe backtest-all-global --weeks=1
from slickbet import BettingScreener, ScreenerConfig
config = ScreenerConfig(min_probability=0.60, all_leagues=True)
screener = BettingScreener(config=config)
result = screener.screen_days(3)
for bet in result.get_top_k(10):
best_dc, prob = bet.double_chance.best_double_chance
print(f"{bet.match.home_team.name} vs {bet.match.away_team.name}: {best_dc} @ {prob:.1%}")
📋 Commands
Screener
| Command | Description |
|---|---|
poe run-all --days N |
Screen ALL leagues for next N days |
poe run-all-week |
Screen ALL leagues for next 7 days |
poe run-major |
Major European leagues (tomorrow) |
poe run-major-week |
Major European leagues for 7 days |
poe run-pl --days N |
Premier League only |
poe run-bundesliga --days N |
Bundesliga only |
poe run-laliga --days N |
La Liga only |
poe run-seriea --days N |
Serie A only |
poe run-ligue1 --days N |
Ligue 1 only |
poe run |
Screen tomorrow's games |
poe run-top --top K |
Show top K opportunities |
poe run-days --days N |
Screen next N days |
Backtest & tune
| Command | Description |
|---|---|
poe backtest-all --weeks N |
Major + minor European leagues |
poe backtest-all-global --weeks N |
All leagues (EU + Asia + Americas) |
poe backtest-pl --weeks N |
Premier League backtest |
poe tune --cache-dir DIR |
Tune weights on cached API data |
API cache (fast reruns / offline tune):
# Populate cache
slickbet backtest-all --weeks 12 --cache-dir data/api_cache
# Offline rerun
slickbet backtest-all --weeks 12 --cache-dir data/api_cache --cache-only
# Tune weights
slickbet tune --cache-dir data/api_cache --trials 20
Development
| Command | Description |
|---|---|
poe check |
Format check + ruff + mypy |
poe test |
Pytest with 100% coverage gate |
poe build |
Build sdist + wheel |
poe fix |
Auto-fix lint + format |
poe clean |
Remove caches and build artifacts |
💻 CLI
slickbet # tomorrow
slickbet --days 5 --top 10
slickbet --major-only
slickbet --asia-only
slickbet --americas-only
slickbet --all-leagues
slickbet --league 2 # competition ID
slickbet --min-prob 0.60
slickbet --json
slickbet --pdf my_report.pdf
slickbet backtest --competition 2 --weeks 4
slickbet backtest-all --include-asia --include-americas --weeks 4
slickbet competitions --country England
slickbet tune --cache-dir data/api_cache
🏆 League IDs
Major Europe
| ID | League | Country |
|---|---|---|
| 1 | Bundesliga | Germany |
| 2 | Premier League | England |
| 3 | La Liga | Spain |
| 4 | Serie A | Italy |
| 5 | Ligue 1 | France |
Minor Europe
| ID | League | Country |
|---|---|---|
| 68 | Belgian Pro League | Belgium |
| 8 | Primeira Liga | Portugal |
| 6 | Super Lig | Turkey |
| 196 | Eredivisie | Netherlands |
| 17 | 1. HNL | Croatia |
| 60 | Ekstraklasa | Poland |
| 75 | Premiership | Scotland |
| 9 | Super League | Greece |
Asia
| ID | League | Country |
|---|---|---|
| 313 | Saudi Pro League | Saudi Arabia |
| 67 | Hyundai A-League | Australia |
| 28 | J. League | Japan |
Americas
| ID | League | Country |
|---|---|---|
| 23 | Liga Professional | Argentina |
| 24 | Serie A | Brazil |
| 45 | Liga MX | Mexico |
Use slickbet competitions --country <name> to discover more IDs.
🧠 Model
flowchart TB
match[Match + stats / odds / form]
subgraph factors [12 weighted factors]
direction LR
venue["venue_form 20.6%"]
momentum["momentum 12.0%"]
defense["defense 10.4%"]
home["home 9.5%"]
reliability["reliability 8.7%"]
goals["goals 8.6%"]
matchStats["match_stats 7.1%"]
h2h["h2h 6.1%"]
odds["odds 5.5%"]
position["position 4.7%"]
xg["xg 3.7%"]
form["form 3.3%"]
end
composite[Weighted composite score]
probs[Home / away win probabilities]
drawRisk[Draw risk]
pred[BetPrediction]
dc["Double chance: 1X · X2 · 12"]
grade[Confidence grade]
match --> factors
factors --> composite
composite --> probs
composite --> drawRisk
probs --> pred
drawRisk --> pred
pred --> dc
pred --> grade
Tuned 12-factor weights (BettingModel.WEIGHTS in src/slickbet/model.py):
| Factor | Weight | Description |
|---|---|---|
| Venue form | 20.6% | Home/away specific win rates |
| Momentum | 12.0% | First-half lead + win rate + comebacks |
| Defense | 10.4% | Clean sheet rate |
| Home advantage | 9.5% | Historical home edge |
| Reliability | 8.7% | Discipline / cards |
| Goals | 8.6% | Attack/defense strength |
| Match stats | 7.1% | Possession, shots, conversion |
| H2H | 6.1% | Head-to-head |
| Odds | 5.5% | Bookmaker implied probability |
| Position | 4.7% | Table differential |
| xG | 3.7% | Expected goals differential |
| Form | 3.3% | Last 5 results |
Double chance & grades
- 1X — home or draw · X2 — away or draw · 12 — no draw
- 🔥 HIGH VALUE · ✅ GOOD BET · 👍 DECENT · ⚠️ RISKY
Backtest snippet (Python)
from slickbet import Backtester, format_backtest_report
results = Backtester().run(competition_id="313", weeks=4)
print(format_backtest_report(results))
print(f"Excl. draws: {results.accuracy_excluding_draws:.1%}")
print(f"Best DC: {results.best_double_chance_accuracy:.1%}")
📁 Project structure
slick-bet/
├── assets/
│ └── logo.png
├── src/slickbet/
│ ├── __init__.py
│ ├── api.py # Livescore client + domain models
│ ├── model.py # 12-factor betting model
│ ├── screener.py # Screening + formatting
│ ├── backtest.py # Historical evaluation
│ ├── cache.py # File-based API cache
│ ├── tune.py # Weight search
│ ├── cli.py # `slickbet` entrypoint
│ └── pdf_export.py # ReportLab PDFs
├── tests/
├── .github/workflows/ # ci.yml + cd.yml only
├── .coveragerc
├── ruff.toml
├── mypy.ini
├── pytest.ini
├── pyproject.toml
└── README.md
⚠️ Disclaimer
For educational and entertainment purposes only.
- Past performance does not guarantee future results
- Sports betting involves risk of financial loss
- Predict responsibly and within your means
- Check local laws in your jurisdiction
❓ Need help?
Join our Slack to talk with the SlickML team.
License
MIT — see LICENSE.
Release files for slickbet 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| slickbet-0.3.0.tar.gz | 178.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| slickbet-0.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 246.7 kB
Release files / slickbet-0.3.0.tar.gz
| Download URL | slickbet-0.3.0.tar.gz |
|---|---|
| Size | 178.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
1c99b433699d075e8833af3c03ae84052e025d07663e0f106ab05d9208e69225
|
|
BLAKE2b-256 checksum How to use checksums |
7c551aa0e70f721a4ff4a6a4b9b88b6e7fb0648a46e964e8eefcbe6d7d2f6f2a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.9.13 {"installer":{"name":"uv","version":"0.9.13"},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / slickbet-0.3.0-py3-none-any.whl
| Download URL | slickbet-0.3.0-py3-none-any.whl |
|---|---|
| Size | 68.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
3dbd1354f02ddde4d3a4fb81356c4fecd08674954ac4db99767ace4ccecb2076
|
|
BLAKE2b-256 checksum How to use checksums |
23c6b750ea2be171096aea54001e660e54e2e0ccbe17f075962611c18a56a754
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.9.13 {"installer":{"name":"uv","version":"0.9.13"},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|