title: “Cobertura con Futuros sobre Índice Bursátil”

author: Liz Johana Ramírez Castaño · José Manuel Sánchez Loaiza · Yonathan Álvarez

date: ‘Fecha inicial de inversión: 30 de abril de 2026’

always_allow_html: true

output:

html_document:

theme: flatly

highlight: tango

toc: yes

toc_float:

  collapsed: no

  smooth_scroll: yes

toc_depth: 4

number_sections: yes

df_print: paged

code_folding: hide

subtitle: ‘Portafolio: PG · SYK · WM | Capital: USD 20,000,000’



Introducción

Este informe presenta y evalúa una estrategia de cobertura e inversión para la administración de un capital de 20 millones de dólares, con un horizonte temporal de cuatro años a partir del 30 de abril de 2026. Con el objetivo de optimizar la relación riesgo-retorno, se diseñó una cartera de renta variable compuesta por tres activos del índice S&P 500, seleccionados por su solidez corporativa y diversificación sectorial: para tener un capital de 20 millones de dólares, con un plazo de cuatro años a partir del 30 de abril de 2026. Para optimizar la relación riesgo-retorno, se conformó una cartera de renta variable con tres activos del índice S&P 500. Estos activos fueron seleccionados por su solidez corporativa y diversificación sectorial: • PG — Procter & Gamble (Consumo básico defensivo) • SYK — Stryker Corporation (Sector salud / dispositivos médicos) • WM — Waste Management (Servicios ambientales) Con el objetivo de reducir la exposición al riesgo sistémico del mercado, se pone en práctica una estrategia de inmunización a través de contratos de futuros E-mini S&P 500 (ES) que se negocian en el Chicago Mercantile Exchange (CME Group). El desarrollo de este trabajo se basa en la teoría de Markowitz (1952) sobre selección de portafolios y el modelo CAPM de Sharpe (1964) para calcular las sensibilidades (Betas), así como en los fundamentos de cobertura óptima con derivados propuestos por Hull (2022)


Objetivo

Estructurar un portafolio accionario óptimo con PG (Procter & Gamble), SYK (Stryker) y WM (Waste Management), pertenecientes al S&P 500, y evaluar una estrategia de cobertura y gestión del riesgo mediante futuros E-mini S&P 500 con horizonte de cuatro años.


1 Parámetros Globales

CAPITAL       <- 20e6

FECHA_INI     <- as.Date("2026-04-30")

FECHA_HIST    <- as.Date("2016-04-30")   # 10 años históricos

TICKERS       <- c("PG", "SYK", "WM")

INDICE        <- "^GSPC"

N_ANUAL       <- 252                     # días hábiles

# Tasa libre de riesgo: ^FVX (CBOE 5-Year Treasury Note Index)
# Proxy del rango 3-5 años especificado en el enunciado.
# Fuente: Yahoo Finance getSymbols("^FVX") al 30/04/2026
RF_ANUAL      <- 0.0418                  # ^FVX al 30/04/2026 (~4.18% anual)

HORIZONTE     <- 4                       # años

N_MESES       <- HORIZONTE * 12          # 48 meses

N_MES         <- 21                      # días hábiles por mes

N_SIM         <- 5000                    # simulaciones GBM

# Contrato E-mini S&P 500 (CME) — datos al 30/04/2026

MULTIPLICADOR      <- 50

MARGEN_INI         <- 14000

MARGEN_MANT        <- 12700

precio_futuro_ini  <- 7168   # Precio F₀ CME al 30/04/2026

# Dividendos anuales aproximados (yield publicado por cada empresa)

DIV_PG  <- 0.024   # 2.4% anual

DIV_SYK <- 0.010   # 1.0% anual

DIV_WM  <- 0.015   # 1.5% anual

params_df <- data.frame(

  Parámetro = c("Capital inicial","Fecha inicial","Horizonte","Tickers",

                "Índice","Días hábiles/año","Tasa libre de riesgo (^FVX 5Y)",

                "Multiplicador E-mini","Margen inicial/contrato",

                "Margen mantenimiento/contrato","Precio futuro inicial (F₀)"),

  Valor = c(

    dollar(CAPITAL), as.character(FECHA_INI),

    paste(HORIZONTE,"años"), paste(TICKERS, collapse=" · "),

    "S&P 500 (^GSPC)", N_ANUAL,

    paste0(RF_ANUAL*100,"% anual"),

    paste0("USD ",MULTIPLICADOR," / punto"),

    dollar(MARGEN_INI), dollar(MARGEN_MANT),

    paste(precio_futuro_ini,"puntos")

  )

)

kable(params_df, align=c("l","r"), caption="Tabla 1. Parámetros globales del ejercicio") %>%

  kable_styling(bootstrap_options=c("striped","hover","condensed"), full_width=FALSE) %>%

  row_spec(0, background="#003087", color="white")
Tabla 1. Parámetros globales del ejercicio
Parámetro Valor
Capital inicial $20,000,000
Fecha inicial 2026-04-30
Horizonte 4 años
Tickers PG · SYK · WM
Índice S&P 500 (^GSPC)
Días hábiles/año 252
Tasa libre de riesgo (^FVX 5Y) 4.18% anual
Multiplicador E-mini USD 50 / punto
Margen inicial/contrato $14,000
Margen mantenimiento/contrato $12,700
Precio futuro inicial (F₀) 7168 puntos

El Parámetro Valor Capital inicial $20,000,000 Fecha inicial 2026 04 30 Horizonte 4 años Tickers PG · SYK · WM Índice S&P 500 (^GSPC) Días hábiles/año 252 Tasa libre de riesgo (^FVX 5Y) 4.18% anual Multiplicador E-mini USD 50 / punto Margen inicial/contrato $14,000 Margen mantenimiento/contrato $12,700 Precio futuro inicial (F₀) 7168 puntosTasa libre de riesgo — ^FVX: El CBOE Interest Rate 5-Year Treasury Note Index (proxy del rango 3–5 años indicado en el enunciado) reportó una tasa de 4.18% anual al 30 de abril de 2026, extraída de Yahoo Finance. Se prefiere el vencimiento de 5 años por ser el más cercano al horizonte de inversión de 4 años del ejercicio. Esta tasa se usa como referencia para el Sharpe Ratio y el valor esperado de la cobertura (Hull, 2022)


2 Análisis Fundamental de las Acciones

El proceso de incorporación de activos al portafolio se estructuró:

  1. Con Base en la optimización de riesgo-retorno, rigiéndose por tres directrices fundamentales:
  2. Diversificación sectorial real dentro del S&P 500.
  3. Estabilidad financiera medida por flujo de caja libre positivo y dividendos
  4. consistentes.
  5. Sensibilidades distintas al ciclo económico para maximizar los beneficios de la diversificación.

2.1 Procter & Gamble (PG) — Consumo Básico Defensivo

PG The Procter & Gamble Company | NYSE | S&P 500

PG The Procter & Gamble Company | NYSE | S&P 500, Procter & Gamble es una de las empresas más grandes en el sector de bienes de consumo en todo el mundo. Opera en más de 180 países y tiene una variedad de productos que generan ingresos. Su negocio se divide en varias áreas, como cuidado del hogar, telas, cuidado familiar, cuidado femenino, belleza, salud y afeitado. El cuidado del hogar y de telas es el que más aporta a sus ventas. La empresa tiene una buena capacidad para generar dinero y mantener una buena situación financiera. Ha tenido márgenes de ganancia superiores al 20% y genera lrededor de 14 mil millones de dólares al año en flujo de caja libre. Procter & Gamble ha distribuido dividendos a sus accionistas durante más de 65 años, lo que la posiciona como una opción estable para inversores con horizontes de largo plazo. La deuda de la empresa se mantiene en niveles manejables respecto a sus ganancias. Entre 2020 y 2026, la compañía registró un crecimiento moderado pero constante, incluso en contextos de incertidumbre económica, manteniendo un perfil defensivo en el mercado. Opción estable para los inversores que buscan una inversión a largo plazo. La deuda de la empresa es manejable en comparación con sus ganancias. Entre 2020 y 2026, Procter & Gamble creció de manera moderada pero constante, incluso en momentos de incertidumbre económica. Su comportamiento en el mercado es defensivo. Para 2027, se proyecta una mejora en la situación de la empresa, con expectativas de recuperación frente a las recientes presiones inflacionarias y un incremento en los márgenes de ganancia. En este contexto, algunos analistas estiman que el precio de las acciones de Procter & Gamble podría situarse entre 170 y 190 dólares en el segundo trimestre de 2027.

2.2 Stryker Corporation (SYK) — Dispositivos Médicos

SYK Stryker Corporation | NYSE | S&P 500

La empresa Stryker Corporation es un líder en tecnología médica. Se enfoca en dispositivos quirúrgicos, implantes ortopédicos y cirugía robótica asistida con su plataforma Mako. La empresa tiene una buena distribución de ingresos entre dos sectores: MedSurg & Neurotechnology y Orthopaedics & Spine. El segmento robótico es el que más crece y da más ingresos. La empresa tiene una buena situación financiera. Ha crecido un 8% al 12% cada año.

En los últimos cinco años. Esto se debe a que la población envejece y hay más procedimientos electivos. Cuenta con un buen margen operativo y un nivel de deuda manejable. La acción ha subido en el mercado secundario, ha superado la volatilidad de los años 2020-2022 y ha mantenido una tendencia alcista. Los analistas proyectan que el precio de la acción llegará a entre USD 420 y USD 470 para el segundo trimestre de 2027.

2.3 Waste Management (WM) — Servicios Ambientales

WM Waste Management, Inc. | NYSE | S&P 500

Es la empresa líder en servicios ambientales en Norteamérica, se enfoca en recoger, reciclar y disponer de residuos de manera responsable. Su éxito se basa en contratos a largo plazo y en importantes activos, como vertederos exclusivos, esto le brinda una fuente estable de ingresos. Cuenta con márgenes de beneficio muy altos, superiores al 30% y un flujo de caja sólido.

La empresa ha incrementado sus dividendos durante más de 20 años consecutivos. En el mercado bursátil, ha registrado un rendimiento acumulado cercano al 380% en los últimos años, lo que demuestra su capacidad para mantener la estabilidad incluso durante periodos de declive del mercado. Actualmente, Waste Management expande su capacidad en reciclaje avanzado y capitaliza oportunidades en contratos de gas de vertedero


3 Datos Históricos y Retornos

3.1 Metodología de datos y calidad

Fuente de datos: Yahoo Finance vía paquete quantmod en R (Keitt, 2023).

Se utilizan precios ajustados por dividendos y splits (columna Ad()), lo que garantiza que los retornos calculados incorporan el retorno total del accionista (apreciación de capital + dividendos reinvertidos). Este tratamiento es coherente con la práctica estándar en gestión de portafolios (Sharpe, 1964; Hull, 2022).

Período histórico: 10 años: 30 de abril de 2016 al 30 de abril de 2026. Frecuencia: Diaria. Se eliminan observaciones con valores faltantes mediante na.omit().

Tratamiento de dividendos: Al usar precios ajustados, los dividendos ya están implícitos en los retornos calculados. No se deben sumar nuevamente para evitar doble conteo. En la sección de rendimiento esperado se desglosa el efecto de los dividendos sobre el retorno total de cada acción.

3.2 Descarga y verificación de precios

descargar <- function(tickers, desde, hasta) {

  lst <- lapply(tickers, function(tk) {

    tryCatch({

      raw <- getSymbols(tk, src="yahoo", from=desde, to=hasta,

                        auto.assign=FALSE, warnings=FALSE)

      Ad(raw)

    }, error=function(e) { message("Error: ",tk); NULL })

  })

  names(lst) <- tickers

  lst <- lst[!sapply(lst, is.null)]

  do.call(merge, lst)

}

precios_acc <- descargar(TICKERS, FECHA_HIST, FECHA_INI)

precios_idx <- descargar(INDICE,  FECHA_HIST, FECHA_INI)

colnames(precios_acc) <- TICKERS

colnames(precios_idx) <- "GSPC"

datos <- na.omit(merge(precios_acc, precios_idx))

# Verificación de calidad de datos

cat("══════════════════════════════════════════════════════\n")
## ══════════════════════════════════════════════════════
cat(sprintf("  Observaciones totales   : %d días hábiles\n",   nrow(datos)))
##   Observaciones totales   : 2513 días hábiles
cat(sprintf("  Fecha inicial efectiva  : %s\n", as.character(index(datos)[1])))
##   Fecha inicial efectiva  : 2016-05-02
cat(sprintf("  Fecha final efectiva    : %s\n", as.character(tail(index(datos),1))))
##   Fecha final efectiva    : 2026-04-29
cat(sprintf("  Años cubiertos          : %.1f años\n",

            as.numeric(diff(range(index(datos))))/365.25))
##   Años cubiertos          : 10.0 años
cat(sprintf("  Valores NA eliminados   : 0 (post na.omit)\n"))
##   Valores NA eliminados   : 0 (post na.omit)
cat(sprintf("  Tickers descargados     : %s\n", paste(colnames(datos), collapse=", ")))
##   Tickers descargados     : PG, SYK, WM, GSPC
cat("══════════════════════════════════════════════════════\n")
## ══════════════════════════════════════════════════════
# Precios iniciales y finales

p_ini <- as.numeric(datos[1, TICKERS])

p_fin <- as.numeric(tail(datos[, TICKERS], 1))

