Análisis de carteras en pandas: matrices de correlación y covarianza, volatilidad ponderada de la cartera y una simulación de reequilibrio
Calcula matrices de covarianza y correlación anualizadas a partir de rentabilidades, obtén con NumPy la volatilidad de la cartera y las contribuciones al riesgo, y simula la deriva frente al reequilibrio por calendario.
Qué aprenderás
- Cómo alinear varias series de precios en un único DataFrame de rentabilidades y calcular
.cov()y.corr()correctamente anualizados. - La fórmula matricial de la volatilidad de la cartera,
w.T @ Σ @ w, y cómo interpretar la contribución de cada activo al riesgo. - Cómo simular una cartera de comprar y mantener que deriva frente a otra reequilibrada por calendario.
- Qué trampas numéricas (fechas desalineadas, monedas mezcladas, sesgo de anticipación en la ventana de covarianza) producen respuestas erróneas.
Explicación
La correlación y el calor de la cartera (Gestión del riesgo y de las operaciones, lección 6), la combinación de dos sistemas (Trading sistemático y backtesting, lección 10) y las reglas de reequilibrio (ETF, fondos e inversión a largo plazo, lección 10) se enseñaron en otros cursos; esta lección los implementa en código para cualquier número de activos.
De los precios a una matriz de rentabilidades
Carga el cierre ajustado de cada instrumento (lección 4) en un único DataFrame, con una columna por ticker: prices = pd.concat(series_dict, axis=1). Los festivos que difieren entre mercados crean filas con NaN; decide explícitamente entre prices.dropna() (solo los días comunes) y prices.ffill() (arrastrar el último precio). Después, rets = prices.pct_change().dropna(). Convierte primero todo a una sola moneda; un ETF estadounidense en manos de un inversor en euros debe convertirse con la serie EUR/USD, o su volatilidad y sus correlaciones describirán algo equivocado.
Covarianza, correlación y anualización
rets.cov() es la matriz de covarianzas muestral de las rentabilidades diarias; multiplícala por 252 para anualizarla (la varianza escala con el tiempo). rets.corr() no tiene unidades y no necesita escalado. La diagonal contiene la varianza de cada activo, así que np.sqrt(np.diag(cov_a)) da las volatilidades anualizadas. La relación Σ_ij = ρ_ij × σ_i × σ_j te permite construir una matriz a partir de volatilidades y correlaciones para probar un escenario hipotético como «las correlaciones suben a 0.8 en una crisis».
Volatilidad de la cartera y contribuciones al riesgo
w = np.array([0.5, 0.3, 0.2]) # pesos, suman 1cov_a = rets.cov().values * 252port_var = w @ cov_a @ wport_vol = np.sqrt(port_var)marginal = cov_a @ w # d(var)/d(w)risk_contrib = w * marginal / port_var # proporciones que suman 1
@ es la multiplicación de matrices. risk_contrib te indica de qué fracción de la varianza de la cartera es responsable cada activo; suele estar lejos del peso en capital, y esa diferencia es el punto de partida de los presupuestos de riesgo (Construcción de carteras en profundidad, lección 1).
Una simulación de reequilibrio
Comprar y mantener deja que los pesos deriven: los ganadores pasan a ocupar una parte mayor. El reequilibrio por calendario restablece los objetivos en fechas fijas. En pandas, remuestrea las rentabilidades a la frecuencia de reequilibrio y recorre los periodos en un bucle:
period_rets = (1 + rets).resample('ME').prod() - 1 # rentabilidades mensualestarget = np.array([0.6, 0.4]); hold = 10_000 * target; path = []for _, r in period_rets.iterrows():hold = hold * (1 + r.values) # hacer crecer cada partepath.append(hold.sum())hold = hold.sum() * target # reequilibrar a los objetivos
Para la versión con deriva, elimina la última línea. Usa 'QE' para trimestral y 'YE' para anual (pandas 2.2 y posteriores; las versiones anteriores usan 'M', 'Q', 'A'). La rotación de un reequilibrio es abs(new_hold - old_hold).sum(); multiplícala por una tasa de coste, como el 0.1 %, y réstala. En una cuenta alemana sujeta a impuestos, el reequilibrio también realiza plusvalías; consulta el efecto fiscal con un Steuerberater (asesor fiscal).
Ejemplo práctico
Ejemplo hipotético con datos inventados; se excluyen comisiones, spreads e impuestos.
Parte 1: volatilidad con tres activos. Volatilidades anualizadas del 20 %, 10 % y 15 %; correlaciones ρ₁₂ = 0.2, ρ₁₃ = 0.6, ρ₂₃ = 0.1; pesos del 50 / 30 / 20 %.
- Covarianzas: Σ₁₂ = 0.2 × 0.20 × 0.10 = 0.0040; Σ₁₃ = 0.6 × 0.20 × 0.15 = 0.0180; Σ₂₃ = 0.1 × 0.10 × 0.15 = 0.0015. Diagonal: 0.0400, 0.0100, 0.0225.
- Varianza de la cartera = Σ wᵢ wⱼ Σᵢⱼ = 0.25 × 0.04 + 0.09 × 0.01 + 0.04 × 0.0225 + 2 × (0.5 × 0.3 × 0.004 + 0.5 × 0.2 × 0.018 + 0.3 × 0.2 × 0.0015) = 0.0100 + 0.0009 + 0.0009 + 2 × (0.0006 + 0.0018 + 0.00009) = 0.01678.
- Volatilidad de la cartera = √0.01678 = 12.95 %, frente a una media ponderada de las volatilidades del 16.0 %; la diferencia es el beneficio de la diversificación.
- Contribuciones al riesgo: el activo 1 soporta el 73.9 % de la varianza con el 50 % del capital; el activo 2, el 9.5 % con el 30 %; el activo 3, el 16.6 % con el 20 %.
Parte 2: deriva frente a reequilibrio. €10,000 repartidos 60 / 40 entre el activo A y el activo B. Rentabilidades anuales: A +20 %, −10 %, +15 %; B +2 %, +4 %, +1 %.
- Deriva: A: 6,000 × 1.20 × 0.90 × 1.15 = €7,452; B: 4,000 × 1.02 × 1.04 × 1.01 = €4,285.63. Total €11,737.63; el peso de A ha derivado hasta el 63.5 %.
- Reequilibrio anual: total del año 1 = 7,200 + 4,080 = €11,280 → se restablece a 6,768 / 4,512; año 2 = 6,091.20 + 4,692.48 = €10,783.68 → se restablece; año 3 = 7,440.74 + 4,356.61 = €11,797.35.
- El reequilibrio terminó €59.72 por encima porque vendió A tras el +20 % y volvió a comprar tras el −10 %. Con un A en tendencia constante, habría ganado la deriva; el reequilibrio controla el riesgo, no garantiza la rentabilidad.
Error frecuente
rets.cov() sobre 2015–2025 y usa el resultado para fijar los pesos en 2015 está usando información del futuro. Estima la covarianza en una ventana móvil o expansiva (rets.rolling(252).cov() o rets.loc[:date].cov()) y aplícala solo al periodo siguiente. Además, las correlaciones suben en las crisis, así que una matriz de un periodo tranquilo subestima el riesgo justo en el momento en que importa.Actividad práctica
En papel: dos activos con volatilidades anualizadas del 18 % y el 6 %, correlación de 0.3 y pesos del 70 / 30 %. (a) Construye la matriz de covarianzas de 2 × 2. (b) Calcula la varianza y la volatilidad de la cartera. (c) Calcula la contribución al riesgo de cada activo como proporción de la varianza. (d) Vuelve a calcular la volatilidad con una correlación de 0.9 y explica en una frase por qué esto importa.
Mostrar solución
(a) Σ₁₁ = 0.0324; Σ₂₂ = 0.0036; Σ₁₂ = 0.3 × 0.18 × 0.06 = 0.00324.
(b) Varianza = 0.49 × 0.0324 + 0.09 × 0.0036 + 2 × 0.7 × 0.3 × 0.00324 = 0.015876 + 0.000324 + 0.0013608 = 0.0175608; volatilidad = 13.25 %.
(c) Marginal: activo 1: 0.7 × 0.0324 + 0.3 × 0.00324 = 0.023652; activo 2: 0.7 × 0.00324 + 0.3 × 0.0036 = 0.003348. Contribuciones: 0.7 × 0.023652 / 0.0175608 = 94.3 %; 0.3 × 0.003348 / 0.0175608 = 5.7 %.
(d) Con ρ = 0.9: Σ₁₂ = 0.00972; varianza = 0.015876 + 0.000324 + 0.0040824 = 0.0202824; volatilidad = 14.24 %. El «diversificador» aporta poco cuando la correlación sube, que es justo lo que suele ocurrir en una ola de ventas; una cartera debe juzgarse con correlaciones de estrés, no solo con la media histórica.
Limitaciones: la covarianza muestral de unos pocos años de datos diarios es ruidosa; pequeños cambios en la ventana pueden mover las correlaciones 0.1 o más.
Ideas clave
- Alinea fechas y monedas antes de calcular rentabilidades; decide explícitamente cómo tratar los días faltantes.
- Anualiza la covarianza multiplicándola por los periodos por año; la correlación no necesita escalado.
- La volatilidad de la cartera es √(wᵀ Σ w); las contribuciones al riesgo w × (Σw) / varianza muestran dónde está realmente el riesgo.
- Simula el reequilibrio remuestreando las rentabilidades y restableciendo las posiciones; estima la covarianza solo con los datos disponibles en cada momento.
Siguiente paso
La lección 12 automatiza la rutina diaria: un script programado que descarga datos, calcula señales y escribe un informe, con las claves de API y los límites de solicitudes bien gestionados.
Autoevaluación
Responde a las preguntas y luego comprueba tus respuestas. Puedes volver a intentarlo tantas veces como quieras.
Autoevaluación automática para tu propio repaso. Tus respuestas se comprueban en tu navegador y no las vemos ni evaluamos. No es un examen ni una titulación.
Tu progreso
«Completada» solo significa que marcaste la lección como terminada. No es una prueba de tu comprensión. El progreso y las notas se guardan solo en este navegador y en este dispositivo, no en una cuenta.