--- id: "ET-ML-010" title: "PVA (Price Variation Attention) 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-010: PVA (Price Variation Attention) Strategy ## Metadata | Campo | Valor | |-------|-------| | **ID** | ET-ML-010 | | **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 PVA (Price Variation Attention) es un modelo hibrido que combina un **Transformer Encoder** para aprendizaje de representaciones y **XGBoost** para predicciones finales. El modelo predice la **direccion** y **magnitud** de variaciones de precio en un horizonte futuro. ### Caracteristicas Clave - **Diseno Time-Agnostic**: No usa features temporales (hora, dia) para evitar sobreajuste - **6 Modelos Independientes**: Un modelo por simbolo (XAUUSD, EURUSD, GBPUSD, USDJPY, BTCUSD, ETHUSD) - **Arquitectura Hibrida**: Transformer Encoder + XGBoost Head - **Prediction Targets**: Direccion (bullish/bearish) y magnitud del movimiento --- ## Arquitectura ### Diagrama de Alto Nivel ``` ┌─────────────────────────────────────────────────────────────────────────┐ │ PVA MODEL │ ├─────────────────────────────────────────────────────────────────────────┤ │ │ │ Input: OHLCV Sequence (seq_len x n_features) │ │ └── Returns, Acceleration, Volatility features │ │ │ │ │ ▼ │ │ ┌───────────────────────────────────────────────────────────────────┐ │ │ │ TRANSFORMER ENCODER │ │ │ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ │ │ │ │ Input Linear │──▶│ Positional │──▶│ Encoder │ │ │ │ │ │ Projection │ │ Encoding │ │ Layers (4) │ │ │ │ │ └──────────────┘ └──────────────┘ └──────────────┘ │ │ │ │ │ │ │ │ │ ▼ │ │ │ │ ┌──────────────────┐ │ │ │ │ │ Sequence Pooling │ │ │ │ │ │ (Mean + Last) │ │ │ │ │ └──────────────────┘ │ │ │ └───────────────────────────────────────────────────────────────────┘ │ │ │ │ │ ▼ │ │ ┌───────────────────────────────────────────────────────────────────┐ │ │ │ XGBOOST HEAD │ │ │ │ ┌──────────────────────┐ ┌──────────────────────┐ │ │ │ │ │ Direction Classifier │ │ Magnitude Regressor │ │ │ │ │ │ (binary: up/down) │ │ (absolute magnitude) │ │ │ │ │ └──────────────────────┘ └──────────────────────┘ │ │ │ └───────────────────────────────────────────────────────────────────┘ │ │ │ │ │ ▼ │ │ Output: PVAPrediction │ │ - direction: float (-1 to 1) │ │ - magnitude: float (absolute expected move) │ │ - confidence: float (0 to 1) │ └─────────────────────────────────────────────────────────────────────────┘ ``` ### Componentes del Transformer Encoder | Componente | Configuracion | |------------|---------------| | **Layers** | 4 encoder layers | | **d_model** | 256 | | **n_heads** | 8 attention heads | | **d_ff** | 1024 (feed-forward dimension) | | **dropout** | 0.1 | | **positional_encoding** | Sinusoidal | | **sequence_length** | 100 candles | ### Configuracion XGBoost | Parametro | Valor | |-----------|-------| | **n_estimators** | 200 | | **max_depth** | 6 | | **learning_rate** | 0.05 | | **subsample** | 0.8 | | **colsample_bytree** | 0.8 | | **reg_alpha** | 0.1 | | **reg_lambda** | 1.0 | --- ## Feature Engineering ### Diseno Time-Agnostic El modelo **no utiliza features temporales** (hora del dia, dia de la semana) para: - Evitar sobreajuste a patrones temporales especificos - Mejorar generalizacion a diferentes condiciones de mercado - Reducir el riesgo de concept drift ### Features Implementados ```python PVAFeatureConfig: return_periods: [1, 5, 10, 20] volatility_window: 20 stats_window: 50 sequence_length: 100 ``` #### 1. Return Features | Feature | Descripcion | Formula | |---------|-------------|---------| | `return_1` | Return 1 periodo | `(close / close.shift(1)) - 1` | | `return_5` | Return 5 periodos | `(close / close.shift(5)) - 1` | | `return_10` | Return 10 periodos | `(close / close.shift(10)) - 1` | | `return_20` | Return 20 periodos | `(close / close.shift(20)) - 1` | #### 2. Acceleration Features | Feature | Descripcion | Formula | |---------|-------------|---------| | `acceleration_1` | Cambio en momentum corto | `return_1 - return_1.shift(1)` | | `acceleration_5` | Cambio en momentum medio | `return_5 - return_5.shift(5)` | | `acceleration_20` | Cambio en momentum largo | `return_20 - return_20.shift(20)` | #### 3. Volatility Features | Feature | Descripcion | Formula | |---------|-------------|---------| | `volatility_returns` | Volatilidad de returns | `return_1.rolling(20).std()` | | `volatility_ratio` | Ratio volatilidad actual/promedio | `volatility / volatility.rolling(50).mean()` | | `range_volatility` | Volatilidad de rangos | `((high - low) / close).rolling(20).std()` | #### 4. Statistical Features | Feature | Descripcion | Formula | |---------|-------------|---------| | `return_skew` | Sesgo de returns | `return_1.rolling(50).skew()` | | `return_kurt` | Curtosis de returns | `return_1.rolling(50).kurt()` | | `zscore_return` | Z-score del return | `(return_1 - mean) / std` | --- ## Pipeline de Entrenamiento ### Flujo de Entrenamiento ``` ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ Data │───▶│ Feature │───▶│ Encoder │───▶│ XGBoost │ │ Loading │ │ Engineering │ │ Training │ │ Training │ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ │ ▼ ┌─────────────────┐ │ Validation & │ │ Model Saving │ └─────────────────┘ ``` ### Configuracion del Trainer ```python PVATrainerConfig: # Data timeframe: '5m' batch_size: 64 sequence_length: 100 target_horizon: 12 # candles ahead # Training encoder_epochs: 50 encoder_learning_rate: 1e-4 early_stopping_patience: 10 # Validation val_ratio: 0.15 walk_forward_splits: 5 min_train_size: 10000 ``` ### Walk-Forward Validation El modelo utiliza **walk-forward validation** para evaluar rendimiento: ``` Time ──────────────────────────────────────────────────────────────▶ Fold 1: [========= TRAIN =========][TEST] Fold 2: [============= TRAIN =============][TEST] Fold 3: [================= TRAIN =================][TEST] Fold 4: [===================== TRAIN =====================][TEST] Fold 5: [========================= TRAIN =========================][TEST] ``` **Caracteristicas:** - Expanding window (ventana creciente) - 5 folds por defecto - Gap opcional entre train y test - Metricas agregadas por fold --- ## Metricas de Evaluacion ### Metricas Primarias | Metrica | Descripcion | Target | |---------|-------------|--------| | **Direction Accuracy** | Precision en direccion (up/down) | >= 55% | | **Magnitude MAE** | Error absoluto medio en magnitud | Minimo | | **Directional Return** | Return promedio considerando direccion | > 0 | | **Sharpe Proxy** | `mean(signed_returns) / std(signed_returns)` | > 1.0 | ### Metricas Secundarias | Metrica | Descripcion | |---------|-------------| | **Encoder Loss** | MSE del autoencoder | | **Confidence Calibration** | Alineacion confianza vs accuracy | | **Per-Symbol Performance** | Metricas desglosadas por simbolo | --- ## API y Uso ### Clase Principal: PVAModel ```python from models.strategies.pva import PVAModel, PVAConfig # Configuracion config = PVAConfig( input_features=15, sequence_length=100, d_model=256, n_heads=8, n_layers=4, d_ff=1024, dropout=0.1, device='cuda' ) # Inicializar modelo model = PVAModel(config) # Entrenar encoder history = model.fit_encoder( X_train, y_train, X_val, y_val, epochs=50, batch_size=64 ) # Entrenar XGBoost metrics = model.fit_xgboost(X_train, y_train, X_val, y_val) # Prediccion predictions = model.predict(X_new) for pred in predictions: print(f"Direction: {pred.direction}, Magnitude: {pred.magnitude}") ``` ### Clase PVAPrediction ```python @dataclass class PVAPrediction: direction: float # -1 to 1 (bearish to bullish) magnitude: float # Expected absolute move confidence: float # 0 to 1 encoder_features: np.ndarray # Latent representation @property def expected_return(self) -> float: return self.direction * self.magnitude @property def signal_strength(self) -> float: return abs(self.direction) * self.confidence ``` ### Clase PVATrainer ```python from models.strategies.pva import PVATrainer, PVATrainerConfig # Configurar trainer config = PVATrainerConfig( timeframe='5m', sequence_length=100, target_horizon=12, encoder_epochs=50 ) trainer = PVATrainer(config) # Entrenar para un simbolo model, metrics = trainer.train( symbol='XAUUSD', start_date='2023-01-01', end_date='2024-12-31' ) # Walk-forward validation results = trainer.walk_forward_train('XAUUSD', n_folds=5) print(f"Avg Direction Accuracy: {results.avg_direction_accuracy:.2%}") # Guardar modelo trainer.save_model(model, 'XAUUSD', 'v1.0.0') ``` --- ## Estructura de Archivos ``` apps/ml-engine/src/models/strategies/pva/ ├── __init__.py ├── model.py # PVAModel, PVAConfig, PVAPrediction ├── feature_engineering.py # PVAFeatureEngineer, PVAFeatureConfig ├── trainer.py # PVATrainer, TrainingMetrics └── attention.py # PriceVariationAttention encoder ``` --- ## Consideraciones de Produccion ### GPU Acceleration ```python # Deteccion automatica de GPU device = 'cuda' if torch.cuda.is_available() else 'cpu' model = PVAModel(config, device=device) # XGBoost con GPU xgb_params = { 'tree_method': 'gpu_hist', 'device': 'cuda' } ``` ### Model Versioning ``` models/pva/{symbol}/{version}/ ├── encoder.pt # PyTorch encoder weights ├── xgb_direction.joblib # XGBoost direction classifier ├── xgb_magnitude.joblib # XGBoost magnitude regressor ├── config.json # Model configuration ├── metadata.json # Training metadata └── feature_names.json # Feature column names ``` ### Inference Batch Size | Escenario | Batch Size Recomendado | |-----------|------------------------| | Real-time single | 1 | | Backtesting | 256 | | Bulk inference | 1024 | --- ## Referencias - [ET-ML-001: Arquitectura ML Engine](./ET-ML-001-arquitectura.md) - [ET-ML-003: Feature Engineering](./ET-ML-003-features.md) - [ET-ML-015: Backtesting Framework](./ET-ML-015-backtesting-framework.md) - [Attention Is All You Need (Vaswani et al.)](https://arxiv.org/abs/1706.03762) --- **Autor:** ML-Specialist (NEXUS v4.0) **Fecha:** 2026-01-25