← Torna agli articoli
March 10, 2026
5 min di lettura

Validazione Multi-Symbol: Testa la Tua Strategia su Tutte le Coppie

Validazione Multi-Symbol: Testa la Tua Strategia su Tutte le Coppie
#algotrading
#backtest
#validazione
#multi-symbol
#diversificazione
#crypto

Articolo della serie "Backtest Senza Illusioni"

Hai ottimizzato una strategia su ETHUSDT. 25 mesi di dati, 12+ parametri. Il backtest mostra PnL +55%, 500 trade, MaxDD -0,9%, posizione aperta il 15% del tempo. La curva equity sale in modo regolare. I parametri hanno superato l'analisi del plateau — l'ottimo appare ampio. Il walk-forward produce WFER > 0,6. Il bootstrap Monte Carlo mostra un 5° percentile positivo.

Tutto è perfetto. Tranne una cosa: hai testato la strategia su un solo strumento.

Lanci lo stesso algoritmo con gli stessi parametri su BTCUSDT — PnL +8%. Su SOLUSDT — PnL -12%. Su DOGEUSDT — PnL -34%. La strategia che ha superato tutti i controlli su ETH si rivela non profittevole sulla maggior parte delle altre coppie.

Non è un bug. Questa è la trappola del singolo symbol — una delle forme di overfitting più comuni e insidiose nell'algotrading.

La Trappola del Singolo Strumento

Trappola del singolo symbol: una curva equity brillante circondata da strategie fallimentari su altri asset

Ottimizzare una strategia su un singolo symbol significa essenzialmente adattarla alla dinamica dei prezzi di un asset specifico. Anche se hai eseguito il walk-forward, anche se il bootstrap mostra ampi intervalli di confidenza — tutti questi controlli sono stati eseguiti all'interno di una singola serie temporale.

Il walk-forward verifica la robustezza nel tempo: i parametri funzionano sui dati futuri dello stesso strumento. Il Monte Carlo verifica la robustezza nell'ordine dei trade: la strategia può reggere una sequenza diversa. Ma nessuno di questi metodi verifica la robustezza tra gli strumenti: la strategia funziona su altri asset con caratteristiche diverse.

Se una strategia è profittevole solo su ETHUSDT — ha catturato non un'inefficienza di mercato, ma la struttura specifica della serie dei prezzi di ETH:

  • Pattern di candele caratteristici unici di ETH
  • Livelli di volatilità specifici a cui le soglie sono calibrate
  • Le specificità di liquidità e microstruttura di questa particolare coppia
  • Correlazione con BTC, caratteristica di un periodo specifico

Nulla di tutto ciò è edge. Questo è curve fitting a livello di strumento.

Gruppi di Symbol (Tier) nel Mercato Crypto

Matrice delle caratteristiche per tier di symbol

Non tutte le criptovalute sono uguali. Per una validazione multi-symbol significativa, è necessario capire che gli strumenti si dividono in gruppi con caratteristiche fondamentalmente diverse.

Tier 1: Blue Chip (BTC, ETH)

Alta liquidità, volatilità relativamente bassa, flusso istituzionale. Correlazione con il macro (S&P 500, DXY, tassi Fed). Order book profondi, spread ridotti, funding rate stabili. Volatilità giornaliera tipica: 2-4%.

Tier 2: Large Cap (SOL, BNB, ADA, XRP, AVAX)

Liquidità moderata, volatilità elevata. I movimenti sono spesso guidati dalla dinamica settoriale (L1 vs L2, DeFi vs infra). I funding rate sono più volatili. Gli spread sono più ampi. Volatilità giornaliera tipica: 4-6%.

Tier 3: Mid Cap (DOGE, SHIB, PEPE, ARB, OP)

Meme coin e token narrativi. Alta volatilità, bassa correlazione con i fondamentali. I movimenti sono determinati dai social media, dai listing, dalle narrative. Order book sottili su alcuni exchange. Volatilità giornaliera tipica: 6-10%.

Tier 4: Low Cap (Nuovi Listing)

Volatilità estrema, order book sottili, rischio di manipolazione. Spesso storia insufficiente per un backtest completo. Volatilità giornaliera tipica: 10-20%+.

Tabella Riepilogativa delle Caratteristiche

Caratteristica Tier 1 Tier 2 Tier 3 Tier 4
Volatilità giornaliera 2-4% 4-6% 6-10% 10-20%+
Spread medio (perps) 0,01-0,02% 0,02-0,05% 0,05-0,15% 0,1-0,5%+
Profondità order book (top 5 bps) $5-50M $1-10M $100K-2M $10K-200K
Funding rate (media assoluta) 0,005-0,01% 0,01-0,03% 0,02-0,08% 0,05-0,2%+
Correlazione con BTC 0,85-0,95 0,6-0,85 0,3-0,7 0,1-0,5
Storia minima 5+ anni 2-5 anni 6 mesi - 3 anni < 6 mesi

