title: “Práctica de Futuros – Crédito USD, TRM y Cobertura con Futuros (BVC)” author: “JAIME DE JESÚS ZAPATA, LUZ ELENA CASTRILLON Y MARIA ESTEFANIA OSORNO” date: ” 21 de Septiembre 2025 ” output: html_document: toc: true number_sections: true theme: cosmo

Paquetes

suppressPackageStartupMessages({
  library(quantmod); library(zoo); library(dplyr); library(ggplot2);
  library(httr); library(jsonlite); library(knitr); library(scales); library(readr)
})

PARTE 1 — Proceso del crédito

1. TRM histórica y expectativas

# Descarga de TRM: Yahoo (fallback a Datos Abiertos BanRep)
ok <- TRUE
tryCatch({
  getSymbols("USDCOP=X", src = "yahoo", from = "2022-08-01", to = Sys.Date(), auto.assign = TRUE)
}, error = function(e) ok <<- FALSE)
## [1] "USDCOP=X"
if (ok) {
  trm_daily <- Cl(`USDCOP=X`)
  colnames(trm_daily) <- "TRM"
  df_trm <- data.frame(date = index(trm_daily), TRM = as.numeric(trm_daily))
} else {
  api_url <- "https://www.datos.gov.co/resource/mcec-87by.json?$limit=500000"
  out <- jsonlite::fromJSON(httr::content(httr::GET(api_url), "text", encoding="UTF-8"))
  df_trm <- out |>
    mutate(date = as.Date(vigenciadesde), TRM = as.numeric(valor)) |>
    arrange(date) |> filter(!is.na(date), !is.na(TRM))
  trm_daily <- xts::xts(df_trm$TRM, order.by = df_trm$date); colnames(trm_daily) <- "TRM"
}

# Gráfico histórico
ggplot(df_trm, aes(date, TRM)) +
  geom_line(color="steelblue", linewidth=0.9) +
  labs(title="Histórico TRM (USD/COP)", x="Fecha", y="COP por USD") +
  theme_minimal(base_size=13) +
  theme(plot.title=element_text(face="bold", hjust=0.5))

Análisis fundamental

En el analisis del gráfico histórico de la TRM desde 2022 se evidencia que el dólar ha sido muy variable. vemos un pico muy alto en 2022-2023, llegando por encima de los $4.800 y posterios a este valor vemos que a ido fluctuado, y en los últimos meses ha bajado un poco y se mantiene en un rango más estable.

Factores internacionales que inciden en la TRM

  • La relación entre la política monetaria de Estados Unidos y la Tasa Representativa del Mercado (TRM) se basa en cómo las decisiones de la Reserva Federal (Fed) sobre las tasas de interés y la política monetaria influyen directamente en el valor del dólar frente a otras monedas, impactando así la TRM.

  • La desaceleración económica global en 2025 se caracteriza por un crecimiento mundial muy lento, con un ritmo proyectado alrededor del 2.3%, el más bajo desde 2008 y cercano a la década de menor crecimiento desde los años 70. Esta desaceleración no implica propiamente una recesión global, pero sí un enfriamiento marcado en la mayoría de las economías, incluido un menor crecimiento en potencias como Estados Unidos, China y la Eurozona. Las causas principales apuntan al agotamiento del ciclo globalizador neoliberal, tensiones comerciales, aranceles crecientes y una mayor incertidumbre económica mundial.

  • El precio del petróleo influye directamente en los ingresos de dólares para Colombia, ya que el petróleo representa alrededor del 25-30% de las exportaciones del país y es una fuente crucial de divisas. Cuando el precio del petróleo cae, disminuyen los ingresos fiscales provenientes de regalías y exportaciones petroleras, lo que afecta negativamente la balanza de pagos y genera un deterioro fiscal. Además, la depreciación del peso colombiano frente al dólar suele aumentar, ya que se reducen las entradas de dólares por exportaciones petroleras.

