trading-platform/docs/99-analisis/ET-ML-FACTORES-ATENCION-SPEC.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

14 KiB

title version date status author epic tags priority
Especificación Técnica: Sistema de Atención con Factores Dinámicos 1.0.0 2026-01-06 Draft ML-Specialist + Orquestador OQI-006
ml
attention
factors
dynamic
specification
HIGH

ET-ML-FACTORES-ATENCION: Sistema de Atención con Factores Dinámicos

1. RESUMEN

Este documento especifica la implementación de un sistema de atención basado en factores dinámicos calculados con ATR/mediana rolling, eliminando los factores hardcodeados actuales y permitiendo escalabilidad a 100+ activos.


2. PROBLEMA ACTUAL

2.1 Factores Hardcodeados

Ubicación actual: range_predictor_factor.py:598-601

# PROBLEMA: Solo 2 activos, valores estáticos
SYMBOLS = {
    'XAUUSD': {'base': 2650.0, 'volatility': 0.0012, 'factor': 2.5},
    'EURUSD': {'base': 1.0420, 'volatility': 0.0004, 'factor': 0.0003},
}

2.2 Impactos

Impacto Descripción Severidad
Escalabilidad No escala a 100+ activos CRÍTICO
Adaptabilidad No se adapta a cambios de volatilidad ALTO
Mantenimiento Requiere código nuevo por cada activo MEDIO
Precisión Factores desactualizados degradan predicciones ALTO

3. SOLUCIÓN PROPUESTA

3.1 Cálculo Dinámico del Factor

def compute_factor_median_range(
    df: pd.DataFrame,
    window: int = 200,
    min_periods: int = 100
) -> pd.Series:
    """
    Factor dinámico = mediana rolling del rango de velas con shift(1).

    El shift(1) evita data leakage - solo usa información pasada.

    Args:
        df: DataFrame con High/Low
        window: Ventana rolling (default: 200 velas)
        min_periods: Períodos mínimos para calcular

    Returns:
        Serie con factor dinámico por timestamp
    """
    range_col = df['High'] - df['Low']
    factor = range_col.rolling(window=window, min_periods=min_periods).median().shift(1)
    return factor

3.2 Mapeo de Pesos de Atención

Función smooth (softplus):

def weight_smooth(m: np.ndarray, w_max: float = 3.0, beta: float = 4.0) -> np.ndarray:
    """
    Mapeo suave de multiplicador a peso de atención.

    Formula: w = log1p(exp(beta * (m - 1))) / beta

    Interpretación:
    - m < 1 → w ≈ 0 (ruido, ignorar)
    - m = 1 → w ≈ 0 (movimiento típico)
    - m = 2 → w ≈ 1 (2x normal, atención media)
    - m = 3 → w ≈ 2 (3x normal, atención alta)
    """
    x = beta * (m - 1.0)
    w = np.where(x > 20, x / beta, np.log1p(np.exp(x)) / beta)
    return np.clip(w, 0.0, w_max)

3.3 Ejemplo para XAUUSD

Variación Real Factor Dinámico Multiplicador Peso de Atención
3.5 USD 5.0 USD 0.70 0.0 (ruido)
5.0 USD 5.0 USD 1.00 0.0 (normal)
7.5 USD 5.0 USD 1.50 ~0.4 (interés)
10.0 USD 5.0 USD 2.00 ~1.0 (atención)
15.0 USD 5.0 USD 3.00 ~2.0 (alta atención)
20.0 USD 5.0 USD 4.00 3.0 (máximo)

4. ARQUITECTURA DE IMPLEMENTACIÓN

4.1 Estructura de Archivos Propuesta

ml-engine/src/
├── config/
│   ├── symbols_config.yaml     # Configuración de símbolos (NEW)
│   └── attention_config.yaml   # Configuración de atención (NEW)
├── models/
│   ├── base/
│   │   └── attention_weighted_model.py  # Base class (NEW)
│   ├── trained/
│   │   ├── XAUUSD/
│   │   │   ├── 5m/
│   │   │   │   ├── range_predictor.joblib
│   │   │   │   ├── movement_predictor.joblib
│   │   │   │   └── config.yaml
│   │   │   └── 15m/
│   │   │       └── ...
│   │   ├── EURUSD/
│   │   │   └── ...
│   │   └── BTCUSDT/
│   │       └── ...
│   └── (existing models)
└── training/
    └── dynamic_factor_calculator.py  # (NEW)

4.2 symbols_config.yaml

# Configuración centralizada de símbolos
# Factores iniciales para warm-start (se actualizan automáticamente)

symbols:
  XAUUSD:
    category: "commodity"
    decimal_places: 2
    pip_size: 0.01
    initial_factor: 5.0  # Solo para warmup
    factor_window: 200
    min_periods: 100

  EURUSD:
    category: "forex"
    decimal_places: 5
    pip_size: 0.0001
    initial_factor: 0.0003
    factor_window: 200
    min_periods: 100

  BTCUSDT:
    category: "crypto"
    decimal_places: 2
    pip_size: 0.01
    initial_factor: 200.0
    factor_window: 200
    min_periods: 100

  # ... más símbolos