cal_df <- data.frame(

  Acción = TICKERS,

  `Precio Inicial (USD)` = round(p_ini, 2),

  `Precio Final (USD)`   = round(p_fin, 2),

  `Retorno Total (%)`    = round((p_fin/p_ini - 1)*100, 2),

  check.names = FALSE

)

kable(cal_df, caption="Tabla 2. Precios ajustados inicio/fin del período de 10 años") %>%

  kable_styling(bootstrap_options=c("striped","hover","condensed"), full_width=FALSE)
Tabla 2. Precios ajustados inicio/fin del período de 10 años
Acción Precio Inicial (USD) Precio Final (USD) Retorno Total (%)
PG 61.64 146.46 137.60
SYK 98.37 315.13 220.34
WM 49.97 230.31 360.92

3.3 Evolución de precios (base 100)

df_norm <- as.data.frame(datos[, TICKERS])

df_norm <- sweep(df_norm, 2, as.numeric(df_norm[1,]), "/") * 100

df_norm$fecha <- index(datos)

df_long <- pivot_longer(df_norm, -fecha, names_to="Accion", values_to="Precio")

# Añadir anotaciones de eventos clave

eventos <- data.frame(

  fecha = as.Date(c("2020-03-23","2022-01-03","2022-12-30")),

  label = c("Mín. COVID-19","Inicio alza\ntasas Fed","Fin ciclo\nalcista tasas")

)

p1 <- ggplot(df_long, aes(x=fecha, y=Precio, color=Accion)) +

  geom_vline(data=eventos, aes(xintercept=fecha), linetype="dotted",

             color="gray50", alpha=0.7) +

  geom_line(linewidth=0.75) +

  geom_text(data=eventos, aes(x=fecha, y=Inf, label=label),

            vjust=1.3, size=2.8, color="gray40", angle=90, hjust=1,

            inherit.aes=FALSE) +

  scale_color_manual(values=c(PG="#003087", SYK="#E31837", WM="#00703C")) +

  scale_x_date(date_breaks="1 year", date_labels="%Y") +

  geom_hline(yintercept=100, linetype="dashed", color="gray60") +

  labs(title="Figura 1. Evolución de precios históricos (base 100 = abril 2016)",

       subtitle="Precios ajustados por dividendos y splits | Fuente: Yahoo Finance",

       x=NULL, y="Precio normalizado (base 100)", color="Acción",

       caption="Datos históricos: 10 años hasta 30/04/2026") +

  theme_minimal(base_size=12) +

  theme(legend.position="bottom", axis.text.x=element_text(angle=45, hjust=1))

ggplotly(p1) %>% layout(hovermode="x unified")

Interpretación:

Waste Management encabeza el crecimiento acumulado (≈480 base 100), lo que confirma su mayor retorno dentro del grupo y una volatilidad moderada. Stryker muestra una alta volatilidad, aunque con rápidas recuperaciones tras las crisis. Procter & Gamble exhibe el comportamiento más defensivo, con caídas limitadas durante la pandemia de COVID-19 y la corrección de 2022, validando su función como activo refugio en el portafolio. mayor retorno del grupo con volatilidad moderada. SYK muestra alta volatilidad pero con recuperaciones rápidas post-crisis. PG presenta el comportamiento más defensivo, con caídas limitadas durante COVID-19 y la corrección de 2022, validando su rol de activo de refugio en el portafolio.

3.4 Retornos y estadísticas descriptivas anualizadas

ret_d    <- na.omit(diff(log(datos)))

ret_acc  <- ret_d[, TICKERS]

ret_idx  <- ret_d[, "GSPC"]

mu_anual  <- colMeans(ret_acc)  * N_ANUAL

sd_anual  <- apply(ret_acc, 2, sd) * sqrt(N_ANUAL)

cov_anual <- cov(ret_acc) * N_ANUAL

cor_mat   <- cor(ret_acc)

# Estadísticas completas

skew_v <- sapply(TICKERS, function(tk) {

  r <- as.numeric(ret_acc[,tk])

  mean((r - mean(r))^3) / sd(r)^3

})

kurt_v <- sapply(TICKERS, function(tk) {

  r <- as.numeric(ret_acc[,tk])

  mean((r - mean(r))^4) / sd(r)^4 - 3

})

est_df <- data.frame(

  Acción              = TICKERS,

  `μ diario (%)`      = round(colMeans(ret_acc)*100, 4),

  `μ anual (%)`       = round(mu_anual*100, 2),

  `σ diaria (%)`      = round(apply(ret_acc,2,sd)*100, 4),

  `σ anual (%)`       = round(sd_anual*100, 2),

  `Sesgo`             = round(skew_v, 3),

  `Curtosis exceso`   = round(kurt_v, 3),

  check.names         = FALSE

)

kable(est_df, align="c", digits=4,

      caption="Tabla 3. Estadísticas de retornos diarios y anualizados (N=252)") %>%

  kable_styling(bootstrap_options=c("striped","hover","condensed"), full_width=FALSE) %>%

  column_spec(3, bold=TRUE, color="darkblue") %>%

  column_spec(5, bold=TRUE, color="darkred") %>%

  row_spec(0, background="#003087", color="white")
Tabla 3. Estadísticas de retornos diarios y anualizados (N=252)
Acción μ diario (%) μ anual (%) σ diaria (%) σ anual (%) Sesgo Curtosis exceso
PG PG 0.0345 8.68 1.1909 18.90 -0.079 10.678
SYK SYK 0.0463 11.68 1.6470 26.15 -0.311 11.223
WM WM 0.0608 15.33 1.2260 19.46 -0.556 12.263

Proceso de anualización:

Siguiendo la metodología estándar de gestión de portafolios (Bodie et al., 2021), los retornos diarios se anualizan al multiplicar la media por 252 días laborables y la volatilidad por √252.

Un punto crítico aquí es que los tres activos presentan curtosis positiva y sesgo negativo. Esto nos confirma que estamos ante distribuciones con colas pesadas (eventos extremos más frecuentes de lo normal). Por esta razón, no basta con el VaR paramétrico; se vuelve indispensable cruzar los resultados con simulaciones de Monte Carlo y el VaR histórico para tener una métrica de riesgo real

3.5 Matrices de covarianzas y correlaciones

kable(round(cov_anual*1e4, 4),

      caption="Tabla 4. Matriz de covarianzas anualizadas (×10⁴)") %>%

  kable_styling(bootstrap_options=c("striped","hover","condensed"), full_width=FALSE)
Tabla 4. Matriz de covarianzas anualizadas (×10⁴)
PG SYK WM
PG 357.3684 192.6064 183.2492
SYK 192.6064 683.5976 239.2142
WM 183.2492 239.2142 378.7501
kable(round(cor_mat, 4),

      caption="Tabla 5. Matriz de correlaciones entre retornos diarios") %>%

  kable_styling(bootstrap_options=c("striped","hover","condensed"), full_width=FALSE)
Tabla 5. Matriz de correlaciones entre retornos diarios
PG SYK WM
PG 1.0000 0.3897 0.4981
SYK 0.3897 1.0000 0.4701
WM 0.4981 0.4701 1.0000
corrplot(cor_mat, method="color", type="upper", tl.col="black",

         tl.srt=45, addCoef.col="black", number.cex=1.2,

         col=colorRampPalette(c("#E31837","white","#003087"))(200),

         mar=c(0,0,2,0), title="Figura 2. Correlaciones entre retornos diarios")

Interpretación:

Las correlaciones son positivas pero moderadas (0.39–0.50). Ninguna supera 0.50, lo que garantiza beneficios reales de diversificación. La correlación más baja (PG-SYK = 0.39) es la combinación más valiosa para reducir riesgo, dado que los ciclos de consumo básico y dispositivos médicos responden de manera diferencial a los mismos shocks macroeconómicos. La covarianza más alta de SYK (diagonal) confirma que es el activo de mayor riesgo propio.


4 Optimización Media-Varianza

4.1 Marco teórico

Problema de optimización (Markowitz, 1952):

\[\min_w \; w^\top \Sigma w \quad \text{s.a.} \quad w^\top \mu = \mu^* \;, \quad \mathbf{1}^\top w = 1 \;, \quad w_i \geq 0\]

Sharpe Ratio (Sharpe, 1964):

\[SR = \frac{\mu_p - r_f}{\sigma_p}\]

4.2 Frontera eficiente

n <- length(TICKERS)

mu_seq   <- seq(min(mu_anual), max(mu_anual), length.out=300)

frontera <- data.frame(mu=numeric(0), sigma=numeric(0))

for (mu_t in mu_seq) {

  tryCatch({

    Dmat <- 2*cov_anual; dvec <- rep(0,n)

    Amat <- cbind(rep(1,n), mu_anual, diag(n))

    bvec <- c(1, mu_t, rep(0,n))

    sol  <- solve.QP(Dmat, dvec, Amat, bvec, meq=2)

    w    <- sol$solution

    if (all(w >= -1e-8) && abs(sum(w)-1) < 1e-6) {

      sp <- sqrt(as.numeric(t(w) %*% cov_anual %*% w))

      frontera <- rbind(frontera, data.frame(mu=mu_t, sigma=sp))

    }

  }, error=function(e) NULL)

}

# Portafolio máximo Sharpe (tangencia)

sharpe_v <- (frontera$mu - RF_ANUAL) / frontera$sigma

idx_opt  <- which.max(sharpe_v)

mu_opt   <- frontera$mu[idx_opt]

Dmat <- 2*cov_anual; dvec <- rep(0,n)

Amat <- cbind(rep(1,n), mu_anual, diag(n))

bvec <- c(1, mu_opt, rep(0,n))

sol_opt    <- solve.QP(Dmat, dvec, Amat, bvec, meq=2)

w_opt      <- sol_opt$solution / sum(sol_opt$solution)

names(w_opt) <- TICKERS

mu_port    <- as.numeric(t(w_opt) %*% mu_anual)

sigma_port <- as.numeric(sqrt(t(w_opt) %*% cov_anual %*% w_opt))

sharpe_opt <- (mu_port - RF_ANUAL) / sigma_port

monto_opt  <- w_opt * CAPITAL

# Mínima varianza

idx_mv   <- which.min(frontera$sigma)

mu_mv    <- frontera$mu[idx_mv]

sigma_mv <- frontera$sigma[idx_mv]

cat(sprintf("✔ Retorno portafolio óptimo : %.2f%% anual\n", mu_port*100))
## ✔ Retorno portafolio óptimo : 15.22% anual
cat(sprintf("✔ Volatilidad portafolio    : %.2f%% anual\n", sigma_port*100))
## ✔ Volatilidad portafolio    : 19.26% anual
cat(sprintf("✔ Sharpe Ratio              : %.4f\n", sharpe_opt))
## ✔ Sharpe Ratio              : 0.5732

4.3 Gráfico de la frontera eficiente

pts_acc <- data.frame(

  ticker = TICKERS,

  sigma  = sqrt(diag(cov_anual))*100,

  mu     = mu_anual*100

)

cml_x  <- seq(0, max(frontera$sigma)*1.15, length.out=100)

cml_y  <- RF_ANUAL + sharpe_opt * cml_x

cml_df <- data.frame(sigma=cml_x*100, mu=cml_y*100)

p2 <- ggplot() +

  geom_line(data=cml_df, aes(x=sigma, y=mu),

            color="darkorange", linetype="dashed", linewidth=1.1) +

  geom_path(data=data.frame(sigma=frontera$sigma*100, mu=frontera$mu*100),

            aes(x=sigma, y=mu), color="steelblue", linewidth=1.8) +

  geom_point(data=pts_acc, aes(x=sigma, y=mu, color=ticker), size=5, shape=17) +

  geom_label_repel(data=pts_acc, aes(x=sigma, y=mu, label=ticker, color=ticker),

                   fontface="bold", size=4, show.legend=FALSE, nudge_y=0.4) +

  geom_point(aes(x=sigma_mv*100, y=mu_mv*100), color="purple", size=4, shape=15) +

  annotate("text", x=sigma_mv*100+0.3, y=mu_mv*100-0.4,

           label="Mín. Varianza", color="purple", size=3.2, hjust=0) +

  geom_point(aes(x=sigma_port*100, y=mu_port*100), color="red", size=7, shape=18) +

  annotate("label", x=sigma_port*100+0.3, y=mu_port*100+0.5,

           label=sprintf("Portafolio Óptimo\nSharpe=%.3f", sharpe_opt),

           color="red", size=3.2, hjust=0, fill="white", label.size=0.3) +

  geom_point(aes(x=0, y=RF_ANUAL*100), color="black", size=3) +

  annotate("text", x=0.2, y=RF_ANUAL*100+0.2,

           label=sprintf("rf = %.2f%%", RF_ANUAL*100), size=3, hjust=0) +

  scale_color_manual(values=c(PG="#003087", SYK="#E31837", WM="#00703C")) +

  scale_x_continuous(labels=function(x) paste0(x,"%"), limits=c(0, NA)) +

  scale_y_continuous(labels=function(x) paste0(x,"%")) +

  labs(

    title    = "Figura 3. Frontera Eficiente — PG, SYK, WM (S&P 500)",

    subtitle = sprintf("Portafolio óptimo: mu=%.2f%% | sigma=%.2f%% | Sharpe=%.4f | rf=%.2f%%",

                       mu_port*100, sigma_port*100, sharpe_opt, RF_ANUAL*100),

    x="Riesgo — Desviación estándar anual (%)", y="Retorno esperado anual (%)",

    color="Acción",

    caption="Línea naranja: Capital Market Line | ◆ Portafolio tangente | ■ Mínima varianza"

  ) +

  theme_minimal(base_size=13) +

  theme(legend.position="bottom",

        plot.title=element_text(face="bold", color="#003087"))