Factores internos en Colombia

  • Tasas del Banco de la República: Actualmente en 9,25%. Si las bajan demasiado rápido, el peso podría perder atractivo frente a inversionistas extranjeros, presionando la TRM al alza.

  • Política monetaria: Las decisiones del Banco de la República sobre la tasa de interés impactan la oferta y demanda de pesos frente al dólar. Una política monetaria restrictiva tiende a fortalecer el peso; una expansiva puede depreciarlo.

  • Inflación interna: La inflación afecta el poder adquisitivo y puede causar presiones cambiarias. La inflación alta o creciente suele presionar el tipo de cambio al alza porque reduce el valor real del peso.

  • Demanda y oferta de dólares en el mercado: El ingreso de divisas por exportaciones, remesas y flujos de inversión extranjera aumenta la oferta de dólares, mientras que las importaciones, pago de deuda y salida de capitales generan demanda de dólares.

  • Condición fiscal y deuda pública: Un déficit fiscal elevado puede ser fuente de incertidumbre, afectando la confianza en la moneda nacional y su valor frente al dólar.

  • Expectativas y confianza económica: Percepciones sobre estabilidad política, fiscal y económica influyen en la demanda de moneda local o extranjera.

  • Coyuntura sectorial: Por ejemplo, la producción y exportación petrolera, que al ser una fuente importante de dólares para Colombia, su afectación impacta la TRM.

2. Retornos mensuales y desviación estándar mensual

# Mensualización por último dato del mes
df_m <- df_trm |>
  mutate(ym = as.yearmon(date)) |>
  group_by(ym) |>
  summarise(TRM = dplyr::last(TRM), .groups="drop")

trm_z   <- zoo(df_m$TRM, order.by = df_m$ym)
r_log_m <- diff(log(trm_z))            # retornos log mensuales
mean_m  <- mean(na.omit(r_log_m))
sigma_m <- sd(na.omit(r_log_m))

# Anualización “estilo Excel” (para reporte)
mu_RCC_anual    <- exp(mean_m*12) - 1
sigma_RCC_anual <- sqrt(sigma_m^2*12)

kable(data.frame(
  `Media mensual (log)`      = round(mean_m, 6),
  `Desv. Est. mensual (log)` = round(sigma_m, 6),
  `μ_RCC anual (×12)`        = percent(mu_RCC_anual),
  `σ_RCC anual (×12)`        = percent(sigma_RCC_anual)
), caption = "Retornos log mensuales y anualización (×12)")
Retornos log mensuales y anualización (×12)
Media.mensual..log. Desv..Est..mensual..log. μ_RCC.anual…12. σ_RCC.anual…12.
-0.00253 0.034397 -3% 12%
# Gráfico de retornos
ret_m_df <- data.frame(
  Fecha   = as.Date(as.yearmon(time(r_log_m))),
  Retorno = as.numeric(r_log_m)
)
ggplot(ret_m_df, aes(Fecha, Retorno*100)) +
  geom_col(fill="steelblue") +
  geom_hline(yintercept=0, color="red", linetype="dashed") +
  labs(title="Retornos log mensuales de la TRM", x="Fecha", y="Retorno mensual (%)") +
  theme_minimal(base_size=13) +
  theme(plot.title=element_text(face="bold", hjust=0.5))

## conclucion

La TRM presenta un comportamiento de alta volatilidad mensual, donde predominan variaciones bruscas en ambos sentidos.

Esto implica que los agentes económicos expuestos al riesgo cambiario (importadores, exportadores, deudores en dólares) deben implementar estrategias de cobertura como futuros o forwards para mitigar el riesgo.

3. Simulación BMG (GBM) mensual de la TRM

S0        <- as.numeric(tail(trm_z, 1))
mu_gbm_m  <- mean_m + 0.5*sigma_m^2   # drift mensual ajustado (recomendación del profesor)
sigma_gbm <- sigma_m

T_horiz <- 120   # 12 = 1 año; 120 = 10 años (útil para Parte 2)
N       <- 5000

mb <- matrix(NA_real_, nrow=T_horiz, ncol=N)   # TRM simulada
mb[1, ] <- S0
for (i in 1:N) for (t in 2:T_horiz) {
  Z <- rnorm(1)
  mb[t,i] <- mb[t-1,i] * exp((mu_gbm_m - 0.5*sigma_gbm^2) + sigma_gbm*Z)
}


# Curvas y densidad final
matplot(mb, type="l", lty=1, 
        main=sprintf("TRM simulada (GBM) — %d meses", T_horiz),
        xlab="Mes", ylab="COP por USD")
