Santiago López, Esteban Moncada, Juana Marín
Descripción de la actividad
Descargue la TRM desde el año 2000 hasta el día de hoy y responda las siguientes preguntas asignando probabilidades basadas en frecuencia y bajo el supuesto de que los rendimientos siguen una distribución normal:
1. ¿Cómo se analiza estadísticamente el precio de la TRM en este lapso de información?
Primero, se descargó la base de datos para realizar el análisis correspondiente
TRM_datos<-read.csv(file = "trm2000.csv", header = TRUE, sep = ";")
head(TRM_datos)
class(TRM_datos[,"Fecha"])
TRM_datos[,"Fecha"]<-as.Date(TRM_datos[,"Fecha"],format = "%d/%m/%Y")
class(TRM_datos[,"Fecha"])
plot(TRM_datos[,"Fecha"],TRM_datos[,"TRM"], type = "l", main = "Serie Historica TRM")Dada la gráfica anterior, se pueden observar cambios notables durante el periodo analizado, tales como la volatilidad en el valor de la TRM alrededor del año 2008 causada por la crisis inmobiliaria en Estados Unidos. En el periodo comprendido entre 2010 y 2015, el dolár presentó una tendencia bajista debido a las dificultades generadas por la crisis tales como nuevas políticas monetarias, desempleo, aumento de la deuda externa, falta de confianza en la moneda dada su lenta recuperación financiera.A su vez también se produjo un aumento histórico durante del año 2015 a causa del colapso del valor del petróleo a nivel mundial que genero una devaluación en la moneda colombiana.
Posteriormente, se calcularon los rendimientos de la TRM durante el periodo seleccionado (2000-2024) y se graficaron los histogramas correspondientes para facilitar el análisis del comportamiento de la variable.
# Rendimientos de la TRM
rendimiento<-diff(log(TRM_datos[,"TRM"]))
plot(TRM_datos[-1,"Fecha"],rendimiento, type = "l", main = "Serie Histórica Rendimientos Diarios TRM")# Histogramas
hist(TRM_datos[,"TRM"], breaks = 30, col = "#465cb3", main = "Histograma de precios", freq = FALSE)hist(rendimiento, breaks = 50, col = "#465cb3", main = "Histograma de rendimientos", freq = FALSE, xlim = c(-0.02,0.02))# Calculo de Medidas de Tendencia Central
# Load necessary packages
if (!requireNamespace("e1071", quietly = TRUE)) {
install.packages("e1071")
}
library(e1071)## Warning: package 'e1071' was built under R version 4.3.3
library(knitr)
ResumenEstadisticoTRM<- data.frame(
Minimo = min(TRM_datos[,"TRM"]),
Maximo = max(TRM_datos[,"TRM"]),
Media = mean(TRM_datos[,"TRM"]),
Desviacion = sd(TRM_datos[,"TRM"]),
Sesgo = skewness(TRM_datos[,"TRM"]),
Curtosis = kurtosis(TRM_datos[,"TRM"])
)
knitr::kable(ResumenEstadisticoTRM)| Minimo | Maximo | Media | Desviacion | Sesgo | Curtosis |
|---|---|---|---|---|---|
| 1652.41 | 5061.21 | 2660.824 | 762.3418 | 0.8967354 | 0.0409679 |
En el análisis estadístico del precio de la Tasa de Cambio Representativa del Mercado (TRM) desde el año 2000 hasta el 2024, se implementaron diversas medidas descriptivas para comprender la distribución de los datos. Esto incluyó el cálculo de la media, desviación estándar, cuantiles, mínimo y máximo, proporcionando una visión detallada de la tendencia central, dispersión y rango de la TRM a lo largo del tiempo.
Además, se evaluaron medidas de forma de la distribución, como el sesgo y la curtosis, para comprender la simetría y la forma de las colas de la distribución, lo que contribuye a la comprensión de la normalidad o presencia de sesgos en la TRM.
El análisis se extendió al rendimiento de la TRM, explorando variaciones porcentuales o rendimientos logarítmicos para comprender mejor la dinámica de cambio en la tasa de cambio. La visualización a través de histogramas permitió identificar patrones, tendencias y posibles anomalías en la variabilidad de la TRM.
Asimismo, se observaron las tendencias temporales de la TRM a lo largo del período, identificando cambios significativos, periodos de volatilidad o estabilidad en la tasa de cambio como se mencionó anteriormente. Se consideraron también posibles conexiones con factores externos, analizando relaciones con variables económicas, políticas o comerciales que podrían haber influido en su comportamiento.
En resumen, el análisis proporcionó una comprensión integral de la TRM desde el 2000 hasta el 2024, destacando tendencias dominantes, periodos de volatilidad y posibles influencias externas. Estos hallazgos son fundamentales para comprender la evolución de la TRM a lo largo del tiempo.
2. ¿Es necesario acortar la información teniendo en cuenta que la TRM ha variado tanto en 20 años? Sustente su respuesta con fundamentos financieros o económicos.
#Percentiles
quantile(TRM_datos[,"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%
## 1762.380 1791.625 1838.275 2389.750 3054.020 3856.000 4093.180 4802.480
quantile(rendimiento,c(0.01,0.05,0.1,0.5,0.75,0.90,0.95,0.99))## 1% 5% 10% 50% 75% 90%
## -0.016723469 -0.008985171 -0.005719345 0.000000000 0.001295553 0.005983632
## 95% 99%
## 0.009561866 0.019031630
quantile(rendimiento, c(0.05,0.95))## 5% 95%
## -0.008985171 0.009561866
qqnorm(rendimiento)
qqline(rendimiento)# Corte
breaks<-c(min(rendimiento)-0.0000001,-0.01)
corte<-cut(rendimiento,breaks)
tabla<-table(corte)
print(tabla)## corte
## (-0.0562,-0.01]
## 359
probabilidad<-tabla/length(rendimiento)
print(probabilidad)## corte
## (-0.0562,-0.01]
## 0.04072604
# Histograma de Rendimientos (Supuesto de normalidad)
hist(rendimiento, breaks = 50, col = "#465cb3", main = "Histograma de rendimientos", freq = FALSE, xlim = c(-0.02,0.02))
curve(dnorm(x,mean=mean(rendimiento),sd=sd(rendimiento)),-0.02,0.02,add = T,col="blue")cuantiles<-c(0.01,0.025,0.05,0.1,0.25,0.40,0.45,0.5,0.75,0.9,0.95,0.975,0.99)
qnorm(cuantiles,mean = mean(rendimiento),sd=sd(rendimiento))## [1] -0.0136968356 -0.0115264995 -0.0096598907 -0.0075078103 -0.0039117784
## [6] -0.0014170696 -0.0006607018 0.0000836742 0.0040791268 0.0076751587
## [11] 0.0098272391 0.0116938478 0.0138641839
quantile(rendimiento, cuantiles)## 1% 2.5% 5% 10% 25% 40%
## -0.016723469 -0.012630315 -0.008985171 -0.005719345 -0.001425601 0.000000000
## 45% 50% 75% 90% 95% 97.5%
## 0.000000000 0.000000000 0.001295553 0.005983632 0.009561866 0.013183574
## 99%
## 0.019031630
qnorm(c(0.05,0.95),mean = mean(rendimiento),sd=sd(rendimiento))## [1] -0.009659891 0.009827239
pnorm(-0.01,mean =mean(rendimiento),sd=sd(rendimiento))## [1] 0.04435248
# Resumen estadístico de los rendimientos
ResumenEstadisticoTRMRendimiento<- data.frame(
Minimo = min(rendimiento),
Maximo = max(rendimiento),
Media = mean(rendimiento),
Desviacion = sd(rendimiento),
Sesgo = skewness(rendimiento),
Curtosis = kurtosis(rendimiento)
)
knitr::kable(ResumenEstadisticoTRMRendimiento)| Minimo | Maximo | Media | Desviacion | Sesgo | Curtosis |
|---|---|---|---|---|---|
| -0.0562194 | 0.0593067 | 8.37e-05 | 0.0059237 | 0.2697206 | 9.808365 |
Teninedo en cuenta la gran variación que la Tasa de Cambio Representativa del Mercado (TRM) ha experimentado en los últimos 20 años, ciertos momentos históricos pueden no reflejar la totalidad del comportamiento de la TRM, ya que algunos factores que afectaron la tasa en el pasado pueden no ser relevantes de su comportamiento actual.
Considerar con mayor importancia los valores más recientes es una mejor estrategia. Dado que la TRM puede estar influenciada por eventos políticos, económicos y financieros de actualidad, otorgar mayor peso a los datos más recientes puede ofrecer una representación más precisa de la realidad del momento. Si bien la muestra diaria proporciona una perspectiva detallada, el cálculo del precio promedio puede conducir a un valor de TRM que no necesariamente refleja la realidad del mercado
Estimación de escenarios
Sabiendo que el valor del activo es al día de hoy, estime un intervalo de confianza del 95% para el valor en pesos de una importación de 500.000 USD. ¿Cuál es la probabilidad de obtener una perdida de hasta un 3% en un día? y la probabilidad de ganar hasta un 5% en un día?
# Probabilidad de pérdida de hasta un 3% en un día
Tres<-pnorm(-0.03,mean =mean(rendimiento),sd=sd(rendimiento))
print("Hay una probabilidad pérdida de hasta un 3% en un día de ")
Tres
# Probabilidad de ganar hasta un 5% en un día
Cinco<-1-pnorm(0.05,mean =mean(rendimiento),sd=sd(rendimiento))
print("Hay una probabilidad de ganar hasta un 5% en un día")
Cinco
# ¿Si usted invierte 10.000.000 COP cual es la probabilidad de obtener perdidas entre -500.000 Y 500.000 COP en un día?
Prop = 500000/10000000
Inv<-pnorm(Prop,mean =mean(rendimiento),sd=sd(rendimiento))
print("La probabilidad de obtener perdidas entre -500.000 Y 500.000 COP en un día es de ")
Inv## [1] "Hay una probabilidad pérdida de hasta un 3% en un día de "
## [1] 1.901571e-07
## [1] "Hay una probabilidad de ganar hasta un 5% en un día"
## [1] 0
## [1] "La probabilidad de obtener perdidas entre -500.000 Y 500.000 COP en un día es de "
## [1] 1
** Descripción de actividad**
Usted toma una posición corta en 10 contratos de futuros de la TRM (TRMH24F) y que tienen un precio actual de 4198 COP por cada USD. Sabiendo que cada contrato es de 50.000 USD y que usted deposita 150.000.000 de COP en la cuenta de margen, realice una simulación de Montecarlo con 10.000 iteraciones bajo el supuesto de que los rendimientos continuos mensuales del futuro, siguen una distribución normal con media de 1% y desviación estándar del 3%, para determinar:
# Leer Datos
TRM_FUTURO<-read.table(file = "futuros_TRM.txt", header = TRUE, sep = "")
F_rendimiento<-diff(log(TRM_FUTURO[,"F_TRM"]))
# Simulacion
N=10000
Trm_Simulado=matrix(,90,N)
TRM_Inicial=4198
Trm_Simulado[1,]=TRM_Inicial
for(j in 1:N){
for(i in 2:90){
Trm_Simulado[i,j]=TRM_Inicial*exp(rnorm(1,mean =mean(F_rendimiento),sd=sd(F_rendimiento)))
}
}
matplot(Trm_Simulado,type = "l", col = "gray", main="FUTURO TRM SIMULADA")Trm_Simulado<-t(Trm_Simulado)
#Posicion en corto
Posicion<-Trm_Simulado[,90]-Trm_Simulado[,1]
Trm_Simulado<-cbind(Trm_Simulado,Posicion)
sum(Trm_Simulado[,90]>0)
sum(Trm_Simulado[,90]<0)
mean(Trm_Simulado[,90])
sd(Trm_Simulado[,90])
# Cantidad de cortos y largos obtenidos
largos=sum(Trm_Simulado[,91]>0)
cortos<-N-largos
largos/N*100
cortos/N*100
# Promedio de largos y cortos obtenidos
promlargos<-0
for(k in 1:N) {
if (Trm_Simulado[k,91]>0) {promlargos=promlargos+Trm_Simulado[k,91]}
}
LargoPayoff<-(promlargos/largos)*10000
promcortos<-0
for(k in 1:N) {
if (Trm_Simulado[k,91]<0) {promcortos=promcortos+Trm_Simulado[k,91]}
}
CortoPayoff<-(promcortos/-cortos)*10000
print("Si se toma una posición de largo, la cantidad de largos obtenida es: ")
largos
print("Si se toma una posición de corto, la cantidad de cortos obtenida es: ")
cortos## [1] 10000
## [1] 0
## [1] 4194.828
## [1] 50.08411
## [1] 47.62
## [1] 52.38
## [1] "Si se toma una posición de largo, la cantidad de largos obtenida es: "
## [1] 4762
## [1] "Si se toma una posición de corto, la cantidad de cortos obtenida es: "
## [1] 5238
Se plantea la liquidación diaria del Derivado TRMH24F, el cuál se calculó bajo el siguiente procedimiento
# ------------------------------------------------------------------------------
# Definicion de variables
ndecontratos<-10
nominaldelc<-50000
precioini<-TRM_Inicial
garantiainicial<-0.35
mantenimiento<-0.18
# Formulas iniciales
ExposicionTotal<-ndecontratos*nominaldelc*precioini
vlrGarantiaInicial<-garantiainicial*ExposicionTotal
vlrGarantiaMinima<-mantenimiento*vlrGarantiaInicial
Apalancamiento<- ExposicionTotal/vlrGarantiaInicial
#Tabla de Liquidacion
tablaliq<-TRM_FUTURO
Dif_FTrm<-diff(tablaliq[,3])
Dif_FTrm<-append(0,Dif_FTrm)
tablaliq<-cbind(tablaliq,(Dif_FTrm*ndecontratos*nominaldelc))
# Nombres de Columnas
colnames(tablaliq) <- c("fecha","TRM","Futuro","LiquidacionDiaria")
# Calculo Tabla Auxiliar Margen y llamado al margen
margen<-matrix()
tabaux<-matrix()
llamado_margen<-matrix()
for (i in 1:(nrow(tablaliq))) {
# Tabla Auxiliar
tabaux[1]=vlrGarantiaInicial
tabaux[i+1] <- tabaux[i] + tablaliq$LiquidacionDiaria[i+1]
# Llamado al Margen
llamado_margen[i] <- if(tabaux[i]<vlrGarantiaMinima){vlrGarantiaInicial-tabaux[i]}
else{0}
# Margen
margen[i]<-tabaux[i]+llamado_margen[i]
}
margen<-na.omit(margen)
tablaliq<-cbind(tablaliq,margen,llamado_margen,Dif_FTrm)
knitr::kable(tail(tablaliq, 15))| fecha | TRM | Futuro | LiquidacionDiaria | margen | llamado_margen | Dif_FTrm | |
|---|---|---|---|---|---|---|---|
| 82 | 31/01/2024 | 3925.60 | 3959.00 | 415000 | 567595000 | 0 | 0.83 |
| 83 | 1/02/2024 | 3915.56 | 3916.80 | -21100000 | 546495000 | 0 | -42.20 |
| 84 | 2/02/2024 | 3889.05 | 3966.00 | 24600000 | 571095000 | 0 | 49.20 |
| 85 | 5/02/2024 | 3928.11 | 3995.00 | 14500000 | 585595000 | 0 | 29.00 |
| 86 | 6/02/2024 | 3975.74 | 3974.80 | -10100000 | 575495000 | 0 | -20.20 |
| 87 | 7/02/2024 | 3950.57 | 3989.81 | 7505000 | 583000000 | 0 | 15.01 |
| 88 | 8/02/2024 | 3962.23 | 3980.20 | -4805000 | 578195000 | 0 | -9.61 |
| 89 | 9/02/2024 | 3954.68 | 3943.10 | -18550000 | 559645000 | 0 | -37.10 |
| 90 | 12/02/2024 | 3926.08 | 3939.50 | -1800000 | 557845000 | 0 | -3.60 |
| 91 | 13/02/2024 | 3915.28 | 3945.00 | 2750000 | 560595000 | 0 | 5.50 |
| 92 | 14/02/2024 | 3929.00 | 3937.15 | -3925000 | 556670000 | 0 | -7.85 |
| 93 | 15/02/2024 | 3916.61 | 3928.00 | -4575000 | 552095000 | 0 | -9.15 |
| 94 | 16/02/2024 | 3909.89 | 3928.90 | 450000 | 552545000 | 0 | 0.90 |
| 95 | 19/02/2024 | 3917.84 | 3933.06 | 2080000 | 554625000 | 0 | 4.16 |
| 96 | 20/02/2024 | 3917.84 | 3941.35 | 4145000 | 558770000 | 0 | 8.29 |
Plantear un intervalo de predicción del 90% del valor de la cuenta de margen para dentro de un mes.
qnorm(c(0.05,0.95),mean = mean(head(tablaliq$margen,30)),sd=sd(head(tablaliq$margen,30)))## [1] 611004219 826890114
La probabilidad de perder mas de 10.000.000 COP en un mes
ProporcionPerdida <- 10000000/150000000
Prob10Perdida<-pnorm(ProporcionPerdida,mean=mean(head(tablaliq$margen,30)),sd=sd(head(tablaliq$margen,30)))
print("La probalidad de perder mas de 10.000.000 COP en un mes es de: ")## [1] "La probalidad de perder mas de 10.000.000 COP en un mes es de: "
Prob10Perdida## [1] 3.128559e-28
Si el margen mínimo es de 130.000.000 COP ¿Cuál es la probabilidad de ser llamado al margen?
# Formulas iniciales
ExposicionTotal<-ndecontratos*nominaldelc*precioini
vlrGarantiaInicial<-garantiainicial*ExposicionTotal
vlrGarantiaMinima<-130000000
Apalancamiento<- ExposicionTotal/vlrGarantiaInicial
#Tabla de Liquidacion
tablaliq<-TRM_FUTURO
Dif_FTrm<-diff(tablaliq[,3])
Dif_FTrm<-append(0,Dif_FTrm)
tablaliq<-cbind(tablaliq,(Dif_FTrm*ndecontratos*nominaldelc))
# Nombres de Columnas
colnames(tablaliq) <- c("fecha","TRM","Futuro","LiquidacionDiaria")
# Calculo Tabla Auxiliar Margen y llamado al margen
margen<-matrix()
tabaux<-matrix()
llamado_margen<-matrix()
for (i in 1:(nrow(tablaliq))) {
# Tabla Auxiliar
tabaux[1]=vlrGarantiaInicial
tabaux[i+1] <- tabaux[i] + tablaliq$LiquidacionDiaria[i+1]
# Llamado al Margen
llamado_margen[i] <- if(tabaux[i]<vlrGarantiaMinima){vlrGarantiaInicial-tabaux[i]}
else{0}
# Margen
margen[i]<-tabaux[i]+llamado_margen[i]
}
margen<-na.omit(margen)
tablaliq<-cbind(tablaliq,margen,llamado_margen,Dif_FTrm)
# Cantidad de veces que se llamó al margen
LlamadoOcurrido<- sum(tablaliq$llamado_margen != 0)
print("La cantidad de veces que se llamó al margen fue")## [1] "La cantidad de veces que se llamó al margen fue"
LlamadoOcurrido## [1] 0
# Probabilidad de que se llame al margen
Prob_LlamadoMargen<-(LlamadoOcurrido/nrow(tablaliq))*100
print("La probabilidad de que se llame al margen es de")## [1] "La probabilidad de que se llame al margen es de"
Prob_LlamadoMargen## [1] 0
TRM_datos<-read.csv(file = "trm2000.csv", header = TRUE, sep = ";")
rendimiento<-diff(log(TRM_datos[,"TRM"]))
#1.1 Graficamos los histogramas correspondiente
hist(TRM_datos[,"TRM"], breaks = 30, col = "green", main = "histograma de precios", freq = FALSE)hist(rendimiento, breaks = 50, col = "red", main = "histograma de rendimientos", freq = FALSE, xlim = c(-0.02,0.02))#Creamos el dataframe con
Tabla<- data.frame(
media = mutrm<-mean(TRM_datos[,"TRM"]),
volatilidad = sdtrm<-sd(TRM_datos[,"TRM"]),
mediadelosrendimientos = mu<- mean(rendimiento)*252,
volatilidaddelosrendimientos = sigma <- sd(rendimiento)*sqrt(252),
cuantiles=quantile(TRM_datos[,"TRM"],c(0.01,0.05,0.1,0.5,0.75,0.90,0.95,0.99)),
sesgo=skewness(TRM_datos[,"TRM"]),
curtosis=kurtosis(TRM_datos[,"TRM"]),
maximo=max(TRM_datos[,"TRM"]),
minimo=min(TRM_datos[,"TRM"])
)
knitr::kable(Tabla)| media | volatilidad | mediadelosrendimientos | volatilidaddelosrendimientos | cuantiles | sesgo | curtosis | maximo | minimo | |
|---|---|---|---|---|---|---|---|---|---|
| 1% | 2660.824 | 762.3418 | 0.0210859 | 0.0940353 | 1762.380 | 0.8967354 | 0.0409679 | 5061.21 | 1652.41 |
| 5% | 2660.824 | 762.3418 | 0.0210859 | 0.0940353 | 1791.625 | 0.8967354 | 0.0409679 | 5061.21 | 1652.41 |
| 10% | 2660.824 | 762.3418 | 0.0210859 | 0.0940353 | 1838.275 | 0.8967354 | 0.0409679 | 5061.21 | 1652.41 |
| 50% | 2660.824 | 762.3418 | 0.0210859 | 0.0940353 | 2389.750 | 0.8967354 | 0.0409679 | 5061.21 | 1652.41 |
| 75% | 2660.824 | 762.3418 | 0.0210859 | 0.0940353 | 3054.020 | 0.8967354 | 0.0409679 | 5061.21 | 1652.41 |
| 90% | 2660.824 | 762.3418 | 0.0210859 | 0.0940353 | 3856.000 | 0.8967354 | 0.0409679 | 5061.21 | 1652.41 |
| 95% | 2660.824 | 762.3418 | 0.0210859 | 0.0940353 | 4093.180 | 0.8967354 | 0.0409679 | 5061.21 | 1652.41 |
| 99% | 2660.824 | 762.3418 | 0.0210859 | 0.0940353 | 4802.480 | 0.8967354 | 0.0409679 | 5061.21 | 1652.41 |
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.
#REALIZAMOS LA SIMULACIÓN CON LOS SIGUIENTES PARÁMETROS
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((mu-sigma^2/2)*delta_t+sigma*sqrt(delta_t)*rnorm(1))
}
}3.1 Graficamos la distribución empirica
plot(density(S[N+1,]),ylab = "",xlab = "", main = "DISTRIBUCION EMPIRICA", lwd = 3)
alpha=0.05
q1=quantile(S[(N+1),],(alpha/2))
q2=quantile(S[(N+1),],(1-alpha/2))
abline(h = NULL, v = q1, col = "blue", lwd=2)
abline(h = NULL, v = q2, col = "green", lwd=2)
3.2 Calcule los cuantiles al 2.5% y 97.5% de los posibles precios
alpha=0.05
q1=quantile(S[(N+1),],(alpha/2))
q2=quantile(S[(N+1),],(1-alpha/2))3.3 Grafique sus resultados.
#Gráfico de la simulacíon
matplot(S, type="l")
2. Calcule de manera teórica un intervalo de confianza al 95% sobre los
posibles precios futuros de la TRM
MU=mean(S)
SIGMA=sd(S)
qnorm(c(0.05,0.95),MU,SIGMA)## [1] 4142.565 4768.585
Con este ejercicio nos damos cuenta de que los posibles precios futuros a mayor sea el tiempo del que se alejen del precio cero, estos tienen una mayor dispersión con respecto al tiempo, lo que quiere decir que diez mil simulaciones pueden ser muchas para una variable como lo es la trm, la cual comparandose diariamente no tiene variaciones considerables pero a la larga si lo cual a pesar de ser muchas simulaciones son necesarias debido a la poca variación diaria de la trm, que a la larga si muestra una gran variación.
# Carga de la TRM
TRM_datos<-read.csv(file = "trm2000.csv", header = TRUE, sep = ";")
class(TRM_datos[,"Fecha"])
TRM_datos[,"Fecha"]<-as.Date(TRM_datos[,"Fecha"],format = "%d/%m/%Y")
class(TRM_datos[,"Fecha"])
rendimiento<-diff(log(TRM_datos[,"TRM"]))
# Simulacion Browniano Geometrico
mu= mean(rendimiento)*252
sigma= sd(rendimiento)*sqrt(252)
T= 5/12 # 5 meses
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((mu-sigma^2/2)*delta_t+sigma*sqrt(delta_t)*rnorm(1))
}
}## [1] "character"
## [1] "Date"
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="#7AC5CD", main="Estimado Cuotas en COP", ylab = "Valor Cuota", xlab = "cuota")
lines(percentil_5_cuotas, type = "l")
lines(percentil_95_cuotas, type = "l")
lines(media_cuotas, type = "l")"Volatilidad de cada cuota en millones"
print(volatilidad_cuotas/1000000)## [1] "Volatilidad de cada cuota en millones"
## [1] 2.450411 3.458318 4.115939 4.584655 5.121731
Cobertura<-0.7
Precio_Entrega= 4500 # Valor Futuro TRM al dia del 17 de febrero del 2023:4907.35
Utilidad_POR_USD=TRM[-1,]-Precio_Entrega
matplot(Utilidad_POR_USD,type="l", col="#7AC5CD")Utilidad_total=Utilidad_POR_USD[1,]*Cuotas_USD[1]*0.8
for(j in 2:length(Cuotas_USD)){
Utilidad_total=rbind(Utilidad_total,Utilidad_POR_USD[j,]*Cuotas_USD[j]*0.8)
}
matplot(Utilidad_total,type="l", col = "#79CDCD")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="#79CDCD", 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")"Volatilidad de cada cuota con cobertura en millones de COP"
print(volatilidad_cuotas_COP_CON_C/1000000)## [1] "Volatilidad de cada cuota con cobertura en millones de COP"
## [1] 0.4900822 0.6916636 0.8231878 0.9169310 1.0243461
# Beneficio real Sin Cobertura
Fechas_pago=c("2022-10-17","2022-11-17","2022-12-17","2023-01-17","2023-02-17")
TRM_OBSERVADA=vector()
for(j in 1:5){
TRM_OBSERVADA[j]=TRM_datos[which(TRM_datos[,1]==Fechas_pago[j]),2]
}
Cuota_Real_COP=TRM_OBSERVADA*Cuotas_USD
matplot(Cuotas_COP,type = "l", col="#8EE5EE", main="Estimado Cuotas en COP", ylab = "Valor Cuota", xlab = "cuota")
lines(percentil_5_cuotas, type = "l")
lines(percentil_95_cuotas, type = "l")
lines(media_cuotas, type = "l")
lines(Cuota_Real_COP, type = "l",lwd=2)"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="#8EE5EE", 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) # Definicion de variables
ndecontratos<-1
nominaldelc<-1790000*0.7
precioini<-4066 # TRM al momento 0
# Operar con garantía de TRM (7%) y margen de mantenimiento de 50%
garantiainicial<-0.063
mantenimiento<-0.5
# Formulas iniciales
ExposicionTotal<-ndecontratos*nominaldelc*precioini
vlrGarantiaInicial<-garantiainicial*ExposicionTotal
vlrGarantiaMinima<-mantenimiento*vlrGarantiaInicial
Apalancamiento<- ExposicionTotal/vlrGarantiaInicial
#Tabla de Liquidacion
TRM_Filas <- TRM[c(22, 43, 64, 85, 106), ]
Promedio_Filas <- rowMeans(TRM_Filas)
TRM_Promedio <- data.frame(Futuro_Promedio = Promedio_Filas)
tablaliq<-TRM_Promedio
TRM_Promedio$Fechas_Pago <- Fechas_pago
TRM_Promedio$TRM_Spot <-TRM_OBSERVADA
TRM_Promedio <- TRM_Promedio[, c("Fechas_Pago", "TRM_Spot", "Futuro_Promedio")]
tablaliq<-TRM_Promedio
Dif_FTrm<-diff(tablaliq[,3])*-1
Dif_FTrm<-append(0,Dif_FTrm)
tablaliq<-cbind(tablaliq,(Dif_FTrm*ndecontratos*nominaldelc))
# Nombres de Columnas
colnames(tablaliq) <- c("Fecha","TRM","Futuro","LiquidacionDiaria")
# Calculo Tabla Auxiliar Margen y llamado al margen
margen<-matrix()
tabaux<-matrix()
llamado_margen<-matrix()
for (i in 1:(nrow(tablaliq))) {
# Tabla Auxiliar
tabaux[1]=vlrGarantiaInicial
tabaux[i+1] <- tabaux[i] + tablaliq$LiquidacionDiaria[i+1]
# Llamado al Margen
llamado_margen[i] <- if(tabaux[i]<vlrGarantiaMinima){vlrGarantiaInicial-tabaux[i]}
else{0}
# Margen
margen[i]<-tabaux[i]+llamado_margen[i]
}
margen<-na.omit(margen)
tablaliq<-cbind(tablaliq,margen,llamado_margen,Dif_FTrm)
knitr::kable(tail(tablaliq, 15))| Fecha | TRM | Futuro | LiquidacionDiaria | margen | llamado_margen | Dif_FTrm |
|---|---|---|---|---|---|---|
| 2022-10-17 | 4636.83 | 4442.920 | 0 | 320965974 | 0 | 0.000000 |
| 2022-11-17 | 4922.70 | 4451.281 | -10476871 | 310489103 | 0 | -8.361430 |
| 2022-12-17 | 4802.48 | 4461.315 | -12572873 | 297916230 | 0 | -10.034216 |
| 2023-01-17 | 4693.99 | 4465.077 | -4713766 | 293202464 | 0 | -3.761984 |
| 2023-02-17 | 4966.33 | 4474.786 | -12165212 | 281037252 | 0 | -9.708869 |
VecesMargen<- sum(llamado_margen > 0)
ProbVecesMargen <- VecesMargen / nrow(tablaliq)
"Dado que nunca se llama al margen, la probabilidad de que se llamé nuevamente al margen es de 0%"## [1] "Dado que nunca se llama al margen, la probabilidad de que se llamé nuevamente al margen es de 0%"
# Probabilidad máxima deseada
probabilidad_maxima <- 0.01
# Calcular el saldo inicial necesario usando la distribución binomial inversa
saldo_inicial <- qbinom(probabilidad_maxima, size = nrow(tablaliq), prob = 0) * (vlrGarantiaMinima)
print(saldo_inicial)
"Dado que en la cantidad de fechas de liquidación nunca se debe recurrir al margen, es decir, el flujo siempre da un valor por encima del valor de garantía mínima, y la probabilidad de llamar al margen es de 0%, la posibilidad de que que se llame al margen nunca llega a ser del 1%."## [1] 0
## [1] "Dado que en la cantidad de fechas de liquidación nunca se debe recurrir al margen, es decir, el flujo siempre da un valor por encima del valor de garantía mínima, y la probabilidad de llamar al margen es de 0%, la posibilidad de que que se llame al margen nunca llega a ser del 1%."
Realizando el modelo de Vasicek se muestra Como resultan las tasas simuladas con 10 iteraciones, para los siguientes 10 periodos, a 252 días.
Se toman los datos de la tasa “Treasury Par Yield” o tasa del bono americano Para aplicar el Modelo de Vasicek se definen los parámetros como:
Tasa_Inicial <- 0.0387 #tasa del TPY del 19/09/2022 a 6 meses
theta <- 0.08
k <- 0.35 # valor tomado entre 0.2 y 0.5
Beta <- 0.0094 #Donde Beta es la desviación estandar de la tasa de los últimos tres añosSimulación de los caminos
n <- 10 # número de iteraciones o simulaciones
T <- 10 # Periodos
m <- 252 # número de días
dt <- T/m # subintervalos
r <- matrix(0,m+1,n) # matriz de tasas simuladas
r[1,] <- Tasa_Inicial
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
}
} t <- seq(0, T, dt)
rT.expected <- theta + (Tasa_Inicial-theta)*exp(-k*t)
rT.stdev <- sqrt( Beta^2/(2*k)*(1-exp(-2*k*t)))
matplot(t, r[,1:10], type="l", lty=1, main="Tasas simuladas TPY", 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,Tasa_Inicial)función para encontrar el precio ZCB usando el modelo Vasicek
VasicekZCBprice <-
function(Tasa_Inicial, 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*Tasa_Inicial))
}
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="Curvas yield TPY")
abline(h=theta, col="red", lty=2)Se replica el Modelo de Vasicek para la tasa Colombiana TES teniendo presente que la tasa se encuentra como efectiva anual
Se definen los parámetros:
Tasa_col_Ini <- 0.0564 #Tasa 19/09/2022 semestral
theta <- 0.08
k <- 0.4
Beta_Col <- 0.0127 # desviación de los últimos tres añosSimulación de los caminos
n <- 10 # número de iteraciones o simulaciones
T <- 10 # Periodos
m <- 252 # número de días
dt <- T/m # subintervalos
r <- matrix(0,m+1,n) # matriz de tasas simuladas
r[1,] <- Tasa_col_Ini
for(j in 1:n){
for(i in 2:(m+1)){
dr <- k*(theta-r[i-1,j])*dt + Beta_Col*sqrt(dt)*rnorm(1,0,1)
r[i,j] <- r[i-1,j] + dr
}
} t <- seq(0, T, dt)
rT.expected <- theta + (Tasa_col_Ini-theta)*exp(-k*t)
rT.stdev <- sqrt( Beta_Col^2/(2*k)*(1-exp(-2*k*t)))
matplot(t, r[,1:10], type="l", lty=1, main="Tasas simuladas TES", 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,Tasa_col_Ini)función para encontrar el precio ZCB usando el modelo Vasicek
## función para encontrar el precio ZCB usando el modelo Vasicek
VasicekZCBprice <-
function(Tasa_col_Ini, k, theta, Beta_Col, T){
b.vas <- (1/k)*(1-exp(-T*k))
a.vas <- (theta-Beta_Col^2/(2*k^2))*(T-b.vas)+(Beta_Col^2)/(4*k)*b.vas^2
return(exp(-a.vas-b.vas*Tasa_col_Ini))
}
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_Col, T))/T
}
}
maturity <- seq(1, 10, 1)
matplot(maturity, yield, type="l", col="black", lty=1, main="Curvas TES")
abline(h=theta, col="red", lty=2)En busca de realizar una inversión prudente de 10.000 USD se busca invertir en el índice Dow Jones, teniendo como prioridad las acciones de Nike, Walmart y Home Depot Se analiza el posible resultado que se puede obtener al invertir estas acciones para lo cual se obtienen los precios históricos para las acciones elegidas. Se instalan las librerías necesarias para descarga de datos y series de tiempo.
options(warn = -1)
suppressPackageStartupMessages({
library(tidyquant)
library(plotly)
library(timetk)
library(forcats)
library(tidyr)
})
tick <- c('NKE', 'WMT', 'HD')
price_data <- tq_get(tick,
from = '2019-04-17',
to = '2023-05-31',
get = 'stock.prices')Una vez se obtienen los precios del portafolios se calculan los rendimientos logarítmicos de cada acción haciendo:
log_ret_tidy <- price_data %>%
group_by(symbol) %>%
tq_transmute(select = adjusted,
mutate_fun = periodReturn,
period = 'daily',
col_rename = 'ret',
type = 'log')
head(log_ret_tidy)## # A tibble: 6 × 3
## # Groups: symbol [1]
## symbol date ret
## <chr> <date> <dbl>
## 1 NKE 2019-04-17 0
## 2 NKE 2019-04-18 0.00528
## 3 NKE 2019-04-22 -0.0208
## 4 NKE 2019-04-23 0.000801
## 5 NKE 2019-04-24 0.0109
## 6 NKE 2019-04-25 -0.00943
Se ordenan los datos, para la visualización en columnas:
log_ret_xts <- log_ret_tidy %>%
spread(symbol, value = ret) %>%
tk_xts()## Using column `date` for date_var.
head(log_ret_xts)## HD NKE WMT
## 2019-04-17 0.000000000 0.0000000000 0.000000e+00
## 2019-04-18 -0.004318297 0.0052828893 1.936921e-04
## 2019-04-22 -0.004287789 -0.0208437703 -7.881175e-03
## 2019-04-23 0.006182582 0.0008012554 6.814467e-03
## 2019-04-24 0.003246182 0.0109200300 4.453179e-03
## 2019-04-25 -0.001064755 -0.0094345377 -9.666435e-05
A continuación, evidenciamos un Histograma de los rendimientos:
#A continuación evidenciamos un Histograma de los rendimientos
if (!requireNamespace("plotly", quietly = TRUE)) {
install.packages("plotly")
}
# Cargar la librería plotly
library(plotly)
# Convertir log_ret_xts a un dataframe para plotly
log_ret_df <- as.data.frame(log_ret_xts)
# Graficar las series de tiempo de los rendimientos
plot_ly(data = log_ret_df, x = ~index(log_ret_df)) %>%
add_lines(y = ~NKE, name = "Nike") %>%
add_lines(y = ~WMT, name = "Walmart") %>%
add_lines(y = ~HD, name = "Home Depot") %>%
layout(title = "Series de Tiempo de Rendimientos Logarítmicos",
xaxis = list(title = "Fecha"),
yaxis = list(title = "Rendimiento Logarítmico"))Se observa el promedio de los rendimientos de los activos.
prom_ret <- colMeans(log_ret_xts)
print(round(prom_ret, 6))## HD NKE WMT
## 0.000427 0.000213 0.000403
El promedio de Home Depot es de 0.000427, el de Nike 0.000213 y el de Walmart es de 0.000403, dado que el valor promedio de las acciones son valores positivos las acciones han dado más rendimientos positivos que negativos, sin embargo, hay que tener presente que el valor al ser cercano a cero, quiere decir que los valores han fluctuado entre valore positivos y negativos, de manera previa se puede decir que la volatilidad es considerable, y los valores de rendimiento obtenido no son tan altos. Home Depot es la acción que ligeramente tiene mejor promedio del rendimiento, mientas que Nike es la acción que menor promedio de retornos ofrece.
Ahora hallamos la matriz de covarianza
cov_mat <- cov(log_ret_xts) * 252
print(round(cov_mat,4))## HD NKE WMT
## HD 0.0941 0.0614 0.0313
## NKE 0.0614 0.1169 0.0247
## WMT 0.0313 0.0247 0.0538
La covarianza de las acciones en este caso son todas positivas, lo que implica que las acciones del portafolio vayan en la misma dirección, es decir, que el portafolio no cuenta con gran diversificación, lo que lo hace más susceptible al riesgo. Analizando los valores de la diagonal, los cuales son las varianzas de los rendimientos de las acciones o en su defecto, el riesgo que estás; se puede encontrar que la acción, que presenta mayor fluctuación es la de Nike, por tanto, tiene mayor riesgo, la de menor riesgo sería la de Walmart con un valor de 0.0538
calculamos los porcentajes o pesos de inversión aleatorios.
pesos <- runif(n = length(tick))
print(pesos)## [1] 0.5834368 0.8784336 0.1628386
print(sum(pesos))## [1] 1.624709
# hacer que los pesos sumen el 100%
pesos <- pesos/sum(pesos)
print(pesos)## [1] 0.3591023 0.5406714 0.1002263
sum(pesos)## [1] 1
Calculamos el indice de Sharpe, riesgo y rendimientos
## se calculan los rendimientos del portafolio
retorno_portafolio <- ((sum(pesos*prom_ret)+1)^252) - 1
retorno_portafolio## [1] 0.08101995
## desviación estandar (anual) o riesgo del portafolio.
riesgo_port <- sqrt(t(pesos) %*% (cov_mat %*% pesos))
print(riesgo_port)## [,1]
## [1,] 0.2749973
## considerando una tasa libre de riesgo nula o de cero calculamos el
##indice de sharpe
ind_sharpe <- retorno_portafolio/riesgo_port
print(ind_sharpe)## [,1]
## [1,] 0.2946209
El índice de Sharp es bajo y está relacionada con la alta volatilidad y riesgo del portafolio, es decir que el rendimiento no es suficiente para el nivel de riesgo que hay que asumir
Realizamos una simulación de 5.000 portafolios, para lo cual debemos prepara las variables para la simulación
## Simular 5.000 portafolios
simulacion <- 5000
## se crea matriz para almacenar los porcentajes de inversión
pesos_porta <- matrix(nrow=simulacion, ncol= length(tick))
## vector vacío para almacenar los retornos del portafolio
retorno_porta <- vector('numeric', length = simulacion)
## vector vacío para almacenar la desviación estandar del portafolio
riesgo_porta <- vector('numeric', length = simulacion)
## vector vacio para almacenar el indice de sharpe del portafolio
indice_sharpe <- vector('numeric', length = simulacion)Con lo anteior, se realiza la simulación.
## simulacion de los 5.000 portafolios
for (i in seq_along(retorno_porta)) {
pesos <- runif(length(tick))
pesos <- pesos/sum(pesos)
# Guardar los pesos del portafolio
pesos_porta[i,] <- pesos
# Calculamos los retornos del portafolio
retorno_portafolio <- sum(pesos * prom_ret)
retorno_portafolio <- ((retorno_portafolio + 1)^252) - 1
# Guardar los retornos del portafolio
retorno_porta[i] <- retorno_portafolio
# Calculamos el riesgo del portafolio
riesgo_portafolio <- sqrt(t(pesos) %*% (cov_mat %*% pesos))
# Guardar el riesgo del portafolio
riesgo_porta[i] <- riesgo_portafolio
# Creamos y guardamos el índice de Sharpe teniendo presente una tasa
# libre de riesgo del 0%
sharpe <- retorno_portafolio/riesgo_portafolio
indice_sharpe[i] <- sharpe
}
# valores en una tabla
Valores_porta <- tibble(Retorno = retorno_porta,
Riesgo = riesgo_porta,
Indice_de_Sharpe = indice_sharpe)
pesos_porta <- tk_tbl(pesos_porta)
colnames(pesos_porta) <- colnames(log_ret_xts)Colocamos ahora todo Junto
# todo junto
Valores_porta <- tk_tbl(cbind(pesos_porta, Valores_porta))
head(Valores_porta)## # A tibble: 6 × 6
## HD NKE WMT Retorno Riesgo Indice_de_Sharpe
## <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 0.247 0.284 0.469 0.0936 0.222 0.421
## 2 0.263 0.719 0.0185 0.0712 0.302 0.236
## 3 0.805 0.173 0.0222 0.103 0.288 0.358
## 4 0.0310 0.382 0.587 0.0871 0.222 0.392
## 5 0.0691 0.416 0.515 0.0856 0.227 0.378
## 6 0.163 0.420 0.416 0.0860 0.232 0.371
Colocamos ahora el Portafolio que se destaca tener el menor riesgo.
## el de menor riesgo
menor_riesgo <- Valores_porta[which.min(Valores_porta$Riesgo),]
## Gráfica del portafolio con Menor Riesgo.
MR <- menor_riesgo %>%
gather(HD:WMT, key = Asset, value = Weights) %>%
mutate(Asset = factor(Asset, levels = c('HD', 'NKE', 'WMT'))) %>%
ggplot(aes(x = fct_reorder(Asset, Weights), y = Weights, fill = Asset)) +
geom_bar(stat = 'identity') +
theme_minimal() +
labs(x = 'Acción', y = 'Porcentaje de inversión', title = "Portafolio de Menor Riesgo") +
scale_y_continuous(labels = scales::percent)
ggplotly(MR)Portafolio Optimo, o con mayor indice de Sharpe
## Observamos el portafolio con mayor indice de sharpe
max_ind_Sharpe <- Valores_porta[which.max(Valores_porta$Indice_de_Sharpe),]
## Gráfica del portafolio con Mayor Indice de Sharpe
MIS <- max_ind_Sharpe %>%
gather(HD:WMT, key = Asset,
value = Weights) %>%
mutate(Asset = as.factor(Asset)) %>%
ggplot(aes(x = fct_reorder(Asset,Weights), y = Weights, fill = Asset)) +
geom_bar(stat = 'identity') +
theme_minimal() +
labs(x = 'Acción', y = 'Porcentaje', title = "Portafolio con Indice de Sharpe Maximizado") +
scale_y_continuous(labels = scales::percent)
ggplotly(MIS)El tercer gráfico valora el proceso y fabríca la forma gráfica de la frontera eficiente donde el indice de Sharp está siendo máximizado
# Frontera eficiente de portafolios.
FE <- Valores_porta %>%
ggplot(aes(x = Riesgo, y = Retorno, color = Indice_de_Sharpe)) +
geom_point() +
theme_classic() +
scale_y_continuous(labels = scales::percent) +
scale_x_continuous(labels = scales::percent) +
labs(x = 'Riesgo',
y = 'Rendimientos',
title = "Optimización del Portafolio & Frontera Eficiente") +
geom_point(data = menor_riesgo, aes(x = Riesgo, y = Retorno), color = 'red', size = 4) +
geom_point(data = max_ind_Sharpe, aes(x = Riesgo, y = Retorno), color = 'blue', size = 4) +
annotate('text', x = 0.20, y = 0.42, label = "Máximo Indice de Sharpe", color = 'blue') +
annotate('text', x = 0.18, y = 0.01, label = "Portafolio de Mínimo Riesgo", color = 'red') +
annotate(geom = 'segment', x = 0.14, xend = 0.135, y = 0.01,
yend = 0.06, color = 'red', arrow = arrow(type = "open")) +
annotate(geom = 'segment', x = 0.22, xend = 0.2275, y = 0.405,
yend = 0.365, color = 'blue', arrow = arrow(type = "open"))
ggplotly(FE)Tras la simulación del portafolio se obtiene que el mayor porcentaje de inversión debe ser para Walmart, quien es la acción que representa menor riesgo y un buen valor promedio de los rendimientos, ya sea para minimizar el riesgo, o por lo contrario maximizar el índice de Sharp obteniendo un portafolio optimo. Por su parte la acción que debe tener la participación más baja o nula directamente debe ser la Nike, debido a su alto riesgo. El riesgo es un valor muy alto, que se hace cercano o supera los valores esperados de rendimiento, Razón por la cual el índice de Sharpe es muy bajo, mostrando que lo obtenido en los retornos no va acorde con el riesgo asumido
#FORMA 1: VOLATILIDAD IMPLICITA
Usamos la volatilidad que aparece en la página de Yahoo Finance y su precio strike.
p_strike = 96
vol_imp = 0.2236#FORMA 2: VOLATILIDAD DE LA ACCIÓN
Usamos la volatilidad histórica de la acción desde el 01/06/2024 hasta el 19/04/2024
op = c("NKE")
data_op = lapply(op, FUN = function(x) {
ROC(Ad(getSymbols(x, from = "2023-06-01", to = "2024-04-19", auto.assign = FALSE)),
type = "continuous")
}) #%returns
ret_op = as.data.frame(do.call(merge, data_op))
colnames(ret_op) = gsub(".Adjusted", "", colnames(ret_op))
ret_op = ret_op[-1, ]
#Volatilidad del activo original
var_op = var(ret_op)
desves_op = sqrt(var_op)
print(desves_op)## [1] 0.01781107
#FORMA 3: VOLATICIDAD DEL PORTAFOLIO
Usaremos la desviación estándar del portafolio ya calculada en la parte uno. “riesgo_portafolio”.
Después de tener las tres volatilidades establecemos las funciones para calcular los resultados.
#OPCION NKE
S1 <- 96
sigma1 <- 0.2236
delta_t <- 0.25
N <- 4
build_stock_tree <- function(S, sigma, delta_t, N) {
tree = matrix(0, nrow=N+1, ncol=N+1)
U = exp(sigma*sqrt(delta_t))
D = exp(-sigma*sqrt(delta_t))
for (i in 1:(N+1)) {
for (j in 1:i) {
tree[i, j] = S * U^(j-1) * D^((i-1)-(j-1))
} }
return(tree)
}
First_tree <- build_stock_tree(S1, sigma1, delta_t, N)
K <- 94.53
IntrinsecValue <- First_tree[5,]-K
IntrinsecValue[IntrinsecValue<0] <- 0
print(IntrinsecValue)## [1] 0.00000 0.00000 1.47000 25.52479 55.60700
q_prob <- function(r, delta_t, sigma) {
u = exp(sigma*sqrt(delta_t))
d = exp(-sigma*sqrt(delta_t))
return((exp(r*delta_t) - d)/(u-d))
}
value_binomial_option <- function(tree, sigma, delta_t, r, X, type) {
q = q_prob(r, delta_t, sigma)
option_tree = matrix(0, nrow=nrow(tree), ncol=ncol(tree))
if(type == 'put') {
option_tree[nrow(option_tree),] = pmax(X - tree[nrow(tree),], 0)
} else { option_tree[nrow(option_tree),] = pmax(tree[nrow(tree),] - X, 0)
}
for (i in (nrow(tree)-1):1) {
for(j in 1:i) {
# Calculamos los pesos dentro del ciclo
peso_abajo = (1 - q) * exp(-r * delta_t)
peso_arriba = q * exp(-r * delta_t)
option_tree[i,j] = (peso_abajo * option_tree[i+1,j] + peso_arriba * option_tree[i+1,j+1])
}
}
return(option_tree)
}
binomial_option <- function(type, sigma, T, r, X, S, N) {
q <- q_prob(r=r, delta_t=T/N, sigma=sigma)
tree <- build_stock_tree(S=S, sigma=sigma, delta_t=T/N, N=N)
option <- value_binomial_option(tree, sigma=sigma, delta_t=T/N, r=r, X=X, type=type)
return(list(q=q, stock=tree, option=option, price=option[1,1]))
}Usaremos la tasa libre de riesgo trimestral de 5.50% y hallamos nuestro arbol binomial con nuestras tres volatilidades.
#FORMA 1:
results1 <- binomial_option(type='call', sigma=0.2236, T=1, r=0.055, X=94.53, S=96, N=4)
#Arbol binomial
results1$stock## [,1] [,2] [,3] [,4] [,5]
## [1,] 96.00000 0.00000 0.0000 0.0000 0.000
## [2,] 85.84542 107.35576 0.0000 0.0000 0.000
## [3,] 76.76495 96.00000 120.0548 0.0000 0.000
## [4,] 68.64499 85.84542 107.3558 134.2560 0.000
## [5,] 61.38394 76.76495 96.0000 120.0548 150.137
#FORMA 2:
results2 <- binomial_option(type='call', sigma=desves_op, T=1, r=0.055, X=94.53, S=96, N=4)
#Arbol binomial
results2$stock## [,1] [,2] [,3] [,4] [,5]
## [1,] 96.00000 0.00000 0.00000 0.00000 0.00000
## [2,] 95.14886 96.85875 0.00000 0.00000 0.00000
## [3,] 94.30527 96.00000 97.72518 0.00000 0.00000
## [4,] 93.46916 95.14886 96.85875 98.59936 0.00000
## [5,] 92.64047 94.30527 96.00000 97.72518 99.48136
#FORMA 3:
results3 <- binomial_option(type='call', sigma=riesgo_portafolio, T=1, r=0.055, X=94.53, S=96, N=4)
#Arbol binomial
results3$stock## [,1] [,2] [,3] [,4] [,5]
## [1,] 96.00000 0.00000 0.0000 0.0000 0.0000
## [2,] 84.09456 109.59092 0.0000 0.0000 0.0000
## [3,] 73.66558 96.00000 125.1059 0.0000 0.0000
## [4,] 64.52994 84.09456 109.5909 142.8174 0.0000
## [5,] 56.52726 73.66558 96.0000 125.1059 163.0364
Después de realizar los tres árboles binomiales nos damos cuenta qe tanto con la volatilidad implicita como con la volatilidad del portafolio el precio de la acción de nike tiene la misma tendencia, cosa que no ocurre si usamos la volatilidad histórica de la propia acción, esto se debe a los tiempos que se usaron para calcular esta última, que es mucho más corto que las otras dos, por lo que los cambios de precio no arrastran tanta información como lo hacen datos de más de 5 años y que a su vez tienen una volatilidad más elevada.
##2. PRECIOS SPOT EXTREMOS
Usaremos los precios spot extremos y sus volatilidades implicitas y hallaremos el arbol binomial.
#Resultados con valores extremos (PRECIO MAS BAJO)
precio_bajo <- binomial_option(type='put', sigma=0.8281, T=1, r=0.055, X=94.53, S=70, N=4)
#Arbol binomial
precio_bajo$stock## [,1] [,2] [,3] [,4] [,5]
## [1,] 70.00000 0.00000 0.0000 0.0000 0.0000
## [2,] 46.26775 105.90529 0.0000 0.0000 0.0000
## [3,] 30.58150 70.00000 160.2276 0.0000 0.0000
## [4,] 20.21339 46.26775 105.9053 242.4136 0.0000
## [5,] 13.36040 30.58150 70.0000 160.2276 366.7554
#Resultados con valores extremos (PRECIO MAS ALTO)
precio_alto <- binomial_option(type='call', sigma=0.8945, T=1, r=0.055, X=94.53, S=125, N=4)
#Arbol binomial
precio_alto$stock## [,1] [,2] [,3] [,4] [,5]
## [1,] 125.00000 0.00000 0.0000 0.0000 0.0000
## [2,] 79.92301 195.50066 0.0000 0.0000 0.0000
## [3,] 51.10149 125.00000 305.7641 0.0000 0.0000
## [4,] 32.67348 79.92301 195.5007 478.2166 0.0000
## [5,] 20.89090 51.10149 125.0000 305.7641 747.9333
Como observamos con estos, dan valores super altos y super bajos, esto debido a la volatilidad implicita que es la más alta, lo que significa que estos precios son los que la acción esmuy poco probable que se ubique, por eso es la diferencia tan grande que tiene con respecto a los anteriores casos que vimos.
"Paso 1: Calcular Rcc Serie desde 01/06/2023 hasta hoy"## [1] "Paso 1: Calcular Rcc Serie desde 01/06/2023 hasta hoy"
tick <- c('NKE', 'WMT', 'HD')
price_data_rcc<- tq_get(tick,
from = '2023-06-01',
to = '2024-04-22',
get = 'stock.prices')
## se calculan los rendimientos logarítmicos
log_ret_tidy <- price_data_rcc %>%
group_by(symbol) %>%
tq_transmute(select = adjusted,
mutate_fun = periodReturn,
period = 'daily',
col_rename = 'ret',
type = 'log')
head(log_ret_tidy)## # A tibble: 6 × 3
## # Groups: symbol [1]
## symbol date ret
## <chr> <date> <dbl>
## 1 NKE 2023-06-01 0
## 2 NKE 2023-06-02 0.0426
## 3 NKE 2023-06-05 -0.0242
## 4 NKE 2023-06-06 0.00937
## 5 NKE 2023-06-07 0.00844
## 6 NKE 2023-06-08 -0.00835
## se ordenan los datos, para la vizualización en columnas.
log_ret_xts_rcc <- log_ret_tidy %>%
spread(symbol, value = ret) %>%
tk_tbl()
head(log_ret_xts_rcc)## # A tibble: 6 × 4
## date HD NKE WMT
## <date> <dbl> <dbl> <dbl>
## 1 2023-06-01 0 0 0
## 2 2023-06-02 0.0258 0.0426 0.00952
## 3 2023-06-05 -0.00964 -0.0242 0.00656
## 4 2023-06-06 0.00985 0.00937 -0.000134
## 5 2023-06-07 0.0191 0.00844 0.00147
## 6 2023-06-08 -0.00202 -0.00835 0.0144
library(dplyr)##
## ######################### Warning from 'xts' package ##########################
## # #
## # The dplyr lag() function breaks how base R's lag() function is supposed to #
## # work, which breaks lag(my_xts). Calls to lag(my_xts) that you type or #
## # source() into this session won't work correctly. #
## # #
## # Use stats::lag() to make sure you're not using dplyr::lag(), or you can add #
## # conflictRules('dplyr', exclude = 'lag') to your .Rprofile to stop #
## # dplyr from breaking base R's lag() function. #
## # #
## # Code in packages is not affected. It's protected by R's namespace mechanism #
## # Set `options(xts.warn_dplyr_breaks_lag = FALSE)` to suppress this warning. #
## # #
## ###############################################################################
##
## Attaching package: 'dplyr'
## The following objects are masked from 'package:xts':
##
## first, last
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
log_ret_xts_rcc <- log_ret_xts_rcc %>%
rename(Fecha = date)
"Paso 2: Sumatoria del Rcc"## [1] "Paso 2: Sumatoria del Rcc"
# Datos iniciales
trimestres <- c("Trimestre 1", "Trimestre 2", "Trimestre 3", "Trimestre 4")
fechas_inicio <- as.Date(c("2023-06-01", "2023-09-01", "2023-12-01", "2024-03-01"))
fechas_fin <- as.Date(c("2023-08-30", "2023-11-30", "2024-02-28", "2024-04-22"))
resultados <- data.frame(Trimestre = trimestres, HD = numeric(length(trimestres)), NKE = numeric(length(trimestres)), WMT = numeric(length(trimestres)))
# Calcular la suma de cada columna para cada trimestre
for (i in 1:length(trimestres)) {
resultados[i, "HD"] <- sum(log_ret_xts_rcc$HD[log_ret_xts_rcc$Fecha >= fechas_inicio[i] & log_ret_xts_rcc$Fecha <= fechas_fin[i]])
resultados[i, "NKE"] <- sum(log_ret_xts_rcc$NKE[log_ret_xts_rcc$Fecha >= fechas_inicio[i] & log_ret_xts_rcc$Fecha <= fechas_fin[i]])
resultados[i, "WMT"] <- sum(log_ret_xts_rcc$WMT[log_ret_xts_rcc$Fecha >= fechas_inicio[i] & log_ret_xts_rcc$Fecha <= fechas_fin[i]])
}
menor_riesgo_mat <- as.matrix(menor_riesgo[, 1:3])
menor_riesgo_mat <- menor_riesgo_mat * 10000
resultados_mat <- as.matrix(resultados[, 2:4])
# Inicializar un nuevo dataframe para almacenar los resultados
resultados_multiplicados <- matrix(NA, nrow = nrow(resultados_mat), ncol = ncol(resultados_mat))
# Realizar la multiplicación por columna y guardar los resultados en el nuevo dataframe
for (i in 1:ncol(resultados_mat)) {
resultados_multiplicados[, i] <- menor_riesgo_mat[, i] * resultados_mat[, i]
}
# Convertir la matriz en un dataframe
resultados_multiplicados <- as.data.frame(resultados_multiplicados)
# Imprimir el resultado
print(resultados_multiplicados)## V1 V2 V3
## 1 221.73910 -18.71640 635.4726
## 2 -70.59219 135.92466 -297.2293
## 3 288.45815 -83.69872 973.5686
## 4 -186.94936 -147.35897 129.6898
# Calcular la suma por fila
resultados_suma <- rowSums(resultados_multiplicados)
# Imprimir el resultado
print(resultados_suma)## [1] 838.4953 -231.8968 1178.3280 -204.6186
# Crear el gráfico de barras
barplot(resultados_suma,
main = "Resultados por Trimestre",
xlab = "Trimestre",
ylab = "Suma",
col = "#7AC5CD",
border = "black",
col.axis = "black",
horiz = FALSE)"Paso 3: Crear estrategia de cobertura"## [1] "Paso 3: Crear estrategia de cobertura"
"Long Straddle"## [1] "Long Straddle"
prices <- seq(80,120,1) # Vector of prices
strike <- 103 # strike price for both put and call
premium_call <- 0.2 # option price call
premium_put <- 0.5 # option price put
# call option payoff at expiration
intrinsicValuesCall <- prices - strike - premium_call
payoffLongCall <- pmax(-premium_call,intrinsicValuesCall)
# put option payoff at expiration
intrinsicValuesPut <- strike - prices - premium_put
payoffLongPut <- pmax(-premium_put,intrinsicValuesPut)
# The payoff of the Strategy is the sum of the call and put payoff. Need
# to sum wise element by element between the two vectors
payoff <- rowSums(cbind(payoffLongCall,payoffLongPut))
# Make a DataFrame with all the variable to plot it with ggplot
results <- data.frame(cbind(prices,payoffLongCall,payoffLongPut,payoff))
ggplot(results, aes(x=prices)) +
geom_line(aes(y = payoffLongCall, color = "LongCall")) +
geom_line(aes(y = payoffLongPut, color="LongPut"))+
geom_line(aes(y=payoff, color = 'Payoff')) +
scale_colour_manual("",
breaks = c("LongCall", "LongPut", "Payoff"),
values = c("#C3ACCE", "#5EB1BF", "#6320EE")) + ylab("Payoff")+
ggtitle("Long Straddle Payoff") "1. Cual estrategia es prudente aplicar en cada opción para sacar provecho en cada pago? Analice"## [1] "1. Cual estrategia es prudente aplicar en cada opción para sacar provecho en cada pago? Analice"
"Dado que según los rendimientos reportados del portafolio en cada uno de los trimestres,
se observa que tiene un comportamiento muy inestable, dandose rendimientos positivos en
los trimestres 1 y 3 y negativos en los trimestres 2 y 4. Por lo tanto se decidió aplicar la
estrategia de Long Straddle con dos opciones del subyacente NKE, con valores de strike y
plazo al vencimiento iguales. Ejecutándose así la compra de una Call y una Put.
Adicionalmente, la teoría sugiere que es apropiado aplicar esta estrategia de cobertura
cuando se espera un movimiento fuerte en el precio de la acción y no se tiene certeza
sobre la dirección de ese movimiento."## [1] "Dado que según los rendimientos reportados del portafolio en cada uno de los trimestres,\nse observa que tiene un comportamiento muy inestable, dandose rendimientos positivos en\nlos trimestres 1 y 3 y negativos en los trimestres 2 y 4. Por lo tanto se decidió aplicar la \nestrategia de Long Straddle con dos opciones del subyacente NKE, con valores de strike y\nplazo al vencimiento iguales. Ejecutándose así la compra de una Call y una Put.\n\nAdicionalmente, la teoría sugiere que es apropiado aplicar esta estrategia de cobertura\ncuando se espera un movimiento fuerte en el precio de la acción y no se tiene certeza\nsobre la dirección de ese movimiento."
"2. ¿Con la información de los últimos tres trimestres, cuales serían los limites mínimos
y máximos? que tanto varían cada trimestre? hay oportunidad de arbitraje según
la posición? analice."## [1] "2. ¿Con la información de los últimos tres trimestres, cuales serían los limites mínimos \ny máximos? que tanto varían cada trimestre? hay oportunidad de arbitraje según\nla posición? analice."
"Teniendo como base el subyacente de NKE, se tiene que por trimestre"## [1] "Teniendo como base el subyacente de NKE, se tiene que por trimestre"
# Definir las fechas deseadas
fechas_deseadas <- as.Date(c("2023-06-01", "2023-09-01", "2023-12-01", "2024-03-01"))
# Filtrar el dataframe price_data_rcc
nke_data <- price_data_rcc %>%
filter(symbol == "NKE" & date %in% fechas_deseadas) %>%
select(date, adjusted)
# Ver el nuevo dataframe
print(nke_data)## # A tibble: 4 × 2
## date adjusted
## <date> <dbl>
## 1 2023-06-01 102.
## 2 2023-09-01 102.
## 3 2023-12-01 113.
## 4 2024-03-01 102.
# Definir las constantes
K <- 103
r <- 0.055
T <- 4/12
# Agregar las columnas K, r y T
nke_data <- nke_data %>%
mutate(K = K,
r = r,
T = T)
# Calcular las columnas adicionales
nke_data <- nke_data %>%
mutate(`Límite Inferior CALL` = adjusted - K * exp(-r * T),
`Límite Superior CALL` = adjusted,
`Arbitraje CALL` = ifelse(0.2 > `Límite Inferior CALL`, TRUE, FALSE),
`Límite Inferior PUT` = K * exp(-r * T) - adjusted,
`Límite Superior PUT` = K * exp(-r * T),
`Arbitraje PUT` = ifelse(0.5 > `Límite Inferior PUT`, TRUE, FALSE))
# Ver el dataframe resultante
print(nke_data)## # A tibble: 4 × 11
## date adjusted K r T `Límite Inferior CALL`
## <date> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 2023-06-01 102. 103 0.055 0.333 1.11
## 2 2023-09-01 102. 103 0.055 0.333 0.524
## 3 2023-12-01 113. 103 0.055 0.333 11.9
## 4 2024-03-01 102. 103 0.055 0.333 0.751
## # ℹ 5 more variables: `Límite Superior CALL` <dbl>, `Arbitraje CALL` <lgl>,
## # `Límite Inferior PUT` <dbl>, `Límite Superior PUT` <dbl>,
## # `Arbitraje PUT` <lgl>
"Dado le calculo anteriormente llevado a cabo, se puede observar que en la opción
PUT siempre se presenta una oportunidad de arbitraje, dado que el valor del subyacente
siempre se encuentra por encima del strike a valor presente, mientras que en la opción
CALL se da la situación contraria. Esto reafirma la oportunidad de aplicar la estrategia de
Straddle, en donde ambas opciones contrarrestan el payoff, dando como resultado una cobertura
en donde se obtiene un mayor payoff y se minimiza la pérdida, como se puede observar en el gráfico
de Long Straddle Payoff"## [1] "Dado le calculo anteriormente llevado a cabo, se puede observar que en la opción\nPUT siempre se presenta una oportunidad de arbitraje, dado que el valor del subyacente\nsiempre se encuentra por encima del strike a valor presente, mientras que en la opción \nCALL se da la situación contraria. Esto reafirma la oportunidad de aplicar la estrategia de\nStraddle, en donde ambas opciones contrarrestan el payoff, dando como resultado una cobertura\nen donde se obtiene un mayor payoff y se minimiza la pérdida, como se puede observar en el gráfico\nde Long Straddle Payoff"
“————————————————————————————”
Para realizar el ejercicio se utilizaron las acciones de PEPSICO y AON.
Se crean las funciones para definir el Black Scholes Merton y las griegas de las acciones escogidas
black_scholes_merton <- function(So, K, r, VencimientoDias, sigma, Stcall, Stput, rates) {
Ano <- 252
# Definir los vencimientos a partir de un número de días establecido
VencimientoDias <- seq(from = VencimientoDias, by = 60, length.out = 6)
# Definir un conjunto de Volatilidad a partir de un valor sigma inicial
sigma <- seq(from = sigma, by = 0.05, length.out = 6)
# Cálculo del vencimiento
T <- VencimientoDias / Ano
# Definir d1 y d2
d1 <- (log(So/K) + (r + ((sigma^2)/2)) * T) / (sigma * sqrt(T))
d2 <- d1 - sigma * sqrt(T)
# Definir N1 y N2 para la posición Call y Put
Nd1 <- pnorm(d1)
Nd2 <- pnorm(d2)
Nd1P <- pnorm(-d1)
Nd2P <- pnorm(-d2)
# Valoración Call
Call <- So * Nd1 - (K * exp(-r * T) * Nd2)
# Valoración Put
Put <- (K * exp(-r * T) * Nd2P) - So * Nd1P
# Crear vector de varios precios st a partir de un stc dado
St <- seq(from = Stcall, by = 10, length.out = 60)
num_filas <- length(St)
num_columnas <- length(sigma)
# Matriz resultados de la Valoración Call
resultadosCall <- matrix(NA, nrow = num_filas, ncol = num_columnas)
for (i in 1:num_filas) {
for (j in 1:num_columnas) {
resultado <- (St[i] * pnorm((log(St[i]/K) + (r[j] + ((sigma[j]^2)/2)) * T[j]) / (sigma[j] * sqrt(T[j]))) -
K * exp(-r[j] * T[j]) * pnorm((log(St[i]/K) + (r[j] - ((sigma[j]^2)/2)) * T[j]) / (sigma[j] * sqrt(T[j])))) /
Call[j]
resultadosCall[i, j] <- resultado
}
}
# Definir el nombre de las columnas
colnames(resultadosCall) <- paste("Vto a", VencimientoDias, "días")
# Crear vector de varios precios st a partir de un stp dado
StP <- seq(from = Stput, by = 10, length.out = 60)
# Matriz de resultados de la valoración Put
resultadosPut <- matrix(NA, nrow = num_filas, ncol = num_columnas)
for (i in 1:num_filas) {
for (j in 1:num_columnas) {
resultado <- (K * exp(-r[j] * T[j]) * pnorm(-(log(StP[i]/K) + (r[j] - ((sigma[j]^2)/2)) * T[j]) / (sigma[j] * sqrt(T[j]))) -
StP[i] * pnorm(-(log(StP[i]/K) + (r[j] + ((sigma[j]^2)/2)) * T[j]) / (sigma[j] * sqrt(T[j])))) /
Put[j]
resultadosPut[i, j] <- resultado
}
}
colnames(resultadosPut) <- paste("Vto a", VencimientoDias, "días")
# Incluir columna de los valores de St para la posición Call en la matriz de resultados
CallTable <- cbind(St, resultadosCall)
# Definir la tabla como un dataframe para evitar error en el tipo de datos
CallTable <- as.data.frame(CallTable)
# Proceso similar al anterior realizado ahora para la posición Put
PutTable <- cbind(StP, resultadosPut)
PutTable <- as.data.frame(PutTable)
# Graficar Call
colores <- rainbow(num_columnas)
matplot(1:num_filas, resultadosCall, type = "l", col = colores, lty = 1, xlab = "Índice", ylab = "Valor", main = "Gráfico de Líneas de Resultados Call")
legend("topleft", legend = colnames(resultadosCall), col = colores, lty = 1, cex = 0.4)
grid()
png(filename = "CallPlot.png")
dev.off()
# Graficar Put
colores <- rainbow(num_columnas)
matplot(1:num_filas, resultadosPut, type = "l", col = colores, lty = 1, xlab = "Índice", ylab = "Valor", main = "Gráfico de Líneas de Resultados Put")
legend("topright", legend = colnames(resultadosPut), col = colores, lty = 1, cex = 0.4)
grid()
png(filename = "PutPlot.png")
dev.off()
return(list(CallTable = CallTable, PutTable = PutTable))
}
"Valoración de las griegas "
Griegas <- function(t=0,T,S,K,r,q=0,sigma,isPut=0) {
# t and T are measured in years; all parameters are annualized
# q is the continuous dividend yield
d1 <- (log(S/K)+(r-q+sigma^2/2)*(T-t))/(sigma*sqrt(T-t))
d2 <- d1-sigma*sqrt(T-t)
binary <- pnorm(-d2)*exp(-r*T)
# Call Delta at t
Delta <- exp(-q*(T-t))*pnorm(d1)
Gamma <- exp(-q*(T-t))*exp(-d1^2/2)/sqrt(2*pi)/S/sigma/sqrt(T-t)
Vega <- S*exp(-q*(T-t))/sqrt(2*pi)*exp(-d1^2/2)*sqrt(T-t)
Theta <- -S*exp(-q*(T-t))*sigma/sqrt(T-t)/2*dnorm(d1) - r*K*exp(-r*(T-t))*pnorm(d2) +
q*S*exp(-q*(T-t))*pnorm(d1)
Rho <- (T-t)*K*exp(-r*(T-t))*pnorm(d2)
# Black-Scholes formula for Calls
BSprice <- -K*exp(-r*(T-t))*pnorm(d2)+S*Delta
if (isPut==1) {
Delta <- -exp(-q*(T-t))*pnorm(-d1)
BSprice <- S*Delta+K*exp(-r*(T-t))*pnorm(-d2)
Theta <- -S*exp(-q*(T-t))*sigma/sqrt(T-t)/2*dnorm(d1) + r*K*exp(-r*(T-t))*pnorm(-d2) -
q*S*exp(-q*(T-t))*pnorm(-d1)
Rho <- -(T-t)*K*exp(-r*(T-t))*pnorm(-d2)
}
Bank <- BSprice-Delta*S
return (list(Delta=Delta,Gamma=Gamma,Theta=Theta,Vega=Vega,Rho=Rho,Price=BSprice,d1=d1,d2=d2,B=Bank))
}1. Valore los precios de las opciones mediante el modelo de Black, Scholes y Merton. Calcule y analice las griegas
Llamada a la función con valores específicos y gráficas
ACCIÓN PEPSICO
Primera simulación K = 180, StCall= 180 y StPut = 177.5
R_Parte1_Pepsico <- black_scholes_merton(So = 177.99, K = 180, r = 0.0556, VencimientoDias = 60, sigma = 0.2, Stcall = 180, Stput = 177.5)Griegas
Griegas1C_Pepsico <-Griegas(t = 0, T = 8/52, S = 177.99, K = 180, r = 0.0556, q = 0, sigma = 0.2, isPut = 0)
Griegas1P_Pepsico <- Griegas(t = 0, T = 8/52, S = 177.99, K = 177.5, r = 0.0556, q = 0, sigma = 0.2, isPut = 1)ACCIÓN AON”
Primera simulación K = 280, StCall= 280 y StPut = 270
R_Parte1_Aon <- black_scholes_merton(So = 275.82, K = 280, r = 0.0556, VencimientoDias = 60, sigma = 0.2, Stcall = 280, Stput = 270)Griegas
Griegas1C_Aon <- Griegas(t = 0, T = 8/52, S = 275.82, K = 280, r = 0.0556, q = 0, sigma = 0.2, isPut = 0)
Griegas1P_Aon <- Griegas(t = 0, T = 8/52, S = 275.82, K = 270, r = 0.0556, q = 0, sigma = 0.2, isPut = 1)Resultados de las griegas
resultadosG_Parte1 <- data.frame(
Empresa = rep(c("Pepsico", "Pepsico", "Aon", "Aon"), each = 1),
Opcion = c("Call", "Put", "Call", "Put"),
Delta = c(Griegas1C_Pepsico$Delta, Griegas1P_Pepsico$Delta, Griegas1C_Aon$Delta, Griegas1P_Aon$Delta),
Gamma = c(Griegas1C_Pepsico$Gamma, Griegas1P_Pepsico$Gamma, Griegas1C_Aon$Gamma, Griegas1P_Aon$Gamma),
Vega = c(Griegas1C_Pepsico$Vega, Griegas1P_Pepsico$Vega, Griegas1C_Aon$Vega, Griegas1P_Aon$Vega),
Theta = c(Griegas1C_Pepsico$Theta, Griegas1P_Pepsico$Theta, Griegas1C_Aon$Theta, Griegas1P_Aon$Theta),
Rho = c(Griegas1C_Pepsico$Rho, Griegas1P_Pepsico$Rho, Griegas1C_Aon$Rho, Griegas1P_Aon$Rho)
)
knitr::kable(resultadosG_Parte1, caption = "Resultados de las Griegas")| Empresa | Opcion | Delta | Gamma | Vega | Theta | Rho |
|---|---|---|---|---|---|---|
| Pepsico | Call | 0.5020408 | 0.0285717 | 27.85116 | -22.77461 | 12.92571 |
| Pepsico | Put | -0.4272398 | 0.0280955 | 27.38701 | -13.31806 | -12.40592 |
| Aon | Call | 0.4826620 | 0.0184205 | 43.11901 | -34.99615 | 19.28277 |
| Aon | Put | -0.3371972 | 0.0168804 | 39.51406 | -20.23213 | -15.08580 |
2. Valore los precios de las opciones mediante el modelo de Black, Scholes y Merton, pero modificando la tasa de interés
ACCIÓN PEPSICO
Primera simulación K = 180, StCall= 180 y StPut = 177.5
R_Parte2_Pepsico <- black_scholes_merton(So = 177.99, K = 180, r = 0.0556, VencimientoDias = 60, sigma = 0.1682, Stcall = 180, Stput = 177.5)Griegas
Griegas2C_Pepsico <- Griegas(t = 0, T = 8/52, S = 177.99, K = 180, r = 0.0556, q = 0, sigma = 0.1682, isPut = 0)
Griegas2P_Pepsico <- Griegas(t = 0, T = 8/52, S = 177.99, K = 177.5, r = 0.0556, q = 0, sigma = 0.1275, isPut = 1)ACCIÓN AON
Primera simulación K = K = 280, StCall= 280 y StPut = 270
R_Parte2_Aon <- black_scholes_merton(So = 275.82, K = 275.82, r = 0.0556, VencimientoDias = 60, sigma = 0.1504, Stcall = 280, Stput = 270)Griegas
Griegas2C_Aon <- Griegas(t = 0, T = 8/52, S = 275.82, K = 280, r = 0.0556, q = 0, sigma = 0.2365, isPut = 0)
Griegas2P_Aon <- Griegas(t = 0, T = 8/52, S = 275.82, K = 270,r = 0.0556, q = 0, sigma = 0.2222, isPut = 1)Resultados de las griegas
resultadosG_Parte2 <- data.frame(
Empresa = rep(c("Pepsico", "Pepsico", "Aon", "Aon"), each = 1),
Opcion = c("Call", "Put", "Call", "Put"),
Delta = c(Griegas2C_Pepsico$Delta, Griegas2P_Pepsico$Delta, Griegas2C_Aon$Delta, Griegas2P_Aon$Delta),
Gamma = c(Griegas2C_Pepsico$Gamma, Griegas2P_Pepsico$Gamma, Griegas2C_Aon$Gamma, Griegas2P_Aon$Gamma),
Vega = c(Griegas2C_Pepsico$Vega, Griegas2P_Pepsico$Vega, Griegas2C_Aon$Vega, Griegas2P_Aon$Vega),
Theta = c(Griegas2C_Pepsico$Theta, Griegas2P_Pepsico$Theta, Griegas2C_Aon$Theta, Griegas2P_Aon$Theta),
Rho = c(Griegas2C_Pepsico$Rho, Griegas2P_Pepsico$Rho, Griegas2C_Aon$Rho, Griegas2P_Aon$Rho)
)
knitr::kable(resultadosG_Parte2, caption = "Resultados de las Griegas (Parte 2)")| Empresa | Opcion | Delta | Gamma | Vega | Theta | Rho |
|---|---|---|---|---|---|---|
| Pepsico | Call | 0.4969802 | 0.0339729 | 27.85073 | -19.895114 | 12.92339 |
| Pepsico | Put | -0.4008400 | 0.0434272 | 26.98669 | -7.070142 | -11.37927 |
| Aon | Call | 0.4906048 | 0.0155880 | 43.14780 | -40.167541 | 19.37759 |
| Aon | Put | -0.3495919 | 0.0154018 | 40.05477 | -23.234337 | -15.74768 |
3. Valore los precios de las opciones mediante el modelo de Black, Scholes y Merton, pero modificando la tasa de interés (una con intervalo de crecimiento y decrecimiento de 2%, hasta llegar a un total de 10 puntos de distancia).
ACCIÓN PEPSICO
Para evidenciar el incremento usamos un ciclo For:
R_Parte3_Pepsico <- list()Ciclo para ejecutar la función con diferentes valores de r
for (r in seq(from = 0.0556, to = 0.1556, by = 0.02)) {
resultado <- black_scholes_merton(So = 177.99, K = 180, r = r, VencimientoDias = 60, sigma = 0.2, Stcall = 180, Stput = 177.5)
R_Parte3_Pepsico[[paste0("r_", round(r, 4))]] <- resultado
}ACCIÓN AON
Para evidenciar el incremento usamos un ciclo For:
R_Parte3_Aon <- list()Ciclo para ejecutar la función con diferentes valores de r
for (r in seq(from = 0.0556, to = 0.1556, by = 0.02)) {
resultado <- black_scholes_merton(So = 275.82, K = 280, r = r, VencimientoDias = 60, sigma = 0.2, Stcall = 280, Stput = 270)
R_Parte3_Aon[[paste0("r_", round(r, 4))]] <- resultado
}Valore los precios de las opciones mediante el modelo de Black, Scholes y Merton, pero modificando la tasa de interés (con una simulación de Vasicek de la tasa de interés.)
Realizamos la función de Vasicek
vasicek_sim <- function(r0, alpha, beta, sigma, T, steps) {
dt <- T / steps
rates <- numeric(steps + 1)
rates[1] <- r0
for (i in 1:steps) {
dW <- rnorm(1, mean = 0, sd = sqrt(dt))
rates[i + 1] <- rates[i] + alpha * (beta - rates[i]) * dt + sigma * sqrt(dt) * dW
}
return(rates)
}Usamos la función de Vasicek con los parametros
r0 <- 0.0556
alpha <- 0.1
beta <- 0.05
sigma_r <- 0.01
T_vasicek <- 1 # Tiempo en años para la simulación de Vasicek
steps <- 252 # Número de pasos en la simulación de Vasicek
rates <- vasicek_sim(r0, alpha, beta, sigma_r, T_vasicek, steps)Usamos la tasa hallada para ambas acciones.
ACCIÓN PEPSICO
Primera simulación K = 180, StCall= 180 y StPut = 177.5
R_Parte3_Pepsico <- black_scholes_merton(So = 177.99, K = 180, r = rates, VencimientoDias = 60, sigma = 0.2, Stcall = 180, Stput = 177.5)Griegas
Griegas3C_Pepsico <-Griegas(t = 0, T = 8/52, S = 177.99, K = 180, r = rates , q = 0, sigma = 0.2, isPut = 0)
Griegas3P_Pepsico <- Griegas(t = 0, T = 8/52, S = 177.99, K = 177.5, r = rates, q = 0, sigma = 0.2, isPut = 1)ACCIÓN AON
Primera simulación K = 280, StCall= 280 y StPut = 270
R_Parte3_Aon <- black_scholes_merton(So = 275.82, K = 280, r = rates, VencimientoDias = 60, sigma = 0.2, Stcall = 280, Stput = 270)Griegas
Griegas3C_Aon <- Griegas(t = 0, T = 8/52, S = 275.82, K = 280, r = rates, q = 0, sigma = 0.2, isPut = 0)
Griegas3P_Aon <- Griegas(t = 0, T = 8/52, S = 275.82, K = 270, r = rates, q = 0, sigma = 0.2, isPut = 1)Seleccione una opción call y una put cercanas al promedio del precio de la acción en el periodo de la muestra genere la siguiente estrategia.
Largo en la acción. largo en la call. Corto en la put.
Calcule el PyG diario en todo el periodo de la muestra, asumiendo que el precio de las opciones no cambia.”
Calculamos la estrategia con pepsico
#PEPSICO
st_p <- 177.99
st_1_p <- -180
k_p <- 180
#Largo en la acción
largo_accionp <- (st_p + st_1_p) + st_1_p
print(largo_accionp)## [1] -182.01
#largo en la call
largo_callp <- max((st_p - k_p), 0)
print(largo_callp)## [1] 0
#Corto en la put
corto_putp <- -max((k_p - st_p), 0)
print(corto_putp)## [1] -2.01
# PyG diario de la estrategia
pyg_diario_pepsico <- largo_accionp + largo_callp + corto_putp
print(pyg_diario_pepsico)## [1] -184.02
Calculamos la estrategia con Aon
#AON
st_a <- 275.82
st_1_a <- - 270
k_a <- 280
#Largo en la acción
largo_acciona <- (st_a + st_1_a) + st_1_a
print(largo_acciona)## [1] -264.18
#largo en la call
largo_calla <- max((st_a - k_a), 0)
print(largo_calla)## [1] 0
#Corto en la put
corto_puta <- -max((k_a - st_a), 0)
print(corto_puta)## [1] -4.18
# PyG diario de la estrategia
pyg_diario_aon <- largo_acciona + largo_calla + corto_puta
print(pyg_diario_aon)## [1] -268.36
## Estrategia de inversión con SWAPS
#Cálculo de tasas mediante el modelo de Vasicek
Tasa_Inicial <- 0.0333 #tasa inicial
theta <- 0.08
k <- 0.35 # valor tomado entre 0.2 y 0.5 constante y subjetivo
Beta <- 0.0094 #Cambiar valor, donde beta es la desviación estandar de las tasas de los últimos tres años.
# Simulación
n <- 10 # número de iteraciones o simulaciones
T <- 10 # Periodos
m <- 10
dt <- T/m # subintervalos
r <- matrix(0,m+1,n) # matriz de tasas simuladas
r[1,] <- Tasa_Inicial
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
}
}
## Gráfica de simulaciones
t <- seq(0, T, dt)
rT.expected <- theta + (Tasa_Inicial-theta)*exp(-k*t)
rT.stdev <- sqrt( Beta^2/(2*k)*(1-exp(-2*k*t)))
matplot(t, r[,1:10], type="l", lty=1, main="Tasas simuladas TPY", 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,Tasa_Inicial)tasa_sorf<-rT.expected
print(tasa_sorf)## [1] 0.03330000 0.04709107 0.05680947 0.06365791 0.06848392 0.07188476
## [7] 0.07428128 0.07597009 0.07716017 0.07799881 0.07858978
## Construir la tabla de amortización
inversion<-100000000
periodos<-0:10
Tfija<-rep(Tasa_Inicial,11)
tabla<-cbind(periodos,Tfija,tasa_sorf)
tabla<-data.frame(tabla)
pagoVariable<-numeric(length(periodos)) ## vector almacenador del pago variable
pagoFijo<-numeric(length(periodos)) ## vector almacenador del pago fijo
#iniciar variables en cero para el primer periodo
pagoVariable[1]<-0
pagoFijo[1]<-0
for(i in 2:length(periodos)){
pagoVariable[i]<-tabla$tasa_sorf[i-1]*inversion
pagoFijo[i]<-tabla$Tfija[i-1]*inversion
}
tabla$pagoVariable<-pagoVariable
tabla$pagoFijo<-pagoFijo
tabla$Diferencia<-tabla$pagoFijo-tabla$pagoVariable
tabla## periodos Tfija tasa_sorf pagoVariable pagoFijo Diferencia
## 1 0 0.0333 0.03330000 0 0 0
## 2 1 0.0333 0.04709107 3330000 3330000 0
## 3 2 0.0333 0.05680947 4709107 3330000 -1379107
## 4 3 0.0333 0.06365791 5680947 3330000 -2350947
## 5 4 0.0333 0.06848392 6365791 3330000 -3035791
## 6 5 0.0333 0.07188476 6848392 3330000 -3518392
## 7 6 0.0333 0.07428128 7188476 3330000 -3858476
## 8 7 0.0333 0.07597009 7428128 3330000 -4098128
## 9 8 0.0333 0.07716017 7597009 3330000 -4267009
## 10 9 0.0333 0.07799881 7716017 3330000 -4386017
## 11 10 0.0333 0.07858978 7799881 3330000 -4469881
## Calcular el valor presente de los pagos
# Crear una lista para almacenar los valores presentes
valor_presente <- vector("list", 10)
# Inicializar cada elemento de la lista como un vector numérico
for (i in 1:10) {
valor_presente[[i]] <- numeric(length(periodos))
}
for (i in 1:11) {
for (j in 1:10) {
valor_presente[[j]][i] <- tabla$pagoFijo[i + j] / ((1 + tabla$tasa_sorf[j])^tabla$periodos[i + 1])
}
}
# Sustituir los valores NA por cero
for (j in 1:10) {
valor_presente[[j]][is.na(valor_presente[[j]])] <- 0
}
valor_presente <-data.frame(valor_presente)
colnames(valor_presente)<-paste0("valor_presente", 1:10)
suma_columnas<-colSums(valor_presente)
# almacenar valor presentes de los pagos fijos
pago_fijo_presente <- numeric(length(periodos))
for(i in 1:length(valor_presente)){
pago_fijo_presente[i]<-suma_columnas[i]
}
pago_fijo_presente## [1] 27933122 23978687 20942277 18350050 15947139 13585030 11171249 8644521
## [9] 5961474 3089057 0
# almacenar inversion inicial traida al presente
inversion_inicial <- numeric(length(periodos))
for (i in 1:11) {
inversion_inicial[i] <- inversion / ((1 + tabla$tasa_sorf[i])^tabla$periodos[12-i])
}
valorBono <- inversion_inicial+pago_fijo_presentetabla$valorBono<-valorBono
tabla$valorNom<-rep(inversion,11)
tabla$diferencia_resultante<-tabla$valorNom-tabla$valorBono
tabla## periodos Tfija tasa_sorf pagoVariable pagoFijo Diferencia valorBono
## 1 0 0.0333 0.03330000 0 0 0 100000000
## 2 1 0.0333 0.04709107 3330000 3330000 0 90069320
## 3 2 0.0333 0.05680947 4709107 3330000 -1379107 85214962
## 4 3 0.0333 0.06365791 5680947 3330000 -2350947 83271198
## 5 4 0.0333 0.06848392 6365791 3330000 -3035791 83150664
## 6 5 0.0333 0.07188476 6848392 3330000 -3518392 84259006
## 7 6 0.0333 0.07428128 7188476 3330000 -3858476 86251888
## 8 7 0.0333 0.07597009 7428128 3330000 -4098128 88923049
## 9 8 0.0333 0.07716017 7597009 3330000 -4267009 92148010
## 10 9 0.0333 0.07799881 7716017 3330000 -4386017 95853538
## 11 10 0.0333 0.07858978 7799881 3330000 -4469881 100000000
## valorNom diferencia_resultante
## 1 1e+08 8.940697e-08
## 2 1e+08 9.930680e+06
## 3 1e+08 1.478504e+07
## 4 1e+08 1.672880e+07
## 5 1e+08 1.684934e+07
## 6 1e+08 1.574099e+07
## 7 1e+08 1.374811e+07
## 8 1e+08 1.107695e+07
## 9 1e+08 7.851990e+06
## 10 1e+08 4.146462e+06
## 11 1e+08 0.000000e+00
Se tiene que a medida que incrementan los valores de la tasa la posición fija de la tasa fija se ve beneficiada, dado que el valor de los pagos aumentan, como es este caso en particular, por su parte, si se diera el caso contrario, si las tasas disminuyeran, la posición variable sería la beneficiada pagará menos que la posición que asume la tasa fija.