trading-platform/docs/90-transversal/estrategias/ESTRATEGIA-PREDICCION-RANGOS.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

26 KiB
Raw Blame History

id title type project version updated_date
ESTRATEGIA-PREDICCION-RANGOS Estrategia de Predicción de Rangos para Entradas Óptimas Documentation trading-platform 1.0.0 2026-01-04

Estrategia de Predicción de Rangos para Entradas Óptimas

Versión: 1.0 Fecha: 2025-12-05 Estado: En Análisis Objetivo: Encontrar entradas con R:R 2:1 y 3:1 con alta efectividad


1. Visión General

Objetivo Principal

Predecir máximos y mínimos en horizontes de:

  • 15 minutos (3 velas de 5min)
  • 60 minutos (12 velas de 5min / 4 velas de 15min)

Para generar entradas con:

  • R:R 3:1 → Efectividad objetivo: ≥80%
  • R:R 2:1 → Efectividad objetivo: ≥90%

Por qué este enfoque funciona

Si predecimos correctamente:
- Máximo probable en próximos 60min: $105
- Mínimo probable en próximos 60min: $98
- Precio actual: $100

Entonces:
- Para LONG: Entry=$100, SL=$98 (riesgo $2), TP=$106 (reward $6) → R:R 3:1
- Para SHORT: Entry=$100, SL=$102 (riesgo $2), TP=$94 (reward $6) → R:R 3:1

Con predicción precisa de rangos, las entradas se vuelven matemáticamente favorables.

2. Arquitectura de Modelos ML

2.1 Modelo Principal: RangePredictor

┌─────────────────────────────────────────────────────────────┐
│                    RANGE PREDICTOR                          │
├─────────────────────────────────────────────────────────────┤
│  Input: Features técnicas + contextuales                    │
│  Output:                                                    │
│    - delta_high_15m: % máximo esperado en 15min            │
│    - delta_low_15m: % mínimo esperado en 15min             │
│    - delta_high_60m: % máximo esperado en 60min            │
│    - delta_low_60m: % mínimo esperado en 60min             │
│    - confidence: nivel de confianza (0-1)                  │
└─────────────────────────────────────────────────────────────┘

2.2 Modelos Auxiliares (Ensemble)

┌─────────────────────┐     ┌─────────────────────┐
│   TrendClassifier   │     │  VolatilityPredictor │
│   (Dirección)       │     │  (Rango esperado)    │
└─────────┬───────────┘     └──────────┬──────────┘
          │                            │
          ▼                            ▼
┌─────────────────────────────────────────────────┐
│              ENSEMBLE COMBINER                   │
│  Pondera predicciones según contexto de mercado │
└─────────────────────────────────────────────────┘
          │
          ▼
┌─────────────────────────────────────────────────┐
│            ENTRY SIGNAL GENERATOR               │
│  - Calcula R:R basado en predicciones           │
│  - Filtra señales por umbral de confianza       │
│  - Genera TP/SL óptimos                         │
└─────────────────────────────────────────────────┘

3. Features para Predicción de Rangos

3.1 Features de Volatilidad (Críticas)

Feature Descripción Importancia
atr_5 ATR 5 períodos (volatilidad reciente)
atr_14 ATR 14 períodos (volatilidad media)
atr_ratio ATR_5 / ATR_14 (expansión/contracción)
bb_width Ancho de Bollinger Bands
bb_squeeze ¿Está en squeeze? (bool)
range_5 (High-Low)/Close últimas 5 velas
range_20 (High-Low)/Close últimas 20 velas

3.2 Features de Estructura de Mercado

Feature Descripción Importancia
dist_to_support Distancia % al soporte más cercano
dist_to_resistance Distancia % a la resistencia más cercana
in_range ¿Precio dentro de rango definido?
range_position Posición dentro del rango (0-1)
swing_high_dist Distancia al último swing high
swing_low_dist Distancia al último swing low

3.3 Features de Tendencia