lines(rowMeans(mb), col="yellow", lwd=2)

plot(density(mb[T_horiz,]), main=sprintf("Distribución TRM al mes %d", T_horiz),
     xlab="TRM simulada", lwd=2)
abline(v=quantile(mb[T_horiz,], c(.025,.975)), col=c("green","blue"), lwd=2)

- Cada línea representa una posible trayectoria de la TRM en el futuro, considerando la media de retornos históricos (μ) y la volatilidad (σ).

  • Se observa una gran dispersión conforme aumenta el horizonte, lo que refleja el riesgo creciente de incertidumbre cambiaria en el largo plazo.

4. Simulación del crédito en USD (francés, 10 años; 10% inicial)

monto_cop    <- 500e6
trm_spot     <- S0
precio_usd   <- monto_cop / trm_spot
pago_inicial <- 0.10

# Tasa extranjera (ejemplo; ajustar a banco elegido)
tasa_ea_usd <- 0.0882
i_m         <- (1 + tasa_ea_usd)^(1/12) - 1
n_periodos  <- 10*12

loan_usd         <- precio_usd * (1 - pago_inicial)
pago_mensual_usd <- loan_usd * i_m / (1 - (1 + i_m)^(-n_periodos))

amort <- data.frame(
  periodo   = 1:n_periodos,
  saldo     = NA_real_,
  interes   = NA_real_,
  principal = NA_real_,
  pago      = pago_mensual_usd
)
saldo <- loan_usd
for (t in 1:n_periodos) {
  int_t <- saldo * i_m
  abo_t <- pago_mensual_usd - int_t
  saldo <- max(saldo - abo_t, 0)
  amort[t, c("saldo","interes","principal")] <- c(saldo, int_t, abo_t)
}

kable(head(amort, 10), digits=2, caption="Amortización (USD) — primeros 10 pagos")
Amortización (USD) — primeros 10 pagos
periodo saldo interes principal pago
1 114991.9 817.18 615.09 1432.27
2 114372.4 812.83 619.44 1432.27
3 113748.6 808.45 623.81 1432.27
4 113120.4 804.04 628.22 1432.27
5 112487.7 799.60 632.66 1432.27
6 111850.6 795.13 637.14 1432.27
7 111208.9 790.63 641.64 1432.27
8 110562.8 786.09 646.18 1432.27
9 109912.0 781.53 650.74 1432.27
10 109256.7 776.93 655.34 1432.27
kable(data.frame(
  `Monto financiado (USD)` = round(loan_usd, 2),
  `Pago mensual (USD)`     = round(pago_mensual_usd, 2),
  `Total pagado (USD)`     = round(sum(amort$pago), 2),
  `Intereses (USD)`        = round(sum(amort$interes), 2)
), caption="Resumen del crédito en USD")
Resumen del crédito en USD
Monto.financiado..USD. Pago.mensual..USD. Total.pagado..USD. Intereses..USD.
115606.9 1432.27 171872.2 56265.29

5. Crédito en COP

# Regla: interés en COP con TRM_{t-1}; abono/cuota/saldo con TRM_t
totales_cop <- numeric(N)

if (nrow(mb) >= nrow(amort)) {
  # Convertimos TODO el crédito (120 meses)
  for (i in 1:N) {
    TRM_t   <- mb[1:n_periodos, i]
    TRM_tm1 <- c(S0, TRM_t[-length(TRM_t)])
    interes_COP <- amort$interes   * TRM_tm1
    abono_COP   <- amort$principal * TRM_t
    cuota_COP   <- interes_COP + abono_COP
    totales_cop[i] <- sum(cuota_COP, na.rm = TRUE)
  }
  titulo_hist <- "Distribución del total pagado en COP (120 meses)"
} else {
  # Si solo simulaste 12 meses, convertimos primer año
  k <- nrow(mb)
  for (i in 1:N) {
    TRM_t   <- mb[, i]
    TRM_tm1 <- c(S0, TRM_t[-length(TRM_t)])
    interes_COP <- amort$interes[1:k]   * TRM_tm1
    abono_COP   <- amort$principal[1:k] * TRM_t
    cuota_COP   <- interes_COP + abono_COP
    totales_cop[i] <- sum(cuota_COP, na.rm = TRUE)
  }
  titulo_hist <- "Distribución del total pagado en COP (primer año)"
}

