Este es un repaso de la sesión 5, donde realizaremos modelos Multivariados de Varianza Condicionada (MGARCH) y Filtros de Kalman, para modelar la media móvil a través del tiempo.
A continuación observaremos los distintos portafolios, una combinación de retornos con niveles de riesgos distintos, siendo el portafolio óptimo el punto tangente entre la línea de mercado de capital y la frontera eficiente, punto en el cual se maximiza el retorno esperado por unidad de riesgo.
Asimismo, una vez identificado nuestro portafolio óptimo, debemos elegir entre los múltiples set de portafolios y activos libres de riesgo (asset allocation), tal como se visualiza en la figura 2.
A continuación realizaremos una aplicación práctica de la teoría de portafolios; para ello utilizaremos los paquete “fPortfolio”, el cual nos ayudará en el análisis de portafolios y su correspondiente análisis gráfico, y “lpsolve”, el cual nos ayudará con la optimización.
# Instalamos y llamamos a los paquetes
install.packages("fPortfolio")
install.packages("lpsolve")
library("fPortfolio")
library("lpsolve")
Una vez instalado los paquetes, nos plantearemos el siguiente reto:
Nota:
La base de datos de “SMALLCAP” y “SMALLCAP.RET” se encuentran dentro del paquete “fPortfolio”.
Los activos a analizar serán: “BKE”, “FCEL”, “GG”, “OII”, “SEB”.
# Base de datos
names(SMALLCAP) # Base del precio de las acciones
## [1] "MODI" "MGF" "MEE" "FCEL" "OII" "SEB" "RML"
## [8] "AEOS" "BRC" "CTC" "TNL" "IBC" "KWD" "TOPP"
## [15] "RARE" "HAR" "BKE" "GG" "GYMB" "KRON" "MARKET"
## [22] "T90"
Data = SMALLCAP.RET # Base de rentabilidades de las acciones
# Seleccionamos los activos a analizar
Data = Data[,c("BKE", "FCEL", "GG", "OII", "SEB")]
head(Data)
## GMT
## BKE FCEL GG OII SEB
## 1997-01-31 0.11500000 -0.18644068 -0.11764706 0.07874016 -0.12734963
## 1997-02-28 -0.09417041 -0.01041667 0.06666667 -0.07299270 0.10285407
## 1997-03-31 0.05940594 -0.15789473 0.03125000 -0.01574803 -0.02246094
## 1997-04-30 0.10280374 -0.01250000 -0.12121213 -0.07200000 -0.01000000
## 1997-05-30 0.44067797 0.00000000 0.03448276 0.17241380 0.12323232
## 1997-06-30 0.08235294 -0.07594936 -0.05000000 0.08823530 -0.04946043
A continuación guardaremos la matriz de varianzas y covarianzas, para ello utilizaremos la función “covEstimator”:
# Matriz Var - Cor
matcovData = covEstimator(Data)
matcovData
## $mu
## BKE FCEL GG OII SEB
## 0.02749712 0.06882631 0.02198486 0.01845474 0.01017200
##
## $Sigma
## BKE FCEL GG OII SEB
## BKE 0.022526377 -0.002610330 -0.003495562 -0.001049804 0.007319867
## FCEL -0.002610330 0.073207122 0.007283986 0.011208017 -0.005218380
## GG -0.003495562 0.007283986 0.036070945 0.012605685 -0.001660664
## OII -0.001049804 0.011208017 0.012605685 0.026924697 -0.004016589
## SEB 0.007319867 -0.005218380 -0.001660664 -0.004016589 0.015560084
Como se puede observar, la función “covEstimator”, nos arroja la matriz de varianzas y covarianzas (Sigma), y los valores promedios de la rentabilidad de cada acción (mu).
Ahora crearemos la especificación:
# Especificación de restriccion de media varianza
especificacion_corta = portfolioSpec()
setSolver(especificacion_corta) = "solveRshortExact"
Y finalmente creamos la frontera eficiente:
# Frontera eficiente
# Restricción (constraints="Short"):
# Esto quiere decir que podemos vender los activos, esto se refleja en el signo negativo
# de Portfolio Weights:
shortFrontier = portfolioFrontier(Data,spec=especificacion_corta,constraints="Short")
# Por default reporta los portafolio: 1,13,25,37,50
shortFrontier
##
## Title:
## MV Portfolio Frontier
## Estimator: covEstimator
## Solver: solveRshortExact
## Optimize: minRisk
## Constraints: Short
## Portfolio Points: 5 of 50
##
## Portfolio Weights:
## BKE FCEL GG OII SEB
## 1 0.0356 -0.0772 0.0982 0.3320 0.6113
## 13 0.2297 0.1270 0.1273 0.1729 0.3432
## 25 0.4238 0.3312 0.1563 0.0137 0.0750
## 37 0.6178 0.5354 0.1854 -0.1454 -0.1932
## 50 0.8281 0.7566 0.2169 -0.3178 -0.4838
##
## Covariance Risk Budgets:
## BKE FCEL GG OII SEB
## 1 0.0197 0.0400 0.0682 0.2608 0.6113
## 13 0.2374 0.1906 0.1236 0.1610 0.2874
## 25 0.2846 0.6167 0.0802 0.0056 0.0129
## 37 0.2351 0.7357 0.0460 -0.0237 0.0069
## 50 0.1958 0.7566 0.0292 -0.0221 0.0405
##
## Target Returns and Risks:
## mean Cov CVaR VaR
## 1 0.0102 0.0932 0.1784 0.1657
## 13 0.0245 0.0807 0.1571 0.1161
## 25 0.0389 0.1136 0.2198 0.1393
## 37 0.0533 0.1670 0.3123 0.2325
## 50 0.0688 0.2319 0.4231 0.3658
##
## Description:
## Wed May 20 01:00:41 2020 by user: User
A continuación graficaremos la frontera eficiente:
frontera = shortFrontier
frontierPlot(frontera,frontier = "both",risk="Sigma",type="l",col = c("blue", "grey"))
Como se puede observar, la línea azul es la frontera eficiente, mientras que la gris es la frontera ineficiente.
Finalmente, podemos graficar también otros portafolios, como el de mínima varianza y otros que se encuentran dentro de la frontera:
# Frontera eficiente
frontierPlot(frontera,frontier = "both",risk="Sigma",type="l",col = c("blue", "grey"))
# Portafolio de mínima varianza
minvariancePoints(frontera,pch=19,col="red")
# Otros portafolios
singleAssetPoints(frontera,risk="Sigma",pch=19,cex=1.5,col=topo.colors(6))
Construir un portafolio y graficar la frontera eficiente y de mínima varianza.
Nota:
Para realizar esta aplicación requerimos del paquete “tseries”, el cual nos proveerá de la data.
install.packages("tseries")
library("tseries")
Luego de ello procedemos con la descarga de la data:
# Construimos la base de datos
sp500 = get.hist.quote(instrument="^gspc" ,start = "2010-01-01", quote="Close")
## time series starts 2010-01-04
## time series ends 2020-05-18
netflix = get.hist.quote(instrument="NFLX" ,start = "2010-01-01", quote="Close")
## time series starts 2010-01-04
## time series ends 2020-05-18
renault = get.hist.quote(instrument="RNO.PA",start = "2010-01-01", quote="Close")
## time series starts 2010-01-04
## time series ends 2020-05-18
klm = get.hist.quote(instrument="AF.PA" ,start = "2010-01-01", quote="Close")
## time series starts 2010-01-04
## time series ends 2020-05-18
# Unimos las bases con merge
portafolio4=merge(sp500,netflix,renault,klm, all=F)
# Renombraremos las variables con "plyr"
library("plyr")
portafolio4=rename(portafolio4,c(Close.sp500="sp500",Close.netflix="netflix",
Close.renault="renault",Close.klm="klm"))
# Finalmente graficamos
plot(portafolio4, col=rainbow(4))
Asimismo construimos los retornos del portafolio:
# Unimos las bases con merge
log_portafolio=diff(log(portafolio4))
# Graficamos los retornos
plot(log_portafolio, col=rainbow(4))
En el gráfico anterior se puede observar como la volatilidad de los retornos en periodos de crisis es más inestable, como el escenario actual de COVID-19, donde los retornos (excepto Netflix) son muy inestables.
Para realizar la frontera eficiente, requerimos trabajar con series de tiempo, por lo que transformamos la data en formato series de tiempo con el siguiente comando:
retornos=timeSeries(log_portafolio)
head(retornos)
## GMT
## sp500 netflix renault klm
## 2010-01-05 0.0031108326 -0.037531711 0.002875443 0.025941222
## 2010-01-06 0.0005453718 0.034535473 0.024240459 0.026976588
## 2010-01-07 0.0039932177 -0.017404961 0.011273791 0.009670035
## 2010-01-08 0.0028775830 0.017029816 -0.007840253 0.003341691
## 2010-01-11 0.0017452316 -0.001314184 -0.004453192 0.029583094
## 2010-01-12 -0.0094254458 -0.016288219 -0.021916515 -0.024176551
A continuación guardaremos la matriz de varianzas y covarianzas, para ello utilizaremos la función “covEstimator”:
# Matriz Var - Cor
matcovData2 = covEstimator(retornos)
matcovData2
## $mu
## sp500 netflix renault klm
## 0.0003711346 0.0015807773 -0.0002705275 -0.0003865889
##
## $Sigma
## sp500 netflix renault klm
## sp500 0.0001228571 0.0001254642 0.0001396219 0.0001066336
## netflix 0.0001254642 0.0010867448 0.0001343763 0.0001057721
## renault 0.0001396219 0.0001343763 0.0005803596 0.0003077332
## klm 0.0001066336 0.0001057721 0.0003077332 0.0007133016
Como se puede observar, la función “covEstimator”, nos arroja la matriz de varianzas y covarianzas (Sigma), y los valores promedios de la rentabilidad de cada acción (mu) de los retornos del portafolio de cuatro activos.
Ahora crearemos la especificación:
# Especificación de restriccion de media varianza
especificacion_corta2 = portfolioSpec()
setSolver(especificacion_corta2) = "solveRshortExact"
Y finalmente creamos la frontera eficiente:
# Frontera eficiente: Retornos de cuatro activos
# Restricción (constraints="Short"):
# Esto quiere decir que podemos vender los activos, esto se refleja en el signo negativo
# de Portfolio Weights:
shortFrontier = portfolioFrontier(retornos,spec=especificacion_corta2,constraints="Short")
# Por default reporta los portafolio: 1,13,25,37,50
shortFrontier
##
## Title:
## MV Portfolio Frontier
## Estimator: covEstimator
## Solver: solveRshortExact
## Optimize: minRisk
## Constraints: Short
## Portfolio Points: 5 of 50
##
## Portfolio Weights:
## sp500 netflix renault klm
## 1 0.8241 -0.3311 0.2322 0.2749
## 13 0.9473 -0.1228 0.0476 0.1278
## 25 1.0706 0.0855 -0.1369 -0.0192
## 37 1.1938 0.2939 -0.3214 -0.1662
## 50 1.3273 0.5195 -0.5213 -0.3255
##
## Covariance Risk Budgets:
## sp500 netflix renault klm
## 1 0.3124 0.2027 0.2101 0.2749
## 13 0.7778 -0.0045 0.0589 0.1678
## 25 0.9554 0.1304 -0.0763 -0.0095
## 37 0.5077 0.4220 0.0357 0.0346
## 50 0.2558 0.5195 0.1228 0.1019
##
## Target Returns and Risks:
## mean Cov CVaR VaR
## 1 -0.0004 0.0179 0.0431 0.0275
## 13 0.0001 0.0122 0.0299 0.0179
## 25 0.0006 0.0116 0.0281 0.0180
## 37 0.0011 0.0169 0.0379 0.0255
## 50 0.0016 0.0250 0.0545 0.0357
##
## Description:
## Wed May 20 01:01:06 2020 by user: User
A continuación graficaremos la frontera eficiente:
frontera2 = shortFrontier
frontierPlot(frontera2,frontier = "both",risk="Sigma",type="l",col = c("blue", "grey"))
Como se puede observar, la línea azul es la frontera eficiente, mientras que la gris es la frontera ineficiente.
Finalmente, podemos graficar también otros portafolios, como el de mínima varianza y otros que se encuentran dentro de la frontera:
# Se recomienda correr línea por línea, para visualizar los cambios
# Frontera eficiente
frontierPlot(frontera2,frontier = "both",risk="Sigma",type="l",col = c("blue", "grey"))
# Otros portafolios
singleAssetPoints(frontera2,risk="Sigma",pch=19,cex=1.5,col=topo.colors(6))
# Portafolio de mínima varianza
minvariancePoints(frontera2,pch=19,col="red")
Se puede observar que también existe otro portafolio cercano al de mínima varianza, siendo el de mínima varianza representado por el círculo rojo.
En los puntos anteriores manteníamos a la matriz de covarianza como estática; a continuación “dinamizaremos” dicha matriz a través del modelo de Garch Multivariado o MGARCH.
Para ello haremos uso del paquete “rmgarch”
install.packages("rmgarch")
library("rmgarch")
Dentro de este paquete se encuentra la base de datos “dji30retw”, la cual utilizaremos para realizar el modelo MGARCH.
# La data contiene retornos de activos
data(dji30retw)
# Trabajaremos con los primeros ocho activos
Dat = dji30retw[,1:8,drop=F]
head(Dat)
## AA AXP BA BAC C
## 1987-03-27 -0.005952399 -0.007942854 -0.008866429 -0.03119837 -0.02586351
## 1987-04-03 0.005952399 -0.025849581 -0.010230268 0.00000000 -0.01762160
## 1987-04-10 -0.014947961 -0.026535554 -0.014239723 -0.03584613 -0.01342302
## 1987-04-17 0.047067511 -0.035932009 -0.023747818 -0.02587945 -0.09440968
## 1987-04-24 0.017094433 -0.055520076 -0.046456441 -0.03042060 -0.03526814
## 1987-05-01 0.025105921 0.025455920 -0.059052432 -0.01165062 0.02030527
## CAT CVX DD
## 1987-03-27 0.015873349 -0.02204814 0.006389798
## 1987-04-03 0.041136906 0.06324389 0.035457312
## 1987-04-10 -0.046400076 -0.01657913 -0.035457312
## 1987-04-17 -0.007947062 -0.03400637 0.005293819
## 1987-04-24 -0.010695289 -0.02871011 -0.031101703
## 1987-05-01 0.036943515 0.01126319 -0.019802627
# Especificamos el modelo GARCH
uspec = ugarchspec(mean.model = list(armaOrder=c(0,0)),
variance.model=list(garchOrder=c(1,1),model="eGARCH"),
distribution.model="norm")
spec1 = dccspec(uspec=multispec(replicate(8,uspec)),
dccOrder=c(1,1),distribution="mvnorm")
# Y estimamos el modelo DCC
fit1=dccfit(spec1,data=Dat)
fit1
##
## *---------------------------------*
## * DCC GARCH Fit *
## *---------------------------------*
##
## Distribution : mvnorm
## Model : DCC(1,1)
## No. Parameters : 70
## [VAR GARCH DCC UncQ] : [0+40+2+28]
## No. Series : 8
## No. Obs. : 1141
## Log-Likelihood : 17800.09
## Av.Log-Likelihood : 15.6
##
## Optimal Parameters
## -----------------------------------
## Estimate Std. Error t value Pr(>|t|)
## [AA].mu 0.000595 0.001303 0.45665 0.647920
## [AA].omega -0.256000 0.166503 -1.53750 0.124170
## [AA].alpha1 -0.107946 0.054682 -1.97406 0.048375
## [AA].beta1 0.956697 0.027907 34.28105 0.000000
## [AA].gamma1 0.199027 0.065157 3.05456 0.002254
## [AXP].mu 0.000866 0.000782 1.10682 0.268372
## [AXP].omega -0.101667 0.013158 -7.72677 0.000000
## [AXP].alpha1 -0.091092 0.022970 -3.96576 0.000073
## [AXP].beta1 0.983231 0.001715 573.18827 0.000000
## [AXP].gamma1 0.119157 0.021341 5.58338 0.000000
## [BA].mu 0.002355 0.002394 0.98393 0.325149
## [BA].omega -0.060658 0.064501 -0.94041 0.347007
## [BA].alpha1 -0.056327 0.111291 -0.50613 0.612767
## [BA].beta1 0.989932 0.011005 89.95226 0.000000
## [BA].gamma1 0.103884 0.053999 1.92382 0.054378
## [BAC].mu 0.001958 0.001467 1.33472 0.181968
## [BAC].omega -0.010052 0.025918 -0.38784 0.698137
## [BAC].alpha1 -0.064921 0.039374 -1.64882 0.099185
## [BAC].beta1 0.996892 0.004284 232.70311 0.000000
## [BAC].gamma1 0.128296 0.026939 4.76246 0.000002
## [C].mu 0.001661 0.001238 1.34110 0.179887
## [C].omega -0.077157 0.033463 -2.30576 0.021124
## [C].alpha1 -0.056115 0.038036 -1.47533 0.140123
## [C].beta1 0.984657 0.005621 175.17454 0.000000
## [C].gamma1 0.171460 0.023412 7.32376 0.000000
## [CAT].mu 0.001794 0.001208 1.48503 0.137536
## [CAT].omega -0.197798 0.005812 -34.03229 0.000000
## [CAT].alpha1 -0.074352 0.017873 -4.16002 0.000032
## [CAT].beta1 0.967659 0.000412 2349.03552 0.000000
## [CAT].gamma1 0.074393 0.002600 28.61074 0.000000
## [CVX].mu 0.001657 0.000938 1.76712 0.077209
## [CVX].omega -0.712817 0.827809 -0.86109 0.389189
## [CVX].alpha1 -0.081153 0.059622 -1.36112 0.173475
## [CVX].beta1 0.896351 0.120470 7.44045 0.000000
## [CVX].gamma1 0.247109 0.158230 1.56171 0.118357
## [DD].mu 0.001135 0.000997 1.13835 0.254975
## [DD].omega -0.109491 0.011343 -9.65248 0.000000
## [DD].alpha1 -0.036420 0.019128 -1.90406 0.056903
## [DD].beta1 0.982890 0.001516 648.16862 0.000000
## [DD].gamma1 0.099008 0.008788 11.26695 0.000000
## [Joint]dcca1 0.009425 0.003160 2.98319 0.002853
## [Joint]dccb1 0.959913 0.020461 46.91410 0.000000
##
## Information Criteria
## ---------------------
##
## Akaike -31.078
## Bayes -30.769
## Shibata -31.085
## Hannan-Quinn -30.961
##
##
## Elapsed time : 12.75073
# DCC: Modelo Dinámico de Correlación Condicional
Finalmente, luego de estimar el modelo DCC, procedemos al análisis gráfico del portafolio con valores en riesgo. Es decir presentamos al portafolio (color azul), y visualizaremos el límite máximo de ganancias (verde), y el límite máximo de pérdida (VaR), observando que existen momentos donde la pérdida del portafolio fue superior al máximo de su pérdida estimada (Hits).
x11()
plot(fit1)
Para graficar el portafolio ys sus límites, se requiere colocar el número 5 cuando la consola del R solicita la instrucción.