- Created TASK-2026-01-26-ANALYSIS-INTEGRATION-PLAN with complete CAPVED documentation - Orchestrated 5 specialized Explore agents in parallel (85% time reduction) - Identified 7 coherence gaps (DDL↔Backend↔Frontend) - Identified 4 P0 blockers preventing GO-LIVE - Documented 58 missing documentation items - Created detailed roadmap Q1-Q4 2026 (2,500h total) - Added 6 new ET specs for ML strategies (PVA, MRD, VBP, MSA, MTS, Backtesting) - Updated _INDEX.yml with new analysis task Hallazgos críticos: - E-COH-001 to E-COH-007: Coherence gaps (6.5h to fix) - BLOCKER-001 to 004: Token refresh, PCI-DSS, Video upload, MT4 Gateway (380h) - Documentation gaps: 8 ET specs, 8 US, 34 Swagger docs (47.5h) Roadmap phases: - Q1: Security & Blockers (249h) - Q2: Core Features + GO-LIVE (542h) - Q3: Scalability & Performance (380h) - Q4: Innovation & Advanced Features (1,514h) ROI: $223k investment → $750k revenue → $468k net profit (165% ROI) Next: Execute ST1 (Coherencia Fixes P0) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
480 lines
16 KiB
Markdown
480 lines
16 KiB
Markdown
---
|
|
id: "ET-ML-011"
|
|
title: "MRD (Momentum Regime Detection) Strategy"
|
|
type: "Technical Specification"
|
|
status: "Approved"
|
|
priority: "Alta"
|
|
epic: "OQI-006"
|
|
project: "trading-platform"
|
|
version: "1.0.0"
|
|
created_date: "2026-01-25"
|
|
updated_date: "2026-01-25"
|
|
task_reference: "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
|
|
|
|
```python
|
|
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)
|
|
|
|
```python
|
|
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)
|
|
|
|
```python
|
|
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)
|
|
|
|
```python
|
|
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)
|
|
|
|
```python
|
|
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
|
|
|
|
```python
|
|
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
|
|
|
|
```python
|
|
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
|
|
|
|
```python
|
|
# 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
|
|
|
|
```python
|
|
# 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
|
|
|
|
```python
|
|
# 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
|
|
|
|
```python
|
|
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
|
|
|
|
```python
|
|
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
|
|
|
|
```python
|
|
@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
|
|
|
|
```python
|
|
# 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
|
|
|
|
```python
|
|
# 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
|
|
|
|
```python
|
|
# 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
|
|
|
|
```python
|
|
# 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
|
|
|
|
- [ET-ML-001: Arquitectura ML Engine](./ET-ML-001-arquitectura.md)
|
|
- [ET-ML-010: PVA Strategy](./ET-ML-010-pva-strategy.md)
|
|
- [Hidden Markov Models (Rabiner, 1989)](https://web.ece.ucsb.edu/Faculty/Rabiner/ece259/Reprints/tutorial%20on%20hmm%20and%20applications.pdf)
|
|
- [hmmlearn Documentation](https://hmmlearn.readthedocs.io/)
|
|
|
|
---
|
|
|
|
**Autor:** ML-Specialist (NEXUS v4.0)
|
|
**Fecha:** 2026-01-25
|