4.3 DynamicFactorCalculator Class

class DynamicFactorCalculator:
    """
    Calcula y mantiene factores dinámicos para todos los símbolos.

    Features:
    - Rolling median con shift(1) para evitar leakage
    - Cache de factores por símbolo
    - Actualización incremental (EMA)
    - Persistencia opcional en Redis/archivo
    """

    def __init__(self, config_path: str = "config/symbols_config.yaml"):
        self.config = self._load_config(config_path)
        self._factors: Dict[str, float] = {}  # Cache
        self._factor_history: Dict[str, List[float]] = {}

    def get_factor(self, symbol: str, df: pd.DataFrame = None) -> float:
        """Obtiene factor actual para un símbolo."""
        if df is not None:
            return self._compute_factor(symbol, df)
        return self._factors.get(symbol, self.config['symbols'][symbol]['initial_factor'])

    def _compute_factor(self, symbol: str, df: pd.DataFrame) -> float:
        """Calcula factor dinámico basado en mediana rolling."""
        cfg = self.config['symbols'].get(symbol, {})
        window = cfg.get('factor_window', 200)
        min_periods = cfg.get('min_periods', 100)

        range_col = df['High'] - df['Low']
        factor = range_col.rolling(window=window, min_periods=min_periods).median().iloc[-1]

        # Cache
        self._factors[symbol] = factor

        return factor

    def update_factor_incremental(self, symbol: str, new_range: float, alpha: float = 0.02):
        """Actualización incremental usando EMA."""
        current = self._factors.get(symbol)
        if current is None:
            self._factors[symbol] = new_range
        else:
            self._factors[symbol] = alpha * new_range + (1 - alpha) * current

5. INTEGRACIÓN CON MODELOS EXISTENTES

5.1 AttentionWeightedModel (Base Class)

class AttentionWeightedModel(ABC):
    """
    Clase base para modelos con pesos de atención dinámicos.

    Subclases:
    - AttentionWeightedXGBoost
    - AttentionWeightedTransformer
    """

    def __init__(self, symbol: str, timeframe: str):
        self.symbol = symbol
        self.timeframe = timeframe
        self.factor_calculator = DynamicFactorCalculator()
        self.attention_config = VolatilityAttentionConfig()

    @abstractmethod
    def train(self, X, y, df_ohlcv: pd.DataFrame):
        """Entrena modelo con pesos de atención."""
        pass

    @abstractmethod
    def predict(self, X, df_ohlcv: pd.DataFrame):
        """Predice con factor dinámico actual."""
        pass

    def compute_sample_weights(self, df: pd.DataFrame) -> np.ndarray:
        """Calcula pesos de muestra basados en volatilidad."""
        factor = self.factor_calculator.get_factor(self.symbol, df)
        multiplier = compute_move_multiplier(df, factor)
        weights = weight_smooth(multiplier, w_max=3.0, beta=4.0)

        # Normalizar a mean=1
        valid_mask = ~np.isnan(weights)
        if weights[valid_mask].mean() > 0:
            weights[valid_mask] /= weights[valid_mask].mean()

        return weights

5.2 Modificación de RangePredictor

# En range_predictor.py - train()

class RangePredictor(AttentionWeightedModel):

    def train(self, X, y_high, y_low, df_ohlcv: pd.DataFrame):
        # Calcular pesos de atención
        sample_weights = self.compute_sample_weights(df_ohlcv)

        # Entrenar modelo HIGH con pesos
        self.model_high = XGBRegressor(**self.config)
        self.model_high.fit(X, y_high, sample_weight=sample_weights)

        # Entrenar modelo LOW con pesos
        self.model_low = XGBRegressor(**self.config)
        self.model_low.fit(X, y_low, sample_weight=sample_weights)

6. SEPARACIÓN POR ACTIVO Y TEMPORALIDAD

6.1 Estructura de Modelos Entrenados

trained/
├── XAUUSD/
│   ├── 5m/
│   │   ├── config.yaml          # Hyperparámetros específicos
│   │   ├── factor_stats.json    # Estadísticas del factor
│   │   ├── range_predictor.joblib
│   │   ├── movement_predictor.joblib
│   │   └── attention_weights.npz
│   └── 15m/
│       └── ...
├── EURUSD/
│   ├── 5m/
│   └── 15m/
└── BTCUSDT/
    ├── 5m/
    └── 15m/

6.2 Config.yaml por Modelo

# trained/XAUUSD/5m/config.yaml
symbol: XAUUSD
timeframe: 5m
prediction_horizon: 15m  # 3 velas de 5m

factor:
  computed_at: "2026-01-06T10:00:00Z"
  value: 4.85
  window: 200
  method: "rolling_median_shift1"

attention:
  w_max: 3.0
  beta: 4.0
  use_smooth: true

xgboost:
  n_estimators: 300
  max_depth: 6
  learning_rate: 0.03