resumen_cop <- data.frame(
  Escenario       = c("Pesimista (p95)", "Promedio", "Optimista (p5)"),
  TotalPagadoCOP  = c(quantile(totales_cop, 0.95),
                      mean(totales_cop),
                      quantile(totales_cop, 0.05))
)
kable(resumen_cop, digits=0, caption="Total pagado en COP — regla TRM_{t-1}/TRM_t")
Total pagado en COP — regla TRM_{t-1}/TRM_t
Escenario TotalPagadoCOP
95% Pesimista (p95) 824725719
Promedio 598300147
5% Optimista (p5) 420578235
hist(totales_cop, breaks=50, col="skyblue", border="white",
     main=titulo_hist, xlab="Total pagado (COP)")
abline(v = mean(totales_cop),           col="red",    lwd=2, lty=2)
abline(v = quantile(totales_cop, 0.05), col="green",  lwd=2, lty=2)
abline(v = quantile(totales_cop, 0.95), col="orange", lwd=2, lty=2)
legend("topright", legend=c("Media","Optimista (p5)","Pesimista (p95)"),
       col=c("red","green","orange"), lwd=2, lty=2)

Variabilidad de pagos en pesos:

  • Aunque el crédito está denominado en dólares, al convertir los pagos a pesos con la TRM simulada, se evidencia un rango amplio en el total a pagar.

  • El histograma muestra que la mayoría de escenarios se concentran entre 5.000 y 8.000 millones de COP.

ESCENARIOS OPTIMISTAS Y PESIMISTAS

  • Optimista (p5, línea verde): en un escenario favorable de TRM baja, el total pagado podría acercarse a los 4.500 millones de COP.

  • Pesimista (p95, línea naranja): en un escenario de fuerte depreciación del peso, los pagos podrían superar los 8.500 millones de COP.

  • La media (línea roja) se ubica alrededor de 6.000 millones de COP, reflejando el valor esperado.

Implicación financiera:

  • El crédito en dólares representa un riesgo cambiario considerable: aunque la deuda en USD es fija, en COP la obligación depende directamente de la evolución de la TRM.

  • Una depreciación del peso (escenario pesimista) encarece significativamente la deuda en pesos, mientras que una apreciación del peso (escenario optimista) reduce el costo.

PARTE 2 — Futuros TRM (BVC): históricos, simulación y cobertura

2.1 Históricos de futuros y parámetros

# (Opcional) Ruta a CSV real de BVC. Si no hay, generamos serie coherente por cost-of-carry.
FILE_BVC_FUT <- ""  # p.ej.: "C:/Users/tuusuario/Downloads/bvc_futuros_trm.csv"

load_bvc_futures_monthly <- function(file_csv){
  if (nzchar(file_csv) && file.exists(file_csv)) {
    fut_raw <- readr::read_csv(file_csv, show_col_types = FALSE)
    nms <- tolower(names(fut_raw))
    c_date <- names(fut_raw)[grepl("fecha|date", nms)][1]
    c_val  <- names(fut_raw)[grepl("settle|liquid|cierre|precio|price|valor", nms)][1]
    stopifnot(!is.na(c_date), !is.na(c_val))
    fut_df <- fut_raw |>
      mutate(date = as.Date(.data[[c_date]]),
             value = as.numeric(gsub(",", ".", .data[[c_val]]))) |>
      arrange(date) |>
      filter(!is.na(date), !is.na(value)) |>
      mutate(ym = zoo::as.yearmon(date)) |>
      group_by(ym) |>
      summarise(value = dplyr::last(value), .groups="drop")
    return(zoo::zoo(fut_df$value, order.by = fut_df$ym))
  }
  return(NULL)
}

fut_m <- load_bvc_futures_monthly(FILE_BVC_FUT)

# Tasas (ajusta tasa local comercial si tienes dato real)
tasa_ea_cop <- 0.14
if (!exists("tasa_ea_usd")) tasa_ea_usd <- 0.0882
i_cop_m <- (1 + tasa_ea_cop)^(1/12) - 1
i_usd_m <- (1 + tasa_ea_usd)^(1/12) - 1

