- 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>
689 lines
24 KiB
Markdown
689 lines
24 KiB
Markdown
---
|
|
id: "ET-ML-014"
|
|
title: "MTS (Multi-Timeframe Synthesis) 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-014: MTS (Multi-Timeframe Synthesis) Strategy
|
|
|
|
## Metadata
|
|
|
|
| Campo | Valor |
|
|
|-------|-------|
|
|
| **ID** | ET-ML-014 |
|
|
| **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 MTS (Multi-Timeframe Synthesis) sintetiza informacion de multiples timeframes usando una **Hierarchical Attention Network** para generar una representacion unificada y **XGBoost** para predicciones finales. El modelo calcula **alineamiento entre timeframes** y **scores de conflicto**.
|
|
|
|
### Caracteristicas Clave
|
|
|
|
- **4 Timeframes**: 5m, 15m, 1h, 4h agregados desde datos base
|
|
- **Hierarchical Attention**: Aprende pesos dinamicos por timeframe
|
|
- **Alignment Score**: Mide coherencia entre timeframes
|
|
- **Conflict Score**: Identifica divergencias entre timeframes
|
|
|
|
---
|
|
|
|
## Arquitectura
|
|
|
|
### Diagrama de Alto Nivel
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────────────────────┐
|
|
│ MTS MODEL │
|
|
├─────────────────────────────────────────────────────────────────────────┤
|
|
│ │
|
|
│ Input: 5m OHLCV Data (base timeframe) │
|
|
│ │ │
|
|
│ ▼ │
|
|
│ ┌───────────────────────────────────────────────────────────────────┐ │
|
|
│ │ TIMEFRAME AGGREGATION │ │
|
|
│ │ │ │
|
|
│ │ 5m Data ─┬──▶ 5m Features ───────────────────────┐ │ │
|
|
│ │ │ │ │ │
|
|
│ │ ├──▶ 15m Aggregation ──▶ 15m Features ───┤ │ │
|
|
│ │ │ │ │ │
|
|
│ │ ├──▶ 1h Aggregation ──▶ 1h Features ───┤ │ │
|
|
│ │ │ │ │ │
|
|
│ │ └──▶ 4h Aggregation ──▶ 4h Features ───┘ │ │
|
|
│ │ │ │ │
|
|
│ └─────────────────────────────────────────│──────────────────────────┘ │
|
|
│ ▼ │
|
|
│ ┌───────────────────────────────────────────────────────────────────┐ │
|
|
│ │ HIERARCHICAL ATTENTION NETWORK │ │
|
|
│ │ │ │
|
|
│ │ ┌─────────────────────────────────────────────────────────────┐ │ │
|
|
│ │ │ Per-Timeframe Encoders │ │ │
|
|
│ │ │ │ │ │
|
|
│ │ │ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ │ │ │
|
|
│ │ │ │ 5m │ │ 15m │ │ 1h │ │ 4h │ │ │ │
|
|
│ │ │ │Enc. │ │Enc. │ │Enc. │ │Enc. │ │ │ │
|
|
│ │ │ └──┬──┘ └──┬──┘ └──┬──┘ └──┬──┘ │ │ │
|
|
│ │ │ │ │ │ │ │ │ │
|
|
│ │ └─────│──────────│──────────│──────────│────────────────────────┘ │ │
|
|
│ │ │ │ │ │ │ │
|
|
│ │ └──────────┼──────────┼──────────┘ │ │
|
|
│ │ ▼ ▼ │ │
|
|
│ │ ┌─────────────────────────────────┐ │ │
|
|
│ │ │ Cross-Timeframe Attention │ │ │
|
|
│ │ │ (learns TF relationships) │ │ │
|
|
│ │ └─────────────────────────────────┘ │ │
|
|
│ │ │ │ │
|
|
│ │ ▼ │ │
|
|
│ │ ┌─────────────────────────────────┐ │ │
|
|
│ │ │ Timeframe Fusion Layer │ │ │
|
|
│ │ │ (learnable TF weights) │ │ │
|
|
│ │ └─────────────────────────────────┘ │ │
|
|
│ │ │ │ │
|
|
│ │ ▼ │ │
|
|
│ │ ┌─────────────────────────────────┐ │ │
|
|
│ │ │ Unified Representation │ │ │
|
|
│ │ │ (d_model = 128) │ │ │
|
|
│ │ └─────────────────────────────────┘ │ │
|
|
│ └───────────────────────────────────────────────────────────────────┘ │
|
|
│ │ │
|
|
│ ▼ │
|
|
│ ┌───────────────────────────────────────────────────────────────────┐ │
|
|
│ │ XGBOOST HEADS │ │
|
|
│ │ │ │
|
|
│ │ ┌────────────────┐ ┌────────────────┐ ┌────────────────┐ │ │
|
|
│ │ │ Direction │ │ Confidence │ │ Optimal Entry │ │ │
|
|
│ │ │ Classifier │ │ Regressor │ │ TF Classifier │ │ │
|
|
│ │ │ (3 classes) │ │ (0 to 1) │ │ (4 classes) │ │ │
|
|
│ │ └────────────────┘ └────────────────┘ └────────────────┘ │ │
|
|
│ └───────────────────────────────────────────────────────────────────┘ │
|
|
│ │ │
|
|
│ ▼ │
|
|
│ Output: MTSPrediction │
|
|
│ - unified_direction: -1 to 1 │
|
|
│ - confidence_by_alignment: 0 to 1 │
|
|
│ - optimal_entry_tf: '5m' | '15m' | '1h' | '4h' │
|
|
│ - tf_contributions: Dict[str, float] │
|
|
└─────────────────────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
### Hierarchical Attention Config
|
|
|
|
```python
|
|
HierarchicalAttentionConfig:
|
|
d_model: 128
|
|
n_heads: 4
|
|
d_ff: 256
|
|
n_layers: 2
|
|
dropout: 0.1
|
|
max_seq_len: 256
|
|
timeframes: ('5m', '15m', '1h', '4h')
|
|
use_cross_tf_attention: True
|
|
use_learnable_tf_weights: True
|
|
```
|
|
|
|
---
|
|
|
|
## Timeframe Aggregation
|
|
|
|
### Proceso de Agregacion
|
|
|
|
El modelo recibe datos en 5m y agrega a timeframes superiores:
|
|
|
|
```python
|
|
class MTSFeatureEngineer:
|
|
def aggregate_to_timeframe(
|
|
self,
|
|
df_5m: pd.DataFrame,
|
|
target_tf: str
|
|
) -> pd.DataFrame:
|
|
"""Agregar datos de 5m al timeframe objetivo"""
|
|
|
|
# Mapeo de periodos
|
|
periods = {
|
|
'5m': 1,
|
|
'15m': 3,
|
|
'1h': 12,
|
|
'4h': 48
|
|
}
|
|
|
|
n_periods = periods[target_tf]
|
|
|
|
# Agregar OHLCV
|
|
resampled = df_5m.resample(target_tf).agg({
|
|
'open': 'first',
|
|
'high': 'max',
|
|
'low': 'min',
|
|
'close': 'last',
|
|
'volume': 'sum'
|
|
})
|
|
|
|
return resampled
|
|
```
|
|
|
|
### Features por Timeframe
|
|
|
|
Cada timeframe tiene su propio conjunto de features:
|
|
|
|
```python
|
|
Per-Timeframe Features:
|
|
# Price-based
|
|
returns_1: 1-period return
|
|
returns_5: 5-period return
|
|
returns_10: 10-period return
|
|
|
|
# Volatility
|
|
atr_14: ATR(14)
|
|
volatility: rolling std of returns
|
|
|
|
# Momentum
|
|
rsi_14: RSI(14)
|
|
macd: MACD line
|
|
macd_signal: Signal line
|
|
|
|
# Trend
|
|
ema_8: EMA(8)
|
|
ema_21: EMA(21)
|
|
ema_55: EMA(55)
|
|
trend_strength: EMA crossover metrics
|
|
```
|
|
|
|
---
|
|
|
|
## Alignment y Conflict Scores
|
|
|
|
### Alignment Score
|
|
|
|
Mide la coherencia direccional entre timeframes:
|
|
|
|
```python
|
|
def compute_alignment_score(
|
|
tf_features: Dict[str, np.ndarray]
|
|
) -> float:
|
|
"""Calcular alineamiento entre timeframes"""
|
|
|
|
# Extraer direccion de cada timeframe
|
|
directions = {}
|
|
for tf, features in tf_features.items():
|
|
# Direction basada en trend indicators
|
|
trend = np.sign(features['ema_8'] - features['ema_21'])
|
|
momentum = np.sign(features['rsi_14'] - 50)
|
|
macd_dir = np.sign(features['macd'])
|
|
|
|
directions[tf] = np.mean([trend, momentum, macd_dir])
|
|
|
|
# Calcular coherencia
|
|
all_directions = list(directions.values())
|
|
|
|
# Alignment = 1 si todos tienen misma direccion
|
|
# Alignment = 0 si direcciones contradictorias
|
|
alignment = 1 - np.std(all_directions)
|
|
|
|
return np.clip(alignment, 0, 1)
|
|
```
|
|
|
|
### Conflict Score
|
|
|
|
Identifica divergencias significativas:
|
|
|
|
```python
|
|
def compute_conflict_score(
|
|
tf_features: Dict[str, np.ndarray],
|
|
hierarchy: List[str] = ['4h', '1h', '15m', '5m']
|
|
) -> float:
|
|
"""Calcular conflicto entre timeframes"""
|
|
|
|
conflicts = []
|
|
|
|
for i, higher_tf in enumerate(hierarchy[:-1]):
|
|
for lower_tf in hierarchy[i+1:]:
|
|
higher_dir = get_direction(tf_features[higher_tf])
|
|
lower_dir = get_direction(tf_features[lower_tf])
|
|
|
|
# Conflicto si direcciones opuestas
|
|
if higher_dir * lower_dir < 0:
|
|
# Mas peso si el conflicto es con TF mayor
|
|
weight = 1.0 / (i + 1)
|
|
conflicts.append(weight)
|
|
|
|
conflict_score = sum(conflicts) / len(hierarchy) if conflicts else 0
|
|
return np.clip(conflict_score, 0, 1)
|
|
```
|
|
|
|
### Interpretacion
|
|
|
|
| Alignment | Conflict | Interpretacion | Accion |
|
|
|-----------|----------|----------------|--------|
|
|
| > 0.8 | < 0.2 | Fuerte consenso | Trade con confianza |
|
|
| 0.5-0.8 | 0.2-0.5 | Consenso parcial | Trade con precaucion |
|
|
| < 0.5 | > 0.5 | Mercado mixto | Esperar o reducir size |
|
|
| < 0.3 | > 0.7 | Conflicto severo | No operar |
|
|
|
|
---
|
|
|
|
## Hierarchical Attention Network
|
|
|
|
### Per-Timeframe Encoder
|
|
|
|
Cada timeframe tiene su propio encoder:
|
|
|
|
```python
|
|
class TimeframeEncoder(nn.Module):
|
|
def __init__(self, input_dim: int, d_model: int):
|
|
super().__init__()
|
|
self.input_proj = nn.Linear(input_dim, d_model)
|
|
self.encoder = nn.TransformerEncoder(
|
|
nn.TransformerEncoderLayer(
|
|
d_model=d_model,
|
|
nhead=4,
|
|
dim_feedforward=d_model * 2,
|
|
dropout=0.1
|
|
),
|
|
num_layers=2
|
|
)
|
|
|
|
def forward(self, x: torch.Tensor) -> torch.Tensor:
|
|
x = self.input_proj(x)
|
|
return self.encoder(x)
|
|
```
|
|
|
|
### Cross-Timeframe Attention
|
|
|
|
Modela relaciones entre timeframes:
|
|
|
|
```python
|
|
class CrossTimeframeAttention(nn.Module):
|
|
def __init__(self, d_model: int, n_heads: int, n_timeframes: int):
|
|
super().__init__()
|
|
self.attention = nn.MultiheadAttention(d_model, n_heads)
|
|
|
|
# Embeddings para cada timeframe
|
|
self.tf_embeddings = nn.Embedding(n_timeframes, d_model)
|
|
|
|
def forward(
|
|
self,
|
|
tf_features: Dict[str, torch.Tensor]
|
|
) -> torch.Tensor:
|
|
# Concatenar features de todos los TFs
|
|
tf_list = list(tf_features.keys())
|
|
features = torch.stack([tf_features[tf] for tf in tf_list])
|
|
|
|
# Agregar TF embeddings
|
|
tf_ids = torch.arange(len(tf_list))
|
|
tf_embs = self.tf_embeddings(tf_ids)
|
|
features = features + tf_embs.unsqueeze(1)
|
|
|
|
# Cross-attention
|
|
attended, weights = self.attention(features, features, features)
|
|
|
|
return attended, weights
|
|
```
|
|
|
|
### Learnable Timeframe Weights
|
|
|
|
```python
|
|
class TimeframeFusion(nn.Module):
|
|
def __init__(self, n_timeframes: int, d_model: int):
|
|
super().__init__()
|
|
|
|
# Pesos aprendibles por timeframe
|
|
self.tf_weights = nn.Parameter(torch.ones(n_timeframes))
|
|
|
|
# Fusion layer
|
|
self.fusion = nn.Sequential(
|
|
nn.Linear(d_model * n_timeframes, d_model * 2),
|
|
nn.GELU(),
|
|
nn.Dropout(0.1),
|
|
nn.Linear(d_model * 2, d_model)
|
|
)
|
|
|
|
def forward(
|
|
self,
|
|
tf_features: List[torch.Tensor],
|
|
alignment: torch.Tensor,
|
|
conflict: torch.Tensor
|
|
) -> torch.Tensor:
|
|
# Normalizar pesos
|
|
weights = F.softmax(self.tf_weights, dim=0)
|
|
|
|
# Ponderar features
|
|
weighted_features = []
|
|
for i, feat in enumerate(tf_features):
|
|
weighted_features.append(feat * weights[i])
|
|
|
|
# Ajustar por alignment (mas peso si hay consenso)
|
|
alignment_factor = 0.5 + alignment * 0.5
|
|
|
|
# Concatenar y fusionar
|
|
concat = torch.cat(weighted_features, dim=-1)
|
|
unified = self.fusion(concat) * alignment_factor
|
|
|
|
return unified, weights
|
|
```
|
|
|
|
---
|
|
|
|
## Training Pipeline
|
|
|
|
### Fase 1: Feature Preparation
|
|
|
|
```python
|
|
model = MTSModel(config)
|
|
|
|
# Preparar datos multi-TF desde 5m base
|
|
tf_features, alignment, conflict = model._prepare_features(df_5m)
|
|
|
|
# Shape: {tf: (n_samples, seq_len, n_features)}
|
|
print(f"5m features: {tf_features['5m'].shape}")
|
|
print(f"1h features: {tf_features['1h'].shape}")
|
|
print(f"Alignment: {alignment.shape}")
|
|
print(f"Conflict: {conflict.shape}")
|
|
```
|
|
|
|
### Fase 2: Attention Training
|
|
|
|
```python
|
|
# Entrenar hierarchical attention
|
|
model.train_attention(
|
|
train_data=train_dfs, # List of 5m DataFrames
|
|
val_data=val_dfs,
|
|
epochs=50,
|
|
batch_size=32,
|
|
lr=0.001
|
|
)
|
|
```
|
|
|
|
### Fase 3: XGBoost Training
|
|
|
|
```python
|
|
# Extraer representaciones unificadas
|
|
unified_rep = model._extract_unified_representation(tf_features, alignment, conflict)
|
|
|
|
# Generar labels
|
|
y_direction = generate_direction_labels(df, forward_bars=12)
|
|
y_confidence = generate_confidence_targets(alignment, conflict)
|
|
y_entry_tf = determine_optimal_entry_tf(df, tf_features)
|
|
|
|
# Entrenar XGBoost
|
|
model.train_xgboost(
|
|
X_train=unified_rep,
|
|
y_direction=y_direction,
|
|
y_confidence=y_confidence,
|
|
y_entry_tf=y_entry_tf
|
|
)
|
|
```
|
|
|
|
### XGBoost Configuration
|
|
|
|
```python
|
|
MTSConfig:
|
|
xgb_n_estimators: 200
|
|
xgb_max_depth: 6
|
|
xgb_learning_rate: 0.05
|
|
xgb_subsample: 0.8
|
|
xgb_colsample_bytree: 0.8
|
|
xgb_min_child_weight: 5
|
|
xgb_reg_alpha: 0.1
|
|
xgb_reg_lambda: 1.0
|
|
```
|
|
|
|
---
|
|
|
|
## Metricas de Evaluacion
|
|
|
|
### Metricas de Direccion
|
|
|
|
| Metrica | Descripcion | Target |
|
|
|---------|-------------|--------|
|
|
| **Direction Accuracy** | Precision direccional | >= 55% |
|
|
| **Direction F1** | F1 por clase | >= 0.50 |
|
|
| **Alignment-Weighted Accuracy** | Accuracy ponderada por alignment | >= 60% |
|
|
|
|
### Metricas de Confianza
|
|
|
|
| Metrica | Descripcion | Target |
|
|
|---------|-------------|--------|
|
|
| **Confidence MSE** | Error en prediccion de confianza | < 0.1 |
|
|
| **Calibration Score** | Alineacion confianza-accuracy | > 0.8 |
|
|
|
|
### Metricas Multi-TF
|
|
|
|
| Metrica | Descripcion | Target |
|
|
|---------|-------------|--------|
|
|
| **TF Contribution Stability** | Estabilidad de pesos TF | std < 0.1 |
|
|
| **Optimal TF Accuracy** | Precision en TF de entrada optimo | >= 50% |
|
|
| **Alignment Prediction** | Correlacion alignment predicho vs real | > 0.7 |
|
|
|
|
---
|
|
|
|
## API y Uso
|
|
|
|
### Clase Principal: MTSModel
|
|
|
|
```python
|
|
from models.strategies.mts import MTSModel, MTSConfig, MTSPrediction
|
|
|
|
# Configuracion
|
|
config = MTSConfig(
|
|
timeframes=('5m', '15m', '1h', '4h'),
|
|
d_model=128,
|
|
n_heads=4,
|
|
n_layers=2,
|
|
use_cross_tf_attention=True,
|
|
use_learnable_tf_weights=True
|
|
)
|
|
|
|
# Inicializar modelo
|
|
model = MTSModel(config, use_xgboost=True)
|
|
|
|
# Entrenar
|
|
model.train_attention(train_dfs, val_dfs, epochs=50)
|
|
model.train_xgboost(X_train, y_direction, y_confidence, y_entry_tf)
|
|
|
|
# Prediccion desde datos 5m
|
|
prediction = model.predict(df_5m)
|
|
print(f"Direction: {prediction.direction_class} ({prediction.unified_direction:.2f})")
|
|
print(f"Confidence: {prediction.confidence:.2f}")
|
|
print(f"Optimal Entry TF: {prediction.optimal_entry_tf}")
|
|
print(f"TF Contributions: {prediction.tf_contributions}")
|
|
```
|
|
|
|
### Clase MTSPrediction
|
|
|
|
```python
|
|
@dataclass
|
|
class MTSPrediction:
|
|
unified_direction: float # -1 to 1
|
|
direction_class: str # 'bullish', 'bearish', 'neutral'
|
|
confidence: float # 0 to 1
|
|
confidence_by_alignment: float # Based on TF alignment
|
|
optimal_entry_tf: str # '5m', '15m', '1h', '4h'
|
|
tf_contributions: Dict[str, float] # Weight per TF
|
|
signal_strength: float # 0 to 1
|
|
recommended_action: str # 'buy', 'sell', 'hold'
|
|
|
|
def to_dict(self) -> Dict[str, Any]:
|
|
return {
|
|
'unified_direction': float(self.unified_direction),
|
|
'direction_class': self.direction_class,
|
|
'confidence': float(self.confidence),
|
|
'confidence_by_alignment': float(self.confidence_by_alignment),
|
|
'optimal_entry_tf': self.optimal_entry_tf,
|
|
'tf_contributions': self.tf_contributions,
|
|
'signal_strength': float(self.signal_strength),
|
|
'recommended_action': self.recommended_action
|
|
}
|
|
```
|
|
|
|
### Timeframe Contributions
|
|
|
|
```python
|
|
# Obtener contribucion de cada timeframe
|
|
contributions = model.get_tf_contributions()
|
|
|
|
# Ejemplo output:
|
|
# {
|
|
# '5m': 0.15, # Short-term noise
|
|
# '15m': 0.25, # Entry timing
|
|
# '1h': 0.35, # Main trend
|
|
# '4h': 0.25 # Higher TF context
|
|
# }
|
|
|
|
# Interpretar: 1h es el TF mas importante para esta prediccion
|
|
```
|
|
|
|
---
|
|
|
|
## Estructura de Archivos
|
|
|
|
```
|
|
apps/ml-engine/src/models/strategies/mts/
|
|
├── __init__.py
|
|
├── model.py # MTSModel, MTSConfig, MTSPrediction
|
|
├── feature_engineering.py # MTSFeatureEngineer (aggregation + features)
|
|
├── hierarchical_attention.py # HierarchicalAttention, CrossTFAttention
|
|
├── timeframe_fusion.py # TimeframeFusion layer
|
|
└── trainer.py # MTSTrainer
|
|
```
|
|
|
|
---
|
|
|
|
## Estrategias de Trading
|
|
|
|
### Entry Based on Alignment
|
|
|
|
```python
|
|
def generate_entry_signal(pred: MTSPrediction) -> Optional[Dict]:
|
|
"""Generar senal basada en MTS"""
|
|
|
|
# Solo operar con alto alineamiento
|
|
if pred.confidence_by_alignment < 0.6:
|
|
return None
|
|
|
|
# Direccion clara
|
|
if abs(pred.unified_direction) < 0.3:
|
|
return None
|
|
|
|
direction = 'LONG' if pred.unified_direction > 0 else 'SHORT'
|
|
|
|
return {
|
|
'direction': direction,
|
|
'entry_tf': pred.optimal_entry_tf,
|
|
'confidence': pred.signal_strength,
|
|
'tf_weights': pred.tf_contributions
|
|
}
|
|
```
|
|
|
|
### Multi-TF Confirmation
|
|
|
|
```python
|
|
def check_tf_confirmation(pred: MTSPrediction) -> Dict:
|
|
"""Verificar confirmacion multi-TF"""
|
|
|
|
contributions = pred.tf_contributions
|
|
|
|
# Verificar que TFs mayores esten alineados
|
|
higher_tf_weight = contributions['4h'] + contributions['1h']
|
|
lower_tf_weight = contributions['15m'] + contributions['5m']
|
|
|
|
# Preferir cuando TFs mayores tienen mas peso
|
|
if higher_tf_weight > lower_tf_weight:
|
|
quality = 'HIGH'
|
|
else:
|
|
quality = 'MEDIUM'
|
|
|
|
return {
|
|
'quality': quality,
|
|
'higher_tf_weight': higher_tf_weight,
|
|
'lower_tf_weight': lower_tf_weight,
|
|
'dominant_tf': max(contributions, key=contributions.get)
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Consideraciones de Produccion
|
|
|
|
### Real-Time Multi-TF Updates
|
|
|
|
```python
|
|
class MTSRealtime:
|
|
def __init__(self, model_path: str):
|
|
self.model = MTSModel.load(model_path)
|
|
self.buffers = {
|
|
'5m': deque(maxlen=500),
|
|
'15m': deque(maxlen=200),
|
|
'1h': deque(maxlen=100),
|
|
'4h': deque(maxlen=50)
|
|
}
|
|
|
|
def on_candle_5m(self, candle: Dict) -> Optional[MTSPrediction]:
|
|
self.buffers['5m'].append(candle)
|
|
|
|
# Agregar a TFs superiores si es momento
|
|
if self._is_15m_close():
|
|
self._aggregate_to_tf('15m')
|
|
if self._is_1h_close():
|
|
self._aggregate_to_tf('1h')
|
|
if self._is_4h_close():
|
|
self._aggregate_to_tf('4h')
|
|
|
|
# Predecir si tenemos suficientes datos
|
|
if len(self.buffers['5m']) >= 100:
|
|
df_5m = pd.DataFrame(list(self.buffers['5m']))
|
|
return self.model.predict(df_5m)
|
|
|
|
return None
|
|
```
|
|
|
|
### Caching de Aggregations
|
|
|
|
```python
|
|
# Cache TFs superiores (cambian menos frecuentemente)
|
|
@cached(ttl=60) # Cache por 1 minuto
|
|
def get_cached_1h_features(symbol: str) -> np.ndarray:
|
|
df = get_1h_data(symbol, bars=100)
|
|
return compute_features(df)
|
|
|
|
@cached(ttl=240) # Cache por 4 minutos
|
|
def get_cached_4h_features(symbol: str) -> np.ndarray:
|
|
df = get_4h_data(symbol, bars=50)
|
|
return compute_features(df)
|
|
```
|
|
|
|
### Performance
|
|
|
|
| Operacion | Tiempo | Notas |
|
|
|-----------|--------|-------|
|
|
| TF Aggregation | 10ms | 4 timeframes |
|
|
| Feature computation | 20ms | Per TF |
|
|
| Attention inference | 30ms | Hierarchical |
|
|
| XGBoost prediction | 5ms | 3 heads |
|
|
| **Total** | ~100ms | Full prediction |
|
|
|
|
---
|
|
|
|
## Referencias
|
|
|
|
- [ET-ML-001: Arquitectura ML Engine](./ET-ML-001-arquitectura.md)
|
|
- [ET-ML-010: PVA Strategy](./ET-ML-010-pva-strategy.md)
|
|
- [Hierarchical Attention Networks (Yang et al.)](https://www.cs.cmu.edu/~./hovy/papers/16HLT-hierarchical-attention-networks.pdf)
|
|
- [Multi-Scale Temporal Fusion](https://arxiv.org/abs/1912.09363)
|
|
|
|
---
|
|
|
|
**Autor:** ML-Specialist (NEXUS v4.0)
|
|
**Fecha:** 2026-01-25
|