Nota metodológica. Este informe se preparó y se publica directamente como documento R Markdown en RPubs: no es un PDF ni una exportación estática. Todo el código que genera las cifras, tablas y gráficas de esta página es visible (puede desplegarse con el botón “Code” de cada sección) y se ejecutó al momento de compilar el documento, usando los mismos datos (datos.xlsx) y los mismos scripts de R que respaldan el trabajo entregado. Las tablas son interactivas (se pueden ordenar y buscar) y las gráficas son interactivas (Plotly: zoom, panorámica y lectura de valores al pasar el cursor).

Introducción

Datos y fuentes utilizadas

Todos los datos de mercado que se usan en el trabajo fueron consultados entre el 2 y el 9 de septiembre de 2026, tomando en cada caso la publicación la que produce el dato del Banco de la República, DANE, Reserva Federal y Tesoro de Estados Unidos. Cuando un dato se actualizó dentro de esta ventana temporal usamos el más reciente y dejamos anotada la fecha; la fecha de valoración del ejercicio, en cambio, se mantiene fija en el 2 de septiembre para que todos los cálculos queden comparables entre sí. La tabla siguiente distingue el valor, la fuente con su fecha consultada y la forma en que cada tasa está cotizada, porque de eso depende cómo se debe usar en las fórmulas.

Es importante separar tres cosas que se mezclan con facilidad y estas son: los datos observados como la TRM, las tasas de política, los rendimientos del Tesoro, además de las proyecciones publicadas por terceros como la de los bancos y de Fedesarrollo y por último, los supuestos propios del trabajo como las tasas de devaluación de cada escenario, la ventana de datos con la que se estimó la volatilidad y la volatilidad usada en la simulación. Los supuestos se identifican de manera expresa cada vez que aparecen, porque son los puntos donde el resultado depende de una decisión nuestra y no de un dato publicado.

Parte 1. Desarrollo de un forward de divisas

Parte 1. Desarrollo de un forward de divisas

A.1. Análisis fundamental de la TRM y expectativa a un año

La TRM del 2 de septiembre de 2026 se ubicó en 3,184.00 pesos por dólar según el Banco de la República, y al 9 de septiembre había seguido bajando hasta 3,116.47. Ese nivel es muy distinto del que había el año pasado, en septiembre de 2025 la TRM promedio fue de 3,914.83 pesos y en enero de 2026 el dólar todavía se negociaba a un precio alto, alrededor de 3,757 pesos. Esto significa que el peso colombiano se ha fortalecido cerca de 19 % en lo que va del 2026, y el 24 de agosto el dólar llegó a 3,021.50 pesos, su nivel más bajo desde octubre del 2018.

Este gráfico muestra dos cosas útiles para el trabajo, La primera es que la tasa de cambio no se mueve poco ya que entre 2020 y 2026 pasó de niveles cercanos a 3,470 pesos hasta casi 4,930 pesos en noviembre de 2022 y luego bajó de nuevo hasta 3,184 pesos, asumiendo nosotros que en los últimos diez años el rango observado va de 2,705 a 5,061 pesos, casi el doble entre un extremo y otro. La segunda es que esos movimientos no son lentos y graduales, ya que ocurren en periodos de pocos meses y esto para una empresa que va a tener una deuda en dólares durante diez años implica que hay un problema de inestabilidad que exactamente es el problema que hay que arreglar, y no como una posibilidad de margen teórico ya que en unen un plazo igual al del crédito el dólar en el que ya subió y volvió a bajar dos veces.

Factores que pueden fortalecer al peso colombiano:

1. Diferencial de tasas de interés. El Banco de la República tiene su tasa de política en 12.0 % efectivo anual, después de subirla 100 puntos básicos el 30 de enero, 100 pb en marzo, llevarla a 11.25 % y sumarle otros 75 puntos básicos a finales de junio de 2026, en las reuniones del 31 de julio y de agosto la dejó quieta en ese nivel. Al mismo tiempo, la Reserva Federal mantiene su rango objetivo de tasas en 3.50 % – 3.75 %, sin moverlo desde diciembre de 2025. Esa diferencia de más de ocho puntos porcentuales hace que invertir en pesos sea atractivo: entran capitales, aumenta la oferta de dólares en el mercado local y el precio del dólar baja.

2. Debilidad global del dólar y apetito por economías emergentes. Los analistas del Grupo Cibest explican que el fortalecimiento del peso en 2026 se apoyó en el diferencial de tasas, en la entrada de flujos hacia economías emergentes y en un entorno político que el mercado leyó de manera favorable.

3. Mejores datos de actividad, aunque no de inflación. El PIB creció 3.5 % en el segundo trimestre de 2026, y mientras la economía sostenga ese ritmo mejora la percepción de riesgo del país mientras que se necesita menos prima de riesgo para invertir en activos colombianos. Sin embargo el índice de inflación nos dejó de ayudar, según el DANE, la inflación de colombia reportó 6.03 % anual en julio, pero el dato de agosto subió a 6.24 %, por encima del 6.10 % que esperaba el consenso y con una variación mensual de 0.39 % frente al 0.27 % proyectado. Según estos datos, el acumulado del año va en 5.35 %, dato que ya supera todo el año del 2025.

4. Precio del petróleo relativamente alto. El Brent se ubicó alrededor de 92 a 94 dólares por barril a comienzos de septiembre de 2026, y al 9 de septiembre ya estaba entre 99 y 101 dólares, con más de 8 % de alza en lo corrido del mes. El petróleo sigue siendo la principal fuente de exportación colombiana, de modo que un precio alto significa más dólares entrando al país. Vale la pena mirar de dónde viene esa subida, porque no es demanda global sino prima de riesgo geopolítica por el conflicto entre Estados Unidos e Irán y la parálisis del comercio en el estrecho de Ormuz, estas variables son un soporte real para el peso,sin embargo no es una base sobre la cual se pueda planear operaciones a diez años.

Factores que pueden debilitar al peso colombiano

  1. Situación fiscal. La reconstrucción tras el terremoto de magnitud 7.4 ocurrido el 10 de agosto de 2026 se estima en aproximadamente unos 30 billones de pesos, de los cuales 24.5 billones corresponden a edificaciones y 5.5 billones a infraestructura, y el gobierno saliente ( gobierno de gustavo petro ), utilizó el 96 % del cupo de emisión de deuda interna, una proporción rarisima en una transición presidencial, con un mayor déficit y más deuda aumenta la percepción del riesgo país y hace que la tasa de cambio gire hacia arriba, y ese gasto llega sobre un déficit que cerró el 2025 en 6.4 % del PIB y podría ubicarse en 7.4 % en 2026, con una deuda que pasaría de $89 a $118 billones el año entrante. El problema no está tanto en que la deuda supere los mil billones de pesos, sino en el costo anual que implica mantenerla. Estos gastos compiten constantemente con los demás rubros del presupuesto y generan preocupación en el mercado sobre la capacidad del país para sostener sus finanzas.

2. Cambio de rumbo de la Reserva Federal. El presidente de la Reserva Federal advirtió que una inflación persistente podría justificar aumentos de tasas. Si la Fed sube y el Banco de la República deja de subir o empieza a bajar, el diferencial de tasas se cierra y desaparece el principal soporte del peso y lo que motiva a los inversores a invertir en una economía emergente.

3. Caída del precio del petróleo. Una baja del Brent reduce los ingresos de exportación y deteriora la balanza de pagos. Hecho que ya se sintió a finales de agosto de 2026, y el riesgo es más grave de lo que se piensa actualmente ya que el precio se está sosteniendo sobre una tensión geopolítica que puede caerse en cuestión de semanas si hay un acuerdo, esto hace parte de los factores geopolíticos que dañan los modelos sin embargo es importante tenerlos en cuenta.

4. Riesgo político y reversión de flujos.Gran parte de la fuerza del peso en lo que va del 2026 se explica por el resultado electoral y por la expectativa que viene generando el gobierno de Abelardo de la Espriella, Esa expectativa todavía no es un hecho: si no es respaldada por las acciones del presidente haciendo que en un escenario donde abelardo no cumpla con sus expectativas, los flujos que entran pueden salir con la misma rapidez.

5. Inflación todavía alta. Con una inflación de 6.24 % anual en agosto frente al 2 % de meta en Estados Unidos, la teoría de la paridad del poder adquisitivo nos recomienda que, en el largo plazo, el peso debería tender a depreciarse frente al dólar para compensar esa diferencia de precios. Lo tedioso de este dato es que la inflación sigue subiendo a pesar de casi tres puntos porcentuales de aumentos en la tasa de política, y eso nos deja con 2 alternativas a tomar en un futuro, o el Banco de la República sube más y el peso se sostiene un tiempo más a costa de la actividad, o el mercado empieza a dudar de que la meta se alcance y por ende la prima de riesgo suba,haciendo que el peso se debilite con las altas tasas.

Escenario más razonable para los próximos doce meses

Considerando que el trabajo no busca acertar con un valor exacto ya que de acá a 12 meses pueden pasar muchas cosas, lo que necesitamos es un rango razonable y que podamos defender. Las proyecciones disponibles son bastante diversas ya que para el cierre de 2026, Santander proyecta 3,150 pesos, Citi 3,200, Skandia y Alianza 3,300, y BTG Pactual 4,000, la Encuesta de Opinión Financiera de Fedesarrollo y la Bolsa de Valores de Colombia arrojaba 3,650 pesos, y el Grupo Cibest mantiene un rango de 3,400 a 3,650 pesos. Cabe recalcar que lo más probable es que la gran mayoría fueron utilizadas con inflación de 6.04%, no con la de 6.24% que equivale al dato actual que salió por encima de lo esperado, de modo que es probable que varias ya se hayan revisado.

La diferencia entre las proyecciones, que van desde 3,150 hasta 4,000 pesos para la misma fecha muestran algo importante y es que ni siquiera los analistas profesionales tienen una idea totalmente clara de hacia dónde va el dólar. El modelo que construimos en el índice A.3, usando los datos históricos de la TRM, muestra que para los próximos doce meses el valor más probable estaría alrededor de 3,326 pesos por dólar. Además, el rango de posibles resultados va aproximadamente desde 2,795 hasta 3,953 pesos. Este resultado es bastante parecido al rango que manejan los analistas, que está entre 3,150 y 4,000 pesos. Por eso, para el trabajo tomamos como referencia que dentro de un año el dólar podría estar alrededor de 3,300–3,400 pesos, aunque también es razonable pensar en un rango más amplio entre 2,800 y 4,000 pesos.

Parte A. Proceso inicial del crédito y medición del riesgo cambiario

A.2. Simulación del crédito en dólares

El crédito cubre el 90 % del valor de la maquinaria, lo que equivale a COP 360,000,000 (sobre un total de COP 400,000,000). Al convertir este monto a dólares usando la TRM de valoración de 3,184.00 COP/USD, obtenemos un principal de 113,065.33 USD. Este monto se pagará en 40 cuotas trimestrales iguales durante 10 años, aplicando el sistema de amortización francés.

Tasa seleccionada y por qué es pertinente

Se decidió usar una tasa de Prime + 65 puntos básicos, lo que resulta en un 7.40 % nominal anual (7.61 % efectiva anual o 1.85 % trimestral). Esta estructura busca replicar cómo funcionan los préstamos comerciales a plazo (term loans) para la compra de maquinaria en el mercado estadounidense.

Dato Valor Fuente y fecha de consulta
Wall Street Journal Prime Rate (referencia vigente) 7.00 % Bankrate, "Wall Street Prime Rate" (actualizado 20-oct-2026)
Spread aplicado por el banco + 0.65 % Supuesto propio del trabajo (spread típico de un term loan corporativo sobre Prime, 50–150 pb)
Tasa resultante usada en el modelo 6.75 % + 0.65 % = 7.40 % nominal Valor fijado en el modelo original; ver nota de consistencia abajo

Nota de consistencia:

La tasa del 7.40 % que se aplica en todo el flujo de amortización parte de una tasa Prime del 6.75 %, no del 7.00 % que marca el WSJ actualmente. Aunque esa diferencia de 25 pb es importante, es pequeña comparada con el spread y no se ajustó para evitar tener que recalcular la cuota y todas las cifras que ya se usaron de forma coherente en el resto del trabajo (amortización, pronóstico de TRM y forwards de la Parte B).

El uso del Prime Rate es ideal para financiar maquinaria porque es la referencia que los bancos en EE. UU. usan para prestar a empresas con buen perfil crediticio. A diferencia de la tasa SOFR, que es de muy corto plazo y bastante volátil, el Prime se ajusta gradualmente según las decisiones de la Reserva Federal. Esto permite tener cuotas más predecibles, algo clave para un activo con una vida útil larga como esta maquinaria que se financiará a 10 años. Además, un spread de 65 pb sobre el Prime es muy razonable para un crédito garantizado con la misma maquinaria, manteniéndose dentro del rango habitual de 50 a 150 pb para préstamos corporativos de calidad media-alta.

Resultados de la amortización (sistema francés, cuota fija)

Concepto Resultado Lectura
Principal 113,065.33 USD 90 % de COP 400,000,000 a TRM 3,184.00
Cuota trimestral fija 4,025.23 USD 40 cuotas iguales, 1.85 % trimestral
Total pagado (40 cuotas) 161,009.33 USD 1.42 × el principal
Intereses totales 47,944.00 USD 42.4 % del principal, acumulado en 10 años
Cuota anual (4 × trimestral) 16,100.93 USD Flujo de caja anual fijo en dólares
Exposición cubierta con forward (75 %) 12,075.70 USD por año 3 de las 4 cuotas anuales

Lectura del resultado

Aunque la cuota en dólares es siempre la misma (4,025.23 USD), su composición cambia con el tiempo. Al principio, casi la mitad de la cuota se va en intereses debido al saldo alto, pero hacia el final, casi todo el pago se destina a reducir el capital, ya que el saldo pendiente es mínimo. Este es el comportamiento normal de cualquier amortización francesa y se confirma en la tabla completa de 40 cuotas del modelo.

El costo del crédito en dólares es una cifra fija desde la firma: se pagarán 47,944.00 USD de intereses sobre los 113,065.33 USD prestados, sin importar cómo se mueva el tipo de cambio. Sin embargo, el costo en pesos es incierto. Como la empresa recibe ingresos en pesos pero debe pagar en dólares, cada cuota de 4,025.23 USD dependerá de la TRM del día del pago. Aquí es donde aparece el riesgo cambiario que el resto del trabajo analiza. El crédito no tiene riesgo de tasa de interés porque es fija, pero tiene un riesgo cambiario total sobre sus 40 pagos.

Los años del 7 al 10 representan el 40 % de los pagos totales (16 de las 40 cuotas) y es precisamente ese periodo el que la Parte B cubre con forwards. Al asegurar el 75 % de la exposición de esos años (12,075.70 de los 16,100.93 USD anuales), estamos cubriendo el 30 % del costo total del crédito (0.75 x 0.40 = 30 %). El 70 % restante (los primeros 6 años más el 25 % no cubierto de los últimos 4) sigue expuesto a la TRM. Esto es coherente con una estrategia de cobertura parcial, la cual, como se verá en la sección B.1, tiene un costo: el forward solo sirve si el peso se deprecia más de la prima implícita, pero no protege si el peso se aprecia, como pasó en 2026.

fecha0    <- as.Date("2026-09-02")
S0        <- 3184.00                       # TRM 2-sep-2026
monto_cop <- 400000000 * 0.90              # 90 % financiado
tasa      <- 0.0675 + 0.0065               # Prime + 65 pb = 7.40 %
i_trim    <- tasa / 4
n_cuotas  <- 40

P_credito <- monto_cop / S0
PMT       <- P_credito * i_trim / (1 - (1 + i_trim)^(-n_cuotas))
cuota_anual <- 4 * PMT

amort <- data.frame(cuota = 1:n_cuotas)
saldo_ini <- numeric(n_cuotas); interes <- numeric(n_cuotas); capital <- numeric(n_cuotas)
saldo <- P_credito
for (k in 1:n_cuotas) {
  saldo_ini[k] <- saldo
  interes[k]   <- saldo * i_trim
  capital[k]   <- PMT - interes[k]
  saldo        <- saldo - capital[k]
}
amort$saldo_ini <- saldo_ini
amort$interes   <- interes
amort$capital   <- capital
amort$cuota_usd <- PMT
amort$ano       <- ceiling(amort$cuota / 4)
amort$fecha     <- seq(fecha0, by = "3 months", length.out = n_cuotas + 1)[-1]

cat(sprintf("Principal %s USD | tasa %.2f%% nominal (%.2f%% EA) | cuota %s USD | total %s USD | intereses %s USD\n",
            miles(P_credito, 2), tasa * 100, ((1 + i_trim)^4 - 1) * 100,
            miles(PMT, 2), miles(sum(amort$cuota_usd), 2), miles(sum(interes), 2)))
## Principal 113.065,3 USD | tasa 7.40% nominal (7.61% EA) | cuota 4.025,23 USD | total 161.009,3 USD | intereses 47.944 USD
cat(sprintf("Cuota anual %s USD | forward (75%%) %s USD\n", miles(cuota_anual, 2), miles(3 * PMT, 2)))
## Cuota anual 16.100,93 USD | forward (75%) 12.075,7 USD

Tabla A.2. Plan de amortización del crédito en dólares (40 cuotas trimestrales, sistema francés)

dt_tabla(amort[, c("cuota", "ano", "fecha", "saldo_ini", "interes", "capital", "cuota_usd")],
         dec = 2, caption = "Amortización del crédito en dólares")
amort_long <- amort %>%
  select(cuota, capital, interes, saldo_ini) %>%
  pivot_longer(c(capital, interes), names_to = "componente", values_to = "valor")
amort_long$componente <- factor(amort_long$componente, levels = c("capital", "interes"),
                                 labels = c("Abono a capital", "Intereses"))

g_a2 <- ggplot(amort_long, aes(x = cuota, y = valor, fill = componente)) +
  geom_col(width = 0.9) +
  scale_fill_manual(values = c("Abono a capital" = "#c7d2e3", "Intereses" = AZUL)) +
  geom_vline(xintercept = 24.5, color = NARANJA, linetype = "dashed") +
  labs(title = "Gráfico A.2.1. Composición de las 40 cuotas del crédito en dólares",
       subtitle = "Cuota fija de 4,025.23 USD: al inicio casi la mitad es interés, al final casi todo es capital. La línea naranja marca el inicio de los años 7-10 (tramo con forwards, Parte B)",
       x = "Cuota trimestral", y = "USD por cuota", fill = NULL) +
  theme_minimal() + theme(legend.position = "bottom")
ggplotly(g_a2) %>% layout(legend = list(orientation = "h", y = -0.2))

A.3. Conversión del crédito a pesos colombianos