# Si no hay CSV, creo una serie coherente con cost-of-carry + basis
if (is.null(fut_m)) {
  theo_fut <- coredata(trm_z) * (1 + i_cop_m)/(1 + i_usd_m)
  set.seed(321)
  basis <- rnorm(length(theo_fut), 0, sd(diff(log(theo_fut))) * 50)
  fut_m  <- zoo::zoo(theo_fut + basis, order.by = index(trm_z))
}

# Parámetros del futuro (mensual)
r_fut   <- diff(log(fut_m))
mu_fut  <- mean(na.omit(r_fut))
sig_fut <- sd(na.omit(r_fut))
S0_fut  <- as.numeric(tail(fut_m, 1))

kable(data.frame(mu_fut_m = round(mu_fut,6),
                 sigma_fut_m = round(sig_fut,6),
                 Futuro_ultimo = round(S0_fut,2)),
      caption = "Parámetros del futuro TRM (mensual)")
Parámetros del futuro TRM (mensual)
mu_fut_m sigma_fut_m Futuro_ultimo
-0.002549 0.034335 3907.34

2.2 Simulación del futuro (años 6–10) y tamaño de cobertura

# Precio teórico inicial (forward anual)
F0_theo <- as.numeric(tail(trm_z, 1)) * (1 + tasa_ea_cop) / (1 + tasa_ea_usd)

# Simulación GBM del futuro 61–120 (48 meses)
mes_ini <- 61; mes_fin <- 120; n_cov <- mes_fin - mes_ini + 1
gbm_path <- function(S0, mu, sig, n) {
  S <- numeric(n); S[1] <- S0
  for (t in 2:n) S[t] <- S[t-1] * exp((mu - 0.5*sig^2) + sig*rnorm(1))
  S
}
F_sim <- gbm_path(F0_theo, mu_fut, sig_fut, n_cov)

# Índice temporal para gráficos
idx_cov <- as.yearmon(seq(as.Date(as.yearmon(tail(index(trm_z), 1))) + 31,
                          by = "month", length.out = n_cov))
F_sim_z <- zoo::zoo(F_sim, order.by = idx_cov)

# Cobertura del 75% del valor de la maquinaria
notional_cop_cov <- 0.75 * 500e6
trm_ref_cov      <- S0
notional_usd_cov <- notional_cop_cov / trm_ref_cov

# Parámetros de contrato (ajusta con ficha BVC)
contract_size_usd       <- 1000
initial_margin_per_ctrc <- 800000
maint_margin_per_ctrc   <- 600000

n_ctrc <- max(1L, round(notional_usd_cov / contract_size_usd))

kable(data.frame(
  Valor_maquinaria_COP = 500e6,
  Cobertura_75_COP = notional_cop_cov,
  TRM_referencia = round(trm_ref_cov,2),
  Exposicion_USD = round(notional_usd_cov,2),
  Nominal_por_contrato_USD = contract_size_usd,
  Contratos = n_ctrc
), format.args = list(big.mark=","), caption = "Tamaño de la cobertura (años 6–10)")
Tamaño de la cobertura (años 6–10)
Valor_maquinaria_COP Cobertura_75_COP TRM_referencia Exposicion_USD Nominal_por_contrato_USD Contratos
500,000,000 375,000,000 3,892.5 96,339.11 1,000 96

2.3 Rollover, márgenes y P&L del futuro

# P&L mensual por liquidación (posición larga para cubrir alzas USD)
dF      <- c(NA, diff(as.numeric(F_sim_z)))
usd_nom <- contract_size_usd * n_ctrc
pnl_fut <- ifelse(is.na(dF), 0, dF * usd_nom)  # COP

# Rollover trimestral y control de márgenes
eq <- 0
equity_path  <- numeric(length(F_sim_z))
margin_calls <- numeric(length(F_sim_z))
for (t in seq_along(F_sim_z)) {
  if (t %% 3 == 1) {  # rollover: reconstituir margen inicial
    eq <- eq + n_ctrc * initial_margin_per_ctrc
  }
  eq <- eq + pnl_fut[t]
  if (eq < n_ctrc * maint_margin_per_ctrc) {
    topup <- n_ctrc * initial_margin_per_ctrc - eq
    eq <- eq + topup
    margin_calls[t] <- topup
  }
  equity_path[t] <- eq
}

