--- id: "RF-ML-002" title: "Generacion de Senales de Trading" type: "Requirement" status: "Done" priority: "Alta" epic: "OQI-006" project: "trading-platform" version: "1.0.0" created_date: "2025-12-05" updated_date: "2026-01-04" --- # RF-ML-002: Generación de Señales de Trading **Versión:** 1.0.0 **Fecha:** 2025-12-05 **Épica:** OQI-006 - Señales ML y Predicciones **Prioridad:** P0 **Story Points:** 10 --- ## Descripción El sistema debe generar señales de trading (BUY/SELL/HOLD) basadas en las predicciones del modelo ML, combinando análisis de rango esperado, clasificación de TP/SL (Take Profit / Stop Loss) y gestión de riesgo. Las señales deben incluir niveles recomendados de entrada, objetivos y stops. --- ## Requisitos Funcionales ### RF-ML-002.1: Tipos de Señales El sistema debe generar tres tipos de señales: | Tipo | Condición | Acción Recomendada | |------|-----------|-------------------| | **BUY** | Predicción alcista con alta confianza | Abrir posición long | | **SELL** | Predicción bajista con alta confianza | Abrir posición short o cerrar long | | **HOLD** | Señal neutral o baja confianza | Mantener posición actual, no operar | ### RF-ML-002.2: Clasificador TP/SL El sistema debe incluir un clasificador que determine: **Take Profit (TP):** - Nivel de precio objetivo para cerrar con ganancia - Basado en `predicted_high` ajustado por confianza - Múltiples niveles: TP1 (conservador), TP2 (moderado), TP3 (agresivo) **Stop Loss (SL):** - Nivel de precio máximo de pérdida aceptable - Basado en `predicted_low` ajustado por confianza - Ratio riesgo/recompensa mínimo: 1:2 ### RF-ML-002.3: Cálculo de Señales El sistema debe aplicar la siguiente lógica: **Señal BUY:** ``` Condiciones: - predicted_high > current_price * 1.005 (mín 0.5% de subida esperada) - confidence >= 0.60 - rsi_14 < 70 (no sobrecompra) - volume_ratio > 0.8 (volumen suficiente) Niveles: - entry_price = current_price - tp1 = current_price + (predicted_high - current_price) * 0.5 - tp2 = current_price + (predicted_high - current_price) * 0.75 - tp3 = predicted_high - stop_loss = current_price - (current_price - predicted_low) * 0.5 ``` **Señal SELL:** ``` Condiciones: - predicted_low < current_price * 0.995 (mín 0.5% de bajada esperada) - confidence >= 0.60 - rsi_14 > 30 (no sobreventa) - volume_ratio > 0.8 Niveles: - entry_price = current_price - tp1 = current_price - (current_price - predicted_low) * 0.5 - tp2 = current_price - (current_price - predicted_low) * 0.75 - tp3 = predicted_low - stop_loss = current_price + (predicted_high - current_price) * 0.5 ``` **Señal HOLD:** ``` Condiciones: - No cumple criterios de BUY ni SELL - O confidence < 0.60 - O rango esperado muy estrecho (< 0.5%) ``` ### RF-ML-002.4: Gestión de Riesgo El sistema debe calcular: **Risk/Reward Ratio:** ``` rr_ratio = (tp_price - entry_price) / (entry_price - stop_loss) ``` - Mínimo aceptable: 1:2 - Óptimo: 1:3 o superior **Position Size Recomendado:** ``` position_size = account_balance * risk_per_trade / (entry_price - stop_loss) Donde: - risk_per_trade: 1% - 2% del balance (configurable) ``` ### RF-ML-002.5: Priorización de Señales El sistema debe asignar prioridad a las señales: | Prioridad | Score | Criterios | |-----------|-------|-----------| | **HIGH** | >= 8.0 | confidence > 0.70, RR > 1:3, volumen alto | | **MEDIUM** | 6.0 - 7.9 | confidence > 0.60, RR > 1:2, volumen normal | | **LOW** | 4.0 - 5.9 | confidence > 0.50, RR > 1:1.5 | **Fórmula de Score:** ``` score = (confidence * 10) * 0.4 + (rr_ratio / 3) * 10 * 0.4 + (volume_ratio) * 10 * 0.2 ``` ### RF-ML-002.6: Histórico de Señales El sistema debe: - Guardar todas las señales generadas con timestamp - Rastrear el outcome real vs predicción - Calcular accuracy histórico de señales - Permitir filtrado por símbolo, horizonte, tipo de señal --- ## Datos de Entrada | Campo | Tipo | Descripción | Requerido | |-------|------|-------------|-----------| | symbol | string | Par de trading | Sí | | horizon | enum | scalping, intraday, swing, position | No (default: scalping) | | risk_per_trade | float | % de balance a arriesgar | No (default: 0.01) | --- ## Datos de Salida ```typescript interface TradingSignal { signal_id: string; // UUID único symbol: string; timestamp: string; // ISO 8601 horizon: string; // Señal principal action: 'BUY' | 'SELL' | 'HOLD'; priority: 'HIGH' | 'MEDIUM' | 'LOW'; score: number; // 0-10 // Precios current_price: number; entry_price: number; // Niveles objetivo take_profit: { tp1: number; tp2: number; tp3: number; }; stop_loss: number; // Métricas risk_reward_ratio: number; expected_gain_pct: number; max_risk_pct: number; confidence: number; // 0-1 // Posición recomendada recommended_position_size?: number; // Indicadores técnicos rsi: number; volume_ratio: number; // Razones reasons: string[]; // Por qué se generó la señal } ``` **Ejemplo:** ```json { "signal_id": "550e8400-e29b-41d4-a716-446655440000", "symbol": "BTCUSDT", "timestamp": "2025-12-05T18:30:00.000Z", "horizon": "scalping", "action": "BUY", "priority": "HIGH", "score": 8.5, "current_price": 89400.00, "entry_price": 89400.00, "take_profit": { "tp1": 89650.00, "tp2": 89775.00, "tp3": 89900.00 }, "stop_loss": 89150.00, "risk_reward_ratio": 2.0, "expected_gain_pct": 0.56, "max_risk_pct": 0.28, "confidence": 0.72, "recommended_position_size": 0.05, "rsi": 55.3, "volume_ratio": 1.2, "reasons": [ "Strong upward prediction (0.72 confidence)", "Healthy RSI (55.3, not overbought)", "Above average volume (1.2x)", "Favorable risk/reward (1:2)" ] } ``` --- ## Reglas de Negocio 1. **Generación Continua:** Las señales se generan cada 5 minutos (cierre de vela) 2. **Expiración:** Una señal expira después de su horizonte temporal 3. **No Duplicados:** No generar señal BUY si ya existe una activa del mismo horizonte 4. **Señal Contradictoria:** Una SELL cancela una BUY anterior del mismo horizonte 5. **Límite Diario:** Máximo 50 señales HIGH por símbolo por día 6. **Validación de Precio:** El entry_price debe estar dentro del 0.1% del current_price --- ## Criterios de Aceptación ```gherkin Escenario: Generar señal BUY con alta confianza DADO que BTCUSDT tiene predicción alcista Y confidence = 0.75 Y predicted_high = current_price * 1.008 Y RSI = 55 CUANDO el sistema calcula la señal ENTONCES action = "BUY" Y priority = "HIGH" Y se generan 3 niveles de TP Y risk_reward_ratio >= 2.0 Escenario: Generar señal HOLD por baja confianza DADO que ETHUSDT tiene predicción neutral Y confidence = 0.45 CUANDO el sistema calcula la señal ENTONCES action = "HOLD" Y priority = "LOW" Y reasons incluye "Low confidence" Escenario: Señal SELL en mercado bajista DADO que BTCUSDT tiene predicción bajista Y confidence = 0.68 Y predicted_low = current_price * 0.992 CUANDO el sistema calcula la señal ENTONCES action = "SELL" Y priority = "MEDIUM" o "HIGH" Y stop_loss > entry_price Escenario: Obtener señales vía API DADO que el usuario está autenticado CUANDO hace GET /api/signals/BTCUSDT?horizon=scalping ENTONCES recibe la señal más reciente Y la señal tiene menos de 5 minutos Y incluye todos los niveles de TP/SL ``` --- ## Dependencias ### Técnicas: - **RF-ML-001:** Predicciones de rangos de precio - **RF-ML-003:** Indicadores técnicos (RSI, volumen) - **PostgreSQL:** Almacenamiento de histórico de señales - **Redis:** Caché de señales activas ### Funcionales: - Sistema de notificaciones para alertas (RF-ML-005) - Integración con charts para visualización (RF-TRD-001) --- ## Notas Técnicas ### Arquitectura del Generador de Señales ```python # apps/ml-services/src/models/signal_generator.py class SignalGenerator: """ Genera señales de trading basadas en predicciones ML """ def generate_signal( self, symbol: str, horizon: str, risk_per_trade: float = 0.01 ) -> TradingSignal: # 1. Obtener predicción del ML prediction = predictor.predict(symbol, horizon) # 2. Obtener indicadores técnicos actuales indicators = get_current_indicators(symbol) # 3. Determinar acción (BUY/SELL/HOLD) action = classify_action(prediction, indicators) # 4. Calcular niveles de TP/SL levels = calculate_levels(action, prediction) # 5. Calcular métricas de riesgo metrics = calculate_risk_metrics(levels, risk_per_trade) # 6. Asignar prioridad y score priority, score = calculate_priority(prediction, metrics, indicators) # 7. Construir razones reasons = build_reasons(action, prediction, indicators, metrics) return TradingSignal(...) ``` ### Base de Datos - Tabla `ml_signals` ```sql CREATE TABLE ml_signals ( signal_id UUID PRIMARY KEY, symbol VARCHAR(20) NOT NULL, horizon VARCHAR(20) NOT NULL, action VARCHAR(10) NOT NULL, priority VARCHAR(10) NOT NULL, score DECIMAL(4,2), current_price DECIMAL(20,8), entry_price DECIMAL(20,8), tp1 DECIMAL(20,8), tp2 DECIMAL(20,8), tp3 DECIMAL(20,8), stop_loss DECIMAL(20,8), confidence DECIMAL(4,3), risk_reward_ratio DECIMAL(5,2), created_at TIMESTAMP DEFAULT NOW(), expires_at TIMESTAMP, -- Tracking actual_outcome VARCHAR(20), -- hit_tp1, hit_tp2, hit_sl, expired closed_at TIMESTAMP, actual_gain_pct DECIMAL(6,3), INDEX idx_symbol_horizon (symbol, horizon), INDEX idx_created_at (created_at), INDEX idx_priority (priority) ); ``` ### Performance: - Generación de señal: < 100ms - Consulta de señales activas: < 50ms (con índices) - Caché en Redis por 5 minutos --- ## Referencias - [Risk Management in Trading](https://www.investopedia.com/articles/trading/09/risk-management.asp) - [Take Profit and Stop Loss Strategies](https://www.babypips.com/learn/forex/take-profit-stop-loss) - [Position Sizing Calculator](https://www.myfxbook.com/forex-calculators/position-size-calculator) --- **Creado por:** Requirements-Analyst **Fecha:** 2025-12-05 **Última actualización:** 2025-12-05