Acciones a analizar y primeros pasos

El primer paso para iniciar con la teoría de Markowitz es escoger los activos que van a componer el portafolio que se va a analizar, además e obtener las series de tiempo de un índice con la finalidad de hacer una comparación visual del comportamiento de los activos y del índice en cuestión. Para efectos prácticos de este compendio, se utilizará el S&P500 y las siguientes acciones: 1. DIS 2. JPM 3. AAPL 4. LLY 5. OXY 5. PM Asimismo, se obterndrán los gráficos de cada uno y se añadieron Bandas de Bollinger, para observar visualmente su comportamiento a lo largo de los 10 años que se están graficando.

Indice <- get.hist.quote(instrument = "^GSPC", 
                        start=as.Date("2012-11-09"), 
                        end=as.Date("2022-11-09"), quote = "AdjClose")
## time series ends   2022-11-08
chartSeries(Indice,
            name = "Historíco del S&P 500 [2012 - 2022]",  
            TA = list("addBBands(n = 10)",
                      "addVo()",
                      "addEMA(20)",
                      "addEMA(10)"))

DIS <- get.hist.quote(instrument = "DIS", 
                      start=as.Date("2012-11-09"), 
                      end=as.Date("2022-11-09"), quote = "AdjClose")
## time series ends   2022-11-08
chartSeries(DIS,
            name = "Histórico de The Walt Disney Company [2012-2022]",  
            TA = list("addBBands(n = 10)",
                      "addVo()",
                      "addEMA(20)",
                      "addEMA(10)"))

JPM <- get.hist.quote(instrument = "JPM", 
                     start=as.Date("2012-11-09"), 
                     end=as.Date("2022-11-09"), quote = "AdjClose")
## time series ends   2022-11-08
chartSeries(JPM,
            name = "Histórico de JP Morgan Chase & Co. [2012-2022]",  
            TA = list("addBBands(n = 10)",
                      "addVo()",
                      "addEMA(20)",
                      "addEMA(10)"))

AAPL <- get.hist.quote(instrument = "AAPL", 
                    start=as.Date("2012-11-09"), 
                    end=as.Date("2022-11-09"), quote = "AdjClose")
## time series ends   2022-11-08
chartSeries(AAPL,
            name = "Histórico de Apple Inc. [2012-2022]",  
            TA = list("addBBands(n = 10)",
                      "addVo()",
                      "addEMA(20)",
                      "addEMA(10)"))

LLY <- get.hist.quote(instrument = "LLY", 
                     start=as.Date("2012-11-09"), 
                     end=as.Date("2022-11-09"), quote = "AdjClose")
## time series ends   2022-11-08
chartSeries(LLY,
            name = "Histórico de Eli Lilly and Company [2012-2022]",  
            TA = list("addBBands(n = 10)",
                      "addVo()",
                      "addEMA(20)",
                      "addEMA(10)"))

OXY <- get.hist.quote(instrument = "OXY", 
                     start=as.Date("2012-11-09"), 
                     end=as.Date("2022-11-09"), quote = "AdjClose")
## time series ends   2022-11-08
chartSeries(OXY,
            name = "Histórico de Occidental Petroleum Corporation [2012-2022]",  
            TA = list("addBBands(n = 10)",
                      "addVo()",
                      "addEMA(20)",
                      "addEMA(10)"))

PM <- get.hist.quote(instrument = "PM", 
                     start=as.Date("2012-11-09"), 
                     end=as.Date("2022-11-09"), quote = "AdjClose")
## time series ends   2022-11-08
chartSeries(PM,
            name = "Histórico de Phillip Morris International Inc. [2012-2022]",  
            TA = list("addBBands(n = 10)",
                      "addVo()",
                      "addEMA(20)",
                      "addEMA(10)"))

Ya con los activos cargados y visualizadas sus gráficas, el siguiente punto radica en unificar los activos en un solo conglomerado al que llamaremos CarteraInv, esto con la idea de maniobrar de manera más fácil los siguientes puntos. Además, se obtiene en una sola impresión las gráficas de toda la cartera.

plot(CarteraInv, main=" ", col="navyblue", xlab="Fecha")
title(main="Histórico de Cartera")

Para tener la información en series de tiempo, se tienen que obtener los rendimientos de cada uno de los activos, se utilizó el método logarítmico que a diferencia del arítmetico es mucho más preciso para series de tiempo.

plot(RetornoIndice, main=" ", col="steelblue3", xlab="Fecha", ylab="Rendimientos")
title(main="Rendimientos del Indice S&P 500")

plot(Rendimientos, main=" ", col="steelblue3", xlab="Fecha")
title(main="Rendimientos logaritmicos de la Cartera")