Feature Descripción Importancia
trend_adx Fuerza de tendencia (ADX)
trend_direction +DI vs -DI
ema_slope_20 Pendiente de EMA 20
price_vs_ema_20 Precio / EMA 20
price_vs_ema_50 Precio / EMA 50
higher_tf_trend Tendencia en timeframe superior

3.4 Features de Momentum

Feature Descripción Importancia
rsi_14 RSI 14 períodos
rsi_divergence Divergencia RSI detectada
macd_histogram Histograma MACD
macd_divergence Divergencia MACD
momentum_10 Rate of Change 10 períodos
stoch_k Stochastic %K

3.5 Features de Volumen

Feature Descripción Importancia
volume_ratio Volumen actual / Volumen promedio 20
volume_trend Tendencia del volumen
obv_slope Pendiente de OBV
vwap_dist Distancia al VWAP

3.6 Features AMD (Wyckoff)

Feature Descripción Importancia
amd_phase Fase actual (A/M/D)
accumulation_score Probabilidad de acumulación
distribution_score Probabilidad de distribución
spring_detected ¿Spring detectado?
upthrust_detected ¿Upthrust detectado?

4. Estrategias Complementarias a AMD

4.1 Estrategia: Volatility Contraction Pattern (VCP)

Concepto: Entrar cuando la volatilidad se contrae antes de expansión.

class VCPStrategy:
    """
    Volatility Contraction Pattern - Mark Minervini

    Detecta contracciones de volatilidad que preceden movimientos explosivos.
    Ideal para encontrar máximos/mínimos antes de breakouts.
    """

    def detect_vcp(self, df: pd.DataFrame) -> pd.Series:
        # Detectar series de contracciones
        # Cada contracción debe ser menor que la anterior
        contractions = []

        for i in range(len(df) - 20):
            ranges = []
            for j in range(4):  # 4 contracciones típicas
                window = df.iloc[i + j*5 : i + (j+1)*5]
                range_pct = (window['high'].max() - window['low'].min()) / window['close'].mean()
                ranges.append(range_pct)

            # VCP válido si cada contracción es menor
            if all(ranges[i] > ranges[i+1] for i in range(len(ranges)-1)):
                contractions.append(i + 20)

        return contractions

    def predict_breakout_range(self, df: pd.DataFrame, vcp_idx: int) -> dict:
        """Predice el rango del breakout basado en contracciones previas."""
        first_contraction_range = ...  # Rango de primera contracción

        return {
            'expected_move': first_contraction_range * 1.5,  # Típicamente 1.5x
            'direction': self.determine_direction(df, vcp_idx)
        }

Utilidad para predicción de rangos:

  • El rango de la primera contracción predice el movimiento esperado
  • Alta probabilidad de alcanzar el target

4.2 Estrategia: Order Block Detection

Concepto: Zonas institucionales donde el precio probablemente reaccione.

class OrderBlockStrategy:
    """
    Order Blocks - Smart Money Concepts

    Identifica zonas donde instituciones dejaron órdenes.
    Estas zonas actúan como imanes para el precio.
    """

    def find_order_blocks(self, df: pd.DataFrame) -> List[OrderBlock]:
        order_blocks = []

        for i in range(3, len(df)):
            # Bullish Order Block
            # Vela bajista seguida de movimiento impulsivo alcista
            if (df['close'].iloc[i-2] < df['open'].iloc[i-2] and  # Vela bajista
                df['close'].iloc[i] > df['high'].iloc[i-1] and    # Impulso alcista
                df['volume'].iloc[i] > df['volume'].iloc[i-1] * 1.5):  # Alto volumen

                order_blocks.append(OrderBlock(
                    type='bullish',
                    top=df['open'].iloc[i-2],
                    bottom=df['close'].iloc[i-2],
                    strength=self.calculate_strength(df, i)
                ))

            # Bearish Order Block (inverso)
            ...

        return order_blocks

    def predict_reaction_zone(self, current_price: float,
                               order_blocks: List[OrderBlock]) -> dict:
        """Predice dónde el precio probablemente reaccione."""
        nearest_bullish = self.find_nearest(order_blocks, 'bullish', current_price)
        nearest_bearish = self.find_nearest(order_blocks, 'bearish', current_price)

        return {
            'probable_low': nearest_bullish.bottom if nearest_bullish else None,
            'probable_high': nearest_bearish.top if nearest_bearish else None
        }

