Backtesting gratuito del FTSE MIB in Python
Di Shakti Tiwari — Trader e ricercatore di IA applicata ai mercati
Fare backtesting del FTSE MIB non deve costare nulla. Con Python, la libreria yfinance e pandas puoi scaricare i dati storici dell'indice italiano e testare le tue strategie senza pagare alcun abbonamento. In questa guida vedrai, passo dopo passo, come costruire un ambiente di backtesting completamente gratuito per il FTSE MIB.
Cos'è il backtesting e perché conta
Il backtesting consiste nell'applicare le regole di una strategia di trading su dati storici per vedere come si sarebbe comportata in passato. Non garantisce risultati futuri, ma aiuta a scartare le idee sbagliate prima di rischiare denaro reale. Per il FTSE MIB —l'indice delle 40 maggiori società quotate alla Borsa di Milano— il backtesting è particolarmente utile perché l'indice alterna fasi di tendenza chiare e periodi laterali che mettono alla prova qualsiasi sistema.
Il punto chiave è l'onestà: un backtest fatto bene include commissioni, slippage ed evita il bias di anticipazione (usare dati non disponibili al momento del segnale).
Strumenti gratuiti di cui hai bisogno
Tutto ciò che useremo è open source e senza costi:
- Python 3 — il linguaggio di base.
-
yfinance — scarica dati storici da Yahoo Finance. Il ticker del FTSE MIB è
^FTSEMIB. - pandas — manipolazione delle serie temporali.
- numpy — calcoli numerici.
- matplotlib — visualizzazione della curva dei risultati.
Installa tutto con un solo comando:
pip install yfinance pandas numpy matplotlib
Scaricare i dati del FTSE MIB
Il primo passo è recuperare lo storico dell'indice. Con yfinance è semplicissimo:
import yfinance as yf
import pandas as pd
# Scaricare 10 anni di dati giornalieri del FTSE MIB
dati = yf.download("^FTSEMIB", start="2015-01-01", end="2025-01-01")
print(dati.tail())
L'oggetto restituito è un DataFrame di pandas con le colonne Open, High, Low, Close e Volume. Lavoreremo sul prezzo di chiusura (Close).
Costruire una strategia semplice: incrocio di medie mobili
Una delle strategie più didattiche è l'incrocio di due medie mobili. Compriamo quando la media veloce incrocia sopra quella lenta e usciamo quando incrocia sotto.
dati["media_veloce"] = dati["Close"].rolling(window=20).mean()
dati["media_lenta"] = dati["Close"].rolling(window=50).mean()
# Segnale: 1 se siamo in posizione, 0 se fuori
dati["segnale"] = 0
dati.loc[dati["media_veloce"] > dati["media_lenta"], "segnale"] = 1
# La posizione si applica al giorno successivo per evitare il bias di anticipazione
dati["posizione"] = dati["segnale"].shift(1)
Lo shift(1) è fondamentale: garantisce che la decisione di oggi possa essere eseguita solo con il prezzo di domani, replicando la realtà del trading.
Calcolare i risultati
Ora misuriamo il rendimento della strategia rispetto al semplice comprare e mantenere l'indice:
import numpy as np
dati["rendimento_mercato"] = dati["Close"].pct_change()
dati["rendimento_strategia"] = dati["rendimento_mercato"] * dati["posizione"]
# Curva del capitale accumulato
dati["capitale_strategia"] = (1 + dati["rendimento_strategia"]).cumprod()
dati["capitale_mercato"] = (1 + dati["rendimento_mercato"]).cumprod()
print(dati[["capitale_mercato", "capitale_strategia"]].tail())
Ottieni due curve: quella del buy and hold e quella della tua strategia. Confrontarle ti dice se il tuo sistema aggiunge valore reale.
Aggiungere metriche di rischio
Un backtest serio non guarda solo al rendimento finale. Queste metriche completano il quadro:
# Rendimento annualizzato
rendimento_annuo = dati["rendimento_strategia"].mean() * 252
# Volatilità annualizzata
volatilita = dati["rendimento_strategia"].std() * np.sqrt(252)
# Indice di Sharpe (tasso privo di rischio = 0)
sharpe = rendimento_annuo / volatilita if volatilita != 0 else 0
# Massimo drawdown
massimo = dati["capitale_strategia"].cummax()
drawdown = (dati["capitale_strategia"] - massimo) / massimo
max_drawdown = drawdown.min()
print(f"Sharpe: {sharpe:.2f}, Max drawdown: {max_drawdown:.2%}")
L'uso di 252 giorni di trading all'anno è una convenzione standard di mercato. L'indice di Sharpe misura il rendimento per unità di rischio, mentre il drawdown massimo indica quanto avresti sofferto nel momento peggiore.
Non dimenticare le commissioni
I backtest che ignorano i costi ingannano. Sottrai una commissione stimata ogni volta che cambi posizione:
dati["operazione"] = dati["posizione"].diff().abs()
costo_per_operazione = 0.001 # 0,1% stimato
dati["rendimento_netto"] = dati["rendimento_strategia"] - dati["operazione"] * costo_per_operazione
Adatta il costo a quello del tuo broker. Molte strategie apparentemente vincenti smettono di esserlo quando si sottraggono commissioni realistiche.
Visualizzare i risultati
Un'immagine vale più di mille numeri:
import matplotlib.pyplot as plt
dati[["capitale_mercato", "capitale_strategia"]].plot(figsize=(12, 6))
plt.title("Backtesting FTSE MIB: strategia vs. mercato")
plt.ylabel("Capitale accumulato")
plt.show()
Takeaway
Con yfinance, pandas e poche righe di Python puoi fare backtesting del FTSE MIB senza spendere nulla. La ricetta vincente è: scaricare i dati con ^FTSEMIB, applicare la tua logica con shift(1) per evitare il bias di anticipazione, includere commissioni realistiche e misurare il rischio con Sharpe e drawdown. Nessuna strategia del passato garantisce il futuro, ma un backtest onesto ti risparmia errori costosi.
Avvertenza legale
Questo articolo ha finalità esclusivamente educative e informative. Non costituisce consulenza finanziaria né una raccomandazione di acquisto o vendita. Il trading comporta il rischio di perdita del capitale. Consulta un consulente finanziario professionista prima di investire.
💬 Hai bisogno di aiuto? (Supporto gratuito)
Posso aiutarti gratis a impostare il backtesting — email shaktitiwari715@gmail.com
📢 Unisciti al nostro Telegram: https://t.me/shaktitrade
🌐 Contatto: https://optiontradingwithai.in

Top comments (0)