Sea P_t el precio de un activo en el tiempo t. Los retornos logarítmicos se definen como:
r_t = log(P_t / P_{t-1})
Estos retornos permiten modelar variaciones relativas del precio y son aditivos en el tiempo.
El Value at Risk mide la pérdida máxima esperada para un nivel de confianza dado alpha.
VaR_alpha = cuantil de orden (1 - alpha) de la distribución de los retornos
Interpretación: con probabilidad alpha la pérdida no excede el valor VaR.
El Expected Shortfall mide la pérdida promedio condicionada a que se supere el VaR.
ES_alpha = E[r | r <= VaR_alpha]
Esta medida captura mejor los eventos extremos que el VaR.
Se utilizan los retornos históricos para estimar cuantiles y promedios en la cola de pérdidas.
# Librerías
library(quantmod)
## Warning: package 'quantmod' was built under R version 4.4.3
## Cargando paquete requerido: xts
## Cargando paquete requerido: zoo
##
## Adjuntando el paquete: 'zoo'
## The following objects are masked from 'package:base':
##
## as.Date, as.Date.numeric
## Cargando paquete requerido: TTR
## Warning: package 'TTR' was built under R version 4.4.3
## Registered S3 method overwritten by 'quantmod':
## method from
## as.zoo.data.frame zoo
library(ggplot2)
## Warning: package 'ggplot2' was built under R version 4.4.3
# Descargar datos
getSymbols("USDCOP=X", src = "yahoo", from = "2020-01-01")
## Warning: USDCOP=X contains missing values. Some functions will not work if
## objects contain missing values in the middle of the series. Consider using
## na.omit(), na.approx(), na.fill(), etc to remove or replace them.
## [1] "USDCOP=X"
# Extraer precios de cierre
precios <- Cl(`USDCOP=X`)
# Data frame de precios
df_precios <- data.frame(
fecha = index(precios),
precio = as.numeric(precios)
)
# Graficar precios (corregido)
ggplot(df_precios, aes(x = fecha, y = precio)) +
geom_line() +
ggtitle("Serie de precios")
# Calcular retornos logarítmicos
retornos <- diff(log(precios))
retornos <- na.omit(retornos)
# Data frame de retornos
df_retornos <- data.frame(
fecha = index(retornos),
retorno = as.numeric(retornos)
)
# Graficar retornos
ggplot(df_retornos, aes(x = fecha, y = retorno)) +
geom_line() +
ggtitle("Retornos logarítmicos")
# Estimar media y varianza
media <- mean(df_retornos$retorno)
varianza <- var(df_retornos$retorno)
media
## [1] 7.708288e-05
varianza
## [1] 9.847159e-05
# Nivel de confianza
alpha <- 0.95
# VaR histórico
VaR <- quantile(df_retornos$retorno, probs = 1 - alpha)
VaR
## 5%
## -0.01482455
# Histograma con VaR
ggplot(df_retornos, aes(x = retorno)) +
geom_histogram(bins = 50) +
geom_vline(xintercept = VaR, linetype = "dashed") +
ggtitle("Distribución de retornos con VaR")
Sea un vector de retornos aleatorios R = (R_1, R_2, …, R_n)^T
El vector de medias es:
mu = E[R]
y la matriz de covarianzas es:
Sigma = Var(R)
Sea w = (w_1, w_2, …, w_n)^T el vector de pesos del portafolio
El retorno del portafolio es:
R_p = w^T R
El retorno esperado es:
E[R_p] = w^T mu
La varianza del portafolio está dada por:
Var(R_p) = w^T Sigma w
La desviación estándar es:
sigma_p = sqrt(w^T Sigma w)
Minimizar la varianza para un nivel de retorno esperado dado:
min w^T Sigma w
sujeto a:
w^T mu = mu_p
w^T 1 = 1
donde 1 es un vector de unos
La función Lagrangiana es:
L(w, lambda_1, lambda_2) = w^T Sigma w - lambda_1 (w^T mu - mu_p) - lambda_2 (w^T 1 - 1)
Condición de primer orden:
2 Sigma w - lambda_1 mu - lambda_2 1 = 0
De donde:
w = (1/2) Sigma^{-1} (lambda_1 mu + lambda_2 1)
Definiciones:
A = 1^T Sigma^{-1} 1
B = 1^T Sigma^{-1} mu
C = mu^T Sigma^{-1} mu
La varianza mínima para un retorno dado mu_p es:
sigma_p^2 = (A mu_p^2 - 2 B mu_p + C) / (A C - B^2)
w_gmv = Sigma^{-1} 1 / (1^T Sigma^{-1} 1)
Sea r_f la tasa libre de riesgo
El portafolio óptimo satisface:
w* proporcional a Sigma^{-1} (mu - r_f 1)
E[R_p] = r_f + ((E[R_m] - r_f) / sigma_m) sigma_p
Sea un vector de retornos aleatorios:
\[ R = (R_1, R_2, \dots, R_n)^T \]
El vector de medias es:
\[ \mu = \mathbb{E}[R] \]
La matriz de covarianzas es:
\[ \Sigma = \mathbb{E}[(R - \mu)(R - \mu)^T] \]
Sea el vector de pesos:
\[ w = (w_1, w_2, \dots, w_n)^T \]
El retorno del portafolio es:
\[ R_p = w^T R \]
El retorno esperado:
\[ \mathbb{E}[R_p] = w^T \mu \]
La varianza del portafolio es:
\[ \sigma_p^2 = w^T \Sigma w \]
Para dos activos, la varianza es:
\[ \sigma_p^2 = w_1^2 \sigma_1^2 + w_2^2 \sigma_2^2 + 2 w_1 w_2 \text{Cov}(R_1, R_2) \]
En términos de correlación:
\[ \sigma_p^2 = w_1^2 \sigma_1^2 + w_2^2 \sigma_2^2 + 2 w_1 w_2 \rho_{12} \sigma_1 \sigma_2 \]
La diversificación reduce el riesgo cuando:
\[ \rho_{12} < 1 \]
Minimizar el riesgo dado un retorno objetivo:
\[ \min_w \; w^T \Sigma w \]
sujeto a:
\[ w^T \mu = \mu_p \]
\[ w^T \mathbf{1} = 1 \]
Condición de primer orden:
\[ 2 \Sigma w - \lambda_1 \mu - \lambda_2 \mathbf{1} = 0 \]
Solución general:
\[ w = \frac{1}{2} \Sigma^{-1} (\lambda_1 \mu + \lambda_2 \mathbf{1}) \]
Definiciones:
\[ A = \mathbf{1}^T \Sigma^{-1} \mathbf{1} \]
\[ B = \mathbf{1}^T \Sigma^{-1} \mu \]
\[ C = \mu^T \Sigma^{-1} \mu \]
Varianza mínima para retorno dado:
\[ \sigma_p^2 = \frac{A \mu_p^2 - 2 B \mu_p + C}{A C - B^2} \]
\[ w_{gmv} = \frac{\Sigma^{-1} \mathbf{1}}{\mathbf{1}^T \Sigma^{-1} \mathbf{1}} \]
Sea \(r_f\), entonces:
\[ w^* \propto \Sigma^{-1} (\mu - r_f \mathbf{1}) \]
\[ \mathbb{E}[R_p] = r_f + \frac{\mathbb{E}[R_m] - r_f}{\sigma_m} \sigma_p \]
# Librerías
library(quantmod)
library(ggplot2)
library(quadprog)
# Descargar datos de varios activos
activos <- c("AAPL", "MSFT", "GOOG", "AMZN")
getSymbols(activos, src = "yahoo", from = "2020-01-01")
## [1] "AAPL" "MSFT" "GOOG" "AMZN"
# Precios de cierre ajustados
precios <- na.omit(merge(Cl(AAPL), Cl(MSFT), Cl(GOOG), Cl(AMZN)))
colnames(precios) <- activos
# Retornos logarítmicos
retornos <- na.omit(diff(log(precios)))
# Media y matriz de covarianza
mu <- colMeans(retornos)
Sigma <- cov(retornos)
# Número de activos
n <- length(mu)
# Función para calcular portafolio eficiente
frontera_eficiente <- function(mu, Sigma, n_port = 100) {
resultados <- data.frame(rend = numeric(), riesgo = numeric())
# Secuencia de retornos objetivo
target_returns <- seq(min(mu), max(mu), length.out = n_port)
for (r_obj in target_returns) {
Dmat <- 2 * Sigma
dvec <- rep(0, n)
Amat <- cbind(
rep(1, n), # suma de pesos = 1
mu # retorno objetivo
)
bvec <- c(1, r_obj)
sol <- solve.QP(Dmat, dvec, Amat, bvec, meq = 2)
w <- sol$solution
riesgo <- sqrt(t(w) %*% Sigma %*% w)
resultados <- rbind(resultados, c(r_obj, riesgo))
}
colnames(resultados) <- c("retorno", "riesgo")
return(resultados)
}
# Calcular frontera eficiente
frontera <- frontera_eficiente(mu, Sigma)
# Graficar frontera eficiente
ggplot(frontera, aes(x = riesgo, y = retorno)) +
geom_line() +
ggtitle("Frontera eficiente de Markowitz")
# Portafolio de mínima varianza global
uno <- rep(1, n)
w_gmv <- solve(Sigma) %*% uno / as.numeric(t(uno) %*% solve(Sigma) %*% uno)
w_gmv
## [,1]
## AAPL 0.28535501
## MSFT 0.37487519
## GOOG 0.24592296
## AMZN 0.09384684
# Riesgo y retorno del GMV
ret_gmv <- sum(w_gmv * mu)
riesgo_gmv <- sqrt(t(w_gmv) %*% Sigma %*% w_gmv)
ret_gmv
## [1] 0.000696512
riesgo_gmv
## [,1]
## [1,] 0.01713038
# Simulación para ver diversificación
set.seed(123)
n_sim <- 5000
pesos <- matrix(runif(n_sim * n), ncol = n)
pesos <- pesos / rowSums(pesos)
retornos_port <- pesos %*% mu
riesgos_port <- apply(pesos, 1, function(w) sqrt(t(w) %*% Sigma %*% w))
df_sim <- data.frame(
retorno = retornos_port,
riesgo = riesgos_port
)
# Graficar nube de portafolios + frontera
ggplot(df_sim, aes(x = riesgo, y = retorno)) +
geom_point(alpha = 0.3) +
geom_line(data = frontera, color = "blue") +
ggtitle("Diversificación de portafolios")
Un proceso estocástico \(X_t\) es continuo en media cuadrática si:
\[ \mathbb{E}[X_t^2] < \infty \]
y
\[ \lim_{s \to t} \mathbb{E}[(X_s - X_t)^2] = 0, \quad \forall t \geq 0 \]
Para el movimiento browniano \(B_t\):
\[ B_t \sim \mathcal{N}(0,t) \]
por lo tanto:
\[ \mathbb{E}[B_t^2] = t < \infty \]
Sean \(s,t \geq 0\) y supongamos \(s > t\). Entonces:
\[ B_s - B_t \sim \mathcal{N}(0, s - t) \]
y:
\[ \mathbb{E}[(B_s - B_t)^2] = \mathrm{Var}(B_s - B_t) = s - t \]
Tomando límite:
\[ \lim_{s \to t} \mathbb{E}[(B_s - B_t)^2] = \lim_{s \to t} (s - t) = 0 \]
Sea \(Y_t = f(B_t)\) con \(f\) Lipschitz, es decir:
\[ |f(x) - f(y)| \leq C |x - y| \]
Entonces:
\[ \mathbb{E}[(Y_s - Y_t)^2] = \mathbb{E}[(f(B_s) - f(B_t))^2] \]
Aplicando la condición Lipschitz:
\[ (f(B_s) - f(B_t))^2 \leq C^2 (B_s - B_t)^2 \]
Por lo tanto:
\[ \mathbb{E}[(Y_s - Y_t)^2] \leq C^2 \mathbb{E}[(B_s - B_t)^2] \]
Como:
\[ \mathbb{E}[(B_s - B_t)^2] = |s - t| \]
se tiene:
\[ \mathbb{E}[(Y_s - Y_t)^2] \leq C^2 |s - t| \]
y:
\[ \lim_{s \to t} \mathbb{E}[(Y_s - Y_t)^2] = 0 \]
Sea \(X_t\) continuo en media cuadrática en \([S,T]\).
Sea una partición:
\[ S = t_0 < t_1 < \cdots < t_n = T \]
Definimos la aproximación simple:
\[ \phi_n(t,\omega) = \sum_j X_{t_j}(\omega)\mathbf{1}_{[t_j, t_{j+1})}(t) \]
Por la isometría de Itô:
\[ \mathbb{E}\left[\left(\int_S^T X_t dB_t - \int_S^T \phi_n(t) dB_t \right)^2\right] = \mathbb{E}\left[\int_S^T (X_t - \phi_n(t))^2 dt\right] \]
Aplicando Fubini:
\[ \mathbb{E}\left[\int_S^T (X_t - \phi_n(t))^2 dt\right] = \int_S^T \mathbb{E}[(X_t - \phi_n(t))^2] dt \]
Esto equivale a:
\[ \int_S^T \mathbb{E}[(X_t - X_{t_j})^2] dt \]
Para \(t \in [t_j, t_{j+1})\).
Por continuidad en media cuadrática:
\[ \forall \epsilon > 0, \exists \delta > 0 \text{ tal que } |t - t_j| < \delta \Rightarrow \mathbb{E}[(X_t - X_{t_j})^2] < \epsilon \]
Si:
\[ \max \Delta t_j < \delta \]
entonces:
\[ \int_S^T \mathbb{E}[(X_t - \phi_n(t))^2] dt < \epsilon (T - S) \]
Por lo tanto:
\[ \lim_{n \to \infty} \mathbb{E}\left[\left(\int_S^T X_t dB_t - \int_S^T \phi_n(t) dB_t \right)^2\right] = 0 \]