trading-platform/docs/02-definicion-modulos/OQI-006-ml-signals/especificaciones/ET-ML-014-mts-strategy.md
Adrian Flores Cortes f1174723ed feat: Add comprehensive analysis and integration plan for trading-platform
- 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>
2026-01-26 16:40:56 -06:00

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


Autor: ML-Specialist (NEXUS v4.0) Fecha: 2026-01-25