Ogni tier è un "mondo" separato con la propria microstruttura. Una strategia calibrata per il Tier 1 entra in un ambiente estraneo quando si sposta al Tier 3.

Metodologia di Validazione Multi-Symbol

Metodologia di validazione multi-symbol: ottimizza, testa lo stesso tier, testa altri tier, analizza i risultati

Passo 1: Ottimizza su un Singolo Symbol

Scegli un symbol per l'ottimizzazione — ad esempio, ETHUSDT. Esegui la pipeline completa: ottimizzazione Optuna, analisi del plateau, walk-forward. Fissa i parametri.

Passo 2: Testa sui Symbol dello Stesso Tier

Esegui la strategia con gli stessi parametri su 5-10 symbol dello stesso tier. Per il Tier 1 è limitato (BTC + ETH), ma per Tier 2 e Tier 3 ci sono abbastanza symbol.

Passo 3: Testa sui Symbol di Altri Tier

Esegui la strategia su 3-5 symbol di ciascun altro tier. Questo è il test più severo: se la strategia funziona su ETHUSDT (Tier 1) e su DOGEUSDT (Tier 3), la probabilità di curve fitting è minima.

Passo 4: Analizza i Risultati per Gruppo

Aggrega le metriche per tier e valuta la robustezza cross-symbol.

Metriche per Ogni Symbol

Per ogni symbol, registra:

  • PnL — rendimento totale
  • MaxDD — drawdown massimo
  • N trade — numero di trade
  • Win rate — frazione di trade profittevoli
  • PnL/giorno attivo — rendimento per unità di tempo attivo (maggiori dettagli in PnL per tempo attivo)

Criteri di Superamento

Una strategia supera la validazione multi-symbol se:

  1. Profittevole su >= 60% dei symbol nello stesso tier
  2. PnL medio nel gruppo è positivo
  3. MaxDD non aumenta drasticamente (non più di 2-3x rispetto al symbol di ottimizzazione)
  4. Se la strategia è profittevole SOLO sul symbol di ottimizzazione — rigettare

Esempio: Tre Strategie, Tre Risultati

Tre strategie a confronto: A (verde, successo parziale), B (ciano, robusta), C (rosso, overfitting)

Consideriamo un esempio concreto. Tre strategie (Strategia A, Strategia B, Strategia C), ottimizzate su ETHUSDT, testate su 12 symbol in quattro tier.

Strategia A (Ottimizzata su ETHUSDT)

Parametri: PnL +55%, ~500 trade, ~15% tempo attivo, MaxDD ~0,9%.

Symbol Tier PnL MaxDD N trade Win rate PnL/giorno attivo
ETHUSDT* 1 +55,2% -0,9% 491 52,1% 0,48%
BTCUSDT 1 +31,4% -1,8% 478 50,8% 0,27%
SOLUSDT 2 +22,7% -3,1% 512 49,2% 0,18%
BNBUSDT 2 +18,3% -2,7% 467 48,9% 0,16%
AVAXUSDT 2 +8,1% -4,5% 498 47,6% 0,07%
ADAUSDT 2 -3,2% -6,1% 445 46,1% -0,03%
DOGEUSDT 3 -12,8% -9,4% 531 44,3% -0,10%
SHIBUSDT 3 -18,7% -12,1% 487 43,1% -0,16%
PEPEUSDT 3 -24,3% -14,8% 556 42,7% -0,18%
ARBUSDT 3 -7,4% -7,2% 419 45,8% -0,07%
OPUSDT 3 -5,1% -6,8% 402 46,2% -0,05%

* — symbol di ottimizzazione

Risultati per tier:

Tier Symbol Profittevoli PnL medio MaxDD medio
Tier 1 2 2 (100%) +43,3% -1,4%
Tier 2 4 3 (75%) +11,5% -4,1%
Tier 3 5 0 (0%) -13,7% -10,1%

Verdetto: La Strategia A funziona su Tier 1-2 ma fallisce completamente sul Tier 3. Questa è una tipica strategia calibrata per un ambiente a bassa volatilità. Per un portafoglio di blue chip e large cap — accettabile. Per uso universale — no.

Strategia B (Ottimizzata su ETHUSDT)

Parametri: PnL +25%, ~40 trade, ~5% tempo attivo.

