Trading Algorítmico en Python: Análisis Cuantitativo de Acciones con Pandas
Lo Que Dominarás en Este Tutorial
- Obtener datos históricos limpios de acciones y ETFs mediante APIs modernas de Python
- Calcular indicadores técnicos vectorizados: Medias Móviles Exponenciales (EMA), MACD y RSI
- Generar señales sistemáticas de compra y venta sin sesgo de anticipación (lookahead bias)
- Calcular métricas cuantitativas clave: Máximo Drawdown, Ratio de Sharpe y CAGR
import pandas as pd
import numpy as np
def calculate_momentum_strategy(df: pd.DataFrame, fast: int = 20, slow: int = 50) -> pd.DataFrame:
"""
Calcula cruces de EMA y evalúa la curva de capital de la estrategia.
"""
df = df.copy()
df['EMA_Fast'] = df['Close'].ewm(span=fast, adjust=False).mean()
df['EMA_Slow'] = df['Close'].ewm(span=slow, adjust=False).mean()
# Señal de posición (1 para Comprado, 0 para Liquidez)
df['Signal'] = np.where(df['EMA_Fast'] > df['EMA_Slow'], 1, 0)
df['Position'] = df['Signal'].shift(1) # Desplazar para evitar anticipación
# Retornos logarítmicos diarios
df['Market_Return'] = np.log(df['Close'] / df['Close'].shift(1))
df['Strategy_Return'] = df['Position'] * df['Market_Return']
df['Cumulative_Market'] = df['Market_Return'].cumsum().apply(np.exp)
df['Cumulative_Strategy'] = df['Strategy_Return'].cumsum().apply(np.exp)
return df
Preguntas Frecuentes
Profundizando: el backtesting de momentum en la práctica
La estrategia de este tutorial —un cruce de medias EMA 20/50 con las posiciones desplazadas una vela— es deliberadamente sencilla, y ahí está su valor: aísla la mecánica que importa en cualquier backtest. En la práctica, ese mismo flujo se extiende a limpiar y alinear los datos históricos antes de calcular una sola señal, a validar los parámetros en periodos sobre los que la estrategia no fue ajustada y a modelar las fricciones que el código omite, como comisiones, diferenciales y deslizamiento. Las métricas de riesgo presentadas aquí —drawdown máximo, ratio de Sharpe y CAGR— son el criterio para juzgar si una curva es robusta o solo tuvo suerte. Recuerda que cada cifra que produce un backtest es rendimiento histórico simulado: describe lo que habría ocurrido en el pasado, no lo que pasará en vivo, y nunca garantiza resultados futuros.
Errores comunes
- Sesgo de anticipación. Calcular una señal con el cierre de la misma vela y operar sobre ella en esa misma vela filtra información del futuro; el desplazamiento de una vela del tutorial existe precisamente para evitarlo.
- Ignorar los costos de transacción. Un sistema de cruces opera con frecuencia, y las comisiones más el deslizamiento pueden convertir en silencio una curva de capital aparentemente rentable en una perdedora.
- Sobreajustar los parámetros. Ajustar los periodos de las EMA hasta que un periodo histórico se ve perfecto suele fracasar con datos nuevos; prueba la estrategia en periodos que no usaste para optimizar.
- Sesgo de supervivencia y de datos. Hacer backtesting solo con acciones que existen hoy, o con precios sin ajustar, infla los resultados porque los fracasos retirados del mercado y los splits se tratan mal.
Preguntas frecuentes
¿Por qué el código desplaza la señal una vela?
Para que la posición de cada día se decida solo con datos que ya se conocían por completo el día anterior. Sin ese desplazamiento, el backtest estaría operando con información del futuro.
Si un backtest se ve rentable, ¿la estrategia ganará dinero en vivo?
No necesariamente. Los backtests son rendimiento histórico simulado, sin costos reales de ejecución, sin deslizamiento y sin cambios de régimen de mercado, y nunca garantizan resultados futuros.
¿Qué métrica de riesgo debería mirar primero?
El drawdown máximo. El ratio de Sharpe y el CAGR describen la calidad del rendimiento, pero el drawdown te dice la peor caída de pico a valle que habrías tenido que soportar para obtenerlos.