ggplotly(p2)

Interpretación:

El análisis de optimización de portafolio para las acciones de Procter & Gamble (PG), SEl análisis de optimización del portafolio con acciones de Procter & Gamble (PG), Stryker (SYK) y Waste Management (WM) muestra los siguientes puntos clave:. El caso más evidente es SYK (triángulo rojo), que presenta un riesgo elevado (cercano al 26% de desviación estándar) para un retorno de apenas el 12%.

Portafolio de Mínima Varianza (Cuadrado Morado): Representa la combinación de activos que minimiza el riesgo total. Se ubica en una volatilidad aproximada del 16% con un rendimiento esperado del 11.5%, ideal para un perfil marcadamente conservador.

Portafolio Óptimo de Mercado (Diamante Rojo): Es el punto de tangencia con la línea de asignación de capital (que arranca desde la tasa libre de riesgo, \(rf = 4.18\%\)). Este portafolio maximiza el Ratio de Sharpe, ofreciendo la mejor relación riesgo-beneficio: un retorno óptimo cercano al 15.5% con un riesgo controlado del 19%.


4.4 Pesos óptimos y asignación de capital

pesos_df <- data.frame(

  Acción          = TICKERS,

  `Peso (%)`      = round(w_opt*100, 2),

  `Monto (USD)`   = dollar(round(monto_opt)),

  `μ anual (%)`   = round(mu_anual*100, 2),

  `σ anual (%)`   = round(sd_anual*100, 2),

  `Div. Yield (%)` = c(DIV_PG*100, DIV_SYK*100, DIV_WM*100),

  check.names     = FALSE

)

kable(pesos_df, align=c("l","c","r","c","c","c"),

      caption="Tabla 6. Pesos óptimos y asignación de capital (USD 20,000,000)") %>%

  kable_styling(bootstrap_options=c("striped","hover","condensed"), full_width=FALSE) %>%

  row_spec(which.max(w_opt), bold=TRUE, background="#eef4fb") %>%

  row_spec(0, background="#003087", color="white")
Tabla 6. Pesos óptimos y asignación de capital (USD 20,000,000)
Acción Peso (%) Monto (USD) μ anual (%) σ anual (%) Div. Yield (%)
PG PG 0.00 $0 8.68 18.90 2.4
SYK SYK 3.05 $609,088 11.68 26.15 1.0
WM WM 96.95 $19,390,912 15.33 19.46 1.5
cat(sprintf("\nRetorno esperado portafolio : %.4f%% anual\n", mu_port*100))
## 
## Retorno esperado portafolio : 15.2181% anual
cat(sprintf("Desviación estándar         : %.4f%% anual\n", sigma_port*100))
## Desviación estándar         : 19.2560% anual
cat(sprintf("Sharpe Ratio                : %.4f\n", sharpe_opt))
## Sharpe Ratio                : 0.5732

Nota sobre la concentración del portafolio: El modelo de media-varianza sin restricciones tiende a concentrar el capital en el activo de mayor eficiencia histórica. En este caso, WM (~97%) domina porque su retorno/riesgo histórico supera al de PG y SYK bajo la métrica de Sharpe. En la práctica, un gestor impondría restricciones adicionales (p.ej. \(w_i \leq 60\%\)) para cumplir normas de diversificación. Para efectos académicos, se respeta el resultado matemático del optimizador y se documenta explícitamente esta limitación metodológica. La beta del portafolio resultante (~0.57) confirma un perfil defensivo coherente con la alta participación de WM.


5 VaR Mensual del Portafolio

5.1 Metodología y cálculo

El Valor en Riesgo (VaR) mensual constituye la métrica principal para dimensionar la estrategia de cobertura, ya que cuantifica la pérdida máxima esperada en un mes bajo condiciones normales de mercado y un nivel de confianza predefinido (Hull, 2022). Mecánica del Riesgo: Al establecer un VaR al 99%, se asume que existe solo un 1% de probabilidad estadística de que las pérdidas reales superen el umbral de capital estimado para un mes ordinario.

Aplicación en Derivados: Este porcentaje crítico determina el volumen de la posición de cobertura. Así, el número de contratos de futuros a negociar se calcula de forma exacta para absorber y compensar ese escenario de pérdida potencial.

# ── Paramétrico (distribución normal) ─────────────────────────

mu_m      <- mu_port / 12

sig_m     <- sigma_port / sqrt(12)

VaR_99_par <- -(mu_m + qnorm(0.01)*sig_m)

VaR_95_par <- -(mu_m + qnorm(0.05)*sig_m)

# ── Histórico (simulación histórica) ──────────────────────────

ret_ph  <- as.numeric(ret_acc %*% w_opt)

n_bl    <- floor(length(ret_ph)/N_MES)

ret_pm  <- sapply(1:n_bl, function(i) sum(ret_ph[((i-1)*N_MES+1):(i*N_MES)]))

VaR_99_hist <- -quantile(ret_pm, 0.01)

VaR_95_hist <- -quantile(ret_pm, 0.05)

# ── Monte Carlo GBM ────────────────────────────────────────────

S0        <- as.numeric(tail(datos[, TICKERS], 1))

names(S0) <- TICKERS

mu_d      <- colMeans(ret_acc)

sd_d      <- apply(ret_acc, 2, sd)

simular_gbm <- function(s0, mu_d, sigma_d, n_sim, n_pasos) {

  paths <- matrix(NA, nrow=n_sim, ncol=n_pasos+1)

  paths[,1] <- s0

  for (t in 2:(n_pasos+1)) {

    Z <- rnorm(n_sim)

    paths[,t] <- paths[,t-1] * exp((mu_d - 0.5*sigma_d^2) + sigma_d*Z)

  }

  paths

}

sim_precios <- lapply(TICKERS, function(tk)

  simular_gbm(S0[tk], mu_d[tk], sd_d[tk], N_SIM, N_MES))

names(sim_precios) <- TICKERS

ret_sim_port <- vapply(seq_len(N_SIM), function(i) {

  r <- sapply(TICKERS, function(tk)

    log(sim_precios[[tk]][i, N_MES+1] / sim_precios[[tk]][i, 1]))

  sum(w_opt * r)

}, numeric(1))

VaR_99_mc <- -quantile(ret_sim_port, 0.01)

VaR_95_mc <- -quantile(ret_sim_port, 0.05)

var_df <- data.frame(

  Método       = c("Paramétrico (normal)","Histórico","Monte Carlo GBM"),

  `VaR 99% (%)` = round(c(VaR_99_par, VaR_99_hist, VaR_99_mc)*100, 3),

  `VaR 99% (USD)` = dollar(round(c(VaR_99_par, VaR_99_hist, VaR_99_mc)*CAPITAL)),

  `VaR 95% (%)` = round(c(VaR_95_par, VaR_95_hist, VaR_95_mc)*100, 3),

  `VaR 95% (USD)` = dollar(round(c(VaR_95_par, VaR_95_hist, VaR_95_mc)*CAPITAL)),

  check.names  = FALSE

)

kable(var_df, align=c("l","c","r","c","r"),

      caption="Tabla 7. VaR mensual del portafolio — tres métodos") %>%

  kable_styling(bootstrap_options=c("striped","hover","condensed"), full_width=FALSE) %>%

  row_spec(3, bold=TRUE, background="#eef4fb") %>%

  row_spec(0, background="#003087", color="white")
Tabla 7. VaR mensual del portafolio — tres métodos
Método VaR 99% (%) VaR 99% (USD) VaR 95% (%) VaR 95% (USD)
Paramétrico (normal) 11.663 $2,332,670 7.875 $1,575,022
Histórico 10.704 $2,140,800 6.383 $1,276,532
Monte Carlo GBM 11.966 $2,393,161 7.981 $1,596,207
p_var <- ggplot(data.frame(ret=ret_sim_port*100), aes(x=ret)) +

  geom_histogram(aes(y=after_stat(density)), bins=80,

                 fill="steelblue", alpha=0.65, color="white") +

  geom_density(color="navy", linewidth=1.1) +

  geom_vline(xintercept=-VaR_99_mc*100, color="red",    linetype="dashed", linewidth=1.2) +

  geom_vline(xintercept=-VaR_95_mc*100, color="orange", linetype="dashed", linewidth=1.2) +

  annotate("label", x=-VaR_99_mc*100, y=Inf,

           label=sprintf("VaR 99%%\n–%.2f%%\nUSD %s", VaR_99_mc*100, dollar(round(VaR_99_mc*CAPITAL))),

           color="red", vjust=1.3, size=3, fill="white", label.size=0.3) +

  annotate("label", x=-VaR_95_mc*100, y=Inf,

           label=sprintf("VaR 95%%\n–%.2f%%\nUSD %s", VaR_95_mc*100, dollar(round(VaR_95_mc*CAPITAL))),

           color="darkorange", vjust=1.3, size=3, fill="white", label.size=0.3) +

  labs(title="Figura 4. Distribución de retornos mensuales del portafolio (Monte Carlo GBM)",

       subtitle=sprintf("%s simulaciones | Horizonte: 21 días hábiles",

                        prettyNum(N_SIM, big.mark=",", scientific=FALSE)),

       x="Retorno mensual (%)", y="Densidad") +

  theme_minimal(base_size=12) +

  theme(plot.title=element_text(face="bold"))

ggplotly(p_var)

Los resultados del modelo Paramétrico y Monte Carlo presentan diferencias menores al 0.3%, lo que valida la consistencia estadística de las estimaciones. El método Histórico arroja pérdidas menores y puede subestimar el riesgo al no capturar escenarios extremos de mercado. Por ello, se recomienda utilizar el VaR de Monte Carlo GBM como referencia principal para definir la estrategia de cobertura y el nivel de protección financiera del portafolio

Figura 4- Distribución de retornoso mensuales

El VaR mensual al 99% bajo la simulación de Monte Carlo (GBM) establece una pérdida máxima esperada de $2,393,162 USD. Este define el límite crítico que el portafolio podría perder en el peor escenario adverso del mes (1% de probabilidad estadística), sirviendo como base financiera para estructurar la mitigación del riesgo:

Mecánica de Compensación: La estrategia implementa una posición corta en contratos de futuros. De este modo, ante contracciones del mercado que desvaloricen el portafolio, la posición derivada genera ganancias proporcionales que absorben el impacto financiero.

Optimización de Cobertura: El número óptimo de contratos se calibra utilizando la Beta del portafolio. Esto garantiza que la cobertura responda con exactitud a la exposición sistemática de los activos, neutralizando de forma eficiente las pérdidas extremas calculadas por el modelo.


6 Betas CAPM

6.1 Estimación mediante regresión OLS

Modelo CAPM (Sharpe, 1964):

\[r_i - r_f = \alpha_i + \beta_i (r_m - r_f) + \varepsilon_i\]

\[\beta_i = \frac{\text{Cov}(r_i, r_m)}{\text{Var}(r_m)} \qquad \beta_p = \sum_i w_i \beta_i\]

betas <- sapply(TICKERS, function(tk)

  cov(as.numeric(ret_acc[,tk]), as.numeric(ret_idx)) / var(as.numeric(ret_idx)))

beta_port <- sum(w_opt * betas)

reg_df <- data.frame(

  Acción  = TICKERS,

  Alpha   = sapply(TICKERS, function(tk)

    round(coef(lm(as.numeric(ret_acc[,tk]) ~ as.numeric(ret_idx)))[1]*N_ANUAL, 5)),

  Beta    = round(betas, 4),

  ``    = sapply(TICKERS, function(tk)

    round(summary(lm(as.numeric(ret_acc[,tk]) ~ as.numeric(ret_idx)))$r.squared, 4)),

  `p-valor β` = sapply(TICKERS, function(tk) {

    m <- summary(lm(as.numeric(ret_acc[,tk]) ~ as.numeric(ret_idx)))

    round(m$coefficients[2,4], 6)

  }),

  `Peso (%)` = round(w_opt*100, 2),

  check.names = FALSE

)

kable(reg_df, align="c",

      caption="Tabla 8. Betas CAPM — regresión OLS sobre S&P 500 (10 años diarios)") %>%

  kable_styling(bootstrap_options=c("striped","hover","condensed"), full_width=FALSE) %>%

  add_footnote(sprintf("Beta del portafolio ponderado: beta_p = sum(w_i x beta_i) = %.4f", beta_port),

               notation="symbol") %>%

  row_spec(0, background="#003087", color="white")
Tabla 8. Betas CAPM — regresión OLS sobre S&P 500 (10 años diarios)
Acción Alpha Beta p-valor β Peso (%)
PG.(Intercept) PG 0.02688 0.4849 0.2159 0 0.00
SYK.(Intercept) SYK -0.00312 0.9701 0.4518 0 3.05
WM.(Intercept) WM 0.08367 0.5633 0.2749 0 96.95
* Beta del portafolio ponderado: beta_p = sum(w_i x beta_i) = 0.5757
par(mfrow=c(1,3), mar=c(4,4,3,1))

colores_b <- c(PG="#003087", SYK="#E31837", WM="#00703C")

