Contenido solo educativo, no asesoramiento financiero. El trading conlleva un riesgo sustancial de pérdida.
Referencia avanzada · Librerías y modelos de ML/IA · Trading algorítmico

Guía avanzada de trading con IA: La referencia completa de librerías, modelos y frameworks de ML para cuants

Un mapa de nivel profesional del ecosistema de código abierto y Hugging Face para el trading sistemático: gradient boosting, arquitecturas profundas de series temporales, modelos base zero-shot, PLN financiero, aprendizaje por refuerzo, el kit de validación de López de Prado, motores de backtesting y MLOps, con notas de arquitectura, licencias, benchmarks y código para cada uno.

Prueba gratuita de 5 días
Sin tarjeta requerida
Operaciones ilimitadas
Ejecución instantánea

ML clásico / tabular: los caballos de batalla

Los árboles de decisión con gradient boosting (GBDT), no las redes profundas, son la familia de modelos por defecto para cada tarea tabular de clasificación/regresión de este pipeline: meta-etiquetado, características de régimen, puntuación de factores. Una comparación de 2024 ampliamente citada sobre más de 100-300 benchmarks tabulares halló que los GBDT igualan o superan al deep learning en datos tabulares con mucho menos ajuste (arXiv:2402.03970). Los datos financieros tabulares son exactamente el régimen donde esto se cumple con más fuerza: baja relación señal-ruido, características mixtas continuas/categóricas/dispersas, fuerte no estacionariedad y tamaños de muestra efectivos pequeños, condiciones en las que la flexibilidad de las redes profundas compra sobre todo varianza, no señal.

Por qué los GBDT dominan en datos financieros tabulares

  • Compromiso sesgo-varianza. Con unos pocos miles de filas efectivas (ponderadas por unicidad) y una señal débil y ruidosa, la baja sesgo de una red de alta capacidad tiene un coste de varianza que no puedes permitirte. Los árboles poco profundos con fuerte regularización (número de hojas, min-data-in-leaf, bagging) se sitúan en un punto mucho mejor de ese compromiso.
  • Características mixtas y dispersas de forma nativa. Los árboles dividen sobre valores de características en bruto: sin escalado, sin estrategia de imputación, sin tabla de embeddings para categóricas poco pobladas (sector, exchange, indicador de proximidad al vencimiento). El esfuerzo de ingeniería de características va a la señal, no a la fontanería de preprocesamiento.
  • Las restricciones monótonas codifican priores financieros directamente. LightGBM/XGBoost/CatBoost admiten todos monotone_constraints: p. ej. forzar que P(ganancia) sea no decreciente en la fuerza de la tendencia y no creciente en la volatilidad realizada. Esto regulariza hacia modelos con sentido de dominio y no está disponible, o es mucho más engorroso, en un MLP estándar.
  • Valores faltantes y no estacionariedad. Los árboles enrutan los valores faltantes de forma nativa (sin imputación propensa a fugas ajustada sobre todo el conjunto de datos), y los árboles poco profundos y reentrenados con frecuencia se adaptan más rápido a los cambios de régimen que una red grande que necesita muchas épocas para desaprender patrones obsoletos.
LibraryLicenseMaturity / stars*Categorical handlingSpeedBest fit here
LightGBMMITMature · moved microsoft/LightGBMlightgbm-org/LightGBM Mar 2026, still MITNative (histogram-based, leaf-wise growth)Fastest of the three on CPU, large-NDefault meta-label / primary classifier
XGBoostApache-2.0Mature, dmlc-maintained, huge ecosystemNeeds one-hot or target-encoding (or enable_categorical)Slightly slower than LightGBM on CPU histogram modeSecond opinion / ensembling partner for LightGBM
CatBoostApache-2.0Mature, Yandex-maintainedBest-in-class native categorical handling (ordered target stats)Slower to train, fast to scoreWhen you have many high-cardinality categoricals (symbol, sector, exchange)
scikit-learnBSD-3-ClauseFoundational, ~19+ yearsVia ColumnTransformer/OneHotEncoderN/A — utility layerCV splitters, metrics, pipelines, calibration, GMM — the glue, not the model

*Los recuentos de estrellas son orientativos, comprobados a mediados de 2026: trátalos como "orden de magnitud", no como cifras exactas.

LightGBM

MIT

Mecanismo: gradient boosting basado en histogramas con crecimiento del árbol por hojas (best-first) en lugar de por niveles: converge más rápido y normalmente a una pérdida menor que el crecimiento por niveles para un presupuesto de hojas dado, a costa de ser más propenso al sobreajuste en datos pequeños (contrólalo con num_leaves/min_data_in_leaf).

Cuándo usarlo: opción por defecto para el filtro de meta-etiqueta y cualquier clasificación/regresión tabular de este stack: entrenamiento en CPU más rápido, enrutamiento nativo de valores faltantes, restricciones monótonas nativas. Cuándo no: muestras muy pequeñas (< ~500 filas) donde el crecimiento por hojas sobreajusta rápido; prefiere XGBoost por niveles o una simple regresión logística ahí.

Python · Entrenamiento de meta-etiqueta con LightGBM sobre etiquetas de triple barrera
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

Mecanismo: árboles con boosting por niveles (depth-wise) con un objetivo regularizado (L1/L2 sobre los pesos de las hojas) integrado en el propio criterio de búsqueda de divisiones, además de un algoritmo de división por histograma/quantile-sketch bien optimizado para datos grandes.

Cuándo usarlo: como un segundo modelo con sesgo distinto para hacer ensembling con LightGBM (el crecimiento por niveles vs. por hojas decorrelaciona los errores de forma útil); entrenamiento en GPU si superas la CPU. Cuándo no: si necesitas un manejo nativo de primera clase de las categóricas sin preprocesamiento; CatBoost es mejor ahí.

Bash · instalación
pip install xgboost
# minimal use: xgboost.XGBClassifier(n_estimators=800, max_depth=4, learning_rate=0.03,
#   subsample=0.7, colsample_bytree=0.7, monotone_constraints="(1,0,-1,0,0,1,0,0,0,-1)")

CatBoost

Apache-2.0

Mecanismo: ordered boosting (un esquema basado en permutaciones que evita la fuga de objetivo que sufre el clásico target-encoding voraz) más estadísticas de objetivo ordenadas nativas para características categóricas: sin paso de codificación manual y menos propenso al desplazamiento de predicción que el target encoding ingenuo.

Cuándo usarlo: modelos transversales de cestas de acciones con muchas características categóricas (sector, industria, exchange, indicadores de pertenencia a índices) donde de otro modo tendrías que hacer target encoding a mano. Cuándo no: presupuestos ajustados de tiempo de entrenamiento en CPU; CatBoost suele ser el más lento de los tres en ajustarse, aunque rápido en puntuar.

Bash · instalación
pip install catboost
# CatBoostClassifier(cat_features=["sector","exchange"], iterations=1500,
#   depth=6, learning_rate=0.03, monotone_constraints="1:1,2:-1")

scikit-learn

BSD-3-Clause

Su papel aquí: no una familia de modelos competidora, sino el tejido conectivo: Pipeline para el preprocesamiento dentro del fold sin fugas, GroupKFold/particionadores purgados personalizados, GaussianMixture para una línea base ligera de régimen, CalibratedClassifierCV para convertir las puntuaciones de GBDT en probabilidades honestas antes de dimensionar posiciones a partir de ellas (las salidas en bruto de GBDT ordenan bien pero están mal calibradas).

Calibra antes de dimensionar

La salida de predict_proba de un GBDT es una buena señal de ranking, pero normalmente no es una probabilidad bien calibrada de fábrica: los GBDT tienden a empujar las predicciones hacia 0/1. Si tu dimensionador de posición consume la "confianza" directamente (fractional-Kelly, tamaño escalado por meta-etiqueta), envuelve el modelo en sklearn.calibration.CalibratedClassifierCV (isotónica o Platt) ajustado dentro del fold de CV, o tu dimensionamiento tendrá un exceso de confianza sistemático.

Arquitecturas de series temporales con deep learning

Estas son las arquitecturas neuronales desde cero que entrenarías tú mismo (normalmente vía neuralforecast, Apache-2.0, que las implementa todas), a diferencia de los modelos base preentrenados de la §3. Todas ellas fueron evaluadas para su creación en M4/M3/electricity/traffic/ETT: ninguna se diseñó frente a series de retornos financieros, y el veredicto honesto por arquitectura lo refleja.