Symbol Tier PnL MaxDD N trade Win rate
ETHUSDT* 1 +25,1% -2,3% 38 57,9%
BTCUSDT 1 +21,8% -2,8% 41 56,1%
SOLUSDT 2 +19,4% -3,5% 44 54,5%
BNBUSDT 2 +16,7% -3,1% 37 54,1%
AVAXUSDT 2 +12,3% -4,2% 42 52,4%
ADAUSDT 2 +8,9% -4,8% 39 51,3%
DOGEUSDT 3 +4,2% -6,7% 48 47,9%
SHIBUSDT 3 -1,3% -8,4% 45 46,7%
PEPEUSDT 3 -3,8% -9,1% 52 46,2%
ARBUSDT 3 +6,1% -5,8% 40 50,0%
OPUSDT 3 +3,7% -6,2% 38 50,0%

Risultati per tier:

Tier Symbol Profittevoli PnL medio MaxDD medio
Tier 1 2 2 (100%) +23,5% -2,6%
Tier 2 4 4 (100%) +14,3% -3,9%
Tier 3 5 3 (60%) +1,8% -7,2%

Verdetto: La Strategia B è profittevole su 9 degli 11 symbol (82%). Il PnL medio è positivo su tutti i tier. Il MaxDD cresce in modo prevedibile con il tier. Questa è una strategia robusta con un vero vantaggio di mercato. Nonostante il PnL più modesto sul symbol di ottimizzazione (+25% vs +55%), la Strategia B è significativamente più affidabile della Strategia A.

Strategia C (Ottimizzata su ETHUSDT)

Parametri: PnL +300%, ~400 trade, ~45% tempo attivo, MaxDD ~17%.

Symbol Tier PnL MaxDD N trade Win rate
ETHUSDT* 1 +301,2% -17,1% 418 53,8%
BTCUSDT 1 +42,7% -28,4% 395 48,6%
SOLUSDT 2 -18,3% -41,2% 456 44,1%
BNBUSDT 2 +12,1% -33,7% 387 46,8%
AVAXUSDT 2 -31,4% -52,8% 471 42,3%
ADAUSDT 2 -44,7% -58,1% 412 40,5%
DOGEUSDT 3 -67,2% -74,3% 528 38,1%
PEPEUSDT 3 -72,1% -81,6% 574 37,4%

Verdetto: La Strategia C è overfitting classico. +301% su ETHUSDT, ma perdite catastrofiche sulla maggior parte delle altre coppie. Il MaxDD sul Tier 3 supera il 70% — questa è distruzione di capitale. La strategia ha catturato pattern unici di ETH, non un'inefficienza di mercato. Rigettare.

Perché le Strategie Si Rompono su Altri Symbol

Quattro fattori che rompono le strategie: volatilità, liquidità, microstruttura e transizioni di regime

1. Disallineamento di Volatilità

Il motivo più comune. I parametri della strategia sono calibrati su un livello specifico di volatilità. Se la strategia usa una soglia di ingresso del 2% — per ETH con volatilità giornaliera del 3%, questo è un filtro ragionevole. Per DOGE con volatilità giornaliera dell'8% — questa soglia scatta troppo spesso, generando una massa di segnali falsi.

Allo stesso modo, uno stop loss dell'1% è adeguato per ETH, ma per PEPE è normale "rumore", e lo stop viene colpito decine di volte al giorno.

2. Differenze di Liquidità

La strategia assume l'esecuzione immediata degli ordini al prezzo corrente. Su BTCUSDT con profondità dell'order book di 50Mentro5bpsquestoeˋrealistico.SuARBUSDTconprofonditaˋdi50M entro 5 bps — questo è realistico. Su ARBUSDT con profondità di 200K — il tuo ordine da $10K sposterà il prezzo, e l'esecuzione effettiva sarà peggiore dello 0,05-0,2%. Su 500 trade, questo significa 25-100% perso solo per slippage.

3. Microstruttura di Mercato

Ogni strumento ha la propria microstruttura:

  • Funding rate: su BTC, il funding è costantemente positivo in un mercato toro (+0,01% ogni 8 ore). Sulle meme coin, il funding può saltare da -0,3% a +0,5%. Maggiori dettagli — in I funding rate distruggono la tua leva.
  • Spread: sul Tier 1 lo spread è 0,01%, sul Tier 4 — 0,5%. Una strategia con take-profit piccoli non può essere profittevole quando lo spread supera la dimensione del take.
  • Pattern di manipolazione: wick, spoofing, wash trading — si manifestano diversamente su ogni tier.

4. Sensibilità al Regime

Le altcoin si comportano diversamente nelle diverse fasi di mercato:

  • In un trend rialzista, le altcoin sovraperformano BTC (beta > 1)
  • In un trend ribassista, le altcoin scendono più di BTC
  • In un mercato laterale, le altcoin possono correlarsi con BTC o muoversi sulle proprie narrative

Una strategia ottimizzata in una fase su un symbol può essere ottimalmente calibrata sul lag/lead di quello specifico symbol rispetto a BTC — e questo lag/lead cambierà quando il regime cambia.

Scalatura Adattiva dei Parametri

