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

```python
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.

```python
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.

```python
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.

```python
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.

```python
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

```python
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

```python
# 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

```python
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

```python
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