ArchitectureYear / venueCore ideaProblem vs. plain LSTMFinancial-data verdict
LSTM / GRU1997 / 2014Gated 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.
TCNBai et al. 2018Stacked 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-BEATSOreshkin 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-HiTSChallu 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.
InformerZhou 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.
AutoformerWu 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.
FEDformerZhou 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.
PatchTSTNie 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.
iTransformerLiu 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.
La advertencia de DLinear: léela antes de recurrir a cualquier transformer

Zeng et al., "Are Transformers Effective for Time Series Forecasting?" (AAAI-23 Oral; código: cure-lab/LTSF-Linear) demostraron que una sola capa lineal con descomposición de tendencia/estacionalidad (DLinear) superó a Informer, Autoformer y FEDformer en casi todos los benchmarks estándar de horizonte largo, argumentando que sus mejoras reportadas provenían sobre todo de la estrategia de entrenamiento directo multi-paso no autorregresivo, no de la atención en sí. El análisis de seguimiento de Hugging Face lo matizó en parte (los transformers con parámetros equiparados lo hacen mejor), pero la lección práctica se mantiene: evalúa siempre cualquier arquitectura profunda frente a una línea base lineal/ARIMA (Nixtla statsforecast, §11) antes de fiarte de una mejora de precisión impulsada por la complejidad. Esto es doblemente cierto en datos financieros, donde el ruido domina la señal mucho más que en datos de electricidad o tráfico.

Modelos base de series temporales en Hugging Face

Los pronosticadores de series temporales preentrenados y zero-shot son reales y útiles, para la volatilidad, no para la dirección del precio. Un estudio de junio de 2026 construido específicamente para probar esto, "Pretrained Time-Series Foundation Models for Financial Return Forecasting" (Noguer i Alonso y Pereira Franklin, AI Finance Institute), evaluó TimeGPT, TimesFM-2.5, Moirai-2.0, Chronos y Chronos-2 frente a NBEATS/NHITS/PatchTST/iTransformer/KAN desde cero sobre cinco acciones estadounidenses líquidas (AAPL, AMZN, GOOG, JPM, META) con un protocolo de origen móvil frente a un benchmark de paseo aleatorio. El resultado: entre diez combinaciones de activo/tarea, solo dos mostraron un rendimiento superior estadísticamente significativo frente al paseo aleatorio: Chronos en AMZN y Moirai-2.0 en GOOG, y los autores afirman llanamente que "las ganancias sobre el benchmark de paseo aleatorio son pequeñas y escasas", concluyendo que los TSFM son "priores prácticos útiles que reducen los costes de desarrollo de modelos", pero explícitamente "no motores universales para la generación de alpha estadísticamente fiable". Trata cada modelo de abajo en consecuencia: motores excelentes, ejecutables en CPU, para entradas de volatilidad/pronóstico de vol a una capa de dimensionamiento; débiles frente al paseo aleatorio para la dirección del precio.

ModelOrgArchitecture familyParamsContextLicense
Chronos / Chronos-BoltAmazon ScienceT5-style encoder-decoder over quantized/tokenized values (Chronos) or direct patch-based multi-step regression heads (Bolt)Bolt-base 205M (mini→large family)Model-dependent, typically up to ~2048 ptsApache-2.0
TimesFMGoogle ResearchDecoder-only transformer over fixed-length input/output patches (32-in / 128-out patch config)200M (v1.0) / 500M (v2.0)Up to 2048 pts trained contextApache-2.0
Moirai / Moirai-MoESalesforceMasked-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 lengthCC BY-NC-4.0
Lag-LlamaServiceNow / 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, tunableApache-2.0
MOMENTAuton Lab, CMUTransformer trained multi-task (forecast + classify + detect anomalies + impute) on the "Time-series Pile" corpusSmall/Base/Large (~40M–341M)Task-dependentMIT
IBM Granite-TimeSeries (PatchTSMixer / PatchTST / TTM)IBM ResearchPatchTSMixer = all-MLP mixer over patches (no attention); PatchTST variant = patch-transformer; TTM = "Tiny Time Mixer," a very small pretrained mixerPatchTSMixer ~1M (task head), TTM sub-5M512-in / 96-out typical configsApache-2.0

Amazon Chronos / Chronos-Bolt

Apache-2.0 · 205M

Ficha del modelo: huggingface.co/amazon/chronos-bolt-base (la familia incluye también chronos-t5-{tiny,mini,small,base,large} y el más reciente amazon/chronos-2).

Arquitectura: el Chronos original tokeniza valores de series temporales escalados y cuantizados en un vocabulario fijo y los pasa por un codificador-decodificador T5 estándar, es decir, trata el pronóstico como modelado de lenguaje sobre un alfabeto numérico discretizado. Chronos-Bolt reemplaza la decodificación autorregresiva token a token por regresión directa multi-paso por parches, reportada como hasta ~250× más rápida y ~20× más eficiente en memoria con una precisión comparable o mejor (medida vía WQL/MASE en 27 conjuntos de datos de benchmark), entrenada con del orden de ~100.000 millones de observaciones de series temporales.

Veredicto: la mejor opción polivalente para una entrada de pronóstico de volatilidad solo en CPU: Apache-2.0, rápido, zero-shot, y el único modelo del benchmark 2606.27100 que alcanzó la significancia (en AMZN). Aun así: un resultado significativo de diez pruebas no es evidencia de una ventaja direccional repetible.

Python · pronóstico de volatilidad 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

Ficha del modelo: huggingface.co/google/timesfm-2.0-500m-pytorch (ICML 2024). Arquitectura: transformer solo decodificador entrenado para consumir parches de entrada de longitud fija (32 puntos) y emitir directamente parches de salida más largos (128 puntos), más cercano al objetivo de siguiente token de un modelo de lenguaje que al enfoque de valores tokenizados de Chronos, pero operando sobre embeddings de parches continuos en lugar de un vocabulario discretizado.

Veredicto: junto con Moirai-2.0, tuvo el rango medio más fuerte en el benchmark de cinco acciones (liderando en AAPL/JPM/GOOG/AMZN), pero según el propio planteamiento del paper, un rango fuerte ≠ una ventaja significativa; ninguna de las victorias de TimesFM superó el listón de significancia del paseo aleatorio. Bueno, bien mantenido, Apache-2.0, adecuado para volatilidad; no luz verde para la dirección del precio.

Bash · instalación
pip install timesfm
# tfm = timesfm.TimesFm(context_len=512, horizon_len=10, backend="cpu")
# tfm.load_from_checkpoint(huggingface_repo_id="google/timesfm-2.0-500m-pytorch")
# point_fc, quantile_fc = tfm.forecast([realized_vol_20d.values], freq=[0])

Salesforce Moirai / Moirai-MoE

CC BY-NC-4.0

Ficha del modelo: huggingface.co/Salesforce/moirai-1.0-R-large. Arquitectura: transformer de codificador enmascarado con "any-variate attention": en lugar de un embedding fijo por canal, aplana un número arbitrario de variables (objetivos + covariables dinámicas/estáticas) en una sola secuencia de tokens, de modo que un único modelo preentrenado maneja de forma nativa cualquier tarea de pronóstico multivariante sin reentrenamiento por conjunto de datos. Moirai-MoE cambia la FFN densa por una capa de mezcla de expertos para una mejor especialización con un coste de inferencia similar.

Bloqueo de licencia: léelo antes de tocar esto en un sistema en vivo

Los pesos de Moirai y Moirai-MoE se publican bajo CC BY-NC 4.0, solo uso no comercial. Usarlos (incluso solo para inferencia) dentro de un sistema que gestiona tu propio capital de trading es discutiblemente un uso comercial y no está cubierto por esta licencia sin un acuerdo aparte con Salesforce. Chronos, TimesFM, Lag-Llama y MOMENT son Apache-2.0/MIT y no conllevan tal restricción: prefiere esos para cualquier cosa que toque capital en vivo. Moirai está bien solo para investigación/backtesting personal.

Veredicto: Moirai-2.0 produjo el otro resultado significativo del benchmark (GOOG) y empató con TimesFM en el rango medio más fuerte: técnicamente interesante, pero las reglas de licencia lo descartan de un pipeline en vivo en cualquier caso.

Lag-Llama

Apache-2.0 · ~2.45M

