---
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*
