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 tomó la decisión de estructurar el financiamiento a través de un crédito vehicular en el exterior. Después de revisar diferentes alternativas de entidades financieras en Estados Unidos, se seleccionó U.S. Bank como entidad de referencia. La elección se fundamenta en que este banco ofrece una de las tasas más competitivas del mercado estadounidense en préstamos vehiculares, con un promedio cercano al 7 % anual (APR) (U.S. Bank, 2025), lo cual resulta sustancialmente inferior a las tasas que actualmente ofrecen los bancos colombianos para créditos similares, que se ubican alrededor del 14–16 % anual (Superintendencia Financiera de Colombia, 2025a). Por lo tanto, se optó por una tasa anual efectiva del 7,96 %, la cual refleja de manera más precisa el costo financiero del crédito en dólares bajo las condiciones actuales de mercado (U.S. Bank, 2025).

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) es el indicador que refleja el número de pesos colombianos que se requieren para adquirir un dólar estadounidense. Es calculada y certificada diariamente por la Superintendencia Financiera de Colombia (SFC) con base en las operaciones de compra y venta de divisas realizadas en el mercado cambiario colombiano, mientras que el Banco de la República (BanRep) la difunde como información oficial (Banco de la República, 2025b; Superintendencia Financiera de Colombia, 2025b).

La TRM constituye una variable macroeconómica de alta relevancia porque afecta de manera directa los precios internos, la balanza comercial y el poder adquisitivo en moneda extranjera. Un aumento de la TRM (depreciación del peso) encarece las importaciones, eleva los costos de insumos para sectores dependientes de bienes externos y presiona al alza la inflación. Por el contrario, una TRM más baja (apreciación del peso) beneficia a los importadores y a los consumidores, pero puede afectar la competitividad de las exportaciones (Banco de la República, 2025c).

Expectativas de la TRM

De acuerdo con la Encuesta de Expectativas de Mercado (EME) publicada por el Banco de la República, los analistas proyectan que la TRM se ubique en un rango entre COP 4.100 y COP 4.250/USD a 12 meses (Banco de la República, 2025a). Por su parte, informes privados como los de BBVA Research advierten que el tipo de cambio se mantendrá presionado por factores fiscales y externos, aunque sin ofrecer una proyección puntual (BBVA Research, 2025). Bancolombia señala, en cambio, una expectativa de estabilidad relativa con un promedio de TRM cercano a COP 4.250/USD hacia el cierre del año (Bancolombia, 2025).

En conclusión, se proyecta que la Tasa Representativa del Mercado (TRM) se ubique en un rango superior al actual, entre 4.200 y 4.300 COP/USD durante el próximo año, lo que implica una depreciación del peso colombiano frente al dólar estadounidense. Este escenario constituye una variable crítica para la estabilidad macroeconómica del país, dado que afecta de manera directa diferentes frentes:

-Inflación importada

-Política monetaria

-Exportaciones

-Deuda externa

-Inversión extranjera

En términos generales, aunque la depreciación mejora la competitividad de los sectores exportadores, también encarece el consumo interno, eleva los costos de la deuda externa y aumenta la vulnerabilidad macroeconómica.

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/Documents/DERIVADOS FINANCIEROS/LABORATORIO 1
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)

cat("\n--- MBG: Costo total crédito (COP) ---\n")
## 
## --- MBG: Costo total crédito (COP) ---
cat(sprintf("Bajo (p5):    %s\n", fmt0(tot_mbg_lo)))
## Bajo (p5):    318.782.148
cat(sprintf("Mediano (p50): %s\n", fmt0(tot_mbg_md)))
## Mediano (p50): 363.506.592
cat(sprintf("Alto (p95):   %s\n", fmt0(tot_mbg_hi)))
## Alto (p95):   622.102.596
# Gráfico MBG
rng <- range(c(TRM_mbg_lo, TRM_mbg_md, TRM_mbg_hi, S0))
yt  <- pretty(rng)
matplot(1:n_meses, cbind(TRM_mbg_lo, TRM_mbg_md, TRM_mbg_hi),
        type="l", lty=1, lwd=2, col=c("darkgreen","black","firebrick"),
        xlab="Mes del crédito", ylab="TRM simulada (COP/USD)",
        main="MBG (GBM): 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)

# 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)
cat("\n--- AR(1): Costo total crédito (COP) ---\n")
## 
## --- AR(1): Costo total crédito (COP) ---
cat(sprintf("Bajo (p5):    %s\n", fmt0(tot_ar1_lo)))
## Bajo (p5):    350.520.771
cat(sprintf("Mediano (p50): %s\n", fmt0(tot_ar1_md)))
## Mediano (p50): 382.802.735
cat(sprintf("Alto (p95):   %s\n", fmt0(tot_ar1_hi)))
## Alto (p95):   384.288.598
# Gráfico AR(1)
rng <- range(c(TRM_ar1_lo, TRM_ar1_md, TRM_ar1_hi, S0))
yt  <- pretty(rng)
matplot(1:n_meses, cbind(TRM_ar1_lo, TRM_ar1_md, TRM_ar1_hi),
        type="l", lty=1, lwd=2, col=c("darkgreen","black","firebrick"),
        xlab="Mes del crédito", ylab="TRM simulada (COP/USD)",
        main="AR(1): 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)

# 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.

Cuando las cuotas en USD se convierten a pesos con la TRM simulada, el patrón se distorsiona: • Con la TRM mediana (p50), las cuotas en COP arrancan en torno a $3,07 millones y cierran cerca de $3,95 millones. • Se observa que en los primeros años las cuotas tienden a ser estables o incluso más bajas (alivio transitorio), pero hacia la segunda mitad del crédito, cuando la TRM sube, las cuotas en pesos aumentan con fuerza.

En la tabla de amortización en COP: • Los intereses_COP tienden a descender en el tiempo, pero el efecto de la TRM hace que este descenso se ralentice o incluso se revierta localmente cuando la tasa de cambio sube (ejemplo: meses 40–50 y 100–110). • La amortización_COP crece más rápido que en USD, pues la TRM amplifica el componente de capital al alza.

Escenarios de TRM 1. Escenario de TRM baja (p5) Cuotas en pesos más baratas, estables en un rango de $2,8–3,2 millones. 2. Escenario de TRM alta (p95) Cuotas en pesos significativamente más altas, llegando en los últimos años a $5,0–6,0 millones por mes. 3. Escenario intermedio – TRM mediana (p50) Escenario más probable. Cuotas inician cerca de $3,0 millones y cierran en $3,9–4,0 millones, con una trayectoria creciente pero controlada.

En conclusión, el análisis del crédito recreado en COP confirma que, aunque la obligación en USD es estable y predecible, su costo en pesos depende fuertemente de la evolución de la TRM.

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)

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)