Utilidad para predicción de rangos:

  • Predice zonas de soporte/resistencia institucional
  • Alta probabilidad de reacción en estos niveles

4.3 Estrategia: Fair Value Gap (FVG)

Concepto: Gaps de valor justo que el precio tiende a llenar.

class FairValueGapStrategy:
    """
    Fair Value Gaps - ICT Concepts

    Detecta gaps de eficiencia que el precio tiende a revisitar.
    Excelente para predecir mínimos/máximos de retroceso.
    """

    def find_fvg(self, df: pd.DataFrame) -> List[FVG]:
        fvgs = []

        for i in range(2, len(df)):
            # Bullish FVG: Gap entre high de vela 1 y low de vela 3
            if df['low'].iloc[i] > df['high'].iloc[i-2]:
                fvgs.append(FVG(
                    type='bullish',
                    top=df['low'].iloc[i],
                    bottom=df['high'].iloc[i-2],
                    filled=False
                ))

            # Bearish FVG
            if df['high'].iloc[i] < df['low'].iloc[i-2]:
                fvgs.append(FVG(
                    type='bearish',
                    top=df['low'].iloc[i-2],
                    bottom=df['high'].iloc[i],
                    filled=False
                ))

        return fvgs

    def predict_fill_probability(self, fvg: FVG,
                                  time_since_creation: int) -> float:
        """
        FVGs se llenan ~70% del tiempo en las primeras 20 velas.
        """
        base_probability = 0.70
        time_decay = max(0, 1 - time_since_creation / 50)
        return base_probability * time_decay

Utilidad para predicción de rangos:

  • FVGs sin llenar son targets probables
  • Ayuda a predecir retrocesos antes de continuación

4.4 Estrategia: Liquidity Sweep

Concepto: El precio busca liquidez antes de moverse en dirección opuesta.

class LiquiditySweepStrategy:
    """
    Liquidity Sweeps - Smart Money Concepts

    Detecta barridas de liquidez que preceden reversiones.
    Crítico para predecir máximos/mínimos locales.
    """

    def detect_liquidity_zones(self, df: pd.DataFrame) -> dict:
        """Identifica zonas de liquidez (stops acumulados)."""

        # Liquidez por encima de equal highs
        equal_highs = self.find_equal_highs(df)

        # Liquidez por debajo de equal lows
        equal_lows = self.find_equal_lows(df)

        # Liquidez en swing points obvios
        swing_highs = self.find_swing_highs(df)
        swing_lows = self.find_swing_lows(df)

        return {
            'buy_side_liquidity': equal_highs + swing_highs,
            'sell_side_liquidity': equal_lows + swing_lows
        }

    def predict_sweep_target(self, current_price: float,
                              liquidity_zones: dict) -> dict:
        """
        Predice el objetivo de la siguiente barrida de liquidez.

        Si el precio se acerca a liquidez, es probable que:
        1. Barra la liquidez (crea máximo/mínimo temporal)
        2. Revierta en dirección opuesta
        """
        nearest_buy_liq = self.find_nearest_above(
            liquidity_zones['buy_side_liquidity'], current_price
        )
        nearest_sell_liq = self.find_nearest_below(
            liquidity_zones['sell_side_liquidity'], current_price
        )

        return {
            'probable_high': nearest_buy_liq * 1.001,  # Ligeramente por encima
            'probable_low': nearest_sell_liq * 0.999,  # Ligeramente por debajo
            'sweep_probability': self.calculate_sweep_prob(...)
        }

Utilidad para predicción de rangos:

  • Predice exactamente dónde se formarán máximos/mínimos
  • Las barridas de liquidez son predecibles

4.5 Estrategia: Market Structure Shift (MSS)