En las gráficas anteriores podemos observar el comportamiento de los rendimientos de los activos a lo largo del tiempo, en algo que coinciden todos, son con ese movimiento abrupto en el 2020 originado por la crisis económica del covid-19.

RendimientoPromedio = c(mean(RetornoIndice),mean(Rendimientos$AAPL),mean(Rendimientos$JPM),mean(Rendimientos$DIS),mean(Rendimientos$PM),mean(Rendimientos$OXY),mean(Rendimientos$LLY))
Volatilidad = c(sd(RetornoIndice),sd(Rendimientos$AAPL),sd(Rendimientos$JPM),sd(Rendimientos$DIS),sd(Rendimientos$PM),sd(Rendimientos$OXY),sd(Rendimientos$LLY))
Cuadro = data.frame (rbind(RendimientoPromedio,Volatilidad))
colnames(Cuadro)<- c("GSPC","AAPL", "JPM", "DIS", "PM", "OXY", "LLY")
Cuadro*100 

En el cuadro anterior se obtuvieron los rendimientos promedio y la volatilidad de cada uno de los activos que conforman al portafolio que estamos analizando, un punto relevante que se observa es que la acción más volatil es OXY y que también tiene los rendimientos promedios más bajos, desde este momento se puede intuir que existen altas posibilidades de que al gráficar el portafolio eficiente y el tangente quede fuera de la composición del mismo.

Cov
##              DIS        JPM        AAPL         LLY         OXY          PM
## DIS  0.026260515 0.01596862 0.012289927 0.006919908 0.019165553 0.008847955
## JPM  0.015968616 0.02839987 0.012899624 0.008219480 0.026221097 0.010217149
## AAPL 0.012289927 0.01289962 0.033568353 0.008812884 0.014403792 0.008451300
## LLY  0.006919908 0.00821948 0.008812884 0.025812184 0.009669622 0.007548221
## OXY  0.019165553 0.02622110 0.014403792 0.009669622 0.096468605 0.012253937
## PM   0.008847955 0.01021715 0.008451300 0.007548221 0.012253937 0.020555219

En la tabla anterior se obtuvieron las varianzas de cada uno de los activos y se unificaron en una sola matríz de covarianza, esto con la finalidad de medir la dirección y cuantía de la rentabilidad esperada de un activo.

generate_heat_map(corr1,"Mapa de calor: Correlaciones")

El mapa de calor que podemos observar, se hizo con las correlaciones de cada uno de los activos, con base a si mismo y a las demás acciones pertenecientes al portafolio. Como se puede observar en esta matríz hay una fila completa de números uno, ya que esta es la correlación que tiene un activo consigo mismo, la lógica nos dice partir de estos para encontrar los números de mayor a menor correlación. Los activos más correlacionados se componen de esta manera y viceversamente: 1. DIS - JPM 2. OXY - JPM 3. PM - JPM Esta información nos indica que cualquier cambio abrupto en el comportamiento de DIS, OXY o PM tendrá un efecto proporcional a la acción de JPM.

corrplot(corr)

En esta segunda matríz de correlación únicamente se hizo con la finalidad de mostrar una segunda manera de mostrar gráficamente la correlación entre los activos.


Teoría de Markowitz

Con esta información, damos por concluida la primera parte de la teoría de portafolios eficientes y empezamos a demostrar la teoría de Markowitz.

Para iniciar lo que debemos de hacer es obtener la tasa libre de riesgo, que para eso utilizaremos el “Market Yield on U.S. Treasury Securities at 10-Year Constant Maturity”

print(paste("La tasa libre de riesgo al día de hoy es igual a", DGS10, "%"))
## [1] "La tasa libre de riesgo al día de hoy es igual a 4.12 %"

Ya con la tasa libre de riesgo el siguiente paso es graficar el espectro de portafolios con su punto de minima varianza en color azul y el punto tangente en color rojo. Para este caso en particular únicamente se tomará como base 20 portafolios, de los cuáles se obtendrán el eficiente y el tangente.

frontierPlot(Frontera)
grid()
tangencyPoints(Frontera, pch = 19, col = "red", cex=2)
tangencyLines(Frontera, col="grey", pch=19, cex=2)
minvariancePoints(Frontera, col="blue", pch=19, cex=2)
monteCarloPoints(Frontera, mCsteps=500, col="gray", cex=0.001)

En la siguiente gráfica se observan los veinte portafolios obtenidos con sus respectivos pesos en cada uno de los resultados graficados, podemos observar que el portafolio que obtiene menores ganancias es el que se compone 100% por “OXY”, y el que otorga mayores ganancias es el que está compuesto de la misma manera pero solo por “LLY”.