training:
  samples: 50000
  train_period: "2021-01-01 to 2025-12-31"
  validation_split: 0.2

metrics:
  mae_high: 2.15
  mae_low: 1.98
  r2_high: 0.72
  r2_low: 0.75

7. API PARA MODELOS

7.1 Endpoint Unificado (Recomendado)

GET /api/ml/predictions/{symbol}
    ?timeframe=15m
    &include_models=range,movement,amd,attention

Response:
{
  "symbol": "XAUUSD",
  "timeframe": "15m",
  "timestamp": "2026-01-06T10:30:00Z",
  "current_price": 2655.50,
  "dynamic_factor": 4.85,
  "attention_weight": 1.8,

  "models": {
    "range_predictor": {
      "pred_high": 2658.5,
      "pred_low": 2652.0,
      "confidence": 0.72,
      "multiplier_high": 0.62,
      "multiplier_low": 0.72
    },
    "movement_predictor": {
      "high_usd": 8.5,
      "low_usd": 3.0,
      "asymmetry_ratio": 2.83,
      "direction": "LONG"
    },
    "amd_detector": {
      "phase": "ACCUMULATION",
      "confidence": 0.68,
      "next_phase_prob": {"manipulation": 0.25, "distribution": 0.07}
    },
    "attention_model": {
      "pred_high": 2659.0,
      "pred_low": 2651.5,
      "attention_score": 1.8
    }
  },

  "metamodel": {
    "direction": "LONG",
    "confidence": 0.75,
    "entry": 2655.50,
    "tp": 2658.7,
    "sl": 2651.8,
    "rr_ratio": 2.83,
    "reasoning": ["High asymmetry", "Accumulation phase", "Attention > 1.5"]
  }
}

7.2 Endpoint por Modelo Individual

GET /api/ml/models/{model_type}/{symbol}
    ?timeframe=15m

# model_type: range | movement | amd | attention | ensemble

8. FRONTEND: 2 PÁGINAS REQUERIDAS

8.1 Página "ML Realtime" (/ml/realtime)

Propósito: Visualización en tiempo real de predicciones ML

Componentes:

  1. Cards por Activo (grid responsive)

    • Símbolo + precio actual
    • Factor dinámico actual
    • Attention weight visual (barra de color)
    • Dirección predicha (LONG/SHORT/NEUTRAL)
    • Niveles TP/SL
    • Confianza
  2. Filtros:

    • Por símbolo (multi-select)
    • Por confianza mínima
    • Por attention weight mínimo
    • Solo señales activas
  3. Auto-refresh: 30 segundos

8.2 Página "ML Historical" (/ml/historical)

Propósito: Análisis de predicciones pasadas sin refresh constante

Componentes:

  1. Date Range Picker (inicio - fin)

  2. Selector de Símbolo

  3. Selector de Modelo (o todos)

  4. Tabla de Predicciones:

    • Timestamp
    • Símbolo
    • Modelo
    • Predicción (High/Low)
    • Actual (High/Low)
    • Error (MAE)
    • Acierto (TP hit / SL hit / Neutral)
  5. Gráfico de Equity Curve (basado en predicciones)

  6. Métricas Agregadas:

    • Win Rate por modelo
    • MAE promedio
    • R² por período
    • Factor promedio usado

9. PLAN DE IMPLEMENTACIÓN

Fase 1: Infraestructura (Prioridad ALTA)

  • Crear symbols_config.yaml
  • Implementar DynamicFactorCalculator
  • Crear AttentionWeightedModel base class
  • Tests unitarios

Fase 2: Migración de Modelos

  • Refactorizar RangePredictor para usar factores dinámicos
  • Refactorizar MovementMagnitudePredictor
  • Refactorizar EnhancedRangePredictor
  • Tests de regresión

Fase 3: Separación por Activo/Timeframe

  • Crear estructura de directorios
  • Script de migración de modelos existentes
  • Pipeline de entrenamiento por activo
  • Documentación

Fase 4: API y Frontend

  • Endpoint /api/ml/predictions/{symbol}
  • Página MLRealtime
  • Página MLHistorical
  • Tests de integración

10. MÉTRICAS DE ÉXITO

Métrica Objetivo Cómo medir
Win Rate (movimientos fuertes) ≥ 80% Backtesting con attention > 1.5
R:R Ratio promedio ≥ 2:1 Promedio de trades ejecutados
Tiempo de adaptación del factor < 24h Correlación factor vs volatilidad real
Latencia de predicción < 100ms API response time
Cobertura de activos 100% de activos configurados Símbolos con modelo entrenado

11. RIESGOS Y MITIGACIONES

Riesgo Probabilidad Impacto Mitigación
Factor dinámico lag Media Alto Usar EMA para actualización incremental
Overfitting por activo Media Medio Cross-validation + walk-forward
Pérdida de modelos Baja Alto Versionado + backups
Incompatibilidad APIs Baja Medio Tests de contrato

Documento generado: 2026-01-06 Pendiente de revisión: Vuelta 2