Laboratorio #1 Derivados Financieros

Yeidy Dian Cartagena Castrillón<br/>
Eliana Ibarra Quiróz<br/><br/>
Instituto Tecnológico Metropolitano (ITM)<br/>
Curso: Derivados Financieros<br/>
Profesor: David Esteban Rodríguez Guevara<br/>
Fecha: 24 de septiembre de 2025

Introducción

Para la adquisición de maquinaria amarilla por un valor de 300 millones de pesos colombianos (COP), equivalente a 75.912 dólares estadounidenses (USD) con una TRM de referencia de 3.951,92 COP/USD, se estructuró un financiamiento internacional a través de un crédito vehicular en el exterior. Tras comparar alternativas en el mercado estadounidense, se seleccionó U.S. Bank como referencia por sus tasas competitivas en préstamos vehiculares y en financiamiento de equipo, cercanas al 7 % anual (APR), sustancialmente menores a las tasas de crédito de consumo en Colombia (14–16 % anual) (Colombia, 2025a; U.S. Bank, 2025). En el trabajo se adopta una tasa efectiva anual de 7,96 % para reflejar condiciones actuales de mercado (U.S. Bank, 2025). El crédito en USD fija el costo financiero en esa moneda, pero expone los flujos en COP a la volatilidad de la TRM; por ello se propone una cobertura parcial (75 %) con futuros TRM listados en la BVC (Banco de la República, 2025b; Bolsa de Valores de Colombia, 2024).

1.Proceso de crédito

1.1 Análisis fundamental de la TRM y la expectativa de los precios hasta dentro de un año

Análisis fundamental de la TRM en Colombia

La Tasa Representativa del Mercado (TRM) corresponde al promedio ponderado de las operaciones de compra y venta de divisas realizadas en el mercado spot colombiano durante una jornada, y es calculada y certificada diariamente por la Superintendencia Financiera de Colombia ((Colombia, 2025b)) y el Banco de la República ((República, 2025b)). El Banco de la República consolida y publica la serie histórica oficial, la cual constituye la referencia cambiaria en análisis macrofinancieros y en la valoración de derivados.

En el transcurso de 2025, el peso colombiano (COP) registró un comportamiento apreciativo frente al dólar estadounidense. A cierre de diciembre de 2024, la TRM se ubicaba en aproximadamente COP 4.401,98/USD, mientras que al finalizar junio de 2025 descendió hasta cerca de COP 4.069,67/USD. Esto implica una apreciación del COP en el primer semestre.

Expectativa TRM 12 meses

La evolución de la Tasa Representativa del Mercado (TRM) en el horizonte de un año depende de factores externos: como la dinámica del precio del petróleo y las decisiones de la Reserva Federal, y factores internos: como la política monetaria del Banco de la República y la sostenibilidad fiscal de Colombia. En este contexto, distintos informes y encuestas de expectativas permiten proyectar un rango para el USD/COP durante 2025.

Escenarios:

• Base / más probable (~COP 4.300 – 4.500/USD). Estabilidad relativa con sesgo bajista leve. La inflación continúa moderándose y la tasa del Banco de la República (9,25%) se mantiene por encima de la de la Fed (4,75–5,00%), lo que preserva el atractivo de los activos en pesos. La Encuesta Mensual de Expectativas (EME) ubica la TRM esperada en torno a 4.300–4.400 ((República, 2025a); (Reserve, 2025)).

• Optimista (~COP 4.150 – 4.300/USD). Una apreciación del COP apoyada en petróleo estable por encima de US$70/barril, entrada de capital extranjero y manejo fiscal prudente. El Banco Mundial proyecta un precio promedio del Brent de US$68/barril en 2025, lo que respalda este escenario ((Bank, 2025)).

• Pesimista (~COP 4.500 – 4.800/USD). Una depreciación del COP por caída del petróleo por debajo de US$60/barril, mayor aversión al riesgo global o deterioro fiscal local. La EIA prevé precios del crudo en descenso hacia 2026 (~US$51/barril), lo que eleva el riesgo alcista en la TRM (((EIA), 2025)).

Proyecciones externas de la divisa.

Algunos portales financieros coinciden con estas estimaciones. TradersUnion proyecta una TRM de aproximadamente COP 4.041/USD hacia finales de 2025 ((TradersUnion, 2025)), mientras que EBC ubica el tipo de cambio en niveles cercanos a COP 4.350/USD bajo supuestos de presión fiscal y choques externos ((Economic & (EBC), 2025)). Estas cifras son consistentes con el rango central de 4.300–4.400 del escenario base, reforzando la expectativa de relativa estabilidad con riesgos sesgados hacia la depreciación

1.2 Calculo de los retornos mensuales y la desviación estándar mensual de la TRM histórica

knitr::opts_chunk$set(echo = FALSE, dev = "png")
knitr::opts_chunk$set(echo = TRUE, message = FALSE, warning = FALSE)
set.seed(1234)

options(OutDec = ",")

# Librerías
library(readr); library(readxl); library(dplyr); library(tidyr); library(knitr)

# Helpers de formato
fmt    <- function(x, dig=2) format(round(x, dig), big.mark=".", decimal.mark=",")
fmt0   <- function(x) format(round(x, 0), big.mark=".", decimal.mark=",", trim=TRUE)
fmt_kb <- function(v, dig=2) formatC(v, big.mark=".", decimal.mark=",", digits=dig, format="f")

ruta_trm     <- if (exists("params")) params[["ruta_trm"]]     %||% ""
ruta_futuros <- if (exists("params")) params[["ruta_futuros"]] %||% ""

leer_trm <- function(path){
  stopifnot(file.exists(path))
  ext <- tolower(tools::file_ext(path))
  if (ext %in% c("xlsx","xls")) {
    df <- readxl::read_excel(path, sheet = 1, col_names = TRUE)
  } else {
    df <- tryCatch(
      readr::read_csv2(path, show_col_types = FALSE, locale = readr::locale(decimal_mark=",")),
      error = function(e) readr::read_csv(path, show_col_types = FALSE)
    )
  }
  nms <- tolower(names(df))
  i_fecha <- which(nms %in% c("fecha","date","periodo","vigenciadesde","vigenciaini","vigenciad"))[1]
  i_valor <- which(nms %in% c("valor","trm","tasa","tasarepresentativadelmercado","valortrm","valor_de_la_tasa"))[1]
  stopifnot(!is.na(i_fecha), !is.na(i_valor))

  # FECHA
  fecha <- df[[i_fecha]]
  if (!inherits(fecha,"Date")) {
    tmp <- suppressWarnings(as.Date(fecha))
    if (all(is.na(tmp))) {
      for(fmt in c("%Y-%m-%d","%d/%m/%Y","%m/%d/%Y","%d-%m-%Y","%m-%d-%Y")){
        tmp <- as.Date(as.character(fecha), format=fmt)
        if(any(!is.na(tmp))) break
      }
    }
    fecha <- tmp
  }

  
  val_raw <- as.character(df[[i_valor]])
  val_raw <- gsub("\\s|\\$|COP|USD", "", val_raw, ignore.case = TRUE)
  val_raw <- gsub("\\.", "", val_raw)          # quita miles con punto
  val_norm <- gsub(",", ".", val_raw, fixed=TRUE)
  valor <- suppressWarnings(as.numeric(val_norm))

  med <- suppressWarnings(median(valor, na.rm=TRUE))
  if (is.finite(med) && med > 10000 && med < 1e6) valor <- valor/100
  if (is.finite(med) && med >= 1e6)               valor <- valor/1000

  tibble::tibble(fecha=fecha, valor=valor) |>
    filter(!is.na(fecha), is.finite(valor)) |>
    arrange(fecha)}
suppressPackageStartupMessages({
  library(readr); library(readxl); library(dplyr); library(tibble)
})

if (!exists("fmt", mode="function")) {
  fmt    <- function(x, dig=2) format(round(x, dig), big.mark=".", decimal.mark=",")
  fmt0   <- function(x) format(round(x, 0), big.mark=".", decimal.mark=",", trim=TRUE)
  fmt_kb <- function(v, dig=2) formatC(v, big.mark=".", decimal.mark=",", digits=dig, format="f")
}

get_ruta_trm <- function(params) {
  if (!is.null(params$ruta_archivo) && nzchar(params$ruta_archivo)) return(params$ruta_archivo)
  if (!is.null(params$ruta_trm)      && nzchar(params$ruta_trm))      return(params$ruta_trm)
  stop("No viene ni 'ruta_archivo' ni 'ruta_trm' en params.")
}

if (!exists("params")) {
  params <- list(
    ruta_archivo = "C:/Users/ASUS/Documents/Tasa_de_Cambio_Representativa_del__Mercado_-Historico_20250918.csv",
    ruta_futuros = "C:/Users/ASUS/Documents/futuros_trm_unidos.xlsx"
  )
}

ruta_trm <- normalizePath(get_ruta_trm(params), winslash = "/", mustWork = TRUE)
cat("WD knit: ", getwd(), "\n")
## WD knit:  C:/Users/ASUS/Downloads
cat("ruta_trm: ", ruta_trm, " | existe? ", file.exists(ruta_trm), "\n")
## ruta_trm:  C:/Users/ASUS/Documents/DERIVADOS FINANCIEROS/LABORATORIO 1/Tasa_de_Cambio_Representativa_del__Mercado_-Historico_20250918.csv  | existe?  TRUE
leer_trm_archivo <- function(path){
  stopifnot(file.exists(path))
  ext <- tolower(tools::file_ext(path))

  if (ext %in% c("xlsx","xls")) {
    df <- readxl::read_excel(path, sheet = 1, col_names = TRUE)
  } else {
    df <- tryCatch(
      readr::read_csv2(path, show_col_types = FALSE,
                       locale = readr::locale(decimal_mark=",")),
      error = function(e) readr::read_csv(path, show_col_types = FALSE)
    )
  }

  nms <- tolower(names(df))
  i_fecha <- which(nms %in% c("fecha","date","periodo","vigenciadesde","vigenciaini","vigenciad"))[1]
  i_valor <- which(nms %in% c("valor","trm","tasa","tasarepresentativadelmercado",
                              "valortrm","valor_de_la_tasa"))[1]
  if (is.na(i_fecha) || is.na(i_valor))
    stop("No pude identificar columnas de fecha/valor.")

  fecha_chr <- as.character(df[[i_fecha]])


  fecha <- suppressWarnings(as.Date(fecha_chr))
  
  need_fix <- is.na(fecha) | (as.integer(format(fecha, "%Y")) < 1900)
  if (any(need_fix)) {
    if (!requireNamespace("lubridate", quietly = TRUE))
      stop("Instala 'lubridate' (install.packages('lubridate')) para parsear fechas.")
    fecha2 <- suppressWarnings(
      lubridate::parse_date_time(
        fecha_chr,
        orders = c("Ymd","Y-m-d","Y/m/d","dmY","d/m/Y","d-m-Y","mdY","m/d/Y","m-d-Y"),
        tz = "UTC"
      )
    )
    fecha2 <- as.Date(fecha2)

    
    yy <- suppressWarnings(as.integer(format(fecha2, "%Y")))
    bad <- !is.na(yy) & yy < 1900
    if (any(bad)) {
      mm <- as.integer(format(fecha2[bad], "%m"))
      dd <- as.integer(format(fecha2[bad], "%d"))
      yy_new <- 2000 + yy[bad]
      fecha2[bad] <- as.Date(sprintf("%04d-%02d-%02d", yy_new, mm, dd))
    }

    fecha[need_fix] <- fecha2[need_fix]
  }

  
  val_raw  <- as.character(df[[i_valor]])
  val_raw  <- gsub("\\s|\\$|COP|USD", "", val_raw, ignore.case = TRUE)
  val_raw  <- gsub("\\.", "", val_raw)           # quitar miles .
  val_norm <- gsub(",", ".", val_raw, fixed=TRUE)
  valor    <- suppressWarnings(as.numeric(val_norm))

  
  med <- suppressWarnings(median(valor, na.rm=TRUE))
  if (is.finite(med) && med > 10000 && med < 1e6) valor <- valor/100
  if (is.finite(med) && med >= 1e6)               valor <- valor/1000

  out <- tibble(fecha = fecha, valor = valor) |>
    dplyr::filter(is.finite(valor), !is.na(fecha)) |>
    dplyr::arrange(fecha)

  cat("Rango de fechas leídas: ",
      format(min(out$fecha), "%Y-%m-%d"), " → ",
      format(max(out$fecha), "%Y-%m-%d"), "\n", sep = "")

  out
}

