library(foreach)
library(DEoptim)
library(iterators)
library(fGarch)
library(Rglpk)
library(ROI)
library(ROI.plugin.glpk)
library(ROI.plugin.quadprog)
pacman::p_load(tidyverse,tidyquant,PortfolioAnalytics,quantmod,PerformanceAnalytics,zoo,
plotly,timekit,ggthemes,quadprog)
Portfolio optimization is the process of selecting proportions of various assets to include in a portfolio, in such a way as to make the portfolio better than any other according to some criterion. The criterion will combine, directly or indirectly, considerations of the expected value of the portfolio’s rate of return as well as of the return’s dispersion and possibly other measures of financial risk. The objective of porrtfolio optimization is to maximize a measure of gain per unit measure of risk and minimize a measure of risk.
Modern portfolio theory was introduced by Harry Markowitz in 1952. It assumes that in general, an investor wants to maximize a portfolio’s expected return contingent on any given amount of risk, with risk measured by the standard deviation of the portfolio’s rate of return. For portfolios that meet this criterion, known as efficient portfolios, achieving a higher expected return requires taking on more risk, so investors are faced with a trade-off between risk and expected return. This risk-expected return relationship of efficient portfolios is graphically represented by a curve known as the efficient frontier. All efficient portfolios, each represented by a point on the efficient frontier, are well-diversified. For the specific formulas for efficient portfolios,[3] see Portfolio separation in mean-variance analysis. While ignoring higher moments can lead to significant over-investment in risky securities, especially when volatility is high[4], the development of portfolios for non-Gaussian economies is mathematically challenging.
## 'http' if 'https' unavailable
#source("https://bioconductor.org/biocLite.R")
#biocLite("BiocUpgrade")
#pacman::p_load("stockPortfolio", "quadprog", "tidyverse")
library(PortfolioAnalytics)
library(quantmod)
library(PerformanceAnalytics)
library(zoo)
library(plotly)
# Get data
getSymbols(c("MSFT", "NVDA", "IBM", "AAPL", "FB", "AMZN"),from = " 2015-01-01",src = 'yahoo')
[1] "MSFT" "NVDA" "IBM" "AAPL" "FB" "AMZN"
# Assign to dataframe
# Get adjusted prices
prices.data <- merge.zoo(MSFT[,6], NVDA[,6], IBM[,6], AAPL[,6], FB[,6], AMZN[,6])
# Calculate returns
returns.data <- sapply(prices.data, CalculateReturns)
returns.data <- na.omit(returns.data)
# Set names
colnames(returns.data) <- c("MSFT", "NVDA", "IBM", "AAPL", "FB", "AMZN")
# Save mean return vector and sample covariance matrix
meanReturns <- colMeans(returns.data)
covMat <- cov(returns.data)
creating a portfolio specification. This can be done by using portfolio.spec()
# Start with the names of the assets
p <- portfolio.spec(assets = colnames(returns.data))
Now for some constraints. Let’s use the following:
Box constraints Leverage (weight sum)
# Box
p <- add.constraint(p, type = "box", min = 0.05, max = 0.8)
# Leverage
p <- add.constraint(portfolio = p, type = "full_investment")
The random solver essentially creates a set of feasible portfolios that satisfy all the constraints we have specified.
# Generate random portfolios
randomport<- random_portfolios(p, permutations = 50000, rp_method = "sample")
p <- add.constraint(portfolio = p, type = "full_investment")
p <- add.constraint(p, type="long_only")
# Get minimum variance portfolio
minvar.port <- add.objective(p, type = "risk", name = "var")
# Optimize
minvar.opt <- optimize.portfolio(returns.data, minvar.port, optimize_method = "random",
rp = randomport)
# Generate maximum return portfolio
maxret.port <- add.objective(p, type = "return", name = "mean")
# Optimize
maxret.opt <- optimize.portfolio(returns.data, maxret.port, optimize_method = "random",
rp = randomport)
# Generate vector of returns
#minret <- 0.02/100
minret <- min(meanReturns)
maxret <- max(meanReturns)
#maxret <- maxret.opt$weights %*% meanReturns
vec <- seq(minret, maxret, length.out = 100)
eff.frontier <- data.frame(Risk =vector("numeric", length(vec)) ,
Return = vector("numeric", length(vec)))
frontier.weights <- mat.or.vec(nr = length(vec), nc = ncol(returns.data))
colnames(frontier.weights) <- colnames(returns.data)
for(i in 1:length(vec)){
# Creates a new portfolio object using p and adds mean as an objective
p <- add.constraint(p, type = "return", name = "mean", return_target = vec[i])
# Creates a new portfolio object using p and adds var as an objective
p <- add.objective(p, type = "risk", name = "var")
# Creates a new portfolio object using p and adds a weight_concentration
# objective. The conc_aversion parameter controls how much concentration is
# penalized. The portfolio concentration is defined as the Herfindahl Hirschman
# Index of the weights.
p <- add.objective(p, type = "weight_concentration", name = "HHI",
conc_aversion = 0.01)
eff.opt <- optimize.portfolio(returns.data, p, optimize_method = "ROI")
eff.frontier$Risk[i] <- sqrt(t(eff.opt$weights) %*% covMat %*% eff.opt$weights)
eff.frontier$Return[i] <- eff.opt$weights %*% meanReturns
frontier.weights[i,] = eff.opt$weights
# print(paste(round(i/length(vec) * 100, 0), "% done..."))
}
eff.frontier$Sharperatio <- eff.frontier$Return / eff.frontier$Risk
feasible.sd <- apply(randomport, 1, function(x){
return(sqrt(matrix(x, nrow = 1) %*% covMat %*% matrix(x, ncol = 1)))
})
feasible.means <- apply(randomport, 1, function(x){
return(x %*% meanReturns)
})
feasible.sr <- feasible.means / feasible.sd
p <- plot_ly() %>%
add_trace(x = feasible.sd, y = feasible.means, color = feasible.sr,
mode = "markers", type = "scattergl", showlegend = F,
marker = list(size = 3, opacity = 0.5,
colorbar = list(title = "Sharpe Ratio"))) %>%
add_trace(data = eff.frontier, x = ~Risk, y = ~Return,mode = "markers", type = "scattergl")%>%
layout(title = "Efficient Frontier",
yaxis = list(title = "Mean Returns", tickformat = ".2%"),
xaxis = list(title = "Standard Deviation", tickformat = ".2%"))
p
p1 <- plot_ly(x = ~feasible.sd, y = feasible.means, color = feasible.sr,
mode = "markers", type = "scattergl", showlegend = F,
marker = list(size = 3, opacity = 0.5,
colorbar = list(title = "Sharpe Ratio")))%>%
# add_trace(data = eff.frontier, x = ~Risk, y = ~Return, mode = "markers",
# type = "scattergl", showlegend = F,
# marker = list(color = "#F7C873", size = 5)) %>%
layout(title = "Random Portfolios with Plotly",
yaxis = list(title = "Mean Returns", tickformat = ".2%"),
xaxis = list(title = "Standard Deviation", tickformat = ".2%"))
#plot_bgcolor = "#434343",
#paper_bgcolor = "#F8F8F8",
#annotations = list(
# list(x = 0.4, y = 0.75,
#ax = -30, ay = -30,
#text = "Efficient frontier",
#font = list(color = "#F6E7C1", size = 15),
# arrowcolor = "white")
# ))
p2 <- plot_ly(data = eff.frontier, x = ~Risk, y = ~Return,mode = "markers", type = "scattergl")%>%
layout(title = "Random Portfolios with Plotly",
yaxis = list(title = "Mean Returns", tickformat = ".2%"),
xaxis = list(title = "Standard Deviation", tickformat = ".2%"))
p <- subplot(p1, p2)
p
d=as.tibble(frontier.weights)%>%tidyr::gather(Stock,Weights)%>%add_column(Index=rep(1:100,6))
p <- plot_ly(d, x = ~Index, y = ~Weights, color = ~Stock, type = "bar") %>%
layout(title = "Portfolio weights across frontier", barmode = "stack",
xaxis = list(title = "Index"),
yaxis = list(title = "Weights(%)", tickformat = ".0%"))
p
search() # see packages currently loaded
[1] ".GlobalEnv" "package:bindrcpp" "package:quadprog"
[4] "package:ggthemes" "package:timekit" "package:plotly"
[7] "package:PortfolioAnalytics" "package:tidyquant" "package:quantmod"
[10] "package:TTR" "package:PerformanceAnalytics" "package:xts"
[13] "package:zoo" "package:lubridate" "package:forcats"
[16] "package:stringr" "package:dplyr" "package:purrr"
[19] "package:readr" "package:tidyr" "package:tibble"
[22] "package:ggplot2" "package:tidyverse" "package:ROI.plugin.quadprog"
[25] "package:ROI.plugin.glpk" "package:ROI" "package:Rglpk"
[28] "package:slam" "package:fGarch" "package:fBasics"
[31] "package:timeSeries" "package:timeDate" "package:iterators"
[34] "package:DEoptim" "package:parallel" "package:foreach"
[37] "tools:rstudio" "package:stats" "package:graphics"
[40] "package:grDevices" "package:utils" "package:datasets"
[43] "package:methods" "Autoloads" "package:base"
sessionInfo()
R version 3.4.1 (2017-06-30)
Platform: x86_64-apple-darwin15.6.0 (64-bit)
Running under: macOS Sierra 10.12.6
Matrix products: default
BLAS: /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib
LAPACK: /Library/Frameworks/R.framework/Versions/3.4/Resources/lib/libRlapack.dylib
locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
attached base packages:
[1] parallel stats graphics grDevices utils datasets methods base
other attached packages:
[1] bindrcpp_0.2 quadprog_1.5-5 ggthemes_3.4.0
[4] timekit_0.3.0 plotly_4.7.1 PortfolioAnalytics_1.0.3636
[7] tidyquant_0.5.3 quantmod_0.4-11 TTR_0.23-2
[10] PerformanceAnalytics_1.4.3541 xts_0.10-0 zoo_1.8-0
[13] lubridate_1.7.1 forcats_0.2.0 stringr_1.2.0
[16] dplyr_0.7.4 purrr_0.2.4 readr_1.1.1
[19] tidyr_0.7.2 tibble_1.3.4 ggplot2_2.2.1.9000
[22] tidyverse_1.2.1 ROI.plugin.quadprog_0.2-5 ROI.plugin.glpk_0.3-0
[25] ROI_0.3-0 Rglpk_0.6-3 slam_0.1-40
[28] fGarch_3042.83 fBasics_3042.89 timeSeries_3042.102
[31] timeDate_3042.101 iterators_1.0.8 DEoptim_2.2-4
[34] foreach_1.4.3
loaded via a namespace (and not attached):
[1] nlme_3.1-131 RColorBrewer_1.1-2 httr_1.3.1 rprojroot_1.2 numDeriv_2016.8-1
[6] tools_3.4.1 backports_1.1.1 R6_2.2.2 lazyeval_0.2.1 colorspace_1.3-2
[11] mnormt_1.5-5 curl_3.0 compiler_3.4.1 cli_1.0.0 rvest_0.3.2
[16] pacman_0.4.6 xml2_1.1.1 scales_0.5.0.9000 psych_1.7.8 spatial_7.3-11
[21] digest_0.6.12 foreign_0.8-69 rmarkdown_1.8 base64enc_0.1-3 pkgconfig_2.0.1
[26] htmltools_0.3.6 htmlwidgets_0.9 rlang_0.1.4 readxl_1.0.0.9000 rstudioapi_0.7
[31] shiny_1.0.5 bindr_0.1 jsonlite_1.5 crosstalk_1.0.0 magrittr_1.5
[36] Rcpp_0.12.14 Quandl_2.8.0 munsell_0.4.3 stringi_1.1.6 yaml_2.1.14
[41] plyr_1.8.4 grid_3.4.1 crayon_1.3.4 lattice_0.20-35 haven_1.1.0
[46] hms_0.4.0 knitr_1.17 reshape2_1.4.2 codetools_0.2-15 glue_1.2.0
[51] evaluate_0.10.1 data.table_1.10.4-3 modelr_0.1.1 httpuv_1.3.5 cellranger_1.1.0
[56] gtable_0.2.0 assertthat_0.2.0 mime_0.5 xtable_1.8-2 broom_0.4.3
[61] rsconnect_0.8.5 viridisLite_0.2.0 registry_0.3
print(paste("R", getRversion()))
[1] "R 3.4.1"
print("-------------")
[1] "-------------"
for (package_name in sort(loadedNamespaces())) {
print(paste(package_name, packageVersion(package_name)))
}
[1] "assertthat 0.2.0"
[1] "backports 1.1.1"
[1] "base 3.4.1"
[1] "base64enc 0.1.3"
[1] "bindr 0.1"
[1] "bindrcpp 0.2"
[1] "broom 0.4.3"
[1] "cellranger 1.1.0"
[1] "cli 1.0.0"
[1] "codetools 0.2.15"
[1] "colorspace 1.3.2"
[1] "compiler 3.4.1"
[1] "crayon 1.3.4"
[1] "crosstalk 1.0.0"
[1] "curl 3.0"
[1] "data.table 1.10.4.3"
[1] "datasets 3.4.1"
[1] "DEoptim 2.2.4"
[1] "digest 0.6.12"
[1] "dplyr 0.7.4"
[1] "evaluate 0.10.1"
[1] "fBasics 3042.89"
[1] "fGarch 3042.83"
[1] "forcats 0.2.0"
[1] "foreach 1.4.3"
[1] "foreign 0.8.69"
[1] "ggplot2 2.2.1.9000"
[1] "ggthemes 3.4.0"
[1] "glue 1.2.0"
[1] "graphics 3.4.1"
[1] "grDevices 3.4.1"
[1] "grid 3.4.1"
[1] "gtable 0.2.0"
[1] "haven 1.1.0"
[1] "hms 0.4.0"
[1] "htmltools 0.3.6"
[1] "htmlwidgets 0.9"
[1] "httpuv 1.3.5"
[1] "httr 1.3.1"
[1] "iterators 1.0.8"
[1] "jsonlite 1.5"
[1] "knitr 1.17"
[1] "lattice 0.20.35"
[1] "lazyeval 0.2.1"
[1] "lubridate 1.7.1"
[1] "magrittr 1.5"
[1] "methods 3.4.1"
[1] "mime 0.5"
[1] "mnormt 1.5.5"
[1] "modelr 0.1.1"
[1] "munsell 0.4.3"
[1] "nlme 3.1.131"
[1] "numDeriv 2016.8.1"
[1] "pacman 0.4.6"
[1] "parallel 3.4.1"
[1] "PerformanceAnalytics 1.4.3541"
[1] "pkgconfig 2.0.1"
[1] "plotly 4.7.1"
[1] "plyr 1.8.4"
[1] "PortfolioAnalytics 1.0.3636"
[1] "psych 1.7.8"
[1] "purrr 0.2.4"
[1] "quadprog 1.5.5"
[1] "Quandl 2.8.0"
[1] "quantmod 0.4.11"
[1] "R6 2.2.2"
[1] "RColorBrewer 1.1.2"
[1] "Rcpp 0.12.14"
[1] "readr 1.1.1"
[1] "readxl 1.0.0.9000"
[1] "registry 0.3"
[1] "reshape2 1.4.2"
[1] "Rglpk 0.6.3"
[1] "rlang 0.1.4"
[1] "rmarkdown 1.8"
[1] "ROI 0.3.0"
[1] "ROI.plugin.glpk 0.3.0"
[1] "ROI.plugin.quadprog 0.2.5"
[1] "rprojroot 1.2"
[1] "rsconnect 0.8.5"
[1] "rstudioapi 0.7"
[1] "rvest 0.3.2"
[1] "scales 0.5.0.9000"
[1] "shiny 1.0.5"
[1] "slam 0.1.40"
[1] "spatial 7.3.11"
[1] "stats 3.4.1"
[1] "stringi 1.1.6"
[1] "stringr 1.2.0"
[1] "tibble 1.3.4"
[1] "tidyquant 0.5.3"
[1] "tidyr 0.7.2"
[1] "tidyverse 1.2.1"
[1] "timeDate 3042.101"
[1] "timekit 0.3.0"
[1] "timeSeries 3042.102"
[1] "tools 3.4.1"
[1] "TTR 0.23.2"
[1] "utils 3.4.1"
[1] "viridisLite 0.2.0"
[1] "xml2 1.1.1"
[1] "xtable 1.8.2"
[1] "xts 0.10.0"
[1] "yaml 2.1.14"
[1] "zoo 1.8.0"
#installed.packages(fields = c ("Package", "Version"))