Ficha del modelo: huggingface.co/time-series-foundation-models/Lag-Llama. Arquitectura: un transformer solo decodificador estilo LLaMA, pero en lugar de alimentarlo con valores en bruto o parches, cada token de entrada es un vector de lag features clásicas (valores en t-1, t-2, t-7, t-30, ...) más covariables de fecha/hora, es decir, pone un transformer encima de una representación con ingeniería de características que recuerda al modelado autorregresivo clásico, deliberadamente mantenido diminuto (~2,45 M de parámetros) frente a las demás entradas aquí.

Veredicto: no forma parte directamente del benchmark 2606.27100, pero arquitectónicamente es el más cercano a una línea base autorregresiva "transparente" del grupo: una segunda opinión razonable para pronosticar volatilidad cuando quieres algo más pequeño/rápido que Chronos-Bolt/TimesFM, y sigue siendo Apache-2.0 sin problemas.

MOMENT

MIT · ~341M

Ficha del modelo: huggingface.co/AutonLab/MOMENT-1-large (ICML 2024; Auton Lab, Carnegie Mellon). Arquitectura: un único backbone transformer preentrenado multitarea en pronóstico, clasificación, detección de anomalías e imputación sobre el curado "Time-series Pile", lo que lo hace el más generalista del grupo en lugar de un especialista en pronóstico.

Cuándo usarlo: sus cabezas de detección de anomalías e imputación son posiblemente más diferenciadas para un pipeline de trading que su cabeza de pronóstico, p. ej. señalar velas intradía anómalas en una compuerta de calidad de datos, o imputar huecos en un feed de datos alternativos, más que como el pronosticador de volatilidad en sí. Licencia: MIT, sin restricción.

IBM Granite-TimeSeries

Apache-2.0

Ficha del modelo: huggingface.co/ibm-granite/granite-timeseries-patchtsmixer (véase también ibm-granite/granite-timeseries-patchtst y la línea "Tiny Time Mixer" TTM). Arquitectura: PatchTSMixer reemplaza la atención por completo con un MLP-Mixer sobre parches, sin ningún coste de atención cuadrática, reportando 2-3× menos memoria/tiempo de ejecución que los patch-transformers con una precisión comparable o mejor en benchmarks públicos de horizonte largo (p. ej. 0,37 de MSE en el pronóstico a 96 pasos de ETTh1).

Cuándo usarlo: la opción más barata de ejecutar aquí por un amplio margen (existen variantes TTM de menos de 5 M de parámetros): buena opción si quieres un componente de pronóstico de vol ligero, trivial en CPU, y no necesitas la generalidad zero-shot de Chronos/TimesFM. Licencia: Apache-2.0.

La política en una frase para toda esta sección

Usa cualquier modelo Apache-2.0/MIT de aquí como entrada de volatilidad/covariable a la capa de dimensionamiento determinista de la §10; no uses ninguno de ellos, incluidos los resultados significativos de Chronos/Moirai, como señal de entrada autónoma: los propios autores del benchmark 2606.27100 califican el efecto de "pequeño y escaso", e iTransformer (una arquitectura desde cero, §2) superó a todos los modelos base en META, subrayando que el preentrenamiento no es una ventaja universal en las series financieras.

PLN financiero y LLM

El sentimiento/PLN financiero pertenece a la capa de riesgo (una característica de veto/régimen), no a la capa de alpha: según la investigación fuente de la §0, la ventaja del sentimiento de noticias por sí sola es en gran medida un artefacto de anticipación que muere fuera de muestra. Aquí están los tres modelos que realmente vale la pena conocer.

FinGPT

MIT (code)

Repositorio: github.com/AI4Finance-Foundation/FinGPT. Arquitectura: no un modelo entrenado desde cero, sino una receta de ajuste fino LoRA (Low-Rank Adaptation) aplicada a LLM base abiertos (LLaMA2-7B/13B para FinGPT v3.2/v3.3, ChatGLM2-6B para v3.1). LoRA congela los pesos base y entrena en su lugar pequeñas matrices adaptadoras de bajo rango, reduciendo los parámetros entrenables de ~6,17 B a ~3,67 M: práctico para ajustar en una sola GPU de consumo.

Casos de uso: análisis de sentimiento financiero, Q&A estilo robo-advisor y experimentos de pronóstico usando señales ingeniadas por LLM (también la base de la pista de "señales ingeniadas por LLM" de FinRL Contest). Matiz de licencia: el código de entrenamiento/inferencia de FinGPT es MIT, pero los pesos base subyacentes de LLaMA conllevan los propios términos de licencia comunitaria de Meta: compruébalos por separado antes de cualquier despliegue comercial de un checkpoint ajustado.

FinBERT-tone

Apache-2.0 · ~110M

Ficha del modelo: huggingface.co/yiyanghkust/finbert-tone (Huang, Wang y Yang, Contemporary Accounting Research 2022). Arquitectura: también BERT-base (12 capas / 768 ocultas / 12 cabezas), pero entrenado sobre un linaje de corpus diferente: preentrenado sobre texto de 10-K/10-Q/earnings calls y luego ajustado sobre 10.000 frases de informes de analistas anotadas manualmente, lo que le da un comportamiento de clasificación de tono algo distinto al del FinBERT de ProsusAI pese al nombre similar.

Cuándo usarlo: una segunda opinión de sentimiento entrenada de forma distinta para hacer ensembling con FinBERT específicamente sobre texto de informes de analistas o earnings calls (en lugar de titulares de noticias generales).

Aprendizaje por refuerzo para trading

El RL es el elemento más sobrevalorado y menos fiable de toda esta página para un motor de trading principal. El instrumental es genuinamente bueno; el veredicto honesto, respaldado por el propio concurso de benchmark de la comunidad de RL, es confinarlo a subproblemas estrechos y estrictamente validados (p. ej. el momento de ejecución) en lugar de un motor principal o a nivel de cartera.

LibraryLicenseRoleStatus
FinRLMITFinancial RL framework: environments, agents, DRL algorithm wrappers for stock/crypto/order-execution tasksActive; ~15k★, runs the annual FinRL Contest
FinRL-MetaMITDynamic market-environment and dataset layer for FinRL (hundreds of market simulators)Active, smaller community (~1–2k★)
Stable-Baselines3MITReliable, well-tested implementations of the underlying RL algorithms (PPO, SAC, DQN, A2C, TD3, DDPG, HER) that FinRL wrapsActively maintained, the de facto standard PyTorch RL library
TensorTradeApache-2.0RL 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.

Las cuatro familias de algoritmos (una línea cada una)

  • PPO (Proximal Policy Optimization): on-policy, acciones discretas o continuas; recorta el paso de actualización de la política para mantenerse cerca de la política anterior, sacrificando algo de eficiencia de muestra por estabilidad de entrenamiento. La primera opción por defecto en la mayoría de ejemplos de FinRL.
  • SAC (Soft Actor-Critic): off-policy, solo acciones continuas; objetivo de máxima entropía (premia explícitamente la exploración) con un búfer de repetición, generalmente más eficiente en muestra que PPO pero más sensible a los hiperparámetros.
  • DQN (Deep Q-Network): off-policy, solo acciones discretas; aprende una función de valor de acción mediante un búfer de repetición y una red objetivo. Necesita un espacio de acción discretizado (p. ej. comprar/mantener/vender), lo que encaja mal con el dimensionamiento continuo de posición.
  • A2C (Advantage Actor-Critic): on-policy, discreto o continuo; un primo más simple y síncrono de A3C, generalmente el más débil de los cuatro en tareas financieras en los propios benchmarks de FinRL.
Por qué el RL es concretamente frágil para el trading, no solo "difícil"

Panorama de recompensa no estacionario: la función de valor de un agente de RL se aprende frente a un régimen histórico específico; cuando el régimen cambia (como hacen constantemente los mercados financieros), la política aprendida optimiza para una superficie de recompensa que ya no existe. A diferencia de un meta-etiquetador GBDT reentrenado, no hay un arreglo simple de "reajustar sobre la última ventana" para una red de política sin arriesgar un olvido catastrófico. Ineficiencia de muestra: el RL profundo suele necesitar millones de interacciones con el entorno para converger; tú tienes exactamente una historia no repetible del mercado, así que "más datos" significa o bien simulación (que codifica tus propias suposiciones como verdad absoluta) o años de espera adicional de reloj. Reward-hacking en los backtests: un agente que optimiza el PnL simulado acumulado aprenderá con gusto a explotar las peculiaridades del simulador (suposiciones de ejecución irreales, impacto de mercado nulo, redondeo exacto del motor de backtest) en lugar de una verdadera ventaja de mercado, precisamente el modo de fallo que documenta el artículo de FinRL Contests (arXiv:2504.02281): los agentes enviados con una alta probabilidad de sobreajuste al backtest son explícitamente rechazados a un nivel de significancia del 10 % por los propios organizadores del concurso; las personas que construyen el ecosistema de trading con RL consideran que la mayoría de los agentes de trading con RL enviados son estadísticamente indistinguibles del ruido sobreajustado por defecto.

