Validazione Multi-Symbol: Testa la Tua Strategia su Tutte le Coppie
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

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

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

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:
- Profittevole su >= 60% dei symbol nello stesso tier
- PnL medio nel gruppo è positivo
- MaxDD non aumenta drasticamente (non più di 2-3x rispetto al symbol di ottimizzazione)
- Se la strategia è profittevole SOLO sul symbol di ottimizzazione — rigettare
Esempio: Tre Strategie, Tre Risultati

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

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 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

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
-
Modalità rigorosa (senza scalatura): esegui con parametri identici. Un test di robustezza assoluta. Se la strategia è profittevole — l'edge è forte.
-
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

Per la valutazione quantitativa della robustezza multi-symbol, introduciamo una metrica composita — Cross-Symbol Robustness Score (CSRS).
Formula
dove:
- — frazione di symbol profittevoli:
- — PnL medio ponderato per liquidità normalizzato:
dove è la liquidità del symbol (volume medio giornaliero).
- — bonus per coerenza cross-tier:
- — penalità per alta varianza del PnL tra i symbol:
Pesi Predefiniti
| Componente | Peso | Motivazione |
|---|---|---|
| (frazione profittevole) | 0,35 | Più importante: la strategia deve funzionare sulla maggioranza |
| (PnL medio) | 0,25 | Rendimenti assoluti |
| (cross-tier) | 0,25 | Bonus per universalità |
| (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

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

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

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:
- Ottimizzazione dei parametri su un singolo symbol
- Analisi del plateau — verifica della stabilità dell'ottimo
- Walk-forward — validazione sull'asse temporale (WFER > 0,5)
- Multi-symbol — validazione sull'asse degli strumenti (CSRS > 0,5)
- Bootstrap Monte Carlo — intervalli di confidenza (5° percentile > 0)
- 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

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:
-
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.
-
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.
-
La scalatura adattiva dei parametri — normalizzazione delle soglie per volatilità — migliora significativamente il realismo del testing multi-symbol.
-
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.
-
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
- Lopez de Prado, M. — Advances in Financial Machine Learning (Wiley)
- Pardo, R. — The Evaluation and Optimization of Trading Strategies (Wiley)
- Bailey, D.H. et al. — The Probability of Backtest Overfitting
- Aronson, D.R. — Evidence-Based Technical Analysis
- Kevin Davey — Building Winning Algorithmic Trading Systems (Wiley)
- Harvey, C.R. & Liu, Y. — Backtesting (2015)
- Chan, E. — Algorithmic Trading: Winning Strategies and Their Rationale (Wiley)
- Binance Research — Cryptocurrency Correlation Analysis
- NumPy — numpy.random.choice
- 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.}
}
Autori
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.