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.

PORTFOLIO OPTIMIZATION USING R’S SOLVE.QP FUNCTION

    ## '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"))
LS0tCnRpdGxlOiBWaXN1YWxpemluZyBUaGUgRWZmaWNpZW50IEZyb250aWVyIGFzc29jaWF0ZWQgd2l0aCB0aGUgUmlzay1SZXR1cm4gUG9ydGZvbGlvCiAgT3B0aW1pemF0aW9uIG1vZGVsCm91dHB1dDogaHRtbF9ub3RlYm9vawp0aGVtZTogY29zbW8KdG9jX2Zsb2F0OiBubwp0b2NfZGVwdGg6IDIKYXV0aG9yOiBOYW5hIEJvYXRlbmcKZGZfcHJpbnQ6IHBhZ2VkClRpbWU6ICdgciBTeXMudGltZSgpYCcKZGF0ZTogImByIGZvcm1hdChTeXMudGltZSgpLCAnJUIgJWQsICVZJylgIgotLS0KCmBgYHtyIHNldHVwLGluY2x1ZGU9RkFMU0V9Cgprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICB3YXJuaW5nID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICBvdXQud2lkdGggPSIxMDAlIiwKICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgIGZpZy5hbGlnbiA9ICdkZWZhdWx0JywgCiAgICAgICAgICAgICAgICAgICAgICB3YXJuaW5nID0gRkFMU0UsIAogICAgICAgICAgICAgICAgICAgICAgZmlnLmNhcCA9IkZpZy4gMzAiLCAKICAgICAgICAgICAgICAgICAgICAgIG91dC53aWR0aD0iMTAwJSIpCgpgYGAKCgoKYGBge3J9CgpsaWJyYXJ5KGZvcmVhY2gpCmxpYnJhcnkoREVvcHRpbSkKbGlicmFyeShpdGVyYXRvcnMpCmxpYnJhcnkoZkdhcmNoKQpsaWJyYXJ5KFJnbHBrKQpsaWJyYXJ5KFJPSSkKbGlicmFyeShST0kucGx1Z2luLmdscGspCmxpYnJhcnkoUk9JLnBsdWdpbi5xdWFkcHJvZykKCgoKCnBhY21hbjo6cF9sb2FkKHRpZHl2ZXJzZSx0aWR5cXVhbnQsUG9ydGZvbGlvQW5hbHl0aWNzLHF1YW50bW9kLFBlcmZvcm1hbmNlQW5hbHl0aWNzLHpvbywKICAgICAgICAgICAgICAgcGxvdGx5LHRpbWVraXQsZ2d0aGVtZXMscXVhZHByb2cpCmBgYAoKClBvcnRmb2xpbyBvcHRpbWl6YXRpb24gaXMgdGhlIHByb2Nlc3MgIG9mIHNlbGVjdGluZyAgcHJvcG9ydGlvbnMgb2YgdmFyaW91cyBhc3NldHMgdG8gaW5jbHVkZSAgaW4gYSBwb3J0Zm9saW8sIGluIHN1Y2ggYSB3YXkgYXMgdG8gbWFrZSB0aGUgcG9ydGZvbGlvIGJldHRlciB0aGFuIGFueSBvdGhlciBhY2NvcmRpbmcgdG8gc29tZSBjcml0ZXJpb24uIFRoZSBjcml0ZXJpb24gd2lsbCBjb21iaW5lLCBkaXJlY3RseSBvciBpbmRpcmVjdGx5LCBjb25zaWRlcmF0aW9ucyBvZiB0aGUgZXhwZWN0ZWQgdmFsdWUgb2YgdGhlIHBvcnRmb2xpbydzIHJhdGUgb2YgcmV0dXJuIGFzIHdlbGwgYXMgb2YgdGhlIHJldHVybidzIGRpc3BlcnNpb24gYW5kIHBvc3NpYmx5IG90aGVyIG1lYXN1cmVzIG9mIGZpbmFuY2lhbCByaXNrLiBUaGUgb2JqZWN0aXZlIG9mIHBvcnJ0Zm9saW8gb3B0aW1pemF0aW9uIGlzIHRvIG1heGltaXplIGEgbWVhc3VyZSBvZiBnYWluIHBlciB1bml0IG1lYXN1cmUgb2YgcmlzayBhbmQgbWluaW1pemUgYSBtZWFzdXJlIG9mIHJpc2suCgoKTW9kZXJuIHBvcnRmb2xpbyB0aGVvcnkgd2FzIGludHJvZHVjZWQgIGJ5IEhhcnJ5IE1hcmtvd2l0eiBpbiAxOTUyLiBJdCAgYXNzdW1lcyB0aGF0IGluIGdlbmVyYWwsIGFuIGludmVzdG9yIHdhbnRzIHRvIG1heGltaXplIGEgcG9ydGZvbGlvJ3MgZXhwZWN0ZWQgcmV0dXJuIGNvbnRpbmdlbnQgb24gYW55IGdpdmVuIGFtb3VudCBvZiByaXNrLCB3aXRoIHJpc2sgbWVhc3VyZWQgYnkgdGhlIHN0YW5kYXJkIGRldmlhdGlvbiBvZiB0aGUgcG9ydGZvbGlvJ3MgcmF0ZSBvZiByZXR1cm4uIEZvciBwb3J0Zm9saW9zIHRoYXQgbWVldCB0aGlzIGNyaXRlcmlvbiwga25vd24gYXMgZWZmaWNpZW50IHBvcnRmb2xpb3MsIGFjaGlldmluZyBhIGhpZ2hlciBleHBlY3RlZCByZXR1cm4gcmVxdWlyZXMgdGFraW5nIG9uIG1vcmUgcmlzaywgc28gaW52ZXN0b3JzIGFyZSBmYWNlZCB3aXRoIGEgdHJhZGUtb2ZmIGJldHdlZW4gcmlzayBhbmQgZXhwZWN0ZWQgcmV0dXJuLiBUaGlzIHJpc2stZXhwZWN0ZWQgcmV0dXJuIHJlbGF0aW9uc2hpcCBvZiBlZmZpY2llbnQgcG9ydGZvbGlvcyBpcyBncmFwaGljYWxseSByZXByZXNlbnRlZCBieSBhIGN1cnZlIGtub3duIGFzIHRoZSBlZmZpY2llbnQgZnJvbnRpZXIuIEFsbCBlZmZpY2llbnQgcG9ydGZvbGlvcywgZWFjaCByZXByZXNlbnRlZCBieSBhIHBvaW50IG9uIHRoZSBlZmZpY2llbnQgZnJvbnRpZXIsIGFyZSB3ZWxsLWRpdmVyc2lmaWVkLiBGb3IgdGhlIHNwZWNpZmljIGZvcm11bGFzIGZvciBlZmZpY2llbnQgcG9ydGZvbGlvcyxbM10gc2VlIFBvcnRmb2xpbyBzZXBhcmF0aW9uIGluIG1lYW4tdmFyaWFuY2UgYW5hbHlzaXMuIFdoaWxlIGlnbm9yaW5nIGhpZ2hlciBtb21lbnRzIGNhbiBsZWFkIHRvIHNpZ25pZmljYW50IG92ZXItaW52ZXN0bWVudCBpbiByaXNreSBzZWN1cml0aWVzLCBlc3BlY2lhbGx5IHdoZW4gdm9sYXRpbGl0eSBpcyBoaWdoWzRdLCB0aGUgZGV2ZWxvcG1lbnQgb2YgcG9ydGZvbGlvcyBmb3Igbm9uLUdhdXNzaWFuIGVjb25vbWllcyBpcyBtYXRoZW1hdGljYWxseSBjaGFsbGVuZ2luZy4KCgoKCgoKCgoKIyMjIyBQT1JURk9MSU8gT1BUSU1JWkFUSU9OIFVTSU5HIFLigJlTIFNPTFZFLlFQIEZVTkNUSU9OCgpgYGB7cn0KICAgICMjICdodHRwJyBpZiAnaHR0cHMnIHVuYXZhaWxhYmxlCiAgICAjc291cmNlKCJodHRwczovL2Jpb2NvbmR1Y3Rvci5vcmcvYmlvY0xpdGUuUiIpCiAgICAjYmlvY0xpdGUoIkJpb2NVcGdyYWRlIikKICAgIAojcGFjbWFuOjpwX2xvYWQoInN0b2NrUG9ydGZvbGlvIiwgInF1YWRwcm9nIiwgInRpZHl2ZXJzZSIpCmBgYAoKCgoKCgpgYGB7cn0KbGlicmFyeShQb3J0Zm9saW9BbmFseXRpY3MpCmxpYnJhcnkocXVhbnRtb2QpCmxpYnJhcnkoUGVyZm9ybWFuY2VBbmFseXRpY3MpCmxpYnJhcnkoem9vKQpsaWJyYXJ5KHBsb3RseSkKIAojIEdldCBkYXRhCmdldFN5bWJvbHMoYygiTVNGVCIsICJOVkRBIiwgIklCTSIsICJBQVBMIiwgIkZCIiwgIkFNWk4iKSxmcm9tID0gIiAyMDE1LTAxLTAxIixzcmMgPSAneWFob28nKQogCiMgQXNzaWduIHRvIGRhdGFmcmFtZQojIEdldCBhZGp1c3RlZCBwcmljZXMKcHJpY2VzLmRhdGEgPC0gbWVyZ2Uuem9vKE1TRlRbLDZdLCBOVkRBWyw2XSwgSUJNWyw2XSwgQUFQTFssNl0sIEZCWyw2XSwgQU1aTlssNl0pCiAKIyBDYWxjdWxhdGUgcmV0dXJucwpyZXR1cm5zLmRhdGEgPC0gc2FwcGx5KHByaWNlcy5kYXRhLCBDYWxjdWxhdGVSZXR1cm5zKQoKcmV0dXJucy5kYXRhIDwtIG5hLm9taXQocmV0dXJucy5kYXRhKQogCiMgU2V0IG5hbWVzCmNvbG5hbWVzKHJldHVybnMuZGF0YSkgPC0gYygiTVNGVCIsICJOVkRBIiwgIklCTSIsICJBQVBMIiwgIkZCIiwgIkFNWk4iKQogCiMgU2F2ZSBtZWFuIHJldHVybiB2ZWN0b3IgYW5kIHNhbXBsZSBjb3ZhcmlhbmNlIG1hdHJpeAptZWFuUmV0dXJucyA8LSBjb2xNZWFucyhyZXR1cm5zLmRhdGEpCmNvdk1hdCA8LSBjb3YocmV0dXJucy5kYXRhKQpgYGAKCgoKCgoKCgpjcmVhdGluZyBhIHBvcnRmb2xpbyBzcGVjaWZpY2F0aW9uLiBUaGlzIGNhbiBiZSBkb25lIGJ5IHVzaW5nIHBvcnRmb2xpby5zcGVjKCkKCmBgYHtyfQojIFN0YXJ0IHdpdGggdGhlIG5hbWVzIG9mIHRoZSBhc3NldHMKcCA8LSBwb3J0Zm9saW8uc3BlYyhhc3NldHMgPSBjb2xuYW1lcyhyZXR1cm5zLmRhdGEpKQpgYGAKCgpOb3cgZm9yIHNvbWUgY29uc3RyYWludHMuIExldOKAmXMgdXNlIHRoZSBmb2xsb3dpbmc6CgpCb3ggY29uc3RyYWludHMKTGV2ZXJhZ2UgKHdlaWdodCBzdW0pCgoKYGBge3J9CiMgQm94CnAgPC0gYWRkLmNvbnN0cmFpbnQocCwgdHlwZSA9ICJib3giLCBtaW4gPSAwLjA1LCBtYXggPSAwLjgpCgojIExldmVyYWdlCnAgPC0gYWRkLmNvbnN0cmFpbnQocG9ydGZvbGlvID0gcCwgdHlwZSA9ICJmdWxsX2ludmVzdG1lbnQiKQpgYGAKClRoZSByYW5kb20gc29sdmVyIGVzc2VudGlhbGx5IGNyZWF0ZXMgYSBzZXQgb2YgZmVhc2libGUgcG9ydGZvbGlvcyB0aGF0IHNhdGlzZnkgYWxsIHRoZSBjb25zdHJhaW50cyB3ZSBoYXZlIHNwZWNpZmllZC4KCgpgYGB7cn0KIyBHZW5lcmF0ZSByYW5kb20gcG9ydGZvbGlvcwpyYW5kb21wb3J0PC0gcmFuZG9tX3BvcnRmb2xpb3MocCwgcGVybXV0YXRpb25zID0gNTAwMDAsIHJwX21ldGhvZCA9ICJzYW1wbGUiKQpgYGAKCgoKCgoKCgoKCmBgYHtyfQoKCnAgPC0gYWRkLmNvbnN0cmFpbnQocG9ydGZvbGlvID0gcCwgdHlwZSA9ICJmdWxsX2ludmVzdG1lbnQiKQpwIDwtIGFkZC5jb25zdHJhaW50KHAsIHR5cGU9Imxvbmdfb25seSIpCiMgR2V0IG1pbmltdW0gdmFyaWFuY2UgcG9ydGZvbGlvCm1pbnZhci5wb3J0IDwtIGFkZC5vYmplY3RpdmUocCwgdHlwZSA9ICJyaXNrIiwgbmFtZSA9ICJ2YXIiKQogCiMgT3B0aW1pemUKbWludmFyLm9wdCA8LSBvcHRpbWl6ZS5wb3J0Zm9saW8ocmV0dXJucy5kYXRhLCBtaW52YXIucG9ydCwgb3B0aW1pemVfbWV0aG9kID0gInJhbmRvbSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBycCA9IHJhbmRvbXBvcnQpCiAKIyBHZW5lcmF0ZSBtYXhpbXVtIHJldHVybiBwb3J0Zm9saW8KbWF4cmV0LnBvcnQgPC0gYWRkLm9iamVjdGl2ZShwLCB0eXBlID0gInJldHVybiIsIG5hbWUgPSAibWVhbiIpCiAKIyBPcHRpbWl6ZQptYXhyZXQub3B0IDwtIG9wdGltaXplLnBvcnRmb2xpbyhyZXR1cm5zLmRhdGEsIG1heHJldC5wb3J0LCBvcHRpbWl6ZV9tZXRob2QgPSAicmFuZG9tIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJwID0gcmFuZG9tcG9ydCkKIAojIEdlbmVyYXRlIHZlY3RvciBvZiByZXR1cm5zCiNtaW5yZXQgPC0gMC4wMi8xMDAKCm1pbnJldCA8LSBtaW4obWVhblJldHVybnMpCm1heHJldCA8LSBtYXgobWVhblJldHVybnMpCiNtYXhyZXQgPC0gbWF4cmV0Lm9wdCR3ZWlnaHRzICUqJSBtZWFuUmV0dXJucwogCnZlYyA8LSBzZXEobWlucmV0LCBtYXhyZXQsIGxlbmd0aC5vdXQgPSAxMDApCgpgYGAKCgoKCmBgYHtyfQplZmYuZnJvbnRpZXIgPC0gZGF0YS5mcmFtZShSaXNrID12ZWN0b3IoIm51bWVyaWMiLCBsZW5ndGgodmVjKSkgLAogICAgICAgICAgICAgICAgICAgICAgICAgICBSZXR1cm4gPSB2ZWN0b3IoIm51bWVyaWMiLCBsZW5ndGgodmVjKSkpCiAKZnJvbnRpZXIud2VpZ2h0cyA8LSBtYXQub3IudmVjKG5yID0gbGVuZ3RoKHZlYyksIG5jID0gbmNvbChyZXR1cm5zLmRhdGEpKQoKY29sbmFtZXMoZnJvbnRpZXIud2VpZ2h0cykgPC0gY29sbmFtZXMocmV0dXJucy5kYXRhKQogCmZvcihpIGluIDE6bGVuZ3RoKHZlYykpewogIAogICMgQ3JlYXRlcyBhIG5ldyBwb3J0Zm9saW8gb2JqZWN0IHVzaW5nIHAgYW5kIGFkZHMgbWVhbiBhcyBhbiBvYmplY3RpdmUKICAKICBwIDwtIGFkZC5jb25zdHJhaW50KHAsIHR5cGUgPSAicmV0dXJuIiwgbmFtZSA9ICJtZWFuIiwgcmV0dXJuX3RhcmdldCA9IHZlY1tpXSkKICAKICAjIENyZWF0ZXMgYSBuZXcgcG9ydGZvbGlvIG9iamVjdCB1c2luZyBwIGFuZCBhZGRzIHZhciBhcyBhbiBvYmplY3RpdmUKICBwIDwtIGFkZC5vYmplY3RpdmUocCwgdHlwZSA9ICJyaXNrIiwgbmFtZSA9ICJ2YXIiKQogIAojIENyZWF0ZXMgYSBuZXcgcG9ydGZvbGlvIG9iamVjdCB1c2luZyBwIGFuZCBhZGRzIGEgd2VpZ2h0X2NvbmNlbnRyYXRpb24KIyBvYmplY3RpdmUuIFRoZSBjb25jX2F2ZXJzaW9uIHBhcmFtZXRlciBjb250cm9scyBob3cgbXVjaCBjb25jZW50cmF0aW9uIGlzCiMgcGVuYWxpemVkLiBUaGUgcG9ydGZvbGlvIGNvbmNlbnRyYXRpb24gaXMgZGVmaW5lZCBhcyB0aGUgSGVyZmluZGFobCBIaXJzY2htYW4KIyBJbmRleCBvZiB0aGUgd2VpZ2h0cy4KICBwIDwtIGFkZC5vYmplY3RpdmUocCwgdHlwZSA9ICJ3ZWlnaHRfY29uY2VudHJhdGlvbiIsIG5hbWUgPSAiSEhJIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25jX2F2ZXJzaW9uID0gMC4wMSkKIAogIGVmZi5vcHQgPC0gb3B0aW1pemUucG9ydGZvbGlvKHJldHVybnMuZGF0YSwgcCwgb3B0aW1pemVfbWV0aG9kID0gIlJPSSIpCiAgCiAgZWZmLmZyb250aWVyJFJpc2tbaV0gPC0gc3FydCh0KGVmZi5vcHQkd2VpZ2h0cykgJSolIGNvdk1hdCAlKiUgZWZmLm9wdCR3ZWlnaHRzKQogIAogIGVmZi5mcm9udGllciRSZXR1cm5baV0gPC0gZWZmLm9wdCR3ZWlnaHRzICUqJSBtZWFuUmV0dXJucwogIAogIAogIAogIGZyb250aWVyLndlaWdodHNbaSxdID0gZWZmLm9wdCR3ZWlnaHRzCiAgCiAjIHByaW50KHBhc3RlKHJvdW5kKGkvbGVuZ3RoKHZlYykgKiAxMDAsIDApLCAiJSBkb25lLi4uIikpCiAgCn0KCmVmZi5mcm9udGllciRTaGFycGVyYXRpbyA8LSBlZmYuZnJvbnRpZXIkUmV0dXJuIC8gZWZmLmZyb250aWVyJFJpc2sKCgpgYGAKCgoKCmBgYHtyfQpmZWFzaWJsZS5zZCA8LSBhcHBseShyYW5kb21wb3J0LCAxLCBmdW5jdGlvbih4KXsKICByZXR1cm4oc3FydChtYXRyaXgoeCwgbnJvdyA9IDEpICUqJSBjb3ZNYXQgJSolIG1hdHJpeCh4LCBuY29sID0gMSkpKQp9KQogCmZlYXNpYmxlLm1lYW5zIDwtIGFwcGx5KHJhbmRvbXBvcnQsIDEsIGZ1bmN0aW9uKHgpewogIHJldHVybih4ICUqJSBtZWFuUmV0dXJucykKfSkKIApmZWFzaWJsZS5zciA8LSBmZWFzaWJsZS5tZWFucyAvIGZlYXNpYmxlLnNkCgpwIDwtIHBsb3RfbHkoKSAlPiUKICBhZGRfdHJhY2UoeCA9IGZlYXNpYmxlLnNkLCB5ID0gZmVhc2libGUubWVhbnMsIGNvbG9yID0gZmVhc2libGUuc3IsIAogICAgICAgIG1vZGUgPSAibWFya2VycyIsIHR5cGUgPSAic2NhdHRlcmdsIiwgc2hvd2xlZ2VuZCA9IEYsCiAgICAgICAgCiAgICAgICAgbWFya2VyID0gbGlzdChzaXplID0gMywgb3BhY2l0eSA9IDAuNSwgCiAgICAgICAgICAgICAgICAgICAgICBjb2xvcmJhciA9IGxpc3QodGl0bGUgPSAiU2hhcnBlIFJhdGlvIikpKSAlPiUKICBhZGRfdHJhY2UoZGF0YSA9IGVmZi5mcm9udGllciwgeCA9IH5SaXNrLCB5ID0gflJldHVybixtb2RlID0gIm1hcmtlcnMiLCB0eXBlID0gInNjYXR0ZXJnbCIpJT4lIAogIGxheW91dCh0aXRsZSA9ICJFZmZpY2llbnQgRnJvbnRpZXIiLAogICAgICAgICB5YXhpcyA9IGxpc3QodGl0bGUgPSAiTWVhbiBSZXR1cm5zIiwgdGlja2Zvcm1hdCA9ICIuMiUiKSwKICAgICAgICAgeGF4aXMgPSBsaXN0KHRpdGxlID0gIlN0YW5kYXJkIERldmlhdGlvbiIsIHRpY2tmb3JtYXQgPSAiLjIlIikpCgpwCgpgYGAKCgoKYGBge3J9CgogCnAxIDwtIHBsb3RfbHkoeCA9IH5mZWFzaWJsZS5zZCwgeSA9IGZlYXNpYmxlLm1lYW5zLCBjb2xvciA9IGZlYXNpYmxlLnNyLCAKICAgICAgICBtb2RlID0gIm1hcmtlcnMiLCB0eXBlID0gInNjYXR0ZXJnbCIsIHNob3dsZWdlbmQgPSBGLAogICAgICAgIAogICAgICAgIG1hcmtlciA9IGxpc3Qoc2l6ZSA9IDMsIG9wYWNpdHkgPSAwLjUsIAogICAgICAgICAgICAgICAgICAgICAgY29sb3JiYXIgPSBsaXN0KHRpdGxlID0gIlNoYXJwZSBSYXRpbyIpKSklPiUgCiAgCiAgCiAKICAgIyBhZGRfdHJhY2UoZGF0YSA9IGVmZi5mcm9udGllciwgeCA9IH5SaXNrLCB5ID0gflJldHVybiwgbW9kZSA9ICJtYXJrZXJzIiwgCiAgICMgICAgICAgICAgdHlwZSA9ICJzY2F0dGVyZ2wiLCBzaG93bGVnZW5kID0gRiwgCiAgICMgICAgICAgICAgbWFya2VyID0gbGlzdChjb2xvciA9ICIjRjdDODczIiwgc2l6ZSA9IDUpKSAlPiUgCiAgCiAgbGF5b3V0KHRpdGxlID0gIlJhbmRvbSBQb3J0Zm9saW9zIHdpdGggUGxvdGx5IiwKICAgICAgICAgeWF4aXMgPSBsaXN0KHRpdGxlID0gIk1lYW4gUmV0dXJucyIsIHRpY2tmb3JtYXQgPSAiLjIlIiksCiAgICAgICAgIHhheGlzID0gbGlzdCh0aXRsZSA9ICJTdGFuZGFyZCBEZXZpYXRpb24iLCB0aWNrZm9ybWF0ID0gIi4yJSIpKQogICAgICAgICAjcGxvdF9iZ2NvbG9yID0gIiM0MzQzNDMiLAogICAgICAgICAjcGFwZXJfYmdjb2xvciA9ICIjRjhGOEY4IiwKICAgICAgICAgI2Fubm90YXRpb25zID0gbGlzdCgKICAgICAgICAgICMgbGlzdCh4ID0gMC40LCB5ID0gMC43NSwgCiAgICAgICAgICAgICAgICAjYXggPSAtMzAsIGF5ID0gLTMwLCAKICAgICAgICAgICAgICAgICN0ZXh0ID0gIkVmZmljaWVudCBmcm9udGllciIsIAogICAgICAgICAgICAgICAgI2ZvbnQgPSBsaXN0KGNvbG9yID0gIiNGNkU3QzEiLCBzaXplID0gMTUpLAogICAgICAgICAgICAgICAjIGFycm93Y29sb3IgPSAid2hpdGUiKQogICAgICAgICMgKSkKCgoKCgpwMiA8LSBwbG90X2x5KGRhdGEgPSBlZmYuZnJvbnRpZXIsIHggPSB+UmlzaywgeSA9IH5SZXR1cm4sbW9kZSA9ICJtYXJrZXJzIiwgdHlwZSA9ICJzY2F0dGVyZ2wiKSU+JSAKICBsYXlvdXQodGl0bGUgPSAiUmFuZG9tIFBvcnRmb2xpb3Mgd2l0aCBQbG90bHkiLAogICAgICAgICB5YXhpcyA9IGxpc3QodGl0bGUgPSAiTWVhbiBSZXR1cm5zIiwgdGlja2Zvcm1hdCA9ICIuMiUiKSwKICAgICAgICAgeGF4aXMgPSBsaXN0KHRpdGxlID0gIlN0YW5kYXJkIERldmlhdGlvbiIsIHRpY2tmb3JtYXQgPSAiLjIlIikpCgoKcCA8LSBzdWJwbG90KHAxLCBwMikKCnAKYGBgCgoKCgoKCmBgYHtyfQoKZD1hcy50aWJibGUoZnJvbnRpZXIud2VpZ2h0cyklPiV0aWR5cjo6Z2F0aGVyKFN0b2NrLFdlaWdodHMpJT4lYWRkX2NvbHVtbihJbmRleD1yZXAoMToxMDAsNikpCgpwIDwtIHBsb3RfbHkoZCwgeCA9IH5JbmRleCwgeSA9IH5XZWlnaHRzLCBjb2xvciA9IH5TdG9jaywgdHlwZSA9ICJiYXIiKSAlPiUKICBsYXlvdXQodGl0bGUgPSAiUG9ydGZvbGlvIHdlaWdodHMgYWNyb3NzIGZyb250aWVyIiwgYmFybW9kZSA9ICJzdGFjayIsCiAgICAgICAgIHhheGlzID0gbGlzdCh0aXRsZSA9ICJJbmRleCIpLAogICAgICAgICB5YXhpcyA9IGxpc3QodGl0bGUgPSAiV2VpZ2h0cyglKSIsIHRpY2tmb3JtYXQgPSAiLjAlIikpCgpwCgpgYGAKCgoKCmBgYHtyfQpzZWFyY2goKSAgICAjIHNlZSBwYWNrYWdlcyBjdXJyZW50bHkgbG9hZGVkCgoKYGBgCgoKYGBge3J9CnNlc3Npb25JbmZvKCkKCgpgYGAKCgpgYGB7cn0KcHJpbnQocGFzdGUoIlIiLCBnZXRSdmVyc2lvbigpKSkKcHJpbnQoIi0tLS0tLS0tLS0tLS0iKQpmb3IgKHBhY2thZ2VfbmFtZSBpbiBzb3J0KGxvYWRlZE5hbWVzcGFjZXMoKSkpIHsKICAgIHByaW50KHBhc3RlKHBhY2thZ2VfbmFtZSwgcGFja2FnZVZlcnNpb24ocGFja2FnZV9uYW1lKSkpCn0KYGBgCgoKYGBge3J9CiNpbnN0YWxsZWQucGFja2FnZXMoZmllbGRzID0gYyAoIlBhY2thZ2UiLCAiVmVyc2lvbiIpKQpgYGAKCg==