# ---- 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

En los últimos cuatro años del crédito (meses 61–120), se implementó un esquema de cobertura con futuros de TRM (TRMZ25F, TRMV25F, TRXV25F) para proteger el 75% de la exposición en dólares. Dado que los contratos de futuros tienen vencimientos de corto plazo, fue necesario realizar rollovers mensuales, cerrando la posición en el contrato vigente y abriendo una nueva posición en el contrato del mes siguiente. Este proceso asegura la continuidad de la cobertura durante toda la vida del crédito.

Flujo de margen.

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

• Cuando la TRM subió, la posición larga en futuros 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), aumentando las necesidades de liquidez.

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 que reflejan la volatilidad histórica de la TRM. Sin embargo, en los años 8–10, donde la simulación de la TRM proyectó una senda ascendente, 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.

#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 de las cuotas en pesos.

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

El flujo de caja de margen y la estrategia de rollover aplicados sobre los futuros de TRM permitieron mitigar el riesgo cambiario de los pagos en COP asociados al crédito de la maquinaria amarilla, asegurando mayor estabilidad en el flujo de caja del deudor durante los últimos cuatro años del crédito.

# 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.

Crédito recreado en COP (sin cobertura)

• Con base en la simulación MBG, el costo total del crédito (120 meses) varía: o Escenario bajo (p5): ≈ COP 318,8 millones. o Escenario mediano (p50): ≈ COP 363,5 millones. o Escenario alto (p95): ≈ COP 622,1 millones • Esto refleja que el mismo flujo en USD (cuotas fijas de ≈781,5 USD) se convierte en una carga muy distinta en pesos según la TRM, con riesgo significativo de encarecimiento en escenarios de depreciación fuerte.

#Futuro de TRM (simulación MBG y rollover)

• En la parte de futuros, se implementaron posiciones periódicas con procesos de rollover cada vencimiento.

• Los flujos de caja se reflejan en los márgenes de variación:

o En fases de depreciación de la TRM, las posiciones largas en futuros generan ganancias, que compensan el mayor costo en COP de las cuotas del crédito. o En fases de apreciación, se generan pérdidas de margen, lo cual encarece el flujo, pero coincide con una menor TRM y cuotas más bajas en pesos.

La comparación confirma que:

• El crédito solo expone al deudor a una volatilidad amplia (COP 318M a 622M de costo total).

• El crédito + futuros suaviza esta variabilidad: en escenarios adversos (TRM alta), los futuros actúan como seguro cambiario, reduciendo pérdidas; en escenarios favorables (TRM baja), limitan las ganancias al generar pérdidas de margen.

En consecuencia, la cobertura con futuros resultó beneficiosa para la financiación de la maquinaria amarilla, ya que redujo la exposición al riesgo cambiario y protegió el flujo de caja en escenarios adversos de TRM alta, aun cuando limitó las ventajas en escenarios de TRM baja.

# 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

Referencias

Banco de la República. (2025a). Encuesta de Expectativas de Mercado (EME) — Agosto 2025. https://www.banrep.gov.co
Banco de la República. (2025b). Estadísticas cambiarias: TRM. https://www.banrep.gov.co
Banco de la República. (2025c). Informe de Política Monetaria — Julio 2025. https://www.banrep.gov.co
Bancolombia. (2025). Proyecciones Macroeconómicas Colombia 2025. https://www.grupobancolombia.com
BBVA Research. (2025). Situación Colombia — Junio 2025. https://www.bbvaresearch.com
Superintendencia Financiera de Colombia. (2025a). Reporte de tasas de interés bancario corriente. https://www.superfinanciera.gov.co
Superintendencia Financiera de Colombia. (2025b). Tasa Representativa del Mercado (TRM) — Información y certificación. https://www.superfinanciera.gov.co
U.S. Bank. (2025). Auto Loan Rates - U.S. Bank. https://www.usbank.com