trm_daily <- leer_trm_archivo(ruta_trm)
## Rango de fechas leídas: 2015-09-16 → 2025-09-13
trm_monthly <- trm_daily |>
  dplyr::mutate(mes = as.Date(paste0(format(fecha, "%Y-%m"), "-01"))) |>
  dplyr::group_by(mes) |>
  dplyr::summarise(TRM = mean(valor, na.rm=TRUE), .groups="drop") |>
  dplyr::arrange(mes)

trm_120 <- tail(trm_monthly, 120)

ret_cc  <- diff(log(trm_120$TRM))
mu_m    <- mean(ret_cc, na.rm=TRUE)
sigma_m <- sd(ret_cc,   na.rm=TRUE)
S0      <- dplyr::last(trm_120$TRM)

cat(sprintf("TRM actual S0 (120m): %s COP/USD\n", fmt(S0,2)))
## TRM actual S0 (120m): 3.951,92 COP/USD
cat(sprintf("Media mensual (log-return, 120m): %0.6f\n", mu_m))
## Media mensual (log-return, 120m): 0.002497
cat(sprintf("Desv. estándar mensual (log-return, 120m): %0.6f\n", sigma_m))
## Desv. estándar mensual (log-return, 120m): 0.031970
# --- Tabla (120m) ---
tab120 <- tibble(
  mes        = trm_120$mes[-1],
  TRM        = trm_120$TRM[-1],
  ret_log    = ret_cc,
  ret_simple = diff(trm_120$TRM) / head(trm_120$TRM, -1)
)
tab120$TRM        <- fmt_kb(tab120$TRM,2)
tab120$ret_log    <- fmt_kb(tab120$ret_log,6)
tab120$ret_simple <- fmt_kb(tab120$ret_simple,6)
knitr::kable(tab120, align='r', caption = "TRM mensual y retornos (últimos 120 meses)")
TRM mensual y retornos (últimos 120 meses)
mes TRM ret_log ret_simple
2015-11-01 3.000,21 0,021622 0,021858
2015-12-01 3.244,51 0,078282 0,081427
2016-01-01 3.291,14 0,014270 0,014372
2016-02-01 3.358,44 0,020245 0,020451
2016-03-01 3.145,26 -0,065582 -0,063478
2016-04-01 2.992,01 -0,049952 -0,048725
2016-05-01 2.995,60 0,001202 0,001203
2016-06-01 2.991,68 -0,001311 -0,001310
2016-07-01 2.969,88 -0,007315 -0,007289
2016-08-01 2.958,20 -0,003938 -0,003930
2016-09-01 2.919,41 -0,013200 -0,013114
2016-10-01 2.933,59 0,004844 0,004856
2016-11-01 3.102,21 0,055890 0,057481
2016-12-01 3.010,17 -0,030118 -0,029669
2017-01-01 2.938,90 -0,023963 -0,023678
2017-02-01 2.880,57 -0,020047 -0,019847
2017-03-01 2.943,49 0,021609 0,021844
2017-04-01 2.877,46 -0,022691 -0,022435
2017-05-01 2.922,80 0,015636 0,015759
2017-06-01 2.958,36 0,012093 0,012167
2017-07-01 3.038,11 0,026599 0,026956
2017-08-01 2.972,62 -0,021790 -0,021554
2017-09-01 2.918,52 -0,018369 -0,018201
2017-10-01 2.956,70 0,012998 0,013083
2017-11-01 3.014,78 0,019451 0,019642
2017-12-01 2.991,42 -0,007779 -0,007749
2018-01-01 2.862,18 -0,044163 -0,043202
2018-02-01 2.860,36 -0,000638 -0,000638
2018-03-01 2.848,86 -0,004026 -0,004017
2018-04-01 2.765,23 -0,029795 -0,029356
2018-05-01 2.861,74 0,034306 0,034901
2018-06-01 2.895,10 0,011589 0,011657
2018-07-01 2.881,69 -0,004643 -0,004632
2018-08-01 2.959,57 0,026666 0,027025
2018-09-01 3.033,76 0,024757 0,025066
2018-10-01 3.088,35 0,017836 0,017996
2018-11-01 3.198,23 0,034959 0,035577
2018-12-01 3.212,48 0,004448 0,004458
2019-01-01 3.159,46 -0,016642 -0,016504
2019-02-01 3.113,77 -0,014569 -0,014463
2019-03-01 3.127,69 0,004461 0,004471
2019-04-01 3.154,19 0,008437 0,008473
2019-05-01 3.308,19 0,047668 0,048823
2019-06-01 3.253,37 -0,016709 -0,016570
2019-07-01 3.208,29 -0,013953 -0,013856
2019-08-01 3.413,34 0,061955 0,063914
2019-09-01 3.396,71 -0,004886 -0,004874
2019-10-01 3.437,73 0,012003 0,012075
2019-11-01 3.412,45 -0,007379 -0,007351
2019-12-01 3.376,03 -0,010732 -0,010675
2020-01-01 3.319,31 -0,016943 -0,016800
2020-02-01 3.416,32 0,028807 0,029226
2020-03-01 3.886,51 0,128949 0,137632
2020-04-01 3.986,56 0,025416 0,025742
2020-05-01 3.856,12 -0,033268 -0,032721
2020-06-01 3.691,57 -0,043610 -0,042672
2020-07-01 3.660,60 -0,008424 -0,008389
2020-08-01 3.788,10 0,034237 0,034830
2020-09-01 3.752,11 -0,009547 -0,009501
2020-10-01 3.834,22 0,021648 0,021884
2020-11-01 3.675,21 -0,042356 -0,041472
2020-12-01 3.468,50 -0,057886 -0,056243
2021-01-01 3.503,13 0,009933 0,009982
2021-02-01 3.557,79 0,015483 0,015603
2021-03-01 3.616,65 0,016409 0,016544
2021-04-01 3.651,85 0,009687 0,009734
2021-05-01 3.741,96 0,024375 0,024675
2021-06-01 3.691,83 -0,013488 -0,013398
2021-07-01 3.833,94 0,037771 0,038494
2021-08-01 3.888,67 0,014173 0,014274
2021-09-01 3.821,72 -0,017365 -0,017215
2021-10-01 3.772,61 -0,012935 -0,012852
2021-11-01 3.904,76 0,034429 0,035029
2021-12-01 3.967,77 0,016009 0,016138
2022-01-01 4.002,19 0,008638 0,008676
2022-02-01 3.938,95 -0,015930 -0,015803
2022-03-01 3.805,52 -0,034460 -0,033873
2022-04-01 3.804,88 -0,000168 -0,000168
2022-05-01 4.030,66 0,057646 0,059340
2022-06-01 3.922,50 -0,027203 -0,026836
2022-07-01 4.389,33 0,112447 0,119013
2022-08-01 4.328,03 -0,014063 -0,013964
2022-09-01 4.435,91 0,024619 0,024925
2022-10-01 4.720,74 0,062232 0,064209
2022-11-01 4.931,33 0,043644 0,044611
2022-12-01 4.790,04 -0,029071 -0,028652
2023-01-01 4.702,31 -0,018485 -0,018316
2023-02-01 4.796,64 0,019862 0,020061
2023-03-01 4.760,96 -0,007465 -0,007437
2023-04-01 4.533,56 -0,048942 -0,047764
2023-05-01 4.536,83 0,000721 0,000722
2023-06-01 4.213,53 -0,073928 -0,071262
2023-07-01 4.061,53 -0,036741 -0,036075
2023-08-01 4.066,87 0,001315 0,001316
2023-09-01 4.007,96 -0,014593 -0,014487
2023-10-01 4.219,05 0,051329 0,052669
2023-11-01 4.037,51 -0,043981 -0,043028
2023-12-01 3.954,14 -0,020866 -0,020650
2024-01-01 3.926,36 -0,007051 -0,007026
2024-02-01 3.932,55 0,001577 0,001578
2024-03-01 3.905,18 -0,006987 -0,006962
2024-04-01 3.867,25 -0,009759 -0,009711
2024-05-01 3.864,44 -0,000726 -0,000726
2024-06-01 4.057,13 0,048657 0,049861
2024-07-01 4.028,28 -0,007137 -0,007111
2024-08-01 4.067,62 0,009719 0,009767
2024-09-01 4.195,18 0,030878 0,031360
2024-10-01 4.257,76 0,014808 0,014918
2024-11-01 4.411,83 0,035546 0,036185
2024-12-01 4.384,53 -0,006207 -0,006188
2025-01-01 4.292,27 -0,021268 -0,021043
2025-02-01 4.133,60 -0,037667 -0,036966
2025-03-01 4.133,48 -0,000028 -0,000028
2025-04-01 4.273,88 0,033402 0,033966
2025-05-01 4.201,50 -0,017079 -0,016934
2025-06-01 4.113,55 -0,021155 -0,020933
2025-07-01 4.049,69 -0,015647 -0,015525
2025-08-01 4.049,93 0,000058 0,000058
2025-09-01 3.951,92 -0,024498 -0,024201
main_txt   <- "TRM histórica (últimos 120 meses)"
ylab_txt   <- "TRM (COP/USD)"
legend_txt <- "TRM actual S0"

y_lim <- range(trm_120$TRM, na.rm = TRUE)
yt    <- pretty(y_lim)


plot(trm_120$mes, trm_120$TRM,
     type = "l", lwd = 2, xlab = "Fecha", ylab = ylab_txt,
     main = main_txt, yaxt = "n", xaxt = "n")
abline(h = S0, col = "darkred", lwd = 2, lty = 2)
axis(2, at = yt, labels = fmt_kb(yt, 0), las = 1)

ticks_x <- seq(from = as.Date(paste0(format(min(trm_120$mes), "%Y"), "-01-01")),
               to   = as.Date(paste0(format(max(trm_120$mes), "%Y"), "-01-01")),
               by   = "year")
axis.Date(1, at = ticks_x, format = "%Y")

legend("topleft", bty = "n", lty = 2, lwd = 2, col = "darkred", legend = legend_txt)

## 1.3 Simulación BMG mensual

H  <- 120    # meses
N  <- 5000
dt <- 1

Z    <- matrix(rnorm(H * N), nrow = H, ncol = N)
incr <- (mu_m - 0.5 * sigma_m^2) * dt + sigma_m * sqrt(dt) * Z
paths <- S0 * exp(apply(incr, 2, cumsum))

percentiles_m <- function(x) c(
  p05 = quantile(x, 0.05),
  p25 = quantile(x, 0.25),
  p50 = quantile(x, 0.50),
  p75 = quantile(x, 0.75),
  p95 = quantile(x, 0.95)
)
fan <- data.frame(mes_fwd = 1:H, t(apply(paths, 1, percentiles_m)))

# Gráfico con ejes locales
yr <- range(as.matrix(fan[,setdiff(names(fan),"mes_fwd")]), na.rm=TRUE)
yt <- pretty(yr)
plot(fan$mes_fwd, fan$p50, type="l", lwd=2,
     xlab="Mes hacia adelante", ylab="TRM (COP/USD)",
     main="TRM simulada (mediana y bandas)", yaxt="n")
