DESARROLLO
A continuación, realizaremos una práctica de simulaciones con MBG y precios futuros, se mostrará el código de ejecución en R-Studio y el análisis correspondiente a cada cálculo.
library(quantmod)
library(zoo)
library(TTR)
library(xts)
library(knitr)
library(fBasics)
library(moments)
library(tidyverse)
library(dplyr)
library(ggplot2)
#Cargar datos.
datos_trm = read.table("trm_cm.txt", head = T)
head(datos_trm)
## Fecha TRM
## 1 01/01/2000 1873.77
## 2 02/01/2000 1873.77
## 3 03/01/2000 1873.77
## 4 04/01/2000 1874.35
## 5 05/01/2000 1895.97
## 6 06/01/2000 1912.69
tail(datos_trm)
## Fecha TRM
## 8291 12/09/2022 4365.32
## 8292 13/09/2022 4346.91
## 8293 14/09/2022 4413.89
## 8294 15/09/2022 4389.80
## 8295 16/09/2022 4404.64
## 8296 17/09/2022 4435.84
# Tamaño de la muestra
n <- nrow(datos_trm)
#Vector de precios
precios = datos_trm[,-1]
precios = ts(precios)
#Precio actual de la TRM
s = tail(precios,1)
s = as.numeric(s)
s
## [1] 4435.84
# Verificar que el formato de la fecha sea correcto.
datos_trm[,"Fecha"]<-as.Date(datos_trm[,"Fecha"],format = "%d/%m/%Y")
datos_trm <- datos_trm %>% arrange(Fecha)
#Media y desviación de los precios de la TRM
mean_precios <- mean(precios)
sd_precios <- sd(precios)
#Vector de rendimientos diarios
Rtos_diarios = diff(log(precios))
#Vector rendimientos anuales
Rtos_anuales = (Rtos_diarios) * 252
# MEDIA de rendimientos diaria
media_diaria = mean(Rtos_diarios)
media_diaria
## [1] 0.0001038896
#Volatilidad diaria(SIGMA/DESVIACIÓN)
volatilidad_diaria = sd(Rtos_diarios)
volatilidad_diaria
## [1] 0.005783866
#Volatilidad anual
Volatilidad_Anual = sd(Rtos_diarios) * 252
#Media de rendimientos anual
media_Anual = mean(Rtos_diarios) * 252
media_Anual
## [1] 0.02618019
plot(datos_trm[,"Fecha"],datos_trm[,"TRM"], type = "l", col = "blue", main = "Serie Historica TRM")
Estadística básica
Sobre Precios:
max(datos_trm[,"TRM"])
## [1] 4627.46
min(datos_trm[,"TRM"])
## [1] 1652.41
mean(datos_trm[,"TRM"])
## [1] 2553.402
sd(datos_trm[,"TRM"])
## [1] 643.277
skewness(datos_trm[,"TRM"])
## [1] 0.7478894
kurtosis(datos_trm[,"TRM"])
## [1] 2.685184
estad_precios=cbind(Estadistica=c("Max", "Min", "Mean", "Desv", "Sesgo", "Kurtosis"), Precios=c(max(datos_trm[,"TRM"]),min(datos_trm[,"TRM"]),mean(datos_trm[,"TRM"]),sd(datos_trm[,"TRM"]),skewness(datos_trm[,"TRM"]),kurtosis(datos_trm[,"TRM"])))
kable(estad_precios)
| Estadistica | Precios |
|---|---|
| Max | 4627.46 |
| Min | 1652.41 |
| Mean | 2553.40167430087 |
| Desv | 643.276997400928 |
| Sesgo | 0.747889447812386 |
| Kurtosis | 2.68518407398657 |
#Cuantiles precios
quantile(datos_trm[,"TRM"],c(0.01,0.05,0.1,0.5,0.75,0.90,0.95,0.99))
## 1% 5% 10% 50% 75% 90% 95% 99%
## 1761.485 1789.540 1830.770 2345.470 2954.158 3580.350 3830.250 4129.870
Sobre Rendimientos:
max(Rtos_diarios)
## [1] 0.05930667
min(Rtos_diarios)
## [1] -0.05621935
mean(Rtos_diarios)
## [1] 0.0001038896
sd(Rtos_diarios)
## [1] 0.005783866
skewness(Rtos_diarios)
## [1] 0.2649411
kurtosis(Rtos_diarios)
## [1] 13.88438
estad_rendimientos=cbind(Estadistica=c("Max", "Min", "Mean", "Desv", "Sesgo", "Kurtosis"), Rendimientos=c(max(Rtos_diarios),min(Rtos_diarios),mean(Rtos_diarios),sd(Rtos_diarios),skewness(Rtos_diarios),kurtosis(Rtos_diarios)))
kable(estad_rendimientos)
| Estadistica | Rendimientos |
|---|---|
| Max | 0.0593066743064448 |
| Min | -0.0562193503314647 |
| Mean | 0.00010388963907742 |
| Desv | 0.00578386604402905 |
| Sesgo | 0.264941128226632 |
| Kurtosis | 13.8843844743101 |
#Comparación de cuantiles
qqnorm(Rtos_diarios)
qqline(Rtos_diarios)
#Cuantiles rendimientos
quantile(Rtos_diarios,c(0.01,0.05,0.1,0.5,0.75,0.90,0.95,0.99))
## 1% 5% 10% 50% 75% 90%
## -0.016347400 -0.008534254 -0.005462864 0.000000000 0.001315725 0.005793101
## 95% 99%
## 0.009327293 0.018328488
#Para los precios
qnorm(c(0.05,0.95),mean = mean(precios),sd=sd(precios))
## [1] 1495.305 3611.498
#Para los rendimientos
qnorm(c(0.05,0.95),mean = mean(Rtos_diarios),sd=sd(Rtos_diarios))
## [1] -0.009409723 0.009617503
Simulación MBG
# Definir los parámetros
S =s # Precio de la TRM del 17 de septiembre de 2022
t <- 180 # Tiempo en días
volatilidad <- volatilidad_diaria # Volatilidad histórica de la serie
mu <- media_diaria # Tasa de crecimiento/rendimiento histórica de la serie
iteraciones <- 10000 # Número de iteraciones
# Crear una función para simular el MBG
set.seed(123) #Establecer una semilla
simular_MB <- function(S, t, volatilidad, mu, iteraciones) {
precios_futuros <- numeric(iteraciones)
for (i in 1:iteraciones) {
W_t <- rnorm(1, mean = 0, sd = sqrt(t)) # Generar un valor del proceso Browniano
S_t <- S * exp((mu - 0.5 * volatilidad^2) * t + volatilidad * W_t) # Calcular el precio futuro
precios_futuros[i] <- S_t
}
return(precios_futuros)
}
precios_simulados = simular_MB(S, t, volatilidad, mu, iteraciones)
# Ver los primeros 5 precios simulados
head(precios_simulados, 5)
## [1] 4314.210 4426.215 5085.331 4530.706 4551.418
Gráfico del histograma y densidad
hist(precios_simulados, breaks = 30, prob = TRUE, col = "skyblue", main = "Distribución Empírica de Precios Futuros", xlab = "Precio Futuro", ylab = "Densidad")
# Curva de densidad
densidad <- density(precios_simulados)
lines(densidad, col = "red", lwd = 2)
La gráfica nos muestra la distribución empírica de los precios futuros simulados.Esta tiende a ser mesocúrtica. La curva de densidad (en rojo) nos da una idea de la forma de la distribución.
cuantil_2_5 <- quantile(precios_simulados, 0.025)
cuantil_97_5 <- quantile(precios_simulados, 0.975)
hist(precios_simulados, breaks = 30, prob = TRUE, col = "skyblue", main = "Distribución Empírica de Precios Futuros", xlab = "Precio Futuro", ylab = "Densidad")
# Curva de densidad
densidad <- density(precios_simulados)
lines(densidad, col = "red", lwd = 2)
abline(v = cuantil_2_5, col = "blue", lty = 2)
abline(v = cuantil_97_5, col = "blue", lty = 2)
# Mostrar los cuantiles en la leyenda
legend("topright", legend = c("Distribución Empírica", "Densidad", "Cuantiles al 2.5% y 97.5%"), fill = c("skyblue", "red", NA), lty = c(0, 1, 2), col = c(NA, "red", "blue"), lwd = c(0, 2, 1), bty = "n", title = "Datos")
# Imprimir los cuantiles
cat("Cuantil al 2.5%:", cuantil_2_5, "\n")
## Cuantil al 2.5%: 3865.042
cat("Cuantil al 97.5%:", cuantil_97_5, "\n")
## Cuantil al 97.5%: 5242.569
Existe una probabilidad del 95% de que el precio futuro esté dentro del rango de 3865.042 y 5242.569 pesos.
Cuantil al 2.5%: 3,865.042: Podemos decir que el 2.5% de los precios futuros simulados son inferiores o iguales a $3,865.042. En otras palabras, hay un 2.5% de probabilidad de que el precio futuro sea igual o inferior a este valor.
Cuantil al 97.5%: 5242.569: Esto nos indica que el 97.5% de los precios futuros simulados son inferiores o iguales a $5,242.569. Por lo tanto, hay un 97.5% de probabilidad de que el precio futuro sea igual o inferior a este valor.
Precio actual de la TRM:
s
## [1] 4435.84
Dado que el último precio conocido (s) es de 4,435.84, y los cuantiles al 2.5% y 97.5% son 3,865.042 y $5,242.569 respectivamente, podemos inferir lo siguiente:
-El rango entre estos cuantiles nos proporciona una estimaciónn de la incertidumbre asociada con los posibles precios futuros. Cuanto más amplio sea este rango, mayor será la incertidumbre.
-Dado que el precio actual es $4435.84 y cae dentro de este rango, podemos concluir que, en general, es recomendable que el precio futuro esté en línea con el precio actual, pero hay una cierta variabilidad y riesgo asociados con el pronóstico debido a la volatilidad de los precios y otros factores inherentes.
-Basándonos en este análisis, concluímos que los precios futuros de la TRM están sujetos a una considerable incertidumbre y variabilidad, lo que es un reflejo de las fluctuaciones históricas y de la naturaleza impredecible de los mercados financieros. Aunque las simulaciones proporcionan una guía sobre lo que podría esperarse en términos de movimientos de precios, la realidad del mercado podría desviarse significativamente de estos rangos proyectados debido a eventos inesperados o cambios en las condiciones económicas.
S <- 4066 # Tasa de cambio actual en COP
t <- 180/252 # Proyección a futuro en términos anuales (para 180 días)
mu <- mean(Rtos_diarios, na.rm = TRUE) * 252 # Rendimiento anual estimado
sigma <- sd(Rtos_diarios, na.rm = TRUE) * sqrt(252) # Volatilidad anual estimada
iteraciones <- 1000 # Número de iteraciones para la nueva simulación
precios_simulados_TRM <- numeric(iteraciones)
set.seed(123) # Garantiza la reproducibilidad
for(i in 1:iteraciones) {
Z <- rnorm(1) # Generar un valor aleatorio de una distribución normal estándar
precios_simulados_TRM[i] <- S * exp((mu - 0.5 * sigma^2) * t + sigma * sqrt(t) * Z)
}
CI_inferior <- quantile(precios_simulados_TRM, probs = 0.025)
CI_superior <- quantile(precios_simulados_TRM, probs = 0.975)
cat("El intervalo de confianza del 95% para el precio futuro de la TRM es de:", CI_inferior, "a", CI_superior, "\n")
## El intervalo de confianza del 95% para el precio futuro de la TRM es de: 3552.626 a 4837.928
pagos_usd <- c(91738, 90992, 90246, 89500, 88754)
fechas <- as.Date(c("2022-10-17", "2022-11-17", "2022-12-17", "2023-01-17", "2023-02-17"))
S <- 4066 # Tasa de cambio actual en COP
mu <- 0.0001039 # Media de rendimientos
sigma <- 0.091816 # Desviación estándar de los rendimientos
dias <- as.numeric(difftime(fechas, as.Date("2022-09-17"), units = "days")) # Días hasta cada pago
iteraciones <- 1000 # Número de iteraciones para la simulación
set.seed(123)
flujo_caja_total <- numeric(iteraciones)
for (i in 1:iteraciones) {
flujo_caja <- 0
for (j in 1:length(pagos_usd)) {
t <- dias[j] / 365
TRM_futura <- S * exp((mu - 0.5 * sigma^2) * t + sigma * sqrt(t) * rnorm(1))
flujo_caja <- flujo_caja + pagos_usd[j] * TRM_futura
}
flujo_caja_total[i] <- flujo_caja
}
media_flujo_caja <- mean(flujo_caja_total)
CI_inferior <- quantile(flujo_caja_total, probs = 0.025)
CI_superior <- quantile(flujo_caja_total, probs = 0.975)
cat("El flujo de caja total esperado promedio es:", media_flujo_caja, "COP\n")
## El flujo de caja total esperado promedio es: 1834672565 COP
cat("El intervalo de confianza del 95% para el flujo de caja total esperado es de:", CI_inferior, "a", CI_superior, "COP\n")
## El intervalo de confianza del 95% para el flujo de caja total esperado es de: 1766560152 a 1903628808 COP
pagos_usd <- c(91738, 90992, 90246, 89500, 88754)
fechas <- as.Date(c("2022-10-17", "2022-11-17", "2022-12-17", "2023-01-17", "2023-02-17"))
S <- 4066
cobertura <- 0.70
exposicion <- 1 - cobertura
mu <- 0.0001039
sigma <- 0.091816
dias <- as.numeric(difftime(fechas, as.Date("2022-09-17"), units = "days"))
iteraciones <- 1000
set.seed(123)
flujo_caja_total_con_cobertura <- numeric(iteraciones)
for (i in 1:iteraciones) {
flujo_caja_con_cobertura <- 0
for (j in 1:length(pagos_usd)) {
t <- dias[j] / 365
TRM_futura <- S * exp((mu - 0.5 * sigma^2) * t + sigma * sqrt(t) * rnorm(1))
pago_cubierto <- pagos_usd[j] * cobertura * S
pago_no_cubierto <- pagos_usd[j] * exposicion * TRM_futura
flujo_caja_con_cobertura <- flujo_caja_con_cobertura + pago_cubierto + pago_no_cubierto
}
flujo_caja_total_con_cobertura[i] <- flujo_caja_con_cobertura
}
media_flujo_caja_con_cobertura <- mean(flujo_caja_total_con_cobertura)
CI_inferior_con_cobertura <- quantile(flujo_caja_total_con_cobertura, probs = 0.025)
CI_superior_con_cobertura <- quantile(flujo_caja_total_con_cobertura, probs = 0.975)
cat("El flujo de caja total esperado promedio con cobertura es:", media_flujo_caja_con_cobertura, "COP\n")
## El flujo de caja total esperado promedio con cobertura es: 1834692595 COP
cat("El intervalo de confianza del 95% para el flujo de caja total esperado con cobertura es de:", CI_inferior_con_cobertura, "a", CI_superior_con_cobertura, "COP\n")
## El intervalo de confianza del 95% para el flujo de caja total esperado con cobertura es de: 1814258872 a 1855379468 COP
media_flujo_caja_sin_cobertura <- mean(flujo_caja_total)
media_flujo_caja_con_cobertura <- mean(flujo_caja_total_con_cobertura)
beneficio_real <- media_flujo_caja_con_cobertura - media_flujo_caja_sin_cobertura
cat("El beneficio real obtenido de aplicar la cobertura es:", beneficio_real, "COP\n")
## El beneficio real obtenido de aplicar la cobertura es: 20030.65 COP
CI_inferior_sin_cobertura <- quantile(flujo_caja_total, probs = 0.025)
CI_superior_sin_cobertura <- quantile(flujo_caja_total, probs = 0.975)
CI_inferior_con_cobertura <- quantile(flujo_caja_total_con_cobertura, probs = 0.025)
CI_superior_con_cobertura <- quantile(flujo_caja_total_con_cobertura, probs = 0.975)
cat("El intervalo de confianza del 95% para el flujo de caja total esperado sin cobertura es de:", CI_inferior_sin_cobertura, "a", CI_superior_sin_cobertura, "COP\n")
## El intervalo de confianza del 95% para el flujo de caja total esperado sin cobertura es de: 1766560152 a 1903628808 COP
cat("El intervalo de confianza del 95% para el flujo de caja total esperado con cobertura es de:", CI_inferior_con_cobertura, "a", CI_superior_con_cobertura, "COP\n")
## El intervalo de confianza del 95% para el flujo de caja total esperado con cobertura es de: 1814258872 a 1855379468 COP
diferencia_flujo_caja <- flujo_caja_total_con_cobertura - flujo_caja_total
media_diferencia_flujo_caja <- mean(diferencia_flujo_caja)
porcentaje_margen <- 0.10
requerimiento_margen <- porcentaje_margen * media_diferencia_flujo_caja
cat("La diferencia promedio del flujo de caja debido a la cobertura es:", media_diferencia_flujo_caja, "COP\n")
## La diferencia promedio del flujo de caja debido a la cobertura es: 20030.65 COP
cat("El requerimiento de margen, asumiendo un 10% de la diferencia promedio, es:", requerimiento_margen, "COP\n")
## El requerimiento de margen, asumiendo un 10% de la diferencia promedio, es: 2003.065 COP
margen_inicial <- 0.10 * media_flujo_caja_sin_cobertura
veces_bajo_margen <- sum(flujo_caja_total_con_cobertura < margen_inicial)
probabilidad_llamado_margen <- veces_bajo_margen / iteraciones
cat("La probabilidad de ser llamado al margen si solo se deposita el margen inicial es:", probabilidad_llamado_margen * 100, "%\n")
## La probabilidad de ser llamado al margen si solo se deposita el margen inicial es: 0 %
calcular_probabilidad_llamado_margen <- function(margen_inicial, flujo_caja_total_con_cobertura) {
veces_bajo_margen <- sum(flujo_caja_total_con_cobertura < margen_inicial)
probabilidad_llamado_margen <- veces_bajo_margen / length(flujo_caja_total_con_cobertura)
return(probabilidad_llamado_margen)
}
margen_inicial <- 0
probabilidad_objetivo <- 0.01
while (TRUE) {
probabilidad <- calcular_probabilidad_llamado_margen(margen_inicial, flujo_caja_total_con_cobertura)
if (probabilidad < probabilidad_objetivo) {
break
}
margen_inicial <- margen_inicial + 10000
}
cat("El margen inicial necesario para que la probabilidad de ser llamado al margen antes de cubrir el primer flujo sea menor al 1% es:", margen_inicial, "COP\n")
## El margen inicial necesario para que la probabilidad de ser llamado al margen antes de cubrir el primer flujo sea menor al 1% es: 0 COP
r0 <- 0.05
k <- 0.3
theta <- 0.08
sigma <- 0.03
dt <- 1/252
iteraciones <- 10
periodos <- 10
t <- seq(0, periodos*dt, by = dt)
tasas_simuladas <- matrix(NA, nrow = iteraciones, ncol = length(t))
set.seed(123)
for (i in 1:iteraciones) {
tasas_simuladas[i, 1] <- r0
for (j in 2:length(t)) {
dW <- rnorm(1, mean = 0, sd = sqrt(dt))
dR <- k * (theta - tasas_simuladas[i, j-1]) * dt + sigma * dW
tasas_simuladas[i, j] <- tasas_simuladas[i, j-1] + dR
}
}
print(tasas_simuladas)
## [,1] [,2] [,3] [,4] [,5] [,6] [,7]
## [1,] 0.05 0.04897651 0.04857845 0.05156154 0.05172865 0.05200663 0.05528113
## [2,] 0.05 0.05234901 0.05306191 0.05385137 0.05409167 0.05307207 0.05648108
## [3,] 0.05 0.04801772 0.04764386 0.04574341 0.04440672 0.04326788 0.04012405
## [4,] 0.05 0.05084166 0.05031874 0.05204570 0.05373849 0.05532240 0.05665319
## [5,] 0.05 0.04872284 0.04836715 0.04601343 0.05015284 0.05247120 0.05038150
## [6,] 0.05 0.05051444 0.05049559 0.05044970 0.05307130 0.05267669 0.05557507
## [7,] 0.05 0.05075317 0.04983868 0.04924488 0.04735657 0.04536994 0.04598478
## [8,] 0.05 0.04910775 0.04478061 0.04672321 0.04542256 0.04416351 0.04614432
## [9,] 0.05 0.05004661 0.05081038 0.05014465 0.05139795 0.05101531 0.05167683
## [10,] 0.05 0.05191326 0.05298307 0.05346639 0.05231135 0.05491570 0.05381118
## [,8] [,9] [,10] [,11]
## [1,] 0.05618160 0.05381922 0.05255235 0.05174281
## [2,] 0.05744992 0.05376021 0.05511689 0.05425302
## [3,] 0.04175480 0.04209017 0.03998443 0.04240155
## [4,] 0.05772779 0.05763730 0.05708571 0.05639396
## [5,] 0.04965538 0.04880961 0.05032073 0.05019851
## [6,] 0.05267728 0.05381463 0.05407986 0.05451881
## [7,] 0.04687231 0.04701192 0.04879411 0.05270556
## [8,] 0.04564645 0.04338041 0.04376663 0.04354729
## [9,] 0.05378338 0.05463700 0.05405125 0.05625318
## [10,] 0.05797603 0.06089861 0.06047592 0.05855941
rendimientos <- apply(tasas_simuladas, 2, function(x) c(0, diff(x) / x[-length(x)]))
periodos_secuencia <- seq(0, periodos*dt, by = dt)[-1]
plot(periodos_secuencia, rendimientos[,1], type = "l", col = "blue", ylim = c(min(rendimientos), max(rendimientos)),
xlab = "Tiempo", ylab = "Rendimiento", main = "Curvas de Rendimiento de Tasas Simuladas")
for (i in 2:iteraciones) {
lines(periodos_secuencia, rendimientos[,i], col = "blue")
}