Datos_TRM = read.table("C:/Users/Felipe/OneDrive - INSTITUTO TECNOLOGICO METROPOLITANO - ITM/Derivados Financieros/TRM MBG/TRM_MBG.txt", header = TRUE)
Se analiza la serie diaria del precio de la TRM desde 2000-01-31 hasta 2022-09-17
Se descargan los paquetes requeridos
options(warn = -1)
suppressPackageStartupMessages({
library(knitr)
library(moments)
library(magrittr)
library(plotly)
library(dplyr)
library(ggplot2)
library(stats)
})
# Fijar la base de datos
attach(Datos_TRM)
names(Datos_TRM)
## [1] "Fecha" "TRM"
options(scipen = 999)
Reconocemos la tendencia de los datos
plot(Datos_TRM[, "TRM"], type="l", col="blue")
• La tendencia de la TRM ha sido creciente durante el período de tiempo analizado.
media<-mean((Datos_TRM[,"TRM"]))
media_anualizada <- mean((Datos_TRM[,"TRM"])) * 252
desviacion_estandar <- sd((Datos_TRM[,"TRM"]))
cuantiles <- quantile(Datos_TRM[,"TRM"], c(0.01, 0.05, 0.1, 0.5, 0.75))
sesgo <- skewness(Datos_TRM[,"TRM"])
curtosis <- kurtosis(Datos_TRM[,"TRM"])
maximo_valor <- max(Datos_TRM[,"TRM"])
minimo_valor <- min(Datos_TRM[,"TRM"])
estadistica_descriptiva <- data.frame(
"Descripción" = c("Media", "Media anualizada", "Desviación estándar", "Cuantiles (1%, 5%, 10%, 50%, 75%)",
"Sesgo", "Curtosis", "Máximo valor", "Mínimo valor"),
"Valor" = c(media, media_anualizada, desviacion_estandar, paste(cuantiles, collapse = ", "),
sesgo, curtosis, maximo_valor, minimo_valor)
)
print(estadistica_descriptiva)
## Descripción
## 1 Media
## 2 Media anualizada
## 3 Desviación estándar
## 4 Cuantiles (1%, 5%, 10%, 50%, 75%)
## 5 Sesgo
## 6 Curtosis
## 7 Máximo valor
## 8 Mínimo valor
## Valor
## 1 2553.40167430087
## 2 643457.221923819
## 3 643.276997400928
## 4 1761.485, 1789.54, 1830.77, 2345.47, 2954.1575
## 5 0.747889447812386
## 6 2.68518407398657
## 7 4627.46
## 8 1652.41
1- Análisis Descriptivo
- Media: La TRM promedio durante el período 2000-2022 fue de $2.553,40 COP por USD.
- Media anualizada: La TRM anualizada durante el período 2000-2022 fue de $643.457,22 COP por USD.
- Desviación estándar: La desviación estándar de la TRM fue de $643.2769 COP por USD, lo que significa que en promedio el precio de la TRM puede subir o bajar $643.2769 en un día.
- Máximo: El valor máximo de la TRM fue de $4627.46 COP por USD.
- Mínimo: El valor mínimo de la TRM fue de $1652.41 COP por USD.
Análisis de Autocorrelación:
La TRM tiene una autocorrelación positiva, lo que significa que los valores actuales de la TRM están correlacionados con los valores pasados.
- Sesgo: El sesgo de la TRM es de 0.7478894, lo que indica una asimetría hacia la derecha.
- Curtosis:La curtosis de la TRM es de 2.685184, indica una distribución más aplanada que la normal.
Análisis de Tendencias: Durante el período analizado, la Tasa Representativa del Mercado (TRM) ha mostrado una tendencia creciente.
Esta tendencia al alza de la TRM ha sido influenciada por una serie de factores tanto internos como externos
Factores Externos - Crecimiento de la moneda cambiaria (USD), impulsada por el crecimiento economico de Estados Unidos. - Los conflictos geopolíticos en las regiones productoras. - Eventos económicos globales, como la guerra en Ucrania o la crisis financiera de 2008 en los Estados Unidos. - La pandemia de COVID-19 en 2020
Factores internos -La inflación en Colombia ha superado la de los Estados Unidos en los últimos años. Cuando el Banco de la República emite más pesos para aumentar la oferta monetaria. -Colombia presenta un mayor deficit con respecto a de Estados Unidos
Estadísticas Descriptivas de los Retornos
print("Rendimiento de la TRM")
## [1] "Rendimiento de la TRM"
Rtos_TRM<-diff(log(Datos_TRM[, "TRM"]))
media_Rto <- mean(Rtos_TRM)
desv_Rtos <- sd(Rtos_TRM) * sqrt(252)
sesgo_Rtos <- skewness(Rtos_TRM)
curtosis_Rtos <- kurtosis(Rtos_TRM)
vol_TRM <- sd(Rtos_TRM) * sqrt(252)
# Crear la tabla de datos
Rendimientos <- data.frame(
"Descripción" = c("Media de los retornos anualizada", "Desviación estándar anualizada",
"Sesgo", "Curtosis", "Volatilidad de la TRM"),
"Valor" = c(media_Rto, desv_Rtos, sesgo_Rtos, curtosis_Rtos, vol_TRM)
)
print(Rendimientos)
## Descripción Valor
## 1 Media de los retornos anualizada 0.0001038896
## 2 Desviación estándar anualizada 0.0918160270
## 3 Sesgo 0.2649411282
## 4 Curtosis 13.8843844743
## 5 Volatilidad de la TRM 0.0918160270
Grafica de los Retornos de la TRM en el tiempo analizado
plot(Rtos_TRM, type="l", col="red")
Cuantos miden los precios y los retornos
length((Datos_TRM[,"TRM"]))
## [1] 8296
length(Rtos_TRM)
## [1] 8295
2- Calcule de manera teórica un intervalo de confianza al 95% sobre los posibles precios futuros de la TRM
quantile(Rtos_TRM, c(0.05,0.95))
## 5% 95%
## -0.008534254 0.009327293
3- Realizando una simulación MBG con S=Precio de la TRM del 17 de septiembre de 2022, y t=180, volatilidad = histórica de la serie, mu = histórica de la serie, iteraciones = 10000, de los posibles precios futuros.
t=5/12
delta_t<-1/252
N<-t/delta_t
M<-10000
S<-matrix(ncol = M,nrow = (N+1))
S[1,]<-4435.84
for (i in 1:M){
for (t in 2:(N+1)){
S[t,i]=S[(t-1),i]*exp((media_Rto-desv_Rtos^2/2)*delta_t+desv_Rtos*sqrt(delta_t)*rnorm(1))
}
}
matplot(S, type = "l")
Proyeccion de los posibles precios futuros
length((Datos_TRM[,"TRM"]))
## [1] 8296
N+1
## [1] 106
proyeccion1<-matrix(nrow =(8296+105), ncol=1)
proyeccion1[1:8296]<-Datos_TRM[,"TRM"]
matplot(proyeccion1, type="l",ylim =c(1000,6000))
proyeccion2<-matrix(nrow =(8296+105), ncol=M)
proyeccion2[8296:8401,]<-S
matlines(proyeccion2,type="l")
# Intervalo de confianza
alfa<-0.025
q1<-quantile(S[(N+1),],(alfa/2))
q2<-quantile(S[(N+1),],(1-alfa/2))
# Valores entre q1 y q2
valores_vector <- seq(q1, q2, length=100)
Distribución Empírica de precios futuros
plot(density(S[N+1,]), ylab="", xlab="",
main="Distribución Empírica", lwd = 3)
abline(h = NULL, v =q1, col = 'cadetblue', lwd = 2)
abline(h = NULL, v =q2, col = 'gold', lwd = 2)
Estimación de un intervalo de predicción del 95% para los precios futuros de la TRM
precios_futuros <- proyeccion1[complete.cases(proyeccion1), ]
qnorm(c(0.05,1), mean = mean(precios_futuros), sd=sd(precios_futuros))
## [1] 1495.305 Inf
Una empresa exportadora que realizó crédito para ejercer una inversión empresarial el 17 de septiembre de 2022 con los siguientes criterios de pago por parte de su capitalizadora de inversión:
Monto de inversión: 1’790.000 USD -Tasa de interés:_ 10% AMV Cuotas: 24 Frecuencia de pago: Mensual
Fechas<- c("17/10/2022","17/11/2022","17/12/2022","17/01/2023","17/02/2023")
Pago_USD<- c(91738,90992,90246,89500,88754)
Frecuencia_Pagos <- data.frame(Fechas = Fechas, Pago_USD = Pago_USD)
print(Frecuencia_Pagos)
## Fechas Pago_USD
## 1 17/10/2022 91738
## 2 17/11/2022 90992
## 3 17/12/2022 90246
## 4 17/01/2023 89500
## 5 17/02/2023 88754
2.1. Simulación
mu_anu<-mean((Datos_TRM[,"TRM"]))*252
sigma<-sd((Datos_TRM[,"TRM"]))*sqrt(252)
T= 5/12
delta_t=1/252
N=T/delta_t
M= 1000 # Numero de simulaciones
TRM= matrix(ncol=M, nrow = (N+1))
TRM[1,]=4435.84
for(i in 1:M){
for (T in 2:(N+1)){
TRM[T,i]=TRM[(T-1),i]*exp((media_Rto-desv_Rtos^2/2)*delta_t+desv_Rtos*sqrt(delta_t)*rnorm(1))
}
}
matplot(TRM, type = "l",
main = "Distribución",
xlab = "Tiempo",
ylab = "Precio")
Proyeccion1 = matrix(nrow = (8296 + 105), ncol = 1)
Proyeccion1[1: 8296] = Datos_TRM[,"TRM"]
matplot(Proyeccion1, type="l", ylim = c(1500, 7000))
title("Proyección")
lines(Proyeccion1, col = "black", type = "l")
proyeccion2<-matrix(nrow =(8296+105), ncol=M)
proyeccion2[8296:8401,]<-TRM
matlines(proyeccion2,type="l")
2.2 Simulación Montecarlo Flujo de caja total esperado cuota sin cobertura
# Pagos dado en el planteamiento incial
Cuotas_USD = c(91738,90992,90246,89500,88754)
Cuotas_COP=TRM[2,]*Cuotas_USD[1]
for(j in 2:length(Cuotas_USD)){
Cuotas_COP=rbind(Cuotas_COP,TRM[j+1,]*Cuotas_USD[j])
}
media_cuotas=vector()
volatilidad_cuotas=vector()
percentil_5_cuotas=vector()
percentil_95_cuotas=vector()
for(l in 1:5){
media_cuotas[l]=mean(TRM[l+1,]*Cuotas_USD[l])
volatilidad_cuotas[l]=sd(TRM[l+1,]*Cuotas_USD[l])
percentil_5_cuotas[l]=quantile(TRM[l+1,]*Cuotas_USD[l],0.05)
percentil_95_cuotas[l]=quantile(TRM[l+1,]*Cuotas_USD[l],0.95)
}
matplot(Cuotas_COP,type = "l", col="cornsilk", main="Estimado Cuotas en COP", ylab = "Valor Cuota", xlab = "Cuota")
lines(percentil_5_cuotas, col = "blue", type = "l")
lines(percentil_95_cuotas, col = "red", type = "l")
lines(media_cuotas, col = "black", type = "l")
legend("topright", legend = c( "Percentil 5", "Percentil 95", "Media"),
col = c("blue", "red", "black"), lty = 1)
print("Volatilidad de cada cuota en millones de COP")
## [1] "Volatilidad de cada cuota en millones de COP"
print(volatilidad_cuotas/1000000)
## [1] 2.353521 3.311844 4.106461 4.619983 5.051429
2.3 Simulación de Montecarlo de los pagos de cuotas con cobertura (70%)
Cobertura<-0.7
Precio_Entrega= 4500
Utilidad_POR_USD=TRM[-1,]-Precio_Entrega
matplot(Utilidad_POR_USD,type="l", col="bisque", main="Utilidad por USD", ylab = "Utilidad (USD)", xlab = "Fecha")
Utilidad_total=Utilidad_POR_USD[1,]*Cuotas_USD[1]*0.7
for(j in 2:length(Cuotas_USD)){
Utilidad_total=rbind(Utilidad_total,Utilidad_POR_USD[j,]*Cuotas_USD[j]*0.7)
}
matplot(Utilidad_total,type="l", col = "burlywood", main="Utilidad Total", ylab = "Utilidad (USD)", xlab = "Fecha")
Cuotas_COP_CON_C=Cuotas_COP-Utilidad_total
media_cuotas_COP_CON_C=vector()
volatilidad_cuotas_COP_CON_C=vector()
percentil_5_cuotas_COP_CON_C=vector()
percentil_95_cuotas_COP_CON_C=vector()
for(l in 1:5){
media_cuotas_COP_CON_C[l]=mean(Cuotas_COP_CON_C[l,])
volatilidad_cuotas_COP_CON_C[l]=sd(Cuotas_COP_CON_C[l,])
percentil_5_cuotas_COP_CON_C[l]=quantile(Cuotas_COP_CON_C[l,],0.05)
percentil_95_cuotas_COP_CON_C[l]=quantile(Cuotas_COP_CON_C[l,],0.95)
}
matplot(Cuotas_COP_CON_C,type = "l", col="#FFF8DC", main="Estimado Cuotas en COP", ylab = "Valor Cuota", xlab = "cuota")
lines(percentil_5_cuotas_COP_CON_C, col = "blue", type = "l")
lines(percentil_95_cuotas_COP_CON_C, col = "red", type = "l")
lines(media_cuotas_COP_CON_C, col = "black", type = "l")
legend("topright", legend = c("Percentil 5", "Percentil 95", "Media"),
col = c("blue", "red", "black"), lty = 1)
print("Volatilidad de cada cuota con cobertura en millones de COP")
## [1] "Volatilidad de cada cuota con cobertura en millones de COP"
print(volatilidad_cuotas_COP_CON_C/1000000)
## [1] 0.7060562 0.9935531 1.2319384 1.3859948 1.5154286
2.4 Beneficios reales de las series
Beneficio real sin cobertura
fecha <- c("17/10/2022", "17/11/2022", "17/12/2022", "17/01/2023", "17/02/2023")
valores_TRM <- c(4636.83, 4922.70, 4802.48, 4693.99, 4966.33)
# Crear un vector vacío para almacenar los valores de TRM_OBSERVADA
TRM_OBSERVADA <- numeric(length(fecha))
# Asignar los valores de TRM_OBSERVADA
for (j in 1:length(fecha)) {
TRM_OBSERVADA[j] <- valores_TRM[j]
}
Cuota_Real_COP=TRM_OBSERVADA*Cuotas_USD
matplot(Cuotas_COP,type = "l", col="#C1FFC1", main="Estimado Cuotas en COP", ylab = "Valor Cuota", xlab = "Cuota")
lines(percentil_5_cuotas, col = "blue", type = "l")
lines(percentil_95_cuotas, col = "red", type = "l")
lines(media_cuotas, col = "black", type = "l")
lines(Cuota_Real_COP, col = "orange", type = "l", lwd = 2)
legend("topright", legend = c( "Percentil 5", "Percentil 95", "Media"),
col = c( "blue", "red", "black"), lty = 1, lwd = c(1, 1, 1, 1))
"Cuota Real COP"
## [1] "Cuota Real COP"
print(Cuota_Real_COP)
## [1] 425373511 447926318 433404610 420112105 440781653
"Beneficio sin cobertura"
## [1] "Beneficio sin cobertura"
Utilidad_POR_USD_Observada=TRM_OBSERVADA-Precio_Entrega
Utilidad_total_observada= Cuotas_USD*Utilidad_POR_USD_Observada
Beneficio real con cobertura
Valor_Observado_Cuotas_con_cobertura=Cuota_Real_COP-Utilidad_total_observada
matplot(Cuotas_COP_CON_C,type = "l", col="#7FFF00", main="Estimado Cuotas en COP", ylab = "Valor Cuota", xlab = "Cuota")
lines(percentil_5_cuotas_COP_CON_C, type = "l")
lines(percentil_95_cuotas_COP_CON_C, type = "l")
lines(media_cuotas_COP_CON_C, type = "l")
lines(Valor_Observado_Cuotas_con_cobertura, type = "l", lwd=2)
2.5. Cuenta de margen con el flujo de caja operado
# Variables y las fórmulas
Numero_de_contratos <- 1
Nominal_del_contrato <- 1790000*0.7
Precio_inicial <- 4066 # TRM al momento 0
Exposicion_Total = Numero_de_contratos*Nominal_del_contrato*Precio_inicial
Exposicion_Contrato = Exposicion_Total/Numero_de_contratos
Garantia_Inicial <- 0.07
Margen_mantenimiento <- Garantia_Inicial/2
Valor_de_la_garantia_inicial = Exposicion_Total*Garantia_Inicial
Valor_de_la_garantía_minima = Margen_mantenimiento*Valor_de_la_garantia_inicial
Valor_de_la_garantia_inicial*Exposicion_Total
## [1] 1816916339784280320
Apalancamiento = Exposicion_Total/Valor_de_la_garantia_inicial
Apalancamiento
## [1] 14.28571
Se liquidan los precios futuros
TRM_Filas <- TRM[c(22, 43, 64, 85, 106), ]
Media_Filas <- rowMeans(TRM_Filas)
Media_TRM <- data.frame(Media_Futuro = Media_Filas)
Tabla_liquidacion <- Media_TRM
Media_TRM$fecha <- fecha
Media_TRM$TRM_OBSERVADA <- TRM_OBSERVADA
Media_TRM <- Media_TRM[, c("fecha", "TRM_OBSERVADA", "Media_Futuro")]
Tabla_liquidacion <- Media_TRM
Dif_Fut_TRM <- diff(Tabla_liquidacion[,3])*-1
Dif_Fut_TRM <- append(0,Dif_Fut_TRM)
Tabla_liquidacion <- cbind(Tabla_liquidacion,(Dif_Fut_TRM*Numero_de_contratos*Nominal_del_contrato))
colnames(Tabla_liquidacion) <- c("Fecha","TRM","Futuro","Liquidacion_Diaria")
Se calcula el llamada al margen
margen <- matrix()
tabaux <- matrix()
Llamado_al_margen <- matrix()
for (i in 1:(nrow(Tabla_liquidacion))) {
# Tabla Auxiliar
tabaux[1]=Valor_de_la_garantia_inicial
tabaux[i+1] <- tabaux[i] + Tabla_liquidacion$Liquidacion_Diaria[i+1]
# Llamado al Margen
Llamado_al_margen[i] <- if(tabaux[i]<Valor_de_la_garantía_minima){Valor_de_la_garantia_inicial-tabaux[i]}
else{0}
# Margen
margen[i] <- tabaux[i]+Llamado_al_margen[i]
}
margen <- na.omit(margen)
Tabla_liquidacion <- cbind(Tabla_liquidacion,margen,Llamado_al_margen,Dif_Fut_TRM)
print(Tabla_liquidacion)
## Fecha TRM Futuro Liquidacion_Diaria margen Llamado_al_margen
## 1 17/10/2022 4636.83 4437.923 0 356628860 0
## 2 17/11/2022 4922.70 4436.770 1444700 358073560 0
## 3 17/12/2022 4802.48 4444.042 -9111784 348961776 0
## 4 17/01/2023 4693.99 4438.774 6601335 355563111 0
## 5 17/02/2023 4966.33 4434.461 5403230 360966341 0
## Dif_Fut_TRM
## 1 0.000000
## 2 1.152993
## 3 -7.271975
## 4 5.268424
## 5 4.312235
2.6 ¿Cuál es la probabilidad de ser llamado al margen si solo se deposita en la cuenta el margen inicial?
llamadas_al_margen <- sum(Llamado_al_margen > 0)
probabilidad_llamado_al_margen <- llamadas_al_margen / nrow(Tabla_liquidacion)
cat("La probabilidad de ser llamado al margen es:", probabilidad_llamado_al_margen)
## La probabilidad de ser llamado al margen es: 0
La probabilidad de ser llamado al margen si solo se deposita en la cuenta el margen inicial es nula
¿Cuánto debería de haber en la cuenta de margen al inicio para que la probabilidad de ser llamado al margen antes de cubrir el primer flujo sea menor al 1%?
# Definir la probabilidad objetivo
probabilidad_objetivo <- 0.01
# Definir el rango inicial para la búsqueda binaria
min_garantia <- 0
max_garantia <- Exposicion_Total
# Realizar búsqueda binaria para encontrar la garantía inicial adecuada
while (max_garantia - min_garantia > 1) {
# Calcular la garantía inicial candidata
garantia_candidata <- (max_garantia + min_garantia) / 2
# Calcular el valor mínimo de la garantía
valor_de_la_garantia_minima <- Margen_mantenimiento * garantia_candidata
# Calcular la probabilidad de ser llamado al margen
probabilidad_llamado_al_margen <- mean(margen < valor_de_la_garantia_minima)
# Ajustar el rango según la probabilidad calculada
if (probabilidad_llamado_al_margen < probabilidad_objetivo) {
max_garantia <- garantia_candidata
} else {
min_garantia <- garantia_candidata
}
}
# La garantía inicial necesaria será el promedio de los valores min_garantia y max_garantia
garantia_inicial_necesaria <- (max_garantia + min_garantia) / 2
# Imprimir el resultado
cat("La garantía inicial necesaria para que la probabilidad de ser llamado al 1% es:", garantia_inicial_necesaria)
## La garantía inicial necesaria para que la probabilidad de ser llamado al 1% es: 0.2965505
Modelo Vasicek
dr(t) = k(- r_0)dt + dW
Como resultan las tasas simuladas con 10 iteraciones, para los siguientes 10 periodos, a 252 días.
r0<-0.0387
theta<-0.08
k<-0.44
beta<-0.03
n<-10
T<-10
m<-252
dt<-T/m
r<-matrix(0,m+1,n)
r[1,]<-r0
for (j in 1:n) {
for (i in 2:(m+1)) {
dr<-k*(theta-r[i-1,j])*dt+beta*sqrt(dt)*rnorm(1,0,1)
r[i,j]<-r[i-1,j]+dr
}
}
t1<-seq(0,T,dt)
rT.expected <- theta+(r0-theta)*exp(-k*t)
rT.stdev<-sqrt(beta^2/(2*k)*(1-exp(-2*k*t)))
matplot(t1, r[,1:10], type="l", lty=1, main="Short Rate Paths", ylab="rt")
abline(h=theta, col="red", lty=2)
lines(t, rT.expected, lty=2)
lines(t, rT.expected + 2*rT.stdev, lty=2)
lines(t, rT.expected - 2*rT.stdev, lty=2)
points(0,r0)
Con la curva de short rate paths se puede observar la evolución del comportamiento de las tasas de interés a corto plazo, sobre estas se espera un crecimiento constante en la mitad del tiempo y al final un crecimiento mas contundente, en su momento de estabilidad podemos deducir que la economía no tuvo mucha variación ni factores que hicieran que fluctuara mucho en el mercado
Como quedan las curvas yield de ambas tasas en los periodos descritos.
## function to find ZCB price using Vasicek model
VasicekZCBprice <-
function(r0, k, theta, beta, T){
b.vas <- (1/k)*(1-exp(-T*k))
a.vas <- (theta-beta^2/(2*k^2))*(T-b.vas)+(beta^2)/(4*k)*b.vas^2
return(exp(-a.vas-b.vas*r0))
}
## define model parameters for plotting yield curves
theta <- 0.10
k <- 0.5
beta <- 0.03
r0 <- seq(0.00, 0.20, 0.05)
n <- length(r0)
yield <- matrix(0, 10, n)
for(i in 1:n){
for(T in 1:10){
yield[T,i] <- -log(VasicekZCBprice(r0[i], k, theta, beta, T))/T
}
}
maturity <- seq(1, 10, 1)
matplot(maturity, yield, type="l", col="black", lty=1, main="Yield Curve Shapes")
abline(h=theta, col="red",lty=2)
En la grafica de la curva de yield podemos analizar la relacion que se tiene con los rendimientos y la madurez de la TRM, la cual representan el riesgo que se tiene, Presentan un compartimiento constante en el cual se observa que su estado en el mercado no ha sido tan fluctuante en la madurez de 5 a 10