Alcance práctico, si usas RL en absoluto: un subproblema estrecho con una recompensa naturalmente en forma de MDP (p. ej. el momento de ejecución de órdenes dentro de una orden padre fija, seguimiento de VWAP), evaluado con la misma disciplina de PBO/DSR que todo lo demás en la §14, nunca como el motor principal de entrada/salida/dimensionamiento.

Pipelines completos de ML cuant: Microsoft Qlib

Qlib es lo más parecido a una plataforma de investigación IA-cuant llave en mano en código abierto: una capa de datos, un DSL de ingeniería de características, un zoo de modelos y un arnés de backtest walk-forward/análisis de cartera, conectados entre sí mediante configuraciones de flujo de trabajo YAML. Licencia MIT (microsoft/qlib), decenas de miles de estrellas en GitHub, MIT desde su apertura en septiembre de 2020, con lanzamientos activos (v0.9.7, agosto de 2025) y ahora emparejado con RD-Agent de Microsoft para experimentación automatizada de bucles de investigación.

Alpha158 vs. Alpha360: los dos conjuntos de características integrados

Alpha158Alpha360
What it is~158 hand-engineered technical/formulaic alpha features (returns, moving averages, volatility ratios, volume ratios, etc.)Raw normalized OHLCV history flattened over a 60-day lookback (6 fields × 60 days = 360 columns), essentially no feature engineering
Feature relationshipsLow spatial/temporal structure between columns — a classic tabular feature matrixStrong spatial-temporal structure — designed for models that learn their own representation from raw sequences
Best-paired modelsLightGBM, XGBoost, CatBoost, linear/MLP modelsGRU, LSTM, Transformer-family, ALSTM, GATs — sequence models that benefit from raw structure

Sistema de flujo de trabajo/configuración y zoo de modelos integrado

Los experimentos de Qlib se conducen normalmente mediante un único archivo YAML consumido por la CLI qrun, que declara el manejador de datos (Alpha158/360 o personalizado), el modelo, la división del conjunto de datos, la estrategia de cartera y los parámetros de backtest: esto hace que cambiar LightGBM por un GRU o un wrapper de TFT sea un cambio de configuración de una línea, no una reescritura. El zoo de modelos integrado abarca enfoques clásicos y profundos: LGBModel (LightGBM), XGBModel, CatBoostModel, MLP, GRU/LSTM/ALSTM (recurrentes), Transformer, wrapper de TFT, TabNet, HIST, IGMTF y varios modelos de investigación de grafos/atención (GATs, KRNN, Localformer), todos entrenados y evaluados a través del mismo arnés de flujo de trabajo con un informe compartido de backtest walk-forward/análisis de IC.

YAML · configuración mínima de flujo de trabajo de Qlib (LightGBM sobre 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
Apuntar Qlib a datos personalizados (p. ej. NSE)

Qlib incluye proveedores de datos de EE. UU. y China de fábrica; NSE/BSE requiere que construyas tu propio almacén de datos binario con scripts/dump_bin.py, alimentándolo con archivos Parquet/CSV de OHLCV point-in-time que ya hayas ensamblado (según la disciplina del plan de datos libre de sesgo de supervivencia). También necesitarás un calendario de trading personalizado (los festivos de NSE difieren de los de NYSE/China) y registrar tu archivo de universo de instrumentos: la capa de datos de Qlib es agnóstica al formato una vez convertida, así que Alpha158/360 y todo el zoo de modelos funcionan sin modificaciones sobre datos de NSE una vez hecho el paso de volcado.

Métodos de ML financiero de López de Prado: mlfinpy y skfolio

El conjunto de herramientas de Advances in Financial Machine Learning de López de Prado solía significar una licencia de pago de mlfinlab: ya no. Dos paquetes gratuitos y con licencia permisiva cubren ahora el etiquetado de triple barrera, el meta-etiquetado, la diferenciación fraccional, la ponderación de unicidad de muestras, CPCV y HRP.

PackageLicenseCovers
mlfinpyMITTriple-barrier labeling, meta-labeling, fractional differentiation, sample-weight/uniqueness utilities — a modern Pythonic re-implementation of the AFML code snippets
skfolioBSD-3-Clausescikit-learn-compatible portfolio optimization and model selection: CombinatorialPurgedCV out of the box, plus HRP, HERC, risk-budgeting, CVaR/CDaR optimization
mlfinlab (paid)CommercialThe original, packaged, paid version — only worth it if you specifically want Hudson & Thames' maintained extras beyond what the two free packages cover
Python · etiquetado de triple barrera 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 de skfolio para el modelo de meta-etiqueta
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)

Qué te aporta cada técnica

  • Diferenciación fraccional (mlfinpy.features.frac_diff / variante FFD de ancho fijo): halla el orden mínimo de diferenciación d (a menudo 0,2-0,5) que pasa un test de estacionariedad ADF conservando una correlación >0,9 con la serie de niveles, dando una entrada estacionaria que conserva memoria: estrictamente mejor para modelos de árbol/lineales que los retornos en bruto (memoria cero) o el precio en bruto (no estacionario).
  • Ponderación de unicidad de muestras: las etiquetas de triple barrera se solapan en el tiempo (un periodo de mantenimiento de 10 días significa que señales adyacentes comparten ventanas de etiqueta), violando la suposición IID en la que se basa la mayoría de la teoría de ML. Pondera cada muestra por su unicidad media (inverso del recuento de etiquetas concurrentes) más decaimiento temporal, o tu tamaño de muestra efectivo será una fracción de tu recuento de filas y cada test de significancia posterior estará sobrestimado.
  • Validación cruzada purgada combinatoria (CPCV): genera muchas combinaciones de rutas train/test (no una sola ruta walk-forward), purga las filas de entrenamiento cuya ventana de etiqueta se solapa con el fold de test, y aplica un embargo de margen tras cada fold de test. Produce una distribución completa de ratios de Sharpe fuera de muestra (que alimenta PBO y DSR) en lugar de una estimación puntual: por eso es estructuralmente más fiable que el walk-forward simple.
  • HRP (Hierarchical Risk Parity) (skfolio.optimization.HierarchicalRiskParity): asigna mediante agrupamiento jerárquico de la matriz de correlación en lugar de invertir una matriz de covarianza ruidosa (lo que hace la optimización media-varianza), lo que lo hace mucho más robusto al error de estimación en una cesta de acciones correlacionadas.

Detección de regímenes: hmmlearn y ruptures

Esta es la sección donde vive el error de fuga silenciosa más común en el gating de régimen minorista, y donde mostrar el patrón equivocado junto al correcto es más útil que describirlo en prosa.

LibraryLicenseMaturityRole
hmmlearnBSDMature, scikit-learn-style API, ~3k★Gaussian/GMM/Categorical HMMs for a discrete calm/stormy regime state
rupturesBSD-2-ClauseMature, 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
El error de anticipación silencioso número 1: decodificación HMM suavizada de muestra completa

La forma por defecto y más fácil de llamar a hmmlearn (ajustar GaussianHMM sobre todo tu historial y luego llamar a .predict() para obtener las etiquetas de régimen) usa por debajo la decodificación Viterbi/suavizada. La etiqueta de régimen en el tiempo t se elige usando la secuencia completa, incluyendo todo lo posterior a t. La compuerta "sabe" efectivamente que se acerca una crisis antes de que ocurra. Cada cifra deslumbrante publicada de reducción de drawdown con HMM (56 %→24 % de DD máximo, etc.) que no controle explícitamente esto está muy probablemente construida así. Abajo: el patrón con fugas, y el patrón causal, walk-forward, de posterior filtrada que sí es desplegable.

