Creare un Algoritmo di Scommesse con Python: Tutorial per Principianti

Dopo tante guide teoriche, è il momento di mettere le mani sulla tastiera. Questo tutorial ti guida nella costruzione di un algoritmo di previsione calcistica funzionante usando Python, partendo da zero. Non serve essere un programmatore esperto — bastano le basi del linguaggio e la voglia di sperimentare. Il risultato sarà un modello di Poisson che scarica i dati, calcola le probabilità dei risultati e le confronta con le quote dei bookmaker per identificare potenziali value bet.
Non è un progetto da mostrare a una conferenza accademica, ma è un punto di partenza concreto che puoi estendere e migliorare man mano che le tue competenze crescono.
Passo 1: preparare l’ambiente e i dati
Il primo passo è configurare l’ambiente di lavoro. Servono Python 3.8 o superiore e tre librerie fondamentali: pandas per la manipolazione dei dati, numpy per i calcoli numerici e scipy per le funzioni statistiche (in particolare la distribuzione di Poisson). Se non le hai già installate, un semplice pip install pandas numpy scipy nel terminale risolve il problema.
La fonte dati che useremo è football-data.co.uk, un sito che dal 2001 pubblica gratuitamente i risultati e le quote di chiusura di decine di campionati. I file sono in formato CSV, direttamente importabili in pandas con una riga di codice. Per questo tutorial useremo i dati della Serie A della stagione corrente.
Il file CSV contiene una riga per ogni partita, con le colonne più importanti che sono: HomeTeam (squadra di casa), AwayTeam (squadra in trasferta), FTHG (gol della squadra di casa), FTAG (gol della squadra in trasferta), e diverse colonne con le quote dei bookmaker (B365H, B365D, B365A per Bet365, per esempio). Con pandas, il caricamento è immediato: df = pd.read_csv(url) dove url è l’indirizzo diretto del file CSV sul sito.
Una volta caricati i dati, il primo controllo è la completezza: verifica che non ci siano righe con valori mancanti nelle colonne gol, elimina le partite non ancora giocate (che nel CSV appaiono con valori NaN) e converti le colonne numeriche nel formato corretto. Questi passaggi di pulizia richiedono poche righe di codice ma sono essenziali — un modello alimentato con dati sporchi produce risultati sporchi.
Passo 2: calcolare la forza d’attacco e di difesa
Il cuore del modello è il calcolo dei parametri di Poisson per ogni coppia di squadre. Come spiegato nella guida sulla distribuzione di Poisson, servono quattro metriche di base a livello di campionato — la media gol segnati in casa, la media gol segnati in trasferta, e le rispettive medie per i gol subiti — più la forza d’attacco e di difesa di ogni squadra.
In Python, il calcolo parte dall’aggregazione dei dati per squadra. Con pandas, puoi raggruppare le partite per squadra di casa e calcolare la media gol segnati e subiti in casa, poi fare lo stesso per le partite in trasferta. Il codice è lineare: home_stats = df.groupby(‘HomeTeam’).agg({‘FTHG’: ‘mean’, ‘FTAG’: ‘mean’}) ti dà le medie per ogni squadra quando gioca in casa.
La forza d’attacco di una squadra in casa è il rapporto tra la sua media gol segnati in casa e la media del campionato. La forza di difesa è il rapporto tra la media gol subiti e la media del campionato. Con queste metriche calcolate per tutte le squadre, il parametro lambda per una partita specifica si ottiene moltiplicando la forza d’attacco della squadra di casa per la forza di difesa della squadra in trasferta per la media gol casalinghi del campionato — e viceversa per la squadra ospite.
Il risultato è una funzione che, date due squadre, restituisce due valori lambda — uno per i gol attesi della squadra di casa, uno per quelli della squadra in trasferta. Questi lambda alimentano la distribuzione di Poisson per generare la matrice delle probabilità.
Passo 3: generare la matrice delle probabilità
La matrice delle probabilità è una tabella dove ogni cella rappresenta la probabilità di un punteggio specifico — 0-0, 1-0, 0-1, 1-1, eccetera. Per calcolarla, si usa la funzione poisson.pmf di scipy, che restituisce la probabilità di osservare x gol data una media lambda.
Il codice costruisce due vettori di probabilità — uno per i gol della squadra di casa (da 0 a 7, per esempio) e uno per i gol della squadra in trasferta — e poi calcola il prodotto esterno per ottenere la matrice completa. L’assunzione di indipendenza tra i gol delle due squadre è implicita in questo prodotto, ed è il limite principale del modello base che può essere corretto con l’estensione Dixon-Coles.
Dalla matrice, estrarre le probabilità 1X2 è immediato: la probabilità di vittoria casa è la somma di tutte le celle dove i gol casa superano i gol trasferta, la probabilità di pareggio è la somma della diagonale e la vittoria trasferta è il resto. Per i mercati over/under, sommi le celle dove il totale gol supera la soglia desiderata (2,5, per esempio).
Passo 4: confrontare con le quote e trovare value bet
Il passaggio finale — e il più interessante — è confrontare le probabilità del modello con le quote dei bookmaker per identificare le value bet. Le quote sono già nel dataset di football-data.co.uk, il che rende il confronto immediato.
Per ogni partita e ogni esito (1, X, 2), il calcolo dell’expected value è: EV = probabilità_modello × quota_bookmaker – 1. Se l’EV è positivo e supera una soglia minima (diciamo il 3%), la scommessa viene segnalata come potenziale value bet.
In Python, questo si implementa con un ciclo che scorre tutte le partite non ancora giocate (o, per il backtesting, tutte le partite del dataset), calcola i lambda, genera la matrice, estrae le probabilità 1X2 e le confronta con le quote di uno o più bookmaker. Il risultato è una tabella con le colonne: partita, esito, probabilità modello, quota bookmaker, EV. Filtrando per EV positivo e ordinando per EV decrescente, ottieni la lista delle value bet del giorno.
Un aspetto pratico importante: le quote nel dataset di football-data.co.uk sono quote di chiusura — le ultime quote offerte prima del fischio d’inizio. Per il backtesting, queste sono le quote rilevanti perché rappresentano il prezzo effettivo al quale avresti potuto scommettere. Per l’uso in tempo reale, hai bisogno di quote correnti da un comparatore o da un feed dati.
Il backtesting completo si realizza applicando il modello sequenzialmente: per ogni giornata di campionato, calcoli i parametri usando solo le partite precedenti (mai i dati futuri), generi le previsioni, le confronti con le quote e registri se la scommessa avrebbe vinto o perso. Il risultato è un registro di scommesse simulate dal quale calcoli il ROI complessivo, il numero di scommesse, la percentuale di vincita e il drawdown massimo.
Passo 5: valutare e migliorare il modello
Un primo modello di Poisson su una singola stagione di Serie A produrrà tipicamente risultati modesti — un’accuratezza sul mercato 1X2 intorno al 50-52% e un ROI vicino allo zero o leggermente negativo dopo il margine del bookmaker. Questo non significa che il modello sia inutile, ma che il Poisson base è un punto di partenza, non un prodotto finito.
Le direzioni di miglioramento più immediate sono tre. La prima è la pesatura temporale: dare più importanza alle partite recenti anziché pesare tutte le partite della stagione allo stesso modo. Un approccio semplice è usare solo le ultime 10-15 partite di ogni squadra, o applicare un decadimento esponenziale come nel modello Dixon-Coles.
La seconda direzione è l’uso degli xG al posto dei gol reali. Come discusso nella guida sugli expected goals, gli xG sono un indicatore più stabile della vera capacità offensiva e difensiva di una squadra. Sostituire i gol reali con gli xG nel calcolo delle medie tende a migliorare la calibrazione del modello, soprattutto a inizio stagione quando il campione è piccolo.
La terza direzione è l’aggiunta del fattore forma. Il Poisson base usa le medie stagionali, che non catturano il momentum recente. Un aggiustamento semplice è calcolare una media pesata tra la media stagionale e la media delle ultime cinque partite, dando più peso alla forma recente quando le due divergono significativamente.
Ogni miglioramento va testato con il backtesting prima di essere implementato nelle scommesse reali. Il rischio dell’overfitting è sempre presente: un aggiustamento che migliora il ROI sulla stagione passata potrebbe peggiorarlo sulla stagione successiva. La cross-validation temporale — testare su stagioni diverse da quelle usate per la calibrazione — è la protezione migliore contro questa trappola.
Il primo algoritmo è il più importante
C’è una differenza qualitativa tra leggere di modelli statistici e costruirne uno. Quando scarichi i dati, calcoli i parametri, generi le probabilità e le confronti con le quote — quando vedi che il tuo modello prevede il 58% per il Napoli mentre il bookmaker offre quota 1,90 (53% implicito) — qualcosa scatta. Non è più teoria: è un numero che hai prodotto tu, con le tue mani e il tuo codice, e che dice qualcosa di specifico su una partita specifica.
Il primo algoritmo non sarà profittevole. Probabilmente non lo sarà nemmeno il secondo. Ma il processo di costruirlo, testarlo, vederlo fallire e cercare di capire perché è il percorso attraverso il quale si diventa scommettitori algoritmici — non leggendo guide, non guardando video, ma sbattendoci la testa personalmente.
Python non è una bacchetta magica. È un amplificatore di competenza: se capisci la statistica e il calcio, Python ti permette di esprimere quella comprensione in forma sistematica e testabile. Se non le capisci, Python ti dà solo un modo più rapido per scoprirlo. In entrambi i casi, scrivere il codice è il passo che separa chi parla di betting algoritmico da chi lo pratica.