Scalatura adattiva dei parametri: indicatore del rapporto di volatilità con slider dei parametri che si trasformano da soglie strette a soglie ampie

Eseguire una strategia con parametri identici su tutti i symbol è scorretto. Ma la ri-ottimizzazione completa su ogni symbol vanifica il vero scopo della validazione multi-symbol (i parametri diventano "nativi" di ogni symbol).

Il compromesso è la normalizzazione dei parametri per volatilità:

import numpy as np

def scale_params_by_volatility(
    base_params: dict,
    optimization_symbol_vol: float,
    target_symbol_vol: float,
    vol_sensitive_params: list[str],
) -> dict:
    """
    Scala i parametri della strategia per volatilità del symbol target.

    Args:
        base_params: parametri ottimizzati sul symbol originale
        optimization_symbol_vol: volatilità giornaliera del symbol di ottimizzazione
        target_symbol_vol: volatilità giornaliera del symbol target
        vol_sensitive_params: lista dei parametri sensibili alla volatilità
    """
    vol_ratio = target_symbol_vol / optimization_symbol_vol
    adjusted = base_params.copy()

    for param in vol_sensitive_params:
        if param in adjusted:
            adjusted[param] = adjusted[param] * vol_ratio

    return adjusted

base_params = {
    "entry_threshold": 0.02,     # 2% — soglia di ingresso
    "stop_loss": 0.01,           # 1% — stop loss
    "take_profit": 0.03,         # 3% — take profit
    "trailing_stop": 0.008,      # 0,8% — trailing stop
    "atr_multiplier": 2.5,       # moltiplicatore ATR (non scalato)
    "rsi_period": 14,            # periodo RSI (non scalato)
    "ma_fast": 10,               # MA veloce (non scalato)
    "ma_slow": 50,               # MA lenta (non scalato)
}

vol_sensitive = ["entry_threshold", "stop_loss", "take_profit", "trailing_stop"]

eth_vol = 0.032     # 3,2%
doge_vol = 0.081    # 8,1%

doge_params = scale_params_by_volatility(
    base_params, eth_vol, doge_vol, vol_sensitive
)

print("ETH params:", {k: f"{v:.4f}" for k, v in base_params.items() if k in vol_sensitive})
print("DOGE params:", {k: f"{v:.4f}" for k, v in doge_params.items() if k in vol_sensitive})

Output:

ETH params:  {'entry_threshold': '0.0200', 'stop_loss': '0.0100', 'take_profit': '0.0300', 'trailing_stop': '0.0080'}
DOGE params: {'entry_threshold': '0.0506', 'stop_loss': '0.0253', 'take_profit': '0.0759', 'trailing_stop': '0.0203'}

Lo stop loss è aumentato dall'1% al 2,53% — appropriato per la volatilità giornaliera dell'8,1% di DOGE. Senza scalatura, uno stop loss dell'1% verrebbe colpito dal "rumore" decine di volte.

Importante: scala solo le soglie di prezzo (ingressi, stop, take). I periodi degli indicatori (RSI, MA) e i moltiplicatori (moltiplicatore ATR) di solito non vengono scalati — sono già normalizzati per volatilità attraverso l'indicatore stesso.

Due Modalità di Validazione

  1. Modalità rigorosa (senza scalatura): esegui con parametri identici. Un test di robustezza assoluta. Se la strategia è profittevole — l'edge è forte.

  2. Modalità adattiva (con scalatura): esegui con parametri normalizzati. Un test della robustezza della logica della strategia, con la concessione che i livelli di volatilità differiscono.

Si raccomanda di eseguire entrambi i test. Modalità rigorosa — per valutare la "forza" dell'edge. Modalità adattiva — per l'applicazione pratica.

Punteggio di Robustezza Cross-Symbol

Radar multi-symbol di robustezza cross

Per la valutazione quantitativa della robustezza multi-symbol, introduciamo una metrica composita — Cross-Symbol Robustness Score (CSRS).

Formula

CSRS=w1Rprofit+w2Rpnl+w3Pconsistencyw4Pvariance\text{CSRS} = w_1 \cdot R_{profit} + w_2 \cdot R_{pnl} + w_3 \cdot P_{consistency} - w_4 \cdot P_{variance}

dove:

  • RprofitR_{profit} — frazione di symbol profittevoli:

Rprofit=NprofitableNtotalR_{profit} = \frac{N_{profitable}}{N_{total}}

  • RpnlR_{pnl} — PnL medio ponderato per liquidità normalizzato:

Rpnl=i=1NliPnLii=1NliR_{pnl} = \frac{\sum_{i=1}^{N} l_i \cdot \text{PnL}_i}{\sum_{i=1}^{N} l_i}

