#install.packages("tseries")
library("tseries")
#install.packages("quantmod")
library("quantmod")
#install.packages("Quandl")
library("Quandl")
#install.packages("PortfolioAnalytics")
library("PortfolioAnalytics")
#install.packages("DEoptim")
library("DEoptim")
library("xts")
#install.packages("knitr")
#library("knitr")
# Reading of Data
data <- read.csv("anupam.csv", header = T)
data <- xts(data[ ,2:5], order.by = as.Date.factor(data[,1]))
View(data)
# Indian Stocks from BSE Index
stocks <- data[,1]
mstocks <- monthlyReturn(stocks, type = "arithmetic")
colnames(mstocks) <- "mstocks"
table.AnnualizedReturns(mstocks)
charts.PerformanceSummary(mstocks)

# Indian Bonds - PGIM India Premier Bond Fund Growth (0P00005VBS.BO)
indian_bonds <- data[,2]
m_indian_bonds <- monthlyReturn(indian_bonds)
colnames(indian_bonds) <- "m_indian_bonds"
table.AnnualizedReturns(m_indian_bonds)
charts.PerformanceSummary(m_indian_bonds)

# International Stocks - From NASDAQ
int_stocks <- data[,3]
mint_stocks <- monthlyReturn(int_stocks)
colnames(mint_stocks) <- "mint_stocks"
table.AnnualizedReturns(mint_stocks)
charts.PerformanceSummary(mint_stocks)

# International Bonds - NASDAQ
intl_bonds <- data[,4]
mintl_bonds <- monthlyReturn(intl_bonds)
colnames(intl_bonds) <- "mintl_bonds"
table.AnnualizedReturns(mintl_bonds)
charts.PerformanceSummary(mintl_bonds)

# Comparing Indian & Intl Bonds
bondscomp <- cbind(m_indian_bonds,mintl_bonds)
table.AnnualizedReturns(bondscomp)
charts.PerformanceSummary(bondscomp)

# Comparing Indian BSE & Intl Stocks
stockcomp <- cbind(mstocks,mint_stocks)
table.AnnualizedReturns(stockcomp)
charts.PerformanceSummary(stockcomp)

# 4. Portfolio Optimization
# 4.2. Portfolio Benchmarks
# 4.2.1. Portfolio Assets Returns Matrix
mport <- cbind(mstocks,mint_stocks,m_indian_bonds, mintl_bonds)
# 4.2.2. Naive Global Portfolio (Monthly Rebalancing)
mnaivew <- as.numeric(t(c(0.25,0.25,0.25,0.25)))
names(mnaivew) <- c("mstocks","mint_stocks","m_indian_bonds","mintl_bonds")
mnaive <- Return.portfolio(R=mport,weights=mnaivew,geometric=F,rebalance_on="months")
colnames(mnaive) <- "mnaive"
# 4.2.3. Roche Global Portfolio (Monthly Rebalancing)
mrochew <- as.numeric(t(c(0.24,0.18,0.33,0.25)))
names(mrochew) <- c("mstocks","mint_stocks","m_indian_bonds","mintl_bonds")
mroche <- Return.portfolio(R=mport,weights=mrochew,geometric=F,rebalance_on="months")
colnames(mroche) <- "mroche"
# 4.2.4. Bogle U.S. Portfolio (Monthly Rebalancing)
mboglew <- as.numeric(t(c(0.40,0.60,0.00,0.00)))
names(mboglew) <- c("mstocks","mint_stocks","m_indian_bonds","mintl_bonds")
mbogle <- Return.portfolio(R=mport,weights=mboglew,geometric=F,rebalance_on="months")
colnames(mbogle) <- "mbogle"
# 4.2.6. Benchmark Portfolios Returns Comparison
benchcomp <- cbind(mnaive,mroche,mbogle)
table.AnnualizedReturns(benchcomp)
charts.PerformanceSummary(benchcomp)