col <- qualiPalette(ncol(Rendimientos), "Pastel1")
weightsPlot(Frontera, col=col)
mtext(text = "Pesos de los portafolios", side = 3, line = 1.5,
      font = 2, cex = 0.7, adj = 0)

El siguiente paso refiere a “sacar” de la gráfica anterior el portafolio eficiente que se compone de la siguiente manera: -DIS - 18.7% -JPM - 8.3% -AAPL - 11.7% -LLY - 27% -PM - 34.3% Como se puede observar al graficar el portafolio eficiente, se observa que “OXY”, no es parte del mismo, el cálculo per se estima que es necesario sacarlo de la composición del portafolio para lograr eficientizar el mismo.

weightsPie(efPortfolio, col=col )
mtext(text = "Portafolio eficiente", side = 3, line = 1.5,
      font = 2, cex = 0.7, adj = 0)

El siguiente portafolio obtenido es el tangente que se elabora a partir del índice o razón de Sharpe, el cual calcula el exceso de rentabilidad sobre la tasa de interés libre de riesgo logrado por el portafolio por unidad de volatilidad o riesgo propio del portafolio.

weightsPie(tgPortfolio, col=col)
mtext(text = "Portafolio tangente", side = 3, line = 1.5,
      font = 2, cex = 0.7, adj = 0)

Con este último paso damos por finalizado la teoría de Markowitz y empezamos a realizar simulaciones de MonteCarlo.

Simulaciones de Montecarlo

El primer paso radicaría en introducir los outputs obtenidos en los pasos anteriores, con la finalidad de que las simulaciones sean basadas en la teoría de portafolios eficientes.

Graficamos las simulaciones, tendremos 121 meses ya que se comienza el primer mes con $1, a este le llamaremos el M0, de aquí empiezan a partir todas las simulaciones efectuadas.

monte_carlo_sim_100 %>% 
  gather(sim, growth, -month) %>% 
  group_by(sim) %>% 
  ggplot(aes(x = month, y = growth, color = sim)) + 
  geom_line() +
  theme(legend.position="none")

El siguiente paso es volver el gráfico dinámico para poder observar de mejor manera los resultados obtenidos en estas simulaciones.

ggplotly(monte_carlo_sim_100 %>% 
           gather(sim, growth, -month) %>% 
           group_by(sim) %>% 
           ggplot(aes(x = month, y = growth, color = sim)) + 
           geom_line() +
           theme(legend.position="none"))

La estadística descriptiva que queremos visualizar son el máximo, mínimo, promedio y mediana de los portafolio simulados los cuales se observan en la siguiente tabla de formato “tibble”. El resultado más propenso a ocurrir se puede interpretar de dos maneras, la primera sería con base al promedio y la segunda como la mediana, sin embargo la primera manera tiene un argumento considerable en contra, ya que se toman todos los datos obtenidos para el cálculo del promedio, incluyendo los máximos y los mínimos, lo cuál puede interpretarse como matemáticas falsas el resultado obtenido, por lo que a opinión propia es mejor interpretar las simulaciones de Montecarlo como la mediana que resulte de las mismas. Que en esta caso el resultado más propenso a ocurrir, entiéndase la mediana, es de $1.12 (valor del portafolio).

resumen<- 
  monte_carlo_sim_100 %>% 
  gather(sim, growth, -month) %>% 
  group_by(sim) %>% 
  summarise(final = last(growth)) %>% 
  summarise(
    max = max(final), 
    min = min(final),
    mean = mean(final),
    median = median(final, na.rm = TRUE))
resumen

En la siguiente gráfica podemos observar los resultados obtenidos en el modelo resumen, en el cual se visualiza la cantidad de portafolios que terminan en la mediana y la evolución de el mínimo y la máxima a lo largo del horizonte de inversión estipulado.

monte_carlo_sim_100 %>% 
  gather(sim, growth, -month) %>% 
  group_by(sim) %>%
  filter(
    last(growth) == resumen$max ||
      last(growth) == resumen$median ||  
      last(growth) == resumen$mean ||
      last(growth) == resumen$min) %>% 
  ggplot(aes(x = month, y = growth)) + 
  geom_line(aes(color = sim)) 

Como último paso se convirtió el gráfico anterior en dinámico.

ggplotly(monte_carlo_sim_100 %>% 
           gather(sim, growth, -month) %>% 
           group_by(sim) %>%
           filter(
             last(growth) == resumen$max ||
               last(growth) == resumen$median ||  
               last(growth) == resumen$min) %>% 
           ggplot(aes(x = month, y = growth)) + 
           geom_line(aes(color = sim)))