Objetivo del ejercicio. Financiar la compra de maquinaria amarilla por $350.000.000 COP mediante un crédito en EE. UU. y evaluar una cobertura con forward de divisas sobre el 75,00% del valor a partir del año 6.
Decisión metodológica. Se modela un crédito equivalente tipo francés en USD con pagos trimestrales a 10 años. Para la cobertura, se implementan 4 forwards anuales (años 6 a 9) y se aplica su tasa a 75% de las cuatro cuotas trimestrales de cada año cubierto. Esta aproximación se explicita porque el enunciado exige “4 forwards de 1 año”.
Variables en español. Todos los objetos, funciones y tablas creadas en el código se nombran en español para que el proyecto quede consistente con tu instrucción.
Bank of America publica que es SBA Preferred Lender y que el programa SBA 504 puede utilizarse para compra de equipos, incluyendo maquinaria de largo plazo, con cuota inicial típica del 10% y plazo de hasta 10 años para equipo (Bank of America 2026). A su vez, un referente público del mercado SBA 504 reportó una tasa fija efectiva de 5,61% para 10 años en marzo de 2026, con financiamiento de hasta 90% y baja cuota inicial (Growth Corp 2026b, 2026a).
Por ello, el informe adopta el siguiente supuesto pedagógico: se aproxima la estructura 504 real (banco + CDC) por un crédito equivalente único en USD, totalmente amortizable, con sistema francés y tasa efectiva anual de 5,61%.
tabla_supuestos <- tibble::tibble(
supuesto = c(
"Valor de la maquinaria",
"Cuota inicial",
"Monto financiado",
"Plazo del crédito",
"Pagos por año",
"Sistema de amortización",
"Tasa anual crédito en USD",
"Cobertura forward sobre el crédito",
"Inicio de cobertura",
"Número de forwards anuales",
"Tasa comercial USD para forward",
"Tasa comercial COP para forward"
),
valor = c(
formatear_moneda_cop(params$monto_maquinaria_cop),
formatear_porcentaje(params$porcentaje_cuota_inicial),
formatear_porcentaje(1 - params$porcentaje_cuota_inicial),
paste(params$plazo_anios_credito, "años"),
params$pagos_por_anio,
"Francés, cuotas trimestrales",
formatear_porcentaje(params$tasa_credito_usd_anual),
formatear_porcentaje(params$porcentaje_cobertura_forward),
paste("Año", params$anio_inicio_cobertura),
params$anios_cobertura,
formatear_porcentaje(params$tasa_comercial_usa_anual),
formatear_porcentaje(params$tasa_comercial_colombia_anual)
)
)
knitr::kable(tabla_supuestos, col.names = c("Supuesto", "Valor"))| Supuesto | Valor |
|---|---|
| Valor de la maquinaria | $350.000.000 COP |
| Cuota inicial | 10,00% |
| Monto financiado | 90,00% |
| Plazo del crédito | 10 años |
| Pagos por año | 4 |
| Sistema de amortización | Francés, cuotas trimestrales |
| Tasa anual crédito en USD | 5,61% |
| Cobertura forward sobre el crédito | 75,00% |
| Inicio de cobertura | Año 6 |
| Número de forwards anuales | 4 |
| Tasa comercial USD para forward | 6,75% |
| Tasa comercial COP para forward | 11,22% |
BBVA Research identifica que la tasa de cambio en Colombia sigue influida por la fortaleza global del dólar, las condiciones financieras internacionales, los precios de materias primas y, a nivel interno, por el déficit fiscal, la cuenta corriente y la percepción de riesgo país. En su escenario base, proyecta un tipo de cambio promedio cercano a COP 3.750 por dólar en 2026 y alrededor de COP 3.817 en 2027, con una trayectoria de depreciación gradual y alta volatilidad (BBVA Research 2026). Por su parte, el Banco de la República reporta una tasa de política monetaria de 10,25% vigente desde el 2 de febrero de 2026 (Banco de la República 2026b). Esa combinación sugiere que el peso podría sostener episodios de volatilidad con sesgo depreciativo si se mantienen las tensiones externas e internas.
serie_spot_diaria <- obtener_serie_spot_usdcop(
fecha_inicio = params$fecha_inicio_historica,
precio_spot_manual_respaldo = params$precio_spot_manual_respaldo
)
serie_spot_mensual <- construir_serie_mensual(serie_spot_diaria)
precio_spot_actual <- dplyr::last(serie_spot_diaria$precio_spot)
fecha_spot_actual <- dplyr::last(serie_spot_diaria$fecha)
retornos_mensuales <- serie_spot_mensual %>%
dplyr::mutate(retorno_log_mensual = c(NA_real_, diff(log(precio_spot)))) %>%
dplyr::filter(!is.na(retorno_log_mensual))
media_mensual_retornos <- mean(retornos_mensuales$retorno_log_mensual)
desviacion_mensual_retornos <- sd(retornos_mensuales$retorno_log_mensual)
exceso_curtosis_retornos <- calcular_exceso_curtosis(retornos_mensuales$retorno_log_mensual)
grados_libertad_t <- estimar_grados_libertad_t(retornos_mensuales$retorno_log_mensual)
forward_teorico_anual_hoy <- precio_spot_actual * ((1 + params$tasa_comercial_colombia_anual) / (1 + params$tasa_comercial_usa_anual))
prima_forward_hoy <- forward_teorico_anual_hoy / precio_spot_actual - 1tabla_variables_mercado <- tibble::tibble(
variable = c(
"Fecha del último spot descargado",
"TRM / spot USD-COP usado en el proyecto",
"Media mensual de retornos logarítmicos",
"Desviación estándar mensual",
"Exceso de curtosis muestral",
"Grados de libertad estimados para T-Student",
"Tasa comercial USD para forward",
"Tasa comercial COP para forward",
"Forward teórico anual hoy",
"Prima forward teórica"
),
valor = c(
as.character(fecha_spot_actual),
formatear_moneda_cop(precio_spot_actual, 2),
formatear_porcentaje(media_mensual_retornos, 4),
formatear_porcentaje(desviacion_mensual_retornos, 4),
round(exceso_curtosis_retornos, 4),
round(grados_libertad_t, 2),
formatear_porcentaje(params$tasa_comercial_usa_anual),
formatear_porcentaje(params$tasa_comercial_colombia_anual),
formatear_moneda_cop(forward_teorico_anual_hoy, 2),
formatear_porcentaje(prima_forward_hoy)
)
)
knitr::kable(tabla_variables_mercado, col.names = c("Variable", "Valor"))| Variable | Valor |
|---|---|
| Fecha del último spot descargado | 2026-03-27 |
| TRM / spot USD-COP usado en el proyecto | $3.670,13 COP |
| Media mensual de retornos logarítmicos | 0,3241% |
| Desviación estándar mensual | 3,7116% |
| Exceso de curtosis muestral | 0.7649 |
| Grados de libertad estimados para T-Student | 11.84 |
| Tasa comercial USD para forward | 6,75% |
| Tasa comercial COP para forward | 11,22% |
| Forward teórico anual hoy | $3.823,81 COP |
| Prima forward teórica | 4,19% |
ggplot(serie_spot_diaria, aes(x = fecha, y = precio_spot)) +
geom_line(linewidth = 0.7) +
labs(
title = "Serie histórica del USD/COP descargada automáticamente",
subtitle = unique(serie_spot_diaria$fuente),
x = "Fecha",
y = "Pesos colombianos por dólar"
) +
scale_y_continuous(labels = scales::label_number(big.mark = ".", decimal.mark = ","))ggplot(retornos_mensuales, aes(x = retorno_log_mensual)) +
geom_histogram(aes(y = after_stat(density)), bins = 35, alpha = 0.7) +
stat_function(
fun = dnorm,
args = list(mean = media_mensual_retornos, sd = desviacion_mensual_retornos),
linewidth = 1
) +
labs(
title = "Retornos logarítmicos mensuales del USD/COP",
subtitle = "Se superpone una densidad normal con media y desviación muestral",
x = "Retorno logarítmico mensual",
y = "Densidad"
) +
scale_x_continuous(labels = scales::percent_format(accuracy = 0.1, decimal.mark = ","))Lectura económica. Si la tasa comercial en COP se mantiene por encima de la tasa comercial en USD, el forward teórico anual resulta superior al spot actual, lo que es coherente con la paridad cubierta de tasas. En otras palabras, cubrirse no significa necesariamente pagar menos en promedio, sino evitar escenarios de depreciación fuerte del peso.
valor_maquinaria_cop <- params$monto_maquinaria_cop
valor_maquinaria_usd <- valor_maquinaria_cop / precio_spot_actual
cuota_inicial_usd <- valor_maquinaria_usd * params$porcentaje_cuota_inicial
monto_credito_usd <- valor_maquinaria_usd - cuota_inicial_usd
numero_cuotas <- params$plazo_anios_credito * params$pagos_por_anio
tasa_trimestral_credito_usd <- (1 + params$tasa_credito_usd_anual)^(1 / params$pagos_por_anio) - 1
tabla_credito_usd <- crear_tabla_amortizacion(
monto = monto_credito_usd,
tasa_periodica = tasa_trimestral_credito_usd,
numero_periodos = numero_cuotas,
fecha_inicio = Sys.Date(),
frecuencia_meses = 12 / params$pagos_por_anio
) %>%
dplyr::mutate(
mes_pago = seq(3, by = 3, length.out = dplyr::n()),
anio_credito = ceiling(numero_cuota / params$pagos_por_anio)
)
cuota_trimestral_usd <- tabla_credito_usd$cuota_usd[1]
resumen_credito_usd <- tibble::tibble(
concepto = c(
"Valor maquinaria en USD",
"Cuota inicial en USD",
"Monto del crédito en USD",
"Tasa trimestral efectiva",
"Número de cuotas",
"Cuota trimestral"
),
valor = c(
formatear_moneda_usd(valor_maquinaria_usd),
formatear_moneda_usd(cuota_inicial_usd),
formatear_moneda_usd(monto_credito_usd),
formatear_porcentaje(tasa_trimestral_credito_usd),
numero_cuotas,
formatear_moneda_usd(cuota_trimestral_usd)
)
)
knitr::kable(resumen_credito_usd, col.names = c("Concepto", "Valor"))| Concepto | Valor |
|---|---|
| Valor maquinaria en USD | USD 95,364.47 |
| Cuota inicial en USD | USD 9,536.45 |
| Monto del crédito en USD | USD 85,828.03 |
| Tasa trimestral efectiva | 1,37% |
| Número de cuotas | 40 |
| Cuota trimestral | USD 2,803.39 |
Con el spot descargado al momento de tejer el informe, el valor de la maquinaria equivale a USD 95,364.47, de los cuales se paga una cuota inicial de USD 9,536.45 y se financian USD 85,828.03. La cuota trimestral del crédito francés resulta aproximadamente en USD 2,803.39.
DT::datatable(
tabla_credito_usd %>%
dplyr::mutate(
saldo_inicial_usd = round(saldo_inicial_usd, 2),
interes_usd = round(interes_usd, 2),
abono_capital_usd = round(abono_capital_usd, 2),
cuota_usd = round(cuota_usd, 2),
saldo_final_usd = round(saldo_final_usd, 2)
),
extensions = "Buttons",
options = list(
dom = "Bfrtip",
buttons = c("copy", "csv", "excel"),
pageLength = 10,
scrollX = TRUE
),
rownames = FALSE
)tabla_componentes_credito_usd <- tabla_credito_usd %>%
dplyr::select(numero_cuota, interes_usd, abono_capital_usd, saldo_final_usd) %>%
tidyr::pivot_longer(
cols = -numero_cuota,
names_to = "concepto",
values_to = "valor"
)
ggplot(tabla_componentes_credito_usd, aes(x = numero_cuota, y = valor, color = concepto)) +
geom_line(linewidth = 1) +
labs(
title = "Amortización del crédito en USD",
subtitle = "Sistema francés con pagos trimestrales",
x = "Número de cuota",
y = "Valor en USD",
color = "Componente"
) +
scale_y_continuous(labels = scales::dollar_format(prefix = "USD ", big.mark = ",", decimal.mark = "."))tabla_credito_cop_hoy <- tabla_credito_usd %>%
dplyr::mutate(
saldo_inicial_cop = saldo_inicial_usd * precio_spot_actual,
interes_cop = interes_usd * precio_spot_actual,
abono_capital_cop = abono_capital_usd * precio_spot_actual,
cuota_cop = cuota_usd * precio_spot_actual,
saldo_final_cop = saldo_final_usd * precio_spot_actual
)
cuota_trimestral_cop_hoy <- tabla_credito_cop_hoy$cuota_cop[1]Al convertir el crédito con el spot actual, la cuota trimestral equivalente es $10.288.792 COP. En esta recreación estática el cronograma en pesos luce ordenado y predecible, pero esa apariencia es engañosa: el verdadero riesgo aparece cuando la TRM cambia en el tiempo. Por eso, en la siguiente sección se simula el USD/COP mes a mes y luego se vuelve a valorar cada pago del crédito en COP.
DT::datatable(
tabla_credito_cop_hoy %>%
dplyr::mutate(
saldo_inicial_cop = round(saldo_inicial_cop, 0),
interes_cop = round(interes_cop, 0),
abono_capital_cop = round(abono_capital_cop, 0),
cuota_cop = round(cuota_cop, 0),
saldo_final_cop = round(saldo_final_cop, 0)
) %>%
dplyr::select(numero_cuota, fecha_pago, anio_credito, saldo_inicial_cop, interes_cop, abono_capital_cop, cuota_cop, saldo_final_cop),
extensions = "Buttons",
options = list(
dom = "Bfrtip",
buttons = c("copy", "csv", "excel"),
pageLength = 10,
scrollX = TRUE
),
rownames = FALSE
)El enunciado pide simular la TRM mensual con dos distribuciones:
meses_simulados <- params$plazo_anios_credito * 12
matriz_rutas_normal <- simular_mbg(
precio_inicial = precio_spot_actual,
media_mensual = media_mensual_retornos,
desviacion_mensual = desviacion_mensual_retornos,
meses = meses_simulados,
numero_rutas = params$numero_rutas,
distribucion = "normal",
grados_libertad = grados_libertad_t,
semilla = params$semilla
)
matriz_rutas_t_student <- simular_mbg(
precio_inicial = precio_spot_actual,
media_mensual = media_mensual_retornos,
desviacion_mensual = desviacion_mensual_retornos,
meses = meses_simulados,
numero_rutas = params$numero_rutas,
distribucion = "t_student",
grados_libertad = grados_libertad_t,
semilla = params$semilla + 1
)
muestra_rutas <- dplyr::bind_rows(
crear_muestra_rutas(matriz_rutas_normal, "Normal"),
crear_muestra_rutas(matriz_rutas_t_student, "T-Student")
)
cuantiles_rutas <- dplyr::bind_rows(
resumir_cuantiles_rutas(matriz_rutas_normal, "Normal"),
resumir_cuantiles_rutas(matriz_rutas_t_student, "T-Student")
)tabla_estadistica_retornos <- tibble::tibble(
medida = c(
"Número de observaciones mensuales",
"Media mensual",
"Desviación estándar mensual",
"Exceso de curtosis",
"Grados de libertad T-Student"
),
valor = c(
nrow(retornos_mensuales),
formatear_porcentaje(media_mensual_retornos, 4),
formatear_porcentaje(desviacion_mensual_retornos, 4),
round(exceso_curtosis_retornos, 4),
round(grados_libertad_t, 2)
)
)
knitr::kable(tabla_estadistica_retornos, col.names = c("Medida", "Valor"))| Medida | Valor |
|---|---|
| Número de observaciones mensuales | 194 |
| Media mensual | 0,3241% |
| Desviación estándar mensual | 3,7116% |
| Exceso de curtosis | 0.7649 |
| Grados de libertad T-Student | 11.84 |
ggplot(muestra_rutas, aes(x = mes, y = precio_spot, group = numero_ruta)) +
geom_line(alpha = 0.20) +
facet_wrap(~ distribucion, scales = "free_y") +
labs(
title = "Muestra de rutas simuladas del USD/COP",
subtitle = "Se muestran 120 trayectorias en cada distribución",
x = "Mes",
y = "Precio spot simulado"
) +
scale_y_continuous(labels = scales::label_number(big.mark = ".", decimal.mark = ","))ggplot(cuantiles_rutas, aes(x = mes)) +
geom_ribbon(aes(ymin = percentil_5, ymax = percentil_95), alpha = 0.25) +
geom_line(aes(y = mediana), linewidth = 1) +
facet_wrap(~ distribucion, scales = "free_y") +
labs(
title = "Banda de incertidumbre de la TRM simulada",
subtitle = "Rango entre percentil 5 y 95, con la mediana de cada mes",
x = "Mes",
y = "Precio spot simulado"
) +
scale_y_continuous(labels = scales::label_number(big.mark = ".", decimal.mark = ","))SET-FX se presenta como la fuente oficial y en tiempo real del dólar en Colombia y su mercado Forward registra operaciones de derivados desde T+1 en adelante sobre USD/COP. Además, SET-ICAP reporta el cierre diario del mercado NDF, incluyendo puntos forward por plazo y devaluación (SET-ICAP FX 2026). Como el ejercicio pide forwards por encima de 6 meses y, además, sugiere 4 forwards de 1 año, se utiliza una estructura anual para cubrir los años 6 a 9.
La tasa forward teórica aplicada en este proyecto es:
\[ Forward_{t,1a} = Spot_t \times \frac{1 + i_{COP}}{1 + i_{USD}} \]
donde:
resultado_cobertura_normal <- aplicar_cobertura_forward(
tabla_amortizacion = tabla_credito_usd,
matriz_rutas_spot = matriz_rutas_normal,
porcentaje_cobertura = params$porcentaje_cobertura_forward,
anio_inicio_cobertura = params$anio_inicio_cobertura,
anios_cobertura = params$anios_cobertura,
tasa_usd_anual = params$tasa_comercial_usa_anual,
tasa_cop_anual = params$tasa_comercial_colombia_anual
)
resultado_cobertura_t_student <- aplicar_cobertura_forward(
tabla_amortizacion = tabla_credito_usd,
matriz_rutas_spot = matriz_rutas_t_student,
porcentaje_cobertura = params$porcentaje_cobertura_forward,
anio_inicio_cobertura = params$anio_inicio_cobertura,
anios_cobertura = params$anios_cobertura,
tasa_usd_anual = params$tasa_comercial_usa_anual,
tasa_cop_anual = params$tasa_comercial_colombia_anual
)
tabla_riesgo_total <- dplyr::bind_rows(
resumir_riesgo_total(resultado_cobertura_normal$resumen_total_rutas, "Normal"),
resumir_riesgo_total(resultado_cobertura_t_student$resumen_total_rutas, "T-Student")
)tabla_forward <- tibble::tibble(
concepto = c(
"Mercado usado como referencia",
"Cobertura aplicada",
"Años cubiertos",
"Convención adoptada",
"Tasa comercial USD",
"Tasa comercial COP",
"Forward teórico anual hoy",
"Prima forward hoy"
),
valor = c(
"SET-FX / NDF USD-COP",
formatear_porcentaje(params$porcentaje_cobertura_forward),
paste(params$anio_inicio_cobertura, "a", params$anio_inicio_cobertura + params$anios_cobertura - 1),
"4 forwards anuales; cada forward cubre 75% de las 4 cuotas trimestrales del año correspondiente",
formatear_porcentaje(params$tasa_comercial_usa_anual),
formatear_porcentaje(params$tasa_comercial_colombia_anual),
formatear_moneda_cop(forward_teorico_anual_hoy, 2),
formatear_porcentaje(prima_forward_hoy)
)
)
knitr::kable(tabla_forward, col.names = c("Concepto", "Valor"))| Concepto | Valor |
|---|---|
| Mercado usado como referencia | SET-FX / NDF USD-COP |
| Cobertura aplicada | 75,00% |
| Años cubiertos | 6 a 9 |
| Convención adoptada | 4 forwards anuales; cada forward cubre 75% de las 4 cuotas trimestrales del año correspondiente |
| Tasa comercial USD | 6,75% |
| Tasa comercial COP | 11,22% |
| Forward teórico anual hoy | $3.823,81 COP |
| Prima forward hoy | 4,19% |
Se considera que la inversión está protegida en un pago si el costo cubierto en COP es menor que el costo del mismo pago valorado al spot simulado. Análogamente, la inversión no está protegida si el costo cubierto es mayor.
tabla_proteccion_anual <- dplyr::bind_rows(
resultado_cobertura_normal$resumen_anual %>% dplyr::mutate(distribucion = "Normal"),
resultado_cobertura_t_student$resumen_anual %>% dplyr::mutate(distribucion = "T-Student")
) %>%
dplyr::filter(cubierto) %>%
dplyr::select(
distribucion, anio_credito, probabilidad_proteccion,
ahorro_medio_cop, costo_spot_medio_cop, costo_cubierto_medio_cop, tasa_forward_promedio
)
DT::datatable(
tabla_proteccion_anual %>%
dplyr::mutate(
probabilidad_proteccion = round(probabilidad_proteccion, 4),
ahorro_medio_cop = round(ahorro_medio_cop, 0),
costo_spot_medio_cop = round(costo_spot_medio_cop, 0),
costo_cubierto_medio_cop = round(costo_cubierto_medio_cop, 0),
tasa_forward_promedio = round(tasa_forward_promedio, 2)
),
extensions = "Buttons",
options = list(
dom = "Bfrtip",
buttons = c("copy", "csv", "excel"),
pageLength = 8,
scrollX = TRUE
),
rownames = FALSE
)ggplot(tabla_proteccion_anual, aes(x = factor(anio_credito), y = probabilidad_proteccion)) +
geom_col(position = "dodge") +
facet_wrap(~ distribucion) +
labs(
title = "Probabilidad de que el forward proteja la inversión",
subtitle = "La protección se mide contra el costo spot de las cuotas del año cubierto",
x = "Año del crédito",
y = "Probabilidad de protección"
) +
scale_y_continuous(labels = scales::percent_format(accuracy = 1, decimal.mark = ","))prob_normal <- tabla_riesgo_total$probabilidad_proteccion[tabla_riesgo_total$distribucion == "Normal"]
prob_t <- tabla_riesgo_total$probabilidad_proteccion[tabla_riesgo_total$distribucion == "T-Student"]
cat(
paste0(
"**Lectura rápida.** En el escenario Normal, la cobertura resulta protectora en ",
formatear_porcentaje(prob_normal),
" de las rutas sobre el período cubierto. En el escenario T-Student, la protección aparece en ",
formatear_porcentaje(prob_t),
"."
)
)Lectura rápida. En el escenario Normal, la cobertura resulta protectora en 35,30% de las rutas sobre el período cubierto. En el escenario T-Student, la protección aparece en 35,56%.
Interpretación. Cuando el peso se deprecia lo suficiente durante los años cubiertos, el forward tiende a ser favorable porque fija parte del costo en COP y evita que el 75% cubierto se pague al spot más alto. En cambio, cuando el peso se aprecia o la depreciación es menor que la prima forward, la cobertura puede parecer “cara” en promedio. Por eso la evaluación correcta no debe limitarse al costo esperado, sino también al riesgo extremo.
tabla_riesgo_total_formateada <- tabla_riesgo_total %>%
dplyr::mutate(
costo_esperado_sin_cobertura_cop = formatear_moneda_cop(costo_esperado_sin_cobertura_cop),
costo_esperado_cubierto_cop = formatear_moneda_cop(costo_esperado_cubierto_cop),
desviacion_sin_cobertura_cop = formatear_moneda_cop(desviacion_sin_cobertura_cop),
desviacion_cubierto_cop = formatear_moneda_cop(desviacion_cubierto_cop),
percentil_95_sin_cobertura_cop = formatear_moneda_cop(percentil_95_sin_cobertura_cop),
percentil_95_cubierto_cop = formatear_moneda_cop(percentil_95_cubierto_cop),
cvar_95_sin_cobertura_cop = formatear_moneda_cop(cvar_95_sin_cobertura_cop),
cvar_95_cubierto_cop = formatear_moneda_cop(cvar_95_cubierto_cop),
ahorro_promedio_total_cop = formatear_moneda_cop(ahorro_promedio_total_cop),
probabilidad_proteccion = formatear_porcentaje(probabilidad_proteccion),
reduccion_percentil_95 = formatear_porcentaje(reduccion_percentil_95),
reduccion_cvar_95 = formatear_porcentaje(reduccion_cvar_95)
)
knitr::kable(tabla_riesgo_total_formateada, col.names = c(
"Distribución", "Costo esperado sin cobertura", "Costo esperado cubierto",
"Desv. sin cobertura", "Desv. cubierta", "P95 sin cobertura", "P95 cubierto",
"CVaR95 sin cobertura", "CVaR95 cubierto", "Ahorro promedio",
"Prob. protección", "Reducción P95", "Reducción CVaR95"
))| Distribución | Costo esperado sin cobertura | Costo esperado cubierto | Desv. sin cobertura | Desv. cubierta | P95 sin cobertura | P95 cubierto | CVaR95 sin cobertura | CVaR95 cubierto | Ahorro promedio | Prob. protección | Reducción P95 | Reducción CVaR95 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Normal | $530.592.482 COP | $532.576.890 COP | $138.497.223 COP | $136.297.087 COP | $785.935.544 COP | $781.336.135 COP | $885.740.682 COP | $879.716.996 COP | -$1.984.408 COP | 35,30% | 0,59% | 0,68% |
| T-Student | $527.083.315 COP | $529.008.850 COP | $137.516.875 COP | $135.420.138 COP | $778.580.985 COP | $775.444.845 COP | $880.218.182 COP | $875.084.317 COP | -$1.925.536 COP | 35,56% | 0,40% | 0,58% |
tabla_densidad_flujo_total <- dplyr::bind_rows(
resultado_cobertura_normal$resumen_total_rutas %>%
dplyr::transmute(distribucion = "Normal", cobertura = "Sin cobertura", flujo_total_cop = total_sin_cobertura_cop),
resultado_cobertura_normal$resumen_total_rutas %>%
dplyr::transmute(distribucion = "Normal", cobertura = "Con cobertura", flujo_total_cop = total_cubierto_cop),
resultado_cobertura_t_student$resumen_total_rutas %>%
dplyr::transmute(distribucion = "T-Student", cobertura = "Sin cobertura", flujo_total_cop = total_sin_cobertura_cop),
resultado_cobertura_t_student$resumen_total_rutas %>%
dplyr::transmute(distribucion = "T-Student", cobertura = "Con cobertura", flujo_total_cop = total_cubierto_cop)
)
ggplot(tabla_densidad_flujo_total, aes(x = flujo_total_cop, fill = cobertura)) +
geom_density(alpha = 0.30) +
facet_wrap(~ distribucion, scales = "free") +
labs(
title = "Distribución del flujo total del crédito en COP",
subtitle = "Comparación entre pagar todo al spot vs pagar con cobertura forward",
x = "Flujo total del crédito en COP",
y = "Densidad",
fill = "Esquema"
) +
scale_x_continuous(labels = scales::label_number(big.mark = ".", decimal.mark = ","))tabla_conclusiones <- tabla_riesgo_total %>%
dplyr::mutate(
cambia_costo_esperado = costo_esperado_cubierto_cop - costo_esperado_sin_cobertura_cop,
cambia_p95 = percentil_95_cubierto_cop - percentil_95_sin_cobertura_cop,
cambia_cvar95 = cvar_95_cubierto_cop - cvar_95_sin_cobertura_cop
)
for (i in seq_len(nrow(tabla_conclusiones))) {
fila <- tabla_conclusiones[i, ]
texto_costo <- if (fila$cambia_costo_esperado < 0) {
paste0("reduce el costo esperado en ", formatear_moneda_cop(abs(fila$cambia_costo_esperado)))
} else {
paste0("incrementa el costo esperado en ", formatear_moneda_cop(abs(fila$cambia_costo_esperado)))
}
texto_p95 <- if (fila$cambia_p95 < 0) {
paste0("reduce el percentil 95 en ", formatear_moneda_cop(abs(fila$cambia_p95)))
} else {
paste0("incrementa el percentil 95 en ", formatear_moneda_cop(abs(fila$cambia_p95)))
}
texto_cvar <- if (fila$cambia_cvar95 < 0) {
paste0("reduce el CVaR 95 en ", formatear_moneda_cop(abs(fila$cambia_cvar95)))
} else {
paste0("incrementa el CVaR 95 en ", formatear_moneda_cop(abs(fila$cambia_cvar95)))
}
cat(
paste0(
"- **Escenario ", fila$distribucion, "**: la cobertura ",
texto_costo, ", ",
texto_p95, " y ",
texto_cvar, ".\n"
)
)
}fila_normal <- tabla_riesgo_total %>% dplyr::filter(distribucion == "Normal")
fila_t <- tabla_riesgo_total %>% dplyr::filter(distribucion == "T-Student")
beneficio_por_riesgo <- (fila_normal$reduccion_cvar_95 > 0) | (fila_t$reduccion_cvar_95 > 0)
beneficio_por_costo <- (fila_normal$ahorro_promedio_total_cop > 0) | (fila_t$ahorro_promedio_total_cop > 0)
if (beneficio_por_riesgo && beneficio_por_costo) {
cat("**Conclusión principal:** la cobertura forward fue beneficiosa tanto como seguro cambiario como en flujo esperado, por lo que la decisión de cubrir 75% del crédito desde el año 6 resulta financieramente consistente para una inversión intensiva en TRM.")
} else if (beneficio_por_riesgo && !beneficio_por_costo) {
cat("**Conclusión principal:** la cobertura forward no necesariamente minimiza el costo promedio, pero sí mejora la protección frente a escenarios extremos de depreciación del peso. En ese sentido, fue beneficiosa como herramienta de gestión de riesgo, aunque no siempre como estrategia de minimización de costo esperado.")
} else if (!beneficio_por_riesgo && beneficio_por_costo) {
cat("**Conclusión principal:** la cobertura forward mejora el costo promedio, pero no reduce suficientemente el riesgo extremo. Bajo este resultado, el forward ayuda más como estrategia táctica que como cobertura robusta.")
} else {
cat("**Conclusión principal:** con los supuestos y la muestra descargada, la cobertura forward no mejora de forma clara ni el costo promedio ni la cola de pérdidas. En ese caso, la cobertura no sería la mejor decisión para este crédito particular.")
}Conclusión principal: la cobertura forward no necesariamente minimiza el costo promedio, pero sí mejora la protección frente a escenarios extremos de depreciación del peso. En ese sentido, fue beneficiosa como herramienta de gestión de riesgo, aunque no siempre como estrategia de minimización de costo esperado.