# 4.3. Portfolio Optimization
# 4.3.1. Mean Maximization
# Portfolio Specifications
mport1c <- portfolio.spec(assets = colnames(mport))
# Portfolio Constraints
mport1c <- add.constraint(mport1c,type="weight_sum",min_sum=0.99,max_sum=1.01)
mport1c <- add.constraint(mport1c,type="long_only")
# Portfolio Objectives
mport1c <- add.objective(mport1c,type="return",name="mean")
# Portfolio Optimization
mportopt1 <- optimize.portfolio(R=mport["::2021-12-31"],portfolio=mport1c,optimize_method="DEoptim",search_size=20000,trace=T )
Iteration: 1 bestvalit: -0.013132 bestmemit: 0.004000 0.994000 0.000000 0.012000
Iteration: 2 bestvalit: -0.013132 bestmemit: 0.004000 0.994000 0.000000 0.012000
Iteration: 3 bestvalit: -0.013132 bestmemit: 0.004000 0.994000 0.000000 0.012000
Iteration: 4 bestvalit: -0.013132 bestmemit: 0.004000 0.994000 0.000000 0.012000
Iteration: 5 bestvalit: -0.013132 bestmemit: 0.004000 0.994000 0.000000 0.012000
Iteration: 6 bestvalit: -0.013132 bestmemit: 0.004000 0.994000 0.000000 0.012000
Iteration: 7 bestvalit: -0.013132 bestmemit: 0.004000 0.994000 0.000000 0.012000
[1] 0.004 0.994 0.000 0.012
chart.Weights(mportopt1)

# 4.3.2. Standard deviation minimization
# Portfolio Specifications
mport2c <- portfolio.spec(assets=colnames(mport))
# Portfolio Constraints
mport2c <- add.constraint(mport2c,type="weight_sum",min_sum=0.99,max_sum=1.01)
mport2c <- add.constraint(mport2c,type="long_only")
# Portfolio Objectives
mport2c <- add.objective(mport2c,type="risk",name="StdDev")
# Portfolio Optimization
mportopt2 <- optimize.portfolio(R=mport["::2021-12-31"],portfolio=mport2c,optimize_method="DEoptim",search_size=20000,trace=T)
Iteration: 1 bestvalit: 0.001255 bestmemit: 0.004000 0.026000 0.974000 0.000000
Iteration: 2 bestvalit: 0.001255 bestmemit: 0.004000 0.026000 0.974000 0.000000
Iteration: 3 bestvalit: 0.001255 bestmemit: 0.004000 0.026000 0.974000 0.000000
Iteration: 4 bestvalit: 0.001255 bestmemit: 0.004000 0.026000 0.974000 0.000000
Iteration: 5 bestvalit: 0.001255 bestmemit: 0.004000 0.026000 0.974000 0.000000
Iteration: 6 bestvalit: 0.001255 bestmemit: 0.004000 0.026000 0.974000 0.000000
Iteration: 7 bestvalit: 0.001058 bestmemit: 0.014000 0.000000 0.964000 0.014000
Iteration: 8 bestvalit: 0.000691 bestmemit: 0.000000 0.000000 0.996000 0.014000
Iteration: 9 bestvalit: 0.000691 bestmemit: 0.000000 0.000000 0.996000 0.014000
Iteration: 10 bestvalit: 0.000628 bestmemit: 0.002000 0.006000 0.990000 0.000000
Iteration: 11 bestvalit: 0.000628 bestmemit: 0.002000 0.006000 0.990000 0.000000
Iteration: 12 bestvalit: 0.000628 bestmemit: 0.002000 0.006000 0.990000 0.000000
Iteration: 13 bestvalit: 0.000628 bestmemit: 0.002000 0.006000 0.990000 0.000000
Iteration: 14 bestvalit: 0.000628 bestmemit: 0.002000 0.006000 0.990000 0.000000
Iteration: 15 bestvalit: 0.000628 bestmemit: 0.002000 0.006000 0.990000 0.000000
Iteration: 16 bestvalit: 0.000628 bestmemit: 0.002000 0.006000 0.990000 0.000000
Iteration: 17 bestvalit: 0.000628 bestmemit: 0.002000 0.006000 0.990000 0.000000
[1] 0.002 0.006 0.990 0.000
chart.Weights(mportopt2)

