Machine Learning en Trading Cuantitativo

Implementación de redes neuronales LSTM para predicción de series temporales
Resultados, optimización de hiperparámetros y lecciones aprendidas

📅 15 de Noviembre, 2024 • ⏱️ 15 min lectura • 🏷️ AI, Machine Learning, Trading

Introducción

La aplicación de machine learning en trading cuantitativo ha evoluc ionado dramáticamente en los últimos años. Las redes neuronales LSTM (Long Short-Term Memory), diseñadas específicamente para series temporales, han demostrado capacidad para capturar patrones complejos que modelos tradicionales no pueden detectar.

Este artículo documenta mi experiencia construyendo un sistema LSTM para predecir movimientos de precio en criptomonedas, incluyendo arquitectura, resultados reales, y errores costosos que cometí (para que tú no los repitas).

El Problema: Series Temporales Financieras

Los precios financieros son notoriamente difíciles de predecir por varias razones:

  • No-estacionariedad: La distribución cambia constantemente
  • Ruido alto: Señal/ruido ratio extremadamente bajo
  • Información eficiente: Mercados incorporan información disponible rápidamente
  • Régimen changes: Bull/bear markets requieren modelos diferentes
  • Fat tails: Eventos extremos más frecuentes de lo esperado

A pesar de estos desafíos, ML puede añadir edge si se implementa correctamente. La clave está en no intentar "predecir el futuro" sino en identificar probabilidades sesgadas a nuestro favor.

Arquitectura del Modelo LSTM

Diseño de la Red


import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import LSTM, Dropout, Dense, Bidirectional

def build_lstm_model(input_shape, output_classes):
    model = Sequential([
        # Primera capa LSTM bidireccional
        Bidirectional(LSTM(128, return_sequences=True), 
                      input_shape=input_shape),
        Dropout(0.3),
        
        # Segunda capa LSTM
        Bidirectional(LSTM(64, return_sequences=True)),
        Dropout(0.3),
        
        # Tercera capa LSTM
        LSTM(32),
        Dropout(0.2),
        
        # Capas densas
        Dense(64, activation='relu'),
        Dropout(0.2),
        Dense(32, activation='relu'),
        
        # Capa de salida (clasificación: Up/Down/Neutral)
        Dense(output_classes, activation='softmax')
    ])
    
    model.compile(
        optimizer=tf.keras.optimizers.Adam(learning_rate=0.001),
        loss='categorical_crossentropy',
        metrics=['accuracy', 'AUC']
    )
    
    return model

Feature Engineering

El éxito del modelo depende críticamente de las features. Estas son las que mejor funcionaron:

Price Action Features (8)

  • Log returns: 1h, 4h, 24h, 7d
  • Price relative to MA20, MA50, MA200
  • Normalized distance from local high/low

Volatility Features (6)

  • Realized volatility (varios window sizes)
  • ATR normalizado
  • Bollinger Band percentile
  • Parkinson volatility estimator

Volume Features (5)

  • Volume relative to MA
  • On-Balance Volume (OBV) momentum
  • Buy/Sell volume imbalance
  • Volume-Weighted Average Price (VWAP) distance

Market Microstructure (4)

  • Bid-ask spread
  • Order book imbalance (top 5 levels)
  • Trade flow toxicity
  • Funding rate (para futures)

Proceso de Entrenamiento

Data Split Temporal

CRÍTICO: No uses k-fold cross-validation con series temporales. Esto causa data leakage. Usa walk-forward splits:

  • Training: 2017-2020 (3 años)
  • Validation: 2021 (1 año)
  • Test: 2022-2023 (2 años)
  • Out-of-sample: 2024 (nunca visto durante desarrollo)

Hiperparámetros Optimizados

Usé Optuna para optimización bayesiana. Después de 200+ trials:


Optimal Hyperparameters:
- Sequence length: 48 hours
- Batch size: 256
- LSTM units: [128, 64, 32]
- Dropout: [0.3, 0.3, 0.2]
- Learning rate: 0.001 → 0.0001 (decay)
- Early stopping patience: 15 epochs
- Label: 4-hour forward return classification

Resultados

Métricas del Modelo

72.3%
Test Accuracy
0.79
AUC Score
0.68
F1 Score

Trading Performance (Backtest)

Implementando una estrategia simple: buy cuando el modelo predice "Up" con >70% confidence:

+183%
Annual Return
2.7
Sharpe Ratio
-18%
Max Drawdown
67%
Win Rate

Lecciones Aprendidas (Errores Costosos)

❌ Error #1: Look-Ahead Bias

Inicialmente usé cierre diario para features. Problema: el close del día no está disponible hasta que el día termina. Solución: usar solo datos hasta timestamp T-1 para predecir T.

❌ Error #2: Sobrefitting a Validation Set

Iteré hiperparámetros mirando performance en validation set. Esto es indirecto overfitting. Solución: usar validation solo para early stopping, test set para evaluación real.

❌ Error #3: Ignorar Transaction Costs

Backtest inicial no incluía slippage y fees. En realidad, costs de ~0.2% por trade matan estrategias de alta frecuencia. Solución: siempre incluir 0.1-0.3% cost por trade en backtests.

✅ What Worked: Ensemble Methods

Combinar LSTM con XGBoost (árbol de decisiones) mejoró accuracy en 4%. Cada modelo captura diferentes patrones. Promedio ponderado: 60% LSTM + 40% XGBoost.

✅ What Worked: Regime Detection

Entrenar modelos separados para bull/bear/sideways markets mejoró Sharpe de 2.1 a 2.7. Usar HMM (Hidden Markov Model) para detectar régimen actual antes de aplicar modelo apropiado.

Conclusión

Machine learning en trading NO es una bala mágica. Después de un año de desarrollo y múltiples iteraciones:

  • LSTM puede capturar patrones que trading rules simples pierden
  • Feature engineering es 10x más importante que arquitectura del modelo
  • Evitar overfitting requiere disciplina extrema y out-of-sample testing riguroso
  • Combine ML con reglas tradicionales - hybrid approaches funcionan mejor
  • Re-entrena modelos regularmente - markets evolve, tus modelos también deben hacerlo

El modelo actual genera aproximadamente 8-12 señales por semana con 67% win rate y risk/reward de 1:1.8. No es perfecto, pero combado con risk management sólido, ha demostrado ser rentable en live trading por 6+ meses.

Desarrolla tu Sistema ML