lines(fan$mes_fwd, fan$p05, lty=2)
lines(fan$mes_fwd, fan$p95, lty=2)
lines(fan$mes_fwd, fan$p25, lty=3)
lines(fan$mes_fwd, fan$p75, lty=3)
abline(h=S0, col="darkred", lwd=2)
axis(2, at=yt, labels=fmt_kb(yt,0), las=1)
legend("topleft", bty="n",
       legend=c("Mediana","p25/p75","p05/p95","S0"),
       lty=c(1,3,2,1), lwd=c(2,1,1,2),
       col=c("black","black","black","darkred"))

## 1.4 Simulación de crédito de la maquinaria con la tasa extranjera, con pago de inicial del 15% del crédito. (En dólares)

monto_COP      <- 300000000           # inversión en COP
precio_USD     <- monto_COP / S0
pago_inicial   <- 0.15 * precio_USD
principal_USD  <- 0.85 * precio_USD
tasa_anual_USD <- 0.0796
n_meses        <- 120
i_mensual      <- tasa_anual_USD / 12

# Cuota francesa
cuota_USD <- principal_USD * i_mensual * (1 + i_mensual)^n_meses / ((1 + i_mensual)^n_meses - 1)

# Tabla completa (120)
amort_USD <- data.frame(
  periodo   = 1:n_meses, saldo_ini = NA_real_, interes = NA_real_,
  amort     = NA_real_,  cuota = rep(cuota_USD, n_meses), saldo_fin = NA_real_
)
saldo <- principal_USD
for (t in 1:n_meses) {
  amort_USD$saldo_ini[t] <- saldo
  amort_USD$interes[t]   <- saldo * i_mensual
  amort_USD$amort[t]     <- cuota_USD - amort_USD$interes[t]
  amort_USD$saldo_fin[t] <- saldo - amort_USD$amort[t]
  saldo <- amort_USD$saldo_fin[t]
}

cat(sprintf("Precio maquinaria: %s USD\n", fmt(precio_USD,2)))
## Precio maquinaria: 75.912,53 USD
cat(sprintf("Pago inicial (15%%): %s USD | Principal: %s USD\n", fmt(pago_inicial,2), fmt(principal_USD,2)))
## Pago inicial (15%): 11.386,88 USD | Principal: 64.525,65 USD
cat(sprintf("Cuota mensual (USD): %s | Tasa anual: %0.2f%%\n", fmt(cuota_USD,2), 100*tasa_anual_USD))
## Cuota mensual (USD): 781,51 | Tasa anual: 7.96%
amort_kable <- amort_USD
amort_kable$saldo_ini <- fmt_kb(amort_kable$saldo_ini,2)
amort_kable$interes   <- fmt_kb(amort_kable$interes,2)
amort_kable$amort     <- fmt_kb(amort_kable$amort,2)
amort_kable$cuota     <- fmt_kb(amort_kable$cuota,2)
amort_kable$saldo_fin <- fmt_kb(amort_kable$saldo_fin,2)

knitr::kable(amort_kable, align='r', caption = "Amortización en USD (120 meses)")
Amortización en USD (120 meses)
periodo saldo_ini interes amort cuota saldo_fin
1 64.525,65 428,02 353,49 781,51 64.172,16
2 64.172,16 425,68 355,84 781,51 63.816,33
3 63.816,33 423,31 358,20 781,51 63.458,13
4 63.458,13 420,94 360,57 781,51 63.097,56
5 63.097,56 418,55 362,96 781,51 62.734,59
6 62.734,59 416,14 365,37 781,51 62.369,22
7 62.369,22 413,72 367,80 781,51 62.001,43
8 62.001,43 411,28 370,23 781,51 61.631,19
9 61.631,19 408,82 372,69 781,51 61.258,50
10 61.258,50 406,35 375,16 781,51 60.883,34
11 60.883,34 403,86 377,65 781,51 60.505,69
12 60.505,69 401,35 380,16 781,51 60.125,53
13 60.125,53 398,83 382,68 781,51 59.742,85
14 59.742,85 396,29 385,22 781,51 59.357,63
15 59.357,63 393,74 387,77 781,51 58.969,86
16 58.969,86 391,17 390,34 781,51 58.579,52
17 58.579,52 388,58 392,93 781,51 58.186,58
18 58.186,58 385,97 395,54 781,51 57.791,04
19 57.791,04 383,35 398,16 781,51 57.392,88
20 57.392,88 380,71 400,80 781,51 56.992,08
21 56.992,08 378,05 403,46 781,51 56.588,61
22 56.588,61 375,37 406,14 781,51 56.182,47
23 56.182,47 372,68 408,83 781,51 55.773,64
24 55.773,64 369,97 411,55 781,51 55.362,09
25 55.362,09 367,24 414,28 781,51 54.947,82
26 54.947,82 364,49 417,02 781,51 54.530,79
27 54.530,79 361,72 419,79 781,51 54.111,00
28 54.111,00 358,94 422,57 781,51 53.688,43
29 53.688,43 356,13 425,38 781,51 53.263,05
30 53.263,05 353,31 428,20 781,51 52.834,85
31 52.834,85 350,47 431,04 781,51 52.403,81
32 52.403,81 347,61 433,90 781,51 51.969,91
33 51.969,91 344,73 436,78 781,51 51.533,13
34 51.533,13 341,84 439,67 781,51 51.093,46
35 51.093,46 338,92 442,59 781,51 50.650,87
36 50.650,87 335,98 445,53 781,51 50.205,34
37 50.205,34 333,03 448,48 781,51 49.756,86
38 49.756,86 330,05 451,46 781,51 49.305,40
39 49.305,40 327,06 454,45 781,51 48.850,95
40 48.850,95 324,04 457,47 781,51 48.393,48
41 48.393,48 321,01 460,50 781,51 47.932,98
42 47.932,98 317,96 463,56 781,51 47.469,43
43 47.469,43 314,88 466,63 781,51 47.002,80
44 47.002,80 311,79 469,73 781,51 46.533,07
45 46.533,07 308,67 472,84 781,51 46.060,23
46 46.060,23 305,53 475,98 781,51 45.584,25
47 45.584,25 302,38 479,14 781,51 45.105,11
48 45.105,11 299,20 482,31 781,51 44.622,80
49 44.622,80 296,00 485,51 781,51 44.137,29
50 44.137,29 292,78 488,73 781,51 43.648,55
51 43.648,55 289,54 491,98 781,51 43.156,58
52 43.156,58 286,27 495,24 781,51 42.661,34
53 42.661,34 282,99 498,52 781,51 42.162,82
54 42.162,82 279,68 501,83 781,51 41.660,98
55 41.660,98 276,35 505,16 781,51 41.155,82
56 41.155,82 273,00 508,51 781,51 40.647,31
57 40.647,31 269,63 511,88 781,51 40.135,43
58 40.135,43 266,23 515,28 781,51 39.620,15
59 39.620,15 262,81 518,70 781,51 39.101,45
60 39.101,45 259,37 522,14 781,51 38.579,31
61 38.579,31 255,91 525,60 781,51 38.053,71
62 38.053,71 252,42 529,09 781,51 37.524,62
63 37.524,62 248,91 532,60 781,51 36.992,03
64 36.992,03 245,38 536,13 781,51 36.455,90
65 36.455,90 241,82 539,69 781,51 35.916,21
66 35.916,21 238,24 543,27 781,51 35.372,94
67 35.372,94 234,64 546,87 781,51 34.826,07
68 34.826,07 231,01 550,50 781,51 34.275,57
69 34.275,57 227,36 554,15 781,51 33.721,42
70 33.721,42 223,69 557,83 781,51 33.163,60
71 33.163,60 219,99 561,53 781,51 32.602,07
72 32.602,07 216,26 565,25 781,51 32.036,82
73 32.036,82 212,51 569,00 781,51 31.467,82
74 31.467,82 208,74 572,77 781,51 30.895,05
75 30.895,05 204,94 576,57 781,51 30.318,47
76 30.318,47 201,11 580,40 781,51 29.738,08
77 29.738,08 197,26 584,25 781,51 29.153,83
78 29.153,83 193,39 588,12 781,51 28.565,70
79 28.565,70 189,49 592,03 781,51 27.973,68
80 27.973,68 185,56 595,95 781,51 27.377,72
81 27.377,72 181,61 599,91 781,51 26.777,82
82 26.777,82 177,63 603,88 781,51 26.173,93
83 26.173,93 173,62 607,89 781,51 25.566,04
84 25.566,04 169,59 611,92 781,51 24.954,12
85 24.954,12 165,53 615,98 781,51 24.338,14
86 24.338,14 161,44 620,07 781,51 23.718,07
87 23.718,07 157,33 624,18 781,51 23.093,89
88 23.093,89 153,19 628,32 781,51 22.465,57
89 22.465,57 149,02 632,49 781,51 21.833,08
90 21.833,08 144,83 636,68 781,51 21.196,39
91 21.196,39 140,60 640,91 781,51 20.555,49
92 20.555,49 136,35 645,16 781,51 19.910,33
93 19.910,33 132,07 649,44 781,51 19.260,89
94 19.260,89 127,76 653,75 781,51 18.607,14
95 18.607,14 123,43 658,08 781,51 17.949,06
96 17.949,06 119,06 662,45 781,51 17.286,61
97 17.286,61 114,67 666,84 781,51 16.619,76
98 16.619,76 110,24 671,27 781,51 15.948,50
99 15.948,50 105,79 675,72 781,51 15.272,78
100 15.272,78 101,31 680,20 781,51 14.592,58
101 14.592,58 96,80 684,71 781,51 13.907,86
102 13.907,86 92,26 689,26 781,51 13.218,61
103 13.218,61 87,68 693,83 781,51 12.524,78
104 12.524,78 83,08 698,43 781,51 11.826,35
105 11.826,35 78,45 703,06 781,51 11.123,29
106 11.123,29 73,78 707,73 781,51 10.415,56
107 10.415,56 69,09 712,42 781,51 9.703,14
108 9.703,14 64,36 717,15 781,51 8.985,99
109 8.985,99 59,61 721,90 781,51 8.264,09
110 8.264,09 54,82 726,69 781,51 7.537,39
111 7.537,39 50,00 731,51 781,51 6.805,88
112 6.805,88 45,15 736,37 781,51 6.069,52
113 6.069,52 40,26 741,25 781,51 5.328,27
114 5.328,27 35,34 746,17 781,51 4.582,10
115 4.582,10 30,39 751,12 781,51 3.830,98
116 3.830,98 25,41 756,10 781,51 3.074,88
117 3.074,88 20,40 761,11 781,51 2.313,77
118 2.313,77 15,35 766,16 781,51 1.547,61
119 1.547,61 10,27 771,25 781,51 776,36
120 776,36 5,15 776,36 781,51 -0,00

1.5 Rereación del crédito en pesos

Crédito transformado a COP (TRM simulada)

# ===== 6A) MBG
n_meses <- 120
N_paths <- 5000
dt <- 1
set.seed(1234)

# Simulación GBM
Z  <- matrix(rnorm(n_meses * N_paths), nrow = n_meses, ncol = N_paths)
incr <- (mu_m - 0.5 * sigma_m^2) * dt + sigma_m * sqrt(dt) * Z
paths_mbg <- S0 * exp(apply(incr, 2, cumsum))

# Caminatas representativas por cuantiles (p5/p50/p95)
ST  <- paths_mbg[n_meses, ]
q5  <- as.numeric(quantile(ST, 0.05))
q50 <- as.numeric(quantile(ST, 0.50))
q95 <- as.numeric(quantile(ST, 0.95))
i5  <- which.min(abs(ST - q5))
i50 <- which.min(abs(ST - q50))
i95 <- which.min(abs(ST - q95))

TRM_mbg_lo <- paths_mbg[, i5]
TRM_mbg_md <- paths_mbg[, i50]
TRM_mbg_hi <- paths_mbg[, i95]