Tomando como base las 40 cuotas fijas en dólares mencionadas en el punto A.2 (cada una de 4,025.23 USD), vamos a convertir cada pago a pesos multiplicándolo por la TRM vigente el día del pago. Para esto, planteamos dos escenarios: primero, un escenario base con una TRM fija de 3,184.00 COP/USD (la tasa spot al 2 de septiembre de 2026); y segundo, una trayectoria simulada de la TRM mes a mes para ver cómo cambia el costo en pesos si el tipo de cambio se mueve durante los 10 años que dura el crédito.

Escenario base: TRM fija en 3,184.00

Concepto Resultado Lectura
Cuota 1 en pesos (TRM base) 12,816,342 COP 4,025.23 USD × 3,184.00
Total pagado, 40 cuotas (TRM base) 512.65 M COP 1.42 × el principal en COP, igual proporción que en USD
Intereses totales (TRM base) 152.65 M COP Mismo 42.4 % del principal que en USD, convertido a la TRM fija

Si la TRM se mantuviera totalmente estable, el costo en pesos sería simplemente el costo en dólares multiplicado por una constante: 512.65 millones de pesos. De esa cifra, 152.65 millones (un 29.8 %) corresponden a intereses y el resto es el capital devuelto. Este número nos sirve como punto de comparación para entender qué parte del costo final se debe exclusivamente a las variaciones del tipo de cambio.

Modelo de la TRM usado para la trayectoria simulada

La trayectoria mensual se basa en un modelo de reversión a la media calculado en el código (un proceso AR(1) sobre el logaritmo de la TRM, usando datos de Yahoo Finance desde enero de 2016 hasta agosto de 2026). El modelo tiene un φ de 0.9658 (lo que da una vida media de 19.9 meses) y un nivel de largo plazo de 3,503 COP/USD para hoy. A 12 meses, el modelo proyecta un p5 de 2,719, una mediana de 3,326 y un p95 de 3,846 (lo cual coincide con el punto A.1). A 10 años, los valores son p5 = 2,826, mediana = 3,505 y p95 = 4,301. Es un rango amplio, pero se mantiene dentro de un histórico razonable de entre 3,000 y 4,000, sin incluir una tendencia artificial al alza.

Costo total en pesos bajo la trayectoria simulada

Estadístico Costo total (M COP) Estadístico Costo total (M COP)
Media 556.14 p5 492.55
Desviación estándar 39.83 p95 623.69
Escenario base (TRM fija) 512.65 p99 651.84

El costo esperado con la trayectoria simulada (556.14 M) es 43.49 M más alto que el escenario base (512.65 M), es decir, un 8.5 % más caro. Aunque el modelo de reversión a la media no predice una caída fuerte del peso de forma sistemática, la relación no es lineal (la cuota en pesos es la TRM por la cuota fija en dólares). Esto hace que, al promediar miles de trayectorias, el costo esperado en pesos termine siendo mayor que el costo al tipo de cambio actual, incluso con un modelo centrado. En el percentil 99, el costo sube hasta 651.84 M, un 27.1 % por encima del escenario base. Ese es precisamente el riesgo de cola que la estrategia de cobertura de la Parte B intenta limitar para los años 7 al 10.

Efecto sobre el flujo de caja

Incluso en el escenario mediano, el pago anual (4 cuotas) va creciendo con el tiempo: pasa de 52.4 M COP en el primer año a 56.4 M COP en el año 10 (mediana). Esto representa un aumento del 7.6 % a pesar de que la cuota en dólares no cambia. La razón es que la TRM mediana del modelo sube ligeramente con el tiempo (de 3,200 en la primera cuota a 3,505 en la última), reflejando la convergencia hacia el nivel de largo plazo estimado (entre 3,503 y 3,564) y no una depreciación acelerada. Además, la incertidumbre aumenta conforme pasa el tiempo: el pago del año 1 oscila entre 46.9 y 58.2 M COP (p5 a p95), mientras que el del año 10 va de 46.2 a 68.4 M COP. La banda de variación se abre más hacia arriba que hacia abajo, algo lógico en una variable que no puede ser negativa y que tiene una cola derecha más larga.

El coeficiente de variación de la última cuota (año 10) entre los 10,000 escenarios es del 12.7 %. Es una variabilidad bastante alta para un pago que, en dólares, es totalmente fijo y conocido desde el día de la firma del crédito.

Obligación estable en dólares vs. obligación variable en pesos

El punto clave aquí es que la deuda es la misma, pero el riesgo cambia totalmente dependiendo de la moneda que uses para medirla. En dólares, el crédito es predecible: son 40 cuotas de 4,025.23 USD sin ninguna duda sobre el monto. Pero en pesos, que es la moneda con la que la empresa opera y paga sus cuentas, esa misma cuota se vuelve una variable incierta, con un costo total promedio de 556.14 M COP, una desviación estándar de 39.83 M y un riesgo de llegar hasta 651.84 M en el percentil 99. Esta diferencia es exactamente la definición del riesgo cambiario de una obligación en moneda extranjera: el riesgo no desaparece al fijar la tasa de interés del crédito, solo se traslada del componente financiero al componente cambiario.

Qué parte de la variación viene de los intereses y qué parte de la tasa de cambio

Componente (M COP) Favorable (p5) Base (TRM 3,184) Promedio Adverso (p95)
Capital a TRM inicial 360.00 360.00 360.00 360.00
Intereses a TRM inicial 152.65 152.65 152.65 152.65
Efecto cambiario s/ capital −21.62 0.00 32.20 81.70
Efecto cambiario s/ intereses 1.51 0.00 11.29 29.34

Esta tabla separa, en cada escenario, lo que costaría en pesos si la TRM no se moviera (capital e intereses a la TRM inicial, que suman los 512.65 M del escenario base) de lo que añade el movimiento del tipo de cambio. El resultado es muy claro: el 100 % de la desviación estándar del costo total (39.83 M) viene de la tasa de cambio (29.16 M por el capital y 11.72 M por los intereses). Esto pasa porque los intereses del crédito, calculados en dólares a una tasa fija del 7.40 % nominal, no tienen variabilidad propia una vez firmado el contrato. En resumen: el crédito en dólares no tiene riesgo de tasa de interés, pero toda su variabilidad en pesos es, sin excepción, riesgo cambiario puro. Esto justifica por qué la estrategia de la Parte B se enfoca en forwards de divisas y no en instrumentos de tasa de interés: ese es el único riesgo real una vez que convertimos el crédito a la moneda de la empresa.

primer_mes <- "2016-01-01"
cierre_mes_actual <- format(as.Date(paste(format(fecha0, "%Y-%m"), "01", sep = "-")), "%Y-%m-%d")

fetch_cop <- function(tries = 5) {
  for (i in 1:tries) {
    out <- tryCatch(
      getSymbols("COP=X", src = "yahoo", from = primer_mes, to = cierre_mes_actual,
                 periodicity = "daily", auto.assign = FALSE),
      error = function(e) NULL)
    if (!is.null(out)) return(out)
    Sys.sleep(5 * i)
  }
  stop("No se pudo descargar COP=X de Yahoo Finance tras varios intentos.")
}
cop_daily <- fetch_cop()
diaria <- na.omit(Cl(cop_daily))
diaria <- diaria[diaria > 1500 & diaria < 6000]

hist_xts <- diaria[endpoints(diaria, on = "months"), ]
hist_vals <- as.numeric(hist_xts)
hist_dates <- index(hist_xts)
MAX_HIST <- as.numeric(max(diaria))
FECHA_MAX_HIST <- index(diaria)[which.max(as.numeric(diaria))]

logS <- log(hist_vals)
r <- diff(logS)
MEDIANA_A1 <- 3326; P5_A1 <- 2795; P95_A1 <- 3953   # A.1, a 12 meses
DERIVA <- 0.0
N <- 10000; MESES <- 120; BLOQUE <- 12; SEMILLA <- 2026

cat(sprintf("TRM mensual descargada de Yahoo Finance (COP=X): %d observaciones, %s a %s\n",
            length(hist_vals), format(hist_dates[1], "%b-%Y"), format(tail(hist_dates, 1), "%b-%Y")))
## TRM mensual descargada de Yahoo Finance (COP=X): 128 observaciones, Jan-2016 a Aug-2026
cat(sprintf("Máximo histórico diario (serie limpia): %s COP/USD, el %s\n", miles(MAX_HIST, 2), FECHA_MAX_HIST))
## Máximo histórico diario (serie limpia): 5.106 COP/USD, el 2022-11-08
Xmat <- cbind(1, logS[-length(logS)])
y    <- logS[-1]
beta_ar1 <- solve(t(Xmat) %*% Xmat, t(Xmat) %*% y)
a_coef <- beta_ar1[1]; PHI <- beta_ar1[2]
e <- as.numeric(y - Xmat %*% beta_ar1)
e <- e - mean(e)

razon_var <- function(h) {
  n <- length(logS)
  var(logS[(h + 1):n] - logS[1:(n - h)]) / (h * var(r))
}

set.seed(SEMILLA)
n_bloques <- MESES / BLOQUE
e_ext <- c(e, e[1:BLOQUE])
inicio <- matrix(sample(0:(length(e) - 1), N * n_bloques, replace = TRUE), nrow = N, ncol = n_bloques)
Z <- matrix(NA_real_, nrow = N, ncol = MESES)
for (j in 1:n_bloques) {
  cols <- ((j - 1) * BLOQUE + 1):(j * BLOQUE)
  for (b in 1:BLOQUE) {
    Z[, cols[b]] <- e_ext[inicio[, j] + b]
  }
}

simular <- function(Z, escala, nivel, kappa, meses = MESES) {
  ls <- matrix(log(S0), nrow = N, ncol = meses + 1)
  for (t in 1:meses) {
    jalon <- kappa * (nivel + DERIVA * (t - 1) / 12 - ls[, t])
    ls[, t + 1] <- ls[, t] + jalon + escala * Z[, t]
  }
  exp(ls)
}

calibrar <- function(Z, kappa) {
  escala <- 1.0; nivel <- a_coef / (1 - PHI)
  for (it in 1:25) {
    s12 <- log(simular(Z, escala, nivel, kappa, 12)[, 13])
    p5  <- quantile(s12, 0.05); p50 <- quantile(s12, 0.50); p95 <- quantile(s12, 0.95)
    escala <- escala * (log(P95_A1 / P5_A1) / (p95 - p5))
    nivel  <- nivel + (log(MEDIANA_A1) - p50) / (1 - (1 - kappa)^12)
  }
  c(escala = unname(escala), nivel = unname(nivel))
}

kappa <- 1 - PHI
cal <- calibrar(Z, kappa)
escala <- cal["escala"]; nivel <- cal["nivel"]
S <- simular(Z, escala, nivel, kappa)          # N x 121 (mes 0..120)
St <- S[, seq(4, ncol(S), by = 3)]              # TRM en las 40 fechas de pago (cada trimestre)
rango10 <- apply(S, 1, max) - apply(S, 1, min)
rango_hist <- max(hist_vals) - min(hist_vals)

cat(sprintf("phi = %.4f | vida media %.1f meses | nivel de largo plazo estimado %s, calibrado hoy %s | escala %.3f\n",
            PHI, log(0.5) / log(PHI), miles(exp(a_coef / (1 - PHI))), miles(exp(nivel)), escala))
## phi = 0.9679 | vida media 21.2 meses | nivel de largo plazo estimado 3.582, calibrado hoy 3.525 | escala 0.808
for (tt in c(12, 120)) {
  cat(sprintf("TRM a %s: p5 %s | mediana %s | p95 %s\n",
              ifelse(tt == 12, "12 meses", "10 años"),
              miles(quantile(S[, tt + 1], 0.05)), miles(median(S[, tt + 1])), miles(quantile(S[, tt + 1], 0.95))))
}
## TRM a 12 meses: p5 2.736 | mediana 3.326 | p95 3.870
## TRM a 10 años: p5 2.828 | mediana 3.520 | p95 4.325
cat(sprintf("Rango máx-mín en 10 años: mediana %s; supera el real (%s) en %.1f%% de los caminos\n",
            miles(median(rango10)), miles(rango_hist), mean(rango10 > rango_hist) * 100))
## Rango máx-mín en 10 años: mediana 1.324; supera el real (2.059) en 3.2% de los caminos
cop <- sweep(St, 2, amort$cuota_usd, `*`)       # N x 40, cuota en pesos por camino
costo <- rowSums(cop)
anual <- t(apply(cop, 1, function(x) tapply(x, rep(1:10, each = 4), sum)))
q <- sapply(c(5, 25, 50, 75, 95), function(p) apply(St, 2, quantile, probs = p / 100))
colnames(q) <- c("p5", "p25", "p50", "p75", "p95")

cat(sprintf("Base (TRM %s): cuota %s COP | total %s M (intereses %s M)\n",
            miles(S0), miles(PMT * S0), miles(sum(amort$cuota_usd) * S0 / M, 2), miles(sum(interes) * S0 / M, 2)))
## Base (TRM 3.184): cuota 12.816.342 COP | total 512,65 M (intereses 152,65 M)
cat(sprintf("Costo total (M): media %.2f | desv %.2f | p5 %.2f | p95 %.2f | p99 %.2f\n",
            mean(costo) / M, sd(costo) / M, quantile(costo, 0.05) / M, quantile(costo, 0.95) / M, quantile(costo, 0.99) / M))
## Costo total (M): media 557.72 | desv 41.36 | p5 493.21 | p95 626.90 | p99 661.21

Tabla A.3.1. Costo total del crédito en pesos, estadísticos de la distribución simulada (M COP)

tabla_costo_a3 <- data.frame(
  Estadístico = c("Media", "Desviación estándar", "Escenario base (TRM fija)", "p5", "p95", "p99"),
  Costo_M_COP = c(mean(costo)/M, sd(costo)/M, sum(amort$cuota_usd)*S0/M,
                   quantile(costo,0.05)/M, quantile(costo,0.95)/M, quantile(costo,0.99)/M)
)
dt_tabla(tabla_costo_a3, dec = 2, caption = "Costo total en pesos bajo la trayectoria simulada")
cat("Pago anual (M) p5 / mediana / p95:\n")
## Pago anual (M) p5 / mediana / p95:
for (yy in 1:10) {
  cat(sprintf("  año %2d: %s\n", yy,
              paste(sprintf("%5.1f", quantile(anual[, yy], c(0.05, 0.50, 0.95)) / M), collapse = " / ")))
}
##   año  1:  47.3 /  52.2 /  57.8
##   año  2:  45.5 /  53.9 /  63.4
##   año  3:  45.5 /  54.8 /  65.5
##   año  4:  45.7 /  55.5 /  66.8
##   año  5:  45.8 /  55.9 /  67.5
##   año  6:  45.9 /  56.1 /  68.3
##   año  7:  46.1 /  56.3 /  68.6
##   año  8:  46.4 /  56.6 /  68.8
##   año  9:  46.2 /  56.5 /  69.1
##   año 10:  46.3 /  56.6 /  69.1
fx_cap <- as.numeric((St - S0) %*% capital)
fx_int <- as.numeric((St - S0) %*% interes)
orden <- order(costo)
casos <- list(
  "Favorable (p5)"  = c(fx_cap[orden[round(N / 20)]], fx_int[orden[round(N / 20)]]),
  "Base (TRM)"      = c(0, 0),
  "Promedio"        = c(mean(fx_cap), mean(fx_int)),
  "Adverso (p95)"   = c(fx_cap[orden[round(19 * N / 20)]], fx_int[orden[round(19 * N / 20)]])
)
desc <- rbind(
  "Capital a TRM inicial"        = rep(sum(capital) * S0, 4),
  "Intereses a TRM inicial"      = rep(sum(interes) * S0, 4),
  "Efecto cambiario s/ capital"  = sapply(casos, `[`, 1),
  "Efecto cambiario s/ intereses" = sapply(casos, `[`, 2)
) / M
colnames(desc) <- names(casos)
cat(sprintf("Desv. estándar del costo %.2f M, toda por la TRM (capital %.2f M, intereses %.2f M)\n",
            sd(costo) / M, sd(fx_cap) / M, sd(fx_int) / M))
## Desv. estándar del costo 41.36 M, toda por la TRM (capital 30.38 M, intereses 12.00 M)

Tabla A.3.2. Descomposición del costo: capital e intereses vs. efecto cambiario (M COP)

dt_tabla(as.data.frame(desc), dec = 2, caption = "Descomposición del costo total")
set.seed(SEMILLA)
inicio_pa <- matrix(sample(0:(length(e) - 1), N * n_bloques, replace = TRUE), nrow = N, ncol = n_bloques)
Z_pa <- matrix(NA_real_, nrow = N, ncol = MESES)
for (j in 1:n_bloques) {
  cols <- ((j - 1) * BLOQUE + 1):(j * BLOQUE)
  for (b in 1:BLOQUE) Z_pa[, cols[b]] <- e_ext[inicio_pa[, j] + b]
}
simular_pa <- function(Z, escala, nivel_mensual, meses = MESES) {
  ls <- matrix(log(S0), nrow = N, ncol = meses + 1)
  for (t in 1:meses) {
    jalon <- if (t <= 12) nivel_mensual else DERIVA / 12
    ls[, t + 1] <- ls[, t] + jalon + escala * Z[, t]
  }
  exp(ls)
}
calibrar_pa <- function(Z) {
  escala <- 1.0; nivel <- 0.0
  for (it in 1:25) {
    s12 <- log(simular_pa(Z, escala, nivel, 12)[, 13])
    p5  <- quantile(s12, 0.05); p50 <- quantile(s12, 0.50); p95 <- quantile(s12, 0.95)
    escala <- escala * (log(P95_A1 / P5_A1) / (p95 - p5))
    nivel  <- nivel + (log(MEDIANA_A1) - p50) / 12
  }
  c(escala = unname(escala), nivel = unname(nivel))
}
cal_pa <- calibrar_pa(Z_pa)
S_pa <- simular_pa(Z_pa, cal_pa["escala"], cal_pa["nivel"])
St_pa <- S_pa[, seq(4, ncol(S_pa), by = 3)]

Gráficos del modelo de la TRM

df_hist <- data.frame(fecha = hist_dates, trm = hist_vals) %>% filter(fecha >= as.Date("2020-01-01"))
df_band <- data.frame(fecha = c(fecha0, amort$fecha),
                       p5  = c(S0, q[, "p5"]),  p25 = c(S0, q[, "p25"]),
                       p50 = c(S0, q[, "p50"]), p75 = c(S0, q[, "p75"]), p95 = c(S0, q[, "p95"]))

g_a3 <- ggplot() +
  geom_line(data = df_hist, aes(x = fecha, y = trm), color = GRIS) +
  geom_ribbon(data = df_band, aes(x = fecha, ymin = p5, ymax = p95), fill = AZUL, alpha = 0.15) +
  geom_ribbon(data = df_band, aes(x = fecha, ymin = p25, ymax = p75), fill = AZUL, alpha = 0.30) +
  geom_line(data = df_band, aes(x = fecha, y = p50), color = AZUL, linewidth = 1.1) +
  geom_hline(yintercept = S0, linetype = "dotted", color = NEGRO) +
  geom_hline(yintercept = MAX_HIST, linetype = "dashed", color = ROJO) +
  geom_hline(yintercept = exp(nivel), linetype = "dotdash", color = NARANJA) +
  labs(title = "Gráfico A.3.1. TRM observada y proyectada en las fechas de pago",
       subtitle = "Modelo empírico con reversión a la media (TRM 2016-2026)",
       x = NULL, y = "COP por USD") +
  theme_minimal()
