Author: Amaury LIN & Thierry ZHANG
Here the Markdown of : Calculating and visualizing a portfolio Beta in the Capital Asset Pricing Mode
Part 1 and 2
library(tidyverse)
## -- Attaching packages --------------------------------------- tidyverse 1.3.2 --
## v ggplot2 3.3.5 v purrr 0.3.4
## v tibble 3.1.8 v dplyr 1.0.10
## v tidyr 1.2.1 v stringr 1.4.0
## v readr 2.1.3 v forcats 0.5.2
## -- Conflicts ------------------------------------------ tidyverse_conflicts() --
## x dplyr::filter() masks stats::filter()
## x dplyr::lag() masks stats::lag()
library(tidyquant)
## Le chargement a nécessité le package : lubridate
## Le chargement a nécessité le package : timechange
##
## Attachement du package : 'lubridate'
##
## Les objets suivants sont masqués depuis 'package:base':
##
## date, intersect, setdiff, union
##
## Le chargement a nécessité le package : PerformanceAnalytics
## Le chargement a nécessité le package : xts
## Le chargement a nécessité le package : zoo
##
## Attachement du package : 'zoo'
##
## Les objets suivants sont masqués depuis 'package:base':
##
## as.Date, as.Date.numeric
##
##
## Attachement du package : 'xts'
##
## Les objets suivants sont masqués depuis 'package:dplyr':
##
## first, last
##
##
## Attachement du package : 'PerformanceAnalytics'
##
## L'objet suivant est masqué depuis 'package:graphics':
##
## legend
##
## Le chargement a nécessité le package : quantmod
## Le chargement a nécessité le package : TTR
## Registered S3 method overwritten by 'quantmod':
## method from
## as.zoo.data.frame zoo
library(timetk)
library(broom)
library(ggplot2)
library(highcharter)
library(tibbletime)
##
## Attachement du package : 'tibbletime'
##
## L'objet suivant est masqué depuis 'package:stats':
##
## filter
library(scales)
##
## Attachement du package : 'scales'
##
## L'objet suivant est masqué depuis 'package:purrr':
##
## discard
##
## L'objet suivant est masqué depuis 'package:readr':
##
## col_factor
#list that contains our stock symbol that we will use
symbols <- c("SPY","VGK", "SBGI", "MCHI","EFA")
#loading data from yahoo finance of our selected stocks from 2013 to 2017
prices <- getSymbols(symbols, src = 'yahoo',from = "2013-01-01",to = "2017-12-31",auto.assign = TRUE, warnings = FALSE) %>%
map(~Ad(get(.))) %>%
reduce(merge) %>%
`colnames<-`(symbols)
#convert the daily data to a monthly format
prices_monthly <- to.monthly(prices, indexAt = "last", OHLC = FALSE)
#calculating the logarithmic monthly return of the stocks
asset_returns_xts <- na.omit(Return.calculate(prices_monthly, method = "log"))
#setting the weight of our stocks in the portfolio (25%, 25%, 20%, 20%, 10%)
w <- c(0.25, 0.25, 0.20, 0.20, 0.10)
#calculating the monthly return of the portfolio
portfolio_returns_xts <- Return.portfolio(asset_returns_xts, weights = w, rebalance_on = "months") %>%
`colnames<-`("returns")
#new format that store all of the monthly stocks returns in a single column
asset_returns_long <- prices %>%
to.monthly(indexAt = "last", OHLC = FALSE) %>%
tk_tbl(preserve_index = TRUE, rename_index = "date") %>%
gather(asset, returns, -date) %>%
group_by(asset) %>%
mutate(returns = (log(returns) - log(lag(returns)))) %>%
na.omit()
#monthly return of the portfolio in a data frame format
portfolio_returns_tq_rebalanced_monthly <- asset_returns_long %>%
tq_portfolio(assets_col = asset, returns_col = returns, weights = w, col_rename = "returns", rebalance_on = "months")
#loading data of the SPY from yahoo finance, it will be use to represent the market data
spy_monthly_xts <- getSymbols("SPY", src = 'yahoo', from = "2013-01-01", to = "2017-12-31", auto.assign = TRUE, warnings = FALSE) %>%
map(~Ad(get(.))) %>%
reduce(merge) %>%
`colnames<-`("SPY") %>%
to.monthly(indexAt = "last", OHLC = FALSE)
#monthly return of the market in xts format
market_returns_xts <- Return.calculate(spy_monthly_xts, method = "log") %>%
na.omit()
#monthly return of the market in data frame format
market_returns_tidy <- market_returns_xts %>%
tk_tbl(preserve_index = TRUE, rename_index = "date") %>%
na.omit() %>%
select(date, returns = SPY)
#calculating the beta of each asset of the portfolio by using SPY as the market
beta_assets <- asset_returns_long %>%
na.omit() %>%
nest(data = -asset) %>%
mutate(model = map(data, ~ lm(returns ~ market_returns_tidy$returns, data = .))) %>%
mutate(model = map(model, tidy)) %>%
unnest(model) %>%
filter(term == "market_returns_tidy$returns") %>%
select(-term)
#portfolio beta
beta <- w[1] * beta_assets$estimate[1] + w[2] * beta_assets$estimate[2] + w[3] * beta_assets$estimate[3] + w[4] * beta_assets$estimate[4] + w[5] * beta_assets$estimate[5]
#calculating the alpha and the beta with Tidyverse
beta_dplyr_byhand <-
portfolio_returns_tq_rebalanced_monthly %>%
do(model = lm(returns ~ market_returns_tidy$returns, data = .))
alpha = beta_dplyr_byhand[[1]][[1]][["coefficients"]][["(Intercept)"]]
beta = beta_dplyr_byhand[[1]][[1]][["coefficients"]][["market_returns_tidy$returns"]]
Part 3:
theme_update(plot.title = element_text(hjust = 0.5))
#this generate monthly return of individual assets scattered against monthly market returns
asset_returns_long %>%
group_by(asset) %>%
summarise(expected_return = mean(returns),
stand_dev = sd(returns)) %>%
ggplot(aes(x = stand_dev, y = expected_return, color = asset)) +
geom_point(size = 2) +
ylab("expected return") +
xlab("standard deviation") +
ggtitle("Expected Monthly Returns v. Risk") +
scale_y_continuous(label = function(x){ paste0(x, "%")})
#Visualization of the relationship between market with a scatter plot of market returns
asset_returns_long %>%
group_by(asset) %>%
summarise(expected_return = mean(returns),
stand_dev = sd(returns)) %>%
ggplot(aes(x = stand_dev, y = expected_return, color = asset)) +
geom_point(size = 2) +
geom_point(aes(x = sd(portfolio_returns_tq_rebalanced_monthly$returns),
y = mean(portfolio_returns_tq_rebalanced_monthly$returns)),
color = "cornflowerblue",
size = 3) +
geom_text(
aes(x = sd(portfolio_returns_tq_rebalanced_monthly$returns) * 1.09,
y = mean(portfolio_returns_tq_rebalanced_monthly$returns),
label = "portfolio")) +
ylab("expected return") +
xlab("standard deviation") +
ggtitle("Expected Monthly Returns v. Risk") +
scale_y_continuous(labels = function(x){ paste0(x, "%")})
#beta calculation from previous part, add simple regression line
portfolio_returns_tq_rebalanced_monthly %>%
mutate(market_returns = market_returns_tidy$returns) %>%
ggplot(aes(x = market_returns, y = returns)) +
geom_point(color = "cornflowerblue") +
geom_smooth(method = "lm", se = FALSE, color = "green", size = .5) +
ylab("portfolio returns") +
xlab("market returns") +
ggtitle("Scatterplot with regression line")
## `geom_smooth()` using formula 'y ~ x'
#add green line to the scatter's slope equale to beta calculation and a y-intercept labeled as alpha
portfolio_returns_tq_rebalanced_monthly %>%
mutate(market_returns = market_returns_tidy$returns) %>%
ggplot(aes(x = market_returns, y = returns)) +
geom_point(color = "cornflowerblue") +
geom_abline(aes(
intercept = alpha,
slope = beta),
color = "purple",
size = .5) +
ylab("portfolio returns") +
xlab("market returns") +
ggtitle("Scatterplot with hand calculated slope")
#add purple line and plot both line
portfolio_returns_tq_rebalanced_monthly %>%
mutate(market_returns = market_returns_tidy$returns) %>%
ggplot(aes(x = market_returns, y = returns)) +
geom_point(color = "cornflowerblue") +
geom_abline(aes(intercept = alpha, slope = beta), color = "purple", size = .5) +
geom_smooth(method = "lm", se = FALSE, color = "green", size = .5) +
ylab("portfolio returns") +
xlab("market returns") +
ggtitle("Compare CAPM beta line to regression line")
## `geom_smooth()` using formula 'y ~ x'
Note that the echo = FALSE parameter was added to the
code chunk to prevent printing of the R code that generated the
plot.