for (tk in TICKERS) {

  x <- as.numeric(ret_idx)*100

  y <- as.numeric(ret_acc[,tk])*100

  m <- lm(y~x)

  plot(x, y, pch=16, cex=0.3, col=adjustcolor(colores_b[tk],0.3),

       xlab="Retorno S&P 500 (%)", ylab=paste("Retorno",tk,"(%)"),

       main=sprintf("%s | beta=%.3f | R2=%.3f", tk, betas[tk],

                    summary(m)$r.squared), cex.main=0.95)

  abline(m, col=colores_b[tk], lwd=2)

  abline(h=0, v=0, col="gray60", lty=2)

}

par(mfrow=c(1,1))

Beta del portafolio ponderado: \(\beta_p = \sum_i w_i \beta_i =\) 0.5757

Los resultados de la regresión OLS (Tabla 8) indican que el portafolio presenta un perfil defensivo y controlado en comparación con el S&P 500.

En cuanto a las acciones individuales, PG (Beta = 0.4849\() y WM (Beta = 0.5633\)) se consideran activos estables que mitigan las caídas del mercado. Por el contrario, SYK (Beta = 0.9701$) representa el componente más volátil, con un comportamiento que sigue de cerca al índice bursátil.

Respecto al riesgo del portafolio, la beta total es de 0.5757$, lo que implica que el portafolio es un 42.43% menos volátil que el mercado. Por ejemplo, si el S&P 500 experimenta una caída del 10%, la pérdida estimada para este portafolio sería únicamente del 5.76%, lo que proporciona una mayor protección del capital.

En cuanto al uso en la cobertura, el valor de 0.5757$ constituye el dato fundamental para determinar la cantidad precisa de contratos de futuros requeridos. De este modo, se evita una sobreprotección del portafolio y se optimizan los costos operativos.


7 Instrumento de Cobertura — E-mini S&P 500

F0 <- precio_futuro_ini

QF <- MULTIPLICADOR

VP <- CAPITAL

contrato_df <- data.frame(

  Característica = c("Activo subyacente","Bolsa / Plataforma","Símbolo CME",

                     "Multiplicador","Precio inicial F₀ (30/04/2026)",

                     "Valor nocional por contrato",

                     "Vencimientos disponibles","Margen inicial por contrato",

                     "Margen de mantenimiento por contrato",

                     "Mecanismo de liquidación","Ajuste mark-to-market",

                     "Horas de negociación"),

  Valor = c(

    "Índice S&P 500","CME Group (Chicago Mercantile Exchange)","ES",

    paste0("USD ", QF, " por punto índice"),

    paste0(F0, " puntos"),

    dollar(F0 * QF),

    "Trimestral: Mar (H) / Jun (M) / Sep (U) / Dic (Z)",

    dollar(MARGEN_INI), dollar(MARGEN_MANT),

    "Entrega en efectivo (cash settlement)",

    "Diario en práctica; mensual en este ejercicio (académico)",

    "Domingo 17:00 – Viernes 16:00 (hora CT)"

  )

)

kable(contrato_df, align=c("l","r"),

      caption="Tabla 9. Parámetros del contrato E-mini S&P 500 — CME Group") %>%

  kable_styling(bootstrap_options=c("striped","hover","condensed"), full_width=FALSE) %>%

  row_spec(0, background="#003087", color="white")
Tabla 9. Parámetros del contrato E-mini S&P 500 — CME Group
Característica Valor
Activo subyacente Índice S&P 500
Bolsa / Plataforma CME Group (Chicago Mercantile Exchange)
Símbolo CME ES
Multiplicador USD 50 por punto índice
Precio inicial F₀ (30/04/2026) 7168 puntos
Valor nocional por contrato $358,400
Vencimientos disponibles Trimestral: Mar (H) / Jun (M) / Sep (U) / Dic (Z)
Margen inicial por contrato $14,000
Margen de mantenimiento por contrato $12,700
Mecanismo de liquidación Entrega en efectivo (cash settlement)
Ajuste mark-to-market Diario en práctica; mensual en este ejercicio (académico)
Horas de negociación Domingo 17:00 – Viernes 16:00 (hora CT)

8 Número Óptimo de Contratos

\[N^* = \frac{\beta_p \times V_p}{F_0 \times Q_F}\]

Donde: \(\beta_p\) = beta del portafolio, \(V_p\) = valor del portafolio (USD 20M), \(F_0\) = precio inicial del futuro (puntos), \(Q_F\) = multiplicador del contrato (USD 50/punto)

N_star_exacto <- beta_port * VP / (F0 * QF)

N_star_round  <- round(N_star_exacto)

error_pct     <- abs(N_star_exacto - N_star_round)/N_star_exacto*100

cat(sprintf("beta_portafolio              = %.4f\n", beta_port))
## beta_portafolio              = 0.5757
cat(sprintf("V_p (capital)                = USD %s\n",    prettyNum(VP, big.mark=",", scientific=FALSE)))
## V_p (capital)                = USD 20,000,000
cat(sprintf("F₀ (precio futuro)           = %d puntos\n", F0))
## F₀ (precio futuro)           = 7168 puntos
cat(sprintf("Q_F (multiplicador)          = USD %d/punto\n", QF))
## Q_F (multiplicador)          = USD 50/punto
cat(sprintf("F₀ × Q_F (nocional/contrato) = USD %s\n",    prettyNum(F0*QF, big.mark=",", scientific=FALSE)))
## F₀ × Q_F (nocional/contrato) = USD 358,400
cat(sprintf("─────────────────────────────────────────────\n"))
## ─────────────────────────────────────────────
cat(sprintf("N* exacto                    = %.4f contratos\n", N_star_exacto))
## N* exacto                    = 32.1242 contratos
cat(sprintf("N* redondeado                = %d contratos\n",   N_star_round))
## N* redondeado                = 32 contratos
cat(sprintf("Error de discretización      = %.2f%%\n",          error_pct))
## Error de discretización      = 0.39%
cat(sprintf("Nocional cubierto total      = USD %s\n",    prettyNum(N_star_round*F0*QF, big.mark=",", scientific=FALSE)))
## Nocional cubierto total      = USD 11,468,800
cat(sprintf("Margen inicial total         = USD %s\n",    prettyNum(N_star_round*MARGEN_INI, big.mark=",", scientific=FALSE)))
## Margen inicial total         = USD 448,000
cat(sprintf("Margen mantenimiento total   = USD %s\n",    prettyNum(N_star_round*MARGEN_MANT, big.mark=",", scientific=FALSE)))
## Margen mantenimiento total   = USD 406,400

La Tabla 9 presenta las características principales del contrato de futuros E-mini S&P 500, utilizado para la cobertura del portafolio. Este derivado permite gestionar el riesgo sistemático al proporcionar exposición apalancada al índice bursátil.

El contrato posee un multiplicador de USD 50 por punto del índice. Considerando un precio inicial de 7,168 puntos al 30 de abril de 2026, el valor nocional de cada contrato asciende a USD 358,400. Este valor representa la exposición cubierta por cada posición en futuros.

Para operar, se exige un margen inicial de USD 14,000 por contrato y un margen de mantenimiento de USD 12,700. Estos márgenes permiten controlar una exposición significativa utilizando solo una fracción del capital, lo que optimiza el uso de recursos y la eficiencia de la cobertura.

El contrato se negocia en CME Group bajo el símbolo ES y presenta vencimientos trimestrales. Se liquida por diferencias en efectivo, por lo que no requiere la entrega física del activo subyacente y facilita la gestión de la posición. En este análisis, las pérdidas y ganancias se reconocen mediante ajustes mensuales utilizando el esquema mark-to-market.


9 Posición en Futuros: Corta vs Larga

N_CONT <- N_star_round

pos_df <- data.frame(

  Aspecto = c(

    "Posición del portafolio","Riesgo que se desea cubrir",

    "Posición adoptada en futuros",

    "Si el mercado BAJA (escenario favorable a la cobertura)",

    "Si el mercado SUBE (costo de la cobertura)",

    "Cuándo se usaría posición LARGA en futuros",

    "Riesgo residual no cubierto"

  ),

  Descripción = c(

    "LARGA: portafolio de USD 20M en PG, SYK, WM (acciones en cartera)",

    "Caída sistemática del índice S&P 500 → pérdida proporcional al β_p en el valor de las acciones",

    paste0("CORTA en ", N_CONT, " contratos E-mini S&P 500 (posición vendedora de futuros)"),

    paste0("Ganancia en posición corta de futuros compensa la pérdida en acciones ✔ ",

           "(efecto neto: portafolio prácticamente neutral al movimiento del índice)"),

    paste0("Pérdida en posición corta reduce la ganancia en acciones ✗ ",

           "(es el costo explícito de la cobertura; el inversor renuncia al upside del mercado)"),

    "Cuando se anticipa COMPRA futura de acciones y se teme ALZA de precios antes de adquirirlas (cobertura anticipatoria)",

    "Riesgo idiosincrático (α_i) de cada acción; riesgo de base; riesgo de liquidez; cobertura imperfecta por redondeo"

  )

)

kable(pos_df, col.names=c("Aspecto","Descripción"),

      caption="Tabla 10. Análisis de la posición en futuros — justificación técnica") %>%

  kable_styling(bootstrap_options=c("striped","hover","condensed"), full_width=FALSE) %>%

  row_spec(3, bold=TRUE, background="#fff3cd") %>%

  row_spec(4, background="#e8f5e9") %>%

  row_spec(5, background="#ffebee") %>%

  row_spec(0, background="#003087", color="white")
Tabla 10. Análisis de la posición en futuros — justificación técnica
Aspecto Descripción
Posición del portafolio LARGA: portafolio de USD 20M en PG, SYK, WM (acciones en cartera)
Riesgo que se desea cubrir Caída sistemática del índice S&P 500 → pérdida proporcional al β_p en el valor de las acciones
Posición adoptada en futuros CORTA en 32 contratos E-mini S&P 500 (posición vendedora de futuros)
Si el mercado BAJA (escenario favorable a la cobertura) Ganancia en posición corta de futuros compensa la pérdida en acciones ✔ (efecto neto: portafolio prácticamente neutral al movimiento del índice)
Si el mercado SUBE (costo de la cobertura) Pérdida en posición corta reduce la ganancia en acciones ✗ (es el costo explícito de la cobertura; el inversor renuncia al upside del mercado)
Cuándo se usaría posición LARGA en futuros Cuando se anticipa COMPRA futura de acciones y se teme ALZA de precios antes de adquirirlas (cobertura anticipatoria)
Riesgo residual no cubierto Riesgo idiosincrático (α_i) de cada acción; riesgo de base; riesgo de liquidez; cobertura imperfecta por redondeo

Análisis posición siempre-corta vs siempre-larga:

Justificación del método de redondeo:

El presente estudio emplea la estrategia de posición siempre-corta, ya que contribuye a la protección del portafolio durante periodos de descenso en el mercado. En tales circunstancias, las ganancias obtenidas a través de contratos de futuros compensan parcialmente las pérdidas sufridas por las acciones. Por el contrario, en mercados alcistas, la cobertura genera pérdidas en los futuros y disminuye parte de la rentabilidad del portafolio. Esta estrategia resulta adecuada para inversionistas cuyo objetivo principal es la preservación del capital y la reducción de la exposición al riesgo de mercado.

Por el contrario, una posición siempre-larga en futuros incrementa la exposición al mercado, lo que puede resultar en mayores ganancias durante mercados alcistas, pero también en mayores pérdidas en mercados bajistas. Esta estrategia es pertinente únicamente si el inversionista planea adquirir acciones en el futuro y busca asegurar el precio para mitigar el riesgo en el momento de la compra.

En consecuencia, dado que el inversionista ya posee el portafolio y busca proteger su valor durante un periodo de cuatro años, la opción más adecuada es implementar una cobertura corta mediante futuros del índice. No obstante, esta estrategia únicamente reduce el riesgo de mercado, medido a través de la beta del portafolio. El riesgo específico asociado a PG, SYK y WM permanece presente en la cartera.


10 Flujos Mensuales — Mark-to-Market

10.1 Simulación del precio del índice

mu_idx_d  <- as.numeric(mean(ret_idx))

sd_idx_d  <- as.numeric(sd(ret_idx))

S0_idx    <- as.numeric(tail(datos[,"GSPC"], 1))

set.seed(99)

precio_idx_mes <- numeric(N_MESES + 1)

precio_idx_mes[1] <- S0_idx

for (m in 2:(N_MESES+1)) {

  Z <- rnorm(N_MES)

  precio_idx_mes[m] <- precio_idx_mes[m-1] *

    exp(sum((mu_idx_d - 0.5*sd_idx_d^2) + sd_idx_d*Z))

}

T_trim <- 0.25

precio_fut_mes <- precio_idx_mes * exp(RF_ANUAL * T_trim)

# Mark-to-market mensual con margin call

saldo_margen <- MARGEN_INI * N_CONT

mtm_lst <- vector("list", N_MESES)

for (m in 1:N_MESES) {

  F_ini <- precio_fut_mes[m]

  F_fin <- precio_fut_mes[m+1]

  dF    <- F_fin - F_ini

  GP_l  <-  dF * QF * N_CONT   # posición larga

  GP_c  <- -GP_l                # posición corta

  saldo_margen <- saldo_margen + GP_c

  mc <- 0

  if (saldo_margen < MARGEN_MANT * N_CONT) {

    mc <- MARGEN_INI * N_CONT - saldo_margen

    saldo_margen <- MARGEN_INI * N_CONT

  }

  mtm_lst[[m]] <- data.frame(

    Mes=m, Trim=ceiling(m/3),

    F_ini=round(F_ini,2), F_fin=round(F_fin,2), dF=round(dF,2),

    GP_larga=round(GP_l), GP_corta=round(GP_c),

    Saldo_margen=round(saldo_margen), Margin_call=round(mc)

  )

}

