Changes include: - Updated architecture documentation - Enhanced module definitions (OQI-001 to OQI-008) - ML integration documentation updates - Trading strategies documentation - Orchestration and inventory updates - Docker configuration updates 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
397 lines
10 KiB
Markdown
397 lines
10 KiB
Markdown
---
|
|
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
|