Python · INCORRECTO: decodificación suavizada de muestra completa con fugas (no desplegar)
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 · CORRECTO: compuerta de régimen causal, walk-forward, de posterior filtrada
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 es la herramienta complementaria cuando quieres puntos de cambio en lugar de un estado de régimen persistente, p. ej. señalar una ruptura de régimen de volatilidad en una serie EWMA para disparar un reajuste del HMM, o como detector alternativo de límites de régimen para contrastar las transiciones del HMM. Pelt (búsqueda exacta de coste lineal, número desconocido de puntos de ruptura, necesita un parámetro de penalización) es el predeterminado; Binseg sacrifica exactitud por velocidad en series más largas; los métodos basados en ventana son los más baratos pero los menos precisos en rupturas sutiles. Como el HMM, ejecútalo en una ventana expansiva/móvil para uso en vivo: la API estándar de ruptures también es un método offline de serie completa por defecto.

Motores de backtesting y ejecución

Ningún motor único es el adecuado para cada etapa. Usa un motor vectorizado para cribar miles de combinaciones de parámetros, y luego revalida cada superviviente en un motor basado en eventos con ejecuciones realistas antes de arriesgar capital: confundir las dos etapas (confiar en un backtest de motor vectorizado como tu respuesta final) es un error común y caro.

EngineSpeedFill realismLicenseMaintenanceBest-fit use case
vectorbt (community)Extremely fast (Numba-vectorized, thousands of configs at once)Weak — vectorized fills, easy to fool yourselfApache-2.0 + Commons ClauseCommunity edition maintenance-frozen; active dev moved to paid vectorbtPROFast first-pass parameter sweep / triage only
backtraderModerate (pure Python, event-driven)Moderate (configurable slippage/commission, but manual)GPL-3.0Stalled ~2021 — open PRs/issues unmerged for yearsLegacy strategies only; don't start new work here
Zipline-reloadedModerateGood (Quantopian-derived fill/slippage models)Apache-2.0Community-maintained fork (stefan-jansen), modest but real activityResearch backtests wanting the original Zipline/Quantopian API and pipeline model
NautilusTraderFast (Rust core)High — same strategy code path for backtest and liveLGPL-3.0-or-laterVery active, ~24k★, production-gradeFinal realistic-fill re-validation and the bridge to live — the one tool built for research-to-live parity
QuantConnect LEANFast (C#/.NET core, Python API)High — institutional-grade fill/slippage/margin modelsApache-2.0Very active, ~19k★, backs a commercial cloud platformFull-featured alternative to NautilusTrader, especially with QuantConnect's hosted data/cloud/live options
btModerateModerate (higher-level "Algo" abstraction over vectorized fills)MITActively maintained (releases into 2026)Fast, readable portfolio-level (multi-asset allocation) backtests, less suited to per-trade microstructure realism
backtesting.pyFast (single-asset, vectorized-ish)Basic (simple slippage/commission model)AGPL-3.0Active, small footprint, ~2.4k★Quick single-asset prototyping only — AGPL is a real constraint if you build a hosted/SaaS product on it

Por qué la arquitectura de NautilusTrader realmente importa

La mayoría de los fracasos de "gran backtest, real decepcionante" no son fallos del modelo: son bugs de sesgo entre investigación y producción: tu motor de backtest y tu código de ejecución en vivo son dos bases de código separadas que se separan silenciosamente (una suposición de precio de ejecución aquí, un bug de timing de vela por uno allá), y nada las obliga a mantenerse consistentes. El diseño basado en eventos con núcleo en Rust de NautilusTrader ejecuta el mismo código de estrategia (las mismas clases, los mismos manejadores de eventos) en modo backtest, paper y en vivo; solo cambian los adaptadores de datos/ejecución. Esa elección arquitectónica elimina toda una clase de bugs por construcción en lugar de por disciplina, por lo que es la herramienta adecuada para el papel de "revalidación final con ejecución realista y puente a producción" en lugar de un lujo prescindible.

Nota de licencia: LGPL-3.0, no GPL

NautilusTrader es LGPL-3.0-or-later, no la más estricta GPL-3.0 que rige backtrader y freqtrade. LGPL permite enlazar/usar la librería desde código propietario sin liberar tu código de estrategia, siempre que las modificaciones al propio NautilusTrader (si las hay) se compartan de vuelta: materialmente menos restrictivo que una dependencia GPL directa para un sistema de trading de código cerrado. Aun así, confirma los términos de licencia actuales en el repositorio antes de un despliegue comercial.

Construcción de carteras y riesgo

Aquí es donde el "control de drawdown" se implementa realmente: como matemática determinista que consume pronósticos de volatilidad y confianza de meta-etiqueta, no como otra tarea de predicción.

LibraryLicenseRole
PyPortfolioOptMITClassical mean-variance / efficient frontier, Black-Litterman, shrinkage covariance estimators, and HRP — the most approachable API of the three
Riskfolio-LibBSD-3-ClauseDeeper risk-based allocation: HRP/HERC, ~24 risk measures including CVaR/CDaR/EVaR, risk-parity/risk-budgeting, built on CVXPY convex optimization
archNCSAGARCH/EGARCH/GJR-GARCH/TARCH volatility-family models — the standard econometric volatility forecaster feeding vol-targeted sizing
Python · pronóstico de volatilidad GJR-GARCH → tamaño de posición con objetivo de 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

Cuándo usarlo: asignación rápida HRP o de covarianza con shrinkage sobre una cesta sin arrastrar un stack completo de dependencias de optimización convexa. Cuándo no: si necesitas objetivos CVaR/CDaR o medidas de riesgo más exóticas; ese es el trabajo de Riskfolio-Lib.

Python · asignación 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

Cuándo usarlo: siempre que el objetivo sea explícitamente consciente del riesgo de cola (CVaR/CDaR) en lugar de la varianza: mejor encaje para un mandato de "mínimo drawdown" que la media-varianza.

Python · cartera óptima 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)

Ingeniería de características y utilidades de pronóstico

Antes de fiarte de cualquier resultado de GBDT o de un modelo base, compáralo con la línea base aburrida. Estas dos librerías cubren la extracción automatizada de características y las líneas base de pronóstico clásicas que nunca deberías saltarte.

LibraryLicenseRole
tsfreshMITAutomated 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 statsforecastApache-2.0Fast classical/econometric baselines — AutoARIMA, AutoETS, AutoCES, Theta — the mandatory benchmark before believing any ML "edge"
Nixtla mlforecastApache-2.0Machine-learning forecasting at scale (pandas/polars/Spark/Dask/Ray backends) with the same lag-feature-engineering plumbing regardless of backend
Nixtla neuralforecastApache-2.030+ 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 · extracción de características automatizada + filtrada 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 · línea base obligatoria antes de fiarte de la "ventaja" de cualquier modelo
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

MLOps para un sistema de trading en vivo

El instrumental de MLOps aquí no va de escala: va de honestidad. La función de MLOps más determinante de todo este stack es la disciplina de recuento de pruebas para el Deflated Sharpe Ratio: cada configuración de backtest que hayas probado, registrada, para siempre, de modo que la corrección por pruebas múltiples se calcule frente a tu recuento de pruebas real, no el subconjunto halagador que recuerdas.

ToolLicenseRoleWhen to adopt
MLflowApache-2.0Experiment tracking (params/metrics/artifacts) + model registry with stage transitionsEarly — every single backtest run, from day one, feeds the DSR trial count
Evidently AIApache-2.0Input-feature and prediction-distribution drift detection (KS-test, PSI, Wasserstein, 100+ built-in metrics)Once a strategy is running on a schedule against live data
NannyMLApache-2.0Label-free live performance estimation — CBPE for classifiers, DLE for regressors — estimates real-world accuracy before ground-truth labels are even availableOnce paper/live trading is running and labels arrive with a lag (exactly the triple-barrier situation)
PrefectApache-2.0Pythonic pipeline orchestration: scheduling, retries, caching, event-driven triggers for the nightly ingest→feature→predict→size→alert DAGOnce a plain cron script becomes unwieldy — not needed for an MVP
DagsterApache-2.0Alternative orchestrator with stronger data-asset lineage/typing — heavier but better observability at scaleIf you outgrow Prefect's simplicity and want asset-level lineage across many pipelines
Python · registro con MLflow que realmente impone la disciplina de recuento de pruebas 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.
Por qué esto es innegociable, no un lujo prescindible

El Deflated Sharpe Ratio necesita un recuento honesto de cada configuración que hayas probado alguna vez contra estos datos, no solo el modelo final. Sin un sistema de registro, el recuento de pruebas se reconstruye de memoria en el momento exacto en que más motivado estás para subestimarlo. MLflow (o un equivalente) convierte "cuántas cosas probé realmente" de una conjetura autoinformada en un hecho consultable.

