# 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