Files
Trading-Bot/BACKTESTING.md

10 KiB
Raw Blame History

🧪 Backtesting Engine - Guía de Uso

📋 Descripción

El motor de backtesting permite simular estrategias de trading sobre datos históricos para evaluar su performance antes de arriesgar capital real.

🚀 Uso Rápido

Demo Simple

python backtest.py

Esto ejecuta un backtest con:

  • Estrategia: Moving Average Crossover (10/30)
  • Símbolo: BTC/USDT
  • Periodo: 60 días
  • Capital inicial: $10,000

Comparar Estrategias

python backtest.py compare

Compara 4 estrategias diferentes sobre los mismos datos.

📊 Estrategias Disponibles

1. Moving Average Crossover

Cruces de medias móviles:

from src.strategies import MovingAverageCrossover

strategy = MovingAverageCrossover(
    fast_period=10,    # Periodo media rápida
    slow_period=30,    # Periodo media lenta
    ma_type='sma'      # 'sma' o 'ema'
)

Señales:

  • BUY: Media rápida cruza por encima de media lenta
  • SELL: Media rápida cruza por debajo de media lenta

2. RSI Strategy

Basada en niveles de RSI:

from src.strategies import RSIStrategy

strategy = RSIStrategy(
    rsi_period=14,              # Periodo del RSI
    oversold_threshold=30,      # Umbral de sobreventa
    overbought_threshold=70     # Umbral de sobrecompra
)

Señales:

  • BUY: RSI < 30 (sobrevendido)
  • SELL: RSI > 70 (sobrecomprado)

3. Buy and Hold

Estrategia base para comparación:

from src.strategies import BuyAndHold

strategy = BuyAndHold()

Compra al inicio y mantiene hasta el final.

🛠️ Uso Programático

Backtest Básico

from src.data.storage import StorageManager
from src.backtest import BacktestEngine
from src.strategies import MovingAverageCrossover

# Cargar datos
storage = StorageManager(...)
data = storage.load_ohlcv('BTC/USDT', '1h')

# Crear estrategia
strategy = MovingAverageCrossover(fast_period=10, slow_period=30)

# Crear motor de backtesting
engine = BacktestEngine(
    strategy=strategy,
    initial_capital=10000,
    commission=0.001,      # 0.1% por trade
    slippage=0.0005,       # 0.05% de slippage
    position_size=0.95     # Usar 95% del capital
)

# Ejecutar
results = engine.run(data)

# Ver resultados
from src.backtest.metrics import print_backtest_report
print_backtest_report(results)

Crear Tu Propia Estrategia

from src.backtest.strategy import Strategy, Signal
import pandas as pd

class MiEstrategia(Strategy):
    
    def __init__(self):
        super().__init__(name="Mi Estrategia", params={})
    
    def init_indicators(self, data: pd.DataFrame) -> pd.DataFrame:
        """
        Calcula tus indicadores aquí
        """
        # Ejemplo: añadir SMA
        data['sma_20'] = data['close'].rolling(20).mean()
        return data
    
    def generate_signal(self, idx: int) -> Signal:
        """
        Lógica de tu estrategia
        """
        current_price = self.data.iloc[idx]['close']
        sma = self.data.iloc[idx]['sma_20']
        
        # Ejemplo: comprar si precio > SMA
        if current_price > sma and self.current_position == 0:
            return Signal.BUY
        
        # Vender si precio < SMA y tenemos posición
        elif current_price < sma and self.current_position > 0:
            return Signal.SELL
        
        return Signal.HOLD

# Usar tu estrategia
strategy = MiEstrategia()
engine = BacktestEngine(strategy, initial_capital=10000)
results = engine.run(data)

📈 Métricas Disponibles

Básicas

  • Total Return: Retorno total del periodo
  • Total Trades: Número de trades ejecutados
  • Win Rate: Porcentaje de trades ganadores
  • Profit Factor: Ganancia bruta / Pérdida bruta

Avanzadas

  • Sharpe Ratio: Retorno ajustado por riesgo
  • Sortino Ratio: Como Sharpe pero solo penaliza volatilidad a la baja
  • Max Drawdown: Máxima caída desde un pico
  • Calmar Ratio: Retorno anualizado / Max Drawdown
  • Expectancy: Ganancia esperada por trade
  • Recovery Factor: Net Profit / Max Drawdown

🎯 Estructura de Resultados

results = {
    # Capital
    'initial_capital': 10000,
    'final_equity': 12500,
    'total_return': 0.25,
    'total_return_pct': 25.0,
    'total_pnl': 2500,
    
    # Trades
    'total_trades': 15,
    'winning_trades': 9,
    'losing_trades': 6,
    'win_rate': 0.6,
    'win_rate_pct': 60.0,
    
    # Performance
    'gross_profit': 3000,
    'gross_loss': 500,
    'profit_factor': 6.0,
    'avg_trade': 166.67,
    'avg_win': 333.33,
    'avg_loss': -83.33,
    
    # Riesgo
    'max_drawdown': -0.15,
    'max_drawdown_pct': -15.0,
    'sharpe_ratio': 1.8,
    
    # Para análisis
    'equity_curve': [...],
    'timestamps': [...],
    'trades': [Trade(...), Trade(...), ...]
}

💡 Mejores Prácticas

1. Periodo de Backtest

  • Mínimo: 1 año de datos
  • Recomendado: 3-5 años
  • Ideal: Múltiples ciclos de mercado

2. Comisiones y Slippage

  • Siempre incluir comisiones realistas
  • Incluir slippage (0.05% - 0.1%)
  • No optimizar en exceso (overfitting)