Datos y conjuntos de datos alternativos en Hugging Face

Más allá de los hubs de modelos, el Datasets Hub de Hugging Face alberga un conjunto creciente de datasets relevantes para las finanzas que vale la pena conocer para prototipado y trabajo de sentimiento: trátalos todos como fuentes de prototipado/respaldo, no como datos de producción libres de sesgo de supervivencia (véase la disciplina del Plan de Datos en el informe de investigación fuente).

DatasetTypeNotes
mito0o852/OHLCV-1mUS equities, minute OHLCVThousands of US stocks, 1992–2026, sourced from Finnhub.io
123olp/binance-futures-ohlcv-2018-2026Crypto futures OHLCVBinance futures history 2018–2026 — good CCXT-pipeline-test alternative/backup
TimKoornstra/financial-tweets-sentimentSocial sentimentLabeled Twitter/X financial and crypto sentiment — useful for fine-tuning or validating a FinBERT-style veto filter
huggingface.co/datasets?search=financeHub searchThe 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 juego diferente, no una fuente de datos para tu propio sistema

Numerai se entiende mejor como un mercado de habilidad de modelado, no como un dataset para enchufar a tu propio pipeline. El torneo principal ofrece características gratuitas, preprocesadas y ofuscadas: con PCA, z-scored y segmentadas en el tiempo para que puedas modelar datos financieros de clase mundial sin saber nunca qué acciones o fechas estás mirando (cada "era" semanal tiene IDs que no se corresponden entre eras, por diseño). Numerai Signals es el producto complementario: envías predicciones sobre tu propio universo/características, buscando señales ortogonales a lo que el stack de modelos existente de Numerai ya captura. Todos los modelos enviados alimentan un meta-modelo ponderado por stake que a su vez impulsa el propio hedge fund de Numerai. Enmárcalo como opcionalidad para monetizar la habilidad de modelado (evaluado sobre rendimiento plurianual e inclusivo de drawdown, no como una vía rápida hacia ingresos) y como un ecosistema adyacente interesante en lugar de un componente del pipeline de la §14.

Arquitectura de referencia: pipeline completo

Cómo un usuario avanzado conecta cada librería anterior en un solo pipeline, de principio a fin. Ingesta de datos → características de Qlib/tsfresh → diferenciación fraccional (mlfinpy) → modelo de meta-etiqueta LightGBM validado con validación cruzada purgada combinatoria anidada (skfolio) → compuerta de régimen causal con hmmlearn → dimensionamiento con objetivo de vol basado en GARCH (arch) → backtest con NautilusTrader → registro con MLflow → webhook de PickMyTrade para la ejecución.

