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).
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.
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)).
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
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
## 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
## Media mensual (log-return, 120m): 0.002497
## 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)")
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)")
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 |
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)")
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)")
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 |
# ===== 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
##
## === AR(1) media-revertente: Costo total del credito (COP) ===
## Bajo (p5): 350.520.771
## Mediano (p50): 382.802.735
## Alto (p95): 384.288.598
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.
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
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.
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.
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.
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.
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
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
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)
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)"
)
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 |
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.
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"
)
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)")
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
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)")
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).
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).