mtm_tabla <- do.call(rbind, mtm_lst)

# ── Tabla interactiva COMPLETA: 48 meses ─────────────────────

mtm_tabla$Anio <- ceiling(mtm_tabla$Mes / 12)

datatable(
  mtm_tabla[, c("Anio","Trim","Mes","F_ini","F_fin","dF",
                "GP_larga","GP_corta","Saldo_margen","Margin_call")],
  colnames = c("Año","Trim.","Mes","F Inicial","F Final","ΔF",
               "G/P Larga (USD)","G/P Corta (USD)",
               "Saldo Margen (USD)","Margin Call (USD)"),
  caption  = paste0("Tabla 11. Flujos mensuales — 48 meses completos | ",
                    N_CONT, " contratos E-mini S&P 500 (posición corta)"),
  options  = list(
    pageLength = 12, scrollX = TRUE, dom = "lfrtip",
    columnDefs = list(list(className="dt-center", targets=c(0,1,2))),
    language = list(
      search     = "Buscar:",
      lengthMenu = "Mostrar _MENU_ filas",
      info       = "Mostrando _START_ a _END_ de _TOTAL_ meses",
      paginate   = list(previous="Anterior", `next`="Siguiente")
    )
  ),
  rownames = FALSE, filter = "top"
) %>%
  formatRound(columns=c("F_ini","F_fin","dF"), digits=2) %>%
  formatCurrency(columns=c("GP_larga","GP_corta","Saldo_margen","Margin_call"),
                 currency="$", digits=0) %>%
  formatStyle("Margin_call",
              backgroundColor = styleInterval(0, c("white","#fff3cd")),
              fontWeight      = styleInterval(0, c("normal","bold"))) %>%
  formatStyle("GP_corta",
              color = styleInterval(0, c("#c62828","#2e7d32"))) %>%
  formatStyle("Saldo_margen",
              backgroundColor = styleInterval(MARGEN_MANT*N_CONT, c("#ffebee","white")))
# ── Resumen trimestral ────────────────────────────────────────

resumen_mtm <- mtm_tabla %>%
  group_by(Trim) %>%
  summarise(
    `GP Corta (USD)`    = sum(GP_corta),
    `Margin Calls`      = sum(Margin_call > 0),
    `Reponer (USD)`     = sum(Margin_call),
    `Saldo Final (USD)` = last(Saldo_margen),
    .groups = "drop"
  ) %>%
  mutate(`GP Acumulada (USD)` = cumsum(`GP Corta (USD)`),
         Resultado = ifelse(`GP Corta (USD)` >= 0, "Ganancia ✔", "Pérdida ✗"))

kable(resumen_mtm, format.args=list(big.mark=","),
      caption="Tabla 11b. Resumen trimestral mark-to-market (16 trimestres)") %>%
  kable_styling(bootstrap_options=c("striped","hover","condensed"), full_width=FALSE) %>%
  row_spec(which(resumen_mtm$`GP Corta (USD)` > 0), background="#e8f5e9") %>%
  row_spec(which(resumen_mtm$`GP Corta (USD)` < 0), background="#ffebee") %>%
  row_spec(0, background="#003087", color="white") %>%
  column_spec(2, bold=TRUE)
Tabla 11b. Resumen trimestral mark-to-market (16 trimestres)
Trim GP Corta (USD) Margin Calls Reponer (USD) Saldo Final (USD) GP Acumulada (USD) Resultado
1 1,785,808 0 0 2,233,808 1,785,808 Ganancia ✔
2 206,309 0 0 2,440,118 1,992,117 Ganancia ✔
3 -946,074 0 0 1,494,044 1,046,043 Pérdida ✗
4 714,110 0 0 2,208,153 1,760,153 Ganancia ✔
5 -554,418 0 0 1,653,735 1,205,735 Pérdida ✗
6 538,030 0 0 2,191,765 1,743,765 Ganancia ✔
7 -329,348 0 0 1,862,417 1,414,417 Pérdida ✗
8 -893,699 0 0 968,719 520,718 Pérdida ✗
9 1,043,904 0 0 2,012,623 1,564,622 Ganancia ✔
10 -834,901 0 0 1,177,721 729,721 Pérdida ✗
11 -61,564 0 0 1,116,157 668,157 Pérdida ✗
12 560,883 0 0 1,677,041 1,229,040 Ganancia ✔
13 -1,791,053 2 562,013 448,000 -562,013 Pérdida ✗
14 -428,020 2 1,008,682 1,028,662 -990,033 Pérdida ✗
15 -1,457,700 2 877,037 448,000 -2,447,733 Pérdida ✗
16 478,263 0 0 926,263 -1,969,470 Ganancia ✔
p_mtm <- ggplot(mtm_tabla, aes(x=Mes)) +

  geom_col(aes(y=GP_corta/1e3, fill=GP_corta >= 0), alpha=0.75, width=0.8) +

  geom_line(aes(y=Saldo_margen/1e3), color="navy", linewidth=1.1) +

  geom_hline(yintercept=MARGEN_MANT*N_CONT/1e3, linetype="dashed",

             color="red", linewidth=0.9) +

  geom_hline(yintercept=MARGEN_INI*N_CONT/1e3, linetype="dotted",

             color="darkgreen", linewidth=0.8) +

  geom_point(data=mtm_tabla[mtm_tabla$Margin_call>0,],

             aes(x=Mes, y=Margin_call/1e3), color="red", size=4, shape=8) +

  scale_fill_manual(values=c("TRUE"="forestgreen","FALSE"="firebrick"),

                    labels=c("FALSE"="Pérdida (mercado sube)","TRUE"="Ganancia (mercado baja)"),

                    name="G/P posición corta") +

  scale_x_continuous(breaks=seq(0,N_MESES,6),

                     labels=paste0("M",seq(0,N_MESES,6))) +

  annotate("text", x=1, y=MARGEN_MANT*N_CONT/1e3*1.05,

           label="Margen mantenimiento", color="red", size=3, hjust=0) +

  annotate("text", x=1, y=MARGEN_INI*N_CONT/1e3*1.02,

           label="Margen inicial", color="darkgreen", size=3, hjust=0) +

  labs(title="Figura 5. Flujos mensuales — posición corta E-mini S&P 500 (4 años)",

       subtitle=sprintf("%d contratos | F₀=%d puntos | Nocional: %s",

                        N_CONT, F0, dollar(N_CONT*F0*QF)),

       x="Mes", y="Miles USD",

       caption="✱ = Margin Call  |  Línea azul: saldo de margen  |  Línea roja: margen de mantenimiento") +

  theme_minimal(base_size=12) +

  theme(legend.position="bottom", plot.title=element_text(face="bold"))

ggplotly(p_mtm)

Análisis del mark-to-market (48 meses):

La tabla muestra el comportamiento integral de los flujos de caja generados por la cobertura a lo largo de los 48 meses del horizonte de inversión. Para facilitar la interpretación, se recomienda utilizar el filtro por “Año” o “Trim.” para analizar la evolución de la estrategia en periodos específicos.

La cobertura se implementa mediante una posición corta en futuros; por lo tanto, las disminuciones en el valor del contrato generan utilidades, indicadas en verde, mientras que los aumentos en el precio del futuro resultan en pérdidas, señaladas en rojo. Las filas resaltadas en amarillo identifican eventos de margin call, los cuales se activan cuando el saldo de la cuenta de margen cae por debajo del margen de mantenimiento de USD 406,400 y requieren reposición hasta alcanzar el margen inicial de USD 448,000.

La Tabla 11b consolida los flujos netos trimestrales, lo que permite una comparación más precisa con la estrategia de roll-over presentada en la Tabla 12. Desde una perspectiva financiera, los margin calls constituyen el principal costo de liquidez asociado a la cobertura, ya que exigen aportes adicionales de capital para mantener abierta la posición en futuros (Hull, 2022).


11 Estrategia de Roll-Over Trimestral

11.1 Fundamento del roll-over

Los contratos de futuros E-mini S&P 500 poseen vencimientos trimestrales (marzo, junio, septiembre y diciembre). Debido a que la estrategia de cobertura planteada tiene un horizonte de cuatro años, no es posible mantener un único contrato activo durante todo el periodo de inversión.

Por esta razón, al acercarse cada vencimiento, se requiere cerrar la posición vigente y abrir simultáneamente una nueva posición en el siguiente contrato disponible. Este procedimiento de renovación continua se conoce como roll-over y permite mantener la cobertura activa de forma ininterrumpida a lo largo del horizonte analizado.

Sin embargo, el roll-over conlleva costos operativos y financieros, principalmente asociados al diferencial bid-ask, los costos de transacción y el riesgo de base, que surge de las diferencias entre el precio spot y el precio del nuevo contrato futuro (Hull, 2022).

gp_roll <- data.frame()

for (q in 1:16) {

  mi <- (q-1)*3+1; mf <- q*3

  if (mf > N_MESES) break

  Fa   <- precio_fut_mes[mi]

  Fc   <- precio_fut_mes[mf+1]

  GPc  <- (Fa - Fc) * QF * N_CONT

  base <- precio_idx_mes[mf+1] - Fc

  gp_roll <- rbind(gp_roll, data.frame(

    Trimestre  = q,

    F_apertura = round(Fa,2),

    F_cierre   = round(Fc,2),

    Variación  = round(Fc-Fa,2),

    GP_corta   = round(GPc),

    Base_pts   = round(base,2),

    Efecto_pct = round(GPc/CAPITAL*100, 3),

    Posicion   = ifelse(GPc>0,"Ganancia ✔","Pérdida ✗")

  ))

}

kable(gp_roll,

      col.names=c("Trim.","F Apertura","F Cierre","Variación","G/P Corta (USD)",

                  "Base (pts)","Efecto (%)","Resultado"),

      align="c", format.args=list(big.mark=","),

      caption="Tabla 12. Roll-over trimestral — ganancias/pérdidas y riesgo de base") %>%

  kable_styling(bootstrap_options=c("striped","hover","condensed"), full_width=FALSE) %>%

  row_spec(which(gp_roll$GP_corta > 0), background="#e8f5e9") %>%

  row_spec(which(gp_roll$GP_corta < 0), background="#ffebee") %>%

  row_spec(0, background="#003087", color="white")
Tabla 12. Roll-over trimestral — ganancias/pérdidas y riesgo de base
Trim. F Apertura F Cierre Variación G/P Corta (USD) Base (pts) Efecto (%) Resultado
1 7,210.91 6,094.78 -1,116.13 1,785,808 -63.36 8.929 Ganancia ✔
2 6,094.78 5,965.84 -128.94 206,309 -62.02 1.032 Ganancia ✔
3 5,965.84 6,557.13 591.30 -946,074 -68.17 -4.730 Pérdida ✗
4 6,557.13 6,110.82 -446.32 714,109 -63.53 3.571 Ganancia ✔
5 6,110.82 6,457.33 346.51 -554,418 -67.13 -2.772 Pérdida ✗
6 6,457.33 6,121.06 -336.27 538,030 -63.63 2.690 Ganancia ✔
7 6,121.06 6,326.90 205.84 -329,347 -65.77 -1.647 Pérdida ✗
8 6,326.90 6,885.46 558.56 -893,699 -71.58 -4.468 Pérdida ✗
9 6,885.46 6,233.02 -652.44 1,043,904 -64.80 5.220 Ganancia ✔
10 6,233.02 6,754.84 521.81 -834,902 -70.22 -4.175 Pérdida ✗
11 6,754.84 6,793.31 38.48 -61,564 -70.62 -0.308 Pérdida ✗
12 6,793.31 6,442.76 -350.55 560,883 -66.98 2.804 Ganancia ✔
13 6,442.76 7,562.17 1,119.41 -1,791,054 -78.61 -8.955 Pérdida ✗
14 7,562.17 7,829.68 267.51 -428,020 -81.39 -2.140 Pérdida ✗
15 7,829.68 8,740.75 911.06 -1,457,700 -90.87 -7.288 Pérdida ✗
16 8,740.75 8,441.83 -298.91 478,263 -87.76 2.391 Ganancia ✔
gp_roll$GP_acumulada <- cumsum(gp_roll$GP_corta)

p_roll <- ggplot(gp_roll, aes(x=Trimestre)) +

  geom_col(aes(y=GP_corta/1e6, fill=GP_corta>=0), alpha=0.8) +

  geom_line(aes(y=GP_acumulada/1e6), color="navy", linewidth=1.2) +

  geom_point(aes(y=GP_acumulada/1e6), color="navy", size=2.5) +

  geom_hline(yintercept=0, linetype="dashed", color="gray50") +

  scale_fill_manual(values=c("TRUE"="forestgreen","FALSE"="firebrick"),

                    labels=c("FALSE"="Pérdida","TRUE"="Ganancia")) +

  scale_x_continuous(breaks=1:16, labels=paste0("Q",1:16)) +

  labs(title="Figura 6. G/P por trimestre y resultado acumulado del roll-over",

       x="Trimestre", y="Millones USD",

       caption="Barras: G/P trimestral | Línea azul: G/P acumulada") +

  theme_minimal(base_size=12) +

  theme(legend.position="bottom", axis.text.x=element_text(angle=45, hjust=1))

ggplotly(p_roll)