Concepto: Detectar cambios de estructura para anticipar reversiones.

class MarketStructureStrategy:
    """
    Market Structure Shift - ICT/SMC

    Detecta cambios en la estructura del mercado que indican
    reversiones de tendencia.
    """

    def analyze_structure(self, df: pd.DataFrame) -> MarketStructure:
        swing_points = self.identify_swing_points(df)

        # Determinar estructura actual
        if self.is_higher_highs_higher_lows(swing_points):
            structure = 'bullish'
        elif self.is_lower_highs_lower_lows(swing_points):
            structure = 'bearish'
        else:
            structure = 'ranging'

        return MarketStructure(
            current=structure,
            last_high=swing_points[-1] if swing_points[-1].type == 'high' else None,
            last_low=swing_points[-1] if swing_points[-1].type == 'low' else None
        )

    def detect_mss(self, df: pd.DataFrame, structure: MarketStructure) -> Optional[MSS]:
        """
        Market Structure Shift ocurre cuando:
        - En tendencia alcista: precio rompe último low significativo
        - En tendencia bajista: precio rompe último high significativo
        """
        if structure.current == 'bullish':
            if df['close'].iloc[-1] < structure.last_low.price:
                return MSS(
                    type='bearish_shift',
                    confirmation_level=structure.last_low.price,
                    target=self.calculate_target(df, 'bearish')
                )
        # ... inverso para bearish

    def predict_range_after_mss(self, mss: MSS) -> dict:
        """Después de MSS, el precio típicamente hace un retroceso."""
        return {
            'retracement_high': mss.confirmation_level,  # No debería superar
            'target_low': mss.target,
            'probability': 0.75  # MSS tienen alta probabilidad de seguimiento
        }

5. Arquitectura del Modelo Ensemble

5.1 Modelo de Predicción de Rangos Completo