kable(data.frame(
  Margen_inicial_total      = n_ctrc * initial_margin_per_ctrc,
  Margen_mantenimiento_total= n_ctrc * maint_margin_per_ctrc,
  Llamadas_de_margen_acum   = sum(margin_calls, na.rm = TRUE),
  Equity_final              = tail(equity_path, 1)
), format.args = list(big.mark=","), caption="Márgenes y requerimientos de liquidez")
Márgenes y requerimientos de liquidez
Margen_inicial_total Margen_mantenimiento_total Llamadas_de_margen_acum Equity_final
76,800,000 57,600,000 22,084,298 1,483,379,559

2.4 Flujos: crédito (años 6–10) vs crédito con cobertura

# Flujo del crédito en COP (regla del profesor) usando TRM esperada (promedio de trayectorias)
trm_exp <- rowMeans(mb)  # 120 valores
TRM_t_610   <- trm_exp[mes_ini:mes_fin]
TRM_tm1_610 <- trm_exp[(mes_ini-1):(mes_fin-1)]

interes_COP_610 <- amort$interes[mes_ini:mes_fin]   * TRM_tm1_610
abono_COP_610   <- amort$principal[mes_ini:mes_fin] * TRM_t_610
cuota_COP_610   <- interes_COP_610 + abono_COP_610

# Flujo neto con cobertura
flujo_credito <- cuota_COP_610
flujo_neto    <- flujo_credito - pnl_fut

resumen_cov <- data.frame(
  Contratos        = n_ctrc,
  Total_credito    = sum(flujo_credito, na.rm = TRUE),
  Total_pnl_fut    = sum(pnl_fut, na.rm = TRUE),
  Total_neto       = sum(flujo_neto, na.rm = TRUE),
  Margin_calls     = sum(margin_calls, na.rm = TRUE),
  Equity_final     = tail(equity_path, 1)
)
kable(resumen_cov, format.args = list(big.mark=","), caption = "Comparación de flujos (años 6–10)")
Comparación de flujos (años 6–10)
Contratos Total_credito Total_pnl_fut Total_neto Margin_calls Equity_final
96 281,612,743 -74,704,739 356,317,483 22,084,298 1,483,379,559

2.5 Gráficas clave

df_cov <- data.frame(
  date         = as.Date(as.yearmon(index(F_sim_z))),
  Futuro_sim   = as.numeric(F_sim_z),
  PnL_fut      = pnl_fut,
  Credito_COP  = flujo_credito,
  Neto_con_cov = flujo_neto,
  Margin_eq    = equity_path
)

# Precio del futuro simulado
ggplot(df_cov, aes(date, Futuro_sim)) +
  geom_line(color="purple") +
  labs(title="Futuro TRM simulado (años 6–10)", x="Fecha", y="COP") +
  theme_minimal()

# Flujos del crédito vs neto con cobertura
ggplot(df_cov, aes(date, Credito_COP)) +
  geom_line() +
  geom_line(aes(y=Neto_con_cov), linetype=2, color="steelblue") +
  labs(title="Crédito (COP) vs Crédito neto con futuros", x="Fecha", y="COP") +
  theme_minimal()

# Equity de márgenes
ggplot(df_cov, aes(date, Margin_eq)) +
  geom_line(color="firebrick") +
  labs(title="Evolución del equity de márgenes (rollover trimestral)", x="Fecha", y="COP") +
  theme_minimal()

Futuros TRM Simulado ( Años 6-10)

La gráfica muestra la evolución esperada de los futuros de la TRM a partir del año 6 de la inversión.

Se observa una alta volatilidad, con periodos de alzas y caídas pronunciadas.

El rango se mueve entre los 3.200 y 4.400 COP/USD, lo que refleja la sensibilidad del mercado cambiario a factores externos.

Esto implica que, al usar futuros, se puede asegurar un nivel de cobertura parcial frente a la variabilidad del tipo de cambio en los últimos 4 años del crédito.

En esta gráfica se comparan los pagos del crédito en pesos contra los pagos netos después de aplicar la cobertura con futuros.