dove lil_i è la liquidità del symbol ii (volume medio giornaliero).

  • PconsistencyP_{consistency} — bonus per coerenza cross-tier:

Pconsistency=Nprofitable_tiersNtotal_tiersP_{consistency} = \frac{N_{profitable\_tiers}}{N_{total\_tiers}}

  • PvarianceP_{variance} — penalità per alta varianza del PnL tra i symbol:

Pvariance=σ(PnL1,,PnLN)max(PnLˉ,0.01)P_{variance} = \frac{\sigma(\text{PnL}_1, \ldots, \text{PnL}_N)}{\max(|\bar{\text{PnL}}|, 0.01)}

Pesi Predefiniti

Componente Peso Motivazione
w1w_1 (frazione profittevole) 0,35 Più importante: la strategia deve funzionare sulla maggioranza
w2w_2 (PnL medio) 0,25 Rendimenti assoluti
w3w_3 (cross-tier) 0,25 Bonus per universalità
w4w_4 (penalità varianza) 0,15 Penalità per instabilità

Interpretazione del CSRS

CSRS Interpretazione
> 0,7 Robustezza eccellente. La strategia funziona sulla maggior parte degli strumenti.
0,5 — 0,7 Buona robustezza. La strategia funziona nel suo tier e parzialmente negli altri.
0,3 — 0,5 Borderline. La strategia funziona su un ristretto insieme di symbol.
< 0,3 Bassa robustezza. Il curve fitting a livello di strumento è probabile.

Implementazione Completa: Pipeline di Validazione Multi-Symbol

Pipeline di elaborazione dati 3D isometrica per la validazione multi-symbol delle strategie

import numpy as np
import pandas as pd
from dataclasses import dataclass, field
from typing import Callable, Optional

@dataclass
class SymbolResult:
    """Risultato della strategia su un singolo symbol."""
    symbol: str
    tier: int
    pnl: float
    max_dd: float
    n_trades: int
    win_rate: float
    pnl_per_active_day: float
    avg_daily_volume: float  # liquidità

@dataclass
class TierResult:
    """Risultato aggregato per tier."""
    tier: int
    symbols: list[SymbolResult]
    n_symbols: int
    n_profitable: int
    profit_ratio: float
    avg_pnl: float
    avg_max_dd: float
    pnl_std: float

@dataclass
class MultiSymbolResult:
    """Risultato completo della validazione multi-symbol."""
    symbol_results: list[SymbolResult]
    tier_results: list[TierResult]
    csrs: float
    passed: bool
    optimization_symbol: str
    report: str

SYMBOL_TIERS = {
    1: ["BTCUSDT", "ETHUSDT"],
    2: ["SOLUSDT", "BNBUSDT", "ADAUSDT", "XRPUSDT", "AVAXUSDT"],
    3: ["DOGEUSDT", "SHIBUSDT", "PEPEUSDT", "ARBUSDT", "OPUSDT"],
}

SYMBOL_VOLATILITY = {
    "BTCUSDT": 0.028, "ETHUSDT": 0.032,
    "SOLUSDT": 0.052, "BNBUSDT": 0.038, "ADAUSDT": 0.048,
    "XRPUSDT": 0.045, "AVAXUSDT": 0.055,
    "DOGEUSDT": 0.081, "SHIBUSDT": 0.092, "PEPEUSDT": 0.105,
    "ARBUSDT": 0.068, "OPUSDT": 0.063,
}

SYMBOL_VOLUME = {
    "BTCUSDT": 15e9, "ETHUSDT": 8e9,
    "SOLUSDT": 2e9, "BNBUSDT": 1.5e9, "ADAUSDT": 800e6,
    "XRPUSDT": 1.2e9, "AVAXUSDT": 500e6,
    "DOGEUSDT": 1e9, "SHIBUSDT": 400e6, "PEPEUSDT": 600e6,
    "ARBUSDT": 300e6, "OPUSDT": 250e6,
}