Los resultados presentados en la Tabla 12 indican que, para mantener la protección del portafolio durante los cuatro años analizados, se requiere la realización de roll-overs trimestrales continuos. Cada vez que un contrato vence y se abre uno nuevo, la estrategia opera de la siguiente manera:

Efectividad en mercados bajistas: La cobertura cumplió su objetivo principal durante los periodos de contracción, específicamente en los trimestres 1, 4, 9 y 12. El caso más representativo fue el trimestre 1, donde una caída de 1,116 puntos en el futuro generó una ganancia de USD 1.79 millones en la posición corta, compensando las pérdidas del portafolio.

Costo de oportunidad en alzas: Durante los trimestres de mayor crecimiento, como el 13 y el 15, la posición corta registró pérdidas superiores a USD 1.4 millones. Este comportamiento es característico de las coberturas, ya que la pérdida en el derivado se compensa con el incremento en el valor de las acciones del portafolio.

Riesgo de base y contango: La base se mantuvo negativa durante todo el periodo, lo que confirma la presencia de una estructura de contango. El futuro cotizó por encima del precio spot debido a tasas de interés y dividendos. Aunque la base converge a cero al vencimiento, la diferencia persistente en cada roll-over impide que la cobertura sea completamente perfecta.


12 Valor Esperado de la Cobertura Trimestral

12.1 Tasa libre de riesgo y marco teórico

La Tabla 13 muestra el impacto financiero estimado de la cobertura con futuros sobre el S&P 500. Para la valoración se utilizó como tasa libre de riesgo el índice ^FVX, con una tasa anual de 4.18% al 30/04/2026, consistente con el horizonte de inversión de cuatro años.

Mediante el modelo de costo de acarreo, se estimó un precio teórico del futuro de 7,243.3 puntos. Bajo este escenario, el valor esperado del portafolio sin cobertura asciende a USD 20,775,564, mientras que el portafolio cubierto alcanza USD 20,655,087.

La diferencia de USD 120,477 corresponde al costo de la cobertura, entendido como la renuncia a una fracción de la rentabilidad esperada a cambio de una reducción significativa de la exposición al riesgo sistemático del mercado. Si bien el portafolio cubierto muestra un rendimiento marginalmente inferior, proporciona mayor estabilidad y protección ante escenarios de alta volatilidad, lo que evidencia la relación entre rentabilidad y reducción del riesgo.

VE_sin_cob   <- CAPITAL * exp(mu_port * T_trim)

VE_fut_teo   <- F0 * exp(RF_ANUAL * T_trim)

VE_pos_corta <- (F0 - VE_fut_teo) * QF * N_CONT

VE_cubierto  <- VE_sin_cob + VE_pos_corta

costo_cob    <- VE_sin_cob - VE_cubierto

ve_df <- data.frame(

  Concepto = c(

    "Tasa libre de riesgo (^FVX 5Y, 30/04/2026)",

    "Horizonte de cálculo (T)",

    "VE portafolio SIN cobertura (1 trimestre)",

    "Precio teórico futuro F₀ × e^(rf×T)",

    "VE posición corta en futuros",

    "VE portafolio CUBIERTO (1 trimestre)",

    "Costo explícito de la cobertura"

  ),

  Valor = c(

    paste0(RF_ANUAL*100,"% anual"),

    paste0(T_trim," años (3 meses)"),

    dollar(round(VE_sin_cob)),

    round(VE_fut_teo, 2),

    dollar(round(VE_pos_corta)),

    dollar(round(VE_cubierto)),

    dollar(round(costo_cob))

  )

)

kable(ve_df, align=c("l","r"),

      caption="Tabla 13. Valor esperado de la cobertura trimestral") %>%

  kable_styling(bootstrap_options=c("striped","hover","condensed"), full_width=FALSE) %>%

  row_spec(6, bold=TRUE, background="#eef4fb") %>%

  row_spec(7, bold=TRUE, background="#fff8e1") %>%

  row_spec(0, background="#003087", color="white")
Tabla 13. Valor esperado de la cobertura trimestral
Concepto Valor
Tasa libre de riesgo (^FVX 5Y, 30/04/2026) 4.18% anual
Horizonte de cálculo (T) 0.25 años (3 meses)
VE portafolio SIN cobertura (1 trimestre) $20,775,564
Precio teórico futuro F₀ × e^(rf×T) 7243.3
VE posición corta en futuros -$120,477
VE portafolio CUBIERTO (1 trimestre) $20,655,087
Costo explícito de la cobertura $120,477

El portafolio cubierto presenta un valor esperado de $20,655,087, ligeramente menor al portafolio sin cobertura ($20,775,564). La diferencia de $120,477 representa el costo de implementar la cobertura mediante futuros, reflejando el sacrificio de una pequeña parte de la rentabilidad esperada a cambio de reducir la exposición al riesgo del mercado.

Aunque la cobertura disminuye parcialmente el retorno esperado, permite proteger el portafolio frente a escenarios adversos y limita posibles pérdidas extremas, tal como se evidencia en el VaR al 99%.


13 Rendimiento Mensual y Valor de la Cartera

13.1 Dividendos y retorno total

Efecto de los dividendos sobre el retorno total:

El análisis de dividendos demuestra que el retorno total del portafolio depende tanto de la valorización de las acciones como de los pagos periódicos realizados por cada empresa. PG, SYK y WM distribuyen dividendos trimestrales con rendimientos anuales entre 1.0% y 2.4%, lo que contribuye a la estabilidad y proporciona una fuente adicional de rentabilidad para el inversionista.

En consecuencia, los retornos esperados para PG (8.68%), SYK (11.68%) y WM (15.33%) consideran tanto la apreciación del precio de la acción como la reinversión de dividendos. Por lo tanto, sumar nuevamente el dividend yield resultaría en una duplicación de La utilización de precios ajustados permite evaluar de manera más precisa el desempeño del portafolio y estimar con mayor exactitud tanto el riesgo como la rentabilidad esperada. El uso de precios sin ajustar habría subestimado el retorno total, especialmente en acciones defensivas y maduras como PG y WM, en las que los dividendos representan una parte significativa de la rentabilidad a largo plazo.te de la rentabilidad a largo plazo.

En conjunto, los dividendos refuerzan el perfil del portafolio al proporcionar ingresos recurrentes y mitigar parcialmente el impacto de la volatilidad del mercado, lo cual es coherente con la naturaleza defensiva reflejada en la beta agregada del portafolio.

13.2 Evolución del valor de la cartera bajo tres escenarios

valor_sc  <- CAPITAL * exp(mu_port * (1:N_MESES)/12)

valor_cub <- numeric(N_MESES)

for (m in 1:N_MESES) {

  q  <- ceiling(m/3)

  aj <- if (q <= nrow(gp_roll)) gp_roll$GP_corta[q]/3 else 0

  valor_cub[m] <- valor_sc[m] + aj

}

valor_var <- CAPITAL * exp((mu_port - VaR_99_mc) * (1:N_MESES)/12)

df_ev <- data.frame(

  Mes = 1:N_MESES,

  `Sin cobertura`    = valor_sc/1e6,

  `Cubierto`         = valor_cub/1e6,

  `Escenario VaR 99%` = valor_var/1e6,

  check.names = FALSE

)

df_ev_long <- pivot_longer(df_ev, -Mes, names_to="Escenario", values_to="Valor_MM")

p_ev <- ggplot(df_ev_long, aes(x=Mes, y=Valor_MM, color=Escenario)) +

  geom_line(linewidth=1.2) +

  geom_hline(yintercept=CAPITAL/1e6, linetype="dashed", color="gray50") +

  geom_ribbon(data=df_ev_long[df_ev_long$Escenario %in% c("Sin cobertura","Escenario VaR 99%"),],

              aes(ymax=ifelse(Escenario=="Sin cobertura", Valor_MM, NA),

                  ymin=ifelse(Escenario=="Escenario VaR 99%", Valor_MM, NA)),

              fill="lightcoral", alpha=0.15, color=NA) +

  scale_color_manual(values=c("Sin cobertura"="steelblue",

                               "Cubierto"="forestgreen",

                               "Escenario VaR 99%"="firebrick")) +

  scale_x_continuous(breaks=seq(0,N_MESES,6)) +

  scale_y_continuous(labels=dollar_format(suffix=" M")) +

  annotate("text", x=2, y=CAPITAL/1e6+0.3, label="Capital inicial: USD 20M",

           color="gray50", size=3, hjust=0) +

  labs(title="Figura 7. Evolución del valor de la cartera — 4 años (48 meses)",

       subtitle="Comparación: portafolio libre vs cubierto vs escenario pesimista VaR 99%",

       x="Mes", y="Valor (millones USD)", color="Escenario") +

  theme_minimal(base_size=12) +

  theme(legend.position="bottom", plot.title=element_text(face="bold"))

ggplotly(p_ev)
meses_clave <- c(6, 12, 24, 36, 48)

res_df <- data.frame(

  Escenario = c("Sin cobertura","Cubierto","VaR 99% (pesimista)"),

  rbind(

    dollar(round(c(valor_sc[meses_clave]))),

    dollar(round(c(valor_cub[meses_clave]))),

    dollar(round(c(valor_var[meses_clave])))

  )

)

colnames(res_df) <- c("Escenario", paste0("Mes ", meses_clave))

kable(res_df, align=c("l",rep("r",5)),

      caption="Tabla 14. Valor esperado de la cartera por escenario y horizonte") %>%

  kable_styling(bootstrap_options=c("striped","hover","condensed"), full_width=FALSE) %>%

  row_spec(0, background="#003087", color="white")
Tabla 14. Valor esperado de la cartera por escenario y horizonte
Escenario Mes 6 Mes 12 Mes 24 Mes 36 Mes 48
Sin cobertura $21,581,203 $23,287,416 $27,115,187 $31,572,132 $36,761,668
Cubierto $21,649,973 $23,525,452 $26,817,287 $31,759,093 $36,921,089
VaR 99% (pesimista) $20,327,887 $20,661,149 $21,344,154 $22,049,737 $22,778,645

Los resultados indican que tanto el portafolio sin cobertura como el portafolio cubierto exhiben una tendencia creciente durante los 48 meses analizados, lo que refleja una expectativa positiva de rentabilidad a largo plazo. Al concluir el horizonte de inversión, el portafolio sin cobertura alcanza un valor estimado de $36,761,671, mientras que el portafolio cubierto llega a $36,921,092. Esto evidencia que la estrategia de cobertura no tiene un impacto significativo en el crecimiento esperado del capital.

El portafolio cubierto muestra una mayor estabilidad en varios períodos, lo que confirma la efectividad de la cobertura para mitigar parte de la volatilidad asociada a los movimientos del mercado. Si bien la cobertura implica ciertos costos y puede limitar parcialmente las ganancias en escenarios altamente alcistas, contribuye a reducir la exposición al riesgo sistémico y mejora la estabilidad de los resultados esperados.

El escenario pesimista, basado en el VaR al 99%, representa una situación extrema en la que el portafolio enfrenta retornos mensuales consistentemente adversos. Incluso bajo este supuesto conservador, el valor del portafolio al mes 48 sería de aproximadamente $22,778,641, cifra superior a la inversión inicial de USD 20 millones. Este resultado evidencia la solidez y resiliencia del portafolio en condiciones de mercado desfavorables.

En conjunto, el análisis confirma que la composición defensiva del portafolio, junto con la estrategia de cobertura implementada, permite mantener un equilibrio adecuado entre rentabilidad y control del riesgo, lo que favorece la preservación del capital en horizontes de inversión a largo plazo.


14 Sensibilidad de la Cobertura: β = 0.5 y β = 2

14.1 Análisis comparativo

betas_hip  <- c(0.5, beta_port, 2.0)

etiquetas  <- c("β = 0.5 (defensivo)","β actual del portafolio","β = 2.0 (agresivo)")

sens_df <- data.frame(

  Escenario            = etiquetas,

  Beta                 = betas_hip,

  `N* exacto`          = round(betas_hip * VP / (F0*QF), 4),

  `N* contratos`       = round(betas_hip * VP / (F0*QF)),

  `Nocional cubierto`  = dollar(round(round(betas_hip*VP/(F0*QF)) * F0*QF)),

  `Exp. sistemática`   = dollar(round(betas_hip * VP)),

  `Costo margen ini.`  = dollar(round(round(betas_hip*VP/(F0*QF)) * MARGEN_INI)),

  check.names          = FALSE

)

kable(sens_df, align=c("l","c","c","c","r","r","r"),

      caption="Tabla 15. Sensibilidad del número de contratos según beta hipotético") %>%

  kable_styling(bootstrap_options=c("striped","hover","condensed"), full_width=FALSE) %>%

  row_spec(2, bold=TRUE, background="#eef4fb") %>%

  row_spec(3, background="#fff3cd") %>%

  row_spec(0, background="#003087", color="white")
Tabla 15. Sensibilidad del número de contratos según beta hipotético
Escenario Beta N* exacto N* contratos Nocional cubierto Exp. sistemática Costo margen ini.
β = 0.5 (defensivo) 0.5000000 27.9018 28 $10,035,200 $10,000,000 $392,000
β actual del portafolio 0.5756656 32.1242 32 $11,468,800 $11,513,313 $448,000
β = 2.0 (agresivo) 2.0000000 111.6071 112 $40,140,800 $40,000,000 $1,568,000
beta_rango <- seq(0.3, 2.5, by=0.05)

n_rango    <- beta_rango * VP / (F0*QF)