class RangePredictionEnsemble:
    """
    Ensemble que combina múltiples estrategias y modelos ML
    para predecir máximos y mínimos con alta precisión.
    """

    def __init__(self):
        # Modelos ML
        self.range_predictor = XGBoostRangePredictor()
        self.volatility_predictor = LSTMVolatilityPredictor()
        self.direction_classifier = RandomForestDirectionClassifier()

        # Estrategias
        self.amd_strategy = AMDPhaseStrategy()
        self.vcp_strategy = VCPStrategy()
        self.order_block_strategy = OrderBlockStrategy()
        self.fvg_strategy = FairValueGapStrategy()
        self.liquidity_strategy = LiquiditySweepStrategy()
        self.mss_strategy = MarketStructureStrategy()

    def predict(self, df: pd.DataFrame, horizon: str = '60m') -> RangePrediction:
        """
        Genera predicción de rango combinando todos los modelos.

        Returns:
            RangePrediction con:
            - predicted_high: máximo esperado
            - predicted_low: mínimo esperado
            - confidence: confianza de la predicción
            - best_entry: mejor punto de entrada
            - optimal_sl: stop loss óptimo
            - optimal_tp: take profit óptimo
            - rr_ratio: ratio riesgo/recompensa
        """

        # 1. Features base
        features = self.calculate_features(df)

        # 2. Predicciones ML
        ml_range = self.range_predictor.predict(features)
        ml_volatility = self.volatility_predictor.predict(features)
        ml_direction = self.direction_classifier.predict(features)

        # 3. Análisis de estrategias
        amd_phase = self.amd_strategy.detect_phase(df)
        vcp_signal = self.vcp_strategy.detect_vcp(df)
        order_blocks = self.order_block_strategy.find_order_blocks(df)
        fvgs = self.fvg_strategy.find_fvg(df)
        liquidity = self.liquidity_strategy.detect_liquidity_zones(df)
        structure = self.mss_strategy.analyze_structure(df)

        # 4. Combinar predicciones
        combined = self.combine_predictions(
            ml_predictions={
                'range': ml_range,
                'volatility': ml_volatility,
                'direction': ml_direction
            },
            strategy_signals={
                'amd': amd_phase,
                'vcp': vcp_signal,
                'order_blocks': order_blocks,
                'fvgs': fvgs,
                'liquidity': liquidity,
                'structure': structure
            }
        )

        # 5. Calcular entrada óptima
        entry = self.calculate_optimal_entry(combined, df['close'].iloc[-1])

        return RangePrediction(
            predicted_high=combined['high'],
            predicted_low=combined['low'],
            confidence=combined['confidence'],
            best_entry=entry['price'],
            entry_type=entry['type'],  # 'long' or 'short'
            optimal_sl=entry['sl'],
            optimal_tp=entry['tp'],
            rr_ratio=entry['rr'],
            contributing_factors=combined['factors']
        )

    def combine_predictions(self, ml_predictions: dict,
                           strategy_signals: dict) -> dict:
        """
        Pondera predicciones según confianza y confluencia.

        Pesos base:
        - ML Range Predictor: 30%
        - AMD Phase: 20%
        - Liquidity Zones: 15%
        - Order Blocks: 15%
        - Market Structure: 10%
        - FVG/VCP: 10%

        Los pesos se ajustan según contexto.
        """

        weights = {
            'ml_range': 0.30,
            'amd': 0.20,
            'liquidity': 0.15,
            'order_blocks': 0.15,
            'structure': 0.10,
            'fvg_vcp': 0.10
        }

        # Ajustar pesos según contexto
        if strategy_signals['amd'].phase == 'accumulation':
            weights['amd'] = 0.30  # AMD más confiable en fases claras
            weights['ml_range'] = 0.20

        if len(strategy_signals['order_blocks']) > 0:
            # Order blocks cercanos aumentan confianza
            weights['order_blocks'] = 0.20

        # Calcular predicción ponderada
        ...

        return {
            'high': weighted_high,
            'low': weighted_low,
            'confidence': self.calculate_confluence_confidence(strategy_signals),
            'factors': contributing_factors
        }

    def calculate_optimal_entry(self, prediction: dict,
                                current_price: float) -> dict:
        """
        Calcula la entrada óptima para lograr R:R objetivo.

        Prioriza R:R 3:1, fallback a 2:1.
        """

        high = prediction['high']
        low = prediction['low']

        # Para LONG
        long_sl = low * 0.998  # SL ligeramente por debajo del mínimo predicho
        long_risk = current_price - long_sl
        long_tp_3_1 = current_price + (long_risk * 3)
        long_tp_2_1 = current_price + (long_risk * 2)

        # Verificar si TP es alcanzable según predicción
        long_3_1_achievable = long_tp_3_1 <= high
        long_2_1_achievable = long_tp_2_1 <= high

        # Para SHORT (inverso)
        short_sl = high * 1.002
        short_risk = short_sl - current_price
        short_tp_3_1 = current_price - (short_risk * 3)
        short_tp_2_1 = current_price - (short_risk * 2)

        short_3_1_achievable = short_tp_3_1 >= low
        short_2_1_achievable = short_tp_2_1 >= low

        # Seleccionar mejor entrada
        if long_3_1_achievable and prediction['direction'] == 'bullish':
            return {
                'type': 'long',
                'price': current_price,
                'sl': long_sl,
                'tp': long_tp_3_1,
                'rr': 3.0
            }
        elif short_3_1_achievable and prediction['direction'] == 'bearish':
            return {
                'type': 'short',
                'price': current_price,
                'sl': short_sl,
                'tp': short_tp_3_1,
                'rr': 3.0
            }
        # Fallback a 2:1
        ...

6. Métricas de Éxito

6.1 Objetivos por R:R

R:R Win Rate Objetivo Profit Factor Expectativa
3:1 ≥80% ≥4.0 +1.4R por trade
2:1 ≥90% ≥6.0 +0.8R por trade

6.2 Fórmulas de Validación

# Expectativa = (Win% × Avg Win) - (Loss% × Avg Loss)
# Para 3:1 con 80% win rate:
expectativa_3_1 = (0.80 * 3) - (0.20 * 1) = 2.4 - 0.2 = 2.2R