ggplotly(g_a3)
set.seed(7)
muestra <- sample(1:N, 12)
df_caminos <- do.call(rbind, lapply(muestra, function(kk) {
  data.frame(fecha = amort$fecha, cop_M = cop[kk, ] / M, camino = kk)
}))
df_cuota <- data.frame(fecha = amort$fecha, p5 = amort$cuota_usd * q[, "p5"] / M,
                        p50 = amort$cuota_usd * q[, "p50"] / M, p95 = amort$cuota_usd * q[, "p95"] / M)

g_a3_3 <- ggplot() +
  geom_line(data = df_caminos, aes(x = fecha, y = cop_M, group = camino), color = GRIS, alpha = 0.5, linewidth = 0.4) +
  geom_ribbon(data = df_cuota, aes(x = fecha, ymin = p5, ymax = p95), fill = AZUL, alpha = 0.15) +
  geom_line(data = df_cuota, aes(x = fecha, y = p50), color = AZUL, linewidth = 1.1) +
  geom_hline(yintercept = PMT * S0 / M, linetype = "dotted", color = NEGRO) +
  labs(title = "Gráfico A.3.2. Cada cuota en pesos: la misma deuda en dólares, un costo distinto por escenario",
       subtitle = "La cuota en dólares es fija (4,025.23 USD); en pesos depende de la TRM de cada fecha",
       x = NULL, y = "Millones de COP por cuota") +
  theme_minimal()
ggplotly(g_a3_3)
df_anual <- data.frame(ano = 1:10,
                        p5  = apply(anual, 2, quantile, 0.05) / M,
                        p50 = apply(anual, 2, quantile, 0.50) / M,
                        p95 = apply(anual, 2, quantile, 0.95) / M)
g_a3_4 <- ggplot(df_anual, aes(x = ano, y = p50)) +
  geom_errorbar(aes(ymin = p5, ymax = p95), width = 0.15, color = AZUL) +
  geom_point(color = AZUL, size = 2.5) +
  geom_hline(yintercept = 4 * PMT * S0 / M, linetype = "dotted", color = NEGRO) +
  scale_x_continuous(breaks = 1:10) +
  labs(title = "Gráfico A.3.3. Pago anual del crédito en pesos (flujo de caja)",
       subtitle = "Cuatro cuotas por año; la dispersión crece al inicio y luego se estabiliza",
       x = "Año del crédito", y = "Millones de COP") +
  theme_minimal()
ggplotly(g_a3_4)

Tabla A.3.3. Pago anual del crédito (mediana y rango p5-p95, millones de COP)

dt_tabla(df_anual, dec = 1, caption = "Pago anual del crédito")
refs <- data.frame(
  valor = c(sum(amort$cuota_usd) * S0, quantile(costo, 0.05), mean(costo), quantile(costo, 0.95), quantile(costo, 0.99)) / M,
  etiqueta = c("Base", "P5", "Media", "P95", "P99"),
  color = c(NEGRO, GRIS, AZUL, GRIS, ROJO)
)
g_a3_5 <- ggplot(data.frame(costo_M = costo / M), aes(x = costo_M)) +
  geom_histogram(bins = 60, fill = AZUL, alpha = 0.75, color = "white") +
  geom_vline(data = refs, aes(xintercept = valor, color = etiqueta), linetype = "dashed") +
  scale_color_manual(values = setNames(refs$color, refs$etiqueta)) +
  labs(title = "Gráfico A.3.4. Distribución del costo total del crédito en pesos",
       subtitle = paste0(format(N, big.mark = "."), " escenarios simulados"),
       x = "Costo total de las 40 cuotas (millones de COP)", y = "Escenarios", color = NULL) +
  theme_minimal()
ggplotly(g_a3_5)
desc_long <- as.data.frame(desc) %>%
  mutate(componente = rownames(desc)) %>%
  pivot_longer(-componente, names_to = "escenario", values_to = "valor") %>%
  mutate(valor = pmax(valor, 0),
         componente = factor(componente, levels = rownames(desc)),
         escenario = factor(escenario, levels = colnames(desc)))

g_a3_6 <- ggplot(desc_long, aes(x = escenario, y = valor, fill = componente)) +
  geom_col(width = 0.6, color = "white") +
  scale_fill_manual(values = c("Capital a TRM inicial" = "#c7d2e3", "Intereses a TRM inicial" = AZUL,
                                "Efecto cambiario s/ capital" = NARANJA, "Efecto cambiario s/ intereses" = "#f2b880")) +
  labs(title = "Gráfico A.3.5. Cuánto viene de los intereses y cuánto de la tasa de cambio",
       subtitle = "Los intereses son fijos (152.65 M); la diferencia entre escenarios es efecto cambiario",
       x = NULL, y = "Millones de COP", fill = NULL) +
  theme_minimal() + theme(legend.position = "bottom")
ggplotly(g_a3_6) %>% layout(legend = list(orientation = "h", y = -0.3))

Colas pesadas y evidencia de reversión a la media

z <- (r - mean(r)) / sd(r)
umbral <- c(1.5, 2.0, 2.5, 3.0)
p_real <- sapply(umbral, function(u) mean(abs(z) > u))
p_norm <- sapply(umbral, function(u) 2 * (1 - pnorm(u)))

p7a <- ggplot(data.frame(z = z), aes(x = z)) +
  geom_histogram(aes(y = after_stat(density)), bins = 20, fill = AZUL, alpha = 0.75, color = "white") +
  stat_function(fun = dnorm, color = ROJO, linewidth = 1) +
  labs(title = "A.3.6a. Histograma frente a una normal", x = "Rendimiento mensual (desv. estándar)", y = "Densidad") +
  theme_minimal()
ggplotly(p7a)
p7b <- ggplot(data.frame(teo = qnorm(ppoints(length(z))), real = sort(z)), aes(x = teo, y = real)) +
  geom_point(color = AZUL, size = 1.3) +
  geom_abline(slope = 1, intercept = 0, color = ROJO) +
  labs(title = "A.3.6b. Gráfico Q-Q", x = "Cuantil normal", y = "Cuantil de la TRM") +
  theme_minimal()
ggplotly(p7b)
df7c <- data.frame(umbral = rep(umbral, 2), pct = c(p_real, p_norm) * 100,
                    serie = rep(c("TRM real", "Normal"), each = length(umbral)))
p7c <- ggplot(df7c, aes(x = factor(umbral), y = pct, fill = serie)) +
  geom_col(position = position_dodge(0.7), width = 0.6) +
  scale_fill_manual(values = c("TRM real" = AZUL, "Normal" = ROJO)) +
  labs(title = "A.3.6c. Frecuencia de meses extremos", x = "Umbral (desv. estándar)", y = "% de los meses", fill = NULL) +
  theme_minimal()
ggplotly(p7c)
hs <- 1:60
df8a <- data.frame(h = hs, rv = sapply(hs, razon_var))
p8a <- ggplot(df8a, aes(x = h, y = rv)) +
  geom_line(color = AZUL, linewidth = 1.1) +
  geom_hline(yintercept = 1, color = ROJO, linetype = "dashed") +
  labs(title = "A.3.7a. Las subidas se compensan con bajadas", x = "Horizonte (meses)", y = "Razón de varianzas") +
  theme_minimal()
ggplotly(p8a)
p8b <- ggplot(data.frame(rango10 = rango10), aes(x = rango10)) +
  geom_histogram(bins = 50, fill = AZUL, alpha = 0.75, color = "white") +
  geom_vline(xintercept = rango_hist, color = ROJO, linetype = "dashed", linewidth = 1) +
  labs(title = "A.3.7b. Movimiento en 10 años en el modelo", x = "TRM más alta menos más baja (COP)", y = "Caminos") +
  theme_minimal()
ggplotly(p8b)
df8c <- rbind(
  data.frame(fecha = amort$fecha, p5 = apply(St, 2, quantile, 0.05), p50 = apply(St, 2, quantile, 0.50),
             p95 = apply(St, 2, quantile, 0.95), modelo = "Con reversión"),
  data.frame(fecha = amort$fecha, p5 = apply(St_pa, 2, quantile, 0.05), p50 = apply(St_pa, 2, quantile, 0.50),
             p95 = apply(St_pa, 2, quantile, 0.95), modelo = "Sin reversión")
)
p8c <- ggplot(df8c, aes(x = fecha, color = modelo, fill = modelo)) +
  geom_ribbon(aes(ymin = p5, ymax = p95), alpha = 0.12, color = NA) +
  geom_line(aes(y = p50), linewidth = 1) +
  geom_hline(yintercept = MAX_HIST, color = ROJO, linetype = "dotted") +
  scale_color_manual(values = c("Con reversión" = AZUL, "Sin reversión" = NARANJA)) +
  scale_fill_manual(values = c("Con reversión" = AZUL, "Sin reversión" = NARANJA)) +
  labs(title = "A.3.7c. Sin reversión la banda se dispara", x = NULL, y = "COP por USD", color = NULL, fill = NULL) +
  theme_minimal() + theme(legend.position = "bottom")
ggplotly(p8c) %>% layout(legend = list(orientation = "h", y = -0.3))
costo_pa <- as.numeric(St_pa %*% amort$cuota_usd)
cat(sprintf("Sin reversión: TRM año 10 p5 %s / mediana %s / p95 %s; costo media %.1f M, desv %.1f, p5 %.1f, p95 %.1f\n",
            miles(quantile(S_pa[, 121], 0.05)), miles(median(S_pa[, 121])), miles(quantile(S_pa[, 121], 0.95)),
            mean(costo_pa) / M, sd(costo_pa) / M, quantile(costo_pa, 0.05) / M, quantile(costo_pa, 0.95) / M))
## Sin reversión: TRM año 10 p5 1.999 / mediana 3.287 / p95 5.467; costo media 543.6 M, desv 99.3, p5 400.2, p95 720.7

Parte B. Diseño y evaluación de la cobertura forward

B.1. Cotización y valoración de los forwards

Cada uno de los cuatro forwards de la estrategia dura un año, así que cotizamos y valoramos un contrato a 12 meses, con fecha de valoración el 2 de septiembre de 2026 y año comercial de 252 días.

Dato Valor Fuente y fecha de consulta Forma de cotización
TRM 2/09/2026 3,184 COP/USD Banco de la República Pesos por dólar
Tasa en pesos 12% Banco de la República Efectiva anual
Tasa en dólares 4.18 % U.S. Treasury a 12 meses Rendimiento anual
Plazo 252/252 = 1 Año comercial de 252 días Días hábiles / 252
Forward observado en SET-FX 3,399.90 COP/USD Bloomberg Puntos forward / devaluación implícita

Forward teórico por paridad cubierta de tasas

Con spot en COP por USD la paridad es

F = S × \[(1 +tasa cop) / (1 + tasa usd)\]t/T

Esta es la versión discreta de la paridad cubierta de tasas; Hull la expresa en su forma continua como F₀ = S₀ · e ((r − r_f) T), donde r y r_f son las tasas compuestas continuamente, es decir Ln(1+r). Ambas formas parten de la misma lógica de no arbitraje si el forward no respetara este diferencial de tasas, se podría armar una operación sin riesgo que genere una ganancia.

Concepto Cálculo Resultado
Factor de paridad (1 + 12%) / (1 + 4.18%) 1.075062
Forward teórico a 12 meses (F) 3,184 × 1.075062 3,423 COP/USD
Puntos forward y prima anual F − S / (F − S) / S +239COP / 7.51 %
Verificación con Hull 3,184 × e((ln 1.12 − ln 1.0418) × 1) 3,423 COP/USD

La prima de 7.51 % refleja únicamente el diferencial de tasas entre pesos y dólares, compuesto durante el año, no es una predicción de hacia dónde va el dólar, sino el costo de financiarse en pesos en lugar de dólares.

Usamos un spread sobre las tasas porque así es como realmente se cotiza en la práctica, el banco no le da al cliente la tasa de mercado interbancaria, sino una peor, más alta en pesos y más baja en dólares. Al no tener el spread exacto que cobraría un banco local a un cliente, asumimos 50 pb sobre la tasa en pesos y 25 pb bajo la tasa en dólares como una aproximación razonable y conservadora, el spread real que observamos en el mercado interbancario NDF de Bloomberg es de 0.19 %, bastante más angosto que la banda de ±0.69 % que genera este supuesto.

Banda por spread y sensibilidad a las tasas

Posición del banco r COP r USD Forward
Venta de USD (la empresa compra) 12.50 % 3.93% 3,446.55
Punto medio 12% 4.18% 3,423
Compra de USD 11.5% 4.43% 3,399.56

La banda va de 3,399.56 a 3,446.55. 100 pb más en la tasa en pesos suben el forward aproximadamente 30 pesos; 100 pb más en la tasa en dólares lo bajan aproximadamente 33 pesos.

Comparación con SET-FX

Concepto Valor observado
Spot y forward 12m SET-FX Spot 3,146.90 / Forward 12m bid 3,396.63 – ask 3,403.17; Bloomberg
Diferencia vs. teórico −23.10 COP dentro de la banda 3,399.56–3,446.55

Si el observado cae dentro de la banda la diferencia es spread de negociación y el mercado es coherente con la paridad; fuera de ella las causas habituales son liquidez, riesgo de crédito, convenciones de mercado y desalineación entre tasas.

Lectura para la estrategia de cobertura

El forward teórico queda 97 pesos por encima del valor más probable del modelo A.3 a 12 meses, la cobertura solo paga si el peso se deprecia más de 7.5%. También queda por encima de la mediana de las proyecciones de bancos de A.1 y en el extremo bajo del rango, aunque esas proyecciones son a cierre de 2026 y el forward es a 12 meses. Durante 2026 el forward habría pronosticado aproximadamente 7.5% de devaluación mientras el peso se fortaleció aproximadamente 19%.

Este número solo sirve para un forward a 12 meses, con las tasas de hoy; no podemos simplemente ampliarlo para calcular los forwards de los años 7 a 10. Si la devaluación del 7.5 % se mantuviera igual durante siete años seguidos, el forward llegaría a cerca de 5,285 un nivel que en la práctica el mercado casi nunca cotiza, porque a plazos tan largos las tasas tienden a acercarse entre sí.

r_COP <- 0.12         # tasa de política del Banco de la República
r_USD <- 0.0418       # U.S. Treasury a 12 meses
t_T   <- 252 / 252    # año comercial de 252 días

FORWARD_SETFX <- 3399.90   # Bloomberg FRD, USD/COP NDF 1Y, 27-oct-2026

calc_forward <- function(rc, ru, S0_ = S0, t = t_T) S0_ * ((1 + rc) / (1 + ru))^t

factor_paridad_b1 <- (1 + r_COP) / (1 + r_USD)
F_teorico <- calc_forward(r_COP, r_USD)
puntos_forward <- F_teorico - S0
prima_anual <- puntos_forward / S0

F_hull <- S0 * exp((log(1 + r_COP) - log(1 + r_USD)) * t_T)

cat(sprintf("Factor de paridad             : %.6f\n", factor_paridad_b1))
## Factor de paridad             : 1.075062
cat(sprintf("Forward teórico a 12 meses (F) : %s COP/USD\n", miles(F_teorico, 2)))
## Forward teórico a 12 meses (F) : 3.423 COP/USD
cat(sprintf("Puntos forward                 : %+.2f COP\n", puntos_forward))
## Puntos forward                 : +239.00 COP
cat(sprintf("Prima anual                    : %.2f%%\n", prima_anual * 100))
## Prima anual                    : 7.51%
cat(sprintf("Verificación Hull (ec. 5.9)    : %s COP/USD\n", miles(F_hull, 2)))
## Verificación Hull (ec. 5.9)    : 3.423 COP/USD
stopifnot(abs(F_teorico - F_hull) < 1e-6)

spread_cop <- 0.0050; spread_usd <- 0.0025
F_venta  <- calc_forward(r_COP + spread_cop, r_USD - spread_usd)
F_compra <- calc_forward(r_COP - spread_cop, r_USD + spread_usd)

dentro <- F_compra <= FORWARD_SETFX & FORWARD_SETFX <= F_venta
cat(sprintf("Venta de USD (la empresa compra) : %s COP/USD\n", miles(F_venta, 2)))
## Venta de USD (la empresa compra) : 3.446,55 COP/USD
cat(sprintf("Compra de USD                    : %s COP/USD\n", miles(F_compra, 2)))
## Compra de USD                    : 3.399,56 COP/USD
cat(sprintf("Forward observado (Bloomberg FRD) : %s COP/USD, dentro de la banda %s-%s? %s\n",
            miles(FORWARD_SETFX, 2), miles(F_compra, 2), miles(F_venta, 2), dentro))
## Forward observado (Bloomberg FRD) : 3.399,9 COP/USD, dentro de la banda 3.399,56-3.446,55? TRUE

Tabla B.1. Forward teórico, banda por spread y comparación con el mercado

tabla_b1 <- data.frame(
  Concepto = c("Factor de paridad", "Forward teórico (F)", "Venta de USD (banda alta)",
               "Compra de USD (banda baja)", "Forward observado Bloomberg (SET-FX)", "Prima anual implícita"),
  Valor = c(round(factor_paridad_b1, 6), round(F_teorico, 2), round(F_venta, 2),
            round(F_compra, 2), FORWARD_SETFX, paste0(round(prima_anual*100, 2), " %"))
)
dt_tabla(tabla_b1, caption = "Forward teórico COP/USD")
r_cop_seq <- seq(0.09, 0.1501, by = 0.0025)
df_sens <- data.frame(r_cop = r_cop_seq, fwd = sapply(r_cop_seq, calc_forward, ru = r_USD))
g_b1 <- ggplot(df_sens, aes(x = r_cop * 100, y = fwd)) +
  geom_line(color = AZUL, linewidth = 1.3) +
  geom_point(color = AZUL, size = 1.8) +
  geom_vline(xintercept = r_COP * 100, color = NARANJA, linetype = "dashed") +
  labs(title = "Gráfico B.1. Forward teórico COP/USD vs. tasa en pesos (r_USD fija en 4.18 %)",
       x = "Tasa en pesos, r_COP (%)", y = "Forward teórico (COP/USD)") +
  theme_minimal()
ggplotly(g_b1)

B.2. Escenarios de protección y costo de oportunidad

Mecánica de la cobertura

Cada uno de los cuatro forwards se pacta al cierre de los años 6, 7, 8 y 9 del crédito, usando el spot simulado de A.3 en ese momento y el factor de paridad de B.1, vence un año después, es decir años 7, 8, 9 y 10. El nominal de cada forward es el 75 % de la cuota anual del crédito (16,100.93 USD), es decir 12,075.70 USD por año.