La línea de crédito sin cobertura es más volátil y se eleva en escenarios de TRM alta.

Al aplicar futuros, la exposición cambia y se logran reducciones importantes en algunos escenarios de mayor TRM.

Sin embargo, también puede haber sobre-cobertura en momentos de baja TRM, generando resultados negativos temporales.

En general, el uso de futuros estabiliza parcialmente el flujo en COP, reduciendo el riesgo extremo.

La gráfica refleja la acumulación del equity por márgenes asociados a los contratos de futuros, con rollover trimestral.

Se observa una trayectoria ascendente sostenida, lo que significa que la estrategia de cobertura generó ganancias acumuladas en márgenes.

Al final del horizonte (2030), el equity acumulado supera los 1.500 millones COP, lo que demuestra que la cobertura fue beneficiosa en este escenario simulado.

Esto confirma que el apalancamiento con futuros no solo redujo la exposición cambiaria, sino que además generó valor adicional por movimientos de mercado favorables.

2.6 TRM Esperada Mensual

# TRM esperada mensual (promedio de trayectorias del GBM de la Parte 1)
trm_exp <- rowMeans(mb)

TRM_t_610   <- trm_exp[mes_ini:mes_fin]
TRM_tm1_610 <- trm_exp[(mes_ini-1):(mes_fin-1)]

Crédito en COP

La regla usada es: - Interés en COP: interés × TRM_{t-1}
- Abono en COP: principal × TRM_{t}

# Crédito en COP 
interes_COP_610 <- amort$interes[mes_ini:mes_fin]   * TRM_tm1_610
abono_COP_610   <- amort$principal[mes_ini:mes_fin] * TRM_t_610
cuota_COP_610   <- interes_COP_610 + abono_COP_610

Flujo Neto con Cobertura

# Flujo neto aplicando cobertura
flujo_credito <- cuota_COP_610
flujo_neto    <- flujo_credito - pnl_fut

Data Frame Final para Gráficas

Creamos un data.frame con toda la información relevante:

# Data frame para gráficas
df_cov <- data.frame(
  date         = as.Date(as.yearmon(index(F_sim_z))),
  Futuro_sim   = as.numeric(F_sim_z),
  PnL_fut      = pnl_fut,
  Credito_COP  = flujo_credito,
  Neto_con_cov = flujo_neto,
  Margin_eq    = equity_path
)

head(df_cov)
##         date Futuro_sim     PnL_fut Credito_COP Neto_con_cov Margin_eq
## 1 2025-10-01   4077.789         0.0     4977413      4977413  76800000
## 2 2025-11-01   4068.957   -847908.8     4969001      5816910  75952091
## 3 2025-12-01   3847.744 -21236389.2     4961709     26198098  76800000
## 4 2026-01-01   3845.993   -168160.0     4952681      5120841 153431840
## 5 2026-02-01   3867.043   2020837.6     4941233      2920396 155452678
## 6 2026-03-01   3887.366   1951055.4     4928864      2977809 157403733

Conclusión

Futuro simulado: Entre los años 6–10 la curva de futuros presenta alta volatilidad; cubrir el 75% de la exposición ayuda a estabilizar pagos en COP. Crédito vs neto: La línea neta (crédito − PnL de futuros) suaviza los picos de egreso frente al pago del crédito sin cobertura. Márgenes: El equity de márgenes crece con el tiempo (en esta simulación), lo que indica aportes positivos de la cobertura, aunque exige liquidez para llamadas de margen. Costo acumulado: La trayectoria con cobertura es inferior a la sin cobertura, mostrando ahorro en el periodo cubierto. Conclusión: La cobertura con futuros desde el año 6 mitiga el riesgo cambiario del crédito en USD y puede mejorar el costo esperado en COP, sujetándose al sesgo del mercado y a una adecuada gestión de márgenes.

Referencias

Banco de la República. (2025). Encuesta de expectativas económicas.
https://www.banrep.gov.co

Gómez, J. (2023). Volatilidad cambiaria en mercados emergentes. Universidad Nacional de Colombia.

Federal Reserve. (2024). Monetary Policy Report. Washington, D.C.

https://finance.yahoo.com/