def run_multi_symbol_validation(
    strategy_fn: Callable,
    base_params: dict,
    optimization_symbol: str,
    data_loader: Callable,
    vol_sensitive_params: list[str],
    adaptive: bool = True,
    csrs_weights: tuple = (0.35, 0.25, 0.25, 0.15),
    min_profit_ratio: float = 0.6,
) -> MultiSymbolResult:
    """
    Pipeline completa di validazione multi-symbol.

    Args:
        strategy_fn: funzione della strategia (data, params) -> (pnl, max_dd, n_trades, win_rate, returns)
        base_params: parametri ottimizzati su optimization_symbol
        optimization_symbol: symbol di ottimizzazione
        data_loader: funzione di caricamento dati (symbol) -> np.ndarray
        vol_sensitive_params: parametri da scalare per volatilità
        adaptive: usa la scalatura della volatilità
        csrs_weights: pesi (w1, w2, w3, w4) per CSRS
        min_profit_ratio: frazione minima di symbol profittevoli in un tier
    """
    w1, w2, w3, w4 = csrs_weights
    opt_vol = SYMBOL_VOLATILITY.get(optimization_symbol, 0.03)

    symbol_results = []

    for tier, symbols in SYMBOL_TIERS.items():
        for symbol in symbols:
            data = data_loader(symbol)
            if data is None or len(data) < 100:
                continue

            if adaptive and symbol != optimization_symbol:
                sym_vol = SYMBOL_VOLATILITY.get(symbol, 0.05)
                params = scale_params_by_volatility(
                    base_params, opt_vol, sym_vol, vol_sensitive_params
                )
            else:
                params = base_params.copy()

            pnl, max_dd, n_trades, win_rate, returns = strategy_fn(data, params)

            active_days = max(n_trades * 0.5, 1)  # stima approssimativa
            pnl_per_day = pnl / active_days

            symbol_results.append(SymbolResult(
                symbol=symbol,
                tier=tier,
                pnl=pnl,
                max_dd=max_dd,
                n_trades=n_trades,
                win_rate=win_rate,
                pnl_per_active_day=pnl_per_day,
                avg_daily_volume=SYMBOL_VOLUME.get(symbol, 1e6),
            ))

    tier_results = []
    tiers_present = sorted(set(r.tier for r in symbol_results))

    for tier in tiers_present:
        tier_symbols = [r for r in symbol_results if r.tier == tier]
        n_profitable = sum(1 for r in tier_symbols if r.pnl > 0)
        pnls = [r.pnl for r in tier_symbols]

        tier_results.append(TierResult(
            tier=tier,
            symbols=tier_symbols,
            n_symbols=len(tier_symbols),
            n_profitable=n_profitable,
            profit_ratio=n_profitable / len(tier_symbols) if tier_symbols else 0,
            avg_pnl=np.mean(pnls),
            avg_max_dd=np.mean([r.max_dd for r in tier_symbols]),
            pnl_std=np.std(pnls),
        ))

    all_pnls = [r.pnl for r in symbol_results]
    all_volumes = [r.avg_daily_volume for r in symbol_results]
    n_total = len(symbol_results)
    n_profitable = sum(1 for r in symbol_results if r.pnl > 0)

    r_profit = n_profitable / n_total if n_total > 0 else 0

    total_vol = sum(all_volumes)
    r_pnl_raw = sum(r.pnl * r.avg_daily_volume for r in symbol_results) / total_vol
    r_pnl = 1 / (1 + np.exp(-r_pnl_raw * 5))

    profitable_tiers = sum(1 for tr in tier_results if tr.avg_pnl > 0)
    p_consistency = profitable_tiers / len(tier_results) if tier_results else 0

    pnl_std = np.std(all_pnls) if len(all_pnls) > 1 else 0
    pnl_mean = np.mean(all_pnls) if all_pnls else 0.01
    p_variance = pnl_std / max(abs(pnl_mean), 0.01)
    p_variance = min(p_variance, 5.0)  # limita la penalità

    csrs = w1 * r_profit + w2 * r_pnl + w3 * p_consistency - w4 * (p_variance / 5.0)
    csrs = max(0, min(1, csrs))  # clamp a [0, 1]

    opt_tier = None
    for tier, symbols in SYMBOL_TIERS.items():
        if optimization_symbol in symbols:
            opt_tier = tier
            break

    same_tier_result = next((tr for tr in tier_results if tr.tier == opt_tier), None)
    passed = (
        csrs >= 0.5
        and (same_tier_result is None or same_tier_result.profit_ratio >= min_profit_ratio)
        and np.mean(all_pnls) > 0
    )

    report = _generate_report(
        symbol_results, tier_results, csrs, passed,
        optimization_symbol, adaptive
    )

    return MultiSymbolResult(
        symbol_results=symbol_results,
        tier_results=tier_results,
        csrs=csrs,
        passed=passed,
        optimization_symbol=optimization_symbol,
        report=report,
    )