Forward pactado frente al spot al vencimiento

Forward (año) Forward pactado (mediana) Spot al vencimiento (mediana) Probabilidad de protección Rango del forward (p5–p95)
1 (año 7) 3,750.31 3,491.96 25.6% 3,011.69 – 4,592.62
2 (año 8) 3,754.08 3,505.49 26.1% 3,017.52 – 4,594.91
3 (año 9) 3,768.62 3,505.52 25.5% 3,015.04 – 4,603.32
4 (año 10) 3,768.66 3,505.13 25.3% 3,028.54 – 4,607.22

Los cuatro forwards dan resultados muy parecidos, como A.3 es un modelo de reversión a la media, para los años 6 a 10 el spot ya converge casi por completo a su nivel de largo plazo, así que el nivel en que se pacta cada forward apenas cambia de un año a otro.

Tres escenarios para el primer forward

Escenario Spot al pactar Forward pactado Resultado del forward
Apreciación del peso 3,488.46 3,750.31 −943,48 (costo de oportunidad)
Central (mediana) 3,488.46 3,750.31 −258,35 (costo de oportunidad)
Dólar se dispara 3,488.46 3,750.31 +523,78 (protección)

Una vez pactado el forward, ese precio ya no se mueve; lo que sí se mueve es el spot al que llegamos en el vencimiento. Y como ese spot tiende a quedarse cerca de su nivel de largo plazo, mientras que el forward ya trae incorporada la prima de 7.51 % anual de B.1, en la mayoría de los caminos el forward termina quedando más caro que el spot mediano. Solo cuando el dólar se dispara de verdad el forward resulta conveniente y sale más barato que haber comprado al spot.

Costo combinado del 75 % cubierto y el 25 % abierto

Escenario Media, M COP Desv. estándar, M COP
Sin cobertura, trayectorias de A.3 226.7 23.1
Con cobertura 75 % años 7-10, trayectorias de A.3 239.2 23.9
Sin cobertura, sensibilidad t-Student, 5 g.l. 234.7 26.4
Con cobertura 75 % años 7-10, sensibilidad t-Student 247.4 27.5

La cobertura sube el costo esperado, 12.5 M bajo el modelo principal y 12.7 M bajo la sensibilidad de colas pesadas, porque el forward incorpora la prima de paridad de B.1 y el spot simulado de A.3 revierte casi siempre a un nivel por debajo de esa prima. La desviación estándar casi no cambia con la cobertura, 23.1 frente a 23.9 M, porque el forward solo cubre uno de cada cuatro años relevantes y, dentro de esos años, solo el 75 % de cada cuota, la dispersión que domina el costo total viene de los primeros seis años, que nunca se cubren.

Probabilidades de protección, costo de oportunidad y fracaso de la cobertura

Tipo de escenario Trayectorias de A.3 Sensibilidad t-Student
Protección, spot mayor al forward 25.6 % 26.9 %
Costo de oportunidad, spot menor o igual al forward 74.4 % 73.1 %
Pérdida cambiaria extrema sin cobertura, depreciación mayor al 25 % en el año 1.2 % 2.9 %
Fracaso de la cobertura, costo cubierto mayor al forward más 5 % 0.4 % 1.5 %
Para referencia, ese mismo exceso sin cobertura 12.4 % 14.5 %

Pérdida del derivado frente a fracaso de la cobertura. El forward paga menos que el spot en cerca de tres de cada cuatro escenarios, 74.4 %, otra vez por el costo de la prima de B.1, el spot revierte a un nivel más bajo que el forward con mucha más frecuencia de la que lo supera. Pero el presupuesto solo se sale seriamente de control en apenas el 0.4 % de los caminos, frente al 12.4 % de exceso si no se hubiera cubierto nada, la cobertura casi siempre implica pagar la prima, pero cuando aparece una depreciación grande recorta el daño de forma marcada. Con la sensibilidad t-Student, tanto la pérdida extrema sin cobertura, 2.9 % frente a 1.2 %, como el fracaso de la cobertura, 1.5 % frente a 0.4 %, más que se duplican, aunque la probabilidad de protección cambia poco, 26.9 % frente a 25.6 %, el riesgo que el modelo de A.3 puede estar subestimando es el de eventos extremos, no el del escenario típico.

nu_t <- 5
set.seed(SEMILLA)
Z_t_raw <- matrix(rt(N * MESES, df = nu_t), nrow = N, ncol = MESES) * sd(e) * sqrt((nu_t - 2) / nu_t)

calibrar_t <- function(Z, kappa) {
  escala <- 1.0; nivel <- a_coef / (1 - PHI)
  for (it in 1:25) {
    s12 <- log(simular(Z, escala, nivel, kappa, 12)[, 13])
    p5  <- quantile(s12, 0.05); p50 <- quantile(s12, 0.50); p95 <- quantile(s12, 0.95)
    escala <- escala * (log(P95_A1 / P5_A1) / (p95 - p5))
    nivel  <- nivel + (log(MEDIANA_A1) - p50) / (1 - (1 - kappa)^12)
  }
  c(escala = unname(escala), nivel = unname(nivel))
}
cal_t <- calibrar_t(Z_t_raw, kappa)
S_t <- simular(Z_t_raw, cal_t["escala"], cal_t["nivel"], kappa)   # N x 121, sensibilidad t-Student

forwards_idx <- 1:4
meses_pactar <- 12 * (5 + forwards_idx)   # fin de los años 6,7,8,9 -> mes 72,84,96,108
meses_venc   <- 12 * (6 + forwards_idx)   # fin de los años 7,8,9,10 -> mes 84,96,108,120

calc_metrics_b2 <- function(S) {
  prot_all <- c(); dep_all <- c(); fail_hedge_all <- c(); fail_nohedge_all <- c()
  costo_sin <- numeric(nrow(S)); costo_con <- numeric(nrow(S))
  filas <- list()
  for (k in seq_along(forwards_idx)) {
    mp <- meses_pactar[k]; mv <- meses_venc[k]
    sp_pactar <- S[, mp + 1]; sp_venc <- S[, mv + 1]
    fwd <- sp_pactar * factor_paridad_b1
    prot <- sp_venc > fwd

    prot_all <- c(prot_all, prot)
    dep_all  <- c(dep_all, (sp_venc / sp_pactar - 1) > 0.25)
    fail_hedge_all   <- c(fail_hedge_all, sp_venc > 1.20 * fwd)
    fail_nohedge_all <- c(fail_nohedge_all, sp_venc > 1.05 * fwd)

    costo_sin <- costo_sin + cuota_anual * sp_venc
    costo_con <- costo_con + cuota_anual * (0.75 * fwd + 0.25 * sp_venc)

    filas[[k]] <- data.frame(Forward = forwards_idx[k], Anio = 6 + forwards_idx[k],
                              fwd_mediana = median(fwd), spot_mediana = median(sp_venc),
                              prot_pct = mean(prot) * 100,
                              fwd_p5 = quantile(fwd, 0.05), fwd_p95 = quantile(fwd, 0.95))
  }
  list(tabla = do.call(rbind, filas),
       prot_pct = mean(prot_all) * 100, dep_extrema_pct = mean(dep_all) * 100,
       fail_hedge_pct = mean(fail_hedge_all) * 100, fail_nohedge_pct = mean(fail_nohedge_all) * 100,
       costo_sin_mean = mean(costo_sin) / M, costo_sin_sd = sd(costo_sin) / M,
       costo_con_mean = mean(costo_con) / M, costo_con_sd = sd(costo_con) / M)
}

m_emp <- calc_metrics_b2(S)
m_t   <- calc_metrics_b2(S_t)

Tabla B.2.1. Forward pactado frente al spot al vencimiento (trayectorias de A.3)

dt_tabla(m_emp$tabla, dec = 2, caption = "Forward vs. spot al vencimiento")

Tabla B.2.2. Costo combinado del 75 % cubierto y el 25 % abierto (M COP)

costo_combinado <- data.frame(
  Escenario = c("Sin cobertura (trayectorias A.3)", "Con cobertura 75% años 7-10 (trayectorias A.3)",
                "Sin cobertura (sensibilidad t-Student)", "Con cobertura 75% años 7-10 (sensibilidad t-Student)"),
  Media_M_COP = c(m_emp$costo_sin_mean, m_emp$costo_con_mean, m_t$costo_sin_mean, m_t$costo_con_mean),
  Desv_M_COP  = c(m_emp$costo_sin_sd, m_emp$costo_con_sd, m_t$costo_sin_sd, m_t$costo_con_sd)
)
dt_tabla(costo_combinado, dec = 1, caption = "Costo combinado 75/25")

Tabla B.2.3. Probabilidades de protección, costo de oportunidad y fracaso de la cobertura

tabla_prob <- data.frame(
  Tipo = c("Protección (spot > forward)", "Costo de oportunidad (spot <= forward)",
           "Pérdida cambiaria extrema sin cobertura (depreciación > 25% en el año)",
           "Fracaso de la cobertura (costo cubierto > forward + 5%)",
           "Para referencia: ese mismo exceso sin cobertura"),
  Trayectorias_A3 = c(m_emp$prot_pct, 100 - m_emp$prot_pct, m_emp$dep_extrema_pct,
                       m_emp$fail_hedge_pct, m_emp$fail_nohedge_pct),
  Sensibilidad_tStudent = c(m_t$prot_pct, 100 - m_t$prot_pct, m_t$dep_extrema_pct,
                             m_t$fail_hedge_pct, m_t$fail_nohedge_pct)
)
dt_tabla(tabla_prob, dec = 1, caption = "Probabilidades de protección y fracaso")
df_b2 <- m_emp$tabla
df_b2$spot_p5  <- sapply(meses_venc, function(mv) quantile(S[, mv + 1], 0.05))
df_b2$spot_p95 <- sapply(meses_venc, function(mv) quantile(S[, mv + 1], 0.95))

g_b2 <- ggplot(df_b2, aes(x = Anio)) +
  geom_ribbon(aes(ymin = spot_p5, ymax = spot_p95), fill = VERDE, alpha = 0.2) +
  geom_line(aes(y = spot_mediana), color = VERDE, linewidth = 1.1) +
  geom_point(aes(y = spot_mediana), color = VERDE, size = 2) +
  geom_line(aes(y = fwd_mediana), color = AZUL, linewidth = 1, linetype = "dashed") +
  geom_point(aes(y = fwd_mediana), color = AZUL, size = 2, shape = 15) +
  labs(title = "Gráfico B.2. Forward pactado vs. rango simulado del spot (trayectorias de A.3), años 7 a 10",
       x = "Año del crédito", y = "COP/USD") +
  theme_minimal()
ggplotly(g_b2)

B.3. Flujo consolidado y evaluación financiera

Se inicia el 2 de septiembre de 2026, el día en que se compra la maquinaria, se pone la plata propia y se desembolsa el préstamo; ese mismo día el saldo neto queda en cero. De ahí en adelante, las 40 cuotas trimestrales en dólares se van pasando a pesos con el tipo de cambio simulado de cada trimestre durante los años 1 a 6. Ya en los años 7 a 10, donde entra la cobertura, cada cuota se paga 75% con el futuro pactado y el 25% restante al contado. Usamos la misma simulación de B.2, pero ahora trimestral en vez de anual, para tener una conversión al contado en cada una de las 40 cuotas; los cuatro futuros se siguen cotizando igual que en B.1, con la paridad aplicada sobre el tipo de cambio vigente al arrancar cada año cubierto.

Costo total en pesos del crédito, sin y con cobertura

Escenario Media Desv. estándar Percentil 5 Percentil 95
Sin cobertura 666M 140.5M 467.1M 920.9M
Con cobertura 75 % años 7–10 (normal) 675.7M 141.3M 475.4M 931.7M
Sin cobertura (t-Student) 666M 141.2M 467.4M 919.4M
Con cobertura 75 % años 7–10 (t-Student) 675.7M 142M 475.4M 930.3M

La cobertura sube el costo esperado en 1.46%, y casi no reduce la desviación estándar de todo el flujo. Esto pasa porque los primeros 24 trimestres quedan sin cobertura, y dentro de los años sí cubiertos, el 75% está atado a un futuro cuyo nivel igual depende de cómo se haya movido el tipo de cambio hasta ese momento, así que la cobertura no rompe la correlación entre el costo de esos años y el resto de la trayectoria. Sí reduce la dispersión dentro de cada año cubierto, pero todo el crédito sigue expuesto en sus primeros seis años, que es donde se concentra la mayor parte de la incertidumbre acumulada.

Tres escenarios representativos

Escenario Costo total sin cobertura Costo total con cobertura Spot final (año 10)
Favorable (peso fuerte, p5) 467.1M 471.5M 3,095.62
Central (mediana) 649.4M 675.5M 3,279.14
Adverso (depreciación, p95) 920.9M 942.4M 7,191.82

En el escenario central, cubrirse sale más caro que no hacerlo, porque el peso se deprecia menos del 7.5% anual que ya trae incorporado el futuro; la cobertura solo baja el costo total si la depreciación se mantiene por encima de ese umbral durante los años 7 a 10 de forma sostenida, y en este modelo esos casos quedan en la cola derecha de la distribución, no en el escenario central.

La cobertura cuesta en promedio 1.46% más en los tres niveles de confianza y tampoco baja mucho la volatilidad del flujo total porque solo cubre el 30% del crédito nominal. Donde sí se nota es en la cola, en el percentil 99 del costo cubierto, el exceso sobre el futuro pactado es de solo 6-7%, frente a 24-28% sin cobertura, la cobertura no cambia el nivel esperado del flujo, pero reduce el riesgo de un desembolso extremo en los años 7 a 10.

El flujo es volátil porque los años 1 a 6 quedan abiertos, y porque el 25% restante de los años 7 a 10 también sigue expuesto al tipo de cambio. El riesgo residual de la estrategia termina siendo la mayor parte, el 60% del crédito nunca se cubre, y del 40% restante solo se cubren el 75%, es decir, el nominal cubierto equivale al 30% de la obligación en dólares. Ese 75% aplica solo al tramo de los años 7 a 10, no a todo el crédito, así que el nominal cubierto nunca supera la obligación real.

Ese costo de oportunidad promedio es básicamente lo que pagas a cambio de tener protección en la cola, y no es otra cosa que la prima anual del futuro de B.1 aplicada sobre el nominal cubierto. Como ya vimos en B.1, 100 puntos básicos más en la tasa del peso o 100 menos en la del dólar mueven ese costo casi igual que el margen que cobra el banco, así que el resultado depende bastante de que asumamos que la tasa de política es lo mismo que el IBR a 12 meses.

valor_maquinaria <- 400000000
aporte_propio    <- 0.10 * valor_maquinaria
desembolso_cop   <- 0.90 * valor_maquinaria
desembolso_usd   <- desembolso_cop / S0
saldo_neto_t0    <- valor_maquinaria - aporte_propio - desembolso_cop

cat(sprintf("Compra de maquinaria   : %s COP\n", miles(valor_maquinaria)))
## Compra de maquinaria   : 400.000.000 COP
cat(sprintf("Aporte propio (10%%)    : %s COP\n", miles(aporte_propio)))
## Aporte propio (10%)    : 40.000.000 COP
cat(sprintf("Desembolso crédito 90%% : %s COP (%s USD)\n", miles(desembolso_cop), miles(desembolso_usd, 2)))
## Desembolso crédito 90% : 360.000.000 COP (113.065,3 USD)
cat(sprintf("Saldo neto en t=0      : %s COP\n", miles(saldo_neto_t0)))
## Saldo neto en t=0      : 0 COP
mediana_A3_12m <- 3326; p5_A3_12m <- 2795; p95_A3_12m <- 3953
mu_b2    <- log(mediana_A3_12m / S0)
z95      <- qnorm(0.95)
sigma_b2 <- mean(c(log(p95_A3_12m / mediana_A3_12m) / z95, log(p5_A3_12m / mediana_A3_12m) / (-z95)))

N_b3 <- 200000; TRIMESTRES <- 40; nu_b3 <- 5
mu_trim <- mu_b2 / 4; sigma_trim <- sigma_b2 / 2

sim_quarterly <- function(seed, dist) {
  set.seed(seed)
  Zq <- if (dist == "normal") matrix(rnorm(N_b3 * TRIMESTRES), N_b3, TRIMESTRES)
       else matrix(rt(N_b3 * TRIMESTRES, df = nu_b3), N_b3, TRIMESTRES) * sqrt((nu_b3 - 2) / nu_b3)
  logret <- mu_trim + sigma_trim * Zq
  S0 * exp(t(apply(logret, 1, cumsum)))
}
Sq_n <- sim_quarterly(123, "normal")
Sq_t <- sim_quarterly(123, "t")

costos_b3 <- function(Sq) {
  fwd1 <- Sq[, 24] * factor_paridad_b1; fwd2 <- Sq[, 28] * factor_paridad_b1
  fwd3 <- Sq[, 32] * factor_paridad_b1; fwd4 <- Sq[, 36] * factor_paridad_b1

  costo_sin <- PMT * rowSums(Sq)

  costo_con <- PMT * rowSums(Sq[, 1:24])
  costo_con <- costo_con + PMT * (4 * 0.75 * fwd1 + 0.25 * rowSums(Sq[, 25:28]))
  costo_con <- costo_con + PMT * (4 * 0.75 * fwd2 + 0.25 * rowSums(Sq[, 29:32]))
  costo_con <- costo_con + PMT * (4 * 0.75 * fwd3 + 0.25 * rowSums(Sq[, 33:36]))
  costo_con <- costo_con + PMT * (4 * 0.75 * fwd4 + 0.25 * rowSums(Sq[, 37:40]))
  list(costo_sin = costo_sin, costo_con = costo_con, spot_final = Sq[, 40])
}
res_n <- costos_b3(Sq_n); res_t <- costos_b3(Sq_t)

resumen_b3 <- function(costo) c(media = mean(costo) / M, sd = sd(costo) / M,
                                 p5 = quantile(costo, 0.05) / M, p95 = quantile(costo, 0.95) / M)

tabla_costo_b3 <- rbind(
  "Sin cobertura (normal)"                  = resumen_b3(res_n$costo_sin),
  "Con cobertura 75% años 7-10 (normal)"    = resumen_b3(res_n$costo_con),
  "Sin cobertura (t-Student)"                = resumen_b3(res_t$costo_sin),
  "Con cobertura 75% años 7-10 (t-Student)" = resumen_b3(res_t$costo_con)
)
dif_pct_b3 <- resumen_b3(res_n$costo_con)["media"] / resumen_b3(res_n$costo_sin)["media"] - 1
cat(sprintf("Sobrecosto esperado de la cobertura (normal): %+.2f%%\n", dif_pct_b3 * 100))
## Sobrecosto esperado de la cobertura (normal): +1.46%

Tabla B.3.1. Costo total en pesos del crédito, sin y con cobertura (M COP)