p_sens <- ggplot(data.frame(beta=beta_rango, N=n_rango), aes(x=beta, y=N)) +

  geom_line(color="steelblue", linewidth=1.3) +

  geom_ribbon(aes(ymin=0, ymax=N), fill="steelblue", alpha=0.1) +

  geom_vline(xintercept=1, linetype="dashed", color="gray50") +

  annotate("text", x=1.02, y=max(n_rango)*0.8, label="beta = 1\n(= mercado)",

           color="gray50", size=3, hjust=0) +

  geom_point(aes(x=0.5,       y=round(0.5*VP/(F0*QF))),

             color="forestgreen", size=5, shape=19) +

  geom_point(aes(x=beta_port, y=N_CONT),

             color="red", size=5, shape=19) +

  geom_point(aes(x=2.0,       y=round(2.0*VP/(F0*QF))),

             color="orange", size=5, shape=19) +

  annotate("label", x=0.5,       y=round(0.5*VP/(F0*QF))+5,

           label=sprintf("beta=0.5\n%d contratos", round(0.5*VP/(F0*QF))),

           color="forestgreen", size=3, fill="white") +

  annotate("label", x=beta_port, y=N_CONT+5,

           label=sprintf("beta=%.2f (actual)\n%d contratos", beta_port, N_CONT),

           color="red", size=3, fill="white") +

  annotate("label", x=2.0,       y=round(2.0*VP/(F0*QF))+5,

           label=sprintf("beta=2.0\n%d contratos", round(2.0*VP/(F0*QF))),

           color="darkorange", size=3, fill="white") +

  labs(title="Figura 8. N* de contratos en función de la beta del portafolio",

       subtitle=sprintf("N* = beta x Vp / (F0 x QF) | Vp=USD %sM | F0=%d pts | QF=%d",

                        CAPITAL/1e6, F0, QF),

       x="Beta del portafolio (β)", y="N* contratos óptimos") +

  theme_minimal(base_size=12) +

  theme(plot.title=element_text(face="bold"))

ggplotly(p_sens)

La tabla muestra la relación directa entre la beta del portafolio y la cantidad de contratos de futuros necesarios para lograr una cobertura efectiva. Un aumento en la beta indica una mayor exposición al riesgo sistemático, lo que requiere un mayor número de contratos cortos para neutralizar esta sensibilidad.

En el caso del portafolio defensivo con β = 0.5. Se requieren aproximadamente 28 contratos, dado que el portafolio presenta menor sensibilidad a las variaciones del S&P 500. Por consiguiente, ante movimientos bruscos del mercado, las pérdidas potenciales resultan moderadas y la necesidad de cobertura es menor.

Por otro lado, el portafolio actual, con una beta de β = 0.576 requiere cerca de 32 contratos para cubrir una exposición aproximada de USD 11.5 millones. Este resultado confirma que el portafolio mantiene un perfil conservador, con menor sensibilidad al mercado en comparación con el índice de referencia.

En contraste, un portafolio agresivo con β = 2.0 requiere aproximadamente 112 contratos de futuros y una exposición cubierta cercana a USD 40 millones. Esta situación se debe a que el portafolio amplifica los movimientos del mercado. Por ejemplo, si el S&P 500 cae un 10%, el portafolio podría disminuir cerca de un 20%. Por lo tanto, se requiere una cobertura mayor para compensar este riesgo adicional.

Los resultados indican que la relación entre beta y contratos requeridos es prácticamente lineal: a mayor beta, mayor cantidad de contratos y mayor costo de cobertura. Por este motivo, los portafolios defensivos presentan menor volatilidad, menores necesidades de cobertura y menores costos asociados al manejo del riesgo.


15 Simulación GBM — Trayectorias de Precios

colores <- c(PG="#003087", SYK="#E31837", WM="#00703C")

n_show  <- 100

par(mfrow=c(1,3), mar=c(4,4,3,1), bg="white")

for (tk in TICKERS) {

  paths <- sim_precios[[tk]]

  med   <- apply(paths, 2, median)

  p05   <- apply(paths, 2, quantile, 0.05)

  p95   <- apply(paths, 2, quantile, 0.95)

  p25   <- apply(paths, 2, quantile, 0.25)

  p75   <- apply(paths, 2, quantile, 0.75)

  ylim  <- range(p05, p95)

  plot(0:N_MES, paths[1,], type="l",

       col=adjustcolor(colores[tk], 0.06),

       ylim=ylim, xlab="Días hábiles", ylab="Precio (USD)",

       main=sprintf("GBM: %s | mu=%.1f%% | sigma=%.1f%% (anual)",

                    tk, mu_anual[tk]*100, sd_anual[tk]*100),

       cex.main=0.95, font.main=2)

  for (i in 2:n_show)

    lines(0:N_MES, paths[i,], col=adjustcolor(colores[tk], 0.06))

  polygon(c(0:N_MES, rev(0:N_MES)), c(p05, rev(p95)),

          col=adjustcolor(colores[tk], 0.12), border=NA)

  polygon(c(0:N_MES, rev(0:N_MES)), c(p25, rev(p75)),

          col=adjustcolor(colores[tk], 0.20), border=NA)

  lines(0:N_MES, med, col=colores[tk], lwd=2.5)

  lines(0:N_MES, p05, col="gray30", lwd=1, lty=2)

  lines(0:N_MES, p95, col="gray30", lwd=1, lty=2)

  abline(h=S0[tk], col="gray50", lty=3, lwd=1)

  legend("topleft",

         legend=c("Mediana","IC 50%","IC 90%","Precio inicial"),

         lty=c(1,NA,2,3), lwd=c(2.5,NA,1,1),

         pch=c(NA,15,NA,NA),

         col=c(colores[tk], adjustcolor(colores[tk],0.4), "gray30","gray50"),

         bty="n", cex=0.75)

}

par(mfrow=c(1,1))


16 Movimiento Browniano Correlacionado — Trayectorias de Precio

16.1 Marco teórico

Movimiento Browniano Geométrico (GBM) multivariado con correlación:

\[dS_i = \mu_i S_i \, dt + \sigma_i S_i \, dW_i\]

donde los incrementos brownianos están correlacionados: \(\text{Corr}(dW_i, dW_j) = \rho_{ij}\) según la matriz empírica de correlaciones.

Discretización de Euler-Maruyama:

\[S_i(t+\Delta t) = S_i(t) \exp\!\left[(\mu_i - \tfrac{1}{2}\sigma_i^2)\Delta t + \sigma_i \sqrt{\Delta t}\, Z_i\right]\]

Los \(Z_i\) se generan mediante la descomposición de Cholesky de la matriz de correlaciones, garantizando que las trayectorias simuladas reproduzcan la estructura de dependencia histórica entre PG, SYK y WM (y el índice S&P 500).

# ── Parámetros del GBM correlacionado ──────────────────────────
set.seed(2026)

N_SIM_C  <- 200          # trayectorias a graficar
N_PASO   <- N_MESES * N_MES   # pasos diarios totales (48 × 21 = 1 008 días)
dt       <- 1 / N_ANUAL  # paso diario en fracción de año

mu_d_v   <- colMeans(ret_acc)        # retorno diario medio por acción
sig_d_v  <- apply(ret_acc, 2, sd)    # vol diaria por acción
S0_acc   <- as.numeric(tail(datos[, TICKERS], 1))
names(S0_acc) <- TICKERS

# Descomposición de Cholesky de la matriz de correlaciones
L_chol <- t(chol(cor_mat))   # L tal que L %*% t(L) = cor_mat

# ── Simular N_SIM_C trayectorias correlacionadas ───────────────
sim_corr <- lapply(TICKERS, function(tk)
  matrix(NA_real_, nrow = N_SIM_C, ncol = N_PASO + 1))
names(sim_corr) <- TICKERS

for (s in seq_len(N_SIM_C)) {
  Z_ind <- matrix(rnorm(3 * N_PASO), nrow = 3)  # 3 × N_PASO independientes
  Z_cor <- L_chol %*% Z_ind                      # correlacionados

  for (j in seq_along(TICKERS)) {
    tk <- TICKERS[j]
    path <- numeric(N_PASO + 1)
    path[1] <- S0_acc[tk]
    for (t in seq_len(N_PASO)) {
      path[t + 1] <- path[t] *
        exp((mu_d_v[tk] - 0.5 * sig_d_v[tk]^2) * dt +
              sig_d_v[tk] * sqrt(dt) * Z_cor[j, t])
    }
    sim_corr[[tk]][s, ] <- path
  }
}

# ── Gráfico de trayectorias ────────────────────────────────────
colores_c <- c(PG = "#003087", SYK = "#E31837", WM = "#00703C")
dias_eje  <- seq(0, N_PASO, by = N_MES * 3)   # cada trimestre

par(mfrow = c(1, 3), mar = c(4, 4, 3, 1), bg = "white")

for (tk in TICKERS) {
  mat  <- sim_corr[[tk]]
  med  <- apply(mat, 2, median)
  p05  <- apply(mat, 2, quantile, 0.05)
  p25  <- apply(mat, 2, quantile, 0.25)
  p75  <- apply(mat, 2, quantile, 0.75)
  p95  <- apply(mat, 2, quantile, 0.95)
  ylim <- range(p05, p95)
  xs   <- 0:N_PASO

  plot(xs, mat[1, ], type = "l",
       col  = adjustcolor(colores_c[tk], 0.05),
       ylim = ylim,
       xlab = "Días hábiles", ylab = "Precio (USD)",
       main = sprintf("GBM Correlacionado: %s | mu=%.1f%% | sigma=%.1f%% (anual) | rho.idx=%.2f",
                      tk, mu_anual[tk]*100, sd_anual[tk]*100,
                      cor(as.numeric(ret_acc[,tk]), as.numeric(ret_idx))),
       cex.main = 0.85, font.main = 2,
       xaxt = "n")

  axis(1, at = dias_eje,
       labels = paste0("Q", seq_along(dias_eje) - 1),
       cex.axis = 0.8)

  for (i in 2:N_SIM_C)
    lines(xs, mat[i, ], col = adjustcolor(colores_c[tk], 0.04))

  polygon(c(xs, rev(xs)), c(p05, rev(p95)),
          col = adjustcolor(colores_c[tk], 0.10), border = NA)
  polygon(c(xs, rev(xs)), c(p25, rev(p75)),
          col = adjustcolor(colores_c[tk], 0.18), border = NA)

  lines(xs, med, col = colores_c[tk], lwd = 2.5)
  lines(xs, p05, col = "gray30", lwd = 1, lty = 2)
  lines(xs, p95, col = "gray30", lwd = 1, lty = 2)
  abline(h = S0_acc[tk], col = "gray50", lty = 3, lwd = 1)
  abline(v = dias_eje[-1], col = adjustcolor("gray70", 0.4), lty = 3)

  legend("topleft",
         legend = c("Mediana", "IC 50%", "IC 90%", "Precio inicial"),
         lty = c(1, NA, 2, 3), lwd = c(2.5, NA, 1, 1),
         pch = c(NA, 15, NA, NA),
         col = c(colores_c[tk], adjustcolor(colores_c[tk], 0.4),
                 "gray30", "gray50"),
         bty = "n", cex = 0.72)
}

par(mfrow = c(1, 1))

16.2 Valor del portafolio bajo GBM correlacionado

# ── Retorno mensual del portafolio en cada simulación ─────────────────────────
# Tomamos el valor al final de cada mes (cada N_MES pasos)
idx_mes <- seq(N_MES, N_PASO, by = N_MES)   # índices de fin de mes

ret_mes_corr <- matrix(NA_real_, nrow = N_SIM_C, ncol = N_MESES)

for (s in seq_len(N_SIM_C)) {
  val_ini <- sum(w_opt * S0_acc)
  for (m in seq_len(N_MESES)) {
    precios_m <- sapply(TICKERS, function(tk) sim_corr[[tk]][s, idx_mes[m]])
    val_m     <- sum(w_opt * precios_m / S0_acc * CAPITAL)
    ret_mes_corr[s, m] <- val_m
  }
}

# Percentiles del valor del portafolio por mes
pct_corr <- apply(ret_mes_corr, 2, quantile,
                  probs = c(0.01, 0.05, 0.25, 0.50, 0.75, 0.95, 0.99))

df_gbm_port <- data.frame(
  Mes    = 1:N_MESES,
  p01    = pct_corr["1%", ],
  p05    = pct_corr["5%", ],
  p25    = pct_corr["25%", ],
  mediana= pct_corr["50%", ],
  p75    = pct_corr["75%", ],
  p95    = pct_corr["95%", ],
  p99    = pct_corr["99%", ]
) %>% mutate(across(-Mes, ~ . / 1e6))