def _generate_report(
    symbol_results, tier_results, csrs, passed,
    opt_symbol, adaptive
) -> str:
    """Genera il report testuale."""
    lines = []
    lines.append("=" * 60)
    lines.append("REPORT DI VALIDAZIONE MULTI-SYMBOL")
    lines.append(f"Symbol di ottimizzazione: {opt_symbol}")
    lines.append(f"Modalità: {'adattiva' if adaptive else 'rigorosa'}")
    lines.append(f"CSRS: {csrs:.3f}")
    lines.append(f"Superato: {'SÌ' if passed else 'NO'}")
    lines.append("=" * 60)

    for tr in tier_results:
        lines.append(f"\n--- Tier {tr.tier} ---")
        lines.append(f"  Symbol: {tr.n_symbols}, Profittevoli: {tr.n_profitable} "
                      f"({tr.profit_ratio:.0%})")
        lines.append(f"  PnL medio: {tr.avg_pnl:.2%}, MaxDD medio: {tr.avg_max_dd:.2%}")
        lines.append(f"  DevStd PnL: {tr.pnl_std:.2%}")

        for sr in tr.symbols:
            marker = "*" if sr.symbol == opt_symbol else " "
            status = "+" if sr.pnl > 0 else "-"
            lines.append(
                f"  {marker} [{status}] {sr.symbol:12s} "
                f"PnL={sr.pnl:+.2%}  MaxDD={sr.max_dd:.2%}  "
                f"Trade={sr.n_trades:4d}  WR={sr.win_rate:.1%}"
            )

    lines.append("\n" + "=" * 60)
    return "\n".join(lines)

Esempio di Utilizzo della Pipeline

def my_strategy(data, params):
    """La tua strategia. Restituisce (pnl, max_dd, n_trades, win_rate, returns)."""
    pass

def load_ohlcv(symbol):
    """Carica i dati OHLCV per un symbol."""
    pass

base_params = {
    "entry_threshold": 0.02,
    "stop_loss": 0.01,
    "take_profit": 0.03,
    "trailing_stop": 0.008,
    "atr_multiplier": 2.5,
    "rsi_period": 14,
    "ma_fast": 10,
    "ma_slow": 50,
}

result = run_multi_symbol_validation(
    strategy_fn=my_strategy,
    base_params=base_params,
    optimization_symbol="ETHUSDT",
    data_loader=load_ohlcv,
    vol_sensitive_params=["entry_threshold", "stop_loss", "take_profit", "trailing_stop"],
    adaptive=True,
)

print(result.report)
print(f"\nCSRS: {result.csrs:.3f}")
print(f"Superato: {result.passed}")

Quando la Validazione su Singolo Symbol È Accettabile

Eccezioni: order book di market making, arbitraggio cross-exchange e pattern di correlazione unici specifici dell'asset

Non ogni strategia deve funzionare su più strumenti. Esistono casi legittimi in cui il singolo symbol è un approccio normale:

Market Making su uno Specifico Order Book

Una strategia di market making (ad es. usando il modello Avellaneda-Stoikov) è per definizione legata a uno specifico order book. I parametri dipendono dalla microstruttura specifica: profondità, spread, posizione in coda, tasso di esecuzione. Testare su un altro symbol non ha senso — è un order book diverso.

Arbitraggio tra Coppie Specifiche

L'arbitraggio del funding rate o l'arbitraggio cross-exchange è per definizione legato a coppie di strumenti specifiche. La validazione qui avviene su altri exchange con le stesse coppie, non su symbol diversi.

Strategie che Usano Esplicitamente Proprietà Uniche dell'Asset