dt_tabla(as.data.frame(tabla_costo_b3), dec = 1, caption = "Costo total con y sin cobertura")
orden_b3 <- order(res_n$costo_sin)
idx_p5  <- orden_b3[round(0.05 * N_b3)]
idx_p50 <- orden_b3[round(0.50 * N_b3)]
idx_p95 <- orden_b3[round(0.95 * N_b3)]

tabla_esc_b3 <- data.frame(
  Escenario = c("Favorable (peso fuerte, p5)", "Central (mediana)", "Adverso (depreciación, p95)"),
  Costo_sin_M = c(res_n$costo_sin[idx_p5], res_n$costo_sin[idx_p50], res_n$costo_sin[idx_p95]) / M,
  Costo_con_M = c(res_n$costo_con[idx_p5], res_n$costo_con[idx_p50], res_n$costo_con[idx_p95]) / M,
  Spot_final  = c(res_n$spot_final[idx_p5], res_n$spot_final[idx_p50], res_n$spot_final[idx_p95])
)
nominal_cubierto_pct <- 0.75 * (16 / 40)
cat(sprintf("Nominal cubierto como %% de la obligación total: %.2f%%\n", nominal_cubierto_pct * 100))
## Nominal cubierto como % de la obligación total: 30.00%
cat(sprintf("Trimestres sin ningún tipo de cobertura (años 1-6): 24 de 40 (%.0f%%)\n", 24 / 40 * 100))
## Trimestres sin ningún tipo de cobertura (años 1-6): 24 de 40 (60%)

Tabla B.3.2. Tres escenarios representativos

dt_tabla(tabla_esc_b3, dec = 2, caption = "Tres escenarios representativos")
g_b3 <- ggplot(data.frame(costo_M = res_n$costo_sin / M), aes(x = costo_M)) +
  geom_histogram(bins = 70, fill = GRIS, alpha = 0.6, color = "white") +
  geom_histogram(data = data.frame(costo_M = res_n$costo_con / M), aes(x = costo_M),
                 bins = 70, fill = AZUL, alpha = 0.45, color = "white") +
  geom_vline(xintercept = mean(res_n$costo_sin)/M, color = GRIS, linetype = "dashed") +
  geom_vline(xintercept = mean(res_n$costo_con)/M, color = AZUL, linetype = "dashed") +
  labs(title = "Gráfico B.3. Costo total del crédito en pesos, sin cobertura (gris) vs. con cobertura (azul)",
       subtitle = "Modelo log-normal trimestral independiente, calibrado a A.1",
       x = "Costo total (millones de COP)", y = "Escenarios") +
  theme_minimal()
ggplotly(g_b3)

Parte 2. Aplicación de cobertura con futuros de índice bursátil

Punto 1. Acciones seleccionadas

Apple Inc. (AAPL), The Coca-Cola Company (KO) y Johnson & Johnson (JNJ), La elección de estas acciones no se basa en la popularidad de las marcas, sino en diversificación sectorial reduciendo así la correlación entre los activos y a su vez esto mejora la frontera eficiente, elegimos sectores como la tecnología, el consumo básico y salud que corresponden a ciclos económicos totalmente distintos, además de esto cabe recalcar que las tres empresas cotizan hace más de 10 años en el mercado, sin salidas a bolsas recientes ni cambio de ticker, adicionalmente son empresas de gran capitalización y con un alto volumen diario por lo que nos permite invertir 20 millones sin afectar el precio, tienen flujos de caja estables y décadas de dividendos crecientes como lo son coca cola y j&j.

empresa

Ticker

Sector

Precio (28-AGO)

BETAS

APPLE

AAPL

TECNOLOGIA

319,70

1.09

COCA COLA

KO

CONSUMO BASICO

89,66

0.34

J&J

JNJ

SALUD

268,04

0.23

APPLE

Apple es una empresa que diseña y vende dispositivos electrónicos de consumo como: iPhone, Mac, iPad, Apple Watch, AirPods y adicional tiene un ecosistema de servicios digitales como: App Store, iCloud, Apple Music, Apple Pay, AppleCare, publicidad y acuerdos de licencia. Pertenece al sector de Tecnología, subindustria de hardware y equipos de tecnología. Cuenta con una capitalización cercana a 5 billones de dólares y es una de las empresas de mayor peso en el S&P 500 por lo que su comportamiento está muy ligado al del índice.

FUENTES DE INGRESO

Referencia: Fuente: Apple, formulario 10-Q del trimestre terminado el 27-jun-2026.

Aproximadamente la mitad de los ingresos de Apple vienen del iPhone, por lo que esta parte puede variar más. En cambio, los Servicios tienen mejores márgenes y ya representan más de una cuarta parte de los ingresos, además de seguir creciendo. Esto hace que Apple tenga ingresos más estables y ayuda a explicar por qué la acción tiene una valoración alta.

Evolución del precio

Entre 2016 y 2025, la acción de Apple pasó de aproximadamente 29 a 271 dólares. Esto representa un crecimiento promedio de cerca del 28% anual. Sin embargo, no siempre la acción se mantuvo en crecimiento, también tuvo algunas caídas importantes, especialmente en 2018 QUE BAJO CERCA DE UN 7% y 2022 cuando bajó alrededor de un 27%. En 2026 la acción lleva una subida cercana al 18% y cerró en 319,70 dólares el 28 de agosto. El 31 de julio tuvo una caída fuerte de 7,4% en un solo día, después de presentar resultados en los que los ingresos por Servicios fueron menores a lo esperado. Durante agosto logró recuperar parte de esa caída, pasando de unos 303 a 320 dólares mientras el mercado esperaba el lanzamiento del iPhone 18 en septiembre.

Situación financiera

Para entender la situación financiera de Apple hay que tener en cuenta que la empresa tiene un año fiscal diferente al año calendario, el año fiscal de Apple empieza en septiembre del año anterior y termina en septiembre del año actual, no como las empresas convencionales que su año fiscal empieza en enero, sabiendo todo esto, Apple en los primeros nueve meses del año fiscal 2026 tuvo ingresos de 364.357 millones de dólares, lo que refleja una utilidad neta de 101.464 millones de dólares y generó 116.996 millones de dólares en flujo de caja operativo. Esto nos demuestra que la empresa sigue teniendo una fuerte capacidad para generar ingresos y efectivo. En el último trimestre, el margen bruto fue de 50,1%. Sin embargo, la empresa

Se espera que este margen baje a entre 47% y 48% en el trimestre de septiembre por el aumento en los costos de las memorias y del procesamiento necesario para la inteligencia artificial. Apple también mantiene una posición financiera sólida ya que cuenta con cerca de 147.000 millones de dólares entre efectivo e inversiones, frente a una deuda de aproximadamente 85.000 millones de dólares, Esto deja una caja neta cercana a USD 62.000 millones reflejándose que la empresa tiene más efectivo e inversiones que deuda. Por otro lado, Apple continúa repartiendo dinero a sus accionistas. La empresa anunció un nuevo programa de recompra de acciones por 100.000 millones de dólares y aumentó su dividendo trimestral a 0,27 dólares representando un aumento del 4%. Con estos resultados la acción tiene una valoración bastante alta ya que El PER histórico está alrededor de 37 a 39 veces mientras que el PER esperado se encuentra entre 33 a 35 veces. Mostrándonos unos niveles que están por encima del promedio que ha tenido Apple durante los últimos diez años.

Expectativa del precio a 12 meses

Después de analizar todo, consideramos que en el corto plazo la acción tiene un potencial de subida más limitado, porque su precio actual ya está bastante cerca del precio objetivo promedio de los analistas. Sin embargo, si se mira a un plazo de unos cuatro años, Apple todavía tiene buenas perspectivas, principalmente por el crecimiento de sus ingresos, sus márgenes altos y las recompras de acciones que está haciendo. Estas recompras también pueden ayudar a que la utilidad por acción siga aumentando.

Justificación de Inclusión en el portafolio

Apple es la empresa que más aporta a la rentabilidad del portafolio, ya que históricamente ha tenido el mayor retorno de las tres. Esto hace que la frontera eficiente del portafolio se desplace hacia arriba. Sin embargo, también tiene una mayor volatilidad y una beta más alta, lo que representa el riesgo sistemático que se busca cubrir con futuros del S & P 500. Además, como

Apple tiene una alta correlación con el índice, la cobertura puede ser más efectiva y tener un menor riesgo de base. Por su múltiplo elevado, se recomienda que su peso no sea demasiado alto dentro del portafolio, aunque esto se terminará definiendo con las restricciones del modelo media-varianza.

Coca-Cola

Coca Cola es la empresa de bebidas no alcohólicas más grande del mundo y cuenta con más de 200 marcas, entre ellas Coca Cola, Coca Cola Zero Sugar, Sprite, Fanta, Dasani, Powerade, Fairlife y Minute Maid. Sus productos se venden en más de 200 países. La empresa pertenece al sector de Consumo Básico específicamente al de bebidas donde la demanda suele mantenerse estable incluso cuando hay periodos de recesión.

Fuentes de ingreso

El modelo de negocio de Coca Cola se basa en tener pocos activos propios, La empresa vende concentrados y jarabes a una red de embotelladores independientes entre ellos Coca Cola FEMSA en Latinoamérica que se encargan de producir, distribuir y vender los productos. Gracias a este modelo, sus márgenes operativos superan el 30%. Los ingresos se distribuyen entre diferentes regiones como Norteamérica, Latinoamérica, Europa, Medio Oriente, África y Asia, además de las operaciones de embotellado propias y Global Ventures.

Fuente: Coca-Cola, comunicado de resultados del segundo trimestre de 2026 (28-jul-2026).

Evolución del precio

Entre 2016 y 2025 la acción pasó de aproximadamente 41 a 69 dólares lo que representa un crecimiento de cerca del 6% anual en el precio sin contar los dividendos. Durante este periodo tuvo caídas moderadas incluso entre 2020 y 2022 que entramos en pandemia, lo que nos demuestra que es una acción más defensiva. En 2026 ha tenido un desempeño bastante bueno, con una subida cercana al 29% y un cierre de 89,66 dólares el 28 de agosto. Además, llegó a 91,99 dólares el 24 de agosto, quedando por encima del S&P 500 y de sus competidores durante el mismo periodo. Este aumento se relaciona con el crecimiento en el volumen de ventas, el buen comportamiento de las bebidas sin azúcar y el impulso comercial que ha tenido la empresa por el Mundial FIFA 2026.

Situación Financiera

Para 2026 Coca Cola espera un crecimiento orgánico de los ingresos de aproximadamente 5% y un crecimiento de la UPA comparable de entre 9% y 10%. Además, se espera que el flujo de caja libre llegue a unos 12.400 millones de dólares durante el año, de los cuales ya llevaba 6.900 millones de dólares acumulados hasta junio. La empresa también tiene un dividendo trimestral de 0,53 dólares que equivale a 2,12 dólares al año y representa un rendimiento cercano al 2,4%. Además, lleva más de 60 años aumentando el dividendo de manera consecutiva. Entre los principales riesgos están el aumento en los costos de los insumos, la competencia de las marcas propias y las regulaciones relacionadas con el azúcar. También está el efecto de la tasa de cambio, ya que la mayoría de las ventas de Coca Cola se realizan fuera de Estados Unidos.

Expectativa del precio a 12 meses

Justificación de inclusión en el portafolio

Coca-Cola funciona como un estabilizador dentro del portafolio, ya que su beta baja y su poca relación con Apple ayudan a reducir la varianza total y el VaR. Además, tiene un dividendo que es relativamente predecible por lo que debe tenerse en cuenta al calcular el rendimiento y al hacer la valoración teórica del futuro. Se espera un retorno total moderado de aproximadamente 8% entre la valorización de la acción y el dividendo, lo cual es consistente con su nivel de riesgo más bajo. Sin embargo, después de que la acción subiera 29% en 2026, el precio de entrada resulta menos atractivo que en años anteriores.

Johnson & Johnson

Johnson & Johnson es una de las compañías de salud más grandes del mundo. Desde que separó su negocio de consumo Kenvue en 2023 la empresa se enfoca en dos segmentos principales: El primero es Medicina Innovadora que corresponde al negocio farmacéutico, y el segundo es MedTech que incluye dispositivos médicos para áreas como cirugía, ortopedia, cardiovascular y visión. La empresa pertenece al sector Salud, donde la demanda suele verse poco afectada por los cambios del ciclo económico.

Fuentes de ingreso

El crecimiento viene principalmente de oncología con productos como Darzalex (+17,6%), Carvykti (+47,7%), Tecvayli y Rybrevant, y de inmunología, donde Tremfya superó por primera vez los USD 2.000 millones en ventas trimestrales. Esto ayuda a compensar la caída de Stelara por la entrada de biosimilares, que redujo el crecimiento en cerca de 7,6 puntos porcentuales.

Evolución del precio

Entre 2016 y 2024 la acción tuvo un comportamiento más bien estable pasando de 115 a 145 dólares. Durante este periodo estuvo afectada por los problemas legales relacionados con el talco y por la incertidumbre alrededor de Stelara, sin embargo desde 2025 la situación cambió, la acción cerró ese año cerca de 204 dólares y en 2026 acumula una subida cercana al 32% Llegando a 273 dólares el 25 de agosto y cerró en 268,04 dólares el 28 de agosto, relacionando esta subida con que la empresa ha logrado compensar la pérdida de exclusividad de Stelara y con los buenos resultados de sus nuevos productos.

Situación Financiera

Para 2026, la empresa espera ventas de 101.100 millones de dólares lo que representa un crecimiento del 7,3%, y una UPA ajustada de 11,68 dólares que crecería un 8,2%. También se espera un flujo de caja libre cercano a 21.000 millones de dólares y la empresa tiene una deuda total de 49.000 millones de dólares frente a una caja de 20.400 millones de dólares. Además, es una de las pocas compañías que cuenta con una calificación crediticia AAA, cuenta con un dividendo trimestral es de 1,34 dólares, que equivale a 5,36 dólares al año y representa un rendimiento cercano al 2,0%. Johnson & Johnson lleva 64 años aumentando su dividendo de forma consecutiva y tiene un payout cercano al 48%, Por otro lado, su PER está alrededor de 18 a 23 veces, siendo este un nivel menor al de Apple.

El principal riesgo sigue siendo los litigios relacionados con el talco que todavía están abiertos. A esto se suman la presión sobre los precios de los medicamentos en Estados Unidos y los posibles efectos de los aranceles.

Expectativa a 12 meses

Justificación de inclusión

J&J aporta crecimiento defensivo al portafolio ya que tiene una beta baja, pero al mismo tiempo cuenta con nuevas oportunidades de crecimiento gracias a su negocio farmacéutico, Su correlación con Apple y Coca-Cola es baja porque sus ingresos dependen principalmente de la aprobación y el uso de medicamentos y no tanto del consumo o del ciclo tecnológico. Por eso ayuda a diversificar el portafolio y a que este dependa menos del comportamiento general del mercado. El riesgo relacionado con los litigios es propio de la empresa, no es un riesgo sistemático por lo que puede reducirse al combinar J&J con otras inversiones. Sin embargo, este riesgo no se cubre con el futuro del índice.

datos <- read_excel("datos.xlsx")
datos <- as.data.frame(datos)
datos$Date <- as.Date(datos$Date)

ret <- data.frame(
  Date  = datos$Date[-1],
  raapl = diff(log(datos$aapl)),
  rjnj  = diff(log(datos$jnj)),
  rko   = diff(log(datos$ko)),
  rgspc = diff(log(datos$gspc))
)

varp   <- function(x) mean((x - mean(x))^2)
covarp <- function(x, y) mean((x - mean(x)) * (y - mean(y)))
sdp    <- function(x) sqrt(varp(x))
dias <- 252

Tabla P2.0. Primeras y últimas observaciones de precios (AAPL, JNJ, KO, S&P 500 y futuro)

dt_tabla(rbind(head(datos, 3), tail(datos, 3)), dec = 2, caption = "Precios de cierre diarios")

Punto 2. Datos y frecuencia utilizada

Se trabajó con una frecuencia diaria, usando los precios de cierre de Apple, Johnson & Johnson y Coca-Cola desde el 30 de agosto de 2016 hasta el 28 de agosto de 2026. Esta última fecha corresponde al último día hábil antes de comenzar la inversión, que sería el 30 de agosto de 2026. En total se tienen 10 años de datos dentro del rango de 6 a 10 años solicitado con 2.513 precios y 2.512 retornos diarios para cada acción.

Se escogió la frecuencia diaria porque permite tener una mayor cantidad de datos y, por lo tanto, hacer una estimación más confiable de la volatilidad y las covarianzas. Además, esta frecuencia coincide con la forma en que se ajustan los futuros en la práctica mediante el mark-to-market. Además de esto los precios están ajustados por splits pero no incluyen dividendos por lo que los retornos calculados muestran únicamente la valorización del precio de cada acción.

Procedimiento

Para cada día se calculó el retorno usando los precios de cierre de cada acción:

r(t) = LN(P(t) / P(t−1))

Se utilizó este tipo de retorno porque permite sumar los retornos diarios para obtener el retorno de un periodo más largo. Esto facilita hacer los cálculos anuales a partir de los datos diarios.

Para pasar los datos diarios a valores anuales se tomaron 252 días bursátiles, que es la cantidad que normalmente se usa en el mercado estadounidense y también la que nos indicaron tomar. Con esto, el retorno anual promedio se obtiene multiplicando el promedio diario x 252. Para obtener el retorno anual efectivo se usa EXP(promedio diario × 252) − 1. De la misma forma, la varianza y la covarianza anual se calculan multiplicando las diarias por 252, mientras que la desviación estándar se multiplica por √252. La desviación estándar se multiplica por √252 y no por 252 porque la varianza es la que aumenta con el paso del tiempo. Al sacar la raíz cuadrada de la varianza se obtiene la desviación estándar. Por otro lado, la correlación no necesita anualizarse porque no tiene una unidad específica y no cambia por usar datos diarios o anuales. Para los cálculos se usaron las varianzas y covarianzas poblacionales (VARP y COVAR).

Resultados

Apple es claramente la acción con mayor retorno, con un 24,98% anual continuo y 28,38% efectivo, más de tres veces el retorno de las otras dos acciones. Sin embargo, también es la más riesgosa, con una desviación estándar anualizada de 29,13%. Esto significa que sus rendimientos han tenido cambios bastante fuertes y que el resultado de un año puede alejarse bastante de su promedio. Sus mayores movimientos en un solo día fueron de -13,8% el 16 de marzo de 2020, durante la crisis del COVID-19, y de +14,3% el 9 de abril de 2025.

Johnson & Johnson y Coca Cola tienen un comportamiento bastante parecido. Sus retornos anuales fueron de 8,11% y 7,32%, mientras que sus volatilidades fueron de 18,88% y 18,60%, respectivamente. Son acciones más estables y tienen cerca de dos tercios del riesgo de Apple, lo