# 4.3.3. Mean Maximization and Standard Deviation Minimization Portfolio
# Portfolio Specifications
mport3c <- portfolio.spec(assets=colnames(mport))
# Portfolio Constraints
mport3c <- add.constraint(mport3c,type="weight_sum",min_sum=0.99,max_sum=1.01)
mport3c <- add.constraint(mport3c,type="long_only")
# Portfolio Objectives
mport3c <- add.objective(mport3c,type="return",name="mean")
mport3c <- add.objective(mport3c,type="risk",name="StdDev")
# Portfolio Optimization
mportopt3 <- optimize.portfolio(R=mport["::2021-12-31"],portfolio=mport3c,optimize_method="DEoptim",search_size=20000,trace=T)
Iteration: 1 bestvalit: -0.005359 bestmemit: 0.006000 0.004000 0.990000 0.000000
Iteration: 2 bestvalit: -0.005359 bestmemit: 0.006000 0.004000 0.990000 0.000000
Iteration: 3 bestvalit: -0.005359 bestmemit: 0.006000 0.004000 0.990000 0.000000
Iteration: 4 bestvalit: -0.005359 bestmemit: 0.006000 0.004000 0.990000 0.000000
Iteration: 5 bestvalit: -0.005359 bestmemit: 0.006000 0.004000 0.990000 0.000000
Iteration: 6 bestvalit: -0.005359 bestmemit: 0.006000 0.004000 0.990000 0.000000
Iteration: 7 bestvalit: -0.005359 bestmemit: 0.006000 0.004000 0.990000 0.000000
Iteration: 8 bestvalit: -0.005359 bestmemit: 0.006000 0.004000 0.990000 0.000000
[1] 0.006 0.004 0.990 0.000
chart.Weights(mportopt3)

chart.EfficientFrontier(mportopt3,match.col="StdDev")

# 4.3.4. Mean Maximization Value at Risk (VaR) Minimization Portfolio
# Portfolio Specifications
mport4c <- portfolio.spec(assets=colnames(mport))
# Portfolio Constraints
mport4c <- add.constraint(mport4c,type="weight_sum",min_sum=0.99,max_sum=1.01)
mport4c <- add.constraint(mport4c,type="long_only")
# Portfolio Objectives
mport4c <- add.objective(mport4c,type="return",name="mean")
mport4c <- add.objective(mport4c,type="risk",name="VaR",arguments=list(p = 0.99,method="modified"))
# Portfolio Optimization
mportopt4 <- optimize.portfolio(R=mport["::2021-12-31"],portfolio=mport4c,optimize_method="DEoptim",search_size=20000,trace=T)
Iteration: 1 bestvalit: -0.003747 bestmemit: 0.000000 0.008000 0.912000 0.084000
Iteration: 2 bestvalit: -0.003747 bestmemit: 0.000000 0.008000 0.912000 0.084000
Iteration: 3 bestvalit: -0.003747 bestmemit: 0.000000 0.008000 0.912000 0.084000
VaR calculation produces unreliable result (inverse risk) for column: 1 : -1.29607669646214e-05
Warning in FUN(newX[, i], ...) :
NA or NaN produced in objective function for weights 0.0160.0020.960.028
Iteration: 4 bestvalit: -0.003747 bestmemit: 0.000000 0.008000 0.912000 0.084000
VaR calculation produces unreliable result (inverse risk) for column: 1 : -0.000792700838880535
Warning in FUN(newX[, i], ...) :
NA or NaN produced in objective function for weights 0.0040.0180.9580.0190368894291137
Iteration: 5 bestvalit: -0.003747 bestmemit: 0.000000 0.008000 0.912000 0.084000
VaR calculation produces unreliable result (inverse risk) for column: 1 : -0.00128555619418081
Warning in FUN(newX[, i], ...) :
NA or NaN produced in objective function for weights 00.0040.9720.034
Iteration: 6 bestvalit: -0.003747 bestmemit: 0.000000 0.008000 0.912000 0.084000
VaR calculation produces unreliable result (inverse risk) for column: 1 : -0.000459446799292463
Warning in FUN(newX[, i], ...) :
NA or NaN produced in objective function for weights 0.004708329857731880.020.9505835071134060.022
Iteration: 7 bestvalit: -0.005319 bestmemit: 0.002376 0.034867 0.935243 0.031624
Iteration: 8 bestvalit: -0.005319 bestmemit: 0.002376 0.034867 0.935243 0.031624
Iteration: 9 bestvalit: -0.005319 bestmemit: 0.002376 0.034867 0.935243 0.031624
VaR calculation produces unreliable result (inverse risk) for column: 1 : -0.00116990908081472
Warning in FUN(newX[, i], ...) :
NA or NaN produced in objective function for weights 0.00800.9720.024
Iteration: 10 bestvalit: -0.005319 bestmemit: 0.002376 0.034867 0.935243 0.031624
Iteration: 11 bestvalit: -0.005319 bestmemit: 0.002376 0.034867 0.935243 0.031624
VaR calculation produces unreliable result (inverse risk) for column: 1 : -0.000612935601496843
Warning in FUN(newX[, i], ...) :
NA or NaN produced in objective function for weights 0.0100.950.034
Iteration: 12 bestvalit: -0.005319 bestmemit: 0.002376 0.034867 0.935243 0.031624
Iteration: 13 bestvalit: -0.005319 bestmemit: 0.002376 0.034867 0.935243 0.031624
VaR calculation produces unreliable result (inverse risk) for column: 1 : -0.00105573779958479
Warning in FUN(newX[, i], ...) :
NA or NaN produced in objective function for weights 0.0060.010.9740.016
Iteration: 14 bestvalit: -0.005319 bestmemit: 0.002376 0.034867 0.935243 0.031624
[1] 0.002376075 0.034867119 0.935243386
[4] 0.031623732
chart.Weights(mportopt4)

# 4.3.5. Optimized Portfolios Backtesting Comparison
#mportcomp <- cbind(mnaive["2015-01-31::"],mportopt1,mportopt2,mportopt3,mportopt4)
mportcomp <- cbind(mportopt1,mportopt2,mportopt3,mport4c)
table.AnnualizedReturns(mportcomp)
Error in if (class(x) == "numeric") { : the condition has length > 1
LS0tDQp0aXRsZTogIlIgTm90ZWJvb2siDQpvdXRwdXQ6DQogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQNCiAgcGRmX2RvY3VtZW50OiBkZWZhdWx0DQotLS0NCg0KDQpgYGB7cn0NCiNpbnN0YWxsLnBhY2thZ2VzKCJ0c2VyaWVzIikNCmxpYnJhcnkoInRzZXJpZXMiKQ0KI2luc3RhbGwucGFja2FnZXMoInF1YW50bW9kIikNCmxpYnJhcnkoInF1YW50bW9kIikNCiNpbnN0YWxsLnBhY2thZ2VzKCJRdWFuZGwiKQ0KbGlicmFyeSgiUXVhbmRsIikNCiNpbnN0YWxsLnBhY2thZ2VzKCJQb3J0Zm9saW9BbmFseXRpY3MiKQ0KbGlicmFyeSgiUG9ydGZvbGlvQW5hbHl0aWNzIikNCiNpbnN0YWxsLnBhY2thZ2VzKCJERW9wdGltIikNCmxpYnJhcnkoIkRFb3B0aW0iKQ0KbGlicmFyeSgieHRzIikNCiNpbnN0YWxsLnBhY2thZ2VzKCJrbml0ciIpDQojbGlicmFyeSgia25pdHIiKQ0KDQojIFJlYWRpbmcgb2YgRGF0YQ0KZGF0YSA8LSByZWFkLmNzdigiYW51cGFtLmNzdiIsIGhlYWRlciA9IFQpDQpkYXRhIDwtIHh0cyhkYXRhWyAsMjo1XSwgb3JkZXIuYnkgPSBhcy5EYXRlLmZhY3RvcihkYXRhWywxXSkpICANClZpZXcoZGF0YSkNCg0KIyBJbmRpYW4gU3RvY2tzIGZyb20gQlNFIEluZGV4IA0Kc3RvY2tzIDwtIGRhdGFbLDFdDQptc3RvY2tzIDwtIG1vbnRobHlSZXR1cm4oc3RvY2tzLCB0eXBlID0gImFyaXRobWV0aWMiKQ0KY29sbmFtZXMobXN0b2NrcykgPC0gIm1zdG9ja3MiDQp0YWJsZS5Bbm51YWxpemVkUmV0dXJucyhtc3RvY2tzKQ0KY2hhcnRzLlBlcmZvcm1hbmNlU3VtbWFyeShtc3RvY2tzKQ0KDQojIEluZGlhbiBCb25kcyAtIFBHSU0gSW5kaWEgUHJlbWllciBCb25kIEZ1bmQgR3Jvd3RoICgwUDAwMDA1VkJTLkJPKQ0KDQppbmRpYW5fYm9uZHMgPC0gZGF0YVssMl0NCm1faW5kaWFuX2JvbmRzIDwtIG1vbnRobHlSZXR1cm4oaW5kaWFuX2JvbmRzKQ0KY29sbmFtZXMoaW5kaWFuX2JvbmRzKSA8LSAibV9pbmRpYW5fYm9uZHMiDQp0YWJsZS5Bbm51YWxpemVkUmV0dXJucyhtX2luZGlhbl9ib25kcykNCmNoYXJ0cy5QZXJmb3JtYW5jZVN1bW1hcnkobV9pbmRpYW5fYm9uZHMpDQoNCiMgSW50ZXJuYXRpb25hbCBTdG9ja3MgLSBGcm9tIE5BU0RBUQ0KDQppbnRfc3RvY2tzIDwtIGRhdGFbLDNdDQptaW50X3N0b2NrcyA8LSBtb250aGx5UmV0dXJuKGludF9zdG9ja3MpDQpjb2xuYW1lcyhtaW50X3N0b2NrcykgPC0gIm1pbnRfc3RvY2tzIg0KdGFibGUuQW5udWFsaXplZFJldHVybnMobWludF9zdG9ja3MpDQpjaGFydHMuUGVyZm9ybWFuY2VTdW1tYXJ5KG1pbnRfc3RvY2tzKQ0KDQojIEludGVybmF0aW9uYWwgQm9uZHMgLSBOQVNEQVENCmludGxfYm9uZHMgPC0gZGF0YVssNF0NCm1pbnRsX2JvbmRzIDwtIG1vbnRobHlSZXR1cm4oaW50bF9ib25kcykNCmNvbG5hbWVzKGludGxfYm9uZHMpIDwtICJtaW50bF9ib25kcyINCnRhYmxlLkFubnVhbGl6ZWRSZXR1cm5zKG1pbnRsX2JvbmRzKQ0KY2hhcnRzLlBlcmZvcm1hbmNlU3VtbWFyeShtaW50bF9ib25kcykNCg0KIyBDb21wYXJpbmcgSW5kaWFuICYgSW50bCBCb25kcw0KYm9uZHNjb21wIDwtIGNiaW5kKG1faW5kaWFuX2JvbmRzLG1pbnRsX2JvbmRzKQ0KdGFibGUuQW5udWFsaXplZFJldHVybnMoYm9uZHNjb21wKQ0KY2hhcnRzLlBlcmZvcm1hbmNlU3VtbWFyeShib25kc2NvbXApDQoNCiMgQ29tcGFyaW5nIEluZGlhbiBCU0UgJiBJbnRsIFN0b2Nrcw0KDQpzdG9ja2NvbXAgPC0gY2JpbmQobXN0b2NrcyxtaW50X3N0b2NrcykNCnRhYmxlLkFubnVhbGl6ZWRSZXR1cm5zKHN0b2NrY29tcCkNCmNoYXJ0cy5QZXJmb3JtYW5jZVN1bW1hcnkoc3RvY2tjb21wKQ0KDQojIDQuIFBvcnRmb2xpbyBPcHRpbWl6YXRpb24NCg0KIyA0LjIuIFBvcnRmb2xpbyBCZW5jaG1hcmtzIA0KDQojIDQuMi4xLiBQb3J0Zm9saW8gQXNzZXRzIFJldHVybnMgTWF0cml4DQptcG9ydCA8LSBjYmluZChtc3RvY2tzLG1pbnRfc3RvY2tzLG1faW5kaWFuX2JvbmRzLCBtaW50bF9ib25kcykNCg0KIyA0LjIuMi4gTmFpdmUgR2xvYmFsIFBvcnRmb2xpbyAoTW9udGhseSBSZWJhbGFuY2luZykNCm1uYWl2ZXcgPC0gYXMubnVtZXJpYyh0KGMoMC4yNSwwLjI1LDAuMjUsMC4yNSkpKQ0KbmFtZXMobW5haXZldykgPC0gYygibXN0b2NrcyIsIm1pbnRfc3RvY2tzIiwibV9pbmRpYW5fYm9uZHMiLCJtaW50bF9ib25kcyIpDQptbmFpdmUgPC0gUmV0dXJuLnBvcnRmb2xpbyhSPW1wb3J0LHdlaWdodHM9bW5haXZldyxnZW9tZXRyaWM9RixyZWJhbGFuY2Vfb249Im1vbnRocyIpDQpjb2xuYW1lcyhtbmFpdmUpIDwtICJtbmFpdmUiDQoNCiMgNC4yLjMuIFJvY2hlIEdsb2JhbCBQb3J0Zm9saW8gKE1vbnRobHkgUmViYWxhbmNpbmcpDQptcm9jaGV3IDwtIGFzLm51bWVyaWModChjKDAuMjQsMC4xOCwwLjMzLDAuMjUpKSkNCm5hbWVzKG1yb2NoZXcpIDwtIGMoIm1zdG9ja3MiLCJtaW50X3N0b2NrcyIsIm1faW5kaWFuX2JvbmRzIiwibWludGxfYm9uZHMiKQ0KbXJvY2hlIDwtIFJldHVybi5wb3J0Zm9saW8oUj1tcG9ydCx3ZWlnaHRzPW1yb2NoZXcsZ2VvbWV0cmljPUYscmViYWxhbmNlX29uPSJtb250aHMiKQ0KY29sbmFtZXMobXJvY2hlKSA8LSAibXJvY2hlIg0KDQojIDQuMi40LiBCb2dsZSBVLlMuIFBvcnRmb2xpbyAoTW9udGhseSBSZWJhbGFuY2luZykNCm1ib2dsZXcgPC0gYXMubnVtZXJpYyh0KGMoMC40MCwwLjYwLDAuMDAsMC4wMCkpKQ0KbmFtZXMobWJvZ2xldykgPC0gYygibXN0b2NrcyIsIm1pbnRfc3RvY2tzIiwibV9pbmRpYW5fYm9uZHMiLCJtaW50bF9ib25kcyIpDQptYm9nbGUgPC0gUmV0dXJuLnBvcnRmb2xpbyhSPW1wb3J0LHdlaWdodHM9bWJvZ2xldyxnZW9tZXRyaWM9RixyZWJhbGFuY2Vfb249Im1vbnRocyIpDQpjb2xuYW1lcyhtYm9nbGUpIDwtICJtYm9nbGUiDQoNCiMgNC4yLjYuIEJlbmNobWFyayBQb3J0Zm9saW9zIFJldHVybnMgQ29tcGFyaXNvbg0KYmVuY2hjb21wIDwtIGNiaW5kKG1uYWl2ZSxtcm9jaGUsbWJvZ2xlKQ0KdGFibGUuQW5udWFsaXplZFJldHVybnMoYmVuY2hjb21wKQ0KY2hhcnRzLlBlcmZvcm1hbmNlU3VtbWFyeShiZW5jaGNvbXApDQoNCiMgNC4zLiBQb3J0Zm9saW8gT3B0aW1pemF0aW9uIA0KDQojIDQuMy4xLiBNZWFuIE1heGltaXphdGlvbiANCg0KIyBQb3J0Zm9saW8gU3BlY2lmaWNhdGlvbnMNCm1wb3J0MWMgPC0gcG9ydGZvbGlvLnNwZWMoYXNzZXRzID0gY29sbmFtZXMobXBvcnQpKQ0KDQojIFBvcnRmb2xpbyBDb25zdHJhaW50cw0KbXBvcnQxYyA8LSBhZGQuY29uc3RyYWludChtcG9ydDFjLHR5cGU9IndlaWdodF9zdW0iLG1pbl9zdW09MC45OSxtYXhfc3VtPTEuMDEpDQptcG9ydDFjIDwtIGFkZC5jb25zdHJhaW50KG1wb3J0MWMsdHlwZT0ibG9uZ19vbmx5IikNCg0KIyBQb3J0Zm9saW8gT2JqZWN0aXZlcw0KbXBvcnQxYyA8LSBhZGQub2JqZWN0aXZlKG1wb3J0MWMsdHlwZT0icmV0dXJuIixuYW1lPSJtZWFuIikNCg0KIyBQb3J0Zm9saW8gT3B0aW1pemF0aW9uDQptcG9ydG9wdDEgPC0gb3B0aW1pemUucG9ydGZvbGlvKFI9bXBvcnRbIjo6MjAyMS0xMi0zMSJdLHBvcnRmb2xpbz1tcG9ydDFjLG9wdGltaXplX21ldGhvZD0iREVvcHRpbSIsc2VhcmNoX3NpemU9MjAwMDAsdHJhY2U9VCApDQpjaGFydC5XZWlnaHRzKG1wb3J0b3B0MSkNCg0KIyA0LjMuMi4gU3RhbmRhcmQgZGV2aWF0aW9uIG1pbmltaXphdGlvbg0KDQojIFBvcnRmb2xpbyBTcGVjaWZpY2F0aW9ucw0KbXBvcnQyYyA8LSBwb3J0Zm9saW8uc3BlYyhhc3NldHM9Y29sbmFtZXMobXBvcnQpKQ0KDQojIFBvcnRmb2xpbyBDb25zdHJhaW50cw0KbXBvcnQyYyA8LSBhZGQuY29uc3RyYWludChtcG9ydDJjLHR5cGU9IndlaWdodF9zdW0iLG1pbl9zdW09MC45OSxtYXhfc3VtPTEuMDEpDQptcG9ydDJjIDwtIGFkZC5jb25zdHJhaW50KG1wb3J0MmMsdHlwZT0ibG9uZ19vbmx5IikNCg0KIyBQb3J0Zm9saW8gT2JqZWN0aXZlcw0KbXBvcnQyYyA8LSBhZGQub2JqZWN0aXZlKG1wb3J0MmMsdHlwZT0icmlzayIsbmFtZT0iU3RkRGV2IikNCg0KIyBQb3J0Zm9saW8gT3B0aW1pemF0aW9uDQptcG9ydG9wdDIgPC0gb3B0aW1pemUucG9ydGZvbGlvKFI9bXBvcnRbIjo6MjAyMS0xMi0zMSJdLHBvcnRmb2xpbz1tcG9ydDJjLG9wdGltaXplX21ldGhvZD0iREVvcHRpbSIsc2VhcmNoX3NpemU9MjAwMDAsdHJhY2U9VCkNCmNoYXJ0LldlaWdodHMobXBvcnRvcHQyKQ0KDQojIDQuMy4zLiBNZWFuIE1heGltaXphdGlvbiBhbmQgU3RhbmRhcmQgRGV2aWF0aW9uIE1pbmltaXphdGlvbiBQb3J0Zm9saW8NCg0KIyBQb3J0Zm9saW8gU3BlY2lmaWNhdGlvbnMNCm1wb3J0M2MgPC0gcG9ydGZvbGlvLnNwZWMoYXNzZXRzPWNvbG5hbWVzKG1wb3J0KSkNCg0KIyBQb3J0Zm9saW8gQ29uc3RyYWludHMNCm1wb3J0M2MgPC0gYWRkLmNvbnN0cmFpbnQobXBvcnQzYyx0eXBlPSJ3ZWlnaHRfc3VtIixtaW5fc3VtPTAuOTksbWF4X3N1bT0xLjAxKQ0KbXBvcnQzYyA8LSBhZGQuY29uc3RyYWludChtcG9ydDNjLHR5cGU9Imxvbmdfb25seSIpDQoNCiMgUG9ydGZvbGlvIE9iamVjdGl2ZXMNCm1wb3J0M2MgPC0gYWRkLm9iamVjdGl2ZShtcG9ydDNjLHR5cGU9InJldHVybiIsbmFtZT0ibWVhbiIpDQptcG9ydDNjIDwtIGFkZC5vYmplY3RpdmUobXBvcnQzYyx0eXBlPSJyaXNrIixuYW1lPSJTdGREZXYiKQ0KDQojIFBvcnRmb2xpbyBPcHRpbWl6YXRpb24NCm1wb3J0b3B0MyA8LSBvcHRpbWl6ZS5wb3J0Zm9saW8oUj1tcG9ydFsiOjoyMDIxLTEyLTMxIl0scG9ydGZvbGlvPW1wb3J0M2Msb3B0aW1pemVfbWV0aG9kPSJERW9wdGltIixzZWFyY2hfc2l6ZT0yMDAwMCx0cmFjZT1UKQ0KY2hhcnQuV2VpZ2h0cyhtcG9ydG9wdDMpDQpjaGFydC5FZmZpY2llbnRGcm9udGllcihtcG9ydG9wdDMsbWF0Y2guY29sPSJTdGREZXYiKQ0KDQojIDQuMy40LiBNZWFuIE1heGltaXphdGlvbiBWYWx1ZSBhdCBSaXNrIChWYVIpIE1pbmltaXphdGlvbiBQb3J0Zm9saW8NCg0KIyBQb3J0Zm9saW8gU3BlY2lmaWNhdGlvbnMNCm1wb3J0NGMgPC0gcG9ydGZvbGlvLnNwZWMoYXNzZXRzPWNvbG5hbWVzKG1wb3J0KSkNCg0KIyBQb3J0Zm9saW8gQ29uc3RyYWludHMNCm1wb3J0NGMgPC0gYWRkLmNvbnN0cmFpbnQobXBvcnQ0Yyx0eXBlPSJ3ZWlnaHRfc3VtIixtaW5fc3VtPTAuOTksbWF4X3N1bT0xLjAxKQ0KbXBvcnQ0YyA8LSBhZGQuY29uc3RyYWludChtcG9ydDRjLHR5cGU9Imxvbmdfb25seSIpDQoNCiMgUG9ydGZvbGlvIE9iamVjdGl2ZXMNCm1wb3J0NGMgPC0gYWRkLm9iamVjdGl2ZShtcG9ydDRjLHR5cGU9InJldHVybiIsbmFtZT0ibWVhbiIpDQptcG9ydDRjIDwtIGFkZC5vYmplY3RpdmUobXBvcnQ0Yyx0eXBlPSJyaXNrIixuYW1lPSJWYVIiLGFyZ3VtZW50cz1saXN0KHAgPSAwLjk5LG1ldGhvZD0ibW9kaWZpZWQiKSkNCg0KIyBQb3J0Zm9saW8gT3B0aW1pemF0aW9uDQptcG9ydG9wdDQgPC0gb3B0aW1pemUucG9ydGZvbGlvKFI9bXBvcnRbIjo6MjAyMS0xMi0zMSJdLHBvcnRmb2xpbz1tcG9ydDRjLG9wdGltaXplX21ldGhvZD0iREVvcHRpbSIsc2VhcmNoX3NpemU9MjAwMDAsdHJhY2U9VCkNCmNoYXJ0LldlaWdodHMobXBvcnRvcHQ0KQ0KDQojIDQuMy41LiBPcHRpbWl6ZWQgUG9ydGZvbGlvcyBCYWNrdGVzdGluZyBDb21wYXJpc29uDQoNCiNtcG9ydGNvbXAgPC0gY2JpbmQobW5haXZlWyIyMDE1LTAxLTMxOjoiXSxtcG9ydG9wdDEsbXBvcnRvcHQyLG1wb3J0b3B0MyxtcG9ydG9wdDQpDQoNCm1wb3J0Y29tcCA8LSBjYmluZChtcG9ydG9wdDEsbXBvcnRvcHQyLG1wb3J0b3B0MyxtcG9ydDRjKQ0KDQp0YWJsZS5Bbm51YWxpemVkUmV0dXJucyhtcG9ydGNvbXApDQpjaGFydHMuUGVyZm9ybWFuY2VTdW1tYXJ5KG1wb3J0Y29tcCkNCg0KYGBgDQoNCg==