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

9.8 KiB

id title type status priority epic project version created_date updated_date
RF-ML-003 Indicadores Tecnicos del ML Requirement Done Alta OQI-006 trading-platform 1.0.0 2025-12-05 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:

volatility_N = std(returns[-N:])

Períodos: 5, 10, 20, 50

Average True Range (ATR):

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:

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:

momentum_N = (close / close[-N]) - 1

Períodos: 5, 10, 20

Rate of Change (ROC):

roc_N = ((close - close[-N]) / close[-N]) * 100

Períodos: 5, 10, 20

Relative Strength Index (RSI):

# 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):

sma_N = mean(close[-N:])

Períodos: 5, 10, 20, 50

Exponential Moving Average (EMA):

multiplier = 2 / (N + 1)
ema_N = (close * multiplier) + (ema_prev * (1 - multiplier))

Períodos: 5, 10, 20, 50

SMA Ratios:

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:

# 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:

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:

hl_range_pct = (high - low) / close * 100

// Mide la volatilidad intravela

Distance to High/Low:

high_distance = (high - close) / high
low_distance = (close - low) / low

// Indica posición del cierre dentro de la vela

Historical Max/Min Ratios:

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
limit number Número de velas históricas No (default: 100)

Datos de Salida

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:

{
  "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

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

# 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


Creado por: Requirements-Analyst Fecha: 2025-12-05 Última actualización: 2025-12-05