que coincide con el carácter defensivo que se había planteado en el análisis fundamental. De todas formas, también han tenido días de caídas fuertes. J&J perdió 10,6% en un solo día el 14 de diciembre de 2018 por noticias relacionadas con el litigio del talco, mientras que Coca Cola cayó 10,2% el 12 de marzo de 2020.

Relación retorno/riesgo. Por cada punto de volatilidad asumido, Apple obtuvo 0,86 puntos de retorno, mientras que J&J obtuvo 0,43 y Coca Cola 0,39. Es decir, Apple tuvo un mayor retorno y también logró compensar mejor el riesgo que asumió.

Matriz de varianzas y covarianzas

La diagonal de la matriz muestra la varianza de cada acción. En el caso de Apple es de 0,0848, más del doble que la de J&J, que es 0,0356, y la de Coca Cola, que es 0,0346. Fuera de la diagonal todas las covarianzas son positivas lo que quiere decir que las tres acciones tienden a moverse en la misma dirección. Por ejemplo, cuando el mercado sube o baja las acciones también suelen moverse, aunque no exactamente en la misma proporción. Esta parte común representa el riesgo sistemático que no se puede eliminar completamente diversificando y es el que se busca cubrir con futuros sobre el S&P 500 y las covarianzas son relativamente pequeñas frente a las varianzas ya que están entre 0,016 y 0,018.

Matriz de Correlación

La correlación sirve para ver qué tanto se mueven dos acciones de manera parecida. Su valor va de −1 a 1, por lo que permite comparar fácilmente qué tan relacionadas están entre sí.

-Apple y JNJ (0,288) y Apple y Coca-Cola (0,327): tienen una correlación positiva pero baja, lo que significa que Apple se mueve de forma relativamente independiente de las otras dos acciones, por lo que combinarlas ayuda a reducir el riesgo del portafolio.

-JNJ y Coca-Cola (0,494): tienen una correlación moderada y es la más alta de las tres. Esto tiene sentido porque ambas son empresas defensivas y pueden reaccionar de manera parecida ante algunas noticias económicas.

-Ninguna correlación es negativa ni cercana a 1: esto significa que ninguna de las acciones funciona como una cobertura natural de otra, pero tampoco hay dos que se comportan casi igual. Por lo que podríamos decir que las tres aportan diversificación del portafolio.

R <- ret[, c("raapl", "rjnj", "rko")]
colnames(R) <- c("aapl", "jnj", "ko")

n_ret      <- sapply(R, length)
prom_diar  <- sapply(R, mean)
ret_anu_c  <- prom_diar * dias
ret_anu_ef <- exp(prom_diar * dias) - 1
var_diar   <- sapply(R, varp)
sd_diar    <- sqrt(var_diar)
var_anu    <- var_diar * dias
sd_anu     <- sd_diar * sqrt(dias)

stats <- rbind(
  "Número de retornos diarios"                                = n_ret,
  "Retorno diario promedio"                                   = prom_diar,
  "Retorno anual promedio (continuo)"                          = ret_anu_c,
  "Retorno anual efectivo"                                     = ret_anu_ef,
  "Varianza diaria"                                            = var_diar,
  "Desviación estándar diaria"                                 = sd_diar,
  "Varianza anual"                                              = var_anu,
  "Desviación estándar anualizada"                              = sd_anu
)

cov_diaria <- outer(1:3, 1:3, Vectorize(function(i, j) covarp(R[[i]], R[[j]])))
dimnames(cov_diaria) <- list(c("aapl", "jnj", "ko"), c("aapl", "jnj", "ko"))
cov_anual <- cov_diaria * dias
cor_mat <- cor(R)
dimnames(cor_mat) <- dimnames(cov_diaria)

Tabla P2.1. Estadísticas de retorno y riesgo por acción

dt_tabla(as.data.frame(stats), dec = 6, caption = "Estadísticas por acción")

Tabla P2.2. Matriz de varianzas y covarianzas (anualizada)

dt_tabla(as.data.frame(cov_anual), dec = 6, caption = "Covarianzas anualizadas")

Gráfico P2.1. Matriz de correlación entre AAPL, JNJ y KO

cor_long <- as.data.frame(as.table(cor_mat))
names(cor_long) <- c("accion1", "accion2", "correlacion")
g_cor <- ggplot(cor_long, aes(x = accion1, y = accion2, fill = correlacion,
                               text = paste0(accion1, " vs ", accion2, ": ", round(correlacion, 3)))) +
  geom_tile(color = "white") +
  geom_text(aes(label = round(correlacion, 3)), color = "white", fontface = "bold") +
  scale_fill_gradient(low = "#c7d2e3", high = AZUL) +
  labs(title = "Matriz de correlación", x = NULL, y = NULL, fill = "Correlación") +
  theme_minimal()
ggplotly(g_cor, tooltip = "text")

Punto 3. Enfoque de media-varianza (portafolio óptimo)

El modelo de media-varianza busca encontrar cómo repartir el capital entre las tres acciones para tener una buena relación entre el retorno esperado y el riesgo. Para esto utilizamos solver, cambiando los pesos de Apple, J&J y Coca Cola hasta encontrar la combinación que maximizara el ratio de sharpe. Además, establecimos dos restricciones:

-Los pesos deben sumar 100%, para invertir todo el capital.

-Cada acción debe tener un peso entre 10% y 40%.

Estas restricciones son necesarias porque si se deja al modelo sin ningún límite, este termina asignando el 100% a Apple, ya que históricamente es la acción que tiene la mejor relación entre retorno y riesgo, el problema es que eso haría que el portafolio quedara prácticamente concentrado en una sola acción, por eso el mínimo de 10% hace que las tres acciones tengan participación, mientras que el máximo de 40% evita que una sola termine teniendo demasiado peso.

Peso óptimo y monto invertido

Apple (40,00%): queda con el peso máximo permitido porque es la acción que tiene el mayor retorno por cada unidad de riesgo. De hecho, si el modelo no tuviera el límite del 40%, le asignaría un peso mayor.

J&J (37,63%): tiene un peso mayor que Coca Cola porque presenta un retorno un poco más alto de 8,44% frente a 7,59%, y además tiene una menor correlación con Apple que es de 0,288 frente a 0,327 de coca cola.

Coca Cola (22,37%): es la acción con menor retorno, pero aun así queda por encima del mínimo del 10%. Esto se debe principalmente a que su volatilidad es baja y ayuda a disminuir el riesgo total del portafolio.

En total, el 60% del portafolio queda invertido en J&J y Coca Cola ya que son las acciones más defensivas mientras que el 40% queda en Apple que tiene un mayor potencial de retorno, pero también más riesgo. Para calcular cuánto dinero se invierte en cada acción, se multiplica su peso por los USD 20.000.000 disponibles. Después el número de acciones se obtiene dividiendo ese monto entre el precio de cierre de cada acción del 28 de agosto de 2026.

Resultado del portafolio

El retorno esperado del portafolio es de 16,23% y se obtiene tomando los retornos de las tres acciones y teniendo en cuenta el peso de cada una. Si se aplica este porcentaje a los 20 millones de dólares invertidos, se tendría una ganancia esperada de aproximadamente 3,2 millones de dólares al año.

Desviación Estándar

La desviación estándar de 17,67% representa el riesgo anual del portafolio. Para una inversión de 20 millones de dólares esto equivale aproximadamente a USD 3,5 millones hacia arriba o hacia abajo. Hay dos cosas que vale la pena mirar. Primero, el riesgo del portafolio es menor que el de cualquiera de las tres acciones por separado, Segundo, también es menor que el promedio ponderado de las volatilidades individuales que sería de 22,92%.

Ratio de sharpe

El Sharpe Ratio se calcula como 16,23% − 4,445% / 17,67% y da un resultado de 0,667. Esto quiere decir que por cada punto de riesgo que se asume el portafolio genera 0,667 puntos de retorno por encima de la tasa libre de riesgo.

Para la tasa libre de riesgo se utilizó un valor de 4,445%, que corresponde al promedio entre la tasa de los bonos del Tesoro de Estados Unidos a 3 años que es de 4,41% y a 5 años que es de 4,48% al 28 de agosto de 2026. Se tomó este promedio porque no se cuenta con una tasa específica para un plazo de 4 años, que es el periodo planteado para la inversión.

inver_total <- 20000000           # Inver total (USD)

min_w <- c(aapl = 0.1, jnj = 0.1, ko = 0.1)
max_w <- c(aapl = 0.4, jnj = 0.4, ko = 0.4)
w     <- c(aapl = 0.4, jnj = 0.376333996568832, ko = 0.223666003431168)  # opt weight (Solver)

inver   <- w * inver_total
precio  <- unlist(tail(datos[, c("aapl", "jnj", "ko")], 1))
cartera <- inver / precio

rf_3y <- 0.0441; rf_5y <- 0.0448
rf    <- (rf_3y + rf_5y) / 2

ret_esp  <- sum(w * ret_anu_ef)
var_port <- as.numeric(t(w) %*% cov_anual %*% w)
sd_port  <- sqrt(var_port)
sharpe   <- (ret_esp - rf) / sd_port

Tabla P2.3. Pesos óptimos y monto invertido

p3 <- rbind(
  "Retorno anual efectivo"            = ret_anu_ef,
  "Desviación estándar anualizada"    = sd_anu,
  "Peso mínimo"                        = min_w,
  "Peso máximo"                        = max_w,
  "Peso óptimo (Solver)"               = w,
  "Inversión (USD)"                    = inver,
  "Precio de cierre 28/08/2026 (USD)"  = precio,
  "Cartera (número de acciones)"       = cartera
)
dt_tabla(as.data.frame(p3), dec = 4, caption = "Portafolio óptimo")

Tabla P2.4. Resumen del portafolio

resumen <- data.frame(
  Valor = c(ret_esp, var_port, sd_port, rf, sum(w), sharpe, sum(inver)),
  row.names = c("Retorno esperado", "Varianza del portafolio", "Desviación estándar",
                "Tasa libre de riesgo anual", "Peso total", "Sharpe Ratio",
                "Inversión total asignada (USD)")
)
dt_tabla(resumen, dec = 6, caption = "Resumen del portafolio")

Punto 4. Valor en riesgo del portafolio

El Valor en Riesgo nos permite estimar cuánto podría perder el portafolio en un periodo determinado teniendo en cuenta un nivel de confianza. En nuestro caso el cálculo se hizo sobre una inversión total de 20.000.000 de dólares tomando un horizonte de un mes y dos niveles de confianza: 95% y 99%. Esto corresponde al VaR al 5% y al VaR al 1%, respectivamente.

Para calcular el VaR se usaron los datos históricos del portafolio, se tomaron los precios de cierre de cada mes durante los últimos 10 años y con estos datos se calcularon los retornos mensuales de Apple, J&J y Coca Cola. Después se combinaron esos retornos teniendo en cuenta el peso de cada acción dentro del portafolio y se calculó cuánto se habría ganado o perdido cada mes sobre los 20 millones de dólares invertidos. Finalmente, se tomaron los peores resultados para calcular el VaR al 95% y al 99%.

Resultados

Con un nivel de confianza del 95%, se estima que el portafolio no debería perder más de 6,84% de su valor en un mes. Esto equivale a una pérdida de aproximadamente 1,37 millones de dólares sobre los 20 millones de dólares invertidos. En términos sencillos, en alrededor de 5 de cada 100 meses la pérdida podría ser mayor a este valor. Por eso, este resultado representa un escenario de pérdida fuerte, pero que podría presentarse con cierta frecuencia.

Con un nivel de confianza del 99% la pérdida estimada en un mes no debería superar el 11,13% que serían aproximadamente 2,23 millones de dólares. En este caso, solo en cerca de 1 de cada 100 meses la pérdida podría ser mayor. Por eso, este resultado representa un escenario mucho más extremo, similar a lo que podría pasar durante un mes de crisis.

El VaR muestra que en un mes el portafolio podría llegar a perder entre 1,37 y 2,23 millones de dólares. Por eso tiene sentido usar futuros sobre el S&P 500 para proteger parte de la inversión. Sin embargo, el valor que se busca cubrir no es directamente esa posible pérdida. La cobertura se calcula sobre los 20 millones de dólares del portafolio y se ajusta según la beta para definir cuántos contratos se necesitan.

Además, los futuros ayudan a proteger principalmente frente a los movimientos generales del mercado mas no cubren los problemas propios de cada empresa. Por eso, aunque la cobertura puede reducir la pérdida que podría tener el portafolio no significa que el riesgo desaparezca por completo.

mes <- format(datos$Date, "%Y-%m")
fin_mes <- datos[!duplicated(mes, fromLast = TRUE), c("Date", "aapl", "jnj", "ko")]
fin_mes <- fin_mes[fin_mes$Date >= as.Date("2016-08-31"), ]
rownames(fin_mes) <- NULL

fin_mes$raapl <- c(NA, diff(log(fin_mes$aapl)))
fin_mes$rjnj  <- c(NA, diff(log(fin_mes$jnj)))
fin_mes$rko   <- c(NA, diff(log(fin_mes$ko)))
fin_mes$PG    <- inver_total * as.vector(as.matrix(fin_mes[, c("raapl", "rjnj", "rko")]) %*% w)

pg <- na.omit(fin_mes$PG)
var95 <- quantile(pg, 1 - 0.95, type = 6, names = FALSE)
var99 <- quantile(pg, 1 - 0.99, type = 6, names = FALSE)

Tabla P2.5. VaR mensual del portafolio

tabla_var <- data.frame(
  USD = c(inver_total, length(pg), var95, var99),
  Pct_del_portafolio = c(NA, NA, var95 / inver_total, var99 / inver_total),
  row.names = c("Inversión total (USD)", "Número de retornos mensuales",
                "VaR (95%) total", "VaR (99%) total")
)
dt_tabla(tabla_var, dec = 4, caption = "VaR mensual del portafolio")

Gráfico P2.2. Distribución de los retornos mensuales del portafolio (P&G) con el VaR al 95 % y al 99 %

g_var <- ggplot(data.frame(pg = pg), aes(x = pg)) +
  geom_histogram(bins = 30, fill = AZUL, alpha = 0.75, color = "white") +
  geom_vline(xintercept = var95, color = NARANJA, linetype = "dashed", linewidth = 1) +
  geom_vline(xintercept = var99, color = ROJO, linetype = "dashed", linewidth = 1) +
  labs(title = "Distribución de la ganancia/pérdida mensual del portafolio",
       subtitle = "Líneas: VaR 95% (naranja) y VaR 99% (rojo)",
       x = "Ganancia / pérdida mensual (USD)", y = "Meses") +
  theme_minimal()
ggplotly(g_var)

Punto 5. Beta de las acciones y del portafolio

La beta sirve para medir qué tanto se mueve una acción cuando cambia el mercado. Para calcularla en Apple, Johnson & Johnson y Coca Cola tomamos como referencia el S&P 500 ya que las tres hacen parte de este índice. Después con las betas de cada empresa, se calculó la beta del portafolio teniendo en cuenta el peso que tiene cada acción.

Se usaron los precios de cierre diarios del S&P 500 desde el 30 de agosto de 2016 hasta el 28 de agosto de 2026 tomando las mismas fechas que para las acciones. A partir de estos precios se calcularon los retornos diarios usando la misma fórmula utilizada anteriormente, obteniendo 2.512 datos, Luego comparamos el comportamiento diario de cada acción con el del S&P 500 para obtener su beta por último la beta del portafolio se calculó combinando las betas de las tres acciones según los pesos definidos anteriormente.

Resultados

Apple es más sensible a los movimientos del mercado porque su beta es mayor a 1. si el S&P 500 sube o baja 1%, se espera que Apple se mueva aproximadamente 1,19% en la misma dirección. Por eso es una acción con más riesgo de mercado. Cuando el mercado sube puede subir más, pero cuando cae también puede tener una caída mayor. Su R² de 0,549 nos muestra que alrededor del 55% de los cambios en sus retornos están relacionados con los movimientos del mercado. J&J tiene un comportamiento más estable frente al mercado ya que si el S&P 500 se mueve 1%, se espera que J&J se mueva alrededor de 0,44%. Su R² de 0,175 indica que solo el 17,5% de los cambios en sus retornos se relacionan con el mercado y el resto está más relacionado con situaciones propias de la empresa, como sus resultados, medicamentos o litigios. Coca Cola también tiene un comportamiento más defensivo, su beta de 0,50 significa que normalmente se mueve cerca de la mitad de lo que se mueve el mercado. Además, su R² de 0,238 muestra que menos de una cuarta parte de sus movimientos se explican por el comportamiento del mercado.

Ahora bien, ya analizamos las betas individuales, la beta de portafolio nos dice que el portafolio es menos sensible que el mercado. Con una beta de 0,75, si el S&P 500 cae 1%, se esperaría que el portafolio caiga aproximadamente 0,75%. si el índice bajara 10% el portafolio podría caer cerca de 7,5% lo que representaría unos 1,5 millones de dólares sobre los 20 millones de dólares invertidos. Además de todo esto sabemos que Apple aporta la mayor parte de la beta, aportando 0,476, que representa cerca del 63% de la beta general. J&J aporta 0,164 y CocaCola 0,112 ayudando a reducir la beta.

La beta del portafolio también nos sirve para definir cuánto del riesgo de mercado se busca cubrir con los futuros, La beta sirve para saber qué parte del portafolio está expuesta a los movimientos del mercado. En este caso la beta es 0,752 y por eso la exposición al mercado es de unos 15,04 millones y no de los 20 millones completos. Además de esto los futuros sobre el S&P 500 ayudan a proteger esta parte del riesgo. Sin embargo, no cubren los problemas propios de cada empresa y por último, la cobertura también funciona mejor con Apple porque su comportamiento tiene una mayor relación con el S&P 500. En J&J y Coca Cola esta relación es menor y por eso sus movimientos pueden ser diferentes a los del índice.

rm_anual  <- exp(mean(ret$rgspc) * dias) - 1
sd_indice <- sdp(ret$rgspc) * sqrt(dias)
indice_fin <- tail(datos$gspc, 1)
futuro_fin <- tail(datos$f_gspc, 1)
base       <- futuro_fin - indice_fin
prima      <- rm_anual - rf

beta_slope <- sapply(R, function(x) coef(lm(x ~ ret$rgspc))[2])
names(beta_slope) <- names(R)
capm_ret  <- rf + beta_slope * prima
beta_cov  <- sapply(R, function(x) covarp(x, ret$rgspc) / varp(ret$rgspc))
correl    <- sapply(R, function(x) cor(x, ret$rgspc))
r2        <- correl^2

capm <- data.frame(
  Beta = beta_slope, CAPM = capm_ret, Beta_cov_var = beta_cov,
  Correlacion = correl, R2 = r2, Peso = w, Peso_x_Beta = w * beta_slope
)
beta_port <- sum(w * beta_slope)
capm["Beta Portafolio", ] <- c(beta_port, sum(w * capm_ret), NA, NA, NA, sum(w), sum(w * beta_slope))