Se una strategia si basa su una proprietà specifica di un asset (ad es. la correlazione di BTC con l'hashrate o la correlazione di ETH con le gas fee), la validazione multi-symbol non è applicabile. Ma tali strategie sono rare.

In tutti gli altri casi — se la strategia si basa su segnali "generici" (crossover MA, RSI, momentum, mean reversion) — la validazione multi-symbol è obbligatoria. Se una strategia generica funziona solo su un symbol, non è edge — è overfitting.

Relazione con Altri Metodi di Validazione

Tre assi ortogonali di validazione: tempo (walk-forward), strumento (multi-symbol), ordine dei trade (Monte Carlo)

La validazione multi-symbol è uno dei tre metodi ortogonali di test out-of-sample:

Metodo Asse di Validazione Cosa Rivela
Walk-Forward Tempo Overfitting a un periodo specifico
Multi-symbol Strumento Overfitting a un asset specifico
Bootstrap Monte Carlo Ordine dei trade Dipendenza da una sequenza specifica

Ogni metodo verifica la robustezza lungo il proprio asse. Una strategia può superare il walk-forward ma fallire il multi-symbol (curve fitted allo strumento). Può superare il multi-symbol ma fallire il Monte Carlo (dipende da un ordine fortunato dei trade).

Massima protezione dall'overfitting: usa tutti e tre i metodi.

Pipeline di validazione completa:

  1. Ottimizzazione dei parametri su un singolo symbol
  2. Analisi del plateau — verifica della stabilità dell'ottimo
  3. Walk-forward — validazione sull'asse temporale (WFER > 0,5)
  4. Multi-symbol — validazione sull'asse degli strumenti (CSRS > 0,5)
  5. Bootstrap Monte Carlo — intervalli di confidenza (5° percentile > 0)
  6. Tieni conto dei funding rate e dell'asimmetria perdita-profitto

Una strategia che supera tutti e sei i controlli ha una probabilità minima di essere un artefatto di overfitting.

Estensioni: Correlazione tra Symbol e Strategie a Cascata

Grafo di rete di correlazione delle criptovalute con flussi di allocazione della strategia a cascata

La validazione multi-symbol rivela un ulteriore aspetto: le correlazioni tra symbol. Se una strategia è profittevole su BTC e ETH ma non profittevole su tutte le altcoin — questa è un'informazione che l'edge è legato all'alta correlazione BTC-ETH. Analisi dettagliata delle strutture di correlazione — nell'articolo Correlazione dei segnali e pairs trading.

Per i portafogli di strategie, i risultati multi-symbol determinano su quali strumenti lanciare una strategia. La Strategia A dell'esempio precedente — solo Tier 1-2. La Strategia B — Tier 1-3. Questi sono dati di input per l'orchestrazione a cascata, dove diverse strategie vengono lanciate su diversi strumenti in base al loro profilo di robustezza.

Conclusione

La validazione multi-symbol non è opzionale — è un passo obbligatorio per qualsiasi strategia che pretenda un vantaggio di mercato generalizzato. Punti chiave:

  1. Una strategia che funziona su un solo symbol è molto probabilmente overfit alle specificità di quel symbol. Eccezioni: market making, arbitraggio, strategie basate su proprietà uniche dell'asset.

  2. Il raggruppamento per tier è obbligatorio. Non puoi confrontare i risultati su BTC (Tier 1) con i risultati su PEPE (Tier 3) senza comprendere le differenze di volatilità, liquidità e microstruttura.

  3. La scalatura adattiva dei parametri — normalizzazione delle soglie per volatilità — migliora significativamente il realismo del testing multi-symbol.

  4. CSRS > 0,5 — una soglia minima ragionevole. La strategia dovrebbe essere profittevole su >= 60% dei symbol nello stesso tier, e il PnL medio su tutti i symbol dovrebbe essere positivo.

  5. Walk-forward + Multi-symbol + Monte Carlo — tre assi di validazione ortogonali. Ogni metodo cattura ciò che gli altri mancano. Usali tutti e tre.

Una strategia con PnL +25% e CSRS 0,72 è più affidabile di una strategia con PnL +300% e CSRS 0,18. La prima guadagna dall'inefficienza del mercato. La seconda guadagna dalla memorizzazione di una singola serie di prezzi.


Link Utili

  1. Lopez de Prado, M. — Advances in Financial Machine Learning (Wiley)
  2. Pardo, R. — The Evaluation and Optimization of Trading Strategies (Wiley)
  3. Bailey, D.H. et al. — The Probability of Backtest Overfitting
  4. Aronson, D.R. — Evidence-Based Technical Analysis
  5. Kevin Davey — Building Winning Algorithmic Trading Systems (Wiley)
  6. Harvey, C.R. & Liu, Y. — Backtesting (2015)
  7. Chan, E. — Algorithmic Trading: Winning Strategies and Their Rationale (Wiley)
  8. Binance Research — Cryptocurrency Correlation Analysis
  9. NumPy — numpy.random.choice
  10. Pandas — DataFrame

Citazione

@article{soloviov2026multisymbolvalidation,
  author = {Soloviov, Eugen},
  title = {Validazione Multi-Symbol: Testa la Tua Strategia su Tutte le Coppie},
  year = {2026},
  url = {https://marketmaker.cc/it/blog/post/multi-symbol-validation},
  version = {0.1.0},
  description = {Perché una strategia ottimizzata su ETHUSDT può fallire sulle altcoin. Come testare correttamente su gruppi di coppie (blue chip, large cap, shitcoin) e quale punteggio di robustezza cross-symbol considerare sufficiente.}
}
Disclaimer: le informazioni fornite in questo articolo hanno solo scopo didattico e informativo e non costituiscono consulenza finanziaria, di investimento o di trading. Il trading di criptovalute comporta un rischio significativo di perdita.

Autori

Eugen Soloviov
Eugen Soloviov

Trading-systems engineer

Trading-systems engineer building bots since 2017: cross-exchange arbitrage (connected up to 30 venues), cointegration-based pairs arbitrage across spot and futures, scalping, news and sentiment-driven strategies, trend algorithms, and portfolio management and balancing algorithms. Also builds sub-millisecond order execution, big-data warehouses, backtesting engines, AI agents, and trading interfaces (incl. open-source profitmaker.cc). Stack: JS/TS, Python, Rust/Zig/Go, DevOps, backend, frontend, architecture.

Newsletter

Resta un Passo Avanti al Mercato

Iscriviti alla nostra newsletter per approfondimenti esclusivi sul trading con IA, analisi di mercato e aggiornamenti sulla piattaforma.

Rispettiamo la tua privacy. Annulla l'iscrizione in qualsiasi momento.