# Para 2:1 con 90% win rate:
expectativa_2_1 = (0.90 * 2) - (0.10 * 1) = 1.8 - 0.1 = 1.7R

6.3 Métricas de Predicción de Rangos

Métrica Objetivo Descripción
high_accuracy ≥85% % de veces que el precio alcanza el high predicho
low_accuracy ≥85% % de veces que el precio alcanza el low predicho
range_mae ≤0.5% Error absoluto medio del rango predicho
direction_accuracy ≥75% % de veces que la dirección es correcta

7. Pipeline de Training

7.1 Generación de Labels

def generate_range_labels(df: pd.DataFrame,
                          horizons: List[int] = [3, 12]) -> pd.DataFrame:
    """
    Genera labels para entrenamiento de predicción de rangos.

    Args:
        df: DataFrame con OHLCV
        horizons: [3, 12] = [15min, 60min] en velas de 5min

    Returns:
        DataFrame con labels:
        - delta_high_{horizon}: (max_high - current_close) / current_close
        - delta_low_{horizon}: (min_low - current_close) / current_close
    """

    labels = pd.DataFrame(index=df.index)

    for horizon in horizons:
        # Máximo en las próximas N velas
        future_high = df['high'].rolling(horizon).max().shift(-horizon)
        labels[f'delta_high_{horizon}'] = (future_high - df['close']) / df['close']

        # Mínimo en las próximas N velas
        future_low = df['low'].rolling(horizon).min().shift(-horizon)
        labels[f'delta_low_{horizon}'] = (future_low - df['close']) / df['close']

        # Label de dirección (cuál se alcanza primero)
        labels[f'direction_{horizon}'] = np.where(
            abs(labels[f'delta_high_{horizon}']) > abs(labels[f'delta_low_{horizon}']),
            1,  # Más probable alcista
            -1  # Más probable bajista
        )

    return labels

7.2 Validación Walk-Forward

def walk_forward_validation(model, df: pd.DataFrame,
                            train_size: int = 5000,
                            test_size: int = 1000,
                            step: int = 500) -> List[ValidationResult]:
    """
    Validación walk-forward para evitar overfitting.

    Simula condiciones reales de trading donde el modelo
    solo ve datos pasados.
    """

    results = []

    for i in range(0, len(df) - train_size - test_size, step):
        # Train set
        train_df = df.iloc[i:i+train_size]

        # Test set (datos "futuros")
        test_df = df.iloc[i+train_size:i+train_size+test_size]

        # Entrenar modelo
        model.fit(train_df)

        # Evaluar en test
        predictions = model.predict(test_df)
        metrics = evaluate_range_predictions(predictions, test_df)

        results.append(ValidationResult(
            train_period=(i, i+train_size),
            test_period=(i+train_size, i+train_size+test_size),
            metrics=metrics
        ))

    return results

8. Próximos Pasos

Fase 1: Preparación de Datos

  1. Recolectar datos históricos (mínimo 2 años)
  2. Calcular todas las features definidas
  3. Generar labels de rangos
  4. Split train/validation/test

Fase 2: Desarrollo de Modelos

  1. Implementar RangePredictor base (XGBoost)
  2. Implementar estrategias complementarias
  3. Crear ensemble combiner
  4. Optimizar pesos del ensemble

Fase 3: Validación

  1. Walk-forward validation
  2. Backtesting con R:R targets
  3. Paper trading
  4. Ajuste fino

Fase 4: Integración

  1. Integrar con ML Engine
  2. Exponer endpoints de predicción
  3. Conectar con LLM Agent
  4. Dashboard de métricas

9. Referencias

  • Wyckoff Method (AMD Phases)
  • ICT/SMC Concepts (Order Blocks, FVG, Liquidity)
  • Mark Minervini (VCP Pattern)
  • Elder Triple Screen
  • Documentación interna: ML_INVENTORY.yml

Autor: NEXUS-TRADING-STRATEGIST Revisado por: Product Owner Estado: Análisis Inicial