Este proyecto implementa un sistema de clasificación binaria para predecir si el precio de cierre de una acción será mayor mañana comparado con hoy. Utilizando técnicas de machine learning vistas en clase, el sistema analiza indicadores técnicos y patrones históricos para generar predicciones del tipo "¿mañana sube?" (1=sí, 0=no).
La predicción de movimientos bursátiles es uno de los desafíos más complejos en finanzas cuantitativas. Decidimos abordar este problema por las siguientes razones:
- Relevancia Práctica: Las decisiones de inversión requieren predicciones sobre direcciones de precios
- Complejidad Apropiada: Permite aplicar múltiples algoritmos de clasificación vistos en clase
- Datos Abundantes: Los mercados financieros generan datos continuos ideales para ML
- Evaluación Clara: Métricas binarias fáciles de interpretar y evaluar
- Horizonte de Predicción: 1 día (t+1)
- Tipo de Predicción: Binaria (sube/no sube)
- Activos: Acciones individuales (AAPL, MSFT, NVDA)
- Enfoque: Completamente offline sin dependencias externas
Decisión: Crear datos OHLCV sintéticos en lugar de usar APIs financieras reales.
Justificación:
- ✅ Reproducibilidad: Resultados consistentes en cualquier ejecución
- ✅ Independencia: No requiere conexión a internet o claves API
- ✅ Control: Podemos ajustar complejidad y patrones específicos
- ✅ Realismo: Implementamos random walks con drift y momentum como mercados reales
Implementación:
# Random walk con características realistas
def generate_ohlcv(ticker: str, n_days: int, seed: int = RANDOM_STATE):
# Drift específico por ticker
mu = DRIFT.get(ticker, 0.0) # Tendencia de largo plazo
# Volatilidad específica
s = SIGMA.get(ticker, 0.012) # Volatilidad diaria
# Momentum para simular autocorrelación
mom = 0.15 * rets[t-1] # Persistencia de tendenciasDecisión: Usar indicadores técnicos clásicos en lugar de features complejas.
Justificación:
- Interpretabilidad: Los traders entienden RSI, MACD, medias móviles
- Robustez: Indicadores probados durante décadas en mercados reales
- Diversidad: Combinamos momentum, tendencia, volatilidad y volumen
- No-overfitting: Features conocidas reducen riesgo de sobreajuste
Features Implementadas:
| Categoría | Indicadores | Justificación |
|---|---|---|
| Momentum | ret_1, ret_5, ret_10 | Capturan tendencias recientes |
| Tendencia | sma_5, sma_10, sma_20 | Identifican dirección del mercado |
| Volatilidad | std_5, std_10, std_20 | Miden incertidumbre/riesgo |
| Técnicos | RSI, MACD, signal, histogram | Señales de sobrecompra/sobreventa |
| Volumen | vol_chg, vol_znorm_20 | Confirman movimientos de precio |
| Temporal | dow (día de semana) | Efectos estacionales conocidos |
Decisión: Comparar Regresión Logística, KNN y Gaussian Naive Bayes.
Justificación por Algoritmo:
- ✅ Interpretable: Coeficientes muestran importancia de features
- ✅ Rápida: Entrenamiento y predicción eficientes
- ✅ Probabilidades: Proporciona confianza en predicciones
- ✅ Baseline: Estándar de la industria para clasificación binaria
- ✅ No-paramétrico: No asume distribuciones específicas
- ✅ Adaptativo: Captura patrones locales complejos
- ✅ Robusto: Funciona bien con datos no lineales
⚠️ Limitación: Sensible a dimensionalidad y ruido
- ✅ Simplicidad: Asume independencia entre features
- ✅ Eficiencia: Muy rápido con datos pequeños
- ✅ Probabilístico: Maneja incertidumbre naturalmente
⚠️ Limitación: Asunción fuerte de independencia
Decisión: Usar TimeSeriesSplit en lugar de validación cruzada aleatoria.
Justificación Crítica:
# ❌ INCORRECTO para series temporales
from sklearn.model_selection import KFold
cv = KFold(n_splits=5, shuffle=True) # Mezcla datos temporales!
# ✅ CORRECTO para series temporales
from sklearn.model_selection import TimeSeriesSplit
cv = TimeSeriesSplit(n_splits=3) # Respeta orden temporalPor qué es Crucial:
- Previene Data Leakage: No usar información futura para predecir el pasado
- Realismo: Simula condiciones reales de trading
- Validez: Las métricas reflejan performance real esperada
Decisión: Usar scikit-learn Pipelines con ColumnTransformer.
# Pipeline completo
pipe = Pipeline([
("preprocessor", ColumnTransformer([
("num", StandardScaler(), numerical_features),
("cat", OneHotEncoder(), categorical_features)
])),
("classifier", LogisticRegression())
])Ventajas:
- ✅ Reproducibilidad: Toda la transformación encapsulada
- ✅ Prevención de Leakage: Scaler se ajusta solo en train
- ✅ Deployment: Pipeline completo guardado en .joblib
- ✅ Mantenibilidad: Código limpio y modular
Figura 1: Curva ROC - Regresión Logística (AUC=0.63)
Figura 2: Curva ROC - K-Nearest Neighbors (AUC=0.57)
Figura 3: Curva ROC - Gaussian Naive Bayes (AUC=0.60)
| Modelo | Accuracy | Precision | Recall | F1 | ROC-AUC |
|---|---|---|---|---|---|
| Regresión Logística | 0.6250 | 0.6154 | 0.7273 | 0.6667 | 0.6307 |
| KNN | 0.5625 | 0.5714 | 0.7273 | 0.6400 | 0.5739 |
| Gaussian NB | 0.5938 | 0.5926 | 0.7273 | 0.6531 | 0.6023 |
Regresión Logística emerge como el mejor modelo con:
- ROC-AUC: 0.6307 (mejor capacidad discriminativa)
- Recall: 0.7273 (detecta 72.7% de movimientos alcistas)
- Balance: Mejor compromiso precision-recall
Interpretación Financiera:
- Performance moderada refleja la naturaleza ruidosa de predicciones diarias
- ROC-AUC > 0.6 indica capacidad predictiva superior al azar
- Recall alto es valioso para no perder oportunidades de ganancia
ProyectoFinal/
├── proyecto_final_bolsa.py # Script principal
├── dataset_train.csv # Datos de entrenamiento
├── dataset_test.csv # Datos de prueba
├── pipeline_*.joblib # Modelos entrenados
├── files/
│ ├── roc_*.png # Curvas ROC
│ ├── pipeline_*.joblib # Modelos entrenados
│ └── dataset_*.csv # Datos procesados
├── metrics.csv # Métricas comparativas
├── reporte_resumen.md # Reporte automático
└── README.md # Este documento
# Ejecución básica (3 tickers, 70 días c/u)
python proyecto_final_bolsa.py
# Configuración personalizada
python proyecto_final_bolsa.py --tickers AAPL,MSFT,GOOGL --days 100
# Predicción específica
python proyecto_final_bolsa.py --predict AAPL- Datasets:
dataset_train.csv,dataset_test.csv - Modelos:
pipeline_LogisticRegression.joblib, etc. - Visualizaciones: Curvas ROC disponibles en
files/roc_*.png - Métricas:
metrics.csv - Reporte:
reporte_resumen.md
- Horizonte Corto: Predicciones de 1 día son inherentemente ruidosas
- Datos Sintéticos: No capturan todos los factores de mercados reales
- Features Limitadas: No incluye noticias, sentiment, macro-económicos
- Tamaño de Muestra: ~150 observaciones es pequeño para ML
- Riesgo: Los mercados reales tienen factores no modelados
- Regulación: Trading algorítmico requiere cumplimiento normativo
- Costos: Spreads, comisiones y slippage afectan rentabilidad real
- Liquidez: Modelos pueden fallar en condiciones de mercado extremas
- Viabilidad: Es posible crear sistemas de predicción con herramientas básicas
- Performance: Resultados moderados pero superiores al azar
- Metodología: Validación temporal es crucial para datos financieros
- Interpretabilidad: Regresión Logística ofrece el mejor balance
- Datos Reales: Integrar APIs como Alpha Vantage o Yahoo Finance
- Features Avanzadas: Sentiment analysis, indicadores macro
- Modelos Complejos: Random Forest, XGBoost (si se ven en clase)
- Ensemble: Combinar predicciones de múltiples modelos
- Backtesting: Simular trading real con costos de transacción
- Importancia de Validación Temporal: Cambió nuestra comprensión de ML en finanzas
- Balance Complejidad-Interpretabilidad: Modelos simples pueden ser efectivos
- Ingeniería de Features: Domain knowledge es crucial para features relevantes
- Evaluación Realista: Métricas deben reflejar objetivos de negocio
- Scikit-learn Documentation: https://scikit-learn.org/
- "Advances in Financial Machine Learning" - Marcos López de Prado
- Technical Analysis Literature (RSI, MACD, Moving Averages)
- Time Series Cross-Validation Best Practices
Equipo de Desarrollo: [Nombres del equipo] Curso: TC3006C - Inteligencia Artificial Avanzada para la Ciencia de Datos I Fecha: Septiembre 2024
Nota: Este proyecto demuestra la aplicación práctica de algoritmos de machine learning en un dominio complejo, respetando las mejores prácticas de validación temporal y evaluación robusta.