in sviluppo
KillerBet
Terminale di analisi calcistica su oltre trent'anni di storico, con un agente AI che interroga il database.
-
299.986
partite storiche, dal 1993 a oggi
-
358
campionati
-
177.610
giocatori in anagrafe
-
20
strumenti dell'agente AI sul database
Il problema
Analizzare un campionato significa incrociare storico, quote e formazioni su fonti che non parlano fra loro, con formati e granularità diverse. A mano si riesce per poche partite alla volta, e i numeri che contano di più, come il valore di una quota alla chiusura, spariscono se nessuno li cattura al momento giusto.
Cosa ho costruito
Un terminale che unifica tre fonti in un solo database interrogabile: un hub per competizione con partite, tabellone, classifiche e marcatori; un match center con eventi, formazioni e il movimento delle quote dall’apertura alla chiusura; il confronto fra oltre venti bookmaker.
Sopra il database c’è una chat in tool-use: venti strumenti che l’agente usa per rispondere interrogando i dati veri (briefing di partita, testa a testa, tendenze degli arbitri, movimenti di quota) invece di riassumerli a memoria. Le risposte arrivano in streaming e le conversazioni hanno memoria, anche fra sessioni.
Cosa c’è dentro
L’ETL ha 22 loader su tre fonti e 14 job schedulati che catturano quote, risultati e formazioni, scritti per una macchina che ogni tanto dorme: i job arretrati si fondono in un’esecuzione sola invece di accumularsi in raffica. Ogni chiamata al modello AI passa da un guardiano di spesa (budget verificato prima della chiamata, costo reale registrato dopo) e da un router che sui turni di seguito sceglie il modello più economico, perché è lì che il contesto trascinato costa. Il rating delle squadre è un Glicko-2 implementato da zero; sopra c’è un modello XGBoost validato walk-forward, con l’anti-leakage scritto come test, non come commento. La misura del cantiere:
| Cosa | Quanto |
|---|---|
| Righe di Python | 42.000 |
| Righe di TypeScript | 22.000 |
| Endpoint API | 140 |
| Migrazioni di schema | 11 |
| Test, con CI bloccante | 463 |
Il numero che si è bocciato da solo
La pipeline del closing line value mostrava un 72,5% di scelte in guadagno sulla chiusura. Rimisurata come si deve, con la stessa definizione di quota da una parte e dall’altra, è diventata un −3,5%: quel 72,5% era un artefatto del confronto, non un merito del modello. Il modello predittivo è stato declassato a sola lettura e i suoi numeri compaiono solo dietro un avviso. È la parte del progetto che mostro più volentieri: la revisione che ha smontato il suo numero migliore è nel repo, scritta e datata.
Stack
- Python 3.12
- FastAPI
- SQLAlchemy 2
- SQLite
- APScheduler
- Claude API (tool-use)
- ChromaDB
- XGBoost
- scikit-learn
- React 18
- TypeScript
- Vite
- TanStack Query