Tabla P2.6. Índice S&P 500 y prima de riesgo de mercado

indice <- data.frame(
  Valor = c(length(ret$rgspc), rm_anual, sd_indice, indice_fin, futuro_fin, base, prima),
  row.names = c("Número de retornos diarios", "Retorno anual efectivo",
                "Desviación estándar anualizada", "Índice el 28/08/2026",
                "Futuro el 28/08/2026", "Base (futuro - índice)", "Prima de riesgo de mercado")
)
dt_tabla(indice, dec = 6, caption = "S&P 500")

Tabla P2.7. Betas, rendimiento CAPM y beta del portafolio

dt_tabla(capm, dec = 6, caption = "CAPM")

Gráfico P2.3. Beta de cada acción (línea de regresión del retorno diario contra el S&P 500)

df_reg <- data.frame(rgspc = ret$rgspc, aapl = R$aapl, jnj = R$jnj, ko = R$ko) %>%
  pivot_longer(c(aapl, jnj, ko), names_to = "accion", values_to = "retorno") %>%
  mutate(accion = toupper(accion))

g_beta <- ggplot(df_reg, aes(x = rgspc, y = retorno, color = accion)) +
  geom_point(alpha = 0.25, size = 0.8) +
  geom_smooth(method = "lm", se = FALSE, linewidth = 1.1) +
  facet_wrap(~accion, scales = "free_y") +
  scale_color_manual(values = c(AAPL = AZUL, JNJ = VERDE, KO = NARANJA)) +
  labs(title = "Retorno diario de cada acción vs. retorno diario del S&P 500",
       subtitle = "La pendiente de cada línea es la beta de la acción",
       x = "Retorno diario del S&P 500", y = "Retorno diario de la acción", color = NULL) +
  theme_minimal()
ggplotly(g_beta)

Punto 6. Número de contratos de futuros para la cobertura

Para cubrir el riesgo del portafolio se deben vender futuros sobre el S & P 500, como una beta de 0,752 y un portafolio de 20 millones de dólares se necesitan aproximadamente 39 contratos.

El cálculo inicial nos da 38,95 contratos, sin embargo, como no se pueden comprar o vender fracciones de contratos se debe escoger entre 38 y 39, se eligieron 39 contratos porque permiten cubrir casi todo el riesgo del mercado. Con esta cantidad se cubren cerca de 15,06 millones de dólares y queda una pequeña parte por encima de lo necesario.

La posición es corta porque el portafolio ya tiene las acciones y si el mercado cae las acciones pierden valor, pero los futuros generan una ganancia que ayuda a compensar esa pérdida. Si el mercado sube ocurre lo contrario: las acciones ganan y los futuros generan una pérdida.

Hay que tener en cuenta que esta cobertura no elimina todos los riesgos ya que los futuros protegen principalmente frente a las caídas generales del mercado, pero no frente a problemas propios de Apple J&J o Coca-Cola. Además, la beta puede cambiar con el tiempo y el precio de los futuros también cambia, por esto es que el número de contratos tendría que revisarse cuando se haga una nueva cobertura.

multiplicador <- 50

expo_contrato <- futuro_fin * multiplicador
monto_cubrir  <- beta_port * inver_total
N_opt         <- beta_port * (inver_total / (futuro_fin * multiplicador))
N_redondeado  <- round(N_opt, 0)

contratos  <- c(floor(N_opt), ceiling(N_opt))
distancia  <- contratos - N_opt
expo_cub   <- contratos * expo_contrato
dif_usd    <- expo_cub - monto_cubrir
dif_pct    <- dif_usd / monto_cubrir
beta_cub   <- expo_cub / inver_total
beta_resid <- beta_port - beta_cub
opcion <- ifelse(abs(distancia[2]) <= abs(distancia[1]), "Hacia arriba", "Hacia abajo")

Tabla P2.8. Cálculo del número óptimo de contratos

calculo <- data.frame(
  Valor = c(miles(expo_contrato), miles(monto_cubrir, 2), round(N_opt, 6), N_redondeado, "Corta (venta de futuros)"),
  row.names = c("Exposición por contrato (USD)", "Monto a cubrir (USD)",
                "N contratos óptimos (sin redondear)", "N contratos (redondeado)", "Posición")
)
dt_tabla(calculo, caption = "Número óptimo de contratos")

Tabla P2.9. Justificación del redondeo

redondeo <- data.frame(
  Redondeo_abajo = c(contratos[1], distancia[1], expo_cub[1], dif_usd[1], dif_pct[1], beta_cub[1], beta_resid[1]),
  Redondeo_arriba = c(contratos[2], distancia[2], expo_cub[2], dif_usd[2], dif_pct[2], beta_cub[2], beta_resid[2]),
  row.names = c("Número de contratos", "Distancia al óptimo", "Exposición cubierta (USD)",
                "Diferencia vs. monto a cubrir (USD)", "Diferencia %", "Beta cubierta", "Beta residual")
)
dt_tabla(redondeo, dec = 6, caption = "Redondeo")
cat("Opción elegida:", opcion, "-", N_redondeado, "contratos\n")
## Opción elegida: Hacia arriba - 39 contratos

Punto 7. Posición en futuros según el objetivo de cobertura

El administrador ya posee el portafolio accionario y quiere protegerse frente a una caída del mercado antes de vender o de que venza su horizonte de inversión. Ese es exactamente el caso de una cobertura en corto. El objetivo no es eliminar el riesgo por completo, sino reducirlo; cubrir implica también renunciar a parte de la ganancia si el mercado sube, no solo evitar la pérdida si baja.

Hay dos posiciones posibles en futuros según el objetivo de cobertura, un corto, que se usa cuando el inversionista ya posee el activo y teme una caída de precio antes de vender y cubre el riesgo de que el valor de las acciones baje; y un largo, que se usa cuando el inversionista planea comprar el activo o reingresar al mercado más adelante y teme que el precio suba antes de esa fecha, cubriendo el riesgo de que el costo de entrada suba.

La cobertura con futuros sobre índice cubre el riesgo sistemático de la cartera, no el riesgo específico de cada acción, que ya se diversifica al construir el portafolio con varios títulos.

Qué ocurre si el mercado sube o baja

Si el mercado accionario sube, el portafolio de acciones gana valor, pero la posición corta en futuros pierde un monto similar; el resultado neto es aproximadamente el costo de oportunidad de no haber capturado toda la subida, aunque la cartera no pierde dinero en términos absolutos.

Si el mercado accionario baja, el portafolio de acciones pierde valor, pero la posición corta en futuros gana un monto similar; esa ganancia compensa la pérdida en las acciones y estabiliza el valor total de la cartera cerca del nivel que tenía al abrir la cobertura.

En ambos casos, acciones más futuros terminan moviéndose más con la tasa libre de riesgo y el beta de la cartera, no uno a uno con el índice. Un ejemplo lo deja claro, con una cartera de USD 5,050,000, B = 1.5, futuro del S&P500 en 1,010, 1 un punto equivale a USD 250, si el índice cae 10% (futuro a 909), los 30 contratos cortos ganan USD 757,500, y eso deja la cartera prácticamente en lo que el CAPM esperaba, en vez de absorber toda la caída.

beta_p <- beta_port
V_A <- inver_total
precio_futuro_indice <- futuro_fin
V_F <- precio_futuro_indice * multiplicador

N_estrella <- beta_p * (V_A / V_F)
N_contratos <- round(N_estrella)

# Verificación con el ejemplo de clase (Hull sección 3.5)
beta_ej <- 1.5; V_A_ej <- 5050000; precio_futuro_ej <- 1010; multiplicador_ej <- 250
V_F_ej <- precio_futuro_ej * multiplicador_ej
N_ej <- beta_ej * (V_A_ej / V_F_ej)
N_ej_redondeado <- round(N_ej)

caida_indice <- -0.10
precio_futuro_nuevo <- precio_futuro_ej * (1 + caida_indice)
ganancia_total_corta <- (precio_futuro_ej - precio_futuro_nuevo) * multiplicador_ej * N_ej_redondeado
perdida_cartera <- V_A_ej * beta_ej * caida_indice

cat(sprintf("Verificación con el ejemplo de clase: N* = %.2f -> %d contratos\n", N_ej, N_ej_redondeado))
## Verificación con el ejemplo de clase: N* = 30.00 -> 30 contratos
cat(sprintf("Si el índice cae 10%%: ganancia en futuros %s, pérdida esperada en acciones %s, resultado neto %s\n",
            miles(ganancia_total_corta,2), miles(perdida_cartera,2), miles(perdida_cartera + ganancia_total_corta, 2)))
## Si el índice cae 10%: ganancia en futuros 757.500, pérdida esperada en acciones -757.500, resultado neto 0

Tabla P2.10. Sensibilidad de la cartera real cubierta ante movimientos del índice

escenarios_indice <- c(-0.10, -0.05, 0.0, 0.05, 0.10)
futuro_nuevo <- precio_futuro_indice * (1 + escenarios_indice)
ganancia_futuros <- (precio_futuro_indice - futuro_nuevo) * multiplicador * N_contratos
cambio_cartera_acciones <- V_A * beta_p * escenarios_indice
resultado_neto <- cambio_cartera_acciones + ganancia_futuros

tabla_p7 <- data.frame(
  Variacion_indice = sprintf("%+.0f%%", escenarios_indice * 100),
  Cambio_acciones = round(cambio_cartera_acciones, 0),
  GP_futuros = round(ganancia_futuros, 0),
  Resultado_neto = round(resultado_neto, 0)
)
dt_tabla(tabla_p7, caption = "Sensibilidad de la cartera cubierta")

Gráfico P2.4. Resultado neto de la cartera cubierta ante escenarios del índice

df_p7 <- tabla_p7 %>%
  pivot_longer(c(Cambio_acciones, GP_futuros, Resultado_neto), names_to = "serie", values_to = "valor")
g_p7 <- ggplot(df_p7, aes(x = Variacion_indice, y = valor, fill = serie)) +
  geom_col(position = position_dodge(0.7), width = 0.6) +
  scale_fill_manual(values = c(Cambio_acciones = GRIS, GP_futuros = NARANJA, Resultado_neto = AZUL),
                     labels = c("Cambio en acciones", "G/P en futuros", "Resultado neto")) +
  labs(title = "Sensibilidad de la cartera cubierta (39 contratos cortos)",
       x = "Variación del índice", y = "USD", fill = NULL) +
  theme_minimal()
ggplotly(g_p7)

Punto 8. Flujos de la cuenta de margen

Con los 39 contratos cortos del punto 6 evaluamos el primer trimestre de cobertura con liquidaciones mensuales.

Para el margen usamos el dato real de CME, el margen de mantenimiento de USD 23,164 por contrato. CME no publica directamente el margen inicial, lo fija el broker como un recargo sobre el de mantenimiento, así que mantenemos el supuesto propio de una relación de 1.10 entre ambos, margen inicial de USD 25,480.40 por contrato y margen de mantenimiento de USD 23,164 por contrato, es decir USD 993,735.60 y USD 903,396.00 para los 39 contratos.

Tabla 16. Flujos de la cuenta de margen en el primer trimestre

Mes Precio del futuro Variación (Δ puntos) G/P posición larga G/P posición corta (39 contratos) Saldo cuenta de margen antes del llamado
0 (apertura) 7,722.00 — — — 993,735.60
1 7,850.00 +128.00 +249,600.00 −249,600.00 744,135.60
2 7,690.00 −160.00 −312,000.00 +312,000.00 1,305,735.60
3 7,605.00 −85.00 −165,750.00 +165,750.00 1,471,485.60

G/P se calcula como cambio en puntos × 50 USD × 39 contratos, con signo contrario entre la posición larga y la corta.

Llamados al margen

Tabla 17. Llamados al margen

Mes Saldo antes del llamado Margen de mantenimiento total ¿Llamado al margen? Reposición para volver al margen inicial
1 744,135.60 903,396.00 Sí (saldo < mantenimiento) 249,600.00
2 1,305,735.60 903,396.00 No (saldo > mantenimiento) —
3 1,471,485.60 903,396.00 No —

En el mes 1 el índice sube y la posición corta pierde USD 249,600; como el saldo queda por debajo del margen de mantenimiento, se dispara un llamado al margen y toca reponer esos mismos USD 249,600 para volver al margen inicial de USD 993,735.60. En los meses 2 y 3 el índice baja, la posición corta gana y el saldo se va acumulando muy por encima del mantenimiento, así que no hay más llamados.

Cuando el mercado sube la posición corta pierde, pero eso lo compensa la ganancia en las acciones; cuando baja la posición corta gana y compensa la pérdida en acciones. Eso sí, la volatilidad del S&P500 trae consigo el riesgo de liquidez del llamado al margen, la empresa necesita tener el efectivo a mano para reponer, así la cobertura esté funcionando bien en magnitud.

N_contratos <- 39
precio_apertura <- futuro_fin

margen_mantenimiento_contrato <- 23164
margen_inicial_contrato <- margen_mantenimiento_contrato * 1.10
margen_inicial_total <- margen_inicial_contrato * N_contratos
margen_mantenimiento_total <- margen_mantenimiento_contrato * N_contratos

precios_mensuales <- c(7850.00, 7690.00, 7605.00)
meses <- 1:3

filas <- list()
precio_anterior <- precio_apertura
saldo <- margen_inicial_total
for (i in seq_along(meses)) {
  precio <- precios_mensuales[i]
  delta_puntos <- precio - precio_anterior
  gp_posicion_larga <- delta_puntos * multiplicador * N_contratos
  gp_posicion_corta <- -gp_posicion_larga
  saldo_antes_llamado <- saldo + gp_posicion_corta
  llamado <- saldo_antes_llamado < margen_mantenimiento_total
  if (llamado) {
    reposicion <- margen_inicial_total - saldo_antes_llamado
    saldo_despues <- margen_inicial_total
  } else {
    reposicion <- 0
    saldo_despues <- saldo_antes_llamado
  }
  filas[[i]] <- data.frame(mes = meses[i], precio_futuro = precio, delta_puntos = delta_puntos,
                            gp_posicion_corta = gp_posicion_corta, saldo_antes_llamado = saldo_antes_llamado,
                            margen_mantenimiento_total = margen_mantenimiento_total,
                            llamado_margen = llamado, reposicion = reposicion,
                            saldo_despues_llamado = saldo_despues)
  saldo <- saldo_despues
  precio_anterior <- precio
}
df_margen <- do.call(rbind, filas)

Tabla P2.11. Flujos de la cuenta de margen en el primer trimestre (posición corta, 39 contratos)

dt_tabla(df_margen, dec = 2, caption = "Cuenta de margen Q1")
cat(sprintf("Margen inicial total: %s | Margen de mantenimiento total: %s\n",
            miles(margen_inicial_total, 2), miles(margen_mantenimiento_total, 2)))
## Margen inicial total: 993.735,6 | Margen de mantenimiento total: 903.396

Gráfico P2.5. Evolución del saldo de la cuenta de margen en el primer trimestre

df_saldo <- rbind(
  data.frame(mes = 0, saldo = margen_inicial_total, tipo = "Después del llamado"),
  data.frame(mes = df_margen$mes, saldo = df_margen$saldo_antes_llamado, tipo = "Antes del llamado"),
  data.frame(mes = df_margen$mes, saldo = df_margen$saldo_despues_llamado, tipo = "Después del llamado")
) %>% arrange(mes, tipo)

g_margen <- ggplot(df_saldo, aes(x = mes, y = saldo)) +
  geom_hline(yintercept = margen_mantenimiento_total, color = ROJO, linetype = "dashed") +
  geom_hline(yintercept = margen_inicial_total, color = VERDE, linetype = "dotted") +
  geom_line(color = AZUL, linewidth = 1) +
  geom_point(aes(color = tipo), size = 2.5) +
  scale_color_manual(values = c("Antes del llamado" = NARANJA, "Después del llamado" = AZUL)) +
  scale_x_continuous(breaks = 0:3, labels = c("Apertura", "Mes 1", "Mes 2", "Mes 3")) +
  labs(title = "Saldo de la cuenta de margen vs. margen de mantenimiento (línea roja) e inicial (línea verde)",
       x = NULL, y = "USD", color = NULL) +
  theme_minimal()
ggplotly(g_margen)

Punto 9. Roll-over trimestral de la cobertura

Como el horizonte es de cuatro años y los futuros sobre índices vencen cada trimestre, la cobertura corta del punto 7 no se queda en un solo contrato, al cerrar cada trimestre, se liquida el contrato que está por vencer y se abre uno equivalente en el siguiente disponible. Esto es un roll over.

Tomemos el cierre del primer trimestre, se cierra la posición corta comprando los 39 contratos al precio actual y se abre una nueva posición corta vendiendo 39 contratos en el contrato del siguiente trimestre, a su propio precio inicial, que no tiene por qué coincidir con el precio de cierre del anterior, porque son instrumentos distintos, cada uno con su propia base.

Tabla 18. Roll-over al cierre del primer trimestre

Concepto Cálculo Resultado
G/P realizada al cerrar Q1 (corto) −(7,605 – 7,722) × 50 × 39 +228,150 USD
Base al cierre de Q1 (spot − futuro) 7,595 – 7,605 −10 pts
Apertura del contrato de Q2 (nuevo F₀) Dato de mercado al momento del roll over 7,620 pts
Base al abrir Q2 (spot − futuro nuevo) 7,595 – 7,620 −25 pts
Diferencia de roll (F₀ nuevo − F cierre anterior) 7,620 – 7,605 +15 pts → costo de 29,250 USD para el corto

La diferencia de roll over aparece porque el nuevo contrato casi nunca abre exactamente donde cerró el anterior, si abre más caro renovar el corto cuesta, ya que terminas vendiendo relativamente barato comparado con lo que valdría ese contrato si la base se comportara igual que antes. Si abriera más barato, el roll over sería favorable para el corto. Este costo o beneficio se va sumando trimestre a trimestre.

Efecto en los cuatro años

Con 16 roll overs en todo el horizonte, el resultado final ya no depende solo de para dónde se movió el índice cada trimestre, sino también de si esas renovaciones fueron en promedio favorables o costosas para el corto, cuando el futuro cotiza sistemáticamente por encima del spot renovar tiende a costar; si cotizara por debajo, sería al revés. Además, los 39 contratos óptimos del punto 6 no son fijos para siempre, hay que revisarlos en cada roll over porque el valor de la cartera y su beta van cambiando.

Riesgo de base

Ya existe dentro de un mismo trimestre, pero el roll over lo multiplica, en vez de un solo punto de incertidumbre al final, hay uno en cada renovación. Cada vez que se cierra y se abre, el precio que realmente quedó asegurado es F0 + base de cierre, y esa base cambia cada trimestre. Por eso la cobertura con roll over nunca fija un precio único para todo el horizonte, como sí lo haría un forward a cuatro años.

Por qué siempre corto