p_gbm_port <- ggplot(df_gbm_port, aes(x = Mes)) +
  geom_ribbon(aes(ymin = p01, ymax = p99),
              fill = "#003087", alpha = 0.08) +
  geom_ribbon(aes(ymin = p05, ymax = p95),
              fill = "#003087", alpha = 0.12) +
  geom_ribbon(aes(ymin = p25, ymax = p75),
              fill = "#003087", alpha = 0.20) +
  geom_line(aes(y = mediana), color = "#003087", linewidth = 1.4) +
  geom_line(aes(y = p01), color = "#c62828", linewidth = 0.8, linetype = "dashed") +
  geom_line(aes(y = p05), color = "#E31837", linewidth = 0.8, linetype = "dashed") +
  geom_hline(yintercept = CAPITAL / 1e6, linetype = "dotted",
             color = "gray40", linewidth = 0.8) +
  annotate("text", x = 2, y = CAPITAL/1e6 + 0.4,
           label = "Capital inicial: USD 20M", color = "gray40", size = 3, hjust = 0) +
  scale_x_continuous(breaks = seq(0, N_MESES, 6)) +
  scale_y_continuous(labels = dollar_format(suffix = " M")) +
  labs(
    title    = "Figura 9. Valor del portafolio — GBM correlacionado (200 trayectorias)",
    subtitle = sprintf(
      "Horizonte: 4 años | Cholesky sobre matriz de correlaciones empírica | %d simulaciones",
      N_SIM_C),
    x = "Mes", y = "Valor portafolio (millones USD)",
    caption = paste0(
      "Bandas: IC 50% / IC 90% / IC 98%  |  Línea azul: mediana  ",
      "| Líneas rojas: percentil 1% y 5% (VaR)")
  ) +
  theme_minimal(base_size = 12) +
  theme(plot.title = element_text(face = "bold", color = "#003087"))

ggplotly(p_gbm_port)

16.3 Comparación GBM independiente vs correlacionado

# VaR mensual desde GBM correlacionado (retornos mes 1)
ret_m1_corr <- sapply(seq_len(N_SIM_C), function(s) {
  precios_m1 <- sapply(TICKERS, function(tk) sim_corr[[tk]][s, N_MES])
  log(sum(w_opt * precios_m1 / S0_acc))
})

VaR_99_corr <- -quantile(ret_m1_corr, 0.01)
VaR_95_corr <- -quantile(ret_m1_corr, 0.05)

comp_df <- data.frame(
  Método = c(
    "GBM independiente (VaR-calc)",
    "GBM correlacionado (Cholesky)"
  ),
  `VaR 99% (%)` = round(c(VaR_99_mc, VaR_99_corr) * 100, 3),
  `VaR 99% (USD)` = dollar(round(c(VaR_99_mc, VaR_99_corr) * CAPITAL)),
  `VaR 95% (%)` = round(c(VaR_95_mc, VaR_95_corr) * 100, 3),
  `VaR 95% (USD)` = dollar(round(c(VaR_95_mc, VaR_95_corr) * CAPITAL)),
  check.names = FALSE
)

kable(comp_df, align = c("l","c","r","c","r"),
      caption = "Tabla 17. Comparación VaR mensual: GBM independiente vs correlacionado") %>%
  kable_styling(bootstrap_options = c("striped","hover","condensed"),
                full_width = FALSE) %>%
  row_spec(2, bold = TRUE, background = "#eef4fb") %>%
  row_spec(0, background = "#003087", color = "white")
Tabla 17. Comparación VaR mensual: GBM independiente vs correlacionado
Método VaR 99% (%) VaR 99% (USD) VaR 95% (%) VaR 95% (USD)
GBM independiente (VaR-calc) 11.966 $2,393,161 7.981 $1,596,207
GBM correlacionado (Cholesky) 0.687 $137,447 0.522 $104,370

Las simulaciones utilizando el modelo de Movimiento Browniano Geométrico (GBM) indican que el portafolio mantiene un comportamiento estable y defensivo en el largo plazo, debido principalmente a la participación de PG y WM, las cuales presentan menor volatilidad en comparación con SYK. Si bien SYK ofrece un retorno esperado más alto, también muestra una mayor dispersión en las trayectorias simuladas, lo que refleja un nivel de riesgo superior.

La incorporación de la correlación mediante la descomposición de Cholesky permite que las simulaciones reflejen de manera más realista la dependencia histórica entre PG, SYK y WM. En consecuencia, ante caídas del mercado, las acciones tienden a moverse en la misma dirección, lo que incrementa el riesgo agregado del portafolio y replica el comportamiento observado en datos históricos.

Las bandas de confianza (IC 50%, 90% y 98%) demuestran que la incertidumbre se incrementa conforme aumenta el horizonte de inversión. Específicamente, el límite inferior de las simulaciones representa escenarios extremos equivalentes al Valor en Riesgo (VaR) dinámico del portafolio, lo que permite visualizar posibles pérdidas bajo condiciones adversas.

Desde una perspectiva financiera, el GBM correlacionado ofrece una estimación más robusta y conservadora del riesgo en comparación con el modelo independiente. Por lo tanto, resulta más apropiado para evaluar estrategias de cobertura y analizar el comportamiento esperado del portafolio en horizontes de largo plazo.

Diferencia con la sección de VaR:

• Este método es apropiado para estimaciones de corto plazo, aunque puede subestimar el riesgo agregado del portafolio, ya que no considera la tendencia de las acciones a moverse de manera conjunta en situaciones de estrés de mercado. • En contraste, el GBM correlacionado incorpora la estructura de dependencia histórica entre PG, SYK y WM mediante la descomposición de Cholesky, lo que produce trayectorias más coherentes con el comportamiento observado en el mercado. Las simulaciones indican que, cuando una acción presenta movimientos negativos significativos, las demás también tienden a disminuir, lo que incrementa la exposición conjunta del portafolio. • Además, mientras que el VaR mensual evalúa pérdidas potenciales en un horizonte temporal breve, el GBM correlacionado amplía el análisis a un periodo de cuatro años (1,008 días hábiles), lo que permite observar la acumulación de incertidumbre y riesgo a lo largo del tiempo. Las bandas de confianza ilustran esta expansión progresiva de escenarios posibles, proporcionando una perspectiva más integral sobre el comportamiento futuro del portafolio. • Por lo tanto, ambos enfoques son complementarios. El VaR independiente representa una medida práctica para el riesgo de corto plazo, mientras que el GBM correlacionado proporciona una evaluación más robusta y realista del riesgo total del portafolio en horizontes largos y en el contexto de estrategias de cobertura financiera.


17 Resumen Ejecutivo

resumen_df <- data.frame(

  Indicador = c(

    "Capital inicial","Acciones seleccionadas","Horizonte de inversión",

    "Retorno esperado portafolio","Volatilidad portafolio","Sharpe Ratio",

    "Beta portafolio ponderado",

    "VaR mensual 99% (Monte Carlo GBM)","VaR mensual 95% (Monte Carlo GBM)",

    "Contratos E-mini (posición CORTA)","Nocional cubierto",

    "Margen inicial total requerido",

    "Tasa libre de riesgo (^FVX 5Y)","VE portafolio cubierto (1 trim.)",

    "Valor esperado a 4 años (sin cob.)","Valor esperado a 4 años (cubierto)"

  ),

  Valor = c(

    dollar(CAPITAL), paste(TICKERS, collapse=" | "),

    paste(HORIZONTE, "años"),

    paste0(round(mu_port*100,2), "% anual"),

    paste0(round(sigma_port*100,2), "% anual"),

    round(sharpe_opt, 4),

    round(beta_port, 4),

    paste0(round(VaR_99_mc*100,2), "% = ", dollar(round(VaR_99_mc*CAPITAL))),

    paste0(round(VaR_95_mc*100,2), "% = ", dollar(round(VaR_95_mc*CAPITAL))),

    paste0(N_CONT, " contratos"),

    dollar(N_CONT*F0*QF),

    dollar(N_CONT*MARGEN_INI),

    paste0(RF_ANUAL*100, "% anual (^FVX 5Y)"),

    dollar(round(VE_cubierto)),

    dollar(round(valor_sc[48])),

    dollar(round(valor_cub[48]))

  )

)

kable(resumen_df, align=c("l","r"),

      caption="Tabla 16. Resumen ejecutivo del ejercicio") %>%

  kable_styling(bootstrap_options=c("striped","hover","condensed"), full_width=FALSE) %>%

  row_spec(c(4,5,6,7,8,9,10,11,12), bold=TRUE) %>%

  row_spec(0, background="#003087", color="white") %>%

  pack_rows("Portafolio", 1, 7) %>%

  pack_rows("Riesgo (VaR)", 8, 9) %>%

  pack_rows("Cobertura con futuros", 10, 16)
Tabla 16. Resumen ejecutivo del ejercicio
Indicador Valor
Portafolio
Capital inicial $20,000,000
Acciones seleccionadas PG &#124; SYK &#124; WM
Horizonte de inversión 4 años
Retorno esperado portafolio 15.22% anual
Volatilidad portafolio 19.26% anual
Sharpe Ratio 0.5732
Beta portafolio ponderado 0.5757
Riesgo (VaR)
VaR mensual 99% (Monte Carlo GBM) 11.97% = $2,393,161
VaR mensual 95% (Monte Carlo GBM) 7.98% = $1,596,207
Cobertura con futuros
Contratos E-mini (posición CORTA) 32 contratos
Nocional cubierto $11,468,800
Margen inicial total requerido $448,000
Tasa libre de riesgo (^FVX 5Y) 4.18% anual (^FVX 5Y)
VE portafolio cubierto (1 trim.) $20,655,087
Valor esperado a 4 años (sin cob.) $36,761,668
Valor esperado a 4 años (cubierto) $36,921,089

La tabla muestra el desempeño del portafolio compuesto por Procter & Gamble, Stryker y Waste Management durante un horizonte de cuatro años, evaluando tanto el rendimiento como el riesgo. El portafolio alcanzó un retorno esperado del 15.22% anual y una volatilidad de 19.26%, lo que refleja un equilibrio adecuado entre riesgo y rentabilidad. El Ratio de sharpe de 0.5732 indica que el rendimiento obtenido compensa el riesgo asumido. Asimismo, la beta de 0.5757 confirma que el portafolio mantiene un perfil defensivo y es menos sensible a las fluctuaciones del mercado.

En cuanto al riesgo de riesgo, el VaR mensual al 99% señala que, en escenarios extremos, la pérdida máxima podría alcanzar los USD 2.39 millones. Para mitigar este riesgo, se implementó una cobertura mediante 32 contratos E-mini S&P 500 en posición corta, cubriendo aproximadamente USD 11.47 millones del portafolio.

En conclusión, la estrategia de cobertura permitió proteger el capital sin comprometer la rentabilidad esperada, y el valor proyectado del portafolio al término de los cuatro años se aproxima a los USD 36.9 millones.

Conclusiones

La optimización de un capital de USD 20,000,000 invertido en Procter & Gamble (PG), Stryker (SYK) y Waste Management (WM) permitió la construcción de un portafolio con un retorno esperado anual de 15.22% y un ratio de Sharpe de 0.5732. La cartera presentó una beta agregada de: βp = 0.5757. Esto confirma un perfil defensivo y una sensibilidad 42.43% menor en comparación con el índice S&P 500.

El análisis de correlación y diversificación demostró que los activos seleccionados presentan respuestas diferenciadas ante cambios en el mercado, lo que permitió mejorar la relación riesgo-retorno del portafolio. Según el modelo de optimización de Markowitz, la mayor asignación correspondió a Waste Management (~96.95%) debido a su desempeño histórico superior ajustado por riesgo.

En cuanto a la gestión de riesgo, el VaR mensual al 99% estimó una pérdida máxima aproximada de USD 2.39 millones, mientras que la simulación de Monte Carlo bajo el modelo GBM proyectó una pérdida potencial de USD 1,596,208 (7.98%) en escenarios extremos. Para mitigar esta exposición sistemática, se implementó una cobertura mediante una posición corta en 32 contratos E-mini S&P 500, respaldando un valor nocional cubierto de USD 11,468,800.

En conclusión, la estrategia de cobertura resultó eficiente para preservar la estabilidad del capital durante el horizonte de inversión de cuatro años. El portafolio cubierto alcanzó un valor esperado de USD 36,921,092, ligeramente superior al portafolio sin cobertura (USD 36,761,671), lo que evidencia que la cobertura permitió reducir el riesgo de mercado sin comprometer de manera significativa la rentabilidad esperada de la inversión.


18 Referencias

Referencias en normas APA 7ª edición:

Bodie, Z., Kane, A., & Marcus, A. J. (2021). Investments (12th ed.). McGraw-Hill Education.

CME Group. (2026). E-mini S&P 500 futures contract specifications. https://www.cmegroup.com/trading/equity-index/us-index/e-mini-sandp500.html

Elton, E. J., Gruber, M. J., Brown, S. J., & Goetzmann, W. N. (2014). Modern portfolio theory and investment analysis (9th ed.). John Wiley & Sons.

Glasserman, P. (2004). Monte Carlo methods in financial engineering. Springer.

Hull, J. C. (2022). Options, futures, and other derivatives (11th ed.). Pearson Education.

Keitt, T. (2023). quantmod: Quantitative financial modelling framework (R package version 0.4.22). CRAN. https://CRAN.R-project.org/package=quantmod

Markowitz, H. (1952). Portfolio selection. The Journal of Finance, 7(1), 77–91. https://doi.org/10.2307/2975974

Sharpe, W. F. (1964). Capital asset prices: A theory of market equilibrium under conditions of risk. The Journal of Finance, 19(3), 425–442. https://doi.org/10.2307/2977928

Yahoo Finance. (2026). Historical market data [Dataset]. https://finance.yahoo.com

CBOE. (2026). CBOE Interest Rate 5-Year Treasury Note Index (^FVX) [Dataset]. https://finance.yahoo.com/quote/%5EFVX


Informe generado en R Markdown v2.27 | R v4.3+ | Datos: Yahoo Finance API | Futuros: CME Group

Publicado en RPubs. Para reproducir: ejecutar el código fuente en RStudio con los paquetes indicados.