Contenuto solo didattico, non consulenza finanziaria. Il trading comporta un rischio sostanziale di perdita.
Riferimento avanzato · Librerie e modelli ML/IA · Trading algoritmico
Guida avanzata al trading con IA: Il riferimento completo di librerie, modelli e framework di ML per quant
Una mappa di livello professionale dell'ecosistema open source e Hugging Face per il trading sistematico: gradient boosting, architetture profonde per serie temporali, modelli di fondazione zero-shot, NLP finanziario, apprendimento per rinforzo, il toolkit di validazione di López de Prado, motori di backtesting e MLOps, con note di architettura, licenze, benchmark e codice per ciascuno.
Prova gratuita di 5 giorni
Nessuna carta richiesta
Operazioni illimitate
Esecuzione istantanea
👋
Nuovo al trading con IA/ML? Questa pagina presuppone dimestichezza con ML e Python e salta i fondamentali. Se preferisci iniziare con la versione in linguaggio semplice (cos'è la meta-etichettatura, come si incastra la pipeline, come automatizzare l'esecuzione con PickMyTrade), leggi prima la Guida al trading con IA per principianti e poi torna qui.
01
ML classico / tabulare: i cavalli di battaglia
Gli alberi decisionali con gradient boosting (GBDT), non le reti profonde, sono la famiglia di modelli predefinita per ogni compito tabulare di classificazione/regressione di questa pipeline: meta-etichettatura, caratteristiche di regime, scoring dei fattori. Un confronto del 2024 ampiamente citato, su oltre 100-300 benchmark tabulari, ha rilevato che i GBDT eguagliano o superano il deep learning sui dati tabulari con molta meno messa a punto (arXiv:2402.03970). I dati finanziari tabulari sono esattamente il regime in cui questo vale con più forza: basso rapporto segnale-rumore, caratteristiche miste continue/categoriali/sparse, forte non stazionarietà e piccole dimensioni effettive del campione, condizioni in cui la flessibilità delle reti profonde compra soprattutto varianza, non segnale.
Perché i GBDT dominano sui dati finanziari tabulari
Compromesso bias-varianza. Con poche migliaia di righe effettive (ponderate per unicità) e un segnale debole e rumoroso, il basso bias di una rete ad alta capacità ha un costo in varianza che non puoi permetterti. Alberi poco profondi con forte regolarizzazione (numero di foglie, min-data-in-leaf, bagging) si collocano in un punto molto migliore di quel compromesso.
Caratteristiche miste e sparse in modo nativo. Gli alberi dividono sui valori grezzi delle caratteristiche: nessuna scalatura, nessuna strategia di imputazione, nessuna tabella di embedding per categoriali raramente popolate (settore, borsa, indicatore di prossimità alla scadenza). Lo sforzo di ingegneria delle caratteristiche va nel segnale, non nell'idraulica di preprocessing.
I vincoli monotoni codificano direttamente priori finanziari. LightGBM/XGBoost/CatBoost supportano tutti monotone_constraints: ad es. forzare P(vincita) a essere non decrescente nella forza del trend e non crescente nella volatilità realizzata. Questo regolarizza verso modelli sensati per il dominio ed è indisponibile, o molto più macchinoso, in un MLP standard.
Valori mancanti e non stazionarietà. Gli alberi instradano i valori mancanti in modo nativo (nessuna imputazione soggetta a fughe adattata sull'intero dataset), e alberi poco profondi e frequentemente riaddestrati si adattano più rapidamente ai cambi di regime rispetto a una grande rete che ha bisogno di molte epoche per disimparare schemi obsoleti.
Library
License
Maturity / stars*
Categorical handling
Speed
Best fit here
LightGBM
MIT
Mature · moved microsoft/LightGBM → lightgbm-org/LightGBM Mar 2026, still MIT
Native (histogram-based, leaf-wise growth)
Fastest of the three on CPU, large-N
Default meta-label / primary classifier
XGBoost
Apache-2.0
Mature, dmlc-maintained, huge ecosystem
Needs one-hot or target-encoding (or enable_categorical)
Slightly slower than LightGBM on CPU histogram mode
When you have many high-cardinality categoricals (symbol, sector, exchange)
scikit-learn
BSD-3-Clause
Foundational, ~19+ years
Via ColumnTransformer/OneHotEncoder
N/A — utility layer
CV splitters, metrics, pipelines, calibration, GMM — the glue, not the model
*I conteggi di stelle sono indicativi, verificati a metà 2026: trattali come "ordine di grandezza", non come cifre esatte.
LightGBM
MIT
Meccanismo: gradient boosting basato su istogrammi con crescita dell'albero per foglia (best-first) anziché per livello: converge più velocemente e di solito verso una perdita più bassa rispetto alla crescita per livello per un dato budget di foglie, al costo di essere più incline all'overfitting su dati piccoli (da controllare con num_leaves/min_data_in_leaf).
Quando usarlo: scelta predefinita per il filtro di meta-etichetta e qualsiasi classificazione/regressione tabulare di questo stack: addestramento su CPU più veloce, instradamento nativo dei valori mancanti, vincoli monotoni nativi. Quando no: campioni molto piccoli (< ~500 righe) dove la crescita per foglia va rapidamente in overfitting; preferisci lì XGBoost per livello o una semplice regressione logistica.
Python · Addestramento di meta-etichetta LightGBM su etichette di tripla barriera
import lightgbm as lgb
from sklearn.model_selection import train_test_split
# X: one row per primary-strategy signal date. Columns e.g.
# log_ret_5d, log_ret_20d, realized_vol_20d, atr_14, frac_diff_price,
# ema_slope, rsi_14, bb_pctb, obv_z, dist_200ma
# y: triple-barrier label from mlfinpy -> 1 = profit barrier hit first, 0 = stop/time first
# w: sample weight from mlfinpy uniqueness/time-decay (NEVER plain 1s -- labels overlap)
X, y, w = features_df[feature_cols], labels_df["tb_label"], labels_df["sample_weight"]
X_train, X_val, y_train, y_val, w_train, w_val = train_test_split(
X, y, w, test_size=0.2, shuffle=False # never shuffle time series
)
params = {
"objective": "binary", "metric": "auc",
"num_leaves": 31, "learning_rate": 0.03,
"feature_fraction": 0.7, "bagging_fraction": 0.7, "bagging_freq": 5,
"min_data_in_leaf": 50,
# financial priors: e.g. [trend, vol, ...] -> win-prob non-decreasing in trend,
# non-increasing in realized vol, unconstrained (0) elsewhere
"monotone_constraints": [1, 0, -1, 0, 0, 1, 0, 0, 0, -1],
"verbosity": -1,
}
train_set = lgb.Dataset(X_train, label=y_train, weight=w_train)
val_set = lgb.Dataset(X_val, label=y_val, weight=w_val, reference=train_set)
model = lgb.train(params, train_set, num_boost_round=2000,
valid_sets=[val_set], callbacks=[lgb.early_stopping(100)])
meta_label_proba = model.predict(X_new) # P(this signal hits the profit barrier first)
XGBoost
Apache-2.0
Meccanismo: alberi con boosting per livello (depth-wise) con un obiettivo regolarizzato (L1/L2 sui pesi delle foglie) integrato nel criterio stesso di ricerca delle divisioni, più un algoritmo di divisione a istogramma/quantile-sketch ben ottimizzato per grandi dati.
Quando usarlo: come secondo modello con bias diverso per l'ensembling con LightGBM (la crescita per livello vs per foglia decorrela gli errori in modo utile); addestramento su GPU se superi la CPU. Quando no: se ti serve una gestione nativa di prim'ordine delle categoriali senza preprocessing, CatBoost è migliore lì.
Meccanismo: ordered boosting (uno schema guidato da permutazioni che evita la fuga di target di cui soffre il classico target-encoding greedy) più statistiche di target ordinate native per le caratteristiche categoriali: nessun passo di codifica manuale e meno incline allo spostamento di predizione rispetto al target encoding ingenuo.
Quando usarlo: modelli trasversali di panieri di azioni con molte caratteristiche categoriali (settore, industria, borsa, indicatori di appartenenza a indici) dove altrimenti dovresti costruire a mano il target encoding. Quando no: budget stretti di tempo di addestramento su CPU: CatBoost è tipicamente il più lento dei tre da adattare, benché rapido a valutare.
Il suo ruolo qui: non una famiglia di modelli concorrente ma il tessuto connettivo: Pipeline per un preprocessing intra-fold privo di fughe, GroupKFold/splitter depurati personalizzati, GaussianMixture per una linea di base leggera di regime, CalibratedClassifierCV per trasformare i punteggi dei GBDT in probabilità oneste prima di dimensionare le posizioni a partire da essi (gli output grezzi dei GBDT sono ben ordinati ma mal calibrati).
Calibra prima di dimensionare
L'output di predict_proba di un GBDT è un buon segnale di ranking ma di solito non è una probabilità ben calibrata così com'è: i GBDT tendono a spingere le predizioni verso 0/1. Se il tuo dimensionatore di posizione consuma direttamente la "confidenza" (Kelly frazionario, dimensione scalata per meta-etichetta), avvolgi il modello in sklearn.calibration.CalibratedClassifierCV (isotonica o Platt) adattato all'interno del fold di CV, altrimenti il tuo dimensionamento sarà sistematicamente troppo sicuro di sé.
02
Architetture per serie temporali con deep learning
Queste sono le architetture neurali da addestrare da zero tu stesso (tipicamente tramite neuralforecast, Apache-2.0, che le implementa tutte), in contrapposizione ai modelli di fondazione preaddestrati del §3. Ognuna di esse è stata portata all'esistenza a suon di benchmark su M4/M3/electricity/traffic/ETT: nessuna è stata progettata contro serie di rendimenti finanziari, e il verdetto onesto per architettura lo riflette.
Architecture
Year / venue
Core idea
Problem vs. plain LSTM
Financial-data verdict
LSTM / GRU
1997 / 2014
Gated recurrent units carry a cell state across time steps to fight vanishing gradients.
— (baseline)
Still a reasonable baseline for sequence classification (e.g. regime state); rarely beats GBDT on tabular-framed return prediction and is slower to train/tune.
TCN
Bai et al. 2018
Stacked causal, dilated 1-D convolutions (WaveNet-style) give an exponentially growing receptive field with fully parallel training.
Parallelizable (no sequential recurrence) and avoids vanishing/exploding gradients over long lookbacks.
Solid, fast baseline in neuralforecast; no documented financial edge over GBDT, but useful when you specifically need a long causal receptive field cheaply.
N-BEATS
Oreshkin et al. 2020 (ICLR)
Pure fully-connected stacks with backward/forward residual "basis expansion" blocks; interpretable trend/seasonality decomposition, no recurrence or attention.
Much simpler and more parallel than RNN/attention stacks; beat the M4-competition winner by ~3% and a statistical benchmark by ~11%.
Benchmarks are M3/M4/tourism — non-financial. Useful as a fast, interpretable univariate baseline; not evidence of edge on returns.
N-HiTS
Challu et al. 2023 (AAAI)
Extends N-BEATS with hierarchical interpolation and multi-rate input sampling so different blocks specialize in different frequency bands.
Cuts long-horizon compute and reportedly beats Transformer baselines by >25% on long-horizon benchmarks.
Same caveat as N-BEATS — a strong long-horizon forecaster on benchmark data, unproven on financial returns specifically.
Temporal Fusion Transformer (TFT)
Lim et al. 2021 (Int. J. Forecasting)
LSTM encoder for local processing + interpretable multi-head self-attention for long-range dependencies + a variable-selection gating network that also yields feature-importance-like interpretability.
Natively handles static covariates, known-future inputs (e.g. expiry date), and produces quantile forecasts with built-in interpretability — none of which vanilla LSTM offers.
The most finance-plausible of the deep architectures because of native covariate support; still no peer-reviewed evidence of consistent OOS financial-return edge over GBDT meta-labeling.
Informer
Zhou et al. 2021 (AAAI, best paper)
ProbSparse self-attention selects only the top-scoring queries, cutting attention cost from O(L²) to O(L log L) for very long sequences.
Makes long-sequence (thousands of steps) transformer forecasting computationally tractable.
Designed for long-horizon benchmark forecasting, not noisy short-memory financial returns; see the DLinear caveat below.
Autoformer
Wu et al. 2021 (NeurIPS)
Replaces standard attention with an auto-correlation mechanism plus built-in series decomposition (trend/seasonal) between blocks.
Captures periodicity more directly than dot-product attention; more robust on strongly seasonal series.
Financial returns have weak/no reliable seasonality at daily/swing frequency — decomposition assumption is a weaker fit than on electricity/traffic data.
FEDformer
Zhou et al. 2022 (ICML)
Performs attention in the frequency domain (via Fourier/wavelet transforms) with a mixture-of-experts decomposition for trend.
Frequency-domain attention scales sub-quadratically and captures global periodic structure.
Same seasonality-dependence caveat as Autoformer; frequency-domain priors are a mismatch for near-random-walk return series.
PatchTST
Nie et al. 2023 (ICLR)
Splits each series into subseries "patches" as transformer tokens (like ViT for time series) and treats each channel independently, sharing one transformer backbone across all channels.
Patch tokenization retains local semantics and cuts attention cost quadratically vs. point-wise tokens; channel-independence avoids spurious cross-channel overfitting. Reported ~21% MSE reduction over prior transformer SOTA on long-horizon benchmarks.
The architectural basis for several foundation models below (see §3); channel-independence is a genuinely useful inductive bias, but the MSE gains are on ETT/weather/traffic, not equities.
iTransformer
Liu et al. 2024 (ICLR spotlight)
"Inverts" the standard transformer: each variate's whole time series becomes one token, and attention runs across variates instead of across time steps, with a per-series FFN handling temporal encoding.
Captures multivariate correlations directly via attention without modifying core transformer components; generalizes to unseen variate counts.
Notably, in a 2026 financial-return benchmark (arXiv:2606.27100, see §3), iTransformer beat the pretrained foundation models on META — a rare case of a from-scratch architecture outperforming zero-shot foundation models on a specific liquid single-name equity.
L'avvertenza DLinear: leggila prima di ricorrere a un qualsiasi transformer
Zeng et al., "Are Transformers Effective for Time Series Forecasting?" (AAAI-23 Oral; codice: cure-lab/LTSF-Linear) hanno mostrato che un singolo strato lineare con decomposizione trend/stagionalità (DLinear) ha battuto Informer, Autoformer e FEDformer su quasi tutti i benchmark standard a lungo orizzonte, sostenendo che i loro guadagni riportati provenivano soprattutto dalla strategia di addestramento diretto multi-step non autoregressiva, non dall'attenzione in sé. L'analisi di follow-up di Hugging Face ha in parte replicato (i transformer con parametri equiparati fanno meglio), ma la lezione pratica regge: fai sempre il benchmark di qualsiasi architettura profonda rispetto a una linea di base lineare/ARIMA (Nixtla statsforecast, §11) prima di fidarti di un guadagno di accuratezza dovuto alla complessità. Questo è doppiamente vero sui dati finanziari, dove il rumore domina il segnale molto più che sui dati di elettricità o traffico.
03
Modelli di fondazione per serie temporali su Hugging Face
I previsori di serie temporali preaddestrati e zero-shot sono reali e utili, per la volatilità, non per la direzione del prezzo. Uno studio del giugno 2026 costruito appositamente per testare questo, "Pretrained Time-Series Foundation Models for Financial Return Forecasting" (Noguer i Alonso e Pereira Franklin, AI Finance Institute), ha messo a benchmark TimeGPT, TimesFM-2.5, Moirai-2.0, Chronos e Chronos-2 contro NBEATS/NHITS/PatchTST/iTransformer/KAN addestrati da zero su cinque azioni statunitensi liquide (AAPL, AMZN, GOOG, JPM, META) con un protocollo a origine mobile rispetto a un benchmark di random walk. Il risultato: su dieci combinazioni asset/compito, solo due hanno mostrato una sovraperformance statisticamente significativa rispetto al random walk: Chronos su AMZN e Moirai-2.0 su GOOG, e gli autori affermano senza mezzi termini che "i guadagni sul benchmark di random walk sono piccoli e sparsi", concludendo che i TSFM sono "priori pratici utili che riducono i costi di sviluppo dei modelli", ma esplicitamente "non motori universali per una generazione di alpha statisticamente affidabile". Tratta ogni modello sotto di conseguenza: motori eccellenti, eseguibili su CPU, per input di volatilità/previsione di vol verso uno strato di dimensionamento; deboli o pari al random walk per la direzione del prezzo.
Model
Org
Architecture family
Params
Context
License
Chronos / Chronos-Bolt
Amazon Science
T5-style encoder-decoder over quantized/tokenized values (Chronos) or direct patch-based multi-step regression heads (Bolt)
Masked-encoder transformer with "any-variate" attention (flattens multiple series into one token sequence so it natively handles arbitrary channel counts and covariates)
Small/Base/Large (14M–311M)
Flexible, any positive length
CC BY-NC-4.0
Lag-Llama
ServiceNow / Morgan Stanley / Mila et al.
LLaMA-style decoder-only transformer fed engineered lag features (not raw tokenized values) as its "vocabulary"
~2.45M (deliberately tiny)
Recommended 32–1024 pts, tunable
Apache-2.0
MOMENT
Auton Lab, CMU
Transformer trained multi-task (forecast + classify + detect anomalies + impute) on the "Time-series Pile" corpus
Small/Base/Large (~40M–341M)
Task-dependent
MIT
IBM Granite-TimeSeries (PatchTSMixer / PatchTST / TTM)
IBM Research
PatchTSMixer = all-MLP mixer over patches (no attention); PatchTST variant = patch-transformer; TTM = "Tiny Time Mixer," a very small pretrained mixer
PatchTSMixer ~1M (task head), TTM sub-5M
512-in / 96-out typical configs
Apache-2.0
Amazon Chronos / Chronos-Bolt
Apache-2.0 · 205M
Scheda del modello:huggingface.co/amazon/chronos-bolt-base (la famiglia include anche chronos-t5-{tiny,mini,small,base,large} e il più recente amazon/chronos-2).
Architettura: il Chronos originale tokenizza valori di serie temporali scalati e quantizzati in un vocabolario fisso e li fa passare attraverso un encoder-decoder T5 standard, cioè tratta la previsione come modellazione del linguaggio su un alfabeto numerico discretizzato. Chronos-Bolt sostituisce la decodifica autoregressiva token per token con una regressione diretta multi-step per patch, riportata come fino a ~250× più veloce e ~20× più efficiente in memoria a parità o miglior accuratezza (misurata via WQL/MASE su 27 dataset di benchmark), addestrata su un ordine di ~100 miliardi di osservazioni di serie temporali.
Verdetto: la migliore scelta tuttofare per un input di previsione di volatilità solo su CPU: Apache-2.0, veloce, zero-shot, e l'unico modello del benchmark 2606.27100 ad aver raggiunto la significatività (su AMZN). Comunque: un risultato significativo su dieci prove non è prova di un vantaggio direzionale ripetibile.
Python · previsione di volatilità zero-shot con Chronos-Bolt
pip install chronos-forecasting torch
import torch
from chronos import BaseChronosPipeline
pipeline = BaseChronosPipeline.from_pretrained(
"amazon/chronos-bolt-base", # T5-style encoder-decoder, 205M params, Apache-2.0
device_map="cpu", # CPU is fine for daily-bar, small-batch inference
torch_dtype=torch.bfloat16,
)
# Feed REALIZED VOLATILITY, not raw price -- this is a vol forecaster, not an oracle
context = torch.tensor(realized_vol_20d.values[-512:])
quantiles, mean = pipeline.predict_quantiles(
context=context,
prediction_length=10, # 10-day-ahead vol forecast
quantile_levels=[0.1, 0.5, 0.9],
)
vol_forecast_median = quantiles[0, :, 1] # feed straight into GARCH/vol-target sizing (see §10)
Google TimesFM
Apache-2.0 · 200M/500M
Scheda del modello:huggingface.co/google/timesfm-2.0-500m-pytorch (ICML 2024). Architettura: transformer solo decoder addestrato a consumare patch di input a lunghezza fissa (32 punti) ed emettere direttamente patch di output più lunghe (128 punti), più vicino all'obiettivo di token successivo di un modello linguistico che all'approccio a valori tokenizzati di Chronos, ma operando su embedding di patch continui anziché su un vocabolario discretizzato.
Verdetto: insieme a Moirai-2.0, ha avuto il miglior rango medio sul benchmark a cinque azioni (in testa su AAPL/JPM/GOOG/AMZN), ma secondo l'impostazione stessa del paper, un rango forte ≠ un vantaggio significativo; nessuna delle vittorie di TimesFM ha superato l'asticella di significatività del random walk. Buono, ben mantenuto, Apache-2.0, adatto alla volatilità; non un via libera per la direzione del prezzo.
Scheda del modello:huggingface.co/Salesforce/moirai-1.0-R-large. Architettura: transformer a encoder mascherato con "any-variate attention": invece di un embedding fisso per canale, appiattisce un numero arbitrario di variabili (target + covariate dinamiche/statiche) in un'unica sequenza di token, così un singolo modello preaddestrato gestisce nativamente qualsiasi compito di previsione multivariata senza riaddestramento per dataset. Moirai-MoE sostituisce la FFN densa con uno strato a mistura di esperti per una migliore specializzazione a costo di inferenza simile.
Blocco di licenza: leggilo prima di toccare questo in un sistema in reale
I pesi di Moirai e Moirai-MoE sono rilasciati sotto CC BY-NC 4.0, solo uso non commerciale. Usarli (anche solo per inferenza) all'interno di un sistema che gestisce il tuo capitale di trading è verosimilmente un uso commerciale e non è coperto da questa licenza senza un accordo separato con Salesforce. Chronos, TimesFM, Lag-Llama e MOMENT sono Apache-2.0/MIT e non comportano tale restrizione: preferisci quelli per qualsiasi cosa tocchi capitale reale. Moirai va bene solo per ricerca/backtesting personali.
Verdetto: Moirai-2.0 ha prodotto l'altro risultato significativo del benchmark (GOOG) e ha pareggiato TimesFM per il miglior rango medio: tecnicamente interessante, ma le regole di licenza lo escludono comunque da una pipeline in reale.
Lag-Llama
Apache-2.0 · ~2.45M
Scheda del modello:huggingface.co/time-series-foundation-models/Lag-Llama. Architettura: un transformer solo decoder in stile LLaMA, ma invece di alimentarlo con valori grezzi o patch, ogni token di input è un vettore di classiche lag feature (valori a t-1, t-2, t-7, t-30, ...) più covariate di data/ora, cioè mette un transformer sopra una rappresentazione con caratteristiche ingegnerizzate che richiama la modellazione autoregressiva classica, tenuto deliberatamente minuscolo (~2,45 M di parametri) rispetto alle altre voci qui.
Verdetto: non fa parte direttamente del benchmark 2606.27100, ma architetturalmente il più vicino a una linea di base autoregressiva "trasparente" del gruppo: una ragionevole seconda opinione per prevedere la volatilità quando vuoi qualcosa di più piccolo/veloce di Chronos-Bolt/TimesFM, restando comunque Apache-2.0 senza problemi.
MOMENT
MIT · ~341M
Scheda del modello:huggingface.co/AutonLab/MOMENT-1-large (ICML 2024; Auton Lab, Carnegie Mellon). Architettura: un unico backbone transformer preaddestrato in modalità multi-task su previsione, classificazione, rilevamento anomalie e imputazione sul curato "Time-series Pile", il che lo rende il più generalista del gruppo anziché uno specialista di previsione.
Quando usarlo: le sue teste di rilevamento anomalie e imputazione sono probabilmente più differenziate per una pipeline di trading rispetto alla sua testa di previsione, ad es. segnalare barre intraday anomale in un controllo di qualità dei dati, o imputare buchi in un feed di dati alternativi, piuttosto che come previsore di volatilità in sé. Licenza: MIT, nessuna restrizione.
IBM Granite-TimeSeries
Apache-2.0
Scheda del modello:huggingface.co/ibm-granite/granite-timeseries-patchtsmixer (vedi anche ibm-granite/granite-timeseries-patchtst e la linea "Tiny Time Mixer" TTM). Architettura: PatchTSMixer sostituisce interamente l'attenzione con un MLP-Mixer sulle patch, senza alcun costo di attenzione quadratica, riportando una memoria/tempo di esecuzione 2-3× inferiori rispetto ai patch-transformer a parità o miglior accuratezza su benchmark pubblici a lungo orizzonte (ad es. 0,37 di MSE sulla previsione a 96 passi di ETTh1).
Quando usarlo: l'opzione di gran lunga più economica da eseguire qui (esistono varianti TTM sotto i 5 M di parametri): una buona scelta se vuoi un componente di previsione di vol leggero, banale su CPU, e non ti serve la generalità zero-shot di Chronos/TimesFM. Licenza: Apache-2.0.
La policy in una frase per tutta questa sezione
Usa qualsiasi modello Apache-2.0/MIT di qui come input di volatilità/covariata verso lo strato di dimensionamento deterministico del §10; non usare nessuno di essi, inclusi i risultati significativi di Chronos/Moirai, come segnale di ingresso autonomo: gli autori stessi del benchmark 2606.27100 definiscono l'effetto "piccolo e sparso", e iTransformer (un'architettura addestrata da zero, §2) ha battuto ogni modello di fondazione su META, sottolineando che il preaddestramento non è un vantaggio universale sulle serie finanziarie.
04
NLP finanziario e LLM
Il sentiment/NLP finanziario appartiene allo strato di rischio (una caratteristica di veto/regime) e non allo strato di alpha: secondo la ricerca fonte del §0, il vantaggio del sentiment delle notizie da solo è in gran parte un artefatto di anticipazione che muore fuori campione. Ecco i tre modelli che vale davvero la pena conoscere.
FinBERT (ProsusAI)
Apache-2.0 · ~110M
Scheda del modello:huggingface.co/ProsusAI/finbert (~7,5 M di download/mese al momento della ricerca). Architettura: BERT-base (12 strati, 768 nascosti, 110 M di parametri) ulteriormente preaddestrato su un ampio corpus finanziario (Reuters TRC2), poi affinato per sentiment a 3 classi sul Financial PhraseBank. Benchmark: 86% di accuratezza sull'intero Financial PhraseBank (97% sul sottoinsieme ad alta concordanza tra annotatori), circa 8 punti sopra il BERT vanilla (arXiv:1908.10063).
Quando usarlo: scoring dei titoli a fine giornata come caratteristica di veto di blackout degli utili / regime ribassista. Quando no: come segnale di alpha autonomo, o su titoli raccolti a orizzonte di 1 giorno dove i feed istituzionali hanno già mosso il prezzo.
Python · inferenza di sentiment FinBERT
pip install transformers torch
from transformers import AutoTokenizer, AutoModelForSequenceClassification
import torch
tok = AutoTokenizer.from_pretrained("ProsusAI/finbert")
model = AutoModelForSequenceClassification.from_pretrained("ProsusAI/finbert")
model.eval()
headlines = ["Company X beats earnings estimates, raises guidance",
"Regulators open investigation into Company X"]
with torch.no_grad():
inputs = tok(headlines, return_tensors="pt", padding=True, truncation=True)
probs = torch.softmax(model(**inputs).logits, dim=-1)
# label order per config.id2label: 0=positive, 1=negative, 2=neutral
labels = ["positive", "negative", "neutral"]
scores = [dict(zip(labels, p.tolist())) for p in probs]
# aggregate to a daily sentiment score; use ONLY as a veto/regime feature, not alpha
FinGPT
MIT (code)
Repository:github.com/AI4Finance-Foundation/FinGPT. Architettura: non un modello addestrato da zero, ma una ricetta di fine-tuning LoRA (Low-Rank Adaptation) applicata a LLM di base aperti (LLaMA2-7B/13B per FinGPT v3.2/v3.3, ChatGLM2-6B per v3.1). LoRA congela i pesi di base e addestra invece piccole matrici adattatrici a basso rango, riducendo i parametri addestrabili da ~6,17 mld a ~3,67 M: pratico da affinare su una singola GPU consumer.
Casi d'uso: analisi del sentiment finanziario, Q&A stile robo-advisor ed esperimenti di previsione usando segnali ingegnerizzati da LLM (anche la base della categoria "segnali ingegnerizzati da LLM" del FinRL Contest). Sfumatura di licenza: il codice di addestramento/inferenza di FinGPT è MIT, ma i pesi di base LLaMA sottostanti comportano i termini di licenza community propri di Meta: verificali separatamente prima di qualsiasi distribuzione commerciale di un checkpoint affinato.
FinBERT-tone
Apache-2.0 · ~110M
Scheda del modello:huggingface.co/yiyanghkust/finbert-tone (Huang, Wang e Yang, Contemporary Accounting Research 2022). Architettura: anch'esso BERT-base (12 strati / 768 nascosti / 12 teste), ma addestrato su una diversa discendenza di corpus: preaddestrato su testo di 10-K/10-Q/earnings call, poi affinato su 10.000 frasi di report di analisti annotate manualmente, dandogli un comportamento di classificazione del tono un po' diverso da quello del FinBERT di ProsusAI nonostante il nome simile.
Quando usarlo: una seconda opinione di sentiment addestrata in modo diverso per l'ensembling con FinBERT specificamente su testo di report di analisti o earnings call (anziché su titoli di notizie generali).
05
Apprendimento per rinforzo per il trading
Il RL è l'elemento più sopravvalutato e meno affidabile di tutta questa pagina per un motore di trading centrale. La strumentazione è genuinamente buona; il verdetto onesto, supportato dallo stesso concorso di benchmark della comunità RL, è confinarlo a sotto-problemi ristretti e rigorosamente validati (ad es. il timing di esecuzione) anziché a un motore principale o a livello di portafoglio.
Dynamic market-environment and dataset layer for FinRL (hundreds of market simulators)
Active, smaller community (~1–2k★)
Stable-Baselines3
MIT
Reliable, well-tested implementations of the underlying RL algorithms (PPO, SAC, DQN, A2C, TD3, DDPG, HER) that FinRL wraps
Actively maintained, the de facto standard PyTorch RL library
TensorTrade
Apache-2.0
RL trading-environment framework (Gym-style)
Maintenance stalled — a community fork, TensorTrade-NG, was created explicitly because the original "needed a lot of refactoring, was outdated, and looked not really maintained." Treat as unmaintained for planning purposes.
Le quattro famiglie di algoritmi (una riga ciascuna)
PPO (Proximal Policy Optimization): on-policy, azioni discrete o continue; limita il passo di aggiornamento della policy per restare vicino alla policy precedente, scambiando un po' di efficienza campionaria con stabilità di addestramento. La prima scelta predefinita nella maggior parte degli esempi FinRL.
SAC (Soft Actor-Critic): off-policy, solo azioni continue; obiettivo a massima entropia (premia esplicitamente l'esplorazione) con un replay buffer, generalmente più efficiente in campioni di PPO ma più sensibile agli iperparametri.
DQN (Deep Q-Network): off-policy, solo azioni discrete; apprende una funzione valore-azione tramite un replay buffer e una rete target. Necessita di uno spazio d'azione discretizzato (ad es. compra/mantieni/vendi), che mal si adatta al dimensionamento continuo della posizione.
A2C (Advantage Actor-Critic): on-policy, discreto o continuo; un cugino più semplice e sincrono di A3C, generalmente il più debole dei quattro sui compiti finanziari nei benchmark di FinRL stesso.
Perché il RL è concretamente fragile per il trading, non solo "difficile"
Paesaggio di ricompensa non stazionario: la funzione di valore di un agente RL è appresa rispetto a un regime storico specifico; quando il regime cambia (come fanno costantemente i mercati finanziari), la policy appresa ottimizza per una superficie di ricompensa che non esiste più. A differenza di un meta-etichettatore GBDT riaddestrato, non c'è un semplice "riadattare sull'ultima finestra" per una rete di policy senza rischiare un oblio catastrofico. Inefficienza campionaria: il RL profondo tipicamente ha bisogno di milioni di interazioni con l'ambiente per convergere; tu hai esattamente una storia non riproducibile del mercato, quindi "più dati" significa o simulazione (che codifica le tue stesse assunzioni come verità di riferimento) o anni di attesa aggiuntiva a tempo di orologio. Reward-hacking sui backtest: un agente che ottimizza il PnL simulato cumulato imparerà volentieri a sfruttare le stranezze del simulatore (assunzioni di esecuzione irrealistiche, impatto di mercato nullo, arrotondamento esatto del motore di backtest) anziché un vero vantaggio di mercato, precisamente la modalità di fallimento che documenta il paper dei FinRL Contests (arXiv:2504.02281): gli agenti inviati con un'alta probabilità di overfitting al backtest sono esplicitamente respinti a un livello di significatività del 10% dagli stessi organizzatori del concorso: le persone che costruiscono l'ecosistema di trading con RL considerano la maggior parte degli agenti di trading RL inviati statisticamente indistinguibili da rumore in overfitting per impostazione predefinita.
Ambito pratico, se usi il RL comunque: un sotto-problema ristretto con una ricompensa naturalmente in forma di MDP (ad es. il timing di esecuzione degli ordini all'interno di un ordine padre fisso, il tracking VWAP), valutato con la stessa disciplina PBO/DSR di tutto il resto nel §14, mai come motore principale di ingresso/uscita/dimensionamento.
06
Pipeline complete di ML quant: Microsoft Qlib
Qlib è la cosa più vicina a una piattaforma di ricerca IA-quant chiavi in mano nell'open source: uno strato dati, un DSL di ingegneria delle caratteristiche, uno zoo di modelli e un'infrastruttura di backtest walk-forward/analisi di portafoglio, collegati tra loro tramite configurazioni di workflow YAML. Con licenza MIT (microsoft/qlib), decine di migliaia di stelle su GitHub, MIT dalla sua apertura del settembre 2020, attivamente rilasciato (v0.9.7, agosto 2025) e ora abbinato all'RD-Agent di Microsoft per una sperimentazione automatizzata a ciclo di ricerca.
Alpha158 vs. Alpha360: i due set di caratteristiche integrati
Raw normalized OHLCV history flattened over a 60-day lookback (6 fields × 60 days = 360 columns), essentially no feature engineering
Feature relationships
Low spatial/temporal structure between columns — a classic tabular feature matrix
Strong spatial-temporal structure — designed for models that learn their own representation from raw sequences
Best-paired models
LightGBM, XGBoost, CatBoost, linear/MLP models
GRU, LSTM, Transformer-family, ALSTM, GATs — sequence models that benefit from raw structure
Sistema di workflow/configurazione e zoo di modelli integrato
Gli esperimenti Qlib sono tipicamente guidati da un singolo file YAML consumato dalla CLI qrun, che dichiara il gestore dei dati (Alpha158/360 o personalizzato), il modello, la suddivisione del dataset, la strategia di portafoglio e i parametri di backtest: questo rende il passaggio da LightGBM a un GRU o a un wrapper TFT un cambio di configurazione di una riga, non una riscrittura. Lo zoo di modelli integrato spazia tra approcci classici e profondi: LGBModel (LightGBM), XGBModel, CatBoostModel, MLP, GRU/LSTM/ALSTM (ricorrenti), Transformer, wrapper TFT, TabNet, HIST, IGMTF e diversi modelli di ricerca a grafi/attenzione (GATs, KRNN, Localformer), tutti addestrati e valutati attraverso la stessa infrastruttura di workflow con un report condiviso di backtest walk-forward/analisi dell'IC.
YAML · configurazione di workflow Qlib minimale (LightGBM su Alpha158)
qlib_init:
provider_uri: "~/.qlib/qlib_data/custom_nse" # see note below on pointing Qlib at NSE data
region: in # generic region tag; India isn't a stock Qlib region out of the box
market: &market custom_nse_500
benchmark: &benchmark NIFTY500
data_handler_config: &data_handler_config
start_time: 2010-01-01
end_time: 2025-12-31
fit_start_time: 2010-01-01
fit_end_time: 2019-12-31
instruments: *market
task:
model:
class: LGBModel
module_path: qlib.contrib.model.gbdt
kwargs:
loss: binary
num_leaves: 31
learning_rate: 0.03
monotone_constraints: [1, 0, -1, 0]
dataset:
class: DatasetH
module_path: qlib.data.dataset
kwargs:
handler:
class: Alpha158
module_path: qlib.contrib.data.handler
kwargs: *data_handler_config
segments:
train: [2010-01-01, 2019-12-31]
valid: [2020-01-01, 2021-12-31]
test: [2022-01-01, 2025-12-31]
# run with: qrun this_config.yaml
Puntare Qlib a dati personalizzati (ad es. NSE)
Qlib include provider di dati USA e Cina pronti all'uso; NSE/BSE richiede che tu costruisca il tuo archivio di dati binario con scripts/dump_bin.py, alimentandolo con file Parquet/CSV OHLCV point-in-time che hai già assemblato (secondo la disciplina di un piano dati privo di survivorship bias). Ti serviranno anche un calendario di trading personalizzato (i festivi NSE differiscono da quelli NYSE/Cina) e la registrazione del tuo file di universo di strumenti: lo strato dati di Qlib è agnostico al formato una volta convertito, quindi Alpha158/360 e l'intero zoo di modelli funzionano senza modifiche sui dati NSE una volta completato il passo di dump.
07
Metodi di ML finanziario di López de Prado: mlfinpy e skfolio
Il toolkit di Advances in Financial Machine Learning di López de Prado significava un tempo una licenza a pagamento mlfinlab: non è più così. Due pacchetti gratuiti e con licenza permissiva coprono ora l'etichettatura a tripla barriera, la meta-etichettatura, la differenziazione frazionaria, la ponderazione di unicità del campione, la CPCV e la HRP.
Package
License
Covers
mlfinpy
MIT
Triple-barrier labeling, meta-labeling, fractional differentiation, sample-weight/uniqueness utilities — a modern Pythonic re-implementation of the AFML code snippets
skfolio
BSD-3-Clause
scikit-learn-compatible portfolio optimization and model selection: CombinatorialPurgedCV out of the box, plus HRP, HERC, risk-budgeting, CVaR/CDaR optimization
mlfinlab (paid)
Commercial
The original, packaged, paid version — only worth it if you specifically want Hudson & Thames' maintained extras beyond what the two free packages cover
Python · etichettatura a tripla barriera con mlfinpy
pip install mlfinpy
from mlfinpy.labeling import get_events, add_vertical_barrier, get_bins
from mlfinpy.util import get_daily_vol
# causal, EWMA-based daily volatility -- uses data strictly up to t, no leakage
daily_vol = get_daily_vol(close=prices, lookback=50)
vertical_barriers = add_vertical_barrier(
t_events=signal_dates, close=prices, num_days=10 # time-limit barrier
)
triple_barrier_events = get_events(
close=prices,
t_events=signal_dates, # your primary (Pine) strategy's signal dates
pt_sl=[2.0, 1.5], # profit-take / stop-loss as multiples of daily_vol
target=daily_vol,
min_ret=0.0005,
num_threads=4,
vertical_barrier_times=vertical_barriers,
)
labels = get_bins(triple_barrier_events, prices)
# labels['bin'] -> 1 = profit barrier hit first, 0 = stop/time barrier hit first
# labels['ret'] -> realized return at the barrier that was hit
# labels['t1'] -> the barrier-touch timestamp (needed for purging downstream)
Python · CombinatorialPurgedCV di skfolio per il modello di meta-etichetta
pip install skfolio
from skfolio.model_selection import CombinatorialPurgedCV, cross_val_predict
from sklearn.pipeline import Pipeline
import lightgbm as lgb
meta_label_pipeline = Pipeline([
("model", lgb.LGBMClassifier(num_leaves=31, learning_rate=0.03,
min_child_samples=50)),
])
# n_folds=10, n_test_folds=2 -> C(10,2) = 45 combinatorial train/test paths
# purged_size / embargo_size sized to the max holding horizon (t1 - t0), NOT a flat 1%
cv = CombinatorialPurgedCV(n_folds=10, n_test_folds=2,
purged_size=10, embargo_size=10)
# returns an empirical DISTRIBUTION of out-of-sample paths, not one score --
# use it to compute PBO and the Deflated Sharpe Ratio, not a single train/test split
oos_paths = cross_val_predict(estimator=meta_label_pipeline, X=X, y=y,
cv=cv, sample_weight=w)
Cosa ti dà ciascuna tecnica
Differenziazione frazionaria (mlfinpy.features.frac_diff / variante FFD a larghezza fissa): trova l'ordine minimo di differenziazione d (spesso 0,2-0,5) che supera un test di stazionarietà ADF pur mantenendo una correlazione >0,9 con la serie dei livelli, dando un input stazionario che conserva memoria: strettamente migliore per modelli ad alberi/lineari rispetto ai rendimenti grezzi (memoria nulla) o al prezzo grezzo (non stazionario).
Ponderazione di unicità del campione: le etichette a tripla barriera si sovrappongono nel tempo (un periodo di mantenimento di 10 giorni significa che segnali adiacenti condividono finestre di etichetta), violando l'assunzione IID su cui si basa gran parte della teoria del ML. Pondera ogni campione per la sua unicità media (inverso del conteggio di etichette concorrenti) più un decadimento temporale, altrimenti la tua dimensione effettiva del campione è una frazione del tuo conteggio di righe e ogni test di significatività a valle è sovrastimato.
Validazione incrociata depurata combinatoria (CPCV): genera molte combinazioni di percorsi train/test (non un singolo percorso walk-forward), depura le righe di addestramento la cui finestra di etichetta si sovrappone al fold di test e applica un embargo cuscinetto dopo ogni fold di test. Produce una distribuzione completa di indici di Sharpe fuori campione (che alimenta PBO e DSR) anziché una stima puntuale: ecco perché è strutturalmente più affidabile del walk-forward semplice.
HRP (Hierarchical Risk Parity) (skfolio.optimization.HierarchicalRiskParity): alloca tramite clustering gerarchico della matrice di correlazione anziché invertire una matrice di covarianza rumorosa (cosa che fa l'ottimizzazione media-varianza), rendendola molto più robusta all'errore di stima su un paniere di azioni correlate.
08
Rilevamento dei regimi: hmmlearn e ruptures
Questa è la sezione dove vive il bug di fuga silenziosa più comune nel gating di regime al dettaglio, e dove mostrare lo schema sbagliato accanto a quello giusto è più utile che descriverlo a parole.
Library
License
Maturity
Role
hmmlearn
BSD
Mature, scikit-learn-style API, ~3k★
Gaussian/GMM/Categorical HMMs for a discrete calm/stormy regime state
ruptures
BSD-2-Clause
Mature, academic (ENS Paris-Saclay/CNRS)
Offline changepoint detection — PELT (exact, linear-cost, unknown number of changes), binary segmentation (BinSeg, greedy/approximate), and sliding-window methods
Il bug di anticipazione silenzioso n. 1: decodifica HMM smussata sull'intero campione
Il modo predefinito e più facile di chiamare hmmlearn (adattare GaussianHMM sull'intera storia, poi chiamare .predict() per le etichette di regime) usa sotto il cofano una decodifica Viterbi/smussata. L'etichetta di regime al tempo t viene scelta usando l'intera sequenza, incluso tutto ciò che segue t. Il gate di fatto "sa" che sta arrivando una crisi prima che accada. Ogni cifra pubblicata sbalorditiva di riduzione del drawdown con HMM (56%→24% di DD massimo, ecc.) che non controlli esplicitamente per questo è molto probabilmente costruita così. Sotto: lo schema con fughe, e lo schema causale, walk-forward, a posteriore filtrata che è effettivamente distribuibile.
from hmmlearn.hmm import GaussianHMM
model = GaussianHMM(n_components=2, covariance_type="diag", n_iter=1000)
model.fit(X_full) # fit on the ENTIRE history -- future leaks into the fit
regimes = model.predict(X_full) # Viterbi = globally-smoothed decode over the whole path
# regimes[t] used information from t+1 ... T. This is look-ahead bias.
# Any backtest of a regime gate built this way is invalid and will not reproduce live.
Python · CORRETTO: gate di regime causale, walk-forward, a posteriore filtrata
from hmmlearn.hmm import GaussianHMM
import numpy as np
regime_at_t = np.full(len(X), np.nan)
model, refit_every, min_train = None, 63, 500 # e.g. refit quarterly
for t in range(min_train, len(X)):
if model is None or t % refit_every == 0:
model = GaussianHMM(n_components=2, covariance_type="diag", n_iter=200)
model.fit(X[:t]) # ONLY data strictly before t
# forward-algorithm FILTERED posterior using data up to and including t --
# no smoothing, no future information, no re-fit on data that includes t's label use
posteriors = model.predict_proba(X[:t + 1])
regime_at_t[t] = posteriors[-1].argmax() # today's regime, knowable today
# regime_at_t is safe to merge into the feature frame for both backtest and live use.
# Expect a MUCH smaller, laggier drawdown benefit than the full-sample-smoothed version --
# that gap IS the size of the leakage bug you just closed.
ruptures è lo strumento complementare quando vuoi punti di cambiamento anziché uno stato di regime persistente, ad es. segnalare una rottura di regime di volatilità in una serie EWMA per innescare un riadattamento dell'HMM, o come rilevatore alternativo di confini di regime per verificare le transizioni dell'HMM. Pelt (ricerca esatta a costo lineare, numero sconosciuto di punti di rottura, richiede un parametro di penalità) è quello predefinito; Binseg scambia l'esattezza con la velocità su serie più lunghe; i metodi basati su finestra sono i più economici ma i meno precisi sulle rotture sottili. Come l'HMM, eseguilo in una finestra espansiva/mobile per l'uso in reale: anche l'API standard di ruptures è un metodo offline sull'intera serie per impostazione predefinita.
09
Motori di backtesting ed esecuzione
Nessun singolo motore è adatto a ogni fase. Usa un motore vettorizzato per selezionare migliaia di combinazioni di parametri, poi rivalida ogni sopravvissuto su un motore basato su eventi con esecuzioni realistiche prima di rischiare capitale: confondere le due fasi (fidarsi di un backtest di motore vettorizzato come risposta finale) è un errore comune e costoso.
Engine
Speed
Fill realism
License
Maintenance
Best-fit use case
vectorbt (community)
Extremely fast (Numba-vectorized, thousands of configs at once)
Weak — vectorized fills, easy to fool yourself
Apache-2.0 + Commons Clause
Community edition maintenance-frozen; active dev moved to paid vectorbtPRO
Fast first-pass parameter sweep / triage only
backtrader
Moderate (pure Python, event-driven)
Moderate (configurable slippage/commission, but manual)
GPL-3.0
Stalled ~2021 — open PRs/issues unmerged for years
Legacy strategies only; don't start new work here
Zipline-reloaded
Moderate
Good (Quantopian-derived fill/slippage models)
Apache-2.0
Community-maintained fork (stefan-jansen), modest but real activity
Research backtests wanting the original Zipline/Quantopian API and pipeline model
NautilusTrader
Fast (Rust core)
High — same strategy code path for backtest and live
LGPL-3.0-or-later
Very active, ~24k★, production-grade
Final realistic-fill re-validation and the bridge to live — the one tool built for research-to-live parity
QuantConnect LEAN
Fast (C#/.NET core, Python API)
High — institutional-grade fill/slippage/margin models
Apache-2.0
Very active, ~19k★, backs a commercial cloud platform
Full-featured alternative to NautilusTrader, especially with QuantConnect's hosted data/cloud/live options
bt
Moderate
Moderate (higher-level "Algo" abstraction over vectorized fills)
MIT
Actively maintained (releases into 2026)
Fast, readable portfolio-level (multi-asset allocation) backtests, less suited to per-trade microstructure realism
backtesting.py
Fast (single-asset, vectorized-ish)
Basic (simple slippage/commission model)
AGPL-3.0
Active, small footprint, ~2.4k★
Quick single-asset prototyping only — AGPL is a real constraint if you build a hosted/SaaS product on it
Perché l'architettura di NautilusTrader conta davvero
La maggior parte dei fallimenti "ottimo backtest, reale deludente" non sono fallimenti del modello: sono bug di scostamento ricerca/produzione: il tuo motore di backtest e il tuo codice di esecuzione in reale sono due basi di codice separate che silenziosamente divergono l'una dall'altra (un'assunzione di prezzo di esecuzione qui, un bug di timing di barra spostato di uno là), e nulla le costringe a rimanere coerenti. Il design basato su eventi con nucleo in Rust di NautilusTrader esegue lo stesso codice di strategia (le stesse classi, gli stessi gestori di eventi) in modalità backtest, paper e reale; cambiano solo gli adattatori di dati/esecuzione. Quella scelta architetturale elimina un'intera classe di bug per costruzione anziché per disciplina, motivo per cui è lo strumento giusto per il ruolo di "rivalidazione finale con esecuzioni realistiche e ponte verso la produzione" anziché un semplice di più.
Nota di licenza: LGPL-3.0, non GPL
NautilusTrader è LGPL-3.0-or-later, non la più rigida GPL-3.0 che governa backtrader e freqtrade. La LGPL permette di collegare/usare la libreria da codice proprietario senza rendere open source il tuo codice di strategia, a condizione che le modifiche a NautilusTrader stesso (se presenti) siano condivise a ritroso: materialmente meno restrittiva di una dipendenza GPL pura per un sistema di trading a codice chiuso. Conferma comunque i termini di licenza attuali sul repository prima di una distribuzione commerciale.
10
Costruzione del portafoglio e rischio
È qui che il "controllo del drawdown" viene effettivamente implementato: come matematica deterministica che consuma previsioni di volatilità e confidenza della meta-etichetta, non come un altro compito di predizione.
Library
License
Role
PyPortfolioOpt
MIT
Classical mean-variance / efficient frontier, Black-Litterman, shrinkage covariance estimators, and HRP — the most approachable API of the three
Riskfolio-Lib
BSD-3-Clause
Deeper risk-based allocation: HRP/HERC, ~24 risk measures including CVaR/CDaR/EVaR, risk-parity/risk-budgeting, built on CVXPY convex optimization
arch
NCSA
GARCH/EGARCH/GJR-GARCH/TARCH volatility-family models — the standard econometric volatility forecaster feeding vol-targeted sizing
Python · previsione di volatilità GJR-GARCH → dimensione di posizione con targeting di vol (arch)
pip install arch
from arch import arch_model
import numpy as np
returns_pct = 100 * log_returns.dropna() # arch expects % returns for numerical stability
# GJR-GARCH(1,1,1) with Student-t errors -- captures the leverage effect (vol reacts more to
# negative returns than positive ones), which plain GARCH(1,1) misses
am = arch_model(returns_pct, vol="GARCH", p=1, o=1, q=1, dist="t")
res = am.fit(disp="off", last_obs=train_end_date) # fit only on data up to the current date
fcast = res.forecast(horizon=10, reindex=False)
vol_forecast_daily = np.sqrt(fcast.variance.values[-1]) / 100 # back to decimal daily vol
target_vol_daily = 0.10 / (252 ** 0.5) # ~10% annualized portfolio vol target
position_scale = target_vol_daily / vol_forecast_daily[0]
position_size = base_size * min(position_scale, max_leverage_cap) # always cap leverage
PyPortfolioOpt
MIT
Quando usarlo: un'allocazione rapida HRP o a covarianza con shrinkage su un paniere senza tirarti dietro un intero stack di dipendenze di ottimizzazione convessa. Quando no: se ti servono obiettivi CVaR/CDaR o misure di rischio più esotiche, quello è il compito di Riskfolio-Lib.
Python · allocazione HRP
from pypfopt import HRPOpt
hrp = HRPOpt(returns=daily_returns_df) # NOT prices -- pass returns
weights = hrp.optimize() # hierarchical-clustering-based, no covariance inversion
Riskfolio-Lib
BSD-3
Quando usarlo: ogni volta che l'obiettivo è esplicitamente consapevole del rischio di coda (CVaR/CDaR) anziché della varianza: una scelta migliore per un mandato di "minimo drawdown" rispetto alla media-varianza.
Python · portafoglio ottimale CVaR
import riskfolio as rp
port = rp.Portfolio(returns=daily_returns_df)
port.assets_stats(method_mu="hist", method_cov="hist")
weights = port.optimization(model="Classic", rm="CVaR", obj="MinRisk", rf=0, l=0)
11
Ingegneria delle caratteristiche e utilità di previsione
Prima di fidarti di qualsiasi risultato di GBDT o di un modello di fondazione, mettilo a benchmark rispetto alla noiosa linea di base. Queste due librerie coprono l'estrazione automatizzata delle caratteristiche e le linee di base di previsione classiche che non dovresti mai saltare.
Library
License
Role
tsfresh
MIT
Automated extraction of hundreds of statistical/signal-processing time-series features, with a built-in hypothesis-testing-based relevance filter (the "FRESH" algorithm) to control false-discovery rate on the feature explosion
Nixtla statsforecast
Apache-2.0
Fast classical/econometric baselines — AutoARIMA, AutoETS, AutoCES, Theta — the mandatory benchmark before believing any ML "edge"
Nixtla mlforecast
Apache-2.0
Machine-learning forecasting at scale (pandas/polars/Spark/Dask/Ray backends) with the same lag-feature-engineering plumbing regardless of backend
Nixtla neuralforecast
Apache-2.0
30+ neural architectures under one API — every model in §2 (NBEATS, NHITS, TFT, Informer, Autoformer, FEDformer, PatchTST, iTransformer, TimeLLM, ...) available without hand-rolling each paper's code
Python · estrazione di caratteristiche automatizzata + filtrata con tsfresh
pip install tsfresh
from tsfresh import extract_relevant_features
# long-format df: columns [id, time, value]; y indexed by id (e.g. triple-barrier label)
features = extract_relevant_features(
long_format_df, y=labels_by_id, column_id="id", column_sort="time",
fdr_level=0.01, # false-discovery-rate control -- do NOT skip this on financial data
)
# re-run the relevance filter INSIDE each CV fold in production, never on the full dataset
Python · linea di base obbligatoria prima di fidarti del "vantaggio" di qualsiasi modello
pip install statsforecast
from statsforecast import StatsForecast
from statsforecast.models import AutoARIMA, AutoETS
sf = StatsForecast(models=[AutoARIMA(), AutoETS()], freq="D", n_jobs=-1)
sf.fit(train_df)
baseline_forecast = sf.predict(h=10)
# your GBDT / foundation-model forecast must beat THIS, net of cost, or there is no edge
12
MLOps per un sistema di trading in reale
La strumentazione MLOps qui non riguarda la scala, riguarda l'onestà. La funzione MLOps più determinante di tutto questo stack è la disciplina del conteggio delle prove per il Deflated Sharpe Ratio: ogni configurazione di backtest che hai mai provato, tracciata, per sempre, così che la correzione per test multipli sia calcolata rispetto al tuo conteggio di prove reale, non al sottoinsieme lusinghiero che ricordi.
Tool
License
Role
When to adopt
MLflow
Apache-2.0
Experiment tracking (params/metrics/artifacts) + model registry with stage transitions
Early — every single backtest run, from day one, feeds the DSR trial count
Once a strategy is running on a schedule against live data
NannyML
Apache-2.0
Label-free live performance estimation — CBPE for classifiers, DLE for regressors — estimates real-world accuracy before ground-truth labels are even available
Once paper/live trading is running and labels arrive with a lag (exactly the triple-barrier situation)
Prefect
Apache-2.0
Pythonic pipeline orchestration: scheduling, retries, caching, event-driven triggers for the nightly ingest→feature→predict→size→alert DAG
Once a plain cron script becomes unwieldy — not needed for an MVP
Dagster
Apache-2.0
Alternative orchestrator with stronger data-asset lineage/typing — heavier but better observability at scale
If you outgrow Prefect's simplicity and want asset-level lineage across many pipelines
Python · logging MLflow che impone davvero la disciplina del conteggio delle prove del DSR
pip install mlflow
import mlflow
with mlflow.start_run(run_name="lgbm_meta_label_v37"):
mlflow.log_params(params) # every hyperparameter tried
mlflow.log_param("cv_scheme", "CombinatorialPurgedCV(10,2)")
mlflow.log_param("feature_set_hash", feature_set_hash) # so re-used feature sets don't double count
mlflow.log_metric("oos_sharpe_median", oos_sharpe_median) # across the CPCV path distribution
mlflow.log_metric("pbo", pbo_value)
mlflow.log_metric("trial_number_in_family", trial_counter) # THIS feeds the Deflated Sharpe N
mlflow.lightgbm.log_model(model, "model")
# Query the full run history to compute N for the Deflated Sharpe Ratio -- include prior
# Pine-Script optimization trials too (see §14), not just the ML runs.
Perché questo è non negoziabile, non un semplice di più
Il Deflated Sharpe Ratio ha bisogno di un conteggio onesto di ogni configurazione che tu abbia mai provato rispetto a questi dati, non solo del modello finale. Senza un sistema di registrazione, il conteggio delle prove viene ricostruito a memoria nel momento esatto in cui sei più motivato a sottostimarlo. MLflow (o un equivalente) trasforma "quante cose ho effettivamente provato" da un'ipotesi autodichiarata in un fatto interrogabile.
13
Dati e dataset alternativi su Hugging Face
Oltre agli hub di modelli, il Datasets Hub di Hugging Face ospita un insieme crescente di dataset rilevanti per la finanza che vale la pena conoscere per la prototipazione e il lavoro sul sentiment: trattali tutti come fonti di prototipazione/di riserva, non come dati di produzione privi di survivorship bias (vedi la disciplina del Piano Dati nel report di ricerca fonte).
Labeled Twitter/X financial and crypto sentiment — useful for fine-tuning or validating a FinBERT-style veto filter
huggingface.co/datasets?search=finance
Hub search
The Hub's finance-tagged dataset list changes frequently — always re-search rather than trusting a static list; verify licensing per-dataset before any commercial use
Numerai: un gioco diverso, non una fonte di dati per il tuo sistema
Numerai si capisce meglio come un mercato di abilità di modellazione, non come un dataset da collegare alla tua pipeline. Il torneo principale fornisce gratuitamente caratteristiche pre-ingegnerizzate e offuscate: passate in PCA, z-scored e suddivise nel tempo, così puoi modellare dati finanziari di livello mondiale senza mai sapere quali azioni o quali date stai guardando (ogni "era" settimanale ha ID che non si corrispondono tra le ere, per progetto). Numerai Signals è il prodotto complementare: invii previsioni sul tuo proprio universo/caratteristiche, puntando a segnali ortogonali a ciò che lo stack di modelli esistente di Numerai già cattura. Tutti i modelli inviati alimentano un meta-modello ponderato per lo stake che a sua volta guida l'hedge fund di Numerai stesso. Inquadralo come opzionalità per monetizzare l'abilità di modellazione (valutata su performance pluriennale e inclusiva del drawdown, non come una via rapida verso un reddito) e come un ecosistema adiacente interessante anziché un componente della pipeline del §14.
14
Architettura di riferimento: pipeline completa
Come un utente avanzato collega ogni libreria sopra in un'unica pipeline, dall'inizio alla fine. Ingestione dei dati → caratteristiche Qlib/tsfresh → differenziazione frazionaria (mlfinpy) → modello di meta-etichetta LightGBM validato con validazione incrociata depurata combinatoria annidata (skfolio) → gate di regime causale hmmlearn → dimensionamento con targeting di vol basato su GARCH (arch) → backtest NautilusTrader → logging MLflow → webhook PickMyTrade per l'esecuzione.
Ogni freccia è un passaggio di dati tra librerie sostituibili in modo indipendente: nessuna fase dipende da una scelta specifica in un'altra.
Python · scheletro della pipeline di riferimento dall'inizio alla fine
"""
Reference pipeline skeleton: data ingestion -> PickMyTrade execution.
Every preprocessing step is fit INSIDE the CPCV training fold only -- never on
the full dataset. Illustrative structure; wire in your own data store / config.
"""
import numpy as np
import pandas as pd
import lightgbm as lgb
import mlflow
import requests
from hmmlearn.hmm import GaussianHMM
from arch import arch_model
from mlfinpy.labeling import get_events, add_vertical_barrier, get_bins
from mlfinpy.util import get_daily_vol
from mlfinpy.features import frac_diff_ffd
from skfolio.model_selection import CombinatorialPurgedCV, cross_val_predict
from sklearn.pipeline import Pipeline
from qlib.contrib.data.handler import Alpha158
from tsfresh import extract_relevant_features
from nautilus_trader.backtest.engine import BacktestEngine
from nautilus_trader.trading.strategy import Strategy
# 1. DATA INGESTION -- point-in-time, survivorship-bias-free universe only
def load_point_in_time_universe(as_of_date, min_adv_usd=2_500_000):
"""Never filter by TODAY's liquidity -- that imports survivorship bias."""
raw = data_store.query_asof(as_of_date=as_of_date) # Parquet/DuckDB store
return raw[raw["adv_20d_asof"] > min_adv_usd]
# 2. FEATURES -- Qlib Alpha158 for technicals, tsfresh + mlfinpy for the rest
def build_features(prices: pd.DataFrame) -> pd.DataFrame:
alpha158 = Alpha158(instruments=prices["symbol"].unique().tolist(),
start_time=prices.index.min(), end_time=prices.index.max())
tech_features = alpha158.fetch()
tsfresh_features = extract_relevant_features(
prices.reset_index(), y=None, column_id="symbol", column_sort="date", fdr_level=0.01,
)
d = find_min_ffd_order(prices["close"], adf_pvalue=0.05, min_corr=0.9) # search d in [0.1, 1.0]
frac_diff_price = frac_diff_ffd(prices["close"], d=d, threshold=1e-4) # stationary, RETAINS memory
return tech_features.join(tsfresh_features, how="inner").assign(frac_diff_price=frac_diff_price)
# 3. LABELS -- causal EWMA vol -> ATR-scaled triple barrier (mlfinpy)
def label_events(prices: pd.Series, signal_dates: pd.DatetimeIndex) -> pd.DataFrame:
daily_vol = get_daily_vol(close=prices, lookback=50)
vertical_barriers = add_vertical_barrier(t_events=signal_dates, close=prices, num_days=10)
events = get_events(close=prices, t_events=signal_dates, pt_sl=[2.0, 1.5], target=daily_vol,
min_ret=0.0005, num_threads=4, vertical_barrier_times=vertical_barriers)
return get_bins(events, prices) # -> bin (0/1), ret, t1 (needed for purging)
# 4. META-LABEL MODEL -- LightGBM inside nested Combinatorial Purged CV
def train_meta_label_model(X: pd.DataFrame, y: pd.Series, w: pd.Series, trial_counter: int):
pipeline = Pipeline([("model", lgb.LGBMClassifier(
num_leaves=31, learning_rate=0.03, min_child_samples=50,
monotone_constraints=MONO_CONSTRAINTS))])
cv = CombinatorialPurgedCV(n_folds=10, n_test_folds=2, purged_size=10, embargo_size=10)
oos_paths = cross_val_predict(estimator=pipeline, X=X, y=y, cv=cv, sample_weight=w)
pbo = compute_pbo(oos_paths)
dsr = compute_deflated_sharpe(oos_paths, n_trials=get_trial_count_from_mlflow() + trial_counter)
if pbo > 0.50 or dsr.p_value > 0.05:
raise ValueError(f"Model rejected: PBO={pbo:.2f}, DSR p={dsr.p_value:.3f}")
final_model = pipeline.fit(X, y, model__sample_weight=w)
return final_model, pbo, dsr
# 5. REGIME GATE -- causal, walk-forward, FILTERED (never smoothed) HMM posterior
def causal_regime_state(vol_return_features: np.ndarray, t: int, model_cache: dict,
refit_every: int = 63, min_train: int = 500) -> int:
if t < min_train:
return 1 # default "calm" until enough history exists
if t % refit_every == 0 or "model" not in model_cache:
hmm = GaussianHMM(n_components=2, covariance_type="diag", n_iter=200)
hmm.fit(vol_return_features[:t]) # only data strictly before t
model_cache["model"] = hmm
posteriors = model_cache["model"].predict_proba(vol_return_features[: t + 1])
return int(posteriors[-1].argmax()) # filtered state at t, no look-ahead
# 6. VOL-TARGETED SIZING -- GJR-GARCH forecast -> fractional-Kelly-scaled size
def size_position(returns_pct: pd.Series, meta_label_confidence: float, regime_state: int,
target_vol_annual: float = 0.10, kelly_fraction: float = 0.5,
max_leverage: float = 1.5) -> float:
if regime_state == 0: # 0 = "stormy" -- stand aside
return 0.0
res = arch_model(returns_pct, vol="GARCH", p=1, o=1, q=1, dist="t").fit(disp="off")
vol_fc = np.sqrt(res.forecast(horizon=1, reindex=False).variance.values[-1, 0]) / 100
vol_scale = (target_vol_annual / (252 ** 0.5)) / vol_fc
kelly_scale = kelly_fraction * max(2 * meta_label_confidence - 1, 0) # confidence -> edge proxy
return float(np.clip(vol_scale * kelly_scale, 0, max_leverage))
# 7. BACKTEST -- NautilusTrader (same strategy class runs backtest AND live)
class MetaLabelStrategy(Strategy):
def __init__(self, model, hmm_cache, config):
super().__init__(config)
self.model, self.hmm_cache = model, hmm_cache
def on_bar(self, bar):
feats = self.build_live_features(bar) # same code path as build_features()
confidence = self.model.predict_proba(feats)[:, 1][0]
regime = causal_regime_state(self.vol_history, self.clock.timestamp_ns, self.hmm_cache)
size = size_position(self.returns_pct_history, confidence, regime)
if confidence > 0.55 and size > 0:
self.submit_bracket_order(side="BUY", size=size, sl_atr_mult=1.5, tp_atr_mult=2.0)
def run_backtest(historical_bars, final_model, strat_config):
engine = BacktestEngine()
engine.add_data(historical_bars)
engine.add_strategy(MetaLabelStrategy(model=final_model, hmm_cache={}, config=strat_config))
return engine.run() # the SAME strategy object later promotes to paper/live -- adapters swap only
# 8. MLFLOW LOGGING -- every trial, forever (feeds the Deflated Sharpe trial count)
def log_run(params, pbo, dsr, backtest_results, final_model, trial_counter):
with mlflow.start_run(run_name=f"pipeline_v{trial_counter}"):
mlflow.log_params(params)
mlflow.log_metric("pbo", pbo)
mlflow.log_metric("dsr_p_value", dsr.p_value)
mlflow.log_metric("backtest_sharpe", backtest_results.sharpe_ratio)
mlflow.log_metric("backtest_max_dd", backtest_results.max_drawdown)
mlflow.log_metric("trial_number_in_family", trial_counter)
mlflow.lightgbm.log_model(final_model, "meta_label_model")
# 9. EXECUTION -- PickMyTrade webhook JSON (paper first, then tiny live)
def send_to_pickmytrade(symbol, side, qty, sl_price, tp_price, webhook_url, secret):
payload = {
"secret": secret, "symbol": symbol, "action": side, # "buy" / "sell"
"quantity": qty, "stopLoss": sl_price, "takeProfit": tp_price, "orderType": "market",
}
resp = requests.post(webhook_url, json=payload, timeout=5)
resp.raise_for_status()
return resp.json()
Ogni freccia è un punto di sostituzione, per progetto
Nota che nessuna fase è cablata in modo fisso a una scelta specifica delle sezioni precedenti: sostituisci LightGBM con CatBoost, l'Alpha158 di Qlib con un set di caratteristiche fatto a mano, NautilusTrader con QuantConnect LEAN, o PickMyTrade con un diverso ponte di esecuzione, e nient'altro nella pipeline deve cambiare. Quel disaccoppiamento è ciò che rende la matrice decisionale del §15 attuabile anziché prescrittiva.
14.5
Claude Fable come co-ingegnere per questo stack
Claude Fable è il modello di punta di Anthropic (id modello claude-fable-5), disponibile tramite l'app Claude e Claude Code. Su uno stack così profondo, il suo valore non è "scrivimi un bot di trading": è la parte intermedia ingrata e soggetta a errori: azzeccare l'aritmetica dei fold di CPCV, scrivere un ciclo di decodifica HMM causale (non con fughe) al primo colpo, cablare un gestore di dati Qlib per un mercato che non arriva di serie, e leggere una pipeline multi-fase dall'inizio alla fine per trovare l'unica fuga che altrimenti emergerebbe solo come uno scarto reale/backtest mesi dopo.
Dove si guadagna la pagnotta sullo stack specifico di questa pagina:
Logica dei fold di CPCV: derivare le dimensioni di depurazione/embargo dall'orizzonte della tua etichetta e dal lookback di caratteristica più lento (§7), anziché indovinarle e scoprirlo da uno Sharpe di backtest gonfiato.
Inferenza di regime causale: scrivere il ciclo walk-forward a posteriore filtrata anziché la chiamata con fughe a decode()/Viterbi sull'intero campione mostrata come esempio "sbagliato" nel §8.
Configurazione Qlib: generare e adattare lo YAML di workflow Alpha158/Alpha360 a un gestore di dati personalizzato per una regione che Qlib non fornisce, come l'esempio NSE nel §6.
Revisione delle fughe sull'intera pipeline: leggere lo scheletro del §14 fase per fase in cerca di un bug di adattamento fuori dal fold prima che tocchi capitale.
Conversione Pine Script → Python: portare la logica di ingresso di una strategia TradingView nella funzione di segnale primario che alimenta il modello di meta-etichettatura.
Collante di esecuzione: redigere il codice del payload del webhook / della chiave di idempotenza trattato nel §14.6, e il logging MLflow che mantiene onesto il tuo conteggio delle prove del Deflated Sharpe (§12).
Prompt pronti da adattare per ciascuno di quei casi, specifici per lo stack di questa pagina, non richieste generiche di "costruiscimi un bot":
Prompt 1 · Revisione di depurazione/embargo di CPCV
Review this skfolio CombinatorialPurgedCV setup [paste code]: 10 folds, 2 test folds, on triple-barrier-labeled
signals where barriers can resolve up to 10 trading days after the signal (get_events num_days=10). Check whether
purged_size and embargo_size are large enough to cover that full label-resolution window plus my slowest feature's
lookback. Flag any fold where a training sample's resolution window overlaps a test sample's, explain the leak, and
give me corrected purge/embargo values with the reasoning shown.
Prompt 2 · Gate di regime HMM causale, non con fughe
Here is my hmmlearn regime-detection code [paste code]. Confirm it only calls predict_proba on data up to and
including index t when producing the label used AT time t, and that it never calls hmm.decode() or reads a Viterbi
path computed over the full series. If it's using the full-sample smoothed posterior, rewrite it as a walk-forward
loop that refits every N bars on strictly past data and returns the filtered (not smoothed) posterior at each step,
matching the causal pattern, not the leaky one.
Prompt 3 · Qlib Alpha158 su un mercato non predefinito
I want Microsoft Qlib's Alpha158 handler running on NSE (India) equities, not one of Qlib's built-in regions.
Here's my current workflow YAML [paste config]. Write a custom data handler/provider that points Alpha158's feature
computation at my own point-in-time OHLCV store instead of Qlib's default region data, keeping the Alpha158 feature
set intact. Explain specifically what breaks -- calendar, instrument universe, trading-day alignment -- if I just
change the region tag without supplying compatible replacements.
Prompt 4 · Audit delle fughe sull'intera pipeline
Here is my end-to-end pipeline: data ingestion, feature engineering, triple-barrier labeling, LightGBM meta-label
training inside CombinatorialPurgedCV, HMM regime gate, GARCH-based sizing, and NautilusTrader backtest [paste code].
Walk it stage by stage and flag every point where a transform -- scaler, feature selector, frac-diff order search, HMM
fit -- is fit on data outside the current CV training fold, or a feature could see information unavailable at signal
time. Rank findings by how much each would inflate the backtest Sharpe if left uncorrected.
Prompt 5 · Pine Script → funzione di segnale primario
Here is my TradingView Pine Script strategy [paste script]. Convert its entry logic into a Python function that
takes a pandas DataFrame of OHLCV bars and returns a boolean signal series, matching the Pine version bar-for-bar on
identical historical data. This becomes the primary-model signal feeding my meta-labeling filter, so flag anything --
security() calls with lookahead, use of the current bar's close before it closes -- that would make the two versions
diverge.
Prompt 6 · Payload del webhook + chiave di idempotenza
Write a Python function that takes a meta-label confidence score, ATR-based stop/target multiples, and a
position size from my vol-targeted sizing calc, and builds the JSON payload for a PickMyTrade webhook POST -- symbol,
side, quantity, stopLoss, takeProfit. Add a deterministic idempotency key (hash of symbol + signal timestamp + bar
index) as a payload field, and wrap the POST in retry-with-backoff logic that treats a timeout as "unknown, reconcile
before retrying" rather than blindly resubmitting.
Fable redige, tu fai il merge
Nessuno dei prompt sopra sostituisce la lettura del diff da parte tua. Claude Fable è veloce nelle parti meccaniche (aritmetica dei fold di CV, logica di retry ripetitiva, conversione di Pine in pandas), ma le dimensioni di depurazione/embargo, le soglie di rifiuto PBO/DSR e la decisione di instradare capitale attraverso un dato webhook restano tue da approvare, ogni volta, prima che qualcosa tocchi un conto paper o reale.
14.6
Ponte di esecuzione: costruire vs. acquistare per l'ultimo salto
La stessa decisione costruire vs. acquistare che prende qualsiasi team di sistemi, applicata all'ultimo salto della pipeline del §14: le tue scarse ore di ingegneria vanno nell'idraulica di instradamento degli ordini, o negli strati di modello che sono davvero tuoi? Questa sezione sostiene di trattare l'esecuzione in reale come una dipendenza acquistata a interfaccia ristretta, e mostra come appare l'interfaccia dal lato della pipeline.
1 · L'idraulica di instradamento degli ordini ha un ampio raggio d'impatto per i bug silenziosi
Logica di retry, riautenticazione della sessione broker, riconciliazione delle esecuzioni parziali, macchine a stati dei bracket OCO, deduplicazione dei webhook: ognuno è un problema ben compreso isolatamente, e ognuno è esattamente il tipo di codice dove un bug non solleva un'eccezione. Silenziosamente duplica un ordine, lascia cadere uno stop, o lascia una macchina a stati sul nodo sbagliato. Un listener andato in crash che tiene una posizione in futures aperta overnight non è uno stack trace; è una telefonata al desk del tuo broker.
2 · Un bug di esecuzione silenzioso è un evento di P&L, non un'eccezione catturata
Gli errori del tuo modello si manifestano come uno Sharpe più basso su migliaia di operazioni: rumorosi ma limitati e diagnosticabili. Un errore dello strato di esecuzione si manifesta come uno specifico stop mancante o un'esecuzione duplicata, realizzato in dollari, di solito l'unica volta in cui la volatilità schizza e non stai guardando il terminale. I test unitari catturano i bug per cui hai pensato di scrivere un test; raramente catturano un token di sessione che scade a metà giornata o un webhook consegnato due volte durante un intoppo di rete.
3 · Le ore che vale la pena spendere sono quelle che solo tu puoi spendere
Retry/backoff, macchine a stati OCO e traduzione degli ordini specifica del broker sono lo stesso problema per ogni trader che instrada verso Rithmic o IB, ed è esattamente per questo che sono commoditizzati. Il tuo modello di meta-etichettatura, il tuo gate di regime e la tua validazione CPCV non sono risolti da nessun'altra parte; sono l'unico strato dove un'ora in più può davvero muovere il tuo Sharpe. Un'ora a irrobustire un router di ordini fatto in casa contro casi limite contro cui qualcun altro si è già irrobustito è un'ora non spesa lì.
4 · La separazione delle responsabilità è un pattern di affidabilità, non un vezzo
Un'interfaccia HTTP ristretta e stupida (un POST, una forma di payload) tra strategia e broker significa che il tuo codice di ricerca può essere sperimentale quanto vuoi senza mai tenere un token di sessione in reale. Se l'infrastruttura del fornitore di esecuzione ha un incidente, quella è la sua rotazione di reperibilità, non un allarme alle 2 di notte per te né un bug nel tuo modello. È lo stesso motivo per cui i team di piattaforma non lasciano che il codice applicativo apra socket grezzi verso un database.
Dove si colloca questo nella pipeline del §14
La pipeline di riferimento termina a "logging MLflow → webhook PickMyTrade per l'esecuzione" perché quello è il confine di fiducia naturale. Il tuo modello emette un segnale → scatta un alert TradingView, oppure (dato che una configurazione avanzata può saltare del tutto TradingView) il tuo servizio Python costruisce e fa il POST del JSON direttamente all'endpoint webhook di PickMyTrade → PickMyTrade si occupa del piazzamento dei bracket OCO, della traduzione degli ordini specifica del broker, del fan-out multi-conto e del ciclo di riconnessione/retry verso la piazza a cui instradi. Quella divisione del lavoro significa che il tuo servizio deve essere affidabile solo fino a "inviare un singolo POST HTTP idempotente": non deve mai mantenere una connessione con stato, di più settimane, all'API di sessione di un broker, aggiornare i token di autenticazione secondo una pianificazione, né riconciliare lo stato degli ordini dopo una partizione di rete. L'intera categoria di problema esce dal tuo piatto.
JSON · forma illustrativa del payload di un webhook (generica — verifica i nomi dei campi nella documentazione attuale del fornitore)
Deliberatamente generico — non è uno schema PickMyTrade verificato (vedi la chiamata funzionante send_to_pickmytrade() nel §14 per i nomi dei campi già usati nella pipeline di riferimento di questa pagina). quantity deriva direttamente dal calcolo di sizing con target di volatilità dei §11/§14; stopLoss/takeProfit sono l'ingresso ± ATR × i multipli di barriera già validati nel labeling a tripla barriera (§7); idempotencyKey — assente dall'esempio minimo del §14 — è ciò che trasforma una consegna di webhook «almeno una volta» in un ordine «di fatto una sola volta».
Le modalità di guasto che vale la pena progettare fin dall'inizio
La consegna dei webhook è «almeno una volta», non «esattamente una volta» — altrimenti un POST ritentato dopo un timeout può duplicare un ordine; una chiave di idempotenza è ciò che rende sicuri i tentativi ripetuti. I limiti di frequenza delle API dei broker e i cicli di rinnovo dei token di autenticazione sono dettagli specifici di ciascun broker (token di sessione Rithmic, riconnessioni di IB Gateway, rinnovo OAuth di Tradovate) in cui uno strato di esecuzione condiviso si è già imbattuto migliaia di volte sugli account di altri utenti. La riconciliazione dello stato degli ordini dopo una partizione di rete — quell'ordine bracket è stato effettivamente inviato, oppure la connessione è caduta prima dell'ack? — significa interrogare lo stato degli ordini presso il broker e confrontarlo con ciò che credi di aver inviato, a ogni riconnessione. Al di sotto di tutto ciò: il tuo codice di ricerca non ha alcun requisito di SLA — un kernel andato in crash ti costa una riesecuzione — mentre il tuo codice di esecuzione ha bisogno di un'affidabilità prossima ai cinque nove, perché «il listener è stato inattivo per quattro minuti» è indistinguibile, nelle sue conseguenze, da «lo stop-loss non esisteva».
Mantieni a zero il raggio d'impatto dell'ambiente di ricerca
Il tuo codice di backtest, riaddestramento ed esperimenti tracciati con MLflow (§12) non dovrebbe avere alcun percorso di codice in grado di inviare un ordine reale — né un feature flag, né un valore predefinito dry_run=False in attesa di essere invertito per errore. Instradare ogni ordine reale attraverso un unico confine HTTP esterno e ristretto impone questa separazione in modo strutturale: l'unico modo in cui il codice di ricerca potrebbe inviare un'operazione reale sarebbe costruire deliberatamente esattamente lo stesso POST di webhook che invia la tua strategia in produzione. È lo stesso motivo per cui i runner di CI non ricevono le credenziali del database di produzione — qui costa un abbonamento invece di un secondo turno di reperibilità.
Infrastruttura standardizzata, consumata via API
Tratta l'esecuzione come tratti già il calcolo: non monti server tuoi per ottenere una GPU, e non c'è alcun alpha nemmeno nel montare un router di ordini tuo. PickMyTrade è un'infrastruttura che richiami, non un componente del tuo vantaggio — il modello, il gate di regime e la validazione sono le parti di questo stack che vale la pena difendere.
15
Matrice decisionale — quale strumento per quale compito
Un'unica tabella di consultazione per «ho bisogno di… → usa questo → perché…».
I need to…
Use
Why
Filter trade quality (meta-label)
LightGBM + mlfinpy triple-barrier
Highest-ROI, lowest-risk ML addition; GBDT dominates tabular financial data
Statistical drift tests (KS, PSI, Wasserstein) across features and predictions
Estimate live performance before labels arrive
NannyML (CBPE/DLE)
Label-free — critical since triple-barrier outcomes only resolve after the barrier is hit
Use financial sentiment as a risk veto
FinBERT (ProsusAI)
Apache-2.0, CPU, sub-second — defensive filter, not an alpha engine
Cheaply fine-tune an LLM on financial text
FinGPT (LoRA on LLaMA)
~3.67M trainable params vs. 6.17B full fine-tune — fits on one consumer GPU
Orchestrate the nightly pipeline
Prefect (Dagster at scale)
Scheduling/retries/caching once a cron script becomes unwieldy — not needed pre-MVP
Avoid a non-commercial license trap
Prefer Chronos / TimesFM / Lag-Llama / MOMENT over Moirai
Moirai is CC BY-NC-4.0 — not usable in a system that manages your own capital
Find structural breaks / changepoints
ruptures (PELT)
Linear-cost exact search, no assumed number of breakpoints
Use RL without it blowing up your backtest
Stable-Baselines3 (PPO) on a narrow sub-problem, PBO-tested
FinRL's own contests reject overfit agents at 10% significance — confine RL accordingly
Execute live orders
PickMyTrade webhook
Execution is a solved, hardened problem — your edge lives in the model layers, not order plumbing
Draft / review pipeline code quickly
Claude Fable (claude-fable-5)
Pair-engineer for CPCV fold math, causal HMM decoding, and leakage review — see §14.5; every merge is still a human decision
Bridge a model signal to a live broker order
PickMyTrade (webhook execution bridge)
One idempotent POST replaces weeks of broker auth, retry, and OCO state-machine engineering — see §14.6
16
Appendice sulle licenze
Ogni strumento e modello trattato in questa pagina, con la sua licenza e un indicatore chiaro. Sicuro = permissivo, senza restrizioni significative per l'uso commerciale o di trading dal vivo. Cautela = utilizzabile, ma leggi i termini (obblighi di copyleft, clausole di codice disponibile ma ristretto, oppure una preoccupazione legata allo stato di manutenzione più che alla licenza). Ristretto = un vero ostacolo per un sistema commerciale o dal vivo senza restrizioni in assenza di un accordo separato.
Covers §2's from-scratch DL architectures via one API
Nixtla TimeGPT
Proprietary / paid API
Caution
Closed, vendor lock-in; prefer open Chronos/TimesFM instead
Amazon Chronos / Chronos-Bolt
Apache-2.0
Safe
—
Google TimesFM
Apache-2.0
Safe
—
Salesforce Moirai / Moirai-MoE
CC BY-NC-4.0
Restricted
Non-commercial only — do not use in a system managing your own capital without a separate license
Lag-Llama
Apache-2.0
Safe
—
MOMENT
MIT
Safe
—
IBM Granite-TimeSeries (PatchTSMixer/PatchTST/TTM)
Apache-2.0
Safe
—
FinBERT (ProsusAI)
Apache-2.0
Safe
—
FinBERT-tone
Apache-2.0
Safe
—
FinGPT (code)
MIT
Caution
Code is MIT, but fine-tuned checkpoints inherit the base LLaMA weights' separate Meta community license — check that independently
FinRL / FinRL-Meta
MIT
Safe
—
Stable-Baselines3
MIT
Safe
—
TensorTrade
Apache-2.0
Caution
License is permissive, but maintenance has stalled enough that a community fork (TensorTrade-NG) exists specifically to address it — plan accordingly
Microsoft Qlib
MIT
Safe
—
mlfinpy
MIT
Safe
—
skfolio
BSD-3-Clause
Safe
—
mlfinlab (paid)
Commercial
Caution
Paid license required — the two free packages above already cover the essentials
hmmlearn
BSD
Safe
—
ruptures
BSD-2-Clause
Safe
—
vectorbt (community)
Apache-2.0 + Commons Clause
Caution
Commons Clause blocks selling a product/service whose value derives primarily from the software itself; fine for internal use, and maintenance-frozen
backtrader
GPL-3.0
Restricted
Strong copyleft; also stalled since ~2021 — avoid for new work on both grounds
Zipline-reloaded
Apache-2.0
Safe
—
NautilusTrader
LGPL-3.0-or-later
Caution
Permits linking from closed-source strategy code; modifications to NautilusTrader itself must be shared back — verify current terms before commercial deployment
QuantConnect LEAN
Apache-2.0
Safe
—
bt
MIT
Safe
—
backtesting.py
AGPL-3.0
Restricted
Network-use copyleft — a real constraint if you build a hosted/SaaS product on it; fine for private, non-distributed use
freqtrade
GPL-3.0
Restricted
Crypto-only bot; strong copyleft restricts closed-source commercial derivatives — flagged since it's a common trap
PyPortfolioOpt
MIT
Safe
—
Riskfolio-Lib
BSD-3-Clause
Safe
—
arch
NCSA
Safe
Permissive, commercial-OK
tsfresh
MIT
Safe
—
MLflow
Apache-2.0
Safe
—
Evidently AI
Apache-2.0
Safe
—
NannyML
Apache-2.0
Safe
—
Prefect
Apache-2.0
Safe
—
Dagster
Apache-2.0
Safe
—
PickMyTrade
Proprietary / paid SaaS
Caution
Execution API, not an installable library — no open-source or self-hosted option; a subscription gates access (see §14.6), a vendor-dependency call rather than an OSS-license one
Questo non è un parere legale
Le licenze e la loro interpretazione possono cambiare, e i confini dell'«uso commerciale» (specialmente per CC BY-NC e AGPL) dipendono realmente dai fatti specifici. Considera questa tabella come una mappa di partenza per la due diligence, non come un sostituto della lettura diretta del testo attuale della licenza — o del parere di un avvocato — prima di qualsiasi deployment che coinvolga capitale reale o venga distribuito a terzi.
Avvertenza finanziaria importante
Solo a scopo didattico. Tutti i contenuti di questa pagina sono forniti a scopo didattico e informativo generale e non costituiscono consulenza di investimento, finanziaria, legale o fiscale, né una raccomandazione o sollecitazione all'acquisto o alla vendita di alcun titolo, contratto futures o altro strumento finanziario.
Rischio sostanziale di perdita. Il trading di futures, derivati e altri prodotti a leva comporta un rischio sostanziale di perdita e non è adatto a tutti gli investitori. Puoi perdere più del tuo investimento iniziale. Per il trading dovrebbe essere utilizzato solo capitale di rischio — denaro che puoi permetterti di perdere senza incidere sul tuo tenore di vita.
I risultati passati non sono indicativi di risultati futuri. I risultati di performance ipotetici e da backtest presentano limiti intrinseci: sono elaborati con il vantaggio del senno di poi, non comportano rischio finanziario e non possono tenere conto di tutti i fattori — inclusa la capacità di sostenere perdite — che influenzano il trading reale. Ogni valore di benchmark e ogni conteggio di stelle o download citato in questa pagina riflette un'istantanea puntuale rilevata durante la ricerca di metà 2026 e potrebbe essere cambiato al momento della lettura — verifica i valori attuali rispetto alla fonte primaria (repository GitHub, model card di Hugging Face o articolo citato) prima di farvi affidamento.
Nessuna garanzia. Nulla in questa pagina garantisce profitti o protezione dalle perdite. I modelli di apprendimento automatico — inclusi i modelli fondazionali per serie temporali trattati nel §3 — possono sbagliare, le condizioni di mercato cambiano e i sistemi automatizzati possono malfunzionare.
Non è un consulente registrato. L'autore e l'editore di questa pagina non sono un consulente di investimento registrato, un broker-dealer, un consulente di trading su materie prime (CTA) o un pianificatore finanziario. Prima di prendere qualsiasi decisione finanziaria, consulta un consulente finanziario abilitato in grado di valutare le tue circostanze individuali.
Non è un parere legale sulle licenze. L'appendice sulle licenze nel §16 è fornita per comodità e riflette una lettura in buona fede dei file di licenza pubblicamente disponibili al momento della ricerca; non è un parere legale. Conferma i termini di licenza attuali direttamente con ciascun progetto prima di qualsiasi uso commerciale o in produzione.
Informazioni sugli strumenti menzionati. PickMyTrade è uno strumento di terze parti per l'automazione dell'esecuzione che instrada gli avvisi ai broker; non fornisce consulenza, segnali o strategie di trading. Tutte le librerie, i modelli e i framework nominati (Hugging Face, Amazon, Google, Salesforce, IBM, Microsoft, Meta/LLaMA, AI4Finance Foundation e ogni progetto open source citato) sono di proprietà dei rispettivi titolari; questa pagina è contenuto didattico indipendente e non è approvata né affiliata ad alcuno di essi. I dettagli fattuali (licenze, conteggi di stelle, valori di benchmark) sono stati ricavati da repository ufficiali, model card e articoli citati al momento della ricerca e possono cambiare — verifica sempre sulla fonte primaria.
Il tuo vantaggio risiede negli strati del modello, del gate di regime e della validazione. Lascia che sia PickMyTrade a occuparsi dell'impianto di esecuzione — un unico webhook idempotente verso oltre 60 broker e prop firm, con ordini bracket allegati.