- 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>
24 KiB
24 KiB
| id | title | type | status | priority | epic | project | version | created_date | updated_date | task_reference |
|---|---|---|---|---|---|---|---|---|---|---|
| ET-ML-014 | MTS (Multi-Timeframe Synthesis) 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-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
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:
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:
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:
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:
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:
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:
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
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
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
# 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
# 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
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
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
@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
# 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
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
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
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
# 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-010: PVA Strategy
- Hierarchical Attention Networks (Yang et al.)
- Multi-Scale Temporal Fusion
Autor: ML-Specialist (NEXUS v4.0) Fecha: 2026-01-25