Descripción: En el siguiente entrenamiento se aplicará la teoría de portafolios eficientes para la elaboración de una cartera de inversión con seis valores bursátiles, correspondientes a empresas pertenecientes a diferentes sectores económicos y registradas en el índice Standard and Poor 500 (S&P 500).
En 1952, un economista llamado Harry Markowitz escribió un artículo titulado “Portfolio Selection”, un documento que contenía teorías que transformaron el panorama de la gestión de cartera, páginas que le otorgarían el Premio Nobel de Economía casi cuatro décadas después.
Antagónica a las estrategias clásicas de inversión, su Teoría de Portafolio Moderna continúa siendo una estrategia de inversión utilizada por traders profesionales. Esta herramienta de gestión de cartera, si se usa correctamente, puede dar como resultado una cartera de inversión diversa y rentable.
La idea central de su teoría plantea que el inversor racional, buscará maximizar sus beneficios (retornos) asumiendo el menor riesgo (volatilidad) posible, esto se puede lograr con la diversificación de la cartera, eligiendo en principio, acciones que tengan una correlación baja o negativa. Por ejemplo, combinando acciones de empresas con distinta actividad económica.
La teoría de Markowitz también es conocida como análisis de varianza media, que se resume en: encontrar el mayor rendimiento en un determinado nivel de riesgo o el menor riesgo en un determinado nivel de rendimiento.
Markowitz postuló que la diversificación no solo debe apuntar a reducir el riesgo de un valor reduciendo su variabilidad o desviación estándar, sino también reduciendo la covarianza o el riesgo interactivo de dos o más valores en una cartera. Como por combinación de diferentes valores, es teóricamente posible tener un rango de riesgo que varía de cero a infinito.
La frontera eficiente es el conjunto de carteras óptimas que ofrecen el rendimiento esperado más alto para un nivel de riesgo definido o el riesgo más bajo para un nivel dado de rendimiento esperado.
Frontera eficiente
Los activos a usar son los siguientes activos financieros:
El rendimiento esperado de la cartera se calcula como una suma ponderada de los rendimientos de los activos individuales. Para su cálculo se utiliza la siguiente fórmula: \[ Rep: \sum_{i=1}^{n}(Rep_1W_1)+(Rep_2W_2)+..........+(Rep_nW_n+) \]
La covarianza es una medida de la relación entre dos variables aleatorias. La métrica evalúa cuánto, en qué medida, las variables cambian juntas. En otras palabras, es esencialmente una medida de la varianza entre dos variables. Sin embargo, la métrica no evalúa la dependencia entre variables. Su cálculo se realiza mediante la sumatoria de la diferencia entre las rentabilidades de cada uno de los activos (Ri) y su rentabilidad esperada (Re), multiplicados por la probabilidad de ocurrencia (p).
\[ COV=\sum_{i=1}^n(Ri_x-Re_x)(Ri_y-Re_y)(p) \]
La correlación mide la fuerza de la relación entre variables. La correlación es la medida a escala de la covarianza. Es adimensional. En otras palabras, el coeficiente de correlación siempre es un valor puro y no se mide en ninguna unidad.
\[ r=\frac{COV_{xy}}{\sigma_x\sigma_y} \]
La variación de la cartera es un valor estadístico que evalúa el grado de dispersión de los rendimientos de una cartera. Es un concepto importante en la teoría moderna de la inversión. Aunque la medida estadística en sí misma puede no proporcionar información significativa, podemos calcular la desviación estándar de la cartera utilizando la varianza de la cartera.
\[ \sigma^2=\sum_{i=1}^{n}(WxWyCOV_{(x,y)}) \]
library(quantmod)
library(PerformanceAnalytics)
library(ggplot2)
library(IntroCompFinR)
library(pacman)
library(tidyverse)tickers<-c("IBM","BABA","AMZN","FB","MSFT","LNVGY","TSLA")
precios<-NULL
fecha<-"2015-01-01"
for(a in tickers){
precios <- cbind(precios, getSymbols.yahoo(a, from=fecha , periodicity = "daily" , auto.assign=F)[,6])
}
names(precios)<-tickersmean<- apply(PerformanceAnalytics::Return.calculate(precios,method = "log")[-1,],
2,function(x) mean(x))
sd<- apply(PerformanceAnalytics::Return.calculate(precios,method = "log")[-1,],
2,function(x) sd(x))
m<- as.data.frame(mean)
m<- t(m)
s<- t(as.data.frame(sd))
x<- rbind(m,s)*100
library(kableExtra)
x %>% t() %>% kbl(caption = "Table 1: Media & desviación estandar de los activos", escape = TRUE) %>%
kable_classic(full_width = FALSE, html_font = "Cambria")| mean | sd | |
|---|---|---|
| IBM | -0.0023392 | 1.606594 |
| BABA | 0.0613897 | 2.131121 |
| AMZN | 0.1555131 | 1.935110 |
| FB | 0.0801107 | 2.018976 |
| MSFT | 0.1149366 | 1.751622 |
| LNVGY | 0.0177169 | 2.220536 |
| TSLA | 0.1934034 | 3.474488 |
library(ggplot2)
g1<- ggplot(mapping = aes(sd,mean,
label=c("IBM","BABA","AMZN","FB","MSFT","LNVGY","TSLA")))+
geom_point()
g1<- g1+geom_text(hjust=0,vjust=0)
g1<- g1+theme_bw()+xlab("Riesgo")+
ylab("Retorno")
g2<- g1
g2<-g2+scale_y_continuous(
breaks = seq(0,0.003,by=0.001),
limits = c(0,0.003)
)
g2<- g2+scale_x_continuous(
breaks = seq(0.015,0.037,by=0.007),
limits = c(0.015,0.037)
)
g2<- g2+ggtitle("Trade-off Riesgo-Retorno",
subtitle = "7 Activos Riesgosos")+theme_minimal()
g2retornos<- PerformanceAnalytics::Return.calculate(precios,method = "log")[-1,]
cov<-cov(retornos)*100
cov %>% round(digits = 4) %>% kbl(caption = "Table 2: Matriz de covarianzas de los activos", escape = TRUE) %>%
kable_classic(full_width = FALSE, html_font = "Cambria")| IBM | BABA | AMZN | FB | MSFT | LNVGY | TSLA | |
|---|---|---|---|---|---|---|---|
| IBM | 0.0258 | 0.0110 | 0.0110 | 0.0117 | 0.0152 | 0.0088 | 0.0150 |
| BABA | 0.0110 | 0.0454 | 0.0198 | 0.0188 | 0.0183 | 0.0153 | 0.0221 |
| AMZN | 0.0110 | 0.0198 | 0.0374 | 0.0236 | 0.0222 | 0.0099 | 0.0244 |
| FB | 0.0117 | 0.0188 | 0.0236 | 0.0408 | 0.0216 | 0.0098 | 0.0240 |
| MSFT | 0.0152 | 0.0183 | 0.0222 | 0.0216 | 0.0307 | 0.0114 | 0.0244 |
| LNVGY | 0.0088 | 0.0153 | 0.0099 | 0.0098 | 0.0114 | 0.0493 | 0.0146 |
| TSLA | 0.0150 | 0.0221 | 0.0244 | 0.0240 | 0.0244 | 0.0146 | 0.1207 |
library(gplots)
generate_heat_map <- function(correlationMatrix, title)
{
heatmap.2(x = correlationMatrix,
cellnote = correlationMatrix,
main = title,
symm = TRUE,
dendrogram="none",
Rowv = FALSE,
trace="none",
density.info="none",
notecol="black")
}
corr1 <- round(cor(retornos) * 100, 2)
generate_heat_map(corr1,"Heatmap: Correlaciones")Primero calculamos la media, la desviasión estandar y la matriz de varianza y covarianzas que son requeridas, esto se puede verificar en el teorema revisado en la sección anterio.
mean<- apply(retornos,2,function(x) mean(x))
sd<- apply(retornos, 2,function(x) sd(x))
cov<- cov(retornos)Después de haber realizado estos cálculos se procede al realizar el cálculo del portafolio de minima varianza.
library(IntroCompFinR)
library(ggplot2)
# Pesos ------------------------------------------------------------------
weights<- rep(1,7)/7
# construimos el portafolio -----------------------------------------------
getPortfolio(mean,cov,weights =
weights)
# Portafolio de minima varianza -------------------------------------------
globalmin=globalMin.portfolio(mean,cov,
shorts = F)
# Grafico -----------------------------------------------------------------
g3<- ggplot()+geom_point(
mapping = aes(globalmin$sd,
globalmin$er,
color="1"),size=4
)
g3<- g3+geom_point(mapping =
aes(sd,mean,color="2"),
size=4)
g3<- g3+ scale_color_manual(
"",values = c("blue","purple"),
labels=c("Min Var.","Stocks 1")
)
g3<- g3+ xlab("Riesgo")+ylab("Retorno")+
ggtitle("Trade-off Riesgo-Retorno",
subtitle = "Siete Activos riesgos & minima varianza")+
theme_minimal()
g3library(scales)
data=as.data.frame(round(globalmin$weights*100,2))
for(i in 1:7){
if(data[i,1]==0){
data[i,1]=NA
}
else{
data[i,1]=data[i,1]
}
}
names(data)=c("Pesos")
data=data.frame("Acciones"=tickers,"Pesos"=data)
data=na.omit(data)
bp<- ggplot(data = data,aes(x="",y=Pesos,fill=Acciones))+geom_bar(width = 1,stat = "identity")
pie<- bp + coord_polar("y",start=0)
aa<-pie +scale_fill_brewer(palette = "Blues")+ggtitle("Portafolio de minima varianza")
ata<-aa+geom_text(aes(label=percent(data[,2])),position = position_stack(vjust = 0.4),color="black")+
theme_minimal()
ata + theme(panel.grid.major = element_line(linetype = "longdash")
)+
theme(plot.title = element_text(family = "Times",
hjust = 0.50), legend.position = "bottom",
legend.direction = "horizontal") +labs(x = "Acciones")library(IntroCompFinR)
library(ggplot2)
# Portafolio de minima varianza sujeto a un retorno objetivo -------------
port.ibm<- efficient.portfolio(mean,cov,mean[1],shorts = F)
port.baba<- efficient.portfolio(mean,cov,mean[2],shorts = F)
port.amzn<- efficient.portfolio(mean,cov,mean[3],shorts = F)
port.fb<- efficient.portfolio(mean,cov,mean[4],shorts = F)
port.msft<- efficient.portfolio(mean,cov,mean[5],shorts = F)
port.lngvgy<- efficient.portfolio(mean,cov,mean[6],shorts = F)
port.tsla<- efficient.portfolio(mean,cov,mean[7],shorts = F)
mean.2<- c(port.ibm$er,port.baba$er,port.amzn$er,port.fb$er,port.msft$er,
port.lngvgy$er,port.tsla$er)
sd.2 <- c(port.ibm$sd,port.baba$sd,port.amzn$sd,port.fb$sd,port.msft$sd,
port.lngvgy$sd,port.tsla$sd)
# Cáluclo Portafolio tangente ---------------------------------------------
risk_free<- 0.0001
por.tang<- tangency.portfolio(mean,cov,
risk_free,shorts = F)
sharpe.ratio= (por.tang$er-risk_free)/por.tang$sd
# Frontera eficiente -----------------------------------------------------
eff.front.short<- efficient.frontier(mean,cov,
nport = 50,
alpha.min = -2,
alpha.max = 1.5,shorts =F )
# grafica
g6<- ggplot()+geom_point(mapping =
aes(eff.front.short$sd,
eff.front.short$er,color="1"))
g6<- g6+geom_point(mapping = aes(por.tang$sd,
por.tang$er,color="4"),size=4)
g6<- g6 + geom_point(mapping = aes(globalmin$sd
,globalmin$er,color="5"),size=4)
g6<- g6+geom_abline(intercept = risk_free,
slope=sharpe.ratio,color="#58FAF4",lty=2,size=1)
g6<- g6+ggtitle("Frontera Eficiente y Recta tangente")+xlab("Riesgo")+ylab("Retorno")+
theme_minimal()
g6<- g6+scale_color_manual("",
values = c(
"#0040FF","#FE2EF7","#BDBDBD"
),
labels=c("Frontera Eficiente","Portafolio Tangente",
"Min.var"))
g6library(scales)
library(ggplot2)
data=as.data.frame(round(por.tang$weights*100,2))
for(i in 1:7){
if(data[i,1]==0){
data[i,1]=NA
}
else{
data[i,1]=data[i,1]
}
}
names(data)=c("Pesos")
data=data.frame("Acciones"=tickers,"Pesos"=data)
data=na.omit(data)
bp<- ggplot(data = data,aes(x="",y=Pesos,fill=Acciones))+geom_bar(width = 1,stat = "identity")
pie<- bp + coord_polar("y",start=0)
aa<-pie +scale_fill_brewer(palette = "Blues")+ggtitle("Portafolio tangente")
ata<-aa+geom_text(aes(label=percent(data[,2])),position = position_stack(vjust = 0.4),color="black")+
theme_minimal()
ata + theme(panel.grid.major = element_line(linetype = "longdash")
)+
theme(plot.title = element_text(family = "Times",
hjust = 0.50), legend.position = "bottom",
legend.direction = "horizontal") +labs(x = "Acciones")
#install.packages("IntroCompFinR", repos="http://R-Forge.R-project.org")
library(IntroCompFinR)
library(pacman)
library(PerformanceAnalytics)
library(quantmod)
library(tidyverse)
tickers<-c("IBM","BABA","AMZN","FB","MSFT","LNVGY","TSLA")
precios<-NULL
fecha<-"2015-01-01"
for(a in tickers){
precios <- cbind(precios, getSymbols.yahoo(a, from=fecha , periodicity = "daily" , auto.assign=F)[,6])
}
names(precios)<-tickers
retornos<- Return.calculate(precios,method = "log")[-1,]
# Promedio
mean<- apply(PerformanceAnalytics::Return.calculate(precios,method = "log")[-1,],
2,function(x) mean(x))
# Desviación estandar
sd<- apply(PerformanceAnalytics::Return.calculate(precios,method = "log")[-1,],
2,function(x) sd(x))
# matriz de covarianzas
cov<- cov(retornos)
# Vamos a graficar
g1<- ggplot(mapping = aes(sd,mean,
label=c("IBM","BABA","AMZN","FB","MSFT","LNVGY","TSLA")))+
geom_point()
g1<- g1+geom_text(hjust=0,vjust=0)
g1<- g1+theme_bw()+xlab("Riesgo")+
ylab("Retorno")
g2<- g1
g2<-g2+scale_y_continuous(
breaks = seq(0,0.003,by=0.001),
limits = c(0,0.003)
)
g2<- g2+scale_x_continuous(
breaks = seq(0.015,0.037,by=0.007),
limits = c(0.015,0.037)
)
g2<- g2+ggtitle("Trade-off Riesgo-Retorno",
subtitle = "7 Activos Riesgosos")+theme_minimal()
g2
# Pesos ------------------------------------------------------------------
weights<- rep(1,7)/7
# construimos el portafolio -----------------------------------------------
getPortfolio(mean,cov,weights =
weights)
# Portafolio de minima varianza -------------------------------------------
globalmin=globalMin.portfolio(mean,cov,
shorts = T)
# Grafico -----------------------------------------------------------------
g3<- ggplot()+geom_point(
mapping = aes(globalmin$sd,
globalmin$er,
color="1"),size=4
)
g3<- g3+geom_point(mapping =
aes(sd,mean,color="2"),
size=4)
g3<- g3+ scale_color_manual(
"",values = c("blue","purple"),
labels=c("Min Var.","Stocks 1")
)
g3<- g3+ xlab("Riesgo")+ylab("Retorno")+
ggtitle("Trade-off Riesgo-Retorno",
subtitle = "Tres Activos riesgos & minima varianza")+
theme_modern_rc()
# Portafolio de minima varianza sujeto a un retorno objetivo -------------
c("IBM","BABA","AMZN","FB","MSFT","LNVGY","TSLA")
port.ibm<- efficient.portfolio(mean,cov,mean[1],shorts = T)
port.baba<- efficient.portfolio(mean,cov,mean[2],shorts = T)
port.amzn<- efficient.portfolio(mean,cov,mean[3],shorts = T)
port.fb<- efficient.portfolio(mean,cov,mean[4],shorts = T)
port.msft<- efficient.portfolio(mean,cov,mean[5],shorts = T)
port.lngvgy<- efficient.portfolio(mean,cov,mean[6],shorts = T)
port.tsla<- efficient.portfolio(mean,cov,mean[7],shorts = T)
mean.2<- c(port.ibm$er,port.baba$er,port.amzn$er,port.fb$er,port.msft$er,
port.lngvgy$er,port.tsla$er)
sd.2 <- c(port.ibm$sd,port.baba$sd,port.amzn$sd,port.fb$sd,port.msft$sd,
port.lngvgy$sd,port.tsla$sd)
# Cáluclo Portafolio tangente ---------------------------------------------
risk_free<- 0.0001
por.tang<- tangency.portfolio(mean,cov,
risk_free,shorts = T)
sharpe.ratio= (por.tang$er-risk_free)/por.tang$sd
g4<- ggplot()+geom_point(mapping = aes(sd,
mean,color="1"))
g4<-g4 + geom_point(mapping = aes(sd.2,mean.2),color="2")
g4<- g4+geom_point(mapping = aes(por.tang$sd,
por.tang$er,color="3"))
g4<- g4 + geom_point(mapping = aes(globalmin$sd
,globalmin$er,color="4"))
g4<- g4+geom_abline(intercept = risk_free,
slope=sharpe.ratio,color="#58FAF4")
g4<- g4+scale_color_manual("",
values = c(
"red","pink","blue","green"
),
labels=c("stock1","tang.Port"
"stock2","Min.var"))
g4<- g4+theme_modern_rc()+xlab("Riesgo")+
ylab("Retorno")+
ggtitle("Trade-off Riesgo-Retorno",
subtitle = "Tres activos riesgosos & minima varianza")
# Frontera eficiente -----------------------------------------------------
eff.front.short<- efficient.frontier(mean,cov,
nport = 50,
alpha.min = -2,
alpha.max = 1.5,shorts = T)
# grafica
g6<- ggplot()+geom_point(mapping =
aes(eff.front.short$sd,
eff.front.short$er,color="1"))
g6<- g6+geom_point(mapping = aes(por.tang$sd,
por.tang$er,color="4"),size=4)
g6<- g6 + geom_point(mapping = aes(globalmin$sd
,globalmin$er,color="5"),size=4)
g6<- g6+geom_abline(intercept = risk_free,
slope=sharpe.ratio,color="#58FAF4",lty=2,size=1)
g6<- g6+ggtitle("Frontera Eficiente y Recta tangente")+xlab("Riesgo")+ylab("Retorno")+
theme_modern_rc()
g6<- g6+scale_color_manual("",
values = c(
"#0040FF","#FE2EF7","#BDBDBD"
),
labels=c("Frontera Eficiente","Portafolio Tangente",
"Min.var"))
library(scales)
data=as.data.frame(round(globalmin$weights*100,2))
for(i in 1:7){
if(data[i,1]==0){
data[i,1]=NA
}
else{
data[i,1]=data[i,1]
}
}
names(data)=c("Pesos")
data=data.frame("Acciones"=tickers,"Pesos"=data)
data=na.omit(data)
bp<- ggplot(data = data,aes(x="",y=Pesos,fill=Acciones))+geom_bar(width = 1,stat = "identity")
bp
pie<- bp + coord_polar("y",start=0)
aa<-pie +scale_fill_brewer(palette = "Blues")+ggtitle("Portafolio de minima varianza")
ata<-aa+geom_text(aes(label=percent(data[,2])),position = position_stack(vjust = 0.4),color="black")+
theme_minimal()
ata + theme(panel.grid.major = element_line(linetype = "longdash")
)+
theme(plot.title = element_text(family = "Times",
hjust = 0.50), legend.position = "bottom",
legend.direction = "horizontal") +labs(x = "Acciones")
library(scales)
data=as.data.frame(round(por.tang$weights*100,2))
for(i in 1:7){
if(data[i,1]==0){
data[i,1]=NA
}
else{
data[i,1]=data[i,1]
}
}
names(data)=c("Pesos")
data=data.frame("Acciones"=tickers,"Pesos"=data)
data=na.omit(data)
bp<- ggplot(data = data,aes(x="",y=Pesos,fill=Acciones))+geom_bar(width = 1,stat = "identity")
bp
pie<- bp + coord_polar("y",start=0)
aa<-pie +scale_fill_brewer(palette = "Blues")+ggtitle("Portafolio tangente")
ata<-aa+geom_text(aes(label=percent(data[,2])),position = position_stack(vjust = 0.4),color="black")+
theme_minimal()
ata + theme(panel.grid.major = element_line(linetype = "longdash")
)+
theme(plot.title = element_text(family = "Times",
hjust = 0.50), legend.position = "bottom",
legend.direction = "horizontal") +labs(x = "Acciones")