3. Position Sizing

  • No usar 100% del capital por trade
  • Recomendado: 50-95% del capital disponible
  • Considerar gestión de riesgo

4. Validación

  • In-sample: Periodo de entrenamiento/optimización
  • Out-of-sample: Periodo de validación (datos no vistos)
  • Walk-forward: Validación continua

5. Métricas Importantes

  • No solo mirar retorno total
  • Sharpe Ratio > 1.0 es bueno, > 2.0 es excelente
  • Max Drawdown < 20% es aceptable
  • Win Rate: >50% es bueno, pero no es lo único importante
  • Profit Factor > 1.5 es bueno, > 2.0 es excelente

⚠️ Advertencias

Limitaciones del Backtesting

  1. Look-ahead bias: No usar información futura
  2. Survivorship bias: Incluir activos que ya no existen
  3. Overfitting: Optimizar demasiado para datos históricos
  4. Market conditions: Pasado no garantiza futuro
  5. Ejecución perfecta: Backtesting asume ejecución instantánea

Realismo

El backtest asume:

  • Comisiones y slippage incluidos
  • No hay look-ahead bias
  • Liquidez infinita (órdenes siempre se ejecutan)
  • No considera impacto de mercado
  • No simula rechazo de órdenes

📊 Ejemplos de Resultados

Estrategia Exitosa

Retorno Total:     45.2%
Sharpe Ratio:      2.1
Max Drawdown:     -12.3%
Win Rate:          58%
Profit Factor:     2.4

Estrategia Problemática

Retorno Total:     15.2%
Sharpe Ratio:      0.4
Max Drawdown:     -35.8%
Win Rate:          45%
Profit Factor:     1.1

🔁 Walk-Forward Validation (Out-of-Sample)

📌 ¿Qué es Walk-Forward Validation?

El walk-forward validation es una técnica avanzada de validación que simula cómo se comportaría una estrategia en condiciones reales:

  • Los parámetros se optimizan solo en datos pasados (TRAIN)
  • La estrategia se ejecuta en datos futuros no vistos (TEST)
  • El proceso se repite de forma deslizante a lo largo del tiempo

Esto evita:

  • Look-ahead bias
  • Overfitting clásico
  • Optimismo artificial en backtests

Es el estándar en quant research profesional.


🧠 Metodología aplicada en este proyecto

Para cada ventana temporal:

  1. TRAIN

    • Periodo fijo de entrenamiento
    • Optimización por grid search
    • Selección de parámetros según métrica objetivo (Sharpe Ratio)
  2. TEST (Out-of-Sample)

    • Backtest con los mejores parámetros del TRAIN
    • Sin reoptimización
    • Métricas registradas de forma independiente
  3. Desplazamiento

    • La ventana avanza en el tiempo
    • Se repite el proceso hasta agotar los datos

⏱️ Configuración utilizada

  • Activo: BTC/USDT
  • Timeframe: 1h
  • Ventana TRAIN: 365 días
  • Ventana TEST: 90 días
  • Step: 90 días
  • Capital inicial: $10,000
  • Comisión: 0.1%
  • Slippage: 0.05%

Estrategia base:

  • Moving Average Crossover
  • Filtro de tendencia con ADX

📊 Resultados por ventana (TEST Out-of-Sample)

Window Return % Sharpe Max DD % Trades Parámetros
1 +38.00 0.75 -11.93 3 MA(15/50) + ADX 25
2 +3.62 0.10 -23.67 2 MA(15/50) + ADX 30
3 +8.54 0.22 -10.28 2 MA(15/50) + ADX 30
4 0.00 0.00 0.00 0 Sin trades
5 +9.71 0.26 -10.57 2 MA(15/50) + ADX 30
6 0.00 0.00 0.00 0 Sin trades
7 -2.25 -0.06 -12.42 2 MA(15/50) + ADX 30
8 -2.27 -0.13 -5.46 2 MA(15/30) + ADX 30

📈 Métricas agregadas (Out-of-Sample)

  • Ventanas evaluadas: 8
  • Retorno medio: +6.92%
  • Sharpe medio: 0.14
  • Max Drawdown medio: -9.29%

🧩 Interpretación de resultados

  • La estrategia no es sobreoptimizada
  • Existen ventanas sin operaciones → el sistema sabe no operar
  • Las pérdidas están controladas
  • No hay colapsos en mercados adversos
  • El rendimiento depende claramente del régimen de mercado

Este comportamiento es consistente con una estrategia:

  • Tendencial
  • Conservadora
  • Apta para mejoras vía position sizing y portfolio diversification

Decisiones tomadas tras Walk-Forward

  1. NO modificar la lógica de entrada
  2. NO optimizar más los parámetros base
  3. Mantener el filtro ADX como componente estructural
  4. Avanzar hacia mejoras de:
    • Position sizing
    • Stops dinámicos
    • Portfolio multi-asset

El walk-forward valida que la señal base es estable y explotable, aunque no espectacular por sí sola.

🔄 Próximos Pasos

Después del backtesting:

  1. Si resultados son buenos → Paper trading
  2. Validar en out-of-sample
  3. Optimizar parámetros (con cuidado)
  4. Añadir gestión de riesgo
  5. Testear en diferentes condiciones de mercado

📝 Notas

  • Siempre testea en datos out-of-sample
  • Un buen backtest no garantiza éxito futuro
  • Considera paper trading antes de dinero real
  • Mantén expectativas realistas
  • El mercado puede cambiar

Para dudas o problemas, consulta el README principal del proyecto.