trading-platform/docs/02-definicion-modulos/OQI-006-ml-signals/requerimientos/RF-ML-003-indicadores.md
rckrdmrd a7cca885f0 feat: Major platform documentation and architecture updates
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>
2026-01-07 05:33:35 -06:00

467 lines
9.8 KiB
Markdown

---
id: "RF-ML-003"
title: "Indicadores Tecnicos del ML"
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-003: Indicadores Técnicos del ML
**Versión:** 1.0.0
**Fecha:** 2025-12-05
**Épica:** OQI-006 - Señales ML y Predicciones
**Prioridad:** P1
**Story Points:** 5
---
## Descripción
El sistema debe calcular y proporcionar indicadores técnicos avanzados utilizados como features del modelo ML. Estos indicadores deben estar disponibles tanto para el entrenamiento del modelo como para visualización en la interfaz de usuario.
---
## Requisitos Funcionales
### RF-ML-003.1: Indicadores de Volatilidad
El sistema debe calcular:
**Volatilidad Estándar:**
```python
volatility_N = std(returns[-N:])
Períodos: 5, 10, 20, 50
```
**Average True Range (ATR):**
```python
true_range = max(
high - low,
abs(high - close_prev),
abs(low - close_prev)
)
atr_N = sma(true_range, N)
Períodos: 5, 10, 20, 50
```
**Bollinger Bands Position:**
```python
bb_middle = sma(close, 20)
bb_std = std(close, 20)
bb_upper = bb_middle + (2 * bb_std)
bb_lower = bb_middle - (2 * bb_std)
bb_position = (close - bb_lower) / (bb_upper - bb_lower)
// Rango: 0 (en banda inferior) a 1 (en banda superior)
```
### RF-ML-003.2: Indicadores de Momentum
El sistema debe calcular:
**Momentum Simple:**
```python
momentum_N = (close / close[-N]) - 1
Períodos: 5, 10, 20
```
**Rate of Change (ROC):**
```python
roc_N = ((close - close[-N]) / close[-N]) * 100
Períodos: 5, 10, 20
```
**Relative Strength Index (RSI):**
```python
# RSI de 14 períodos
gains = max(0, close - close_prev)
losses = max(0, close_prev - close)
avg_gain = ema(gains, 14)
avg_loss = ema(losses, 14)
rs = avg_gain / avg_loss
rsi_14 = 100 - (100 / (1 + rs))
// Rango: 0 (sobreventa extrema) a 100 (sobrecompra extrema)
// Zonas: < 30 sobreventa, > 70 sobrecompra
```
### RF-ML-003.3: Medias Móviles
El sistema debe calcular:
**Simple Moving Average (SMA):**
```python
sma_N = mean(close[-N:])
Períodos: 5, 10, 20, 50
```
**Exponential Moving Average (EMA):**
```python
multiplier = 2 / (N + 1)
ema_N = (close * multiplier) + (ema_prev * (1 - multiplier))
Períodos: 5, 10, 20, 50
```
**SMA Ratios:**
```python
sma_ratio_N = close / sma_N - 1
// Indica distancia del precio actual respecto a la SMA
// Positivo: precio sobre SMA (alcista)
// Negativo: precio bajo SMA (bajista)
Períodos: 5, 10, 20, 50
```
### RF-ML-003.4: MACD (Moving Average Convergence Divergence)
El sistema debe calcular:
```python
# MACD estándar (12, 26, 9)
ema_12 = ema(close, 12)
ema_26 = ema(close, 26)
macd_line = ema_12 - ema_26
macd_signal = ema(macd_line, 9)
macd_histogram = macd_line - macd_signal
// Interpretación:
// macd > signal: momento alcista
// macd < signal: momento bajista
// histogram > 0: aceleración alcista
// histogram < 0: aceleración bajista
```
### RF-ML-003.5: Indicadores de Volumen
El sistema debe calcular:
**Volume Ratio:**
```python
volume_sma = sma(volume, 20)
volume_ratio = volume / volume_sma
// Rango típico: 0.5 - 2.0
// > 1.5: volumen alto (confirmación de movimiento)
// < 0.7: volumen bajo (falta de interés)
```
### RF-ML-003.6: Indicadores de High/Low
El sistema debe calcular:
**High-Low Range Percentage:**
```python
hl_range_pct = (high - low) / close * 100
// Mide la volatilidad intravela
```
**Distance to High/Low:**
```python
high_distance = (high - close) / high
low_distance = (close - low) / low
// Indica posición del cierre dentro de la vela
```
**Historical Max/Min Ratios:**
```python
hist_max_N = max(high[-N:])
hist_min_N = min(low[-N:])
hist_max_ratio_N = close / hist_max_N - 1
hist_min_ratio_N = close / hist_min_N - 1
Períodos: 10, 20, 50, 100
```
---
## Datos de Entrada
| Campo | Tipo | Descripción | Requerido |
|-------|------|-------------|-----------|
| symbol | string | Par de trading | Sí |
| limit | number | Número de velas históricas | No (default: 100) |
---
## Datos de Salida
```typescript
interface TechnicalIndicators {
symbol: string;
timestamp: string;
price: number;
// Volatilidad (9 indicators)
volatility: {
vol_5: number;
vol_10: number;
vol_20: number;
vol_50: number;
atr_5: number;
atr_10: number;
atr_20: number;
atr_50: number;
bb_position: number; // 0-1
};
// Momentum (7 indicators)
momentum: {
mom_5: number;
mom_10: number;
mom_20: number;
roc_5: number;
roc_10: number;
roc_20: number;
rsi_14: number; // 0-100
};
// Medias Móviles (12 indicators)
moving_averages: {
sma_5: number;
sma_10: number;
sma_20: number;
sma_50: number;
ema_5: number;
ema_10: number;
ema_20: number;
ema_50: number;
sma_ratio_5: number;
sma_ratio_10: number;
sma_ratio_20: number;
sma_ratio_50: number;
};
// MACD (3 indicators)
macd: {
macd_line: number;
macd_signal: number;
macd_histogram: number;
};
// Volumen (1 indicator)
volume: {
volume_ratio: number;
};
// High/Low (7 indicators)
high_low: {
hl_range_pct: number;
high_distance: number;
low_distance: number;
hist_max_ratio_10: number;
hist_max_ratio_20: number;
hist_min_ratio_10: number;
hist_min_ratio_20: number;
};
}
```
**Ejemplo:**
```json
{
"symbol": "BTCUSDT",
"timestamp": "2025-12-05T18:35:00.000Z",
"price": 89450.00,
"volatility": {
"vol_5": 0.0012,
"vol_10": 0.0015,
"vol_20": 0.0018,
"vol_50": 0.0022,
"atr_5": 250.5,
"atr_10": 280.3,
"atr_20": 310.8,
"atr_50": 345.2,
"bb_position": 0.65
},
"momentum": {
"mom_5": 0.0025,
"mom_10": 0.0045,
"mom_20": 0.0082,
"roc_5": 0.25,
"roc_10": 0.45,
"roc_20": 0.82,
"rsi_14": 58.3
},
"moving_averages": {
"sma_5": 89380.5,
"sma_10": 89320.2,
"sma_20": 89250.8,
"sma_50": 89100.4,
"ema_5": 89400.1,
"ema_10": 89350.6,
"ema_20": 89280.3,
"ema_50": 89150.7,
"sma_ratio_5": 0.0008,
"sma_ratio_10": 0.0014,
"sma_ratio_20": 0.0022,
"sma_ratio_50": 0.0039
},
"macd": {
"macd_line": 45.2,
"macd_signal": 38.7,
"macd_histogram": 6.5
},
"volume": {
"volume_ratio": 1.25
},
"high_low": {
"hl_range_pct": 0.35,
"high_distance": 0.0002,
"low_distance": 0.0032,
"hist_max_ratio_10": -0.0015,
"hist_max_ratio_20": -0.0028,
"hist_min_ratio_10": 0.0042,
"hist_min_ratio_20": 0.0078
}
}
```
---
## Reglas de Negocio
1. **Datos Mínimos:** Requiere al menos 100 velas para indicadores de período 50
2. **Actualización:** Los indicadores se recalculan cada 5 minutos (nueva vela)
3. **Caché:** Resultados se cachean por 1 minuto
4. **Precisión:** Cálculos con precisión de 8 decimales
5. **NaN Handling:** Valores NaN/Inf se reemplazan con 0 o último valor válido
---
## Criterios de Aceptación
```gherkin
Escenario: Calcular indicadores para BTCUSDT
DADO que existen al menos 100 velas históricas
CUANDO hace GET /api/indicators/BTCUSDT
ENTONCES recibe 39 indicadores técnicos
Y todos los valores son números válidos (no NaN)
Y rsi_14 está entre 0 y 100
Y bb_position está entre 0 y 1
Escenario: Indicadores en tiempo real vía WebSocket
DADO que el usuario está conectado a /ws/BTCUSDT
CUANDO se cierra una nueva vela de 5 minutos
ENTONCES recibe indicadores actualizados
Y el timestamp coincide con el cierre de la vela
Escenario: Datos insuficientes
DADO que solo existen 30 velas históricas
CUANDO solicita indicadores
ENTONCES recibe error 400 Bad Request
Y el mensaje indica "Insufficient data: need 100+ candles"
```
---
## Dependencias
### Técnicas:
- **NumPy:** Cálculos vectorizados
- **Pandas:** Series de tiempo
- **TA-Lib (opcional):** Librería de indicadores técnicos
- **Binance API:** Datos OHLCV
### Funcionales:
- Usado por RF-ML-001 (como features del modelo)
- Usado por RF-ML-002 (para generar señales)
- Usado por RF-TRD-002 (visualización en charts)
---
## Notas Técnicas
### Implementación - Feature Calculator
```python
# apps/ml-services/src/models/indicators.py
import numpy as np
import pandas as pd
class TechnicalIndicators:
"""
Calcula indicadores técnicos para ML features
"""
@staticmethod
def calculate_all(ohlcv: pd.DataFrame) -> dict:
"""
Calcula todos los indicadores
Args:
ohlcv: DataFrame con columnas [timestamp, open, high, low, close, volume]
Returns:
dict con 39 indicadores
"""
close = ohlcv['close'].values
high = ohlcv['high'].values
low = ohlcv['low'].values
volume = ohlcv['volume'].values
indicators = {}
# Volatilidad (9)
indicators.update(calculate_volatility(close, high, low))
# Momentum (7)
indicators.update(calculate_momentum(close))
# Medias Móviles (12)
indicators.update(calculate_moving_averages(close))
# MACD (3)
indicators.update(calculate_macd(close))
# Volumen (1)
indicators.update(calculate_volume(volume))
# High/Low (7)
indicators.update(calculate_high_low(close, high, low))
return indicators
```
### Optimizaciones:
- Uso de NumPy vectorizado (100x más rápido que loops)
- Cálculo incremental para nuevas velas
- Caché de medias móviles intermedias
### Performance:
- Cálculo de 39 indicadores: < 10ms para 500 velas
- Memoria: ~50KB por símbolo en caché
---
## Referencias
- [TA-Lib Documentation](https://ta-lib.org/)
- [Investopedia - Technical Indicators](https://www.investopedia.com/terms/t/technicalindicator.asp)
- [NumPy Performance Tips](https://numpy.org/doc/stable/user/c-info.html)
---
**Creado por:** Requirements-Analyst
**Fecha:** 2025-12-05
**Última actualización:** 2025-12-05