Reference pipeline: data → features → labels → meta-label CV → regime/sizing → NautilusTrader → MLflow → PickMyTrade 1 · Data ingestion Point-in-time OHLCV + constituent/delisting table; Parquet/DuckDB no survivorship bias 2 · Features Qlib Alpha158 + tsfresh + mlfinpy fractional differentiation (FFD) fit inside-fold only 3 · Triple-barrier mlfinpy: causal EWMA vol → PT/SL/vertical barriers + sample weight uniqueness-weighted 4 · Meta-label model LightGBM inside skfolio CombinatorialPurgedCV → PBO + Deflated Sharpe reject if PBO > 50% 5 · Regime + sizing Causal filtered hmmlearn gate + GARCH (arch) vol- targeted fractional Kelly deterministic math 6 · NautilusTrader One strategy class, backtest → paper → live (only adapters swap) research/live parity 7 · MLflow → PickMyTrade Every run logged; webhook JSON → broker bracket order execute, don't build
Cada flecha es un traspaso de datos entre una librería intercambiable de forma independiente: ninguna etapa depende de una elección específica en otra.
Python · esqueleto del pipeline de referencia de principio a fin
"""
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()
Cada flecha es un punto de intercambio, por diseño

Fíjate en que ninguna etapa está cableada a una elección específica de secciones anteriores: cambia LightGBM por CatBoost, el Alpha158 de Qlib por un conjunto de características hecho a mano, NautilusTrader por QuantConnect LEAN, o PickMyTrade por un puente de ejecución distinto, y nada más en el pipeline necesita cambiar. Ese desacoplamiento es lo que hace que la matriz de decisión de la §15 sea accionable en lugar de prescriptiva.

Claude Fable como ingeniero de apoyo para este stack

Claude Fable es el modelo de vanguardia de Anthropic (id de modelo claude-fable-5), disponible a través de la app de Claude y de Claude Code. En un stack tan profundo, su valor no es "escríbeme un bot de trading": es el punto intermedio poco glamuroso y propenso a errores: acertar la aritmética de los folds de CPCV, escribir un bucle de decodificación de HMM causal (no con fugas) a la primera, cablear un manejador de datos de Qlib para un mercado que no viene de fábrica, y leer un pipeline multietapa de principio a fin en busca de la única fuga que de otro modo solo saldría a la luz como una brecha entre real y backtest meses después.

Dónde se gana el sueldo en el stack específico de esta página:

  • Lógica de folds de CPCV: derivar los tamaños de purga/embargo a partir del horizonte de tu etiqueta y del lookback de característica más lento (§7), en lugar de adivinarlos y descubrirlo por un Sharpe de backtest inflado.
  • Inferencia de régimen causal: escribir el bucle de posterior filtrada, walk-forward, en lugar de la llamada con fugas a decode()/Viterbi de muestra completa mostrada como el ejemplo "incorrecto" en la §8.
  • Configuración de Qlib: generar y adaptar el YAML de flujo de trabajo Alpha158/Alpha360 a un manejador de datos personalizado para una región que Qlib no incluye, como el ejemplo de NSE en la §6.
  • Revisión de fugas en todo el pipeline: leer el esqueleto de la §14 etapa por etapa en busca de un bug de ajuste fuera del fold antes de que llegue a tocar capital.
  • Conversión de Pine Script → Python: portar la lógica de entrada de una estrategia de TradingView a la función de señal primaria que alimenta el modelo de meta-etiquetado.
  • Pegamento de ejecución: redactar el código del payload del webhook / clave de idempotencia cubierto en la §14.6, y el registro con MLflow que mantiene honesto tu recuento de pruebas del Deflated Sharpe (§12).

Prompts listos para adaptar para cada uno de esos, específicos del stack de esta página, no peticiones genéricas de "constrúyeme un bot":

Prompt 1 · Revisión de purga/embargo de 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 · Compuerta de régimen HMM causal, no con fugas
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 en un mercado no predeterminado
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 · Auditoría de fugas de todo el 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 → función de señal primaria
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 de webhook + clave de idempotencia
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 redacta, tú fusionas

Ninguno de los prompts anteriores reemplaza la lectura del diff por ti mismo. Claude Fable es rápido en las partes mecánicas (aritmética de folds de CV, lógica de reintentos repetitiva, convertir Pine a pandas), pero los tamaños de purga/embargo, los umbrales de rechazo de PBO/DSR y la decisión de enrutar capital a través de un webhook dado siguen siendo tuyos para firmarlos, cada vez, antes de que nada toque una cuenta de paper o real.

Puente de ejecución: construir vs. comprar para el último salto

La misma decisión de construir vs. comprar que toma cualquier equipo de sistemas, aplicada al último salto del pipeline de la §14: ¿tus escasas horas de ingeniería van a la fontanería de enrutamiento de órdenes, o a las capas de modelo que sí son tuyas? Esta sección defiende tratar la ejecución en vivo como una dependencia comprada de interfaz estrecha, y muestra cómo se ve la interfaz desde el lado del pipeline.

1 · La fontanería de enrutamiento de órdenes tiene un gran radio de impacto para bugs silenciosos

Lógica de reintentos, reautenticación de sesión del bróker, reconciliación de ejecuciones parciales, máquinas de estado de brackets OCO, deduplicación de webhooks: cada una es un problema bien entendido de forma aislada, y cada una es exactamente el tipo de código donde un bug no lanza una excepción. Silenciosamente duplica una orden, descarta un stop o deja una máquina de estado en el nodo equivocado. Un listener caído manteniendo una posición de futuros abierta de un día para otro no es un stack trace; es una llamada a la mesa de tu bróker.

2 · Un bug de ejecución silencioso es un evento de P&L, no una excepción capturada

Los errores de tu modelo aparecen como un Sharpe más bajo a lo largo de miles de operaciones: ruidosos pero acotados y diagnosticables. Un error de la capa de ejecución aparece como un stop concreto que falta o una ejecución duplicada, realizado en dólares, normalmente la única vez que la volatilidad se dispara y no estás mirando el terminal. Los tests unitarios atrapan los bugs para los que pensaste escribir un test; rara vez atrapan un token de sesión que expira a media jornada o un webhook entregado dos veces durante un fallo de red.

3 · Las horas que vale la pena invertir son las que solo tú puedes invertir

Reintentos/backoff, máquinas de estado OCO y traducción de órdenes específica del bróker son el mismo problema para cada trader que enruta a Rithmic o IB, y por eso están comoditizadas. Tu modelo de meta-etiquetado, tu compuerta de régimen y tu validación CPCV no están resueltos en ningún otro sitio; son la única capa donde una hora extra puede realmente mover tu Sharpe. Una hora endureciendo un enrutador de órdenes casero frente a casos límite contra los que alguien ya se endureció es una hora no invertida ahí.

4 · La separación de responsabilidades es un patrón de fiabilidad, no un adorno

Una interfaz HTTP estrecha y tonta (un POST, una forma de payload) entre estrategia y bróker significa que tu código de investigación puede ser tan experimental como quieras sin llegar nunca a mantener un token de sesión en vivo. Si la infraestructura del proveedor de ejecución tiene un incidente, esa es su rotación de guardia, no un aviso a las 2 de la mañana para ti ni un bug en tu modelo. Es la misma razón por la que los equipos de plataforma no dejan que el código de aplicación abra sockets en bruto a una base de datos.

Dónde encaja esto en el pipeline de la §14

El pipeline de referencia termina en "registro con MLflow → webhook de PickMyTrade para la ejecución" porque ese es el límite de confianza natural. Tu modelo emite una señal → se dispara una alerta de TradingView, o (dado que una configuración avanzada puede saltarse TradingView por completo) tu propio servicio Python construye y hace POST del JSON directamente al endpoint del webhook de PickMyTrade → PickMyTrade se encarga de la colocación de brackets OCO, la traducción de órdenes específica del bróker, el fan-out multicuenta y el bucle de reconexión/reintento contra el mercado al que enrutes. Esa división del trabajo significa que tu servicio solo tiene que ser fiable hasta "enviar un POST HTTP idempotente": nunca tiene que mantener una conexión con estado, de varias semanas, a la API de sesión de un bróker, refrescar tokens de autenticación según un horario ni reconciliar el estado de las órdenes tras una partición de red. Toda esa categoría de problema se retira de tu plato.

JSON · forma ilustrativa del payload de un webhook (genérica — verifica los nombres de los campos con la documentación actual del proveedor)
{
  "idempotencyKey": "SIG-MES-2026-07-03T14:32:00Z-000481",
  "symbol": "MES",
  "side": "buy",
  "quantity": 2,
  "orderType": "market",
  "stopLoss": 5320.25,
  "takeProfit": 5364.75,
  "meta": {
    "metaLabelConfidence": 0.62,
    "atr14": 14.8,
    "slAtrMult": 1.5,
    "tpAtrMult": 2.0,
    "regimeState": 1
  }
}

Deliberadamente genérico — no es un esquema verificado de PickMyTrade (consulta la llamada operativa send_to_pickmytrade() en §14 para los nombres de campo que ya se usan en el pipeline de referencia de esta página). quantity sale directamente del cálculo de sizing con objetivo de volatilidad de §11/§14; stopLoss/takeProfit son la entrada ± ATR × los múltiplos de barrera ya validados en el etiquetado de triple barrera (§7); idempotencyKey — ausente del ejemplo mínimo de §14 — es lo que convierte una entrega de webhook «al menos una vez» en una orden «efectivamente una vez».

Los modos de fallo que conviene contemplar desde el principio

La entrega de webhooks es «al menos una vez», no «exactamente una vez» — de lo contrario, un POST reintentado tras un tiempo de espera puede duplicar una orden; una clave de idempotencia es lo que hace seguros los reintentos. Los límites de tasa de las API de los brókeres y los ciclos de renovación de tokens de autenticación son detalles propios de cada bróker (tokens de sesión de Rithmic, reconexiones de IB Gateway, renovación OAuth de Tradovate) con los que una capa de ejecución compartida ya ha tropezado miles de veces en las cuentas de otros usuarios. La reconciliación del estado de las órdenes tras una partición de red — ¿se llegó a colocar esa orden bracket, o se cayó la conexión antes del ack? — implica consultar el estado de las órdenes en el bróker y contrastarlo con lo que crees que enviaste, en cada reconexión. Por debajo de todo ello: tu código de investigación no tiene requisitos de SLA — un kernel caído te cuesta una reejecución — mientras que tu código de ejecución necesita una fiabilidad cercana a los cinco nueves, porque «el listener estuvo caído cuatro minutos» es indistinguible, en sus consecuencias, de «el stop-loss no existía».

Mantén el radio de impacto del entorno de investigación en cero

Tu código de backtest, reentrenamiento y experimentos rastreados con MLflow (§12) no debería tener ninguna ruta de código capaz de colocar una orden real — ni un feature flag, ni un valor por defecto dry_run=False a la espera de que alguien lo cambie por error. Enrutar cada orden real a través de una única frontera HTTP externa y estrecha impone esa separación de forma estructural: la única manera de que el código de investigación pudiera colocar una operación real sería construyendo deliberadamente exactamente el mismo POST de webhook que hace tu estrategia en vivo. Es la misma razón por la que los runners de CI no reciben credenciales de la base de datos de producción — aquí cuesta una suscripción en lugar de una segunda rotación de guardias.

Infraestructura mercantilizada, consumida vía API

Trata la ejecución igual que ya tratas la computación: no montas tus propios servidores para conseguir una GPU, y tampoco hay alfa en montar tu propio enrutador de órdenes. PickMyTrade es infraestructura que llamas, no un componente de tu ventaja competitiva — el modelo, la puerta de régimen y la validación son las partes de este stack que vale la pena defender.

Matriz de decisión — qué herramienta para qué trabajo

Una única tabla de consulta para «necesito… → usa esto → porque…».

I need to…UseWhy
Filter trade quality (meta-label)LightGBM + mlfinpy triple-barrierHighest-ROI, lowest-risk ML addition; GBDT dominates tabular financial data
Detect market regime causallyhmmlearn (filtered posterior) + ruptures cross-checkCheap, interpretable; ruptures independently confirms structural breaks the HMM finds
Size positionsarch (GARCH) vol forecast + fractional KellyDeterministic math owns sizing — this is where drawdown control actually lives
Get a zero-shot volatility forecastChronos-Bolt or TimesFMApache-2.0, CPU-runnable, no training needed, legitimately useful for vol (not direction)
Validate without leakageskfolio CombinatorialPurgedCV + PBO + Deflated SharpeProduces an OOS performance distribution, not one lucky split; lower PBO than plain walk-forward
Track every experiment / enforce trial-count honestyMLflowThe DSR correction is only as honest as your trial count — MLflow makes it a queryable fact, not a memory
Fast first-pass parameter sweepvectorbt (community)Numba-vectorized triage of thousands of configs in seconds — never trust it as the final answer
Re-validate with realistic fills before capitalNautilusTraderOnly engine here with true research-to-live parity — same strategy code, real fill/slippage modeling
Build a full quant research pipeline fastMicrosoft QlibData handler + Alpha158/360 + model zoo + walk-forward harness, all wired via one YAML config
Extract automated time-series featurestsfreshHundreds of candidate features with a built-in FDR-controlled relevance filter
Benchmark before trusting any "edge"Nixtla statsforecast AutoARIMA/AutoETSMandatory sanity check — DLinear/AAAI-23 showed complexity alone proves nothing
Allocate across a correlated basketHRP via PyPortfolioOpt, skfolio, or Riskfolio-LibRobust to noisy covariance estimates, unlike mean-variance optimization
Optimize for tail risk specifically (CVaR/CDaR)Riskfolio-LibPurpose-built convex-optimization risk measures beyond variance — matches a "least drawdown" mandate
Detect live input/prediction driftEvidently AIStatistical drift tests (KS, PSI, Wasserstein) across features and predictions
Estimate live performance before labels arriveNannyML (CBPE/DLE)Label-free — critical since triple-barrier outcomes only resolve after the barrier is hit
Use financial sentiment as a risk vetoFinBERT (ProsusAI)Apache-2.0, CPU, sub-second — defensive filter, not an alpha engine
Cheaply fine-tune an LLM on financial textFinGPT (LoRA on LLaMA)~3.67M trainable params vs. 6.17B full fine-tune — fits on one consumer GPU
Orchestrate the nightly pipelinePrefect (Dagster at scale)Scheduling/retries/caching once a cron script becomes unwieldy — not needed pre-MVP
Avoid a non-commercial license trapPrefer Chronos / TimesFM / Lag-Llama / MOMENT over MoiraiMoirai is CC BY-NC-4.0 — not usable in a system that manages your own capital
Find structural breaks / changepointsruptures (PELT)Linear-cost exact search, no assumed number of breakpoints
Use RL without it blowing up your backtestStable-Baselines3 (PPO) on a narrow sub-problem, PBO-testedFinRL's own contests reject overfit agents at 10% significance — confine RL accordingly
Execute live ordersPickMyTrade webhookExecution is a solved, hardened problem — your edge lives in the model layers, not order plumbing
Draft / review pipeline code quicklyClaude 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 orderPickMyTrade (webhook execution bridge)One idempotent POST replaces weeks of broker auth, retry, and OCO state-machine engineering — see §14.6

Apéndice de licencias

Cada herramienta y modelo tratado en esta página, con su licencia y un indicador claro. Segura = permisiva, sin restricción significativa para el uso comercial o de trading en vivo. Precaución = usable, pero lee los términos (obligaciones de copyleft, cláusulas de código disponible pero restringido, o una preocupación por el estado de mantenimiento más que por la licencia). Restringida = un obstáculo real para un sistema comercial o en vivo sin restricciones si no media un acuerdo aparte.

Tool / modelLicenseFlagNote
LightGBMMITSafe
XGBoostApache-2.0Safe
CatBoostApache-2.0Safe
scikit-learnBSD-3-ClauseSafe
neuralforecast / statsforecast / mlforecast (Nixtla)Apache-2.0SafeCovers §2's from-scratch DL architectures via one API
Nixtla TimeGPTProprietary / paid APICautionClosed, vendor lock-in; prefer open Chronos/TimesFM instead
Amazon Chronos / Chronos-BoltApache-2.0Safe
Google TimesFMApache-2.0Safe
Salesforce Moirai / Moirai-MoECC BY-NC-4.0RestrictedNon-commercial only — do not use in a system managing your own capital without a separate license
Lag-LlamaApache-2.0Safe
MOMENTMITSafe
IBM Granite-TimeSeries (PatchTSMixer/PatchTST/TTM)Apache-2.0Safe
FinBERT (ProsusAI)Apache-2.0Safe
FinBERT-toneApache-2.0Safe
FinGPT (code)MITCautionCode is MIT, but fine-tuned checkpoints inherit the base LLaMA weights' separate Meta community license — check that independently
FinRL / FinRL-MetaMITSafe
Stable-Baselines3MITSafe
TensorTradeApache-2.0CautionLicense is permissive, but maintenance has stalled enough that a community fork (TensorTrade-NG) exists specifically to address it — plan accordingly
Microsoft QlibMITSafe
mlfinpyMITSafe
skfolioBSD-3-ClauseSafe
mlfinlab (paid)CommercialCautionPaid license required — the two free packages above already cover the essentials
hmmlearnBSDSafe
rupturesBSD-2-ClauseSafe
vectorbt (community)Apache-2.0 + Commons ClauseCautionCommons Clause blocks selling a product/service whose value derives primarily from the software itself; fine for internal use, and maintenance-frozen
backtraderGPL-3.0RestrictedStrong copyleft; also stalled since ~2021 — avoid for new work on both grounds
Zipline-reloadedApache-2.0Safe
NautilusTraderLGPL-3.0-or-laterCautionPermits linking from closed-source strategy code; modifications to NautilusTrader itself must be shared back — verify current terms before commercial deployment
QuantConnect LEANApache-2.0Safe
btMITSafe
backtesting.pyAGPL-3.0RestrictedNetwork-use copyleft — a real constraint if you build a hosted/SaaS product on it; fine for private, non-distributed use
freqtradeGPL-3.0RestrictedCrypto-only bot; strong copyleft restricts closed-source commercial derivatives — flagged since it's a common trap
PyPortfolioOptMITSafe
Riskfolio-LibBSD-3-ClauseSafe
archNCSASafePermissive, commercial-OK
tsfreshMITSafe
MLflowApache-2.0Safe
Evidently AIApache-2.0Safe
NannyMLApache-2.0Safe
PrefectApache-2.0Safe
DagsterApache-2.0Safe
PickMyTradeProprietary / paid SaaSCautionExecution 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
Esto no es asesoramiento legal

Las licencias y su interpretación pueden cambiar, y los límites del «uso comercial» (especialmente en CC BY-NC y AGPL) son genuinamente específicos de cada caso. Trata esta tabla como un mapa de partida para la debida diligencia, no como un sustituto de leer tú mismo el texto actual de la licencia — o la opinión de un abogado — antes de cualquier despliegue que implique capital real o que se distribuya a terceros.

Aviso financiero importante

Solo con fines educativos. Todo el contenido de esta página se ofrece con fines educativos e informativos generales y no constituye asesoramiento de inversión, financiero, legal ni fiscal, ni una recomendación o solicitud de compra o venta de ningún valor, contrato de futuros u otro instrumento financiero.

Riesgo sustancial de pérdida. Operar con futuros, derivados y otros productos apalancados conlleva un riesgo sustancial de pérdida y no es adecuado para todos los inversores. Puedes perder más que tu inversión inicial. Para operar solo debe utilizarse capital de riesgo — dinero que puedas permitirte perder sin que afecte a tu nivel de vida.

Los resultados pasados no son indicativos de resultados futuros. Los resultados de rendimiento hipotéticos y de backtest tienen limitaciones inherentes: se elaboran con la ventaja de la retrospectiva, no implican riesgo financiero y no pueden dar cuenta de todos los factores — incluida la capacidad de soportar pérdidas — que afectan a la operativa real. Cada cifra de benchmark y cada recuento de estrellas o descargas citado en esta página refleja una instantánea puntual tomada durante la investigación de mediados de 2026 y puede haber cambiado para cuando lo leas — verifica las cifras actuales frente a la fuente primaria (repositorio de GitHub, tarjeta de modelo de Hugging Face o artículo citado) antes de basarte en ellas.

Sin garantías. Nada en esta página garantiza beneficios ni protección frente a pérdidas. Los modelos de aprendizaje automático — incluidos los modelos fundacionales de series temporales tratados en §3 — pueden equivocarse, las condiciones del mercado cambian y los sistemas automatizados pueden fallar.

No es un asesor registrado. El autor y el editor de esta página no son un asesor de inversiones registrado, un bróker-dealer, un asesor de trading de materias primas (CTA) ni un planificador financiero. Antes de tomar cualquier decisión financiera, consulta a un asesor financiero autorizado que pueda evaluar tus circunstancias individuales.

No es asesoramiento legal sobre licencias. El apéndice de licencias de §16 se ofrece por comodidad y refleja una lectura de buena fe de los archivos de licencia públicamente disponibles en el momento de la investigación; no es asesoramiento legal. Confirma los términos actuales de cada licencia directamente con cada proyecto antes de cualquier uso comercial o en producción.

Acerca de las herramientas mencionadas. PickMyTrade es una herramienta de automatización de la ejecución de terceros que enruta alertas a los brókeres; no proporciona asesoramiento, señales ni estrategias de trading. Todas las bibliotecas, modelos y frameworks nombrados (Hugging Face, Amazon, Google, Salesforce, IBM, Microsoft, Meta/LLaMA, AI4Finance Foundation y todo proyecto de código abierto referenciado) son propiedad de sus respectivos dueños; esta página es contenido educativo independiente y no está respaldada por ninguno de ellos ni afiliada a ellos. Los datos fácticos (licencias, recuentos de estrellas, cifras de benchmark) se tomaron de repositorios oficiales, tarjetas de modelo y artículos citados en el momento de la investigación y pueden cambiar — verifícalos siempre en la fuente primaria.

↑ Volver arriba

Automatiza el último salto con PickMyTrade

Tu ventaja competitiva reside en las capas del modelo, la puerta de régimen y la validación. Deja que PickMyTrade se encargue de la fontanería de la ejecución — un único webhook idempotente hacia más de 60 brókeres y prop firms, con órdenes bracket adjuntas.