The five-asset portfolio consists of the following equities:
install.packages("tidyquant", repos = "http://cran.us.r-project.org")
install.packages("plotly", repos = "http://cran.us.r-project.org")
install.packages("timetk", repos = "http://cran.us.r-project.org")
install.packages("quantmod", repos = "http://cran.us.r-project.org")
library(tidyquant)
library(plotly)
library(timetk)
library(quantmod)
library(pacman)
pacman::p_load(tidyverse,data.table, fixest, BatchGetSymbols, finreportr, ggplot2, lubridate)
first.date <- Sys.Date() - 5000
last.date <- Sys.Date()
freq.data <- "monthly"
tickers <- c('ADANIPOWER.NS', 'HINDUNILVR.NS', 'RELIANCE.NS', 'INFY.NS', 'HDFCBANK.NS')
stocks <- BatchGetSymbols(tickers = tickers,
first.date = first.date,
last.date = last.date,
freq.data = freq.data,
do.cache = FALSE,
thresh.bad.data = 0)
stocks_DT <- stocks$df.tickers %>% setDT() %>%
.[order(ticker, ref.date)]
returns_plot_all <- ggplot(stocks_DT, aes(x= ref.date, y = ret.adjusted.prices, colour = ticker)) +
geom_line() + theme_bw() + labs(title = "", x = "Date", y= "Monthly Returns", subtitle = "")
returns_plot_all
The portfolio produced by Markowitz gave investors a way to mathematically(statistically) balance out their expectations for rewards and risk tolerance.
This hypothesis was built around two key ideas:
An assumption he kept in mind was that investors are risk-averse and tend to opt portfolios that have lesser risks associated with the given levels of return. This implied that investors took high-risk portfolios only if the rewards were high, i.e., the returns were high.
## Collecting daily stock prices
first.date <- Sys.Date() - 2000
last.date <- Sys.Date()
freq.data <- "daily"
tickers <- c('ADANIPOWER.NS', 'HINDUNILVR.NS', 'RELIANCE.NS', 'INFY.NS', 'HDFCBANK.NS')
stock_data <- tq_get(tickers,
from = first.date,
to = last.date,
get = 'stock.prices')
## Calculating the logarithmic daily returns
log_returns <- stock_data %>%
group_by(symbol) %>%
tq_transmute(select = adjusted,
mutate_fun = periodReturn,
period = 'daily',
col_rename = 'ret',
type = 'log')
head(log_returns)
## # A tibble: 6 × 3
## # Groups: symbol [1]
## symbol date ret
## <chr> <date> <dbl>
## 1 ADANIPOWER.NS 2017-01-05 0
## 2 ADANIPOWER.NS 2017-01-06 0.00306
## 3 ADANIPOWER.NS 2017-01-09 0.00610
## 4 ADANIPOWER.NS 2017-01-10 0.0181
## 5 ADANIPOWER.NS 2017-01-11 0.0481
## 6 ADANIPOWER.NS 2017-01-12 0.0363
## Converting it wide format time-series object
log_returns_xts <- log_returns %>%
spread(symbol, value = ret) %>%
tk_xts()
head(log_returns_xts)
## ADANIPOWER.NS HDFCBANK.NS HINDUNILVR.NS INFY.NS RELIANCE.NS
## 2017-01-05 0.000000000 0.0000000000 0.0000000000 0.0000000000 0.000000000
## 2017-01-06 0.003062881 0.0062609579 0.0007196370 -0.0242849214 -0.002276476
## 2017-01-09 0.006097610 0.0012977107 -0.0032436167 -0.0019562635 0.002554979
## 2017-01-10 0.018072720 0.0158954201 -0.0006018911 0.0002062561 0.011211069
## 2017-01-11 0.048079236 0.0160520671 0.0130979603 -0.0014953380 -0.003493070
## 2017-01-12 0.036316811 0.0008098233 -0.0187122196 0.0314376599 -0.002535310
## Mean daily returns
mean_ret <- colMeans(log_returns_xts)
print(round(mean_ret, 5))
## ADANIPOWER.NS HDFCBANK.NS HINDUNILVR.NS INFY.NS RELIANCE.NS
## 0.00157 0.00064 0.00082 0.00091 0.00116
## Covariance Matrix
cov_mat <- cov(log_returns_xts) * 252
print(round(cov_mat,4))
## ADANIPOWER.NS HDFCBANK.NS HINDUNILVR.NS INFY.NS RELIANCE.NS
## ADANIPOWER.NS 0.3547 0.0354 0.0269 0.0310 0.0545
## HDFCBANK.NS 0.0354 0.0657 0.0182 0.0207 0.0313
## HINDUNILVR.NS 0.0269 0.0182 0.0554 0.0165 0.0227
## INFY.NS 0.0310 0.0207 0.0165 0.0799 0.0240
## RELIANCE.NS 0.0545 0.0313 0.0227 0.0240 0.0974
num_port <- 5000
# Creating a matrix to store the weights
all_wts <- matrix(nrow = num_port,
ncol = length(tickers))
# Creating an empty vector to store
# Portfolio returns
port_returns <- vector('numeric', length = num_port)
# Creating an empty vector to store
# Portfolio Standard deviation
port_risk <- vector('numeric', length = num_port)
# Creating an empty vector to store
# Portfolio Sharpe Ratio
sharpe_ratio <- vector('numeric', length = num_port)
for (i in seq_along(port_returns)) {
wts <- runif(length(tickers))
wts <- wts/sum(wts)
# Storing weight in the matrix
all_wts[i,] <- wts
# Portfolio returns
port_ret <- sum(wts * mean_ret)
port_ret <- ((port_ret + 1)^252) - 1
# Storing Portfolio Returns values
port_returns[i] <- port_ret
# Creating and storing portfolio risk
port_sd <- sqrt(t(wts) %*% (cov_mat %*% wts))
port_risk[i] <- port_sd
# Creating and storing Portfolio Sharpe Ratios
# Assuming 0% Risk free rate
sr <- port_ret/port_sd
sharpe_ratio[i] <- sr
}
# Storing the values in the table
portfolio_values <- tibble(Return = port_returns,
Risk = port_risk,
SharpeRatio = sharpe_ratio)
# Converting matrix to a tibble and changing column names
all_wts <- tk_tbl(all_wts)
colnames(all_wts) <- colnames(log_returns_xts)
# Combing all the values together
portfolio_values <- tk_tbl(cbind(all_wts, portfolio_values))
head(portfolio_values)
## # A tibble: 6 × 8
## ADANIPOWER.NS HDFCBANK.NS HINDUNILVR.NS INFY.NS RELIANCE.NS Return Risk
## <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 0.113 0.595 0.111 0.171 0.00938 0.228 0.213
## 2 0.298 0.152 0.106 0.159 0.285 0.328 0.263
## 3 0.451 0.00849 0.0791 0.268 0.194 0.369 0.324
## 4 0.0436 0.523 0.00295 0.0932 0.337 0.248 0.220
## 5 0.326 0.215 0.282 0.0463 0.130 0.311 0.263
## 6 0.345 0.0388 0.267 0.0619 0.288 0.344 0.280
## # … with 1 more variable: SharpeRatio <dbl>
min_var <- portfolio_values[which.min(portfolio_values$Risk),]
max_sr <- portfolio_values[which.max(portfolio_values$SharpeRatio),]
print(min_var)
## # A tibble: 1 × 8
## ADANIPOWER.NS HDFCBANK.NS HINDUNILVR.NS INFY.NS RELIANCE.NS Return Risk
## <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 0.0199 0.277 0.361 0.217 0.125 0.238 0.182
## # … with 1 more variable: SharpeRatio <dbl>
print(max_sr)
## # A tibble: 1 × 8
## ADANIPOWER.NS HDFCBANK.NS HINDUNILVR.NS INFY.NS RELIANCE.NS Return Risk
## <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 0.0945 0.000944 0.339 0.257 0.308 0.293 0.205
## # … with 1 more variable: SharpeRatio <dbl>
p <- min_var %>%
gather(ADANIPOWER.NS:RELIANCE.NS, 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_classic() +
labs(x = 'Assets', y = 'Weights', title = "Minimum Variance Portfolio Weights") +
scale_y_continuous(labels = scales::percent)
ggplotly(p)
p <- max_sr %>%
gather(ADANIPOWER.NS:RELIANCE.NS, 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 = 'Assets', y = 'Weights', title = "Tangency Portfolio Weights") +
scale_y_continuous(labels = scales::percent)
ggplotly(p)
p <- portfolio_values %>%
ggplot(aes(x = Risk, y = Return, color = SharpeRatio)) +
geom_point() +
theme_classic() +
scale_y_continuous(labels = scales::percent) +
scale_x_continuous(labels = scales::percent) +
labs(x = 'Annualized Risk',
y = 'Annualized Returns',
title = "Portfolio Optimization & Efficient Frontier") +
geom_point(aes(x = Risk,
y = Return), data = min_var, color = 'red') +
geom_point(aes(x = Risk,
y = Return), data = max_sr, color = 'red') +
annotate('text', x = 0.21, y = 0.28, label = "Tangency Portfolio") +
annotate('text', x = 0.21, y = 0.21, label = "Minimum variance portfolio")
ggplotly(p)