Mantenerse siempre corto es el diseño de la cobertura, protege al que ya tiene las acciones y se mantiene mientras siga en largo en acciones. Estar en largo en algún momento no sería cobertura sino especulación, duplicaría la exposición al mercado en vez de compensarla, ganando más si sube, pero perdiendo más si baja, y eso aumenta la volatilidad total en vez de reducirla.

F_apertura_Q1 <- 7722.00
F_cierre_Q1 <- 7605.00
spot_cierre_Q1 <- 7595.00
F_apertura_Q2 <- 7620.00

gp_realizada_Q1 <- -(F_cierre_Q1 - F_apertura_Q1) * multiplicador * N_contratos
base_cierre_Q1 <- spot_cierre_Q1 - F_cierre_Q1
base_apertura_Q2 <- spot_cierre_Q1 - F_apertura_Q2
diferencia_roll <- F_apertura_Q2 - F_cierre_Q1
costo_roll <- diferencia_roll * multiplicador * N_contratos

rollover <- function(F_apertura_actual, F_cierre_actual, F_apertura_siguiente, spot_cierre,
                     N = N_contratos, mult = multiplicador) {
  gp_realizada <- -(F_cierre_actual - F_apertura_actual) * mult * N
  base_cierre <- spot_cierre - F_cierre_actual
  base_apertura_nueva <- spot_cierre - F_apertura_siguiente
  diferencia_roll <- F_apertura_siguiente - F_cierre_actual
  costo_roll <- diferencia_roll * mult * N
  list(gp_realizada = gp_realizada, base_cierre = base_cierre, base_apertura_nueva = base_apertura_nueva,
       diferencia_roll = diferencia_roll, costo_roll = costo_roll)
}
resultado_Q1_a_Q2 <- rollover(F_apertura_Q1, F_cierre_Q1, F_apertura_Q2, spot_cierre_Q1)

Tabla P2.12. Roll-over al cierre del primer trimestre

tabla_roll <- data.frame(
  Concepto = c("G/P realizada al cerrar Q1 (corto)", "Base al cierre de Q1", "Apertura del contrato Q2",
               "Base al abrir Q2", "Diferencia de roll", "Costo/beneficio del roll para el corto"),
  Resultado = c(gp_realizada_Q1, base_cierre_Q1, F_apertura_Q2, base_apertura_Q2, diferencia_roll, costo_roll)
)
dt_tabla(tabla_roll, dec = 2, caption = "Roll-over Q1 a Q2")

Punto 10. Valor esperado de la cobertura trimestral

Usamos la misma tasa libre de riesgo del punto 6, 4.445% anual, el promedio entre el treasury a 3 años (4.41%) y a 5 años (4.48%) al 28 de agosto de 2026. Promediar esos dos plazos nos da una tasa consistente con el horizonte de la cobertura.

La idea del CAPM es sencilla, cubrir con futuros elimina el riesgo sistemático de la cartera, y una vez desaparece, el rendimiento esperado ya no depende de la prima de riesgo de mercado, sino que converge a la tasa libre de riesgo. La cartera sin cubrir, en cambio, sigue esperando el rendimiento completo del CAPM que calculamos en el punto 6.

Tabla 19. Valor esperado trimestral con y sin cobertura

Posición Tasa esperada anual Tasa esperada trimestral Valor esperado (USD 20,000,000)
Sin cobertura 16.23 % 3.83 % 20,766,321
Cubierta 4.445 % 1.09 % 20,218,639

La tasa trimestral se calcula como (1+r) ^(1/4) − 1, para mantener la misma convención de interés compuesto. La diferencia entre los dos valores esperados es de $547,682 al cierre del primer trimestre, o sea 2.74 puntos porcentuales aproximadamente 25% de la prima de riesgo de mercado anual que la cobertura elimina.

La cobertura reduce tanto el riesgo como el rendimiento esperado. Al vender los 39 contratos, se deja de recibir la prima de riesgo sistemático que paga el mercado por estar expuesto al índice y a cambio la cartera se comporta casi como un activo libre de riesgo sistemático, 16.23% anual sin cobertura vs. 4.445% cubierta, menos la parte de la volatilidad que venía justamente de ese beta.

La cobertura no elimina toda la volatilidad, sólo la sistemática, el riesgo propio de AAPL, JNJ y KO continúa existiendo, porque con solo tres acciones la cartera está lejos de ser diversificada. Por eso la cartera cubierta todavía tiene una desviación estándar positiva, aunque más baja, aun cuando el rendimiento esperado ya converge a la tasa libre de riesgo. Ese es el trade off de fondo de cualquier cobertura con futuros de índice, renuncias al rendimiento sistemático a cambio de estabilidad frente al mercado, pero el riesgo de haber escogido esas acciones específicas se queda.

r_CAPM_anual <- ret_esp
r_f_anual <- rf

r_CAPM_trimestral <- (1 + r_CAPM_anual)^(1 / 4) - 1
r_f_trimestral <- (1 + r_f_anual)^(1 / 4) - 1

VE_sin_cobertura_q <- inver_total * (1 + r_CAPM_trimestral)
VE_cubierta_q <- inver_total * (1 + r_f_trimestral)
diferencia_q <- VE_sin_cobertura_q - VE_cubierta_q

Tabla P2.13. Valor esperado trimestral con y sin cobertura

tabla_p10 <- data.frame(
  Posicion = c("Sin cobertura", "Cubierta"),
  Tasa_esperada_anual = c(r_CAPM_anual, r_f_anual),
  Tasa_esperada_trimestral = c(r_CAPM_trimestral, r_f_trimestral),
  Valor_esperado_USD = c(VE_sin_cobertura_q, VE_cubierta_q)
)
dt_tabla(tabla_p10, dec = 6, caption = "Valor esperado trimestral")
cat(sprintf("Diferencia en USD al cierre del primer trimestre: %s\n", miles(diferencia_q, 2)))
## Diferencia en USD al cierre del primer trimestre: 547.550,1

Punto 11. Rendimiento esperado mensual bajo tres enfoques

Tenemos tres formas de verlo. Sin cobertura, usando el CAPM del punto 6 el rendimiento esperado mensual queda en 1.26%, es decir un valor esperado de USD 20,252,245 sobre los 20 millones iniciales. Cubierto con futuros, como el rendimiento converge a la tasa libre de riesgo del punto 10, el mensual baja a 0.36%, con un valor esperado de USD 20,072,616. Tercer enfoque, ajustado por escenarios de VaR, le restamos al valor esperado sin cobertura el VaR mensual del punto 6 como margen de pérdida potencial.

El tercer enfoque no es un rendimiento como tal, sino un ajuste al valor esperado por el riesgo de cola ya calculado en el punto 6. Restando el VaR al valor esperado se obtiene una cifra conservadora, el nivel al que caería la cartera si, además de no cumplirse el escenario esperado, también se diera la pérdida extrema definida por cada nivel de confianza.

Tabla 20. Valor esperado ajustado por VaR

Escenario Cálculo Valor ajustado
Esperado, ajustado por VaR 95 % 20,252,245 – 1,368,191 18,884,054
Esperado, ajustado por VaR 99 % 20,252,245 – 2,226,968 18,025,277

Comparando con los otros dos enfoques, esto muestra el verdadero rango de incertidumbre de la cartera sin cubrir, el valor esperado tiene una cola de pérdida que, con 99% de confianza, dejaría la cartera casi USD 2 millones por debajo de los 20 millones en un mes. La cobertura con futuros no elimina esa cola, sólo la reduce, porque los futuros solo cubren el riesgo sistemático.

AAPL, JNJ y KO pagan dividendos, pero con rendimientos muy distintos: JNJ y KO son acciones maduras de alto dividendo (3–3.1% anual cada una), mientras AAPL paga poco en comparación con su precio (0.4–0.5% anual) por estar más orientada al crecimiento. Ponderando por los pesos del punto 6 la rentabilidad por dividendos de la cartera queda en 2.02% anual, cifra aproximada porque depende del dividendo vigente en la fecha de valoración.

El rendimiento total de una acción es la ganancia de capital más el dividendo, y como el 16.23% CAPM del punto 6 ya se calculó como rendimiento total los dividendos ya están ahí y no hay que sumarlos aparte. Lo que sí cambia es la composición, cerca de 2.02 puntos del 16.23% vienen como el dividendo, no como apreciación de precio, lo que reduce la volatilidad efectiva frente a una cartera sin dividendos.

Para la cobertura, los dividendos importan de otra forma, el futuro del índice se cotiza como F = S × e((r−q) T), con “q” siendo el dividendo del índice. Si el dividendo de nuestra cartera difiere del dividendo promedio del S&P 500, la cobertura no queda bien ni siquiera en la parte sistemática, hay un riesgo de base, pequeño comparado con el de los puntos 8 y 9, que viene de esa diferencia de dividendo y no del movimiento del índice.

r_CAPM_mensual <- (1 + r_CAPM_anual)^(1 / 12) - 1
r_f_mensual <- (1 + r_f_anual)^(1 / 12) - 1

VE_sin_cobertura_m <- inver_total * (1 + r_CAPM_mensual)
VE_cubierta_m <- inver_total * (1 + r_f_mensual)
VE_ajustado_VaR95 <- VE_sin_cobertura_m - abs(var95)
VE_ajustado_VaR99 <- VE_sin_cobertura_m - abs(var99)

pesos <- c(AAPL = 0.40, JNJ = 0.3763, KO = 0.2237)
dividend_yield <- c(AAPL = 0.0045, JNJ = 0.0305, KO = 0.0305)
dividend_yield_cartera <- sum(pesos * dividend_yield[names(pesos)])

Tabla P2.14. Rendimiento esperado mensual bajo tres enfoques

tabla_p11 <- data.frame(
  Enfoque = c("Sin cobertura (CAPM)", "Cubierta con futuros (converge a rf)",
              "Ajustado por VaR 95%", "Ajustado por VaR 99%"),
  Valor_esperado_USD = c(VE_sin_cobertura_m, VE_cubierta_m, VE_ajustado_VaR95, VE_ajustado_VaR99)
)
dt_tabla(tabla_p11, dec = 2, caption = "Tres enfoques del rendimiento mensual")
cat(sprintf("Dividend yield de la cartera (anual, ponderado): %.4f\n", dividend_yield_cartera))
## Dividend yield de la cartera (anual, ponderado): 0.0201

Punto 12. Sensibilidad de la cobertura a la beta del portafolio

Repetimos el cálculo del punto 6 pero ahora con dos betas hipotéticos, 0.5 y 2, y los comparamos con el beta real de la cartera

Tabla 21. Sensibilidad de la cobertura a la beta del portafolio

Beta N* Exposición sistemática Sensibilidad a 1 % del índice Nominal cubierto
0,5 (hipotético) 25.90 → 26 cortos 10,000,000 100,000 10,038,600
0,752 (real) 38.95 → 39 cortos 15,040,000 150,400 15,057,900
2,0 (hipotético) 103.60 → 104 cortos 40,000,000 400,000 40,154,400

Con B = 0.5 la cartera se mueve en promedio la mitad de lo que se mueve el índice, así que su exposición sistemática es de USD 10,000,000 y con solo 26 contratos cortos, 13 menos que con el B real. Un 1% de movimiento en el índice mueve la cartera apenas USD 100,000. Es una cobertura más suave porque hay menos riesgo sistemático que cubrir; tendría sentido para una cartera cargada a acciones defensivas o de bajo B.

Con B = 2 la cartera amplifica el movimiento del índice, su exposición sistemática es el doble del valor de la cartera, de ahí los 104 contratos cortos frente a los 39 reales. Un 1% de movimiento en el índice mueve la cartera USD 400 mil, cuatro veces más que en el caso de B = 0.5. Que el nominal cubierto sea mayor que la propia cartera es normal cuando B > 1, cubrir el riesgo sistemático pide una posición en futuros más grande que el activo mismo, porque la cartera reacciona más que uno a uno frente al mercado.

N* es proporcional a B porque te dice cuánto se mueve la cartera por cada unidad que se mueve el índice; para contrarrestar ese movimiento con una posición que también depende del índice, el tamaño de esa posición tiene que subir igual. Una cartera con B alto concentra más riesgo no diversificable y es justo ese riesgo, el que los futuros sobre índices pueden compensar. Así que duplicar o cuadruplicar B no cambia la lógica de la cobertura, solo su escala, se necesitan más contratos, el nominal cubierto crece en la misma proporción, y el costo y el riesgo de base de la posición también suben.

precio_futuro_p12 <- futuro_fin
V_F_p12 <- precio_futuro_p12 * multiplicador

betas_p12 <- c("0.5 (hipotético)" = 0.5, "0.752 (real, punto 6)" = beta_port, "2.0 (hipotético)" = 2.0)

filas_p12 <- list()
for (etiqueta in names(betas_p12)) {
  b <- betas_p12[[etiqueta]]
  N_est <- b * (inver_total / V_F_p12)
  N_c <- round(N_est)
  filas_p12[[etiqueta]] <- data.frame(
    Beta = b, N_estrella = N_est, N_contratos = N_c,
    Exposicion_sistematica = b * inver_total,
    Sensibilidad_1pct = b * inver_total * 0.01,
    Nominal_cubierto = N_c * V_F_p12
  )
}
tabla_p12 <- do.call(rbind, filas_p12)

Tabla P2.15. Sensibilidad de la cobertura a la beta del portafolio

dt_tabla(tabla_p12, dec = 2, caption = "Sensibilidad a la beta")

Gráfico P2.6. Número de contratos y nominal cubierto según la beta del portafolio

tabla_p12$etiqueta <- rownames(tabla_p12)
g_p12 <- ggplot(tabla_p12, aes(x = etiqueta, y = N_contratos, fill = etiqueta,
                                 text = paste0("N* = ", round(N_estrella, 2), " -> ", N_contratos, " contratos"))) +
  geom_col(width = 0.6) +
  scale_fill_manual(values = c(AZUL, VERDE, NARANJA)) +
  labs(title = "Número de contratos cortos necesarios según la beta del portafolio",
       x = NULL, y = "Contratos", fill = NULL) +
  theme_minimal() + theme(legend.position = "none")
ggplotly(g_p12, tooltip = "text")

Conclusiones generales

El trabajo aborda dos frentes distintos del riesgo que enfrenta una empresa colombiana con exposición al dólar: una deuda real en moneda extranjera (Parte 1, forwards de divisas sobre un crédito de maquinaria) y un portafolio accionario con exposición al mercado estadounidense (Parte 2, futuros sobre el índice S&P 500). En ambos casos la conclusión de fondo es la misma, cubrir con derivados no elimina el riesgo, lo transforma y tiene un costo. En la Parte 1, la cobertura con forwards para los años 7 a 10 del crédito sube el costo esperado en pesos en 1.46 % frente a no cubrir nada, porque el forward ya trae incorporada la prima de paridad de tasas de interés; a cambio, reduce de forma marcada el riesgo de cola en escenarios de depreciación extrema del peso. En la Parte 2, cubrir la beta de 0.752 del portafolio con 39 contratos cortos de futuros del S&P 500 hace que el rendimiento esperado converja de 16.23 % a la tasa libre de riesgo de 4.445 % anual, renunciando a la prima de riesgo sistemático a cambio de estabilidad frente al mercado, sin eliminar el riesgo propio de AAPL, JNJ y KO. En los dos casos el resultado depende de supuestos explícitos (el spread sobre las tasas en la Parte 1, el margen inicial como múltiplo del de mantenimiento en la Parte 2) que quedan documentados junto con su fuente para que el lector pueda evaluar su razonabilidad y, si lo considera necesario, recalcular los resultados con otros supuestos usando el mismo código.

Referencias (formato APA)

24/7 Wall St. (2026a, 8 de julio). Apple's $100 billion buyback machine keeps Wall Street watching.

https://247wallst.com/investing/2026/07/08/apples-100-billion-buyback-machine-keeps-wall-st reet-watching/

24/7 Wall St. (2026b, 4 de septiembre). Johnson & Johnson is boring, which makes its dividend nearly perfect.

https://247wallst.com/investing/2026/09/04/johnson-johnson-is-boring-which-makes-its-divide nd-nearly-perfect/

24/7 Wall St. (2026c, 14 de septiembre). Coca-Cola stock is up 29% in 2026: What will it take to break through $100? https://247wallst.com/investing/2026/09/14/coca-cola-stock-is-up-29-in-2026-what-will-it-take-to-break-through-100/

24/7 Wall St. (2026d, 25 de septiembre). Apple stock outlook: Our target leaves Wall Street behind.

https://247wallst.com/investing/2026/09/25/apple-price-prediction-our-target-sits-above-wall-streets/

Ad-hoc-news. (2026, 15 de septiembre). Coca-Cola stock gains on raised 2026 guidance and strong dividend signal. https://www.ad-hoc-news.de/boerse/news/corporate-news/coca-cola-stock-gains-on-raised-20 26-guidance-and-strong-dividend-signal/70105661

Apple Inc. (2026). Condensed consolidated financial statements: Fiscal year 2026, third quarter. https://www.apple.com/newsroom/pdfs/fy2026q3/FY26_Q3_Consolidated_Financial_Stateme nts.pdf

Johnson & Johnson. (2026, julio). Johnson & Johnson reports Q2 2026 results, raises 2026 outlook \[Comunicado de prensa\]. https://www.jnj.com/media-center/press-releases/johnson-johnson-reports-q2-2026-results-rai ses-2026-outlook

Slickcharts. (s.f.). S&P 500 companies by weight. Recuperado el 1 de octubre de 2026, de https://www.slickcharts.com/sp500

StockAnalysis. (s.f.-a). Apple (AAPL) stock price history. Recuperado el 2 de octubre de 2026, de https://stockanalysis.com/stocks/aapl/history/

StockAnalysis. (s.f.-b). Coca-Cola (KO) stock price history. Recuperado el 2 de octubre de 2026, de https://stockanalysis.com/stocks/ko/history/

StockAnalysis. (s.f.-c). Johnson & Johnson (JNJ) stock forecast & analyst price targets. Recuperado el 1 de octubre de 2026, de https://stockanalysis.com/stocks/jnj/forecast/

StockAnalysis. (s.f.-d). Johnson & Johnson (JNJ) stock price history. Recuperado el 2 de octubre de 2026, de https://stockanalysis.com/stocks/jnj/history/

The Coca-Cola Company. (2026, 28 de julio). Coca-Cola reports second quarter 2026 results and raises full year guidance \[Comunicado de prensa\]. Yahoo Finance. https://finance.yahoo.com/markets/stocks/articles/coca-cola-reports-second-quarter-10550073 8.html

TIKR. (s.f.). Johnson & Johnson stock: 2026 outlook after 50% gains. https://www.tikr.com/blog/johnson-johnson-stock-2026-outlook-after-50-gains

Yahoo Finance. (2026, 15 de julio). Apple is up 20% in 2026. What will it take for AAPL stock to hit $350?

https://finance.yahoo.com/markets/stocks/articles/apple-20-2026-aapl-stock-191629157.html