# Costos del crédito en COP (MBG)
tot_mbg_lo <- sum(amort_USD$cuota * TRM_mbg_lo)
tot_mbg_md <- sum(amort_USD$cuota * TRM_mbg_md)
tot_mbg_hi <- sum(amort_USD$cuota * TRM_mbg_hi)

# Tabla de crédito en COP con TRM mediana MBG (primeros 120)
TRM_mediana_mbg <- TRM_mbg_md
cred_mbg <- amort_USD |>
  dplyr::mutate(TRM_mediana = TRM_mediana_mbg[periodo],
                cuota_COP   = cuota   * TRM_mediana,
                interes_COP = interes * TRM_mediana,
                amort_COP   = amort   * TRM_mediana)
tab_mbg <- cred_mbg[1:120, c("periodo","cuota","TRM_mediana","cuota_COP","interes_COP","amort_COP")]
tab_mbg$cuota       <- fmt_kb(tab_mbg$cuota,2)
tab_mbg$TRM_mediana <- fmt_kb(tab_mbg$TRM_mediana,2)
tab_mbg$cuota_COP   <- fmt_kb(tab_mbg$cuota_COP,2)
tab_mbg$interes_COP <- fmt_kb(tab_mbg$interes_COP,2)
tab_mbg$amort_COP   <- fmt_kb(tab_mbg$amort_COP,2)
knitr::kable(tab_mbg, align='r', caption="MBG: Crédito en COP con TRM mediana (primeros 120 meses)")
MBG: Crédito en COP con TRM mediana (primeros 120 meses)
periodo cuota TRM_mediana cuota_COP interes_COP amort_COP
1 781,51 3.931,13 3.072.220,14 1.682.602,10 1.389.618,05
2 781,51 3.770,29 2.946.525,88 1.604.920,84 1.341.605,04
3 781,51 3.826,75 2.990.650,88 1.619.922,37 1.370.728,51
4 781,51 3.900,32 3.048.145,14 1.641.797,53 1.406.347,60
5 781,51 4.035,53 3.153.813,40 1.689.060,60 1.464.752,80
6 781,51 4.155,13 3.247.276,68 1.729.111,79 1.518.164,89
7 781,51 4.145,51 3.239.765,68 1.715.065,13 1.524.700,55
8 781,51 3.998,24 3.124.671,55 1.644.382,12 1.480.289,43
9 781,51 3.817,21 2.983.190,35 1.560.551,91 1.422.638,43
10 781,51 3.767,25 2.944.144,14 1.530.812,94 1.413.331,21
11 781,51 3.797,01 2.967.409,04 1.533.460,38 1.433.948,66
12 781,51 3.861,31 3.017.654,14 1.549.752,49 1.467.901,64
13 781,51 3.834,82 2.996.953,91 1.529.451,36 1.467.502,56
14 781,51 3.726,51 2.912.306,95 1.476.793,53 1.435.513,42
15 781,51 3.829,97 2.993.162,34 1.508.007,66 1.485.154,68
16 781,51 3.730,93 2.915.763,97 1.459.416,22 1.456.347,75
17 781,51 3.969,08 3.101.877,27 1.542.293,73 1.559.583,54
18 781,51 4.088,24 3.195.005,06 1.577.942,25 1.617.062,81
19 781,51 3.803,58 2.972.539,74 1.458.091,91 1.514.447,82
20 781,51 3.768,84 2.945.387,36 1.434.819,04 1.510.568,32
21 781,51 3.696,71 2.889.020,03 1.397.531,85 1.491.488,17
22 781,51 3.821,05 2.986.195,86 1.434.313,28 1.551.882,58
23 781,51 3.778,43 2.952.887,14 1.408.135,29 1.544.751,85
24 781,51 3.875,27 3.028.569,30 1.433.716,15 1.594.853,14
25 781,51 3.786,07 2.958.852,92 1.390.376,96 1.568.475,97
26 781,51 3.803,56 2.972.520,70 1.386.347,21 1.586.173,48
27 781,51 3.577,81 2.796.100,12 1.294.169,66 1.501.930,45
28 781,51 3.656,25 2.857.397,10 1.312.359,64 1.545.037,46
29 781,51 3.734,71 2.918.715,98 1.330.053,80 1.588.662,18
30 781,51 3.786,17 2.958.937,02 1.337.699,12 1.621.237,91
31 781,51 3.666,86 2.865.690,47 1.285.128,18 1.580.562,28
32 781,51 3.774,42 2.949.748,50 1.312.032,35 1.637.716,15
33 781,51 3.762,90 2.940.746,04 1.297.197,74 1.643.548,30
34 781,51 3.896,82 3.045.404,30 1.332.073,53 1.713.330,77
35 781,51 4.007,25 3.131.710,44 1.358.137,05 1.773.573,39
36 781,51 3.992,18 3.119.936,43 1.341.310,51 1.778.625,92
37 781,51 3.955,70 3.091.421,99 1.317.361,31 1.774.060,68
38 781,51 3.868,37 3.023.174,02 1.276.770,36 1.746.403,66
39 781,51 3.832,29 2.994.979,56 1.253.386,61 1.741.592,95
40 781,51 4.073,54 3.183.516,88 1.320.008,89 1.863.507,99
41 781,51 4.005,70 3.130.501,13 1.285.871,10 1.844.630,03
42 781,51 4.055,00 3.169.030,09 1.289.310,45 1.879.719,64
43 781,51 4.211,28 3.291.164,88 1.326.051,27 1.965.113,61
44 781,51 4.100,11 3.204.281,45 1.278.353,72 1.925.927,73
45 781,51 4.037,70 3.155.509,05 1.246.315,02 1.909.194,03
46 781,51 4.210,00 3.290.161,41 1.286.293,23 2.003.868,19
47 781,51 4.330,38 3.384.243,06 1.309.402,16 2.074.840,90
48 781,51 4.418,16 3.452.842,27 1.321.901,88 2.130.940,38
49 781,51 4.330,60 3.384.415,24 1.281.849,86 2.102.565,39
50 781,51 4.350,57 3.400.017,66 1.273.747,97 2.126.269,69
51 781,51 4.378,61 3.421.935,43 1.267.763,84 2.154.171,59
52 781,51 4.251,45 3.322.554,13 1.217.070,57 2.105.483,57
53 781,51 4.233,92 3.308.856,37 1.198.144,20 2.110.712,17
54 781,51 4.045,44 3.161.559,52 1.131.429,90 2.030.129,62
55 781,51 4.056,32 3.170.061,52 1.120.969,78 2.049.091,74
56 781,51 4.100,93 3.204.924,34 1.119.555,88 2.085.368,46
57 781,51 4.015,03 3.137.792,76 1.082.562,03 2.055.230,72
58 781,51 4.031,11 3.150.360,66 1.073.210,42 2.077.150,24
59 781,51 4.036,31 3.154.422,14 1.060.797,82 2.093.624,32
60 781,51 3.997,37 3.123.991,12 1.036.810,47 2.087.180,65
61 781,51 3.917,50 3.061.568,68 1.002.524,98 2.059.043,69
62 781,51 3.799,43 2.969.298,55 959.064,01 2.010.234,53
63 781,51 3.644,03 2.847.848,59 907.047,32 1.940.801,27
64 781,51 3.895,52 3.044.392,24 955.884,52 2.088.507,72
65 781,51 3.727,03 2.912.712,11 901.284,78 2.011.427,34
66 781,51 3.937,39 3.077.117,11 938.061,29 2.139.055,83
67 781,51 3.838,72 3.000.002,98 900.719,51 2.099.283,48
68 781,51 3.567,70 2.788.198,87 824.185,43 1.964.013,44
69 781,51 3.619,84 2.828.946,76 823.012,06 2.005.934,69
70 781,51 3.584,37 2.801.223,16 801.770,93 1.999.452,22
71 781,51 3.467,36 2.709.783,06 762.768,70 1.947.014,36
72 781,51 3.407,83 2.663.255,43 736.978,34 1.926.277,09
73 781,51 3.336,45 2.607.473,20 709.032,23 1.898.440,98
74 781,51 3.268,33 2.554.236,40 682.220,03 1.872.016,37
75 781,51 3.268,17 2.554.111,51 669.769,57 1.884.341,94
76 781,51 3.114,06 2.433.671,67 626.276,35 1.807.395,32
77 781,51 3.073,84 2.402.241,65 606.353,99 1.795.887,67
78 781,51 3.039,52 2.375.420,20 587.804,22 1.787.615,98
79 781,51 2.934,27 2.293.164,05 556.002,47 1.737.161,57
80 781,51 2.728,45 2.132.312,21 506.287,31 1.626.024,90
81 781,51 2.930,69 2.290.368,49 532.230,07 1.758.138,42
82 781,51 3.134,62 2.449.736,60 556.789,83 1.892.946,78
83 781,51 3.022,59 2.362.183,80 524.782,56 1.837.401,24
84 781,51 3.106,85 2.428.035,75 526.884,35 1.901.151,40
85 781,51 3.155,72 2.466.231,88 522.363,56 1.943.868,32
86 781,51 3.194,97 2.496.907,01 515.806,04 1.981.100,97
87 781,51 3.119,44 2.437.873,21 490.780,35 1.947.092,86
88 781,51 3.210,21 2.508.816,50 491.770,73 2.017.045,77
89 781,51 3.148,32 2.460.445,06 469.167,34 1.991.277,73
90 781,51 2.960,00 2.313.273,71 428.685,40 1.884.588,31
91 781,51 2.945,80 2.302.178,75 414.188,19 1.887.990,57
92 781,51 2.877,14 2.248.513,07 392.301,39 1.856.211,68
93 781,51 2.827,95 2.210.075,86 373.492,80 1.836.583,06
94 781,51 2.809,86 2.195.936,58 358.998,60 1.836.937,98
95 781,51 2.885,51 2.255.055,65 356.150,50 1.898.905,14
96 781,51 3.022,42 2.362.058,18 359.856,11 2.002.202,07
97 781,51 3.241,38 2.533.172,39 371.681,70 2.161.490,68
98 781,51 3.368,26 2.632.335,96 371.332,40 2.261.003,56
99 781,51 3.464,30 2.707.388,91 366.494,18 2.340.894,73
100 781,51 3.786,06 2.958.849,21 383.563,74 2.575.285,48
101 781,51 3.927,59 3.069.457,05 380.180,82 2.689.276,23
102 781,51 3.970,21 3.102.761,35 366.273,45 2.736.487,90
103 781,51 4.321,38 3.377.207,53 378.913,53 2.998.294,00
104 781,51 4.449,34 3.477.208,33 369.655,75 3.107.552,58
105 781,51 4.611,02 3.603.562,43 361.725,75 3.241.836,68
106 781,51 4.785,76 3.740.125,43 353.114,83 3.387.010,61
107 781,51 4.992,85 3.901.964,54 344.955,12 3.557.009,42
108 781,51 4.952,02 3.870.054,88 318.732,26 3.551.322,62
109 781,51 4.890,85 3.822.255,92 291.529,45 3.530.726,47
110 781,51 5.102,80 3.987.893,00 279.727,44 3.708.165,56
111 781,51 5.006,80 3.912.869,31 250.330,22 3.662.539,10
112 781,51 4.976,66 3.889.318,44 224.674,91 3.664.643,53
113 781,51 4.968,32 3.882.798,74 200.030,23 3.682.768,51
114 781,51 5.297,78 4.140.277,15 187.245,77 3.953.031,38
115 781,51 5.068,17 3.960.831,48 154.044,98 3.806.786,50
116 781,51 4.821,88 3.768.351,65 122.534,48 3.645.817,17
117 781,51 5.076,34 3.967.215,58 103.540,73 3.863.674,85
118 781,51 5.226,02 4.084.193,94 80.209,01 4.003.984,94
119 781,51 4.916,28 3.842.123,61 50.469,45 3.791.654,17
120 781,51 5.088,98 3.977.093,54 26.207,54 3.950.885,99
# ===== 6B) AR(1) en log-TRM (media-revertente) 
n_meses <- 120
N_paths <- 5000
set.seed(1234)

