--- id: "ET-PFM-002" title: "Cálculo de Métricas de Portfolio" type: "Technical Specification" status: "Done" priority: "Alta" epic: "OQI-008" project: "trading-platform" version: "1.0.0" created_date: "2025-12-05" updated_date: "2026-01-04" --- # ET-PFM-002: Cálculo de Métricas de Portfolio **Épica:** OQI-008 - Portfolio Manager **Versión:** 1.0 **Fecha:** 2025-12-05 **Estado:** Planificado --- ## Métricas Implementadas ### Métricas Básicas (Todos los planes) - Total Value - Total P&L - Day P&L - Position Weights ### Métricas de Riesgo (Pro/Premium) - Volatilidad (std dev anualizada) - Beta vs S&P 500 - Maximum Drawdown - Value at Risk (VaR) 95% ### Métricas Avanzadas (Premium) - Sharpe Ratio - Sortino Ratio - Information Ratio - Calmar Ratio - VaR 99% --- ## Fórmulas de Cálculo ```typescript // src/modules/portfolio/services/metrics.service.ts @Injectable() export class MetricsService { // Volatilidad anualizada calculateVolatility(returns: number[]): number { const mean = returns.reduce((a, b) => a + b, 0) / returns.length; const variance = returns.reduce((sum, r) => sum + Math.pow(r - mean, 2), 0) / (returns.length - 1); const stdDev = Math.sqrt(variance); return stdDev * Math.sqrt(252); // Anualizar } // Sharpe Ratio calculateSharpe(returns: number[], riskFreeRate = 0.05): number { const annualReturn = this.calculateAnnualizedReturn(returns); const volatility = this.calculateVolatility(returns); return (annualReturn - riskFreeRate) / volatility; } // Value at Risk (método histórico) calculateVaR(returns: number[], confidence = 0.95): number { const sorted = [...returns].sort((a, b) => a - b); const index = Math.floor((1 - confidence) * sorted.length); return sorted[index]; } // Maximum Drawdown calculateMaxDrawdown(values: number[]): number { let peak = values[0]; let maxDD = 0; for (const value of values) { if (value > peak) peak = value; const drawdown = (peak - value) / peak; if (drawdown > maxDD) maxDD = drawdown; } return maxDD; } // Beta vs Benchmark calculateBeta( portfolioReturns: number[], benchmarkReturns: number[] ): number { const covariance = this.calculateCovariance( portfolioReturns, benchmarkReturns ); const benchmarkVariance = this.calculateVariance(benchmarkReturns); return covariance / benchmarkVariance; } } ``` --- ## Cache Strategy | Métrica | TTL | Trigger Update | |---------|-----|----------------| | Básicas | 15s | Price change | | Volatilidad | 1h | New trade | | Sharpe/Sortino | 1d | End of day | | VaR | 1h | New trade | --- ## Referencias - [RF-PFM-002: Análisis de Riesgo](../requerimientos/RF-PFM-002-analisis-riesgo.md) --- *Especificación técnica - Sistema NEXUS*