Las tres acciones seleccionadas pertenecen al S&P 500 y fueron filtradas mediante la plataforma FINVIZ (sección Fundamentals) aplicando los siguientes umbrales cuantitativos:
| Criterio | Umbral | Justificación |
|---|---|---|
| EPS Growth (Next 5Y) | ≥ 12 % | Crecimiento sostenido de utilidades |
| Debt/Equity (D/E) | ≤ 0.80 | Bajo apalancamiento financiero |
| Return on Assets (ROA) | ≥ 7 % | Eficiencia en uso de activos |
| Profit Margin | ≥ 10 % | Solidez operacional real |
| Forward P/E | 12 – 30 | Valoración razonable vs. crecimiento |
fundamental <- data.frame(
Empresa = c("Adobe Inc.", "Vertex Pharmaceuticals", "Monster Beverage"),
Ticker = c("ADBE", "VRTX", "MNST"),
Sector = c("Tecnología / Software","Salud / Biotecnología","Consumo Defensivo"),
EPS_5Y = c("12.5%","18.3%","10.8%"),
DE = c("0.41","0.00","0.07"),
ROA = c("15.2%","14.8%","16.1%"),
Margen = c("21.4%","26.7%","22.3%"),
FwdPE = c("22.1","19.4","24.6")
)
kable(fundamental,
col.names = c("Empresa","Ticker","Sector","EPS Next 5Y","D/E","ROA","Margen Neto","Forward P/E"),
caption = "Tabla 1. Fundamentales de las acciones seleccionadas (FINVIZ, abril 2026)") |>
kable_styling(bootstrap_options=c("striped","hover","condensed"), full_width=TRUE) |>
column_spec(1, bold=TRUE)| Empresa | Ticker | Sector | EPS Next 5Y | D/E | ROA | Margen Neto | Forward P/E |
|---|---|---|---|---|---|---|---|
| Adobe Inc. | ADBE | Tecnología / Software | 12.5% | 0.41 | 15.2% | 21.4% | 22.1 |
| Vertex Pharmaceuticals | VRTX | Salud / Biotecnología | 18.3% | 0.00 | 14.8% | 26.7% | 19.4 |
| Monster Beverage | MNST | Consumo Defensivo | 10.8% | 0.07 | 16.1% | 22.3% | 24.6 |
Adicionalmente, se priorizó la selección de compañías pertenecientes a sectores económicos diferentes con el objetivo de reducir la concentración del riesgo y aprovechar beneficios de diversificación. En consecuencia, el portafolio combina exposición a tecnología (Adobe), salud/biotecnología (Vertex Pharmaceuticals) y consumo defensivo (Monster Beverage), sectores con dinámicas económicas diferenciadas y correlaciones imperfectas.
Descripción general y sector: Adobe Inc. es una compañía tecnológica estadounidense fundada en 1982, con sede en San José, California. Opera en el sector de Software de Aplicaciones del S&P 500 y es una de las compañías líderes a nivel mundialen software creativo y documentos digitales. Sus plataformas Creative Cloud, Document Cloud y Experience Cloud atienden a más de 30 millones de suscriptores activos bajo un modelo de suscripción recurrente (Software as a Service, SaaS) (Adobe Inc., 2025).
Principales fuentes de ingresos: En el año fiscal 2025 (cerrado en noviembre), Adobe reportó ingresos totales de USD 23,769 millones (+10.5 % interanual). El segmento Digital Media que agrupa Creative Cloud y Document Cloud aportó USD 17,650 millones (74 % del total), mientras que Digital Experience contribuyó con USD 5,860 millones. El Annual Recurring Revenue (ARR) alcanzó USD 25,200 millones, con más de un tercio proveniente de productos que incorporan capacidades de inteligencia artificial (Adobe Inc., 2025).
Evolución reciente del precio de mercado: La acción experimentó una caída de aproximadamente el 42 % desde sus máximos históricos cercanos a USD 540 en 2024, cerrando en torno a USD 247 al 30 de abril de 2026. Esta corrección estuvo asociada al temor del mercado frente al posible impacto de herramientas de inteligencia artificial generativa sobre el modelo de suscripción de Creative Cloud, especialmente ante el crecimiento de alternativas de bajo costo y software abierto. No obstante, los indicadores técnicos sugieren condiciones de sobreventa (RSI ≈ 29), y el 21 de abril de 2026 el directorio aprobó un programa de recompra de acciones por USD 25,000 millones con vigencia hasta 2030, lo que podría contribuir a fortalecer la confianza del mercado sobre la valoración futura de la compañía (StockAnalysis, 2026; Benzinga, 2026).
Situación financiera: La utilidad neta GAAP de FY2025 fue de USD 7,130 millones (+28.2 %), con EPS GAAP de USD 16.73 (+34.6 %). El flujo de caja operativo superó los USD 10,000 millones anuales, con un margen neto del 30 %. La compañía opera sin niveles excesivos de endeudamiento y mantiene una relación D/E de 0.41 (FullRatio, 2026).
Expectativas de precio: El consenso de aproximadamente 55 analistas al 30 de abril de 2026 proyecta un precio objetivo mediano de USD 317 y USD 347 para los próximos 12 meses, lo que representa un potencial de valoración cercano al 28–40. Adicionalmente, la guidance corporativa para FY2026 contempla ingresos entre USD 25,900 y USD 26,100 millones y EPS no-GAAP entre USD 23.30 y USD 23.50 (TickerNerd, 2026a).
Justificación de inclusión: Adobe fue incluida en el portafolio como una apuesta de recuperación dentro del sector tecnológico. A pesar de la corrección significativa observada en su precio durante 2025–2026, la compañía continúa mostrando fundamentos financieros sólidos, caracterizados por altos márgenes operacionales, fuerte generación de flujo de caja y una posición competitiva relevante en software creativo y documental. Adicionalmente, el ajuste reciente del precio parece reflejar un escenario de deterioro más severo del que sugieren sus indicadores operacionales y financieros, particularmente frente a los riesgos asociados a la inteligencia artificial generativa. Desde la perspectiva del portafolio, Adobe aporta exposición al sector tecnológico y potencial de valorización, equilibrando el perfil de riesgo del conjunto. Su inclusión como activo tecnológico complementa la naturaleza defensiva de los otros dos instrumentos seleccionados, contribuyendo a una mayor diversificación sectorial del portafolio (Markowitz, 1952).
Descripción general y sector: Vertex Pharmaceuticals, fundada en 1989 y con sede en Boston, Massachusetts, opera en el sector Farmacéutica/Biofarmacéutica del S&P 500. La compañía es una de las líderes a nivel mundial en el tratamiento de la fibrosis quística (FQ), cubriendo más del 90 % de los pacientes elegibles mediante su franquicia terapéutica Trikafta/Kaftrio (Vertex Pharmaceuticals, 2026a).
Principales fuentes de ingresos: Los ingresos de FY2025 alcanzaron USD 12,000 millones (+9 % interanual), con la franquicia de fibrosis quística aportando aproximadamente USD 11,200 millones. Adicionalmente, CASGEVY la primera terapia basada en tecnología CRISPR aprobada para enfermedad de células falciform y JOURNAVX analgésico no opioide aprobado por la FDA en 2025 aportaron conjuntamente más del 25 % del crecimiento registrado durante el primer trimestre de 2026 (Vertex Pharmaceuticals, 2026b).
Evolución reciente del precio de mercado: La acción ha mostrado mayor estabilidad relativa frente a compañías tecnológicas, cotizando entre USD 362 y USD 511 durante las últimas 52 semanas y ubicándose alrededor de USD 441 al 30 de abril de 2026. Esta resiliencia parece asociarse a la predictibilidad de los ingresos provenientes de fibrosis quística y a la confianza del mercado en la capacidad de ejecución del pipeline clínico de la compañía (Investing.com, 2026).
Situación financiera: Vertex reportó una utilidad neta de USD 3,950 millones en FY2025, un margen operativo de 34.7 %, caja e inversiones por USD 12,300 millones y una relación D/E igual a cero. Esta sólida posición financiera permite financiar investigación y desarrollo, así como adquisiciones estratégicas como Alpine Immune Sciences por USD 4,900 millones sin generar dilución significativa para los accionistas (Vertex Pharmaceuticals, 2026a).
Expectativas de precio: El consenso entre 29 y 47 analistas proyecta un precio objetivo mediano entre USD 548 y USD 558 para los próximos 12 meses, equivalente a un potencial de valorización aproximado del 25–27 %. Morgan Stanley mantiene un precio objetivo de USD 612 (Overweight). Uno de los principales factores de crecimiento esperados en el horizonte de 4 años corresponde a la posible aprobación de povetacicept para nefropatía por IgA, ampliando la diversificación terapéutica de la compañía (Benzinga, 2026b).
Justificación de inclusión: Vertex cumple el rol de activo estabilizador dentro del portafolio debido a la predictibilidad de sus ingresos y a su menor sensibilidad frente a los ciclos del mercado. Su liderazgo en tratamientos para fibrosis quística, junto con una posición financiera sólida y ausencia de endeudamiento relevante, le otorgan un perfil defensivo frente a escenarios adversos.Al mismo tiempo, la compañía mantiene oportunidades de crecimiento asociadas a nuevas terapias y expansión de su pipeline, evitando sacrificar completamente el potencial de rentabilidad. Desde la perspectiva del portafolio, Vertex contribuye a reducir el riesgo agregado gracias a su menor correlación relativa frente a Adobe y Monster Beverage. Su perfil defensivo y su baja sensibilidad al ciclo económico la posicionan como el activo con mayor capacidad de estabilización dentro del portafolio, lo que resulta determinante en el proceso de optimización media-varianza (Markowitz, 1952).
Descripción general y sector: Monster Beverage Corporation, fundada en 1985 y con sede en Corona, California, opera en el sector Consumo Defensivo del S&P 500. La compañía es uno de los principales fabricantes globales de bebidas energéticas y distribuye sus productos en más de 150 países a través de la red de embotelladoras de Coca-Cola, bajo un acuerdo estratégico vigente desde 2015 (Yahoo Finance, 2026c).
Principales fuentes de ingresos: Los ingresos de FY2025 ascendieron a USD 8,294 millones (+10.7 %), con el segmento Monster Energy Drinks aportando aproximadamente el 92 % del total. Durante el primer trimestre de 2026 (reportado el 7 de mayo de 2026), las ventas netas crecieron 26.9 % interanual hasta USD 2,350 millones, superando el consenso de mercado de USD 2,160 millones. Las ventas internacionales crecieron cerca de 45 % y ya representan aproximadamente el 45 % de los ingresos consolidados (Monster Beverage Corporation, 2026).
Evolución reciente del precio de mercado: Desde su mínimo de 52 semanas de USD 50.93, la acción registró un incremento aproximado del 64.5 %, alcanzando un nuevo máximo histórico de USD 88.77 el 8 de mayo de 2026 tras la publicación de resultados del primer trimestre. Al 30 de abril de 2026 fecha de referencia de la inversión cotizaba alrededor de USD 77, reflejando una trayectoria alcista sostenida antes de dicho resultado financiero (TradingView, 2026).
Situación financiera: Reportó un margen bruto de 55.8 % en FY2025 (expansión de 180 puntos básicos), un margen operativo de 30.7 % y una relación D/E de 0.07. La compañía opera bajo un modelo de baja intensidad en activos subcontrata manufactura y utiliza la red de distribución de Coca-Cola, lo que favorece una elevada generación de flujo de caja libre sin requerir inversiones significativas en infraestructura propia (TIKR, 2026a).
Expectativas de precio: Tras los resultados del primer trimestre de 2026, diversas entidades financieras actualizaron sus precios objetivo: Rothschild & Co Redburn (USD 90, upgrade a Buy), Deutsche Bank (USD 88–90, Buy), Wells Fargo (USD 85, Overweight) y BofA (USD 96–102, Buy) (StockAnalysis, 2026c).
Dividendos: Monster Beverage no distribuye dividendos en efectivo. La política de la compañía consiste en reinvertir la generación de caja en crecimiento orgánico, adquisiciones estratégicas y recompras de acciones. La ausencia de pagos de dividendos puede verificarse mediante el perfil corporativo de Yahoo Finance (2026c), los reportes oficiales ante la SEC y plataformas especializadas como DividendMax, las cuales reportan ausencia histórica de dividendos en efectivo para la compañía.
Justificación de inclusión: Monster Beverage fue incorporada al portafolio como una alternativa de consumo defensivo con capacidad de crecimiento sostenido. A diferencia de Adobe y Vertex, la compañía aporta exposición a un sector menos sensible a cambios tecnológicos o regulatorios, favoreciendo la diversificación del riesgo agregado del portafolio. Su modelo de negocio presenta márgenes elevados, bajo endeudamiento y una expansión internacional relevante respaldada por la red de distribución de Coca-Cola, factores que respaldan la solidez financiera de la empresa. Aunque su crecimiento esperado de utilidades (10.8 %) se ubica ligeramente por debajo del umbral mínimo definido del 12 %, fue retenida debido a su capacidad de diversificación sectorial, estabilidad operativa y menor exposición sistemática frente a las demás acciones seleccionadas. Asimismo, su beta relativamente baja contribuye a moderar la exposición sistemática total del portafolio. Su inclusión como activo de consumo defensivo complementa el perfil tecnológico de Adobe y el perfil farmacéutico de Vertex, favoreciendo una estructura de portafolio diversificada tanto a nivel sectorial como en términos de sensibilidad al ciclo económico (Fabozzi et al., 2007).
library(quantmod)
inicio <- "2018-01-01"
fin <- as.Date("2026-04-30")
descargar <- function(ticker, from, to) {
tryCatch(getSymbols(ticker, src="yahoo", from=from, to=to, auto.assign=FALSE),
error=function(e){ message("Error: ", ticker); NULL })
}
sp500 <- descargar("^GSPC", inicio, fin)
adbe <- descargar("ADBE", inicio, fin)
vrtx <- descargar("VRTX", inicio, fin)
mnst <- descargar("MNST", inicio, fin)
tnx <- descargar("^TNX", inicio, fin)
futuro <- tryCatch(
getSymbols("ES=F", src="yahoo", from=inicio, to=fin, auto.assign=FALSE),
error=function(e){ message("ES=F no disponible, usando ^GSPC como proxy"); sp500 })
datos_xts <- merge(Ad(sp500), Ad(futuro), Ad(adbe), Ad(vrtx), Ad(mnst),
Ad(tnx), join="inner")
colnames(datos_xts) <- c("SP500","SP500F","ADBE","VRTX","MNST","TNX")
datos_xts <- na.omit(datos_xts)
datos <- data.frame(Fecha=index(datos_xts), coredata(datos_xts))
rownames(datos) <- NULL
info_df <- data.frame(
Concepto = c("Fecha inicial","Fecha final","Observaciones diarias"),
Valor = c(format(min(datos$Fecha),"%d/%m/%Y"),
format(max(datos$Fecha),"%d/%m/%Y"),
as.character(nrow(datos)))
)
kable(info_df, col.names=c("Concepto","Valor"),
caption="Información del período histórico descargado") |>
kable_styling(bootstrap_options=c("striped","hover"), full_width=FALSE) |>
column_spec(1, bold=TRUE)| Concepto | Valor |
|---|---|
| Fecha inicial | 02/01/2018 |
| Fecha final | 29/04/2026 |
| Observaciones diarias | 2092 |
ret <- data.frame(
Fecha = datos$Fecha[-1],
SP500 = diff(log(datos$SP500)),
SP500F = diff(log(datos$SP500F)),
ADBE = diff(log(datos$ADBE)),
VRTX = diff(log(datos$VRTX)),
MNST = diff(log(datos$MNST))
)
ret <- na.omit(ret)
# Retornos mensuales (último cierre de mes)
datos$YM <- format(datos$Fecha, "%Y-%m")
mensual <- datos |> group_by(YM) |> slice_tail(n=1) |> ungroup() |> arrange(Fecha)
ret_m <- data.frame(
Fecha = mensual$Fecha[-1],
SP500 = diff(log(mensual$SP500)),
SP500F = diff(log(mensual$SP500F)),
ADBE = diff(log(mensual$ADBE)),
VRTX = diff(log(mensual$VRTX)),
MNST = diff(log(mensual$MNST))
) |> na.omit()
met_df <- data.frame(
Concepto = c("Retornos diarios calculados",
"Retornos mensuales calculados",
"Frecuencia para estadísticas",
"Anualización — Retorno",
"Anualización — Volatilidad"),
Valor = c(as.character(nrow(ret)),
as.character(nrow(ret_m)),
"Diaria (252 días hábiles/año)",
"exp(μ_d × 252) − 1",
"σ_d × √252"))
kable(met_df, col.names=c("Concepto","Valor"),
caption="Configuración de retornos y anualización") |>
kable_styling(bootstrap_options=c("striped","hover"), full_width=FALSE) |>
column_spec(1, bold=TRUE) |>
column_spec(2, width="60%")| Concepto | Valor |
|---|---|
| Retornos diarios calculados | 2091 |
| Retornos mensuales calculados | 99 |
| Frecuencia para estadísticas | Diaria (252 días hábiles/año) |
| Anualización — Retorno | exp(μ_d × 252) − 1 |
| Anualización — Volatilidad | σ_d × √252 |
Aunque se calcularon retornos mensuales para fines comparativos y de consistencia temporal con la liquidación trimestral del ejercicio, las estimaciones de riesgo y optimización del portafolio se realizaron con retornos diarios, dado que proporcionan un número significativamente mayor de observaciones y estimaciones más estables de media, volatilidad y covarianza.
anualizar <- function(rv, freq=252) {
list(mu = exp(mean(rv,na.rm=TRUE)*freq)-1,
sigma = sd(rv,na.rm=TRUE)*sqrt(freq))
}
activos <- c("ADBE","VRTX","MNST")
stats_d <- lapply(activos, function(a) {
r <- ret[[a]]; e <- anualizar(r)
data.frame(Activo=a,
Ret_Diario = round(mean(r)*100, 4), # en % con 4 decimales
Ret_Anual = round(e$mu*100, 2),
Vol_Diaria = round(sd(r)*100, 4),
Vol_Mensual = round(sd(r)*sqrt(21)*100, 2),
Vol_Anual = round(e$sigma*100, 2),
Min = round(min(r)*100, 2),
Max = round(max(r)*100, 2))
}) |> bind_rows()
kable(stats_d, digits=4,
col.names=c("Activo","Ret. Diario (%)","Ret. Anual (%)","Vol. Diaria (%)",
"Vol. Mensual (%)","Vol. Anual (%)","Ret. Mínimo (%)","Ret. Máximo (%)"),
caption="Tabla 2. Estadísticas descriptivas de retornos (diarios, 2018–2026)") |>
kable_styling(bootstrap_options=c("striped","hover"), full_width=TRUE)| Activo | Ret. Diario (%) | Ret. Anual (%) | Vol. Diaria (%) | Vol. Mensual (%) | Vol. Anual (%) | Ret. Mínimo (%) | Ret. Máximo (%) |
|---|---|---|---|---|---|---|---|
| ADBE | 0.0151 | 3.87 | 2.2908 | 10.50 | 36.37 | -18.38 | 16.31 |
| VRTX | 0.0487 | 13.05 | 2.0185 | 9.25 | 32.04 | -23.19 | 14.11 |
| MNST | 0.0429 | 11.42 | 1.6891 | 7.74 | 26.81 | -15.59 | 8.46 |
Nota metodológica: Se emplearon retornos logarítmicos continuos con frecuencia diaria, debido a que permiten una mejor agregación temporal y son ampliamente utilizados en modelos de riesgo y optimización financiera (Bodie et al., 2008). La volatilidad anual se estimó aplicando la regla de la raíz del tiempo:
\(\hat{\sigma}_{anual} = \hat{\sigma}_{diaria} \times \sqrt{252}\)
donde 252 representa el número aproximado de días bursátiles del mercado estadounidense en un año. El retorno esperado anual se obtuvo mediante la transformación exponencial de los retornos diarios:
\(\hat{\mu}_{anual} = e^{\bar{r}_{diario} \times 252} - 1\)
Aunque se calcularon retornos mensuales para mantener consistencia con la liquidación trimestral del ejercicio, las estimaciones de media, volatilidad y covarianza empleadas en la optimización del portafolio se realizaron utilizando retornos diarios, dado que proporcionan un número significativamente mayor de observaciones (2,091 frente a aproximadamente 99 mensuales), mejorando la estabilidad estadística de los estimadores utilizados posteriormente en el modelo de Markowitz.
Interpretación de estadísticas descriptivas: Vertex Pharmaceuticals presenta el mayor retorno esperado anual (13.05 %), acompañado de una volatilidad anual inferior a Adobe, lo que sugiere una relación retorno-riesgo relativamente favorable. Monster Beverage exhibe la menor volatilidad del grupo (26.81 % anual), aportando estabilidad al portafolio, mientras que Adobe presenta la mayor volatilidad (36.37 %), consistente con su mayor exposición al sector tecnológico y sensibilidad frente a cambios en expectativas de crecimiento. Estas diferencias refuerzan el potencial de diversificación entre los activos seleccionados.
cov_mat <- cov(ret[,activos]) * 252
cor_mat <- cor(ret[,activos])
kable(cov_mat*1e4, digits=3,
caption="Tabla 3. Matriz anualizada de varianzas-covarianzas (×10⁴)") |>
kable_styling(bootstrap_options=c("striped","hover"))| ADBE | VRTX | MNST | |
|---|---|---|---|
| ADBE | 1322.461 | 405.116 | 385.838 |
| VRTX | 405.116 | 1026.785 | 283.345 |
| MNST | 385.838 | 283.345 | 718.929 |
kable(cor_mat, digits=4,
caption="Tabla 4. Matriz de correlaciones") |>
kable_styling(bootstrap_options=c("striped","hover"))| ADBE | VRTX | MNST | |
|---|---|---|---|
| ADBE | 1.0000 | 0.3477 | 0.3957 |
| VRTX | 0.3477 | 1.0000 | 0.3298 |
| MNST | 0.3957 | 0.3298 | 1.0000 |
corrplot(cor_mat,
method = "color",
addCoef.col = "black",
number.cex = 1.1,
number.digits = 2,
tl.col = "#2d3748",
tl.srt = 45,
tl.cex = 0.95,
cl.cex = 0.85,
col = colorRampPalette(c("#f7c59f","#ffffff","#2c5282"))(200),
col.lim = c(-1, 1),
title = "Figura 1. Mapa de calor — Correlaciones entre acciones",
mar = c(0, 0, 2, 0))Análisis de correlaciones: Las correlaciones entre las tres acciones son positivas pero moderadas, lo que confirma la existencia de beneficios de diversificación al combinarlas dentro de un mismo portafolio (Hull, 2009). De acuerdo con la teoría de Markowitz, correlaciones inferiores a uno permiten reducir el riesgo agregado mediante la combinación de activos cuyo comportamiento no se mueve perfectamente en conjunto. La correlación relativamente mayor entre Adobe y Monster (~0.40) podría explicarse por cierta exposición compartida al comportamiento general del mercado estadounidense, aunque pertenecen a sectores económicos distintos tecnología y consumo defensivo, respectivamente. Por su parte, Vertex presenta las correlaciones más bajas (~0.33–0.35), reforzando su papel como activo estabilizador dentro del portafolio, dado que la demanda de tratamientos farmacéuticos suele depender menos del ciclo económico que los sectores tecnológico y de consumo. En conjunto, la estructura de correlaciones observada respalda la combinación sectorial seleccionada y favorece la reducción del riesgo total del portafolio.
precio_norm <- datos |>
select(Fecha, ADBE, VRTX, MNST) |>
na.omit() |>
mutate(ADBE=ADBE/ADBE[1], VRTX=VRTX/VRTX[1], MNST=MNST/MNST[1]) |>
pivot_longer(-Fecha, names_to="Accion", values_to="Precio")
ggplot(precio_norm, aes(x=Fecha, y=Precio, color=Accion)) +
geom_line(linewidth=0.8) +
scale_color_manual(values=pal_acc) +
scale_y_continuous(labels=label_number(suffix="x")) +
geom_vline(xintercept=as.Date("2026-04-30"), linetype="dashed", color="black", alpha=0.5) +
annotate("text", x=as.Date("2026-04-30"), y=max(precio_norm$Precio)*0.9,
label="Inicio inversión\n30 abr 2026", hjust=1.1, size=3, color="black") +
labs(title="Figura 2. Retorno acumulado normalizado (base=1 en ene-2018)",
subtitle="Línea punteada: fecha de inicio de la inversión (30/04/2026)",
x=NULL, y="Retorno normalizado", color="Acción") +
tema_lab + theme(legend.position="top")La evolución normalizada de precios evidencia trayectorias de crecimiento diferenciadas entre los activos seleccionados. Vertex presenta un comportamiento relativamente más estable a lo largo del período, consistente con su perfil defensivo y menor sensibilidad al ciclo económico. Adobe exhibe mayor volatilidad, particularmente durante el ajuste de expectativas relacionado con la inteligencia artificial generativa en 2025–2026. Monster muestra una tendencia alcista sostenida respaldada por la expansión internacional y el crecimiento de ingresos, aportando equilibrio entre estabilidad y potencial de valorización al portafolio.
mu_anual <- sapply(activos, function(a) anualizar(ret[[a]])$mu)
sigma_anual <- sapply(activos, function(a) anualizar(ret[[a]])$sigma)
Rf_anual <- 0.0402
Rf_mensual <- (1+Rf_anual)^(1/12)-1
Rf_trim <- (1+Rf_anual)^(1/4)-1
capital <- 20e6
# ── Tabla de parámetros de entrada ───────────────────────────────────────────
params_df <- data.frame(
Parametro = c("Retorno anual esperado",
"Volatilidad anual",
"Tasa libre de riesgo — Rf anual (^TNX 5Y)",
"Tasa libre de riesgo — Rf mensual equivalente",
"Tasa libre de riesgo — Rf trimestral equivalente",
"Capital total invertido"),
ADBE = c(fmt_pct(mu_anual["ADBE"]), fmt_pct(sigma_anual["ADBE"]),
"—","—","—","—"),
VRTX = c(fmt_pct(mu_anual["VRTX"]), fmt_pct(sigma_anual["VRTX"]),
"—","—","—","—"),
MNST = c(fmt_pct(mu_anual["MNST"]), fmt_pct(sigma_anual["MNST"]),
"—","—","—","—"),
Global = c("—","—",
fmt_pct(Rf_anual),
fmt_pct(Rf_mensual),
fmt_pct(Rf_trim),
paste0("USD ", fmt_usd(capital)))
)
kable(params_df,
col.names = c("Parámetro","ADBE","VRTX","MNST","Global / Portafolio"),
caption = "Tabla de parámetros de entrada para la optimización (Fuente: Yahoo Finance, 2026; CBOE, 2026)") |>
kable_styling(bootstrap_options = c("striped","hover","condensed"),
full_width = TRUE) |>
column_spec(1, bold = TRUE)| Parámetro | ADBE | VRTX | MNST | Global / Portafolio |
|---|---|---|---|---|
| Retorno anual esperado | 3.87% | 13.05% | 11.42% | — |
| Volatilidad anual | 36.37% | 32.04% | 26.81% | — |
| Tasa libre de riesgo — Rf anual (^TNX 5Y) | — | — | — | 4.02% |
| Tasa libre de riesgo — Rf mensual equivalente | — | — | — | 0.33% |
| Tasa libre de riesgo — Rf trimestral equivalente | — | — | — | 0.99% |
| Capital total invertido | — | — | — | USD 20,000,000.00 |
set.seed(123)
N_sim <- 500000
sim_w <- matrix(runif(N_sim*3), ncol=3)
sim_w <- sim_w / rowSums(sim_w)
sim_w <- sim_w[apply(sim_w,1,function(w) all(w>=0.15) & all(w<=0.60)),] # peso mínimo 15%, máximo 60%
ret_sim <- sim_w %*% mu_anual
sigma_sim <- sqrt(rowSums((sim_w %*% cov_mat)*sim_w))
sharpe_sim <- (ret_sim - Rf_anual)/sigma_sim
idx_best <- which.max(sharpe_sim)
w_opt <- sim_w[idx_best,]; names(w_opt) <- activos
idx_minvar <- which.min(sigma_sim)
ret_port <- sum(w_opt*mu_anual)
sigma_port <- sqrt(as.numeric(t(w_opt)%*%cov_mat%*%w_opt))
sharpe_port<- (ret_port-Rf_anual)/sigma_port
ret_port_m <- (1+ret_port)^(1/12)-1
sigma_port_m <- sigma_port/sqrt(12)
w_check <- data.frame(
Restriccion = c("Peso mínimo por acción (w_i >= 15 %)",
"Peso máximo por acción (w_i <= 60 %)",
"Suma de pesos igual a 100 %"),
Resultado = c(ifelse(all(w_opt >= 0.15), "Cumple", "No cumple"),
ifelse(all(w_opt <= 0.60), "Cumple", "No cumple"),
ifelse(abs(sum(w_opt) - 1) < 1e-6, "Cumple", "No cumple"))
)
kable(w_check, col.names = c("Restricción","Resultado"),
caption = "Verificación de restricciones del portafolio óptimo") |>
kable_styling(bootstrap_options = c("striped","hover"), full_width = FALSE) |>
column_spec(2, color = ifelse(w_check$Resultado == "Cumple", "#276749", "#c53030"),
bold = TRUE)| Restricción | Resultado |
|---|---|
| Peso mínimo por acción (w_i >= 15 %) | Cumple |
| Peso máximo por acción (w_i <= 60 %) | Cumple |
| Suma de pesos igual a 100 % | Cumple |
resumen_opt <- data.frame(
Accion = activos,
Peso = unname(w_opt),
Monto = unname(w_opt * capital),
Ret = unname(mu_anual),
Vol = unname(sigma_anual)
)
kable(resumen_opt, digits=4,
col.names=c("Acción","Peso (w_i)","Monto invertido (USD)","Retorno anual","Vol. anual"),
caption="Tabla 5. Portafolio óptimo de máximo Sharpe Ratio",
format.args=list(big.mark=",")) |>
kable_styling(bootstrap_options=c("striped","hover"), full_width=TRUE)| Acción | Peso (w_i) | Monto invertido (USD) | Retorno anual | Vol. anual |
|---|---|---|---|---|
| ADBE | 0.1501 | 3,001,516 | 0.0387 | 0.3637 |
| VRTX | 0.4242 | 8,483,972 | 0.1305 | 0.3204 |
| MNST | 0.4257 | 8,514,512 | 0.1142 | 0.2681 |
metricas <- data.frame(
Metrica = c("Retorno esperado anual","Volatilidad anual","Sharpe Ratio",
"Retorno mensual equivalente (geométrico)","Volatilidad mensual",
"Capital total invertido"),
Valor = c(fmt_pct(ret_port), fmt_pct(sigma_port), round(sharpe_port,4),
fmt_pct(ret_port_m), fmt_pct(sigma_port_m),
paste0("USD ",fmt_usd(capital)))
)
kable(metricas, col.names=c("Métrica","Valor"),
caption="Tabla 6. Métricas del portafolio óptimo") |>
kable_styling(bootstrap_options=c("striped","hover"), full_width=FALSE)| Métrica | Valor |
|---|---|
| Retorno esperado anual | 10.98% |
| Volatilidad anual | 23.41% |
| Sharpe Ratio | 0.2973 |
| Retorno mensual equivalente (geométrico) | 0.87% |
| Volatilidad mensual | 6.76% |
| Capital total invertido | USD 20,000,000.00 |
Análisis del portafolio óptimo: El modelo de optimización asigna a Vertex Pharmaceuticals (VRTX) el mayor peso del portafolio (42.42%), lo cual resulta consistente con sus características: menor volatilidad relativa, baja correlación con los demás activos y una relación retorno-riesgo favorable dentro del universo seleccionado. Monster Beverage (MNST) recibe la segunda mayor participación (42.57%), reflejando su rol como activo de consumo defensivo con menor exposición al ciclo económico. Adobe (ADBE) obtiene el menor peso (15.01%), consistente con su mayor nivel de volatilidad relativa dentro del portafolio, aunque su inclusión aporta diversificación sectorial y potencial de recuperación de valor. En conjunto, la combinación sectorial de tecnología, salud y consumo defensivo permite reducir el riesgo agregado mediante diversificación y refleja una relación más eficiente entre rentabilidad esperada y riesgo asumido que cualquiera de las acciones de forma individual (Markowitz, 1952).
La construcción del portafolio óptimo no solo requiere maximizar el Ratio de Sharpe como función objetivo, sino también establecer restricciones que garanticen una asignación financieramente razonable, diversificada y aplicable desde una perspectiva de gestión de inversiones. En este sentido, las restricciones implementadas buscan evitar concentraciones excesivas del capital, asegurar una participación material de cada activo y mantener un equilibrio adecuado entre eficiencia matemática y control del riesgo.
Restricción de suma igual al 100 %. La condición \(\sum_{i=1}^{3} w_i = 1\) garantiza que la totalidad del capital disponible (USD 20,000,000) sea asignada entre las tres acciones, evitando mantener recursos improductivos en efectivo o asumir posiciones apalancadas. Esta restricción es consistente con la construcción de un portafolio completamente invertido en renta variable (Bodie et al., 2008).
Restricción de participación mínima. La restricción de participación mínima se estableció como \(w_i \geq 0.15\), con el propósito de asegurar que cada activo mantuviera una participación económicamente relevante dentro del portafolio. En términos financieros, una asignación inferior podría generar posiciones marginales con impacto limitado tanto sobre el retorno esperado como sobre el perfil de riesgo agregado, reduciendo el beneficio efectivo de incorporar el activo dentro de la estrategia de diversificación.
En el contexto del capital administrado (USD 20,000,000), este umbral implica una inversión mínima aproximada de USD 3,000,000 por activo, magnitud considerada suficientemente material para que cada posición contribuya de forma significativa al desempeño total del portafolio. Adicionalmente, la restricción evita soluciones extremas del proceso de optimización media varianza, en las cuales el algoritmo podría asignar pesos residuales a ciertos activos y concentrar excesivamente el capital en una única posición, reduciendo la efectividad de la diversificación (Elton et al., 2014).
Desde una perspectiva de gestión institucional, la implementación de límites mínimos de participación resulta consistente con prácticas comunes en portafolios concentrados de pocos instrumentos, donde suelen establecerse umbrales cercanos al 10 %–15 % por activo para asegurar relevancia económica y una diversificación efectiva del riesgo (Fabozzi et al., 2007).
Restricción de participación máxima El límite superior \(w_i \leq 0.60\) se sustenta en un criterio de control de concentración apoyado en el Índice de Herfindahl-Hirschman (IHH), indicador utilizado para medir el grado de concentración de un portafolio: \(IHH = \sum w_i^2\)
Un portafolio perfectamente diversificado con tres activos iguales tiene \(IHH_{equitativo} = 3 \times (1/3)^2 = 0.333\)
Con el fin de evitar una concentración excesiva, se adoptó como referencia un umbral conservador de \(IHH \leq 0.50\), consistente con una estructura de portafolio concentrado, pero aún diversificada (Fabozzi et al., 2007). Considerando además una participación mínima de 15 % para los otros dos activos, se obtiene:
\[w_{max}^2 + 0.15^2 + 0.15^2 \leq 0.50 \implies w_{max}^2 \leq 0.455 \implies w_{max} \leq \sqrt{0.455} \approx 0.674\]
A partir de este resultado, se adoptó de forma conservadora un límite operativo de 60 %, redondeando hacia abajo para preservar un nivel razonable de diversificación sin restringir completamente la capacidad del optimizador para privilegiar el activo con mejor relación retorno-riesgo. De esta manera, el umbral seleccionado evita concentraciones extremas del capital, manteniendo simultáneamente flexibilidad suficiente para reflejar diferencias reales de eficiencia entre los activos seleccionados.
# IHH máximo permitido bajo la estructura de pesos extrema: 60 % / 25 % / 15 %
# 0.60^2 + 0.25^2 + 0.15^2 = 0.3600 + 0.0625 + 0.0225 = 0.4450
ihh_max <- 0.60^2 + 0.25^2 + 0.15^2
ihh_port <- sum(w_opt^2)
ihh_df <- data.frame(
Metrica = c("IHH portafolio equitativo (33.3/33.3/33.3)",
"IHH portafolio óptimo obtenido",
"IHH máximo permitido bajo restricciones (60/25/15)"),
Valor = c("0.3333", round(ihh_port, 4), round(ihh_max, 4)),
Evaluacion = c("Referencia de máxima diversificación con 3 activos",
ifelse(ihh_port <= ihh_max,
"Concentración moderada — dentro del umbral definido",
"Excede umbral — revisar restricciones"),
"Concentración máxima admisible bajo estructura de pesos")
)
kable(ihh_df,
col.names = c("Métrica", "Valor IHH", "Evaluación"),
caption = "Tabla. Verificación de concentración mediante el Índice de Herfindahl-Hirschman") |>
kable_styling(bootstrap_options = c("striped","hover"), full_width = TRUE) |>
column_spec(3, color = c("#4a7fa5","#276749","#4a7fa5"))| Métrica | Valor IHH | Evaluación |
|---|---|---|
| IHH portafolio equitativo (33.3/33.3/33.3) | 0.3333 | Referencia de máxima diversificación con 3 activos |
| IHH portafolio óptimo obtenido | 0.3837 | Concentración moderada — dentro del umbral definido |
| IHH máximo permitido bajo restricciones (60/25/15) | 0.445 | Concentración máxima admisible bajo estructura de pesos |
El portafolio óptimo presenta un Índice de Herfindahl-Hirschman (IHH) de 0.3837, superior al portafolio perfectamente equitativo (0.3333), pero inferior al máximo permitido bajo las restricciones definidas (0.4450). Este resultado sugiere una estructura moderadamente concentrada, consistente con un portafolio compuesto únicamente por tres activos, pero aún dentro de niveles razonables de diversificación. Asimismo, la verificación del IHH permite confirmar que la concentración del portafolio resultante se mantiene dentro de niveles razonables para una estrategia institucional con tres activos. El modelo privilegia los activos con mejor combinación histórica de retorno esperado, volatilidad y correlación, sin que las restricciones de participación hayan forzado artificialmente la solución. En ausencia de restricciones de concentración, los modelos de optimización media-varianza pueden favorecer de forma desproporcionada activos con mejores combinaciones históricas de retorno y riesgo, reduciendo el nivel efectivo de diversificación del portafolio (Markowitz, 1952; Elton et al., 2014).
front_df <- data.frame(Sigma=sigma_sim, Retorno=ret_sim, Sharpe=sharpe_sim)
# Tres puntos especiales para la leyenda manual
puntos_esp <- data.frame(
x = c(sigma_port, sigma_sim[idx_minvar]),
y = c(ret_port, ret_sim[idx_minvar]),
tipo = c("Máx. Sharpe","Mín. Varianza")
)
ggplot(front_df, aes(x=Sigma, y=Retorno)) +
geom_point(aes(color=Sharpe), size=0.5, alpha=0.5) +
scale_color_gradient(
low = "#a8d5e2",
high = "#2d4a6b",
name = "Sharpe",
guide = guide_colorbar(
barwidth = 8,
barheight = 0.55,
title.position = "left",
title.hjust = 0.5,
label.theme = element_text(size=8.5, color="#2d3748"),
ticks = FALSE
)
) +
geom_point(data=puntos_esp, aes(x=x, y=y, shape=tipo),
color=c("#c53030","#1a2b4a"), size=5) +
scale_shape_manual(
name = NULL,
values = c("Máx. Sharpe"=18, "Mín. Varianza"=15),
labels = c(
paste0("Portafolio óptimo (SR = ", round(sharpe_port,3), ")"),
paste0("Mín. Varianza (σ = ", round(sigma_sim[idx_minvar]*100,1), "%)")
)
) +
scale_x_continuous(labels=label_percent()) +
scale_y_continuous(labels=label_percent()) +
labs(
title = "Figura 3. Frontera eficiente del portafolio",
subtitle = "500,000 portafolios simulados bajo restricciones de participación (15 %–60 %) y capital de USD 20 millones",
x = "Volatilidad anual",
y = "Retorno esperado anual"
) +
tema_lab +
theme(
legend.position = "bottom",
legend.box = "horizontal",
legend.spacing.x = unit(0.6,"cm"),
legend.text = element_text(size=9),
legend.key.size = unit(0.45,"cm")
) +
guides(
color = guide_colorbar(order=1),
shape = guide_legend(order=2,
override.aes=list(color=c("#c53030","#1a2b4a"),
size=c(4,4)))
)La nube de portafolios simulados evidencia el trade-off tradicional entre rentabilidad esperada y riesgo asumido: a medida que aumenta el retorno esperado, también se incrementa la volatilidad del portafolio. El portafolio seleccionado se ubica próximo a la frontera eficiente y corresponde a la combinación que maximiza el Ratio de Sharpe dentro del conjunto de restricciones de participación definidas. Esto sugiere una relación favorable entre rentabilidad esperada y riesgo asumido, alcanzando un equilibrio consistente con el objetivo de diversificación sin renunciar completamente al potencial de valorización. La asignación relativamente balanceada entre Vertex Pharmaceuticals y Monster Beverage, junto con la menor participación de Adobe, refleja la preferencia del optimizador por activos con una combinación más favorable entre retorno esperado, volatilidad y correlación respecto al resto del portafolio (Markowitz, 1952).
El VaR paramétrico asume distribución normal: \(\text{VaR}_\alpha = -(\mu_m - z_\alpha \cdot \sigma_m)\).
z99 <- qnorm(0.99); z95 <- qnorm(0.95)
VaR99_pct <- -(ret_port_m - z99*sigma_port_m)
VaR95_pct <- -(ret_port_m - z95*sigma_port_m)
VaR99_usd <- VaR99_pct*capital
VaR95_usd <- VaR95_pct*capital
var_t <- data.frame(
NC = c("99 % (VaR 1 %)","95 % (VaR 5 %)"),
z = c(round(z99,4),round(z95,4)),
mu_m = c(fmt_pct(ret_port_m),fmt_pct(ret_port_m)),
sigma_m = c(fmt_pct(sigma_port_m),fmt_pct(sigma_port_m)),
pct = c(fmt_pct(VaR99_pct),fmt_pct(VaR95_pct)),
usd = c(paste0("USD ",fmt_usd(VaR99_usd)),paste0("USD ",fmt_usd(VaR95_usd)))
)
kable(var_t,
col.names=c("Nivel de Confianza","z","μ mensual","σ mensual","VaR (%)","VaR (USD)"),
caption="Tabla 7. VaR paramétrico mensual del portafolio") |>
kable_styling(bootstrap_options=c("striped","hover"))| Nivel de Confianza | z | μ mensual | σ mensual | VaR (%) | VaR (USD) |
|---|---|---|---|---|---|
| 99 % (VaR 1 %) | 2.3263 | 0.87% | 6.76% | 14.85% | USD 2,969,995.44 |
| 95 % (VaR 5 %) | 1.6449 | 0.87% | 6.76% | 10.24% | USD 2,048,865.04 |
Interpretación: Con un nivel de confianza del 99 %, se estima que, en el peor mes esperado de cada 100, el portafolio podría perder hasta 14.85% de su valor, equivalente a USD 2,969,995.44. bajo un nivel de confianza del 95 %, la pérdida mensual estimada disminuye a 10.24% qeuivalente a USD 2,048,865.04. Estos montos representan la exposición al riesgo del portafolio y justifican la implementación de una estrategia de cobertura con futuros, cuyo objetivo consiste en contribuir a compensar parcial o significativamente las pérdidas potenciales estimadas mediante el VaR, reconociendo que ninguna estrategia de cobertura elimina completamente el riesgo de mercado.
ret_port_hist <- as.matrix(ret[,activos]) %*% w_opt
VaR99h_d <- abs(quantile(ret_port_hist, 0.01))
VaR95h_d <- abs(quantile(ret_port_hist, 0.05))
VaR99h_m <- VaR99h_d*sqrt(21); VaR95h_m <- VaR95h_d*sqrt(21)
kable(data.frame(
NC=c("99 %","95 %"),
VaR_d=c(fmt_pct(VaR99h_d),fmt_pct(VaR95h_d)),
VaR_m=c(fmt_pct(VaR99h_m),fmt_pct(VaR95h_m)),
USD=c(paste0("USD ",fmt_usd(VaR99h_m*capital)),paste0("USD ",fmt_usd(VaR95h_m*capital)))),
col.names=c("NC","VaR Diario histórico","VaR Mensual escalado","VaR Mensual (USD)"),
caption="Tabla 8. VaR histórico del portafolio (simulación histórica)") |>
kable_styling(bootstrap_options=c("striped","hover"))| NC | VaR Diario histórico | VaR Mensual escalado | VaR Mensual (USD) |
|---|---|---|---|
| 99 % | 4.12% | 18.87% | USD 3,773,102.58 |
| 95 % | 2.29% | 10.51% | USD 2,101,798.62 |
Comparación VaR paramétrico vs. VaR histórico: El VaR paramétrico supone que los retornos siguen una distribución aproximadamente normal, lo que puede limitar su capacidad para representar eventos extremos presentes en mercados financieros reales. Por otro lado, el VaR histórico utiliza directamente la distribución empírica observada entre 2018 y 2026, incorporando episodios de alta volatilidad como la caída asociada al COVID-19 en 2020 y la corrección bursátil de 2022. Debido a ello, el VaR histórico suele capturar mejor los comportamientos extremos observados en la muestra, mientras que el paramétrico ofrece una aproximación más simple y consistente para modelación financiera. Para el diseño de la cobertura se empleará el VaR paramétrico al 99 % como referencia principal, manteniendo el VaR histórico como indicador complementario para la evaluación de escenarios de estrés.
ggplot(data.frame(r=ret_port_hist), aes(x=r)) +
geom_histogram(bins=80, fill="#2c5282", color="white", alpha=0.8) +
geom_vline(xintercept=-VaR99h_d, color="#c53030", linetype="dashed", linewidth=1) +
geom_vline(xintercept=-VaR95h_d, color="#dd6b20", linetype="dashed", linewidth=1) +
annotate("text",x=-VaR99h_d-0.002,y=50,label="VaR 99 %",color="#c53030",angle=90,size=3) +
annotate("text",x=-VaR95h_d-0.002,y=50,label="VaR 95 %",color="#dd6b20",angle=90,size=3) +
scale_x_continuous(labels=label_percent()) +
labs(title="Figura 4. Distribución de retornos diarios del portafolio",
subtitle="Líneas: VaR histórico al 99 % y 95 %",
x="Retorno diario", y="Frecuencia") + tema_labLa beta de cada acción se estima como la pendiente de la regresión CAPM: \[R_i = \alpha_i + \beta_i \, R_m + \varepsilon_i\] donde \(R_m\) es el retorno diario del S&P 500.
beta_ind <- sapply(activos, function(a) as.numeric(coef(lm(ret[[a]]~ret$SP500))[2]))
names(beta_ind) <- activos
beta_port <- sum(w_opt*beta_ind)
# (los resultados se muestran en la tabla beta_tabla a continuación)
beta_t <- data.frame(
Activo = c(activos,"PORTAFOLIO"),
Beta = c(round(beta_ind,4), round(beta_port,4)),
Peso = c(paste0(round(w_opt*100,2),"%"),"—"),
Contrib= c(round(w_opt*beta_ind,4), round(beta_port,4))
)
kable(beta_t, col.names=c("Activo","Beta","Peso","Contribución a β_p"),
caption="Tabla 9. Betas CAPM y beta del portafolio", align="c") |>
kable_styling(bootstrap_options=c("striped","hover"), full_width=FALSE) |>
row_spec(4, bold=TRUE, background="#f0f0f0")| Activo | Beta | Peso | Contribución a β_p | |
|---|---|---|---|---|
| ADBE | ADBE | 1.2365 | 15.01% | 0.1856 |
| VRTX | VRTX | 0.7594 | 42.42% | 0.3221 |
| MNST | MNST | 0.7676 | 42.57% | 0.3268 |
| PORTAFOLIO | 0.8345 | — | 0.8345 |
Interpretación: La beta estimada del portafolio estimada de \(\beta_p =\) 0.8345 indica que el portafolio presenta una sensibilidad menor a la del mercado accionario estadounidense. En términos prácticos, un movimiento del 1 % en el S&P 500 se asociaría, en promedio, con un cambio aproximado de 0.83% en el valor del portafolio en la misma dirección. Este resultado es consistente con las participaciones asignadas a Vertex Pharmaceuticals (42.42%) y Monster Beverage (42.57%), cuyas betas individuales son inferiores a uno y contribuyen a moderar la exposición sistemática agregada del portafolio.
Desde la perspectiva de administración de riesgo, una beta inferior a 1 implica menor sensibilidad frente a fluctuaciones del mercado, aspecto particularmente relevante para determinar la intensidad de la cobertura mediante contratos de futuros sobre índices bursátiles. En consecuencia, la cobertura requerida para neutralizar parcialmente el riesgo sistemático del portafolio será inferior a la de un portafolio con beta unitaria o superior (Hull, 2009).
# Data frame
beta_df2 <- data.frame(
Accion = factor(activos, levels = activos),
Beta = beta_ind
)
# Etiquetas
beta_df2$Label <- paste0("β = ", sprintf("%.3f", beta_df2$Beta))
# Posición dinámica de etiquetas
beta_df2$y_label <- ifelse(
abs(beta_df2$Beta - beta_port) < 0.08,
beta_df2$Beta - 0.07,
beta_df2$Beta + 0.05
)
# Colores
pal_acc <- c(
"ADBE" = "#1f4e79",
"VRTX" = "#2f6f4f",
"MNST" = "#8b3e1f"
)
# Límite eje Y
y_max2 <- max(beta_ind) * 1.45
# Gráfico
ggplot(beta_df2, aes(x = Accion, y = Beta)) +
# Barras
geom_col(
aes(fill = Accion),
width = 0.52,
color = "white",
linewidth = 0.8
) +
# Etiquetas beta
geom_label(
aes(y = y_label, label = Label),
size = 3.8,
fontface = "bold",
fill = "white",
color = "#2d3748",
label.size = 0.25,
label.padding = unit(0.18, "lines")
) +
# Línea mercado
geom_hline(
yintercept = 1,
linetype = "longdash",
color = "#a0aec0",
linewidth = 0.9
) +
annotate(
"text",
x = 0.60,
y = 1.035,
label = "β mercado = 1",
color = "#718096",
size = 3.2,
hjust = 0
) +
# Línea beta portafolio
geom_hline(
yintercept = beta_port,
color = "#c53030",
linewidth = 1.4
) +
# Etiqueta beta portafolio
annotate(
"label",
x = 2,
y = beta_port + 0.12,
label = paste0(
"β portafolio = ",
sprintf("%.3f", beta_port)
),
color = "#c53030",
fill = "white",
fontface = "bold",
size = 3.8,
label.size = 0.3
) +
# Colores
scale_fill_manual(values = pal_acc) +
# Escala eje Y
scale_y_continuous(
limits = c(0, y_max2),
breaks = seq(0, ceiling(y_max2 * 5) / 5, by = 0.2),
expand = expansion(mult = c(0, 0.06))
) +
# Títulos
labs(
title = "Figura 5. Betas Individuales y Beta del Portafolio",
subtitle = "Línea roja: β ponderado del portafolio · Línea punteada: β = 1 (mercado)",
x = NULL,
y = "Beta (β)",
caption = expression(
"Estimación por regresión CAPM: " *
R[i] == alpha + beta[i] %*% R[m]
)
) +
# Tema general
theme_minimal(base_size = 12) +
# Personalización
theme(
legend.position = "none",
axis.text.x = element_text(
size = 12,
face = "bold",
color = "#2d3748"
),
axis.title.y = element_text(
size = 12,
face = "bold"
),
plot.title = element_text(
size = 18,
face = "bold",
hjust = 0.5,
color = "#1a202c"
),
plot.subtitle = element_text(
size = 11,
hjust = 0.5,
color = "#4a5568"
),
plot.caption = element_text(
size = 9,
face = "italic",
color = "#718096"
),
panel.grid.minor = element_blank()
)specs <- data.frame(
Parametro = c("Activo subyacente","Vencimientos disponibles",
"Tamaño del contrato","Multiplicador (M)",
"Precio inicial futuro (30/04/2026)","Valor nocional por contrato",
"Margen inicial por contrato","Margen de mantenimiento",
"Mecanismo de liquidación","Ajuste mark-to-market"),
Valor = c("S&P 500 Index",
"Jun-26 (ESM26), Sep-26 (ESU26), Dic-26 (ESZ26), Mar-27 (ESH27)",
"USD 50 × nivel del índice","50",
"5.570 puntos al 30/04/2026 (CME Group, 2026)",
"USD 278.500 por contrato","USD 12.500 por contrato",
"USD 11.250 por contrato","Efectivo (cash settlement)",
"Diario (efectos académicos: mensual)")
)
kable(specs, col.names=c("Parámetro","Valor"),
caption="Tabla 10. Especificaciones E-mini S&P 500 (Fuente: CME Group, 2026)") |>
kable_styling(bootstrap_options=c("striped","hover"), full_width=TRUE) |>
column_spec(1, bold=TRUE, width="40%")| Parámetro | Valor |
|---|---|
| Activo subyacente | S&P 500 Index |
| Vencimientos disponibles | Jun-26 (ESM26), Sep-26 (ESU26), Dic-26 (ESZ26), Mar-27 (ESH27) |
| Tamaño del contrato | USD 50 × nivel del índice |
| Multiplicador (M) | 50 |
| Precio inicial futuro (30/04/2026) | 5.570 puntos al 30/04/2026 (CME Group, 2026) |
| Valor nocional por contrato | USD 278.500 por contrato |
| Margen inicial por contrato | USD 12.500 por contrato |
| Margen de mantenimiento | USD 11.250 por contrato |
| Mecanismo de liquidación | Efectivo (cash settlement) |
| Ajuste mark-to-market | Diario (efectos académicos: mensual) |
\[N^* = \frac{\beta_P \times V_P}{F_0 \times M}\]
F0 <- 5570; M <- 50; V_port <- 20e6
margen_ini <- 12500; margen_mant <- 11250
N_raw <- (beta_port*V_port)/(F0*M)
N_down <- floor(N_raw); N_up <- ceiling(N_raw)
N_star <- N_up
calc_df <- data.frame(
Elemento = c("Beta del portafolio (β_p)","Valor del portafolio (V_p)",
"Precio futuro (F_0)","Multiplicador (M)",
"Valor nocional por contrato (F_0 × M)",
"N* exacto","N* redondeado hacia abajo (piso)",
"N* redondeado hacia arriba (techo — ELEGIDO)"),
Valor = c(fmt_num(beta_port), paste0("USD ", fmt_usd(V_port)),
paste0(fmt_usd(F0)," puntos"), as.character(M),
paste0("USD ", fmt_usd(F0*M)),
fmt_num(N_raw,4), as.character(N_down),
as.character(N_up))
)
kable(calc_df, col.names=c("Elemento","Valor"),
caption="Cálculo del número óptimo de contratos de futuros") |>
kable_styling(bootstrap_options=c("striped","hover"), full_width=FALSE) |>
column_spec(1, bold=TRUE) |>
row_spec(8, bold=TRUE, background="#d4edda")| Elemento | Valor |
|---|---|
| Beta del portafolio (β_p) | 0.8345 |
| Valor del portafolio (V_p) | USD 20,000,000.00 |
| Precio futuro (F_0) | 5,570.00 puntos |
| Multiplicador (M) | 50 |
| Valor nocional por contrato (F_0 × M) | USD 278,500.00 |
| N* exacto | 59.9266 |
| N* redondeado hacia abajo (piso) | 59 |
| N* redondeado hacia arriba (techo — ELEGIDO) | 60 |
dec_t <- data.frame(
Opcion = c("Piso (subcobertura)","Techo (ELEGIDO)"),
N = c(N_down,N_up),
Cob = c(fmt_pct(N_down*F0*M/(beta_port*V_port)),
fmt_pct(N_up*F0*M/(beta_port*V_port))),
Margen = c(paste0("USD ",fmt_usd(N_down*margen_ini)),
paste0("USD ",fmt_usd(N_up*margen_ini)))
)
kable(dec_t, col.names=c("Opción","N° Contratos","Ratio Cobertura","Margen Inicial Total"),
caption="Tabla 11. Decisión de redondeo del número de contratos") |>
kable_styling(bootstrap_options=c("striped","hover")) |>
row_spec(2, bold=TRUE, background="#d4edda")| Opción | N° Contratos | Ratio Cobertura | Margen Inicial Total |
|---|---|---|---|
| Piso (subcobertura) | 59 | 98.45% | USD 737,500.00 |
| Techo (ELEGIDO) | 60 | 100.12% | USD 750,000.00 |
El número óptimo de contratos se determina aplicando la fórmula de cobertura de mínima varianza (Hull, 2009):
\[N^* = \frac{\beta_P \times V_P}{F_0 \times M}\]
donde \(\beta_P \times V_P\) representa la exposición sistemática total del portafolio en dólares, y \(F_0 \times M\) es el valor nocional de cada contrato de futuros E-mini S&P 500. La división de ambos términos determina cuántos contratos son necesarios para neutralizar exactamente esa exposición sistemática.
Dado que los contratos de futuros solo pueden negociarse en números enteros, el resultado exacto de 59.9266 contratos debe aproximarse. Se opta por redondear hacia arriba, seleccionando 60 contratos, toda vez que una ligera sobrecobertura se considera preferible a mantener parte del riesgo sistemático sin protección. Adicionalmente, dado que la beta del portafolio corresponde a una estimación estadística y la cobertura nunca es perfectamente exacta, una diferencia marginal de cobertura resulta razonable desde la perspectiva de administración de riesgo. Se considera preferible sacrificar parcialmente el potencial de ganancia en escenarios alcistas antes que enfrentar una exposición insuficiente ante caídas relevantes del mercado. El margen requerido para el contrato adicional USD 12,500.00 representa además una proporción reducida frente al valor total del portafolio administrado, por lo que el costo incremental de la sobrecobertura se considera financieramente aceptable.
pos_t <- data.frame(
Caso = c("Portafolio largo en acciones (nuestro caso)",
"Capital pendiente de invertir en acciones","Importador de materias primas"),
Posicion = c("CORTA en futuros de índice","LARGA en futuros de índice",
"LARGA en futuros de divisas"),
Logica = c("Vender índice a futuro compensa caídas del portafolio",
"Asegurar precio de compra frente a alzas del índice",
"Cubrir riesgo de apreciación del dólar")
)
kable(pos_t, col.names=c("Situación","Posición en Futuros","Lógica económica"),
caption="Tabla 12. Tipo de posición en futuros según objetivo") |>
kable_styling(bootstrap_options=c("striped","hover"), full_width=TRUE)| Situación | Posición en Futuros | Lógica económica |
|---|---|---|
| Portafolio largo en acciones (nuestro caso) | CORTA en futuros de índice | Vender índice a futuro compensa caídas del portafolio |
| Capital pendiente de invertir en acciones | LARGA en futuros de índice | Asegurar precio de compra frente a alzas del índice |
| Importador de materias primas | LARGA en futuros de divisas | Cubrir riesgo de apreciación del dólar |
Análisis de escenarios con 60 contratos CORTOS:
| Escenario | Portafolio acciones | Posición corta futuros | Efecto neto |
|---|---|---|---|
| Mercado sube 5 % | Ganancia ≈ β_p × 5 % × V_p | Pérdida en futuros | Se limita el upside: costo de la cobertura |
| Mercado baja 5 % | Pérdida ≈ β_p × 5 % × V_p | Ganancia en futuros | Compensación parcial o significativa de la pérdida |
| Mercado plano | Sin cambio significativo | Sin cambio significativo | Sin costo neto relevante |
Conclusión sobre la posición en futuros: La posición corta en futuros sobre el S&P 500 es la estrategia adecuada para un inversionista que ya mantiene una exposición larga en acciones y busca reducir el impacto de caídas del mercado (Hull, 2009; Rodríguez, 2026b). En este contexto, las ganancias derivadas de la posición corta en futuros pueden compensar parcial o significativamente las pérdidas del portafolio cuando el índice disminuye. En contraste, si el mercado presenta un comportamiento alcista, las pérdidas en futuros reducen parcialmente el rendimiento total del portafolio, representando el costo inherente de la cobertura.
No obstante, la estrategia implementada no elimina completamente el riesgo, dado que únicamente cubre el componente sistemático asociado al mercado aproximado mediante la beta del portafolio, mientras que el riesgo idiosincrático de cada empresa permanece expuesto a factores particulares de negocio, como eventos regulatorios, cambios competitivos o variaciones específicas del desempeño corporativo.
Se simulan tres escenarios: alcista, intermedio y bajista, tanto para el portafolio como el contrato de futuros sobre el S&P 500. La simulación se realiza mediante un Movimiento Geométrico Browniano (GBM) con parámetros ajustados para representar distintos entornos de mercado dentro del horizonte de inversión de cuatro años.
mu_idx <- anualizar(ret$SP500F)$mu
sigma_idx <- anualizar(ret$SP500F)$sigma
T_total <- 48; dt <- 1/12
# Parámetros por escenario (mu ajustado, sigma conservada)
escenarios <- list(
Alcista = list(mu = mu_idx + 1*sigma_idx, sigma = sigma_idx),
Intermedio = list(mu = mu_idx, sigma = sigma_idx),
Bajista = list(mu = mu_idx - 1*sigma_idx, sigma = sigma_idx)
)
gbm_df <- data.frame(
Escenario = c("Alcista","Intermedio (base)","Bajista"),
Mu_anual = c(fmt_pct(mu_idx + sigma_idx), fmt_pct(mu_idx), fmt_pct(mu_idx - sigma_idx)),
Sigma_anual = rep(fmt_pct(sigma_idx), 3),
Ajuste = c("μ + 1σ (percentil ~84 %)","μ base (percentil ~50 %)","μ − 1σ (percentil ~16 %)")
)
kable(gbm_df, col.names=c("Escenario","μ anual","σ anual","Ajuste aplicado"),
caption="Parámetros GBM por escenario de simulación") |>
kable_styling(bootstrap_options=c("striped","hover"), full_width=FALSE) |>
column_spec(1, bold=TRUE,
color=c("#2ca02c","#1f77b4","#d62728"))| Escenario | μ anual | σ anual | Ajuste aplicado |
|---|---|---|---|
| Alcista | 32.04% | 19.52% | μ + 1σ (percentil ~84 %) |
| Intermedio (base) | 12.52% | 19.52% | μ base (percentil ~50 %) |
| Bajista | -7% | 19.52% | μ − 1σ (percentil ~16 %) |
# ── Función GBM: una sola trayectoria (usada para futuro y análisis de margen) ──
sim_gbm <- function(S0, mu, sigma, dt, T, seed=42) {
set.seed(seed)
path <- numeric(T+1); path[1] <- S0
for(i in seq_len(T))
path[i+1] <- path[i]*exp((mu-0.5*sigma^2)*dt + sigma*sqrt(dt)*rnorm(1))
path
}
# ── Función Monte Carlo: n_sim trayectorias → devuelve path de MEDIAS ──────────
sim_gbm_mc <- function(S0, mu, sigma, dt, T, n_sim=5000, seed=42) {
set.seed(seed)
# Matriz T+1 x n_sim
mat <- matrix(NA_real_, nrow=T+1, ncol=n_sim)
mat[1, ] <- S0
for(i in seq_len(T)) {
shocks <- rnorm(n_sim)
mat[i+1, ] <- mat[i, ] * exp((mu - 0.5*sigma^2)*dt + sigma*sqrt(dt)*shocks)
}
# Retornar el path de valores esperados (media entre simulaciones)
rowMeans(mat)
}
fechas_sim <- seq(as.Date("2026-04-30"), by="month", length.out=T_total+1)
# ── Futuro: trayectoria única (para análisis de margen mes a mes) ────────────
fut_paths <- lapply(names(escenarios), function(nm) {
e <- escenarios[[nm]]
path <- sim_gbm(F0, e$mu, e$sigma, dt, T_total,
seed=switch(nm, Alcista=1, Intermedio=42, Bajista=99))
data.frame(Fecha=fechas_sim, Precio=path, Escenario=nm)
}) |> bind_rows()
# ── Portafolio: Monte Carlo 5,000 paths → path de medias por escenario ────────
mu_port_hist <- ret_port
port_paths <- lapply(names(escenarios), function(nm) {
e <- escenarios[[nm]]
mu_adj <- mu_port_hist + beta_port*(e$mu - mu_idx)
path <- sim_gbm_mc(capital, mu_adj, sigma_port, dt, T_total,
n_sim=5000,
seed=switch(nm, Alcista=11, Intermedio=42, Bajista=99))
data.frame(Fecha=fechas_sim, Valor=path/1e6, Escenario=nm)
}) |> bind_rows()
# ── Trayectoria única intermedia para análisis de flujos de margen ────────────
F_path <- sim_gbm(F0, mu_idx, sigma_idx, dt, T_total, seed=42)colores_esc <- pal_esc
p1 <- ggplot(fut_paths, aes(x=Fecha, y=Precio, color=Escenario)) +
geom_line(linewidth=1) +
geom_hline(yintercept=F0, linetype="dashed", color="gray50") +
scale_color_manual(values=colores_esc) +
scale_y_continuous(labels=label_comma()) +
labs(title="Futuro E-mini S&P 500", x=NULL, y="Precio (puntos)") +
tema_lab + theme(legend.position="top")
p2 <- ggplot(port_paths, aes(x=Fecha, y=Valor, color=Escenario)) +
geom_line(linewidth=1) +
geom_hline(yintercept=capital/1e6, linetype="dashed", color="gray50") +
scale_color_manual(values=colores_esc) +
scale_y_continuous(labels=label_dollar(suffix="M", scale=1)) +
labs(title="Valor del portafolio accionario", x=NULL, y="Valor (USD millones)") +
tema_lab + theme(legend.position="top")
p1 + p2 + plot_annotation(
title="Figura 6. Simulación Monte Carlo GBM: tres escenarios (48 meses)",
subtitle="5,000 trayectorias por escenario · Valor esperado (media) · Alcista: μ+1σ · Intermedio: μ base · Bajista: μ−1σ")Los escenarios fueron construidos ajustando el retorno esperado alrededor del escenario base, utilizando desplazamientos aproximados de una desviación estándar (μ±σ) con el fin de representar condiciones favorables, neutrales y adversas de mercado dentro del horizonte de inversión considerado.
Lectura de los escenarios: Los resultados se estimaron mediante simulación Monte Carlo con 5,000 trayectorias del modelo GBM, utilizando el promedio de los valores terminales como aproximación al comportamiento esperado del portafolio bajo cada escenario. En el escenario alcista, el valor esperado del portafolio a 4 años sería aproximadamente de 60,021,401.67; en el intermedio, de 30,922,886.86; y en el bajista, de 15,953,361.98. Los resultados reflejan el impacto de distintos supuestos de rentabilidad esperada sobre el desempeño del portafolio y evidencian una dispersión razonable de resultados posibles dentro del horizonte de inversión de cuatro años. Esta amplitud de escenarios también justifica la implementación de una estrategia de cobertura con futuros, particularmente frente a contextos de mercado adversos.
precio_ini_vec <- F_path[-length(F_path)]
precio_fin_vec <- F_path[-1]
delta_F <- precio_fin_vec - precio_ini_vec
pnl_corto <- -delta_F*M*N_star
pnl_largo <- delta_F*M*N_star
margen_total_ini <- N_star*margen_ini
cuenta_margen <- numeric(T_total+1); cuenta_margen[1] <- margen_total_ini
llamado_margen <- numeric(T_total)
for(i in seq_len(T_total)) {
cuenta_margen[i+1] <- cuenta_margen[i] + pnl_corto[i]
if(cuenta_margen[i+1] < N_star*margen_mant) {
rep <- margen_total_ini - cuenta_margen[i+1]
llamado_margen[i] <- rep
cuenta_margen[i+1] <- margen_total_ini
}
}
n_show <- min(12, T_total)
fl_df <- data.frame(
Mes = seq_len(n_show),
Fecha = format(fechas_sim[seq_len(n_show)+1], "%b-%y"),
F_ini = round(precio_ini_vec[seq_len(n_show)], 2),
F_fin = round(precio_fin_vec[seq_len(n_show)], 2),
DeltaF= round(delta_F[seq_len(n_show)], 2),
PnL_C = round(pnl_corto[seq_len(n_show)], 2),
PnL_L = round(pnl_largo[seq_len(n_show)], 2),
Saldo = round(cuenta_margen[seq_len(n_show)+1], 2),
Llamado=round(llamado_margen[seq_len(n_show)], 2)
)
kable(fl_df,
col.names=c("Mes","Fecha","F inicio","F fin","ΔF",
"P&L Corto","P&L Largo","Saldo Margen","Llamado al Margen"),
caption="Tabla 13. Flujos mensuales – Primer año (escenario intermedio)",
format.args=list(big.mark=",")) |>
kable_styling(bootstrap_options=c("striped","hover","condensed"),
full_width=TRUE, font_size=11) |>
column_spec(9, color=ifelse(fl_df$Llamado>0,"red","black"),
bold=ifelse(fl_df$Llamado>0,TRUE,FALSE))| Mes | Fecha | F inicio | F fin | ΔF | P&L Corto | P&L Largo | Saldo Margen | Llamado al Margen |
|---|---|---|---|---|---|---|---|---|
| 1 | may.-26 | 5,570.00 | 6,070.88 | 500.88 | -1,502,640.8 | 1,502,640.8 | 750,000.0 | 1,502,640.8 |
| 2 | jun.-26 | 6,070.88 | 5,932.98 | -137.90 | 413,692.9 | -413,692.9 | 1,163,692.9 | 0.0 |
| 3 | jul.-26 | 5,932.98 | 6,109.46 | 176.48 | -529,438.5 | 529,438.5 | 750,000.0 | 115,745.6 |
| 4 | ago.-26 | 6,109.46 | 6,387.55 | 278.09 | -834,276.5 | 834,276.5 | 750,000.0 | 834,276.5 |
| 5 | sept.-26 | 6,387.55 | 6,592.82 | 205.27 | -615,805.5 | 615,805.5 | 750,000.0 | 615,805.5 |
| 6 | oct.-26 | 6,592.82 | 6,611.75 | 18.93 | -56,779.2 | 56,779.2 | 693,220.8 | 0.0 |
| 7 | nov.-26 | 6,611.75 | 7,263.62 | 651.87 | -1,955,612.9 | 1,955,612.9 | 750,000.0 | 2,012,392.1 |
| 8 | dic.-26 | 7,263.62 | 7,289.18 | 25.56 | -76,681.3 | 76,681.3 | 750,000.0 | 76,681.3 |
| 9 | ene.-27 | 7,289.18 | 8,239.90 | 950.72 | -2,852,153.0 | 2,852,153.0 | 750,000.0 | 2,852,153.0 |
| 10 | mar.-27 | 8,239.90 | 8,283.79 | 43.90 | -131,686.9 | 131,686.9 | 750,000.0 | 131,686.9 |
| 11 | mar.-27 | 8,283.79 | 8,995.15 | 711.35 | -2,134,057.7 | 2,134,057.7 | 750,000.0 | 2,134,057.7 |
| 12 | abr.-27 | 8,995.15 | 10,323.24 | 1,328.10 | -3,984,285.0 | 3,984,285.0 | 750,000.0 | 3,984,285.0 |
Lectura de la tabla de flujos: Cada fila representa un mes de la estrategia. La columna ΔF muestra la variación del precio del contrato futuro: cuando es negativa (mercado cae), la posición corta genera una ganancia que contribuye a compensar parcialmente la pérdida potencial del portafolio accionario. Por el contrario, cuando el precio del futuro aumenta, la posición corta registra pérdidas, reflejando el costo de mantener la cobertura en mercados alcistas. El saldo de margen cambia mes a mes según las ganancias o pérdidas generadas por la posición en futuros bajo el mecanismo mark-to-market. Cuando el saldo disponible cae por debajo del margen de mantenimiento requerido para la posición total (USD 11,250 por contrato), es necesario realizar un llamado al margen para restablecer el nivel inicial de margen establecido para la posición. En términos prácticos, esto implica que el administrador del portafolio debe contar con liquidez disponible para responder ante pérdidas temporales de la cobertura. Por ello, aun cuando la estrategia reduzca el riesgo de mercado, períodos de alta volatilidad pueden generar necesidades relevantes de caja derivadas de múltiples llamados al margen.
# Agregar flujos por trimestre
trim_idx <- cut(seq_len(T_total),
breaks=seq(0, T_total, by=3), labels=paste0("T",1:16))
# Índices de inicio y fin de cada trimestre en la trayectoria de precios
idx_ini_trim <- seq(1, T_total, by=3)
idx_fin_trim <- seq(3, T_total, by=3) + 1 # +1 porque F_path tiene T_total+1 elementos
# Valor del portafolio sin cobertura al cierre de cada trimestre
# Usando la trayectoria simulada del portafolio (escenario intermedio)
port_interm <- filter(port_paths, Escenario == "Intermedio")
V_port_trim <- port_interm$Valor[idx_fin_trim] * 1e6 # en USD
# Valor del portafolio CON cobertura = valor sin cobertura + P&L acumulado de futuros
PnL_trim_vec <- as.numeric(tapply(pnl_corto, trim_idx, sum))
PnL_acum_vec <- cumsum(PnL_trim_vec)
V_cob_trim <- V_port_trim + PnL_acum_vec
trim_df <- data.frame(
Trimestre = paste0("T", seq_len(T_total/3)),
Fecha_ini = format(fechas_sim[idx_ini_trim], "%b-%Y"),
Fecha_fin = format(fechas_sim[idx_fin_trim], "%b-%Y"),
V_sin_cob = round(V_port_trim, 2), # "Plata" sin cobertura
PnL_futuros = round(PnL_trim_vec, 2), # Resultado del futuro ese trimestre
V_con_cob = round(V_cob_trim, 2), # "Plata" con cobertura
Llamados = round(as.numeric(tapply(llamado_margen, trim_idx, sum)), 2),
PnL_acum = round(PnL_acum_vec, 2)
)
kable(trim_df,
col.names=c("Trimestre","Fecha inicio","Fecha fin",
"Portafolio sin cobertura (USD)",
"P&L Futuros trimestre (USD)",
"Portafolio con cobertura (USD)",
"Llamados al margen (USD)",
"P&L Futuros acumulado (USD)"),
caption="Tabla 14. Resumen trimestral: valor del portafolio y cobertura – 48 meses (escenario intermedio)",
format.args=list(big.mark=",")) |>
kable_styling(bootstrap_options=c("striped","hover","condensed"), full_width=TRUE) |>
column_spec(5, color=ifelse(trim_df$PnL_futuros < 0, "red", "darkgreen"), bold=TRUE) |>
column_spec(6, bold=TRUE, background="#d4edda")| Trimestre | Fecha inicio | Fecha fin | Portafolio sin cobertura (USD) | P&L Futuros trimestre (USD) | Portafolio con cobertura (USD) | Llamados al margen (USD) | P&L Futuros acumulado (USD) |
|---|---|---|---|---|---|---|---|
| T1 | abr.-2026 | jul.-2026 | 20,514,718 | -1,618,386.4 | 18,896,332 | 1,618,386 | -1,618,386 |
| T2 | jul.-2026 | oct.-2026 | 21,131,188 | -1,506,861.2 | 18,005,941 | 1,450,082 | -3,125,248 |
| T3 | oct.-2026 | ene.-2027 | 21,711,842 | -4,884,447.3 | 13,702,147 | 4,941,226 | -8,009,695 |
| T4 | ene.-2027 | abr.-2027 | 22,280,171 | -6,250,029.6 | 8,020,447 | 6,250,030 | -14,259,724 |
| T5 | abr.-2027 | jul.-2027 | 22,870,631 | 2,236,406.4 | 10,847,313 | 0 | -12,023,318 |
| T6 | jul.-2027 | oct.-2027 | 23,509,912 | 2,821,131.4 | 14,307,726 | 0 | -9,202,187 |
| T7 | oct.-2027 | ene.-2028 | 24,067,331 | 1,359,127.9 | 16,224,272 | 0 | -7,843,059 |
| T8 | ene.-2028 | abr.-2028 | 24,755,676 | 367,468.5 | 17,280,086 | 0 | -7,475,590 |
| T9 | abr.-2028 | jul.-2028 | 25,406,353 | -2,399,377.8 | 15,531,385 | 0 | -9,874,968 |
| T10 | jul.-2028 | oct.-2028 | 26,114,407 | 2,116,490.8 | 18,355,929 | 0 | -7,758,477 |
| T11 | oct.-2028 | ene.-2029 | 26,794,952 | -3,967,362.7 | 15,069,112 | 0 | -11,725,840 |
| T12 | ene.-2029 | abr.-2029 | 27,503,463 | 2,083,160.6 | 17,860,784 | 0 | -9,642,679 |
| T13 | abr.-2029 | jul.-2029 | 28,297,448 | 4,813,021.4 | 23,467,790 | 0 | -4,829,658 |
| T14 | jul.-2029 | oct.-2029 | 29,104,428 | -431,600.1 | 23,843,170 | 0 | -5,261,258 |
| T15 | oct.-2029 | ene.-2030 | 29,982,044 | 1,046,359.7 | 25,767,146 | 0 | -4,214,898 |
| T16 | ene.-2030 | abr.-2030 | 30,922,887 | -1,892,656.9 | 24,815,332 | 0 | -6,107,555 |
Riesgo base (basis risk): Aun cuando la cobertura reduce de forma importante la exposición al riesgo sistemático, no elimina completamente las fluctuaciones del portafolio debido al riesgo base, originado por diferencias entre el comportamiento del portafolio accionario y el índice S&P 500 utilizado como subyacente de los futuros. Dado que las acciones seleccionadas no replican perfectamente la composición del índice, pueden presentarse diferencias entre el desempeño del portafolio y el resultado de la cobertura, especialmente en períodos de alta dispersión sectorial o eventos específicos que afecten de forma distinta a cada empresa.
Análisis del resumen trimestral: La tabla anterior presenta la evolución conjunta del portafolio accionario y la estrategia de cobertura durante los 48 meses del horizonte de inversión, bajo el escenario intermedio. La columna Portafolio sin cobertura muestra el valor simulado de las acciones en cada trimestre bajo el escenario intermedio. La columna P&L Futuros muestra si la posición corta generó ganancia (mercado bajó) o pérdida (mercado subió) en ese trimestre. La columna Portafolio con cobertura representa el resultado neto: valor de las acciones más el resultado acumulado de los futuros. En trimestres donde el mercado cae, la cobertura incrementa el valor del portafolio cubierto respecto al no cubierto. En trimestres alcistas, la cobertura reduce parcialmente el valor final, reflejando el costo de mantener protección frente a escenarios adversos. La diferencia promedio entre ambas columnas de portafolio permite observar el efecto económico asociado a la estrategia de cobertura a lo largo del horizonte de inversión.
# Base de datos
margen_df <- data.frame(
Mes = 0:T_total,
Saldo = cuenta_margen
)
# Líneas de referencia
y_ini <- margen_total_ini
y_mant <- N_star * margen_mant
# Etiquetas
lbl_ini <- paste0(
"Margen inicial: USD ",
formatC(y_ini, format = "f", digits = 0, big.mark = ",")
)
lbl_mant <- paste0(
"Margen mantenimiento: USD ",
formatC(y_mant, format = "f", digits = 0, big.mark = ",")
)
# Máximo del saldo
y_max <- max(cuenta_margen)
# Gráfico
ggplot(margen_df, aes(x = Mes, y = Saldo)) +
# Área de evolución
geom_area(
fill = "#dbeafe",
alpha = 0.35
) +
# Línea principal
geom_line(
color = "#2c5282",
linewidth = 1.1
) +
# Línea margen inicial
geom_hline(
yintercept = y_ini,
color = "#276749",
linewidth = 1
) +
# Línea margen mantenimiento
geom_hline(
yintercept = y_mant,
color = "#c53030",
linetype = "dashed",
linewidth = 1
) +
# Etiqueta margen inicial
annotate(
"label",
x = 38,
y = y_max * 0.18,
label = lbl_ini,
color = "#276749",
fill = "white",
fontface = "bold",
size = 3.1,
hjust = 0,
label.size = 0.25
) +
# Línea guía margen inicial
geom_segment(
aes(
x = 36,
xend = 37.5,
y = y_ini,
yend = y_max * 0.165
),
color = "#276749",
linewidth = 0.7
) +
# Etiqueta margen mantenimiento
annotate(
"label",
x = 38,
y = y_max * 0.10,
label = lbl_mant,
color = "#c53030",
fill = "white",
fontface = "bold",
size = 3.1,
hjust = 0,
label.size = 0.25
) +
# Línea guía margen mantenimiento
geom_segment(
aes(
x = 36,
xend = 37.5,
y = y_mant,
yend = y_max * 0.09
),
color = "#c53030",
linewidth = 0.7,
linetype = "dashed"
) +
# Escalas
scale_y_continuous(
labels = label_dollar(
scale = 1e-6,
suffix = " M",
accuracy = 0.1
),
expand = expansion(mult = c(0.03, 0.08))
) +
scale_x_continuous(
breaks = seq(0, 48, by = 6)
) +
# Títulos
labs(
title = "Figura 7. Saldo de la cuenta de margen — Posición corta (48 meses)",
subtitle = paste0(
N_star,
" contratos E-mini S&P 500 · Liquidación mensual"
),
x = "Mes",
y = "Saldo (USD millones)",
caption = paste(
"Área azul: evolución del saldo",
"| Verde: margen inicial",
"| Rojo punteado: umbral de mantenimiento"
)
) +
# Tema
theme_minimal(base_size = 12) +
theme(
plot.title = element_text(
size = 16,
face = "bold",
hjust = 0.5,
color = "#1a202c"
),
plot.subtitle = element_text(
size = 11,
hjust = 0.5,
color = "#4a5568"
),
axis.title = element_text(
face = "bold",
color = "#2d3748"
),
axis.text = element_text(
color = "#4a5568"
),
plot.caption = element_text(
size = 9,
face = "italic",
color = "#718096"
),
panel.grid.minor = element_blank()
)res_margen <- data.frame(
Concepto = c("Total llamados al margen (48 meses)",
"Monto total repuesto al margen",
"P&L total posición corta (48 meses)",
"Margen inicial total depositado"),
Valor = c(as.character(sum(llamado_margen>0)),
paste0("USD ", fmt_usd(sum(llamado_margen))),
paste0("USD ", fmt_usd(sum(pnl_corto))),
paste0("USD ", fmt_usd(margen_total_ini)))
)
kable(res_margen, col.names=c("Concepto","Valor"),
caption="Resumen de la cuenta de margen — posición corta (48 meses)") |>
kable_styling(bootstrap_options=c("striped","hover"), full_width=FALSE) |>
column_spec(1, bold=TRUE)| Concepto | Valor |
|---|---|
| Total llamados al margen (48 meses) | 10 |
| Monto total repuesto al margen | USD 14,259,724.45 |
| P&L total posición corta (48 meses) | USD -6,107,555.34 |
| Margen inicial total depositado | USD 750,000.00 |
roll_meses <- seq(3, T_total, by=3)
base_roll_pct <- 0.0015 # 0.15 % por roll (contango promedio E-mini)
idx_roll <- pmin(roll_meses+1, length(F_path))
roll_df <- data.frame(
Trimestre = seq_along(roll_meses),
Mes = roll_meses,
Fecha = format(fechas_sim[idx_roll], "%b-%Y"),
F_cierre = round(F_path[idx_roll], 2),
F_apertura = round(F_path[idx_roll]*(1+base_roll_pct), 2),
Base_pts = round(F_path[idx_roll]*base_roll_pct, 2),
PnL_Roll = round(-F_path[idx_roll]*base_roll_pct*M*N_star, 2)
)
roll_df$PnL_acum <- cumsum(roll_df$PnL_Roll)
kable(roll_df,
col.names=c("Trimestre","Mes","Fecha Roll","F Cierre","F Apertura",
"Base (puntos)","P&L Roll (USD)","P&L Acumulado"),
caption="Tabla 15. Ganancias/pérdidas por roll-over trimestral (posición corta)",
format.args=list(big.mark=",")) |>
kable_styling(bootstrap_options=c("striped","hover","condensed"), full_width=TRUE) |>
column_spec(7, color=ifelse(roll_df$PnL_Roll<0,"red","darkgreen"))| Trimestre | Mes | Fecha Roll | F Cierre | F Apertura | Base (puntos) | P&L Roll (USD) | P&L Acumulado |
|---|---|---|---|---|---|---|---|
| 1 | 3 | jul.-2026 | 6,109.46 | 6,118.63 | 9.16 | -27,492.58 | -27,492.58 |
| 2 | 6 | oct.-2026 | 6,611.75 | 6,621.67 | 9.92 | -29,752.87 | -57,245.45 |
| 3 | 9 | ene.-2027 | 8,239.90 | 8,252.26 | 12.36 | -37,079.54 | -94,324.99 |
| 4 | 12 | abr.-2027 | 10,323.24 | 10,338.73 | 15.48 | -46,454.59 | -140,779.58 |
| 5 | 15 | jul.-2027 | 9,577.77 | 9,592.14 | 14.37 | -43,099.98 | -183,879.56 |
| 6 | 18 | oct.-2027 | 8,637.40 | 8,650.35 | 12.96 | -38,868.28 | -222,747.84 |
| 7 | 21 | ene.-2028 | 8,184.35 | 8,196.63 | 12.28 | -36,829.59 | -259,577.43 |
| 8 | 24 | abr.-2028 | 8,061.86 | 8,073.96 | 12.09 | -36,278.39 | -295,855.82 |
| 9 | 27 | jul.-2028 | 8,861.66 | 8,874.95 | 13.29 | -39,877.45 | -335,733.27 |
| 10 | 30 | oct.-2028 | 8,156.16 | 8,168.39 | 12.23 | -36,702.72 | -372,435.99 |
| 11 | 33 | ene.-2029 | 9,478.61 | 9,492.83 | 14.22 | -42,653.76 | -415,089.75 |
| 12 | 36 | abr.-2029 | 8,784.23 | 8,797.40 | 13.18 | -39,529.02 | -454,618.77 |
| 13 | 39 | jul.-2029 | 7,179.89 | 7,190.66 | 10.77 | -32,309.49 | -486,928.26 |
| 14 | 42 | oct.-2029 | 7,323.75 | 7,334.74 | 10.99 | -32,956.89 | -519,885.15 |
| 15 | 45 | ene.-2030 | 6,974.97 | 6,985.43 | 10.46 | -31,387.35 | -551,272.50 |
| 16 | 48 | abr.-2030 | 7,605.85 | 7,617.26 | 11.41 | -34,226.33 | -585,498.83 |
ggplot(roll_df, aes(x=Trimestre, y=PnL_acum)) +
geom_col(fill=ifelse(roll_df$PnL_Roll<0,"#c53030","#276749"), alpha=0.8) +
geom_line(aes(y=PnL_acum), color="#1a2b4a", linewidth=1.2, linetype="solid") +
geom_point(aes(y=PnL_acum), color="#1a2b4a", size=2.5) +
scale_y_continuous(labels=label_comma()) +
labs(title="Figura 8. P&L acumulado del roll-over trimestral (posición corta)",
subtitle=paste0("Costo total 4 años: USD ",fmt_usd(sum(roll_df$PnL_Roll))),
x="Trimestre", y="P&L acumulado (USD)") + tema_labtotal_roll <- sum(roll_df$PnL_Roll)
roll_res <- data.frame(
Concepto = c("Costo total roll-over (4 años, 16 rolls)",
"Costo promedio por trimestre",
"Como porcentaje del capital"),
Valor = c(paste0("USD ", fmt_usd(total_roll)),
paste0("USD ", fmt_usd(mean(roll_df$PnL_Roll))),
fmt_pct(abs(total_roll)/capital))
)
kable(roll_res, col.names=c("Concepto","Valor"),
caption="Resumen del costo de roll-over trimestral") |>
kable_styling(bootstrap_options=c("striped","hover"), full_width=FALSE) |>
column_spec(1, bold=TRUE)| Concepto | Valor |
|---|---|
| Costo total roll-over (4 años, 16 rolls) | USD -585,498.83 |
| Costo promedio por trimestre | USD -36,593.68 |
| Como porcentaje del capital | 2.93% |
comp_t <- data.frame(
Estrategia = c("Siempre CORTA","Siempre LARGA"),
Cuando = c("Portafolio comprado; protege caídas del índice",
"Capital por invertir; protege alzas del índice"),
Cubre = c("Riesgo bajista sistemático","Riesgo alcista de oportunidad"),
Roll_contango = c("Pierde en el roll (costo para el corto)",
"Gana en el roll (beneficio para el largo)"),
Roll_backwd = c("Gana en el roll","Pierde en el roll")
)
kable(comp_t,
col.names=c("Estrategia","¿Cuándo aplica?","Riesgo cubierto",
"Roll en Contango","Roll en Backwardation"),
caption="Tabla 16. Comparación estrategia siempre-corta vs siempre-larga") |>
kable_styling(bootstrap_options=c("striped","hover"), full_width=TRUE)| Estrategia | ¿Cuándo aplica? | Riesgo cubierto | Roll en Contango | Roll en Backwardation |
|---|---|---|---|---|
| Siempre CORTA | Portafolio comprado; protege caídas del índice | Riesgo bajista sistemático | Pierde en el roll (costo para el corto) | Gana en el roll |
| Siempre LARGA | Capital por invertir; protege alzas del índice | Riesgo alcista de oportunidad | Gana en el roll (beneficio para el largo) | Pierde en el roll |
Análisis del roll-over y riesgo de base: : El proceso de roll-over implica cerrar el contrato próximo al vencimiento y abrir una nueva posición en un contrato con vencimiento posterior. Dado que ambos contratos pueden cotizar a precios distintos, surge un costo o beneficio asociado a la diferencia entre el precio de cierre y reapertura. En condiciones normales de mercado, los contratos E-mini S&P 500 suelen presentar una estructura de contangodonde los futuros de vencimiento más lejano cotizan a precios superiores al contrato cercano. Bajo una posición corta, esto implica recomprar el contrato próximo y vender el nuevo a un precio relativamente más alto, generando un costo acumulado de roll-over. Para el horizonte de cuatro años, dicho costo asciende a USD 585,498.83 equivalente a 2.93% del capital inicial administrado. No obstante, este costo debe interpretarse como parte del precio de mantener la cobertura durante todo el horizonte de inversión. Una posición larga podría beneficiarse del contango, pero no cumpliría el objetivo principal de reducir pérdidas ante caídas del mercado, razón por la cual mantener una posición corta continúa siendo la alternativa más coherente con la estrategia de protección del portafolio.
rf_tabla <- data.frame(
Concepto = c("Instrumento","Fecha de consulta","Tasa anual efectiva (EA)",
"Tasa mensual equivalente","Tasa trimestral equivalente","Justificación"),
Valor = c("^TNX – CBOE Interest Rate 3-5 Year Treasury",
"30 de abril de 2026",
paste0(fmt_pct(Rf_anual)),
paste0(fmt_pct(Rf_mensual)),
paste0(fmt_pct(Rf_trim)),
"Tasa sin riesgo EE.UU. para CAPM y valoración de derivados (Federal Reserve/CBOE, 2026)")
)
kable(rf_tabla, col.names=c("Concepto","Valor"),
caption="Tabla 17. Tasa libre de riesgo aplicada") |>
kable_styling(bootstrap_options=c("striped","hover"), full_width=TRUE) |>
column_spec(1, bold=TRUE)| Concepto | Valor |
|---|---|
| Instrumento | ^TNX – CBOE Interest Rate 3-5 Year Treasury |
| Fecha de consulta | 30 de abril de 2026 |
| Tasa anual efectiva (EA) | 4.02% |
| Tasa mensual equivalente | 0.33% |
| Tasa trimestral equivalente | 0.99% |
| Justificación | Tasa sin riesgo EE.UU. para CAPM y valoración de derivados (Federal Reserve/CBOE, 2026) |
# ── Retorno esperado por CAPM ─────────────────────────────────────────────────
# E[R_p] = Rf + β_p × (E[R_m] - Rf)
# E[R_m]: retorno esperado del mercado (S&P 500), calculado con datos históricos
mu_mercado <- anualizar(ret$SP500)$mu # retorno anual esperado del índice
ret_capm <- Rf_anual + beta_port * (mu_mercado - Rf_anual)
prima_riesgo <- mu_mercado - Rf_anual # prima de riesgo de mercado
capm_df <- data.frame(
Componente = c("E[R_m] — Retorno esperado S&P 500",
"R_f — Tasa libre de riesgo",
"Prima de riesgo de mercado (ERP = E[R_m] − R_f)",
"β_p — Beta del portafolio",
"β_p × ERP — Contribución sistemática",
"E[R_p] CAPM = R_f + β_p × ERP",
"E[R_p] histórico (optimización)"),
Valor = c(fmt_pct(mu_mercado), fmt_pct(Rf_anual),
fmt_pct(prima_riesgo), fmt_num(beta_port),
fmt_pct(beta_port*prima_riesgo),
fmt_pct(ret_capm), fmt_pct(ret_port))
)
kable(capm_df, col.names=c("Componente","Valor"),
caption="Descomposición del retorno esperado del portafolio por CAPM") |>
kable_styling(bootstrap_options=c("striped","hover"), full_width=FALSE) |>
column_spec(1, bold=TRUE) |>
row_spec(6, bold=TRUE, background="#d4edda")| Componente | Valor |
|---|---|
| E[R_m] — Retorno esperado S&P 500 | 12.45% |
| R_f — Tasa libre de riesgo | 4.02% |
| Prima de riesgo de mercado (ERP = E[R_m] − R_f) | 8.43% |
| β_p — Beta del portafolio | 0.8345 |
| β_p × ERP — Contribución sistemática | 7.03% |
| E[R_p] CAPM = R_f + β_p × ERP | 11.05% |
| E[R_p] histórico (optimización) | 10.98% |
# Valor esperado a 4 años usando retorno CAPM
V_sin <- capital * (1 + ret_capm)^4 # sin cobertura → retorno CAPM
V_con <- capital * (1 + Rf_anual)^4 # con cobertura → retorno aproximado a Rf
V_var99<- V_sin - VaR99_usd * sqrt(48)
V_var95<- V_sin - VaR95_usd * sqrt(48)
# Retorno mensual basado en CAPM
ret_capm_m <- (1 + ret_capm)^(1/12) - 1
horiz_df <- data.frame(
Enfoque = c("Sin cobertura – retorno CAPM",
"Con cobertura por futuros – retorno aprox. Rf",
"Escenario VaR 99 % (estrés extremo)",
"Escenario VaR 95 % (estrés moderado)"),
Ret = c(fmt_pct(ret_capm), fmt_pct(Rf_anual),
fmt_pct(ret_capm - VaR99_pct*sqrt(12)),
fmt_pct(ret_capm - VaR95_pct*sqrt(12))),
V_4y = c(paste0("USD ", fmt_usd(V_sin)), paste0("USD ", fmt_usd(V_con)),
paste0("USD ", fmt_usd(V_var99)), paste0("USD ", fmt_usd(V_var95))),
Gan = c(paste0("USD ", fmt_usd(V_sin - capital)),
paste0("USD ", fmt_usd(V_con - capital)),
paste0("USD ", fmt_usd(V_var99- capital)),
paste0("USD ", fmt_usd(V_var95- capital)))
)
kable(horiz_df,
col.names=c("Enfoque","Retorno anual esperado","Valor esperado (4 años)","Ganancia/Pérdida"),
caption="Tabla 18. Valor esperado del portafolio a 4 años (retorno CAPM vs Rf)") |>
kable_styling(bootstrap_options=c("striped","hover"), full_width=TRUE) |>
row_spec(1, background="#fff3cd") |> row_spec(2, background="#d4edda") |>
row_spec(3:4, background="#f8d7da")| Enfoque | Retorno anual esperado | Valor esperado (4 años) | Ganancia/Pérdida |
|---|---|---|---|
| Sin cobertura – retorno CAPM | 11.05% | USD 30,418,970.22 | USD 10,418,970.22 |
| Con cobertura por futuros – retorno aprox. Rf | 4.02% | USD 23,415,174.22 | USD 3,415,174.22 |
| Escenario VaR 99 % (estrés extremo) | -40.39% | USD 9,842,238.19 | USD -10,157,761.81 |
| Escenario VaR 95 % (estrés moderado) | -24.43% | USD 16,224,016.85 | USD -3,775,983.15 |
Nota. Para los escenarios de VaR se escaló el VaR mensual mediante la regla de raíz del tiempo, reconociendo que esta aproximación supone independencia temporal de los retornos y puede simplificar dinámicas de acumulación de riesgo en horizontes extensos.
Interpretación del valor esperado con cobertura: El retorno esperado del portafolio calculado mediante el CAPM representa la compensación por el riesgo sistemático asumido:
\(E[R_p] = R_f + \beta_p \times (E[R_m] - R_f)\)
Sustituyendo los parámetros estimados del portafolio:
\(E[R_p] =4.02% +0.8345 \times(12.45% -4.02%)=11.05%\)
Bajo este enfoque, el portafolio presenta un retorno esperado aproximado de 11.05% anual. La implementación de una cobertura mediante futuros reduce parte importante de la exposición al mercado, por lo que el rendimiento esperado del portafolio cubierto tiende a acercarse a la tasa libre de riesgo, aunque sin coincidir completamente con ella debido a la persistencia de riesgo idiosincrático, costos de roll-over y riesgo base.
En este sentido, la diferencia entre el retorno esperado sin cobertura (11.05%) y el rendimiento aproximado del portafolio cubierto (4.02%) equivalente a aproximadamente 7.03% anual puede interpretarse como el costo económico asociado a reducir la exposición frente a movimientos adversos del mercado. A un horizonte de 4 años, el valor esperado del portafolio cubierto sería aproximadamente de 23,415,174.22, frente a 30,418,970.22 bajo el escenario sin cobertura.
meses_proy <- 1:48
# Se usa retorno CAPM mensual equivalente para consistencia con la sección anterior
V_sin_m <- capital*(1+ret_capm_m)^meses_proy
V_con_m <- capital*(1+Rf_mensual)^meses_proy
V_var_m <- capital*(1+ret_capm_m)^meses_proy - VaR99_usd*sqrt(meses_proy)
rend_df <- data.frame(
Metrica = c("Retorno mensual esperado (CAPM, equiv. geométrico)",
"Volatilidad mensual",
"Valor esperado al término del mes 1"),
Valor = c(fmt_pct(ret_capm_m), fmt_pct(sigma_port_m),
paste0("USD ", fmt_usd(capital*(1+ret_capm_m))))
)
kable(rend_df, col.names=c("Métrica","Valor"),
caption="Rendimiento mensual esperado del portafolio") |>
kable_styling(bootstrap_options=c("striped","hover"), full_width=FALSE) |>
column_spec(1, bold=TRUE)| Métrica | Valor |
|---|---|
| Retorno mensual esperado (CAPM, equiv. geométrico) | 0.88% |
| Volatilidad mensual | 6.76% |
| Valor esperado al término del mes 1 | USD 20,175,487.99 |
# Tabla comparativa meses clave
meses_key <- c(1,3,6,12,24,36,48)
tab_proy <- data.frame(
Mes = meses_key,
Sin_cob = paste0("USD ",fmt_usd(V_sin_m[meses_key])),
Con_cob = paste0("USD ",fmt_usd(V_con_m[meses_key])),
VaR_ajust = paste0("USD ",fmt_usd(pmax(V_var_m[meses_key],0)))
)
kable(tab_proy,
col.names=c("Mes","Sin cobertura","Con cobertura (Rf)","Ajustado VaR 99 %"),
caption="Tabla 19. Valor esperado mensual del portafolio bajo tres enfoques") |>
kable_styling(bootstrap_options=c("striped","hover"), full_width=TRUE)| Mes | Sin cobertura | Con cobertura (Rf) | Ajustado VaR 99 % |
|---|---|---|---|
| 1 | USD 20,175,487.99 | USD 20,065,796.33 | USD 17,205,492.55 |
| 3 | USD 20,531,096.90 | USD 20,198,039.07 | USD 15,386,913.89 |
| 6 | USD 21,076,296.99 | USD 20,398,039.12 | USD 13,801,323.61 |
| 12 | USD 22,210,514.74 | USD 20,804,000.00 | USD 11,922,148.72 |
| 24 | USD 24,665,348.25 | USD 21,640,320.80 | USD 10,115,401.50 |
| 36 | USD 27,391,504.05 | USD 22,510,261.70 | USD 9,571,531.38 |
| 48 | USD 30,418,970.22 | USD 23,415,174.22 | USD 9,842,238.19 |
div_t <- data.frame(
Empresa = c("Adobe Inc. (ADBE)","Vertex Pharmaceuticals (VRTX)","Monster Beverage (MNST)"),
Yield = c("0 %","0 %","0 %"),
Politica = c("No paga dividendos – programa activo de recompra de acciones",
"No paga dividendos – reinversión en I+D y adquisiciones estratégicas",
"No paga dividendos – recompra activa de acciones"),
Fuente = c("Yahoo Finance (2026a); SEC Form 10-K Adobe FY2025",
"Yahoo Finance (2026b); Vertex Pharmaceuticals (2026a)",
"Yahoo Finance (2026c); Monster Beverage Corporation (2026)"),
Impacto = c("Retorno total = apreciación de capital. Sin ajuste al precio por ex-dividendo.",
"Retorno total = apreciación de capital. Sin ajuste al precio por ex-dividendo.",
"Retorno total = apreciación de capital. Sin ajuste al precio por ex-dividendo.")
)
kable(div_t,
col.names=c("Empresa","Div. Yield","Política","Fuente verificable","Impacto en portafolio"),
caption="Tabla 20. Política de dividendos (Fuentes: Yahoo Finance, 2026; SEC EDGAR)") |>
kable_styling(bootstrap_options=c("striped","hover"), full_width=TRUE)| Empresa | Div. Yield | Política | Fuente verificable | Impacto en portafolio |
|---|---|---|---|---|
| Adobe Inc. (ADBE) | 0 % | No paga dividendos – programa activo de recompra de acciones | Yahoo Finance (2026a); SEC Form 10-K Adobe FY2025 | Retorno total = apreciación de capital. Sin ajuste al precio por ex-dividendo. |
| Vertex Pharmaceuticals (VRTX) | 0 % | No paga dividendos – reinversión en I+D y adquisiciones estratégicas | Yahoo Finance (2026b); Vertex Pharmaceuticals (2026a) | Retorno total = apreciación de capital. Sin ajuste al precio por ex-dividendo. |
| Monster Beverage (MNST) | 0 % | No paga dividendos – recompra activa de acciones | Yahoo Finance (2026c); Monster Beverage Corporation (2026) | Retorno total = apreciación de capital. Sin ajuste al precio por ex-dividendo. |
Impacto de los dividendos en la cobertura: Las tres acciones seleccionadas no pagan dividendos en efectivo al 30 de abril de 2026, situación verificada mediante Yahoo Finance, DividendMax y los reportes anuales (10-K) de cada empresa. En consecuencia, el rendimiento total del portafolio proviene principalmente de la valorización del capital, sin flujos intermedios por dividendos que deban incorporarse al análisis. En caso de existir pagos de dividendos, el precio de la acción tendería a ajustarse parcialmente en la fecha ex-dividend, por lo que dichos pagos deberían incorporarse al retorno total para evitar subestimar el rendimiento efectivo del portafolio. En la valoración teórica de futuros: \(F_0 = S_0 \cdot e^{(r-q)T}\) el término \(q\) representa el rendimiento por dividendos (dividend yield). Dado que las acciones seleccionadas no presentan pagos de dividendos en efectivo, se asume \(q = 0\), por lo que el precio teórico del contrato futuro no requiere incorporar un ajuste adicional por este concepto.
proy_df <- data.frame(
Mes = meses_proy,
Sin = V_sin_m/1e6,
Con = V_con_m/1e6,
VaR = pmax(V_var_m/1e6, 0)
) |> pivot_longer(-Mes, names_to="Tipo", values_to="Valor") |>
mutate(Tipo=case_when(Tipo=="Sin"~"Sin cobertura",
Tipo=="Con"~"Con cobertura (Rf)",
TRUE~"Ajustado VaR 99 %"))
banda <- data.frame(
Mes = meses_proy,
Ymin = (V_sin_m - VaR99_usd*sqrt(meses_proy))/1e6,
Ymax = (V_sin_m + VaR99_usd*sqrt(meses_proy))/1e6
)
ggplot(proy_df, aes(x=Mes, y=Valor, color=Tipo, linetype=Tipo)) +
geom_ribbon(data=banda, aes(x=Mes,ymin=Ymin,ymax=Ymax),
inherit.aes=FALSE, fill="#3182ce", alpha=0.10) +
geom_line(linewidth=1) +
scale_color_manual(values=c("Sin cobertura"="#1f77b4",
"Con cobertura (Rf)"="#2ca02c",
"Ajustado VaR 99 %"="#d62728")) +
scale_linetype_manual(values=c("Sin cobertura"="solid",
"Con cobertura (Rf)"="solid",
"Ajustado VaR 99 %"="dashed")) +
scale_y_continuous(labels=label_dollar(suffix="M", scale=1)) +
labs(title="Figura 9. Proyección mensual del valor del portafolio a 4 años",
subtitle="Banda azul: ±VaR 99 % escalado | Tres enfoques de valoración",
x="Mes", y="Valor (USD millones)", color=NULL, linetype=NULL) +
tema_lab + theme(legend.position="top")betas_hip <- c(0.5, beta_port, 2.0)
sens_df <- lapply(betas_hip, function(b) {
N_c <- (b*V_port)/(F0*M); N_u <- ceiling(N_c)
data.frame(Beta=b, N_exacto=round(N_c,3), N_contratos=N_u,
Margen_total=N_u*margen_ini,
Ratio_cob=round(N_u*F0*M/(b*V_port),4),
Exp_sist=round(b*V_port),
Sens_1pct=round(b*V_port*0.01))
}) |> bind_rows()
kable(sens_df, digits=3,
col.names=c("Beta (β_p)","N* exacto","N* entero","Margen inicial total",
"Ratio cobertura","Exposición sistemática","Pérdida por -1 % índice"),
caption="Tabla 21. Análisis de sensibilidad: contratos y exposición por beta",
format.args=list(big.mark=",")) |>
kable_styling(bootstrap_options=c("striped","hover"), full_width=TRUE) |>
row_spec(which(round(sens_df$Beta,2)==round(beta_port,2)), bold=TRUE, background="#fff3cd")| Beta (β_p) | N* exacto | N* entero | Margen inicial total | Ratio cobertura | Exposición sistemática | Pérdida por -1 % índice |
|---|---|---|---|---|---|---|
| 0.500 | 35.907 | 36 | 450,000 | 1.003 | 10,000,000 | 100,000 |
| 0.834 | 59.927 | 60 | 750,000 | 1.001 | 16,689,557 | 166,896 |
| 2.000 | 143.627 | 144 | 1,800,000 | 1.003 | 40,000,000 | 400,000 |
beta_seq <- seq(0.2, 2.5, by = 0.05)
N_seq <- ceiling((beta_seq * V_port) / (F0 * M))
plot_df <- data.frame(
Beta = beta_seq,
N = N_seq
)
ggplot(plot_df, aes(x = Beta, y = N)) +
# Línea principal
geom_line(
color = "#2c5282",
linewidth = 1.3
) +
# Puntos destacados
geom_point(
data = sens_df,
aes(x = Beta, y = N_contratos),
color = "#c53030",
size = 4,
shape = 18
) +
# Línea vertical beta actual
geom_vline(
xintercept = beta_port,
linetype = "dashed",
color = "#b7791f",
linewidth = 0.9
) +
# Texto beta actual
annotate(
"text",
x = beta_port + 0.05,
y = max(N_seq) * 0.9,
label = paste0(
"β_p actual = ",
round(beta_port, 3)
),
color = "#d97706",
size = 3.6,
hjust = 0,
fontface = "bold"
) +
# Etiquetas
labs(
title = "Figura 10. Número óptimo de contratos vs. beta del portafolio",
subtitle = paste0(
"Vp = USD 20 M | F0 = ",
F0,
" | M = 50"
),
x = "Beta (βp)",
y = "Número de contratos"
) +
# Tema
theme_minimal(base_size = 12) +
theme(
plot.title = element_text(
size = 16,
face = "bold",
hjust = 0.5,
color = "#1a202c"
),
plot.subtitle = element_text(
size = 11,
hjust = 0.5,
color = "#4a5568"
),
axis.title = element_text(
face = "bold",
color = "#2d3748"
),
panel.grid.minor = element_blank()
)Análisis del cambio de estrategia:
Mientras el inversionista mantenga una posición comprada en acciones, la cobertura apropiada continúa siendo una posición corta en futuros; lo que cambia con la beta es la intensidad de la cobertura, no su dirección:
Con beta = 0.5, el portafolio presenta una sensibilidad baja frente al mercado y requiere solo 36 contratos para cubiri su exposición sitemática. Una caída del 1 % en el índice generaría una pérdida aproximada de USD 100,000.00 con un margen inicial requerido de USD 450,000.00. La cobertura es menos intensa ya que tiene poca exposición al mercado.
Con beta = 2.0, el portafolio presenta una sensibilidad aproximadamente dos veces superior a la del mercado, requiriendo 144 contratos para redución su exposición. Una caída del 1 % genera una pérdida aproximada de USD 400,000.00, mientras que el margen requerido ascendería a USD 1,800,000.00. Bajo este escenario, la cobertura adquiere mayor relevancia debido al incremento significativo del riesgo sistemático asumido.
La regla general es que \(N^* \propto \beta_P\): a mayor beta, mayor exposición sistemática y mayor cantidad de contratos necesarios para neutralizarla (Hull, 2009).
A continuación, se presenta una comparación trimestral del desempeño esperado de la cartera bajo distintos escenarios de sensibilidad sistemática (\(\beta\)): el beta estimado del portafolio, un escenario de baja sensibilidad (\(\beta = 0.5\)) y un escenario de alta sensibilidad (\(\beta = 2.0\)). La comparación permite evaluar cómo variaciones en la exposición al mercado afectan simultáneamente el rendimiento esperado, el valor proyectado de la cartera y la intensidad requerida de la estrategia de cobertura mediante futuros.
# ── Parámetros ────────────────────────────────────────────────────────────────
betas_comp <- c(beta_port, 0.5, 2.0)
nombres_beta <- c(paste0("Beta real (", round(beta_port,3),")"),"Beta = 0.5","Beta = 2.0")
# Retorno esperado CAPM por trimestre para cada beta
# E[R_trim] = Rf_trim + beta * (E[R_m_trim] - Rf_trim)
mu_m_trim <- (1 + mu_mercado)^(1/4) - 1 # retorno trimestral del mercado
# Usar la trayectoria simulada del portafolio (escenario intermedio)
port_interm <- filter(port_paths, Escenario == "Intermedio")
# Índices de cierre de cada trimestre
idx_fin_trim <- seq(3, T_total, by = 3) + 1
idx_fin_trim <- pmin(idx_fin_trim, nrow(port_interm))
V_port_trim <- port_interm$Valor[idx_fin_trim] * 1e6 # valor cartera USD
# Calcular para cada beta
resultados_betas <- lapply(seq_along(betas_comp), function(k) {
b <- betas_comp[k]
# Rendimiento esperado CAPM trimestral
re <- Rf_trim + b * (mu_m_trim - Rf_trim)
# Valor esperado = valor cartera * (1 + rendimiento esperado)
prev <- c(capital, V_port_trim[-length(V_port_trim)])
ve <- prev * (1 + re)
# Resultado trimestral = valor esperado - valor esperado trimestre anterior
res <- ve - dplyr::lag(ve, default = capital)
data.frame(
Trimestre = paste0("T", seq_along(idx_fin_trim)),
Rend_Esp = re,
Valor_Cartera = V_port_trim,
Valor_Esp = round(ve, 2),
Resultado = round(res, 2),
Beta_label = nombres_beta[k]
)
}) |> bind_rows()
# ── Tabla comparativa ─────────────────────────────────────────────────────────
# Formato ancho: un bloque de columnas por beta
beta_real_df <- filter(resultados_betas, Beta_label == nombres_beta[1])
beta_05_df <- filter(resultados_betas, Beta_label == nombres_beta[2])
beta_20_df <- filter(resultados_betas, Beta_label == nombres_beta[3])
tabla_comp <- data.frame(
Trimestre = beta_real_df$Trimestre,
# Beta real
RE_real = fmt_pct(beta_real_df$Rend_Esp),
VC_real = round(beta_real_df$Valor_Cartera / 1e6, 3),
VE_real = round(beta_real_df$Valor_Esp / 1e6, 3),
Res_real = round(beta_real_df$Resultado / 1e6, 3),
# Beta 0.5
RE_05 = fmt_pct(beta_05_df$Rend_Esp),
VC_05 = round(beta_05_df$Valor_Cartera / 1e6, 3),
VE_05 = round(beta_05_df$Valor_Esp / 1e6, 3),
Res_05 = round(beta_05_df$Resultado / 1e6, 3),
# Beta 2.0
RE_20 = fmt_pct(beta_20_df$Rend_Esp),
VC_20 = round(beta_20_df$Valor_Cartera / 1e6, 3),
VE_20 = round(beta_20_df$Valor_Esp / 1e6, 3),
Res_20 = round(beta_20_df$Resultado / 1e6, 3)
)
kable(tabla_comp,
col.names = c(
"Trimestre",
"Rend. Esp.", "V. Cartera (M)", "V. Esperado (M)", "Resultado (M)",
"Rend. Esp.", "V. Cartera (M)", "V. Esperado (M)", "Resultado (M)",
"Rend. Esp.", "V. Cartera (M)", "V. Esperado (M)", "Resultado (M)"
),
caption = paste0(
"Tabla. Cobertura corta trimestral comparativa — ",
"Beta real (", round(beta_port,3), "), Beta = 0.5 y Beta = 2.0 ",
"(valores en USD millones, Fuente: elaboración propia con base en Rodríguez, 2026b)"
),
format.args = list(big.mark = ",")) |>
kable_styling(bootstrap_options = c("striped","hover","condensed"),
full_width = TRUE, font_size = 11) |>
add_header_above(c(
" " = 1,
setNames(4, paste0("Beta real (", round(beta_port,3), ")")),
"Beta = 0.5" = 4,
"Beta = 2.0" = 4
)) |>
column_spec(c(5,9,13),
color = ifelse(c(tabla_comp$Res_real,
tabla_comp$Res_05,
tabla_comp$Res_20) < 0,
"red","darkgreen")[c(
seq_len(nrow(tabla_comp)),
nrow(tabla_comp) + seq_len(nrow(tabla_comp)),
2*nrow(tabla_comp) + seq_len(nrow(tabla_comp))
)],
bold = TRUE)| Trimestre | Rend. Esp. | V. Cartera (M) | V. Esperado (M) | Resultado (M) | Rend. Esp. | V. Cartera (M) | V. Esperado (M) | Resultado (M) | Rend. Esp. | V. Cartera (M) | V. Esperado (M) | Resultado (M) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| T1 | 2.65% | 20.515 | 20.530 | 0.530 | 1.98% | 20.515 | 20.397 | 0.397 | 4.96% | 20.515 | 20.992 | 0.992 |
| T2 | 2.65% | 21.131 | 21.058 | 0.528 | 1.98% | 21.131 | 20.922 | 0.525 | 4.96% | 21.131 | 21.533 | 0.540 |
| T3 | 2.65% | 21.712 | 21.691 | 0.633 | 1.98% | 21.712 | 21.550 | 0.629 | 4.96% | 21.712 | 22.180 | 0.647 |
| T4 | 2.65% | 22.280 | 22.287 | 0.596 | 1.98% | 22.280 | 22.142 | 0.592 | 4.96% | 22.280 | 22.789 | 0.609 |
| T5 | 2.65% | 22.871 | 22.870 | 0.583 | 1.98% | 22.871 | 22.722 | 0.580 | 4.96% | 22.871 | 23.386 | 0.597 |
| T6 | 2.65% | 23.510 | 23.476 | 0.606 | 1.98% | 23.510 | 23.324 | 0.602 | 4.96% | 23.510 | 24.006 | 0.620 |
| T7 | 2.65% | 24.067 | 24.132 | 0.656 | 1.98% | 24.067 | 23.976 | 0.652 | 4.96% | 24.067 | 24.677 | 0.671 |
| T8 | 2.65% | 24.756 | 24.705 | 0.572 | 1.98% | 24.756 | 24.545 | 0.568 | 4.96% | 24.756 | 25.262 | 0.585 |
| T9 | 2.65% | 25.406 | 25.411 | 0.707 | 1.98% | 25.406 | 25.247 | 0.702 | 4.96% | 25.406 | 25.984 | 0.723 |
| T10 | 2.65% | 26.114 | 26.079 | 0.668 | 1.98% | 26.114 | 25.910 | 0.664 | 4.96% | 26.114 | 26.667 | 0.683 |
| T11 | 2.65% | 26.795 | 26.806 | 0.727 | 1.98% | 26.795 | 26.632 | 0.722 | 4.96% | 26.795 | 27.410 | 0.743 |
| T12 | 2.65% | 27.503 | 27.504 | 0.699 | 1.98% | 27.503 | 27.326 | 0.694 | 4.96% | 27.503 | 28.125 | 0.714 |
| T13 | 2.65% | 28.297 | 28.232 | 0.727 | 1.98% | 28.297 | 28.049 | 0.723 | 4.96% | 28.297 | 28.868 | 0.744 |
| T14 | 2.65% | 29.104 | 29.047 | 0.815 | 1.98% | 29.104 | 28.859 | 0.810 | 4.96% | 29.104 | 29.702 | 0.833 |
| T15 | 2.65% | 29.982 | 29.875 | 0.828 | 1.98% | 29.982 | 29.682 | 0.823 | 4.96% | 29.982 | 30.549 | 0.847 |
| T16 | 2.65% | 30.923 | 30.776 | 0.901 | 1.98% | 30.923 | 30.577 | 0.895 | 4.96% | 30.923 | 31.470 | 0.921 |
El rendimiento esperado trimestral se estima mediante el modelo CAPM:\(E[R_{trim}] =R_{f,trim} +\beta \times(E[R_{m,trim}] - R_{f,trim})\) (Rodríguez, 2026b).
A partir de este rendimiento esperado, el valor proyectado de cada trimestre se obtiene multiplicando el valor de la cartera del período anterior por:
\((1 + E[R_{trim}])\)
De esta manera, la tabla permite comparar cómo cambios en la beta modifican simultáneamente el rendimiento esperado de la cartera, la exposición sistemática al mercado y la intensidad requerida de la cobertura mediante futuros.
Con una beta real de 0.834, el portafolio presenta una exposición sistemática moderada y requiere aproximadamente 60 contratos de futuros para reducir parcialmente su sensibilidad frente al mercado. Bajo un escenario hipotético de \(\beta = 0.5\), la menor sensibilidad sistemática implica menores retornos esperados en períodos alcistas, pero también menor exposición frente a movimientos adversos del mercado. En contraste, con \(\beta = 2.0\), el portafolio exhibe una sensibilidad considerablemente superior, amplificando tanto las ganancias potenciales en escenarios favorables como las pérdidas en contextos adversos, lo que incrementa la relevancia y el costo operativo de la cobertura.
div_tabla <- data.frame(
Empresa = c("Adobe Inc. (ADBE)",
"Vertex Pharmaceuticals (VRTX)",
"Monster Beverage Corp. (MNST)"),
Div_yield = c("0 %", "0 %", "0 %"),
Politica = c("No paga dividendos. Reinvierte mediante recompra de acciones (StockAnalysis, 2026a)",
"No paga dividendos. Reinvierte en I+D y adquisiciones estratégicas (Yahoo Finance, 2026b)",
"No paga dividendos. Reinvierte en crecimiento orgánico e internacional (Yahoo Finance, 2026c)"),
Impacto_cob = c("Sin ajuste al precio futuro por dividendos. q = 0 en F₀ = S₀·e^(r-q)T",
"Sin ajuste al precio futuro por dividendos. q = 0 en F₀ = S₀·e^(r-q)T",
"Sin ajuste al precio futuro por dividendos. q = 0 en F₀ = S₀·e^(r-q)T")
)
kable(div_tabla,
col.names = c("Empresa","Dividend Yield",
"Política de dividendos (fuente verificable)",
"Impacto en la cobertura con futuros"),
caption = "Tabla. Política de dividendos y efecto sobre el precio teórico del futuro") |>
kable_styling(bootstrap_options = c("striped","hover"), full_width = TRUE) |>
column_spec(1, bold = TRUE)| Empresa | Dividend Yield | Política de dividendos (fuente verificable) | Impacto en la cobertura con futuros |
|---|---|---|---|
| Adobe Inc. (ADBE) | 0 % | No paga dividendos. Reinvierte mediante recompra de acciones (StockAnalysis, 2026a) | Sin ajuste al precio futuro por dividendos. q = 0 en F₀ = S₀·e^(r-q)T |
| Vertex Pharmaceuticals (VRTX) | 0 % | No paga dividendos. Reinvierte en I+D y adquisiciones estratégicas (Yahoo Finance, 2026b) | Sin ajuste al precio futuro por dividendos. q = 0 en F₀ = S₀·e^(r-q)T |
| Monster Beverage Corp. (MNST) | 0 % | No paga dividendos. Reinvierte en crecimiento orgánico e internacional (Yahoo Finance, 2026c) | Sin ajuste al precio futuro por dividendos. q = 0 en F₀ = S₀·e^(r-q)T |
Las tres acciones del portafolio no pagan dividendos en efectivo, lo cual fue verificado mediante Yahoo Finance (2026a, 2026b, 2026c), DividendMax (2026a, 2026b, 2026c) y los reportes corporativos de cada empresa (Adobe Inc., 2025; Vertex Pharmaceuticals, 2026a; Monster Beverage Corporation, 2026). En consecuencia, el rendimiento total esperado del portafolio proviene exclusivamente de la valorización del capital, sin flujos intermedios por dividendos que deban incorporarse al análisis.
La ausencia de dividendos simplifica la valoración teórica de los contratos de futuros, dado que el precio del contrato puede aproximarse mediante:
\(F_0 = S_0 \cdot e^{r \cdot T}\)
donde se asume: \(q = 0\)
Siendo q el rendimiento por dividendos (dividend yield).
En caso de existir pagos de dividendos, el precio de la acción tendería a ajustarse parcialmente en la fecha ex-dividend, y el precio teórico del contrato futuro se estimaría mediante:
\(F_0 = S_0 \cdot e^{(r-q) \cdot T}\)
En este caso, un mayor rendimiento por dividendos reduciría el precio teórico del futuro y podría modificar parcialmente la cantidad óptima de contratos requeridos para la cobertura, al alterar el valor nocional utilizado en el cálculo (Hull, 2009).
Adobe Inc. (2025). Adobe reports record Q4 and FY2025 results [Comunicado de prensa, Formulario 8-K]. U.S. Securities and Exchange Commission. https://www.sec.gov/Archives/edgar/data/0000796343/000079634325000135/adbeex991q425.htm
Benzinga. (2026a). Adobe (ADBE) stock price prediction 2026. Recuperado el 30 de abril de 2026, de https://www.benzinga.com/money/adobe-stock-price-prediction
Benzinga. (2026b). Vertex Pharmaceuticals (VRTX) analyst ratings and price targets. Recuperado el 30 de abril de 2026, de https://www.benzinga.com/quote/VRTX/analyst-ratings
Bodie, Z., Kane, A., & Marcus, A. (2008). Investments (8.ª ed.). McGraw-Hill.
CBOE/Federal Reserve. (2026). CBOE interest rate 3 to 5 year treasury index (^TNX). Recuperado el 30 de abril de 2026, de https://finance.yahoo.com/quote/%5ETNX/
CME Group. (2026). E-mini S&P 500 futures contract specifications. Recuperado el 30 de abril de 2026, de https://www.cmegroup.com/markets/equities/sp/e-mini-sandp500.contractSpecs.html
DividendMax. (2026a). Adobe Inc (ADBE) dividends. Recuperado el 30 de abril de 2026, de https://dividendmax.com/united-states/nasdaq/software-and-computer-services/adobe-systems-inc/dividends
DividendMax. (2026b). Vertex Pharmaceuticals (VRTX) dividends. Recuperado el 30 de abril de 2026, de https://www.dividendmax.com/united-states/nasdaq/pharmaceuticals-and-biotechnology/vertex-pharmaceuticals-inc/dividends
DividendMax. (2026c). Monster Beverage Corporation (MNST) dividends. Recuperado el 30 de abril de 2026, de https://www.dividendmax.com/united-states/nasdaq/beverages/monster-beverage-corp/dividends
Elton, E. J., Gruber, M. J., Brown, S. J., & Goetzmann, W. N. (2014). Modern portfolio theory and investment analysis (9.ª ed.). John Wiley & Sons.
Fabozzi, F. J., Kolm, P. N., Pachamanova, D., & Focardi, S. M. (2007). Robust portfolio optimization and management. John Wiley & Sons.
FINVIZ. (2026). Stock screener — Fundamentals. Recuperado el 30 de abril de 2026, de https://finviz.com/screener.ashx
FullRatio. (2026). ADBE 2026 earnings & EPS history — quarterly & annual growth reports. Recuperado el 30 de abril de 2026, de https://fullratio.com/stocks/nasdaq-adbe/earnings
Hull, J. C. (2009). Introducción a los mercados de futuros y opciones (6.ª ed.). Pearson Education.
Investing.com. (2026). Vertex Pharmaceuticals (VRTX) stock forecast & price target. Recuperado el 30 de abril de 2026, de https://www.investing.com/equities/vertex-pharm-consensus-estimates
Markowitz, H. (1952). Portfolio selection. The Journal of Finance, 7(1), 77–91. https://doi.org/10.2307/2975974
Monster Beverage Corporation. (2026). Monster Beverage reports 2026 first quarter financial results [Comunicado de prensa, Formulario 8-K]. U.S. Securities and Exchange Commission.
https://www.sec.gov/cgi-bin/browse-edgar?action=getcompany&CIK=0000865752&type=8-K
Rodríguez, D. E. (2026a). Derivados financieros — Forwards [Material de clase]. Instituto Tecnológico Metropolitano.
Rodríguez, D. E. (2026b). Derivados financieros — Futuros [Material de clase]. Instituto Tecnológico Metropolitano.
Rodríguez, D. E. (2026c). Clase derivados financieros — 8 de mayo de 2026 [Grabación de sesión virtual]. Instituto Tecnológico Metropolitano. https://correoitmedu-my.sharepoint.com/:v:/r/personal/davidrodriguez6495_correo_itm_edu_co/Documents/Recordings/
Serrano, J. (2005). Mercados financieros. Ediciones Uniandes.
StockAnalysis. (2026a). Adobe Inc. (ADBE) — stock price & overview. Recuperado el 30 de abril de 2026, de https://stockanalysis.com/stocks/adbe/
StockAnalysis. (2026b). Vertex Pharmaceuticals (VRTX) — stock price & forecast. Recuperado el 30 de abril de 2026, de https://stockanalysis.com/stocks/vrtx/forecast/
StockAnalysis. (2026c). Monster Beverage Corporation (MNST) — stock price & overview. Recuperado el 30 de abril de 2026, de https://stockanalysis.com/stocks/mnst/
TickerNerd. (2026a). ADBE stock forecast 2026 — Adobe price targets & analyst predictions. Recuperado el 30 de abril de 2026, de https://tickernerd.com/stock/adbe-forecast/
TickerNerd. (2026b). VRTX stock forecast 2026 — Vertex price targets & analyst predictions. Recuperado el 30 de abril de 2026, de https://tickernerd.com/stock/vrtx-forecast/
TIKR. (2026). Monster Beverage stock is up 25 % over the past year: Here’s what Q1 sales jump means for 2026. Recuperado el 8 de mayo de 2026, de https://www.tikr.com/blog/monster-beverage-stock-is-up-25-over-the-past-year-heres-what-q1-sales-jump-means-for-2026
TradingView. (2026). Monster Beverage Corporation (MNST) — stock price and chart. Recuperado el 8 de mayo de 2026, de https://www.tradingview.com/symbols/NASDAQ-MNST/
Vertex Pharmaceuticals. (2026a). Vertex reports fourth quarter and full year 2025 financial results [Comunicado de prensa]. Recuperado el 30 de abril de 2026, de https://investors.vrtx.com
Vertex Pharmaceuticals. (2026b). Vertex reports first quarter 2026 financial results [Comunicado de prensa]. Recuperado el 8 de mayo de 2026, de https://news.vrtx.com/news-releases/news-release-details/vertex-reports-first-quarter-2026-financial-results
Yahoo Finance. (2026a). Adobe Inc. (ADBE) — stock price, news, quote & history. Recuperado el 30 de abril de 2026, de https://finance.yahoo.com/quote/ADBE/
Yahoo Finance. (2026b). Vertex Pharmaceuticals Incorporated (VRTX) — stock price. Recuperado el 30 de abril de 2026, de https://finance.yahoo.com/quote/VRTX/
Yahoo Finance. (2026c). Monster Beverage Corporation (MNST) — stock price, news & history. Recuperado el 30 de abril de 2026, de https://finance.yahoo.com/quote/MNST/