y      <- log(trm_120$TRM)
fit    <- lm(tail(y, -1) ~ head(y, -1))
a_hat  <- as.numeric(coef(fit)[1])
phi    <- as.numeric(coef(fit)[2])
eps_sd <- sd(residuals(fit))
phi    <- max(min(phi, 0.995), 0.90)

E <- matrix(rnorm(n_meses * N_paths, 0, eps_sd), nrow=n_meses, ncol=N_paths)
Y <- matrix(NA_real_, nrow=n_meses, ncol=N_paths)
yT <- tail(y, 1)
Y[1, ] <- a_hat + phi * yT + E[1, ]
for (t in 2:n_meses) Y[t, ] <- a_hat + phi * Y[t - 1, ] + E[t, ]
paths_ar1 <- exp(Y)

# Caminatas p5/p50/p95
ST  <- paths_ar1[n_meses, ]
q5  <- as.numeric(quantile(ST, 0.05)); q50 <- as.numeric(quantile(ST, 0.50)); q95 <- as.numeric(quantile(ST, 0.95))
i5  <- which.min(abs(ST - q5)); i50 <- which.min(abs(ST - q50)); i95 <- which.min(abs(ST - q95))
TRM_ar1_lo <- paths_ar1[, i5]; TRM_ar1_md <- paths_ar1[, i50]; TRM_ar1_hi <- paths_ar1[, i95]

# Costos del crédito en COP (AR1)
tot_ar1_lo <- sum(amort_USD$cuota * TRM_ar1_lo)
tot_ar1_md <- sum(amort_USD$cuota * TRM_ar1_md)
tot_ar1_hi <- sum(amort_USD$cuota * TRM_ar1_hi)

# Tabla AR(1) (primeros 120) con TRM mediana
TRM_mediana_ar1 <- TRM_ar1_md
cred_ar1 <- amort_USD |>
  dplyr::mutate(TRM_mediana = TRM_mediana_ar1[periodo],
                cuota_COP   = cuota   * TRM_mediana,
                interes_COP = interes * TRM_mediana,
                amort_COP   = amort   * TRM_mediana)
tab_ar1 <- cred_ar1[1:120, c("periodo","cuota","TRM_mediana","cuota_COP","interes_COP","amort_COP")]
tab_ar1$cuota       <- fmt_kb(tab_ar1$cuota,2)
tab_ar1$TRM_mediana <- fmt_kb(tab_ar1$TRM_mediana,2)
tab_ar1$cuota_COP   <- fmt_kb(tab_ar1$cuota_COP,2)
tab_ar1$interes_COP <- fmt_kb(tab_ar1$interes_COP,2)
tab_ar1$amort_COP   <- fmt_kb(tab_ar1$amort_COP,2)
knitr::kable(tab_ar1, align='r', caption="AR(1): Crédito en COP con TRM mediana (primeros 120 meses)")
AR(1): Crédito en COP con TRM mediana (primeros 120 meses)
periodo cuota TRM_mediana cuota_COP interes_COP amort_COP
1 781,51 4.285,26 3.348.978,14 1.834.177,69 1.514.800,45
2 781,51 4.539,39 3.547.580,35 1.932.304,64 1.615.275,71
3 781,51 4.562,52 3.565.656,74 1.931.381,28 1.634.275,46
4 781,51 4.575,94 3.576.145,95 1.926.190,30 1.649.955,65
5 781,51 4.545,03 3.551.987,55 1.902.307,29 1.649.680,26
6 781,51 4.621,21 3.611.523,60 1.923.066,20 1.688.457,40
7 781,51 4.697,47 3.671.123,19 1.943.416,90 1.727.706,30
8 781,51 4.662,06 3.643.450,71 1.917.393,59 1.726.057,12
9 781,51 4.644,33 3.629.598,41 1.898.697,73 1.730.900,68
10 781,51 4.661,70 3.643.173,41 1.894.274,43 1.748.898,97
11 781,51 4.556,84 3.561.220,90 1.840.323,02 1.720.897,89
12 781,51 4.642,87 3.628.455,79 1.863.437,01 1.765.018,78
13 781,51 4.796,20 3.748.283,38 1.912.881,30 1.835.402,08
14 781,51 5.042,87 3.941.059,87 1.998.460,95 1.942.598,91
15 781,51 5.103,61 3.988.524,50 2.009.488,56 1.979.035,94
16 781,51 5.041,16 3.939.721,38 1.971.933,72 1.967.787,67
17 781,51 4.660,46 3.642.197,88 1.810.948,17 1.831.249,71
18 781,51 4.515,88 3.529.207,92 1.742.997,64 1.786.210,28
19 781,51 4.478,91 3.500.320,68 1.716.979,33 1.783.341,35
20 781,51 4.515,46 3.528.883,02 1.719.063,72 1.809.819,30
21 781,51 4.503,28 3.519.363,30 1.702.453,52 1.816.909,78
22 781,51 4.584,85 3.583.110,54 1.721.020,08 1.862.090,46
23 781,51 4.234,45 3.309.271,62 1.578.083,39 1.731.188,23
24 781,51 4.161,81 3.252.500,47 1.539.724,54 1.712.775,93
25 781,51 4.121,95 3.221.347,53 1.513.724,23 1.707.623,29
26 781,51 4.039,04 3.156.556,56 1.472.179,28 1.684.377,28
27 781,51 4.052,08 3.166.746,89 1.465.722,82 1.701.024,07
28 781,51 4.115,86 3.216.592,30 1.477.332,61 1.739.259,69
29 781,51 3.971,36 3.103.662,34 1.414.333,53 1.689.328,80
30 781,51 3.897,35 3.045.820,05 1.376.977,87 1.668.842,18
31 781,51 4.047,39 3.163.083,34 1.418.494,98 1.744.588,36
32 781,51 3.934,42 3.074.792,74 1.367.651,36 1.707.141,38
33 781,51 3.965,31 3.098.930,13 1.366.974,61 1.731.955,52
34 781,51 3.940,73 3.079.723,71 1.347.085,00 1.732.638,71
35 781,51 3.831,85 2.994.631,32 1.298.689,59 1.695.941,73
36 781,51 3.731,75 2.916.402,77 1.253.808,14 1.662.594,63
37 781,51 3.609,40 2.820.787,34 1.202.034,57 1.618.752,77
38 781,51 3.650,20 2.852.673,07 1.204.763,07 1.647.910,00
39 781,51 3.721,12 2.908.093,92 1.217.025,33 1.691.068,59
40 781,51 3.850,66 3.009.333,00 1.247.785,54 1.761.547,46
41 781,51 3.916,36 3.060.680,72 1.257.191,97 1.803.488,75
42 781,51 3.816,57 2.982.692,80 1.213.499,68 1.769.193,12
43 781,51 3.766,15 2.943.291,20 1.185.888,64 1.757.402,56
44 781,51 3.861,08 3.017.478,25 1.203.828,25 1.813.650,00
45 781,51 3.844,85 3.004.794,23 1.186.787,97 1.818.006,26
46 781,51 3.871,15 3.025.345,71 1.182.763,15 1.842.582,55
47 781,51 3.912,42 3.057.600,46 1.183.020,42 1.874.580,04
48 781,51 3.931,66 3.072.637,45 1.176.342,53 1.896.294,91
49 781,51 4.011,83 3.135.291,26 1.187.493,96 1.947.797,30
50 781,51 4.108,77 3.211.047,05 1.202.953,95 2.008.093,10
51 781,51 4.199,01 3.281.570,98 1.215.761,41 2.065.809,57
52 781,51 4.362,59 3.409.411,68 1.248.886,98 2.160.524,69
53 781,51 4.395,85 3.435.406,08 1.243.968,13 2.191.437,95
54 781,51 4.196,60 3.279.689,54 1.173.705,19 2.105.984,35
55 781,51 4.154,15 3.246.511,87 1.148.003,49 2.098.508,38
56 781,51 4.359,21 3.406.774,24 1.190.066,82 2.216.707,42
57 781,51 4.364,28 3.410.735,81 1.176.729,43 2.234.006,37
58 781,51 4.276,88 3.342.426,37 1.138.640,05 2.203.786,32
59 781,51 4.348,81 3.398.642,82 1.142.926,58 2.255.716,24
60 781,51 4.289,26 3.352.103,46 1.112.517,88 2.239.585,59
61 781,51 4.108,27 3.210.661,25 1.051.346,04 2.159.315,21
62 781,51 4.061,13 3.173.814,75 1.025.121,41 2.148.693,34
63 781,51 4.165,80 3.255.615,17 1.036.922,06 2.218.693,11
64 781,51 4.304,16 3.363.749,78 1.056.157,06 2.307.592,73
65 781,51 4.192,56 3.276.533,56 1.013.862,58 2.262.670,98
66 781,51 4.307,65 3.366.478,59 1.026.273,33 2.340.205,26
67 781,51 4.303,81 3.363.477,51 1.009.848,93 2.353.628,58
68 781,51 4.146,32 3.240.395,75 957.853,83 2.282.541,92
69 781,51 4.325,14 3.380.145,17 983.369,60 2.396.775,57
70 781,51 4.386,67 3.428.233,97 981.235,05 2.446.998,92
71 781,51 4.462,13 3.487.207,23 981.603,50 2.505.603,73
72 781,51 4.289,24 3.352.091,83 927.593,74 2.424.498,09
73 781,51 4.258,71 3.328.226,37 905.021,67 2.423.204,70
74 781,51 4.127,50 3.225.687,50 861.560,28 2.364.127,23
75 781,51 4.007,03 3.131.540,22 821.189,81 2.310.350,41
76 781,51 3.825,47 2.989.645,28 769.349,52 2.220.295,77
77 781,51 3.827,93 2.991.569,92 755.107,36 2.236.462,56
78 781,51 3.578,50 2.796.634,86 692.034,94 2.104.599,92
79 781,51 3.417,29 2.670.646,07 647.527,08 2.023.118,99
80 781,51 3.551,09 2.775.213,02 658.935,00 2.116.278,02
81 781,51 3.680,19 2.876.107,31 668.342,58 2.207.764,73
82 781,51 3.760,41 2.938.803,78 667.947,75 2.270.856,03
83 781,51 3.898,70 3.046.875,63 676.893,64 2.369.982,00
84 781,51 4.179,32 3.266.188,17 708.763,63 2.557.424,54
85 781,51 4.209,10 3.289.457,23 696.727,92 2.592.729,32
86 781,51 4.050,04 3.165.153,44 653.851,05 2.511.302,39
87 781,51 3.852,82 3.011.023,63 606.164,11 2.404.859,52
88 781,51 3.859,05 3.015.893,18 591.166,39 2.424.726,79
89 781,51 4.050,89 3.165.811,69 603.669,42 2.562.142,27
90 781,51 3.961,35 3.095.841,47 573.707,31 2.522.134,16
91 781,51 3.948,04 3.085.440,69 555.105,93 2.530.334,76
92 781,51 3.929,23 3.070.738,85 535.756,33 2.534.982,52
93 781,51 3.801,81 2.971.155,42 502.111,80 2.469.043,62
94 781,51 3.757,50 2.936.527,39 480.072,71 2.456.454,69
95 781,51 3.839,89 3.000.913,00 473.946,92 2.526.966,09
96 781,51 3.816,80 2.982.869,41 454.435,79 2.528.433,62
97 781,51 3.823,48 2.988.093,51 438.430,36 2.549.663,15
98 781,51 3.780,24 2.954.300,50 416.750,56 2.537.549,94
99 781,51 3.875,68 3.028.889,54 410.015,12 2.618.874,41
100 781,51 3.973,71 3.105.498,25 402.574,26 2.702.924,00
101 781,51 3.828,97 2.992.379,32 370.634,03 2.621.745,29
102 781,51 3.878,23 3.030.877,62 357.787,75 2.673.089,87
103 781,51 3.722,51 2.909.179,93 326.402,10 2.582.777,83
104 781,51 3.664,38 2.863.750,55 304.440,16 2.559.310,39
105 781,51 3.625,29 2.833.207,28 284.397,46 2.548.809,81
106 781,51 3.673,03 2.870.511,05 271.012,30 2.599.498,74
107 781,51 3.609,70 2.821.020,28 249.393,71 2.571.626,57
108 781,51 3.610,76 2.821.851,54 232.403,71 2.589.447,83
109 781,51 3.669,02 2.867.379,08 218.699,50 2.648.679,58
110 781,51 3.613,76 2.824.193,64 198.100,72 2.626.092,92
111 781,51 3.681,31 2.876.986,66 184.058,46 2.692.928,20
112 781,51 3.810,77 2.978.160,51 172.039,90 2.806.120,62
113 781,51 3.916,44 3.060.743,07 157.680,37 2.903.062,70
114 781,51 3.921,70 3.064.850,30 138.609,14 2.926.241,16
115 781,51 3.857,50 3.014.682,18 117.247,26 2.897.434,92
116 781,51 3.748,59 2.929.563,25 95.259,82 2.834.303,43
117 781,51 3.694,31 2.887.145,04 75.351,87 2.811.793,17
118 781,51 3.777,81 2.952.399,91 57.981,84 2.894.418,07
119 781,51 3.774,95 2.950.161,65 38.752,80 2.911.408,85
120 781,51 3.948,62 3.085.894,07 20.334,88 3.065.559,19

Caminata aleatoria

# ===== Caminatas representativas para ambos modelos (MBG y AR1) =====

caminatas_y_costos <- function(paths, label, n_meses, S0, amort_USD=NULL) {
  ST  <- paths[n_meses, ]
  q5  <- as.numeric(quantile(ST, 0.05))
  q50 <- as.numeric(quantile(ST, 0.50))
  q95 <- as.numeric(quantile(ST, 0.95))
  i5  <- which.min(abs(ST - q5))
  i50 <- which.min(abs(ST - q50))
  i95 <- which.min(abs(ST - q95))

  TRM_lo <- paths[, i5]
  TRM_md <- paths[, i50]
  TRM_hi <- paths[, i95]

  if (!is.null(amort_USD)) {
    tot_lo <- sum(amort_USD$cuota * TRM_lo)
    tot_md <- sum(amort_USD$cuota * TRM_md)
    tot_hi <- sum(amort_USD$cuota * TRM_hi)

    cat("\n=== ", label, ": Costo total del credito (COP) ===\n", sep = "")
    cat(sprintf("Bajo (p5):    %s\n", fmt0(tot_lo)))
    cat(sprintf("Mediano (p50): %s\n", fmt0(tot_md)))
    cat(sprintf("Alto (p95):   %s\n", fmt0(tot_hi)))
  }

  rng <- range(c(TRM_lo, TRM_md, TRM_hi, S0), na.rm = TRUE); yt <- pretty(rng)
  matplot(
    1:n_meses, cbind(TRM_lo, TRM_md, TRM_hi),
    type = "l", lty = 1, lwd = 2,
    col  = c("darkgreen","black","firebrick"),
    xlab = "Mes del credito", ylab = "TRM simulada (COP/USD)",
    main = paste(label, "-- Caminatas (p5 / p50 / p95)"), yaxt = "n"
  )
  abline(h = S0, col = "dodgerblue4", lwd = 2, lty = 2)
  legend("topleft", bty = "n",
         legend = c("Baja (p5)","Mediana (p50)","Alta (p95)","TRM actual S0"),
         col    = c("darkgreen","black","firebrick","dodgerblue4"),
         lty    = c(1,1,1,2), lwd = c(2,2,2,2))
  axis(2, at = yt, labels = fmt_kb(yt, 0), las = 1)

  invisible(list(TRM_lo = TRM_lo, TRM_md = TRM_md, TRM_hi = TRM_hi))
}

# === Graficos y costos para cada modelo ===
res_mbg <- caminatas_y_costos(paths_mbg, "MBG (GBM)", n_meses, S0, amort_USD)
## 
## === MBG (GBM): Costo total del credito (COP) ===
## Bajo (p5):    318.782.148
## Mediano (p50): 363.506.592
## Alto (p95):   622.102.596

res_ar1 <- caminatas_y_costos(paths_ar1, "AR(1) media-revertente", n_meses, S0, amort_USD)
## 
## === AR(1) media-revertente: Costo total del credito (COP) ===
## Bajo (p5):    350.520.771
## Mediano (p50): 382.802.735
## Alto (p95):   384.288.598

1.5. Análisis sobre el comportamiento del crédito transformado en pesos.

En dólares, la cuota mensual es fija (USD 781,51, sistema francés). Sin embargo, al convertirla a COP mediante la TRM simulada, el flujo en pesos deja de ser plano y adquiere una trayectoria creciente y volátil.

  1. Escenario de TRM baja (p5):
  • Cuotas en COP más baratas y estables, entre COP 2,8 y 3,2 millones.
  • Intereses en COP caen rápidamente y la deuda se liquida en pesos sin grandes saltos.
  1. Escenario de TRM alta (p95):
  • Cuotas en COP mucho más altas, llegando en los últimos años a COP 5,0–6,0 millones mensuales.
  • Los intereses en COP se mantienen altos durante más tiempo y el saldo en pesos puede aumentar temporalmente pese a la amortización en dólares.
  1. Escenario intermedio (TRM mediana, p50):
  • Escenario más probable según la simulación.
  • Cuotas que inician en COP 3,0 millones y terminan en COP 3,9–4,0 millones, con trayectoria creciente pero controlada.

Esto implica que, aun cuando el pasivo en USD se reduce mes a mes, en pesos el costo de servicio de deuda tiende a subir porque la depreciación del COP amplifica el valor de cada dólar. Dinámica de la tabla de amortización en COP

  1. la cuota en USD es constante, toda la variación en pesos proviene de la TRM. Esto explica por qué, en escenarios de depreciación, la serie de cuotas en COP muestra una pendiente positiva.

  2. Los intereses en USD bajan con el tiempo (sistema francés), pero al pasarlos a COP: siguen una senda descendente normal y En periodos de subidas fuertes de la TRM (meses 40–50 o 100–110), los intereses en COP pueden dejar de caer e incluso repuntar, ya que cada dólar de interés vale más en pesos.

  3. En USD la amortización crece gradualmente. En COP, la TRM amplifica ese crecimiento: cada dólar de capital abonado vale más pesos cuando el COP se deprecia. Por eso, la pendiente del capital amortizado en COP es mucho más pronunciada que en USD.

  4. el saldo en USD disminuye de manera predecible, en pesos puede subir temporalmente si la depreciación de la TRM es mayor al abono de capital.

2. Proceso de futuro

2.1 Cargar histórico del futuro (BVC), calcular retornos y desviación mensual

library(readxl); library(dplyr)
ruta_futuros <- params$ruta_futuros

futs <- read_excel(ruta_futuros, sheet = 1) |>
  rename_with(tolower) |>
  transmute(
    fecha    = as.Date(fecha),
    contrato = as.character(contrato),
    F_cierre = as.numeric(precio_cierre)
  ) |>
  arrange(fecha)

library(readxl); library(dplyr); library(tidyr)

ruta_futuros <- params$ruta_futuros
futs <- readxl::read_excel(ruta_futuros, sheet = 1) |>
  rename_with(tolower) |>
  transmute(
    fecha = as.Date(fecha),
    contrato = as.character(contrato),
    F_cierre = as.numeric(precio_cierre)
  ) |>
  arrange(fecha)
sheet_name   <- 1

futs <- read_excel(ruta_futuros, sheet = sheet_name) |>
  rename_with(tolower) |>
  transmute(
    fecha    = as.Date(fecha),
    contrato = as.character(contrato),
    F_cierre = as.numeric(precio_cierre)
  ) |>
  arrange(fecha)

stopifnot(all(is.finite(futs$F_cierre)), all(!is.na(futs$fecha)))

futs_m <- futs |>
  mutate(mes = as.Date(paste0(format(fecha, "%Y-%m"), "-01"))) |>
  group_by(mes) |>
  summarise(F = mean(F_cierre, na.rm = TRUE), .groups="drop") |>
  arrange(mes)

## --- Retornos log mensuales del FUTURO ---
ret_f_cc  <- diff(log(futs_m$F))
mu_f_m    <- mean(ret_f_cc, na.rm=TRUE)       # media mensual del FUTURO
sigma_f_m <- sd(ret_f_cc,   na.rm=TRUE)       # desviación mensual del FUTURO

cat(sprintf("Futuro: media mensual (log): %0.6f | sigma mensual: %0.6f\n", mu_f_m, sigma_f_m))
## Futuro: media mensual (log): -0.013817 | sigma mensual: 0.025294

2.2 Cálculo del precio teórico del futuro (solo para el primer mes)

if (!exists("mu_f_m") || !exists("sigma_f_m") || !exists("futs_m")) {
  stop("Primero corre el chunk 2.1 (carga de futuros y cálculo de mu_f_m y sigma_f_m).")
}

if (!exists("S0")) {
  # intenta tomarlo de tu serie TRM mensual de la Parte 1
  if (exists("trm_monthly")) {
    S0 <- dplyr::last(trm_monthly$TRM)
  } else {
    # como último recurso, usa el último precio del futuro como proxy
    S0 <- dplyr::last(futs_m$F)
    message("S0 no estaba en memoria; usando el último precio del futuro como proxy.")
  }
}
stopifnot(is.finite(S0), is.numeric(S0))

r_COP_annual <- 0.13   # p.ej., tasa local anual (CDT/DTF/TY) - SUPUESTO
r_USD_annual <- 0.08   # p.ej., tasa crédito USD (vehicular) - SUPUESTO
tau_years    <- 1/12   # 1 mes

# Fórmula de paridad (cost of carry)
F0_teorico <- S0 * ((1 + r_COP_annual * tau_years) / (1 + r_USD_annual * tau_years))

cat(sprintf("F0 teorico (1 mes): %s COP/USD\n",
            format(round(F0_teorico, 2), big.mark=".", decimal.mark=",")))
## F0 teorico (1 mes): 3.968,27 COP/USD

2.2. Simulación MBG mensual del futuro (de año 6 a año 10)

Se simuló el precio futuro de la TRM con Movimiento Browniano Geométrico (MBG), evaluando trayectorias p05, p50 y p95. La mediana (p50) es consistente con depreciación moderada; p95 captura eventos adversos (devaluación fuerte); y p05 representa apreciación relativa del COP. Estas bandas cuantifican el riesgo sobre cuotas y saldos en COP, y motivan la cobertura (Bancolombia, 2025; Research, 2025).

set.seed(1234)

n_meses_hedge <- 60      # meses 61..120
N_paths_f     <- 5000
dt <- 1                  # mensual

## Punto de arranque: F0_teorico (del mes 61)
Zf   <- matrix(rnorm(n_meses_hedge * N_paths_f), nrow = n_meses_hedge, ncol = N_paths_f)
incr <- (mu_f_m - 0.5 * sigma_f_m^2) * dt + sigma_f_m * sqrt(dt) * Zf
paths_fut <- F0_teorico * exp(apply(incr, 2, cumsum))   # matriz 60 x N

## Caminatas representativas (p5/p50/p95 en t=60)
ST  <- paths_fut[n_meses_hedge, ]
q5  <- as.numeric(quantile(ST, 0.05))
q50 <- as.numeric(quantile(ST, 0.50))
q95 <- as.numeric(quantile(ST, 0.95))
i5  <- which.min(abs(ST - q5))
i50 <- which.min(abs(ST - q50))
i95 <- which.min(abs(ST - q95))

F_lo <- paths_fut[, i5]   # p5
F_md <- paths_fut[, i50]  # mediana
F_hi <- paths_fut[, i95]  # p95

## Gráfico de las 3 caminatas
rng <- range(c(F_lo, F_md, F_hi, F0_teorico))
yt  <- pretty(rng)
matplot(1:n_meses_hedge, cbind(F_lo, F_md, F_hi), type="l", lty=1, lwd=2,
        col=c("darkgreen","black","firebrick"),
        xlab="Mes del hedge (61-120)", ylab="Precio Futuro (COP/USD)",
        main="Futuro TRM - MBG (p5 / p50 / p95)", yaxt="n")
abline(h = F0_teorico, col="dodgerblue4", lwd=2, lty=2)
legend("topleft", bty="n", legend=c("Baja (p5)", "Mediana (p50)", "Alta (p95)", "F0 teorico"),
       col=c("darkgreen","black","firebrick","dodgerblue4"), lty=c(1,1,1,2), lwd=c(2,2,2,2))
axis(2, at=yt, labels=format(yt, big.mark=".", decimal.mark=","), las=1)

2.3 Criterios de exposición, margen inicial y mantenimiento (parámetros)

Se determinó la cobertura del 75 % de la cuota mensual en USD con contratos TRM (nominal 1.000 USD). Se calcularon márgenes inicial 10 % y mantenimiento 7 % sobre el nocional en COP y se implementó rollover mensual. Los márgenes exigidos aumentan cuando el precio futuro sube, por lo que se debe planear liquidez ante posibles margin calls. El rollover puede implicar costos (contango) o beneficios (backwardation); su objetivo es mantener la cobertura activa durante todo el horizonte (Bolsa de Valores de Colombia, 2024; Hull, 2018).

Durante los últimos cuatro años (meses 73–120) se operó una regla simple: posición larga cuando el futuro sube mes a mes y corta cuando cae, coherente con expectativas de mercado (señales EME, petróleo, tasas) (Rodríguez, 2025). Esta gestión dinámica no busca “ganar” con el derivado, sino estabilizar la exposición y suavizar la volatilidad de los pagos en COP

# ---- Normalizador de F_md por si no existe o no tiene 60 datos ----
if (!exists("F_md") || !is.numeric(F_md) || length(F_md) != 60) {
  matriz_fut <- if (exists("paths_fut")) paths_fut else if (exists("paths_credito")) paths_credito else NULL
  stopifnot(!is.null(matriz_fut))
  ST   <- matriz_fut[nrow(matriz_fut), ]
  q50  <- as.numeric(stats::quantile(ST, 0.50))
  i50  <- which.min(abs(ST - q50))
  fm   <- matriz_fut[, i50]
  if (length(fm) == 60) {
    F_md <- fm
  } else if (length(fm) > 60) {
    F_md <- tail(fm, 60)
  } else {
    stop("La matriz de trayectorias del futuro tiene menos de 60 filas.")
  }
}
stopifnot(length(F_md) == 60)

# ---- Parámetros (si no los traes definidos) ----
if (!exists("porc_cobertura"))       porc_cobertura       <- 0.75
if (!exists("nominal_usd_contrato")) nominal_usd_contrato <- 1000   # AJUSTA a la CRCC
if (!exists("pct_margen_inicial"))   pct_margen_inicial   <- 0.10   # AJUSTA a la CRCC
if (!exists("pct_margen_mant"))      pct_margen_mant      <- 0.07   # AJUSTA a la CRCC


if (!exists("amort_USD")) {
  stop("amort_USD no está en el ambiente. Cárgalo desde la Parte 1 o reconstruye antes de 2.4.")
}

idx_hedge  <- 61:120
idx_ult4y  <- 73:120            # últimos 4 años (48 meses dentro de 61..120)
k_ult4y    <- 13:60             # índices relativos dentro de F_md (13..60)

usd_a_cubrir <- amort_USD$cuota[idx_hedge]
n_contratos  <- round((porc_cobertura * usd_a_cubrir) / nominal_usd_contrato)

# ---- Series para la ventana 73–120 ----
F_ult4y           <- F_md[k_ult4y]
n_contratos_ult4y <- n_contratos[k_ult4y]
nocional_COP_ult4y<- F_ult4y * nominal_usd_contrato
m_init_ult4y      <- nocional_COP_ult4y * pct_margen_inicial
m_mant_ult4y      <- nocional_COP_ult4y * pct_margen_mant

tabla_24 <- data.frame(
  mes_hedge      = idx_ult4y,
  n_contratos    = n_contratos_ult4y,
  F_mediana      = round(F_ult4y, 2),
  nocional_COP   = round(nocional_COP_ult4y, 0),
  margen_inicial = round(m_init_ult4y, 0),
  margen_mant    = round(m_mant_ult4y, 0)
)

knitr::kable(
  tabla_24,
  align = 'r',
  caption = "Parámetros de exposición y márgenes — últimos 4 años (meses 73–120)"
)
Parámetros de exposición y márgenes — últimos 4 años (meses 73–120)
mes_hedge n_contratos F_mediana nocional_COP margen_inicial margen_mant
73 1 3605,90 3605896 360590 252413
74 1 3576,20 3576198 357620 250334
75 1 3710,61 3710607 371061 259742
76 1 3674,17 3674166 367417 257192
77 1 3590,06 3590056 359006 251304
78 1 3584,37 3584366 358437 250906
79 1 3661,43 3661431 366143 256300
80 1 3761,34 3761343 376134 263294
81 1 3540,68 3540676 354068 247847
82 1 3541,24 3541236 354124 247887
83 1 3513,93 3513933 351393 245975
84 1 3654,97 3654965 365497 255848
85 1 3452,60 3452603 345260 241682
86 1 3386,08 3386076 338608 237025
87 1 3362,15 3362149 336215 235350
88 1 3324,54 3324544 332454 232718
89 1 3304,29 3304295 330429 231301
90 1 3154,22 3154224 315422 220796
91 1 3095,37 3095373 309537 216676
92 1 2965,29 2965287 296529 207570
93 1 2807,26 2807259 280726 196508
94 1 2722,46 2722456 272246 190572
95 1 2731,71 2731712 273171 191220
96 1 2622,53 2622531 262253 183577
97 1 2487,21 2487211 248721 174105
98 1 2554,55 2554551 255455 178819
99 1 2415,92 2415924 241592 169115
100 1 2372,27 2372275 237227 166059
101 1 2295,62 2295624 229562 160694
102 1 2245,06 2245058 224506 157154
103 1 2190,29 2190294 219029 153321
104 1 2139,77 2139769 213977 149784
105 1 2149,80 2149797 214980 150486
106 1 2052,82 2052820 205282 143697
107 1 2042,54 2042540 204254 142978
108 1 1965,82 1965824 196582 137608
109 1 1900,69 1900693 190069 133049
110 1 1875,57 1875574 187557 131290
111 1 1873,91 1873908 187391 131174
112 1 1843,31 1843313 184331 129032
113 1 1864,03 1864032 186403 130482
114 1 1854,73 1854733 185473 129831
115 1 1817,59 1817590 181759 127231
116 1 1863,49 1863491 186349 130444
117 1 1800,06 1800062 180006 126004
118 1 1814,74 1814743 181474 127032
119 1 1736,86 1736858 173686 121580
120 1 1704,39 1704389 170439 119307

2.4 Flujo de caja de margen (últimos 4 años) con rollover mensual

Durante los últimos 4 años (meses 73–120) se simularon posiciones dinámicas en futuros TRM con rollover mensual, cambiando de posición entre largo y corto según la expectativa de mercado. El flujo de margen resultante muestra que las llamadas de margen fueron frecuentes en escenarios de alta volatilidad, lo cual evidencia que la gestión activa de posiciones es fundamental para evitar incumplimientos por falta de liquidez. Este comportamiento es consistente con la realidad de los mercados de futuros, donde el apalancamiento amplifica tanto las ganancias como las pérdidas (Hull, 2018).

El flujo de caja de margen surge del ajuste diario a valor de mercado (mark-to-market) de los contratos:

Cuando la TRM subió, la posición larga generó ingresos de margen que compensaron el mayor valor en pesos de las cuotas del crédito.

Cuando la TRM bajó, la posición requirió aportes adicionales de margen (margin calls), incrementando las necesidades de liquidez del deudor.

La simulación mostró que en los primeros años de cobertura (años 6–7) el flujo de margen fue relativamente estable, con variaciones moderadas acordes a la volatilidad histórica de la TRM. Sin embargo, en los años 8–10, donde la simulación proyectó una senda ascendente de la TRM, las posiciones largas acumularon ganancias netas de margen con mayor frecuencia. Esto evidencia que el derivado cumplió su función de compensar el encarecimiento de las cuotas del crédito en COP, contribuyendo a estabilizar la carga financiera.

Rollover y cambios de posición

El rollover no altera la exposición total, pero obliga a evaluar la expectativa de mercado en cada vencimiento:

Cuando el consenso de mercado y la simulación MBG anticipaban alzas de la TRM, se mantuvo la posición larga en futuros, protegiendo al deudor frente al mayor costo en pesos de las cuotas.

En meses donde se proyectaba estabilidad o corrección a la baja, la posición se ajustó reduciendo contratos o incluso cambiando a corta, evitando pérdidas innecesarias de margen.

El flujo de caja de margen y la estrategia de rollover aplicada sobre los futuros TRM permitieron mitigar el riesgo cambiario de los pagos en COP asociados al crédito en USD. En conjunto, esta estrategia aportó mayor estabilidad al flujo de caja del deudor durante los últimos cuatro años del crédito, cumpliendo el objetivo central de la cobertura cambiaria.

# Rollover mensual (se recalculan márgenes con el nocional del mes).
# Cambio de posición según expectativa: long si F_t > F_{t-1}, short si F_t < F_{t-1}.

stopifnot(exists("F_md"), length(F_md)==60)
stopifnot(exists("nominal_usd_contrato"), exists("pct_margen_inicial"), exists("pct_margen_mant"))
stopifnot(exists("n_contratos"))

idx_ult4y   <- 73:120
k_ult4y     <- 13:60

F_ult4y           <- F_md[k_ult4y]
n_contratos_ult4y <- n_contratos[k_ult4y]
nocional_COP_ult4y<- F_ult4y * nominal_usd_contrato
m_init_ult4y      <- nocional_COP_ult4y * pct_margen_inicial
m_mant_ult4y      <- nocional_COP_ult4y * pct_margen_mant

# Si F_t > F_{t-1} => LONG (signo +1); si F_t < F_{t-1} => SHORT (signo -1)
signo_pos <- rep(1, length(F_ult4y))
dfF <- c(0, diff(F_ult4y))
signo_pos[dfF < 0] <- -1   # short si cae
# Nota: el primer mes (73) se deja +1 por simplicidad; puedes fijarlo manualmente si deseas.

# --- MTM mensual con posición activa ---
Q_mes   <- nominal_usd_contrato * n_contratos_ult4y * signo_pos
mtm_ult4y <- dfF * Q_mes     # payoff largo/corto: (F_t - F_{t-1}) * Q * signo

# --- Cuenta de margen con llamadas (margin call) y rollover mensual ---
saldo   <- numeric(length(F_ult4y))
calls   <- numeric(length(F_ult4y))

# Mes inicial: se deposita margen inicial
saldo[1] <- m_init_ult4y[1]
calls[1] <- 0

for (t in 2:length(F_ult4y)) {
  # P&L del mes
  saldo[t] <- saldo[t-1] + mtm_ult4y[t]

  # Si saldo cae por debajo del mantenimiento, se hace margin call hasta margen inicial
  if (saldo[t] < m_mant_ult4y[t]) {
    calls[t] <- m_init_ult4y[t] - saldo[t]
    saldo[t] <- saldo[t] + calls[t]
  } else {
    calls[t] <- 0
  }
}

flujo_margen_4y <- data.frame(
  mes_calendario = idx_ult4y,
  F              = round(F_ult4y, 2),
  n_contratos    = n_contratos_ult4y,
  signo_pos      = ifelse(signo_pos>0,"LONG","SHORT"),
  nocional_COP   = round(nocional_COP_ult4y, 0),
  mtm            = round(mtm_ult4y, 0),
  margin_call    = round(calls, 0),
  saldo_margen   = round(saldo, 0)
)

knitr::kable(
  flujo_margen_4y,
  align = 'r',
  caption = "Flujo de caja de margen — últimos 4 años con rollover mensual y cambio de posición"
)
Flujo de caja de margen — últimos 4 años con rollover mensual y cambio de posición
mes_calendario F n_contratos signo_pos nocional_COP mtm margin_call saldo_margen
73 3605,90 1 LONG 3605896 0 0 360590
74 3576,20 1 SHORT 3576198 29698 0 390288
75 3710,61 1 LONG 3710607 134409 0 524697
76 3674,17 1 SHORT 3674166 36441 0 561139
77 3590,06 1 SHORT 3590056 84109 0 645248
78 3584,37 1 SHORT 3584366 5690 0 650938
79 3661,43 1 LONG 3661431 77065 0 728002
80 3761,34 1 LONG 3761343 99912 0 827915
81 3540,68 1 SHORT 3540676 220667 0 1048581
82 3541,24 1 LONG 3541236 560 0 1049141
83 3513,93 1 SHORT 3513933 27303 0 1076444
84 3654,97 1 LONG 3654965 141032 0 1217476
85 3452,60 1 SHORT 3452603 202362 0 1419838
86 3386,08 1 SHORT 3386076 66527 0 1486365
87 3362,15 1 SHORT 3362149 23926 0 1510292
88 3324,54 1 SHORT 3324544 37605 0 1547897
89 3304,29 1 SHORT 3304295 20249 0 1568146
90 3154,22 1 SHORT 3154224 150071 0 1718217
91 3095,37 1 SHORT 3095373 58851 0 1777068
92 2965,29 1 SHORT 2965287 130086 0 1907154
93 2807,26 1 SHORT 2807259 158028 0 2065182
94 2722,46 1 SHORT 2722456 84802 0 2149985
95 2731,71 1 LONG 2731712 9256 0 2159241
96 2622,53 1 SHORT 2622531 109182 0 2268423
97 2487,21 1 SHORT 2487211 135319 0 2403742
98 2554,55 1 LONG 2554551 67339 0 2471081
99 2415,92 1 SHORT 2415924 138626 0 2609707
100 2372,27 1 SHORT 2372275 43650 0 2653357
101 2295,62 1 SHORT 2295624 76651 0 2730008
102 2245,06 1 SHORT 2245058 50565 0 2780574
103 2190,29 1 SHORT 2190294 54765 0 2835338
104 2139,77 1 SHORT 2139769 50524 0 2885862
105 2149,80 1 LONG 2149797 10028 0 2895890
106 2052,82 1 SHORT 2052820 96977 0 2992868
107 2042,54 1 SHORT 2042540 10280 0 3003147
108 1965,82 1 SHORT 1965824 76717 0 3079864
109 1900,69 1 SHORT 1900693 65131 0 3144995
110 1875,57 1 SHORT 1875574 25119 0 3170114
111 1873,91 1 SHORT 1873908 1666 0 3171780
112 1843,31 1 SHORT 1843313 30594 0 3202374
113 1864,03 1 LONG 1864032 20718 0 3223093
114 1854,73 1 SHORT 1854733 9299 0 3232391
115 1817,59 1 SHORT 1817590 37143 0 3269534
116 1863,49 1 LONG 1863491 45900 0 3315435
117 1800,06 1 SHORT 1800062 63428 0 3378863
118 1814,74 1 LONG 1814743 14680 0 3393543
119 1736,86 1 SHORT 1736858 77884 0 3471427
120 1704,39 1 SHORT 1704389 32469 0 3503896
# --- Resumen útil para el análisis ---
resumen_25 <- data.frame(
  total_MTM          = round(sum(mtm_ult4y), 0),
  total_margin_calls = round(sum(calls), 0),
  saldo_final        = round(tail(saldo, 1), 0),
  n_LONG_meses       = sum(signo_pos > 0),
  n_SHORT_meses      = sum(signo_pos < 0)
)
knitr::kable(resumen_25, align='r', caption="Resumen flujo de margen (48 meses)")
Resumen flujo de margen (48 meses)
total_MTM total_margin_calls saldo_final n_LONG_meses n_SHORT_meses
3143307 0 3503896 12 36
# --- dejar listos los vectores que usará 2.5 ---
mtm   <- mtm_ult4y          # MTM de los últimos 48 meses (73..120)
calls <- calls              # (ya existen; esto solo los hace visibles para 2.5)

# chequeo rápido (opcional)
cat("Suma MTM 4y:", sum(mtm, na.rm=TRUE),
    " | Suma calls 4y:", sum(calls, na.rm=TRUE), "\n")
## Suma MTM 4y: 3143307  | Suma calls 4y: 0

2.5 Comparación del flujo total sobre que tanto se cubre los precios del crédito vs el futuro.

El costo del crédito convertido a COP crece cuando la TRM sube; al sumarle el resultado del hedge (MTM + llamadas de margen), se observa que las ganancias del derivado compensan parte del encarecimiento de las cuotas en pesos.

-Sin cobertura: exposición total a TRM; fuerte volatilidad del flujo en COP (p95 ≈ 5,0–6,0 MM COP).

-Con cobertura (75 %): el flujo neto (crédito + hedge) se acerca al escenario base; en p95, el hedge amortigua la presión; en p05, puede haber pérdidas en futuro (costo de seguro). Cubrir 75 % equilibra protección y costo operativo: evita la rigidez de cubrir 100 % y reduce la vulnerabilidad de no cubrir (Banco de la República, 2025a; Bancolombia, 2025; Research, 2025).

# Requisitos mínimos
stopifnot(exists("amort_USD"))
stopifnot(exists("F_md") && length(F_md) >= 60)

# Ventana 4 años: posiciones 13..60 dentro de 61..120 -> meses calendario 73..120
pos_4y <- 13:60
F_4y   <- F_md[pos_4y]

# Traer MTM y calls desde 2.4 (si venían con 60, recortar a 48)
if (!exists("mtm"))   stop("No encuentro 'mtm' del 2.4. Ejecuta primero el chunk 2.4.")
if (!exists("calls")) stop("No encuentro 'calls' del 2.4. Ejecuta primero el chunk 2.4.")
if (length(mtm)   == 60) mtm   <- mtm  [pos_4y]
if (length(calls) == 60) calls <- calls[pos_4y]
stopifnot(length(mtm)==48, length(calls)==48)


# Cuotas USD del crédito en los mismos meses calendario 73..120
idx_cal_4y   <- 60 + pos_4y                 # 73..120
cuota_USD_4y <- amort_USD$cuota[idx_cal_4y]

# Nº de contratos para cubrir el 75% de la cuota USD
n_c_4y <- round((porc_cobertura * cuota_USD_4y) / nominal_usd_contrato)

# Nocional y márgenes (COP) en la ventana 4y
valor_nocional_COP_4y <- F_4y * nominal_usd_contrato
m_init_4y <- valor_nocional_COP_4y * pct_margen_inicial
m_mant_4y <- valor_nocional_COP_4y * pct_margen_mant

# Traer MTM y margin calls si ya los tienes de 2.5; si no, asume 0 para poder comparar
if (exists("mtm")) {
  if (length(mtm) == 60) mtm <- mtm[pos_4y]
} else mtm <- rep(0, length(pos_4y))

if (exists("calls")) {
  if (length(calls) == 60) calls <- calls[pos_4y]
} else calls <- rep(0, length(pos_4y))

stopifnot(length(mtm) == 48, length(calls) == 48)

# Costo/beneficio total del hedge (MTM + calls) en COP
costo_hedge_COP_4y <- sum(mtm + calls, na.rm = TRUE)  # >0: entrada de caja para el hedger

# Costo del crédito en COP (solo ventana 4y)
credito_COP_4y <- cuota_USD_4y * F_4y

# Resumen para la tabla
resumen_4y <- data.frame(
  concepto = c("Total cuotas crédito (COP)", "Resultado hedge (COP)"),
  valor    = round(c(sum(credito_COP_4y, na.rm = TRUE), costo_hedge_COP_4y), 0)
)

knitr::kable(resumen_4y, align = 'r',
             caption = "Comparación 4 años: crédito vs hedge (meses 73–120)")
Comparación 4 años: crédito vs hedge (meses 73–120)
concepto valor
Total cuotas crédito (COP) 100974711
Resultado hedge (COP) 3143307

El costo del crédito convertido a COP crece cuando la TRM sube; al sumarle el resultado del hedge (MTM + llamadas de margen), se observa que las ganancias del derivado compensan parte del encarecimiento de las cuotas en pesos.

Sin cobertura: exposición total a TRM; fuerte volatilidad del flujo en COP (p95 ≈ 5,0–6,0 MM COP).

Con cobertura (75 %): el flujo neto (crédito + hedge) se acerca al escenario base; en p95, el hedge amortigua la presión; en p05, puede haber pérdidas en futuro (costo de seguro). Cubrir 75 % equilibra protección y costo operativo: evita la rigidez de cubrir 100 % y reduce la vulnerabilidad de no cubrir (Banco de la República, 2025a; Bancolombia, 2025; Research, 2025).

Conclusiones

El laboratorio integra simulación estocástica y cobertura con derivados para gestionar el riesgo cambiario de un crédito en USD. Bajo expectativas de depreciación moderada, la cobertura con futuros TRM estabiliza flujos en COP y traslada el riesgo al mercado de derivados, a cambio de requerimientos de margen y posibles costos de rollover. Desde ingeniería financiera, una cobertura parcial (75 %) ofrece un compromiso razonable entre robustez y costo, siempre con disciplina operativa y monitoreo de mercado (Banco de la República, 2025a; Hull, 2018).

Referencias

Banco de la República. (2025a). Encuesta de Expectativas de Mercado - Agosto 2025. https://www.banrep.gov.co/es/estadisticas/encuesta-expectativas.
Banco de la República. (2025b). Tasa Representativa del Mercado (TRM). https://www.banrep.gov.co/es/estadisticas/trm.
Bancolombia. (2025). Proyecciones económicas 2025. https://www.bancolombia.com/.
Bank, W. (2025). Commodity Markets Outlook, 2025. https://www.worldbank.org/.
Bolsa de Valores de Colombia. (2024). Futuros sobre la Tasa Representativa del Mercado (TRM). https://www.bvc.com.co/mercado/futuros-trm.
Colombia, S. F. de. (2025a). Informe de tasas de interés de créditos de consumo. https://www.superfinanciera.gov.co/.
Colombia, S. F. de. (2025b). Tasa Representativa del Mercado (TRM). https://www.superfinanciera.gov.co/.
Economic, & (EBC), B. C. (2025). Proyecciones del tipo de cambio en Colombia 2025. https://www.ebc.com/.
(EIA), E. I. A. (2025). Short-Term Energy Outlook 2025. https://www.eia.gov/.
Hull, J. C. (2018). Options, Futures, and Other Derivatives (10th ed.). Pearson.
República, B. de la. (2025a). Encuesta Mensual de Expectativas (EME). https://www.banrep.gov.co/es/estadisticas/encuesta-expectativas.
República, B. de la. (2025b). Serie histórica de la TRM. https://www.banrep.gov.co/.
Research, B. (2025). Situación Colombia Junio 2025. https://www.bbvaresearch.com/.
Reserve, F. (2025). Monetary Policy Report 2025. https://www.federalreserve.gov/.
Rodríguez, D. E. (2025). Notas de clase: Derivados Financieros. Apuntes del curso, ITM Medellín.
TradersUnion. (2025). USD/COP Forecast 2025. https://tradersunion.com/.
U.S. Bank. (2025). Auto Loans 2025. https://www.usbank.com/.