Modulo 5 — Trading algoritmico · Lezione 22 di 23 · 12 min

Backtest senza illusioni: costi, overfitting e walk-forward

Un backtest minimale in Python con costi, le statistiche in R e le tecniche per non ingannarsi.

Un backtest minimale

Il codice sotto entra all'apertura della candela successiva al segnale, usa stop e target fissi in pip e, se nella stessa candela vengono toccati entrambi, assume in modo prudente che sia stato colpito prima lo stop. Il costo dello spread è sottratto in R.

import numpy as np

def backtest(df, signals, stop_pips, rr=2.0, pip=0.0001, spread_pips=0.8):
    """signals: Series con +1 (long), -1 (short), 0 (nessun segnale)."""
    results = []
    i, n = 0, len(df)
    while i < n - 1:
        s = signals.iloc[i]
        if s == 0:
            i += 1
            continue
        entry = df["open"].iloc[i + 1]
        risk = stop_pips * pip
        stop = entry - s * risk
        target = entry + s * risk * rr
        outcome, j = None, i + 1
        while j < n:
            hi, lo = df["high"].iloc[j], df["low"].iloc[j]
            hit_stop = lo <= stop if s == 1 else hi >= stop
            hit_tp = hi >= target if s == 1 else lo <= target
            if hit_stop:              # prudenza: lo stop vince in caso di dubbio
                outcome = -1.0
                break
            if hit_tp:
                outcome = rr
                break
            j += 1
        if outcome is None:
            break
        results.append(outcome - spread_pips / stop_pips)   # costo in R
        i = j + 1
    return np.array(results)

Statistiche

def stats(r):
    wins, losses = r[r > 0], r[r <= 0]
    equity = np.cumsum(r)
    drawdown = (np.maximum.accumulate(equity) - equity).max()
    return {
        "trades": len(r),
        "win_rate": len(wins) / len(r),
        "expectancy_R": r.mean(),
        "profit_factor": wins.sum() / abs(losses.sum()) if len(losses) else float("inf"),
        "max_drawdown_R": drawdown,
    }

I nemici del backtest

  • Look-ahead: usare in una candela informazioni che si conoscono solo dopo (come gli swing non confermati)
  • Overfitting: provare 200 combinazioni di parametri e tenere la migliore. La migliore è quasi sempre fortuna
  • Costi: spread, commissioni, slippage e swap. Testa con costi più alti del previsto
  • Qualità dei dati: buchi, orari sfalsati, differenze tra broker
  • Campione: poche operazioni non dimostrano nulla

Tecniche di controllo

  • In-sample e out-of-sample: sviluppa su una parte dei dati, verifica sull'altra mai guardata
  • Walk-forward: ottimizza su una finestra, testa sulla successiva, e fai scorrere le finestre nel tempo
  • Sensibilità dei parametri: se cambiando n da 3 a 4 il risultato crolla, il modello è fragile
  • Test su strumenti e periodi diversi, senza modificare le regole
  • Monte Carlo sull'ordine delle operazioni per stimare i drawdown possibili

Regola d'oro

Se il risultato sembra troppo bello per essere vero, probabilmente c'è un errore nel test. Cerca il bug prima di credere al risultato.

Hai una domanda o vuoi condividere il tuo esercizio?

Scrivi nella community, oppure entra nella sala segnali gratuita su Telegram.

Contenuto educativo, non è consulenza finanziaria. Il trading comporta rischi. ICT è un termine riferito ai materiali di Michael Huddleston: questo corso è indipendente e non affiliato.