## Warning: package 'readxl' was built under R version 4.5.2
## Warning: package 'ggplot2' was built under R version 4.5.1
## Warning: package 'imputeTS' was built under R version 4.5.2
## Registered S3 method overwritten by 'quantmod':
## method from
## as.zoo.data.frame zoo
# Con esta librería podemos utilizar la función "dollar" para expresar cifras en unidades monetarias.
library(scales)## Warning: package 'scales' was built under R version 4.5.1
## Warning: package 'quantmod' was built under R version 4.5.2
## Cargando paquete requerido: xts
## Cargando paquete requerido: zoo
##
## Adjuntando el paquete: 'zoo'
## The following object is masked from 'package:imputeTS':
##
## na.locf
## The following objects are masked from 'package:base':
##
## as.Date, as.Date.numeric
## Cargando paquete requerido: TTR
## Warning: package 'writexl' was built under R version 4.5.2
getSymbols(Symbols= c("MXN=X"), from="2020-01-01",to="2025-10-31",
periodicity = "daily", src = "yahoo")## Warning: MXN=X contains missing values. Some functions will not work if objects
## contain missing values in the middle of the series. Consider using na.omit(),
## na.approx(), na.fill(), etc to remove or replace them.
## [1] "MXN=X"
getSymbols(Symbols= c("ZC=F"), from="2020-01-01",to="2025-10-31",
periodicity = "daily", src = "yahoo")## Warning: ZC=F contains missing values. Some functions will not work if objects
## contain missing values in the middle of the series. Consider using na.omit(),
## na.approx(), na.fill(), etc to remove or replace them.
## [1] "ZC=F"
getSymbols(Symbols= c("ZW=F"), from="2020-01-01",to="2025-10-31",
periodicity = "daily", src = "yahoo")## Warning: ZW=F contains missing values. Some functions will not work if objects
## contain missing values in the middle of the series. Consider using na.omit(),
## na.approx(), na.fill(), etc to remove or replace them.
## [1] "ZW=F"
## MXN=X.Adjusted
## 2025-01-01 NA
## 2025-04-17 NA
## 2025-04-20 NA
## ZW=F.Adjusted
## 2023-11-23 NA
## 2025-05-26 NA
## 2025-06-19 NA
## 2025-07-04 NA
## ZC=F.Adjusted
## 2023-11-23 NA
## 2025-05-26 NA
## 2025-06-19 NA
## 2025-07-04 NA
rets.usdmxn <- diff(log(usdmxn.na))
rets.Fwheat <- diff(log(Fwheat.na))
rets.Fcorn <- diff(log(Fcorn.na))# Primero convertimos cada serie a xts si no lo es
usdmxn.xt <- as.xts(usdmxn)
Fwheat.xt <- as.xts(Fwheat)
Fcorn.xt <- as.xts(Fcorn)
# Hacemos el merge por fecha con NAs permitidos
merged <- merge(usdmxn.xt, Fwheat.xt, Fcorn.xt)## Para obtener la varianza de los cambios porcentuales
rets <- na.omit(rets)
mean.usdmxn <- mean(rets$rets.usdmxn, na.rm = TRUE)
var.usdmxn <- var(rets$rets.usdmxn, na.rm = TRUE)
vol.usdmxn <- sd(rets$rets.usdmxn, na.rm = TRUE)
mean.usdmxn## [1] -1.798561e-05
## rets.usdmxn
## rets.usdmxn 7.647583e-05
## [1] 0.008745046
mean.Fwheat <- mean(rets$rets.Fwheat, na.rm = TRUE)
var.Fwheat <- var(rets$rets.Fwheat, na.rm = TRUE)
vol.Fwheat <- sd(rets$rets.Fwheat, na.rm = TRUE)
mean.Fwheat## [1] -5.152401e-05
## rets.Fwheat
## rets.Fwheat 0.0005037217
## [1] 0.02244374
mean.Fcorn <- mean(rets$rets.Fcorn, na.rm = TRUE)
var.Fcorn <- var(rets$rets.Fcorn, na.rm = TRUE)
vol.Fcorn <- sd(rets$rets.Fcorn, na.rm = TRUE)
mean.Fcorn## [1] 7.322026e-05
## rets.Fcorn
## rets.Fcorn 0.0003476655
## [1] 0.01864579
## [1] 0.0608428
## [1] -0.037751
## [1] 0.1970139
## [1] -0.1129709
## [1] 0.07657358
## [1] -0.1909974
library(xts)
library(writexl)
library(readxl)
## 1. Unir las tres series por fecha
merged <- merge(usdmxn.xt, Fwheat.xt, Fcorn.xt) # índices por fecha
merged <- na.omit(merged) # quita filas con NA
## 2. Convertir a data.frame y poner nombres de columnas
df_precios <- data.frame(
Fecha = index(merged),
P.usdmxn = as.numeric(merged[, 1]),
P.Fwheat = as.numeric(merged[, 2]),
P.Fcorn = as.numeric(merged[, 3])
)
getwd()## [1] "C:/Users/GTX/OneDrive - Instituto Tecnologico y de Estudios Superiores de Monterrey/Documents/Tec/Negocios/5to semestre/Periodo 5/Financial modelling and programming/modelopoisson"
## [1] "dailygccdatavar.xlsx" "modelopoisson.Rmd"
## [3] "multassets_mc.Rmd" "PF_sec_agropecuario.html"
## [5] "PF_sec_agropecuario.Rmd" "precios_series.xlsx"
## [7] "rets_eruo.xlsx" "rets_series.xlsx"
# Con esta instrucción conocemos la cantidad de filas con espacios tipo NA (Not Available)
datagcc[!complete.cases(datagcc),]## # A tibble: 0 × 4
## # ℹ 4 variables: Fecha <dttm>, P.usdmxn <dbl>, P.Fwheat <dbl>, P.Fcorn <dbl>
# Hacemos interpolación tipo spline para ocupar los espacios en blanco, de esa forma se evita la pérdida de información.
precios.int<-na_interpolation(datagcc,option = "spline")## # A tibble: 0 × 4
## # ℹ 4 variables: Fecha <dttm>, P.usdmxn <dbl>, P.Fwheat <dbl>, P.Fcorn <dbl>
La transformación se realiza con cambios porcentuales de su forma normal, en vez de utilizar logaritmo de precios, ya que se tienen precios negativos de los futuros del WTI y al obtener las primeras diferencias se genera error.
# Quitar la columna Fecha (asumo que es la 1)
precios.matriz <- data.matrix(precios.int[, -1]) # o precios.int[ , c("P.usdmxn","P.Fwheat","P.Fcorn")]
# Primeras diferencias simples
precios.diff <- diff(precios.matriz, lag = 1)
rets <- diff(log(precios.matriz), lag = 1)
colnames(rets) <- c("rets.usdmxn", "rets.Fwheat", "rets.Fcorn")## Warning: `aes_string()` was deprecated in ggplot2 3.0.0.
## ℹ Please use tidy evaluation idioms with `aes()`.
## ℹ See also `vignette("ggplot2-in-packages")` for more information.
## ℹ The deprecated feature was likely used in the ggcorrplot package.
## Please report the issue at <https://github.com/kassambara/ggcorrplot/issues>.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
La descomposición de Cholesky permite “descomponer” una matriz original en una matriz triangular [A], que después al obtener su traspuesta, será la matriz que buscamos como insumo para obtener números aleatorios correlacionados.
# cor=A*AT
# A es la matriz de Cholesky "mat.chol"
mat.chol<-chol(correts)
# AT es la traspuesta de la matriz de Cholesky
tmat.chol<-t(mat.chol)
tmat.chol## P.usdmxn P.Fwheat P.Fcorn
## P.usdmxn 1.00000000 0.0000000 0.0000000
## P.Fwheat -0.06645563 0.9977894 0.0000000
## P.Fcorn -0.02311026 0.4354520 0.8999153
Primero obtengamos una matriz de números aleatorios independientes de un renglón y después generalizamos a “n”. Se observa que el renglón corresponde a 10 columnas ya que son 10 factores de riesgo.
set.seed(2425)
obs <- 100 # número de escenarios
n_factores <- 3 # usd/mxn, wheat, corn
# 1. Matriz de choques independientes N(0,1)
matrands <- matrix(rnorm(obs * n_factores, mean = 0, sd = 1),
nrow = obs,
ncol = n_factores)
# 2. Matriz de Cholesky (de tu matriz de correlaciones o covarianzas)
# correts ya es cor(rets.precios) o similar
mat.chol <- chol(correts) # 3x3
tmat.chol <- t(mat.chol) # 3x3, triangular inferior
# 3. Obtener choques correlacionados
# (100x3) %*% (3x3) = (100x3)
aleafactores.correl <- as.data.frame(matrands %*% tmat.chol)
head(aleafactores.correl)## P.usdmxn P.Fwheat P.Fcorn
## 1 -0.5567355 -0.3644732 -1.123517244
## 2 0.7306805 0.6334775 1.141765582
## 3 0.8900516 -0.4588709 0.848406457
## 4 1.4049766 -0.2294881 0.009080274
## 5 0.7621400 1.9827812 0.890469801
## 6 0.3944832 -1.0071678 -1.164503311
Después, extraemos la columna de los números aleatorios correlacionados de dos factores de riesgos USDMXN, Fwheat y Fcorn.
Se simulan los índices USDMXN, Fwheat y Fcorn
# Obtenemos el último precio de usdmxn, se trabaja sobre el objeto "precios.int" para poder aplicar el símbolo $ y pueda leer sobre la columna P.usdmxn
lastusdmxn<-tail(precios.int$P.usdmxn,1)
lastusdmxn## [1] 18.4657
## [1] -5.610813e-05
## [1] 7.597163e-05
## [1] 0.008716171
## [1] 524.25
# Estadísticos de rendimientos
meanFwheat <- mean(rets.precios$P.Fwheat)
varFwheat <- var(rets.precios$P.Fwheat)
sdFwheat <- sd(rets.precios$P.Fwheat)
meanFwheat## [1] -0.000302285
## [1] 0.0004989606
## [1] 0.02233743
## [1] 430.25
# Estadísticos de rendimientos
meanFcorn <- mean(rets.precios$P.Fcorn)
varFcorn <- var(rets.precios$P.Fcorn)
sdFcorn <- sd(rets.precios$P.Fcorn)
meanFcorn## [1] -0.0001025247
## [1] 0.0003608217
## [1] 0.01899531
Definimos nivel de significancia y posición
Reordenamos los precios simulados
Obtenemos la posición de los precios ordenados
qalfa.usdmxn<-sortusdmxn[posicion,]
qalfa.Fwheat<-sortFwheat[posicion,]
qalfa.Fcorn<-sortFcorn[posicion,]
qalfa.usdmxn## [1] 18.21177
## [1] 501.7428
## [1] 417.2687
## [1] -0.01375164
## [1] -13751.64
## [1] -0.04293216
## [1] -42932.16
## [1] -0.03017149
## [1] -30171.49
La pérdida esperada en los 3 factores de riesgo, después de haber reconocido el efecto de la correlación entre ellos.
## [1] "-$86,855.28"
Vamos a suponer que los factores de riesgos son independientes, ¿cuál sería la pérdida en la posición total en los 3 factores? Primero creamos números aleatorios independientes.
# USD/MXN sin correlación
set.seed(2121)
h <- 1
rand.usdmxn <- as.matrix(rnorm(obs, mean = 0, sd = 1))
simul.usdmxn.sc <- NULL
for (rands in rand.usdmxn) {
preciotemp <- lastusdmxn * exp((meanusdmxn - 0.5 * varusdmxn) * h +
sdusdmxn * sqrt(h) * rands)
simul.usdmxn.sc <- rbind(simul.usdmxn.sc, preciotemp)
}# Corn sin correlación
rand.Fcorn <- as.matrix(rnorm(obs, mean = 0, sd = 1))
simul.Fcorn.sc <- NULL
for (rands in rand.Fcorn) {
preciotemp <- lastFcorn * exp((meanFcorn - 0.5 * varFcorn) * h +
sdFcorn * sqrt(h) * rands)
simul.Fcorn.sc <- rbind(simul.Fcorn.sc, preciotemp)
}Reordenamos los precios simulados
Obtenemos la posición de los precios ordenados
qalfa.usdmxn.sc<-sortusdmxn.sc[posicion,]
qalfa.Fwheat.sc<-sortFwheat.sc[posicion,]
qalfa.Fcorn.sc<-sortFcorn.sc[posicion,]
qalfa.usdmxn.sc## [1] 18.2287
## [1] 500.5353
## [1] 417.8066
## [1] 18.4657
## [1] -0.01283445
# Suponemos posición de 1 millón de USD en usdmxn
VaR.m.usdmxn.sc<-1000000*VaR.usdmxn.sc
VaR.m.usdmxn.sc## [1] -12834.45
## [1] 524.25
## [1] -0.04523544
# Suponemos posición de 1 millón en Wheat
VaR.m.Fwheat.sc <- 1000000 * VaR.Fwheat.sc
VaR.m.Fwheat.sc## [1] -45235.44
## [1] 430.25
## [1] -0.02892142
## [1] -28921.42
La pérdida esperada en los 3 factores de riesgo
## [1] "-$86,991.32"