| id |
title |
type |
status |
priority |
epic |
project |
version |
created_date |
updated_date |
task_reference |
| ET-ML-011 |
MRD (Momentum Regime Detection) Strategy |
Technical Specification |
Approved |
Alta |
OQI-006 |
trading-platform |
1.0.0 |
2026-01-25 |
2026-01-25 |
TASK-2026-01-25-ML-TRAINING-ENHANCEMENT |
ET-ML-011: MRD (Momentum Regime Detection) Strategy
Metadata
| Campo |
Valor |
| ID |
ET-ML-011 |
| Epica |
OQI-006 - Senales ML |
| Tipo |
Especificacion Tecnica |
| Version |
1.0.0 |
| Estado |
Aprobado |
| Ultima actualizacion |
2026-01-25 |
| Tarea Referencia |
TASK-2026-01-25-ML-TRAINING-ENHANCEMENT |
Resumen
La estrategia MRD (Momentum Regime Detection) detecta regimenes de mercado (tendencia alcista, rango, tendencia bajista) usando un Hidden Markov Model (HMM) con 3 estados, complementado por LSTM para secuencias y XGBoost para predicciones.
Caracteristicas Clave
- HMM de 3 Estados: Detecta regimenes Trend Up, Range, Trend Down
- Features de Momentum: RSI, MACD, ROC, ADX, EMA crossovers
- Transiciones de Regimen: Probabilidades de cambio de estado
- Prediccion de Direccion: Basada en regimen actual + momentum
Arquitectura
Diagrama de Alto Nivel
┌─────────────────────────────────────────────────────────────────────────┐
│ MRD MODEL │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ Input: OHLCV Data │
│ └── Momentum indicators (RSI, MACD, ROC, ADX) │
│ │ │
│ ┌─────────────┴─────────────┐ │
│ ▼ ▼ │
│ ┌──────────────────────┐ ┌──────────────────────┐ │
│ │ HMM REGIME │ │ LSTM ENCODER │ │
│ │ DETECTOR │ │ │ │
│ │ │ │ ┌─────────────────┐ │ │
│ │ States: │ │ │ BiLSTM Layers │ │ │
│ │ 0 = TREND_UP │ │ │ (2 layers) │ │ │
│ │ 1 = RANGE │ │ └─────────────────┘ │ │
│ │ 2 = TREND_DOWN │ │ │ │ │
│ │ │ │ ▼ │ │
│ │ Outputs: │ │ ┌─────────────────┐ │ │
│ │ - current_regime │ │ │ Attention Pool │ │ │
│ │ - regime_probs │ │ └─────────────────┘ │ │
│ │ - transition_probs │ └──────────────────────┘ │
│ └──────────────────────┘ │ │
│ │ │ │
│ └───────────┬───────────────┘ │
│ ▼ │
│ ┌───────────────────────────────────────────────────────────────────┐ │
│ │ XGBOOST PREDICTOR │ │
│ │ │ │
│ │ Features: [regime_encoded, regime_probs, lstm_features, │ │
│ │ momentum_features, transition_probs] │ │
│ │ │ │
│ │ Outputs: │ │
│ │ - direction: bullish/bearish/neutral │ │
│ │ - regime_continuation_prob │ │
│ │ - expected_regime_duration │ │
│ └───────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ Output: MRDPrediction │
│ - current_regime: 'TREND_UP' | 'RANGE' | 'TREND_DOWN' │
│ - direction: float │
│ - regime_confidence: float │
│ - next_regime_probs: Dict │
└─────────────────────────────────────────────────────────────────────────┘
Componentes HMM
HMMConfig:
n_states: 3 # Trend Up, Range, Trend Down
n_iter: 100 # EM iterations
covariance_type: 'full'
random_state: 42
| Estado |
Caracteristicas |
Probabilidad Tipica |
| TREND_UP |
RSI > 50, MACD > 0, ADX > 25 |
~30% |
| RANGE |
RSI ~50, ADX < 20 |
~40% |
| TREND_DOWN |
RSI < 50, MACD < 0, ADX > 25 |
~30% |
Componentes LSTM
| Componente |
Configuracion |
| Layers |
2 BiLSTM layers |
| hidden_size |
128 |
| dropout |
0.2 |
| sequence_length |
50 |
| output_dim |
64 (latent features) |
Feature Engineering
Momentum Features
1. RSI (Relative Strength Index)
RSI Features:
rsi_14: RSI period 14
rsi_7: RSI period 7
rsi_28: RSI period 28
rsi_divergence: price_trend - rsi_trend
rsi_zone: oversold (-1) / neutral (0) / overbought (1)
| Feature |
Formula |
Interpretacion |
rsi_14 |
RSI standard |
Momentum actual |
rsi_divergence |
np.sign(price_slope) - np.sign(rsi_slope) |
Divergencia bull/bear |
rsi_zone |
Discretizado (-1, 0, 1) |
Zona de RSI |
2. MACD (Moving Average Convergence Divergence)
MACD Features:
macd: EMA_12 - EMA_26
macd_signal: EMA_9(macd)
macd_hist: macd - macd_signal
macd_crossover: binary (1 if macd > signal, else -1)
macd_hist_slope: trend of histogram
| Feature |
Descripcion |
macd_hist |
Histograma MACD |
macd_crossover |
Cruce de linea de senal |
macd_hist_slope |
Direccion del histograma |
3. ROC (Rate of Change)
ROC Features:
roc_5: (close / close.shift(5) - 1) * 100
roc_10: (close / close.shift(10) - 1) * 100
roc_20: (close / close.shift(20) - 1) * 100
roc_acceleration: roc_5 - roc_5.shift(5)
4. ADX (Average Directional Index)
ADX Features:
adx: ADX(14)
plus_di: +DI(14)
minus_di: -DI(14)
di_crossover: +DI > -DI ? 1 : -1
trend_strength: ADX > 25 ? 'strong' : 'weak'
| Feature |
Interpretacion |
adx > 25 |
Mercado en tendencia |
adx < 20 |
Mercado en rango |
+DI > -DI |
Tendencia alcista dominante |
5. EMA Crossovers
EMA_Crossover Features:
ema_8_21_cross: EMA(8) vs EMA(21)
ema_21_55_cross: EMA(21) vs EMA(55)
ema_stack: 1 if EMA8 > EMA21 > EMA55 else -1 if EMA8 < EMA21 < EMA55 else 0
price_vs_ema21: (close - EMA21) / close
Estados del Regimen
Definicion de Estados HMM
class RegimeState(Enum):
TREND_UP = 0 # Mercado en tendencia alcista
RANGE = 1 # Mercado lateral/consolidacion
TREND_DOWN = 2 # Mercado en tendencia bajista
Caracteristicas por Estado
| Estado |
RSI |
MACD |
ADX |
EMA Stack |
Volatilidad |
| TREND_UP |
> 55 |
> 0, rising |
> 25 |
8 > 21 > 55 |
Media |
| RANGE |
40-60 |
Near 0 |
< 20 |
Mixto |
Baja |
| TREND_DOWN |
< 45 |
< 0, falling |
> 25 |
8 < 21 < 55 |
Media-Alta |
Matriz de Transicion
TREND_UP RANGE TREND_DOWN
TREND_UP [0.80 0.15 0.05 ]
RANGE [0.25 0.50 0.25 ]
TREND_DOWN [0.05 0.15 0.80 ]
La matriz de transicion se estima dinamicamente via EM.
Pipeline de Entrenamiento
Fase 1: Entrenamiento HMM
# Entrenar HMM en features de momentum
hmm_model = GaussianHMM(n_components=3, covariance_type='full')
hmm_model.fit(momentum_features)
# Obtener estados y probabilidades
hidden_states = hmm_model.predict(momentum_features)
state_probs = hmm_model.predict_proba(momentum_features)
transition_matrix = hmm_model.transmat_
Fase 2: Entrenamiento LSTM
# Entrenar LSTM en secuencias de momentum
lstm_encoder = MRDLSTMEncoder(
input_dim=n_features,
hidden_dim=128,
n_layers=2,
output_dim=64
)
# Loss: Combinacion de regime prediction + reconstruction
loss = regime_cross_entropy + 0.3 * reconstruction_mse
Fase 3: Entrenamiento XGBoost
# Combinar features para XGBoost
combined_features = np.concatenate([
one_hot_regime, # Estado HMM actual
state_probs, # Probabilidades de estado
lstm_features, # Features LSTM
momentum_features, # Features originales
transition_probs # Probabilidades de transicion
], axis=1)
# Entrenar clasificador de direccion
xgb_direction = XGBClassifier(**xgb_params)
xgb_direction.fit(combined_features, direction_labels)
Metricas de Evaluacion
Metricas de Regimen
| Metrica |
Descripcion |
Target |
| Regime Accuracy |
Precision en deteccion de estado |
>= 70% |
| Transition Accuracy |
Precision en cambios de regimen |
>= 60% |
| Regime Duration Error |
MAE en duracion esperada |
< 5 candles |
Metricas de Direccion
| Metrica |
Descripcion |
Target |
| Direction Accuracy |
Precision en direccion |
>= 55% |
| Regime-Conditional Accuracy |
Accuracy por regimen |
Trend >= 60%, Range >= 50% |
| Transition Signal Quality |
Performance en cambios |
> 0 return |
Evaluacion de HMM
MRDMetrics:
log_likelihood: float # Log-likelihood del modelo
aic: float # Akaike Information Criterion
bic: float # Bayesian Information Criterion
regime_accuracy: float
transition_f1: float
avg_regime_duration: Dict[str, float]
API y Uso
Clase Principal: MRDModel
from models.strategies.mrd import MRDModel, MRDConfig
# Configuracion
config = MRDConfig(
n_regimes=3,
lstm_hidden_dim=128,
lstm_layers=2,
sequence_length=50,
xgb_n_estimators=200
)
# Inicializar modelo
model = MRDModel(config)
# Entrenar
model.fit(df_train, df_val)
# Prediccion
predictions = model.predict(df_new)
for pred in predictions:
print(f"Regime: {pred.current_regime}")
print(f"Direction: {pred.direction}")
print(f"Next Regime Probs: {pred.next_regime_probs}")
Clase MRDPrediction
@dataclass
class MRDPrediction:
current_regime: str # 'TREND_UP', 'RANGE', 'TREND_DOWN'
regime_confidence: float # 0 to 1
direction: float # -1 to 1
direction_confidence: float
next_regime_probs: Dict[str, float] # Probabilidades del proximo estado
expected_regime_duration: int # Candles esperados en este regimen
momentum_strength: float # Fuerza del momentum actual
@property
def trading_bias(self) -> str:
if self.current_regime == 'TREND_UP' and self.direction > 0:
return 'STRONG_LONG'
elif self.current_regime == 'TREND_DOWN' and self.direction < 0:
return 'STRONG_SHORT'
elif self.current_regime == 'RANGE':
return 'NEUTRAL'
else:
return 'WEAK_' + ('LONG' if self.direction > 0 else 'SHORT')
Deteccion de Cambio de Regimen
# Obtener probabilidad de cambio de regimen
def detect_regime_change(predictions: List[MRDPrediction]) -> bool:
if len(predictions) < 2:
return False
current = predictions[-1]
previous = predictions[-2]
# Cambio de regimen si:
# 1. Estado actual diferente
# 2. Probabilidad del nuevo estado > 70%
if current.current_regime != previous.current_regime:
if current.regime_confidence > 0.7:
return True
return False
Estructura de Archivos
apps/ml-engine/src/models/strategies/mrd/
├── __init__.py
├── model.py # MRDModel, MRDConfig, MRDPrediction
├── feature_engineering.py # MRDFeatureEngineer
├── hmm_regime.py # HMM regime detector (GaussianHMM wrapper)
├── lstm_encoder.py # BiLSTM encoder
└── trainer.py # MRDTrainer
Consideraciones de Produccion
Actualizacion Online del HMM
# El HMM puede actualizarse incrementalmente
def update_hmm(model, new_data, window_size=1000):
"""Actualiza HMM con datos recientes manteniendo estabilidad"""
if len(new_data) > window_size:
recent_data = new_data[-window_size:]
else:
recent_data = new_data
# Re-fit con warm start
model.hmm.fit(recent_data)
Deteccion de Regimen en Tiempo Real
# Pipeline de inferencia optimizado
class MRDInference:
def __init__(self, model_path: str):
self.model = MRDModel.load(model_path)
self.feature_buffer = deque(maxlen=100)
def update(self, candle: Dict) -> MRDPrediction:
self.feature_buffer.append(candle)
if len(self.feature_buffer) >= 50:
features = self.compute_features()
return self.model.predict_single(features)
return None
Alertas de Cambio de Regimen
# Sistema de alertas
def check_regime_alerts(prediction: MRDPrediction) -> List[Alert]:
alerts = []
# Alerta de cambio de regimen inminente
if prediction.regime_confidence < 0.5:
alerts.append(Alert(
type='REGIME_UNCERTAINTY',
message='Regimen actual inestable',
severity='WARNING'
))
# Alerta de transicion probable
for regime, prob in prediction.next_regime_probs.items():
if regime != prediction.current_regime and prob > 0.4:
alerts.append(Alert(
type='REGIME_TRANSITION',
message=f'Posible transicion a {regime}',
severity='INFO'
))
return alerts
Referencias
Autor: ML-Specialist (NEXUS v4.0)
Fecha: 2026-01-25