From f52a214762a3c514b44bce58630c701d4ed38bdb Mon Sep 17 00:00:00 2001 From: xinran Date: Fri, 11 Oct 2024 23:49:13 -0700 Subject: [PATCH 1/4] update demo --- demo/demo_cvxrPortfolioAnalytics.R | 125 ++--- demo/demo_robustCovMatForPA.R | 723 +++++++++++++++-------------- 2 files changed, 433 insertions(+), 415 deletions(-) diff --git a/demo/demo_cvxrPortfolioAnalytics.R b/demo/demo_cvxrPortfolioAnalytics.R index d92626bb..b5ddc3da 100644 --- a/demo/demo_cvxrPortfolioAnalytics.R +++ b/demo/demo_cvxrPortfolioAnalytics.R @@ -153,20 +153,20 @@ opt_es_1 <- optimize.portfolio(ret_edhec, pspec_es_1, optimize_method = "CVXR") opt_es_1 -#' 7 MINIMIZING EXPECTED QUADRATIC SHORTFALL +#' 7 MINIMIZING COHERENT SECOND MOMENT -#' Generate min-EQS portfolio -pspec_eqs <- portfolio.spec(assets = fund_edhec) -pspec_eqs <- add.constraint(pspec_eqs, type = "full_investment") -pspec_eqs <- add.constraint(pspec_eqs, type = "long_only") -#' Add objective of minimizing EQS -pspec_eqs <- add.objective(portfolio = pspec_eqs, type = "risk", name = "EQS", +#' Generate min-CSM portfolio +pspec_csm <- portfolio.spec(assets = fund_edhec) +pspec_csm <- add.constraint(pspec_csm, type = "full_investment") +pspec_csm <- add.constraint(pspec_csm, type = "long_only") +#' Add objective of minimizing CSM +pspec_csm <- add.objective(portfolio = pspec_csm, type = "risk", name = "CSM", arguments = list(p=0.05)) -#' GMEQS with default gamma=0.05 -opt_eqs <- optimize.portfolio(ret_edhec, pspec_eqs, optimize_method = "CVXR") -opt_eqs +#' GMCSM with default gamma=0.05 +opt_csm <- optimize.portfolio(ret_edhec, pspec_csm, optimize_method = "CVXR") +opt_csm #' 8 MAXIMIZING MEAN RETURN PER UNIT RISK @@ -198,17 +198,17 @@ pspec_ESratio <- add.objective(pspec_ESratio, type = "risk", name = "ES", optimize.portfolio(ret_edhec, pspec_ESratio, optimize_method = "CVXR", ESratio = TRUE) #' Create portfolio object -pspec_EQSratio <- portfolio.spec(assets = fund_edhec) -#' Add constraints of maximizing return per unit EQS -pspec_EQSratio <- add.constraint(pspec_EQSratio, type = "full_investment") -pspec_EQSratio <- add.constraint(pspec_EQSratio, type = "long_only") -#' Add objectives of maximizing return per unit EQS -pspec_EQSratio <- add.objective(pspec_EQSratio, type = "return", name = "mean") -pspec_EQSratio <- add.objective(pspec_EQSratio, type = "risk", name = "EQS", +pspec_CSMratio <- portfolio.spec(assets = fund_edhec) +#' Add constraints of maximizing return per unit CSM +pspec_CSMratio <- add.constraint(pspec_CSMratio, type = "full_investment") +pspec_CSMratio <- add.constraint(pspec_CSMratio, type = "long_only") +#' Add objectives of maximizing return per unit CSM +pspec_CSMratio <- add.objective(pspec_CSMratio, type = "return", name = "mean") +pspec_CSMratio <- add.objective(pspec_CSMratio, type = "risk", name = "CSM", arguments = list(p=0.05)) #' Optimization -optimize.portfolio(ret_edhec, pspec_EQSratio, optimize_method = "CVXR", EQSratio = TRUE) +optimize.portfolio(ret_edhec, pspec_CSMratio, optimize_method = "CVXR", CSMratio = TRUE) #' 9 COMPARATIVE PERFORMANCE OF PORTFOLIOS @@ -244,16 +244,16 @@ retM_CRSP_5 <- tail(retM_CRSP, 60) #' time series plot of 10 stocks tsPlotMP(retM_CRSP_5[, 1:10]) -#' Test run time for Backtesting with GMV, GMES, GMEQS portfolios +#' Test run time for Backtesting with GMV, GMES, GMCSM portfolios start_time1 <- Sys.time() -#' Generate GMV, GMES and GMEQS portfolios +#' Generate GMV, GMES and GMCSM portfolios pspec_sc <- portfolio.spec(assets = sc30largest) pspec_sc <- add.constraint(pspec_sc, type = "full_investment") pspec_sc <- add.constraint(pspec_sc, type = "long_only") pspec_GMV <- add.objective(pspec_sc, type = "risk", name = "var") pspec_GMES <- add.objective(pspec_sc, type = "risk", name = "ES") -pspec_GMEQS <- add.objective(pspec_sc, type = "risk", name = "EQS") +pspec_GMCSM <- add.objective(pspec_sc, type = "risk", name = "CSM") #' Optimize Portfolio at Monthly Rebalancing and 500-Day Training bt.GMV <- optimize.portfolio.rebalancing(retD_CRSP, pspec_GMV, @@ -266,7 +266,7 @@ bt.ES <- optimize.portfolio.rebalancing(retD_CRSP, pspec_GMES, rebalance_on = "months", training_period = 30, rolling_window = 500) -bt.EQS <- optimize.portfolio.rebalancing(retD_CRSP, pspec_GMEQS, +bt.CSM <- optimize.portfolio.rebalancing(retD_CRSP, pspec_GMCSM, optimize_method = "CVXR", rebalance_on = "months", training_period = 30, @@ -277,34 +277,34 @@ wts.GMV <- extractWeights(bt.GMV) wts.GMV <- wts.GMV[complete.cases(wts.GMV),] wts.ES <- extractWeights(bt.ES) wts.ES <- wts.ES[complete.cases(wts.ES),] -wts.EQS <- extractWeights(bt.EQS) -wts.EQS <- wts.EQS[complete.cases(wts.EQS),] +wts.CSM <- extractWeights(bt.CSM) +wts.CSM <- wts.CSM[complete.cases(wts.CSM),] #' Compute cumulative returns of three portfolios GMV <- Return.rebalancing(retM_CRSP, wts.GMV) ES <- Return.rebalancing(retM_CRSP, wts.ES) -EQS <- Return.rebalancing(retM_CRSP, wts.EQS) +CSM <- Return.rebalancing(retM_CRSP, wts.CSM) -#' Combine GMV, ES and EQS portfolio cumulative returns -ret.comb <- na.omit(merge(GMV, ES, EQS, all=F)) -names(ret.comb) <- c("GMV", "GMES", "GMEQS") +#' Combine GMV, ES and CSM portfolio cumulative returns +ret.comb <- na.omit(merge(GMV, ES, CSM, all=F)) +names(ret.comb) <- c("GMV", "GMES", "GMCSM") backtest.plot(ret.comb, colorSet = c("black", "darkblue", "darkgreen"), ltySet = c(3, 2, 1)) -#' Return run-time for Backtesting with GMV, GMES, GMEQS portfolios +#' Return run-time for Backtesting with GMV, GMES, GMCSM portfolios end_time1 <- Sys.time() runningtime1 <- end_time1 - start_time1 cat("The run time for Figure 9.2 is", format(round(runningtime1, 2))) -#' Test run-time for Backtesting with SR, ESratio, EQSratio portfolios +#' Test run-time for Backtesting with SR, ESratio, CSMratio portfolios start_time2 <- Sys.time() -#' Generate GMV, GMES and GMEQS portfolios +#' Generate GMV, GMES and GMCSM portfolios pspec_sc_ratio <- add.objective(pspec_sc, type = "return", name = "mean") pspec_Sr <- add.objective(pspec_sc_ratio, type = "risk", name = "var") pspec_ESr <- add.objective(pspec_sc_ratio, type = "risk", name = "ES") -pspec_EQSr <- add.objective(pspec_sc_ratio, type = "risk", name = "EQS") +pspec_CSMr <- add.objective(pspec_sc_ratio, type = "risk", name = "CSM") #' Optimize Portfolio at Monthly Rebalancing and 500-Day Training bt.Sr <- optimize.portfolio.rebalancing(retD_CRSP, pspec_Sr, maxSR = TRUE, @@ -317,7 +317,7 @@ bt.ESr <- optimize.portfolio.rebalancing(retD_CRSP, pspec_ESr, rebalance_on = "months", training_period = 30, rolling_window = 500) -bt.EQSr <- optimize.portfolio.rebalancing(retD_CRSP, pspec_EQSr, +bt.CSMr <- optimize.portfolio.rebalancing(retD_CRSP, pspec_CSMr, optimize_method = "CVXR", rebalance_on = "months", training_period = 30, @@ -328,21 +328,21 @@ wts.Sr <- extractWeights(bt.Sr) wts.Sr <- wts.Sr[complete.cases(wts.Sr),] wts.ESr <- extractWeights(bt.ESr) wts.ESr <- wts.ESr[complete.cases(wts.ESr),] -wts.EQSr <- extractWeights(bt.EQSr) -wts.EQSr <- wts.EQSr[complete.cases(wts.EQSr),] +wts.CSMr <- extractWeights(bt.CSMr) +wts.CSMr <- wts.CSMr[complete.cases(wts.CSMr),] #' Compute cumulative returns of three portfolios Sr <- Return.rebalancing(retM_CRSP, wts.Sr, rebalance_on = "months") ESr <- Return.rebalancing(retM_CRSP, wts.ESr, rebalance_on = "months") -EQSr <- Return.rebalancing(retM_CRSP, wts.EQSr, rebalance_on = "months") +CSMr <- Return.rebalancing(retM_CRSP, wts.CSMr, rebalance_on = "months") -#' Combine Sr, ESr and EQSr portfolio cumulative returns -ret.comb <- na.omit(merge(Sr, ESr, EQSr, all=F)) -names(ret.comb) <- c("Sharpe ratio", "ES ratio", "EQS ratio") +#' Combine Sr, ESr and CSMr portfolio cumulative returns +ret.comb <- na.omit(merge(Sr, ESr, CSMr, all=F)) +names(ret.comb) <- c("Sharpe ratio", "ES ratio", "CSM ratio") backtest.plot(ret.comb, colorSet = c("black", "darkblue", "darkgreen"), ltySet = c(3, 2, 1)) -#' Return run-time for Backtesting with SR, ESratio, EQSratio portfolios +#' Return run-time for Backtesting with SR, ESratio, CSMratio portfolios end_time2 <- Sys.time() runningtime2 <- end_time2 - start_time2 cat("The run time for Figure 9.3 is", format(round(runningtime2, 2))) @@ -444,29 +444,46 @@ chart.EfficientFrontierOverlay(R = retM_CRSP_5, portfolio_list = portf_ES_list, main = "Overlay Mean-ES Efficient Frontiers", xlim = c(0.035, 0.165), ylim = c(0.005, 0.03)) -#' Mean-EQS Efficient Frontier -meaneqs.ef <- create.EfficientFrontier(R = retM_CRSP_5, portfolio = pspec_sc, - type = "mean-EQS") -chart.EfficientFrontier(meaneqs.ef, match.col = "EQS", type = "l", - chart.assets = FALSE, main = "Mean-EQS Efficient Frontier", - RAR.text = "EQS ratio", pch = 1) +#' Mean-CSM Efficient Frontier +meancsm.ef <- create.EfficientFrontier(R = retM_CRSP_5, portfolio = pspec_sc, + type = "mean-CSM") +chart.EfficientFrontier(meancsm.ef, match.col = "CSM", type = "l", + chart.assets = FALSE, main = "Mean-CSM Efficient Frontier", + RAR.text = "CSM ratio", pch = 1) -#' usage example: minStd Portfolio +#' minStd Portfolio minstd_port <- add.objective(pspec_sc, type = "risk", name = "StdDev") -minstd_w <- optimize.portfolio(retM_CRSP_5, minstd_port, optimize_method = "CVXR")$weight +minstd_opt <- optimize.portfolio(retM_CRSP_5, minstd_port, optimize_method = "CVXR") +minstd_w <- minstd_opt$weight -#' risk values with default alpha = 0.05 +#' extract risk example 1: risk values with default alpha = 0.05 extract_risk(retM_CRSP_5, minstd_w) -#' risk values with specific alpha -extract_risk(retM_CRSP_5, minstd_w, ES_alpha = 0.1, EQS_alpha = 0.1) +#' extract risk example 2: risk values with specific alpha +extract_risk(retM_CRSP_5, minstd_w, ES_alpha = 0.1, CSM_alpha = 0.1) -#' example 1: Compare StdDev of minStd and minES portfolios with guideline +#' extract risk example 3: risk values with customized momentFUN +minstd_opt_custM <- optimize.portfolio(retM_CRSP_5, minstd_port, optimize_method = "CVXR", + momentFUN = 'custom.covRob.Mcd') +extract_risk(retM_CRSP_5, minstd_w, moment_setting = minstd_opt_custM$moment_values) + +#' EFCompare example 1: Compare StdDev of minStd and minES portfolios with guideline chart.EfficientFrontierCompare(R = retM_CRSP_5, portfolio = pspec_sc, risk_type = "StdDev", match.col = c("StdDev", "ES"), lwd = c(2, 2)) -#' example 2: Compare ES of minStd, minES and minEQS portfolios without guideline +#' EFCompare example 2: Compare ES of minStd, minES and minCSM portfolios without guideline chart.EfficientFrontierCompare(R = retM_CRSP_5, portfolio = pspec_sc, risk_type = "ES", - match.col = c("StdDev", "ES", "EQS"), guideline = FALSE, + match.col = c("StdDev", "ES", "CSM"), guideline = FALSE, col = c(1,2,4), lty = c(1, 2, 4), lwd = c(2, 2, 2)) +#' plotFrontiers example 1: Compare mean-CSM frontiers for minvar, minES, minCSM portfolio +ef1 = meancsm.efficient.frontier(pspec_sc, retM_CRSP_5, optimize_method = 'CVXR') +ef2 = meanetl.efficient.frontier(pspec_sc, retM_CRSP_5, optimize_method = 'CVXR') +ef3 = meanvar.efficient.frontier(pspec_sc, retM_CRSP_5, optimize_method = 'CVXR') +plotFrontiers(R=retM_CRSP_5, frontiers=list(ef1, ef2, ef3), risk='CSM') + +#' plotFrontiers example 2: Compare mean-var frontiers with different moment settings +ef4 = meanvar.efficient.frontier(pspec_sc, retM_CRSP_5, optimize_method = 'CVXR') +ef5 = meanvar.efficient.frontier(pspec_sc, retM_CRSP_5, optimize_method = 'CVXR', + momentFUN = 'custom.covRob.TSGS') +plotFrontiers(R=retM_CRSP_5, frontiers=list(ef4, ef5), risk='StdDev') \ No newline at end of file diff --git a/demo/demo_robustCovMatForPA.R b/demo/demo_robustCovMatForPA.R index 70ee7747..31f53f3a 100644 --- a/demo/demo_robustCovMatForPA.R +++ b/demo/demo_robustCovMatForPA.R @@ -1,361 +1,362 @@ -## ----setup, include=FALSE------------------------------- -knitr::opts_chunk$set(echo = TRUE, fig.width = 6, fig.height = 4, fig.align = "center") - - -## ---- warning = FALSE, message = FALSE------------------ -library(PCRA) -library(PortfolioAnalytics) -library(CVXR) -library(xts) - - -## ------------------------------------------------------- -stocksCRSPweekly <- getPCRAData("stocksCRSPweekly") -dateRange <- c("2006-01-01", "2012-12-31") -stockItems <- c("Date", "TickerLast", "CapGroupLast", "Return", "MktIndexCRSP") -returnsAll <- selectCRSPandSPGMI("weekly", - dateRange = dateRange, - stockItems = stockItems, - factorItems = NULL, - subsetType = "CapGroupLast", - subsetValues = "SmallCap", - outputType = "xts") -returns <- returnsAll[,1:30] -MARKET <- returnsAll[, 107] -returns10 <- returnsAll[140:300, 21:30] -range(index(returns)) -range(index(returns10)) - - -## ------------------------------------------------------- -tsPlotMP(MARKET) - - -## ------------------------------------------------------- -tsPlotMP(returns[, 21:30]) - - -## ------------------------------------------------------- -tsPlotMP(returns10) - - -## ------------------------------------------------------- -funds <- colnames(returns10) -pspec <- portfolio.spec(funds) -pspec <- add.constraint(pspec, type="full_investment") -pspec <- add.constraint(pspec, type="long_only") -pspec <- add.objective(pspec, type="risk", name="var") - - -## ------------------------------------------------------- -opt <- optimize.portfolio(returns10, pspec, optimize_method = "CVXR") - - -## ------------------------------------------------------- -opt - - -## ------------------------------------------------------- -outCovClassic <- opt.outputMvo(opt, returns10, digits = 3, frequency = "weekly") -(WtsCovClassic <- outCovClassic$Wgts) - - -## ---- eval = FALSE-------------------------------------- -## custom.covRob.MM <- function(R, ...){ -## out <- list() -## if(hasArg(tol)) tol = match.call(expand.dots = TRUE)$tol else tol = 1e-4 -## if(hasArg(maxit)) maxit = match.call(expand.dots = TRUE)$maxit else maxit = 50 -## robustCov <- RobStatTM::covRobMM(X=R, tol=tol, maxit=maxit) -## out$sigma <- robustCov$cov -## out$mu <- robustCov$center -## return(out) -## } - - -## ------------------------------------------------------- -opt <- optimize.portfolio(returns10, pspec, - optimize_method = "CVXR", - momentFUN = "custom.covRob.MM", - maxit = 100, tol = 1e-5) -outCovRobMM <- opt.outputMvo(opt, returns10, digits = 3, frequency = "weekly") -(WtsCovRobMM <- outCovRobMM$Wgts) - - -## ---- eval = FALSE-------------------------------------- -## custom.covRob.Rocke <- function(R, ...){ -## out <- list() -## if(hasArg(tol)) tol = match.call(expand.dots = TRUE)$tol else tol = 1e-4 -## if(hasArg(maxit)) maxit = match.call(expand.dots = TRUE)$maxit else maxit = 50 -## if(hasArg(initial)) initial = match.call(expand.dots = TRUE)$initial else initial = 'K' -## if(hasArg(maxsteps)) maxsteps = match.call(expand.dots = TRUE)$maxsteps else maxsteps = 5 -## if(hasArg(propmin)) propmin = match.call(expand.dots = TRUE)$propmin else propmin = 2 -## if(hasArg(qs)) qs = match.call(expand.dots = TRUE)$qs else qs = 50 -## -## robustCov <- RobStatTM::covRobRocke(X = R, initial = initial, maxsteps = maxsteps, propmin = propmin, -## qs = qs, tol = tol, maxit = maxit) -## -## out$sigma <- robustCov$cov -## out$mu <- robustCov$center -## return(out) -## } - - -## ------------------------------------------------------- -opt <- optimize.portfolio(returns10, pspec, - optimize_method = "CVXR", - momentFUN = "custom.covRob.Rocke", - tol = 1e-5, maxit =100, maxsteps = 7) -outCovRobRocke <- opt.outputMvo(opt, returns10, digits = 3, frequency = "weekly") -(WtsCovRobRocke <- outCovRobRocke$Wgts) - - -## ---- eval = FALSE-------------------------------------- -## custom.covRob.Mcd <- function(R, ...){ -## -## if(hasArg(control)) control = match.call(expand.dots = TRUE)$control else control = MycovRobMcd() -## if(hasArg(alpha)) alpha = match.call(expand.dots = TRUE)$alpha else alpha = control$alpha -## if(hasArg(nsamp)) nsamp = match.call(expand.dots = TRUE)$nsamp else nsamp = control$nsamp -## if(hasArg(nmini)) nmini = match.call(expand.dots = TRUE)$nmini else nmini = control$nmini -## if(hasArg(kmini)) kmini = match.call(expand.dots = TRUE)$kmini else kmini = control$kmini -## if(hasArg(scalefn)) scalefn = match.call(expand.dots = TRUE)$scalefn else scalefn = control$scalefn -## if(hasArg(maxcsteps)) maxcsteps = match.call(expand.dots = TRUE)$maxcsteps -## else maxcsteps = control$maxcsteps -## -## if(hasArg(initHsets)) initHsets = match.call(expand.dots = TRUE)$initHsets -## else initHsets = control$initHsets -## -## if(hasArg(seed)) seed = match.call(expand.dots = TRUE)$seed else seed = control$seed -## if(hasArg(tolSolve)) tolSolve = match.call(expand.dots = TRUE)$tolSolve else tolSolve = control$tolSolve -## if(hasArg(wgtFUN)) wgtFUN = match.call(expand.dots = TRUE)$wgtFUN else wgtFUN = control$wgtFUN -## -## if(hasArg(use.correction)) use.correction = match.call(expand.dots = TRUE)$use.correction -## else use.correction = control$use.correction -## -## robustMCD <- robustbase::covMcd(x = R, alpha = alpha, -## nsamp = nsamp, nmini = nmini, -## kmini = kmini, seed = seed, -## tolSolve = tolSolve, scalefn = scalefn, -## maxcsteps = maxcsteps, -## initHsets = initHsets, -## wgtFUN = wgtFUN, use.correction = use.correction) -## -## return(list(mu = robustMCD$center, sigma = robustMCD$cov)) -## } - - -## ------------------------------------------------------- -opt <- optimize.portfolio(returns10, pspec, - optimize_method = "CVXR", - momentFUN = "custom.covRob.Mcd", - alpha = 0.75, nsamp = 600) -outCovRobMcd <- opt.outputMvo(opt, returns10, digits = 3, frequency = "weekly") -(WtsCovRobMcd <- outCovRobMcd$Wgts) - - -## ---- eval = FALSE-------------------------------------- -## MycovRobMcd <- function(alpha = 1/2, -## nsamp = 500, nmini = 300, kmini = 5, -## scalefn = "hrv2012", maxcsteps = 200, -## seed = NULL, tolSolve = 1e-14, -## wgtFUN = "01.original", beta, -## use.correction = TRUE -## ){ -## if(missing(beta) || !is.numeric(beta)) -## beta <- 0.975 -## -## return(list(alpha = alpha, nsamp = nsamp, -## nmini = as.integer(nmini), kmini = as.integer(kmini), -## seed = as.integer(seed), -## tolSolve = tolSolve, scalefn = scalefn, -## maxcsteps = as.integer(maxcsteps), -## wgtFUN = wgtFUN, beta = beta, -## use.correction = use.correction)) -## } - - -## ---- eval = FALSE-------------------------------------- -## covMcd.params <- MycovRobMcd(alpha = 0.75, nsamp = 600) -## opt <- optimize.portfolio(returns, pspec, -## optimize_method = "CVXR", -## momentFUN = "custom.covRob.Mcd", -## control = covMcd.params) - - -## ---- eval = FALSE-------------------------------------- -## custom.covRob.TSGS <- function(R, ...){ -## if(hasArg(control)) control = match.call(expand.dots = TRUE)$control else control = MycovRobTSGS() -## if(hasArg(filter)) filter = match.call(expand.dots = TRUE)$filter else filter = control$filter -## -## if(hasArg(partial.impute)) partial.impute = match.call(expand.dots = TRUE)$partial.impute -## else partial.impute = control$partial.impute -## -## if(hasArg(tol)) tol = match.call(expand.dots=TRUE)$tol else tol=control$tol -## if(hasArg(maxiter)) maxiter = match.call(expand.dots = TRUE)$maxiter else maxiter = control$maxiter -## if(hasArg(loss)) loss = match.call(expand.dots = TRUE)$loss else loss = control$loss -## if(hasArg(init)) init = match.call(expand.dots = TRUE)$init else init = control$init -## -## tsgsRob <- GSE::TSGS(x = R, filter = filter, -## partial.impute = partial.impute, tol = tol, -## maxiter = maxiter, method = loss, -## init = init) -## -## return(list(mu = tsgsRob@mu, sigma = tsgsRob@S)) -## -## } - - -## ------------------------------------------------------- -opt <- optimize.portfolio(returns10, pspec, - optimize_method = "CVXR", - momentFUN = "custom.covRob.TSGS") -outCovRobTSGS <- opt.outputMvo(opt, returns10, digits = 3, frequency = "weekly") -(WtsCovRobTSGS <- outCovRobTSGS$Wgts) - - -## ---- eval = F------------------------------------------ -## MycovRobTSGS <- function(filter = c("UBF-DDC","UBF","DDC","UF"), -## partial.impute = FALSE, tol = 1e-4, maxiter = 150, -## loss = c("bisquare","rocke"), -## init = c("emve", "qc", "huber", "imputed", "emve_c")){ -## -## filter <- match.arg(filter) -## loss <- match.arg(loss) -## init <- match.arg(init) -## -## return(list(filter = filter, partial.impute = partial.impute, -## tol = tol, maxiter = as.integer(maxiter), -## loss = loss,init)) -## } - - -## ------------------------------------------------------- -dat <- data.frame(rbind(WtsCovClassic, WtsCovRobMM, WtsCovRobRocke, - WtsCovRobMcd, WtsCovRobTSGS)) -print.data.frame(dat) - - -## ------------------------------------------------------- -dat.mat <- rbind(outCovClassic[2:4], outCovRobMM[2:4], outCovRobRocke[2:4], - outCovRobMcd[2:4], outCovRobTSGS[2:4]) -dat <- as.data.frame(dat.mat) -row.names(dat) <- c("GmvLOcovClassic", "GmvLOcovRobMM", "GmvLOcovRobRocke", - "GmvLOcovRobMcd", "GmvLOcovRobTSGS") -print.data.frame(dat) - - -## ------------------------------------------------------- -# Plot function -robPlot <- function(GMV, MARKET, plot=1){ - # Optimize Portfolio at Monthly Rebalancing and 5-Year Training - if(plot == 1){ - momentEstFun = 'custom.covRob.Rocke' - name = "GmvLOCovRobRocke" - }else if(plot == 2){ - momentEstFun = 'custom.covRob.Mcd' - name = "GmvLOCovMcd" - }else if(plot == 3){ - momentEstFun = 'custom.covRob.TSGS' - name = "GmvLOTSGS" - }else{ - print("plot should be 1, 2 or 3") - return() - } - - bt.gmv.rob <- optimize.portfolio.rebalancing(returns, pspec, - optimize_method = "CVXR", - rebalance_on = "weeks", - training_period = 100, - momentFUN = momentEstFun) - - # Extract time series of portfolio weights - wts.gmv.rob <- extractWeights(bt.gmv.rob) - # Compute cumulative returns of portfolio - GMV.rob <- Return.rebalancing(returns, wts.gmv.rob) - - # Combine GMV.LO and MARKET cumulative returns - ret.comb <- na.omit(merge(GMV.rob, GMV, MARKET, all=F)) - names(ret.comb) <- c(name, "GmvLO", "MARKET") - - plot <- backtest.plot(ret.comb, colorSet = c("darkgreen", "black", - "red"), ltySet = c(1,2,3)) - - return(list(ret = ret.comb, plot = plot)) -} - - - -## ------------------------------------------------------- -bt.gmv <- optimize.portfolio.rebalancing(returns, pspec, - optimize_method = "CVXR", - rebalance_on="weeks", - training_period = 100) -# Extract time series of portfolio weights -wts.gmv <- extractWeights(bt.gmv) -# Compute cumulative returns of portfolio -GMV <- Return.rebalancing(returns, wts.gmv) - -res.covRob <- robPlot(GMV=GMV, MARKET=MARKET, plot=1) -res.covRob$plot - - -## ------------------------------------------------------- -table.Drawdowns(res.covRob$ret$GmvLOCovRobRocke, top=1) - - -## ------------------------------------------------------- -table.Drawdowns(res.covRob$ret$GmvLO, top=1) - - -## ------------------------------------------------------- -table.Drawdowns(res.covRob$ret$MARKET, top=1) - - -## ------------------------------------------------------- -set.seed(1234) -res.covMcd = robPlot(GMV=GMV, MARKET=MARKET, plot=2) -res.covMcd$plot - - -## ------------------------------------------------------- -# longest drawdown for robust based portfolio -table.Drawdowns(res.covMcd$ret$GmvLOCovMcd, top=1) - - -## ------------------------------------------------------- -res.TSGS = robPlot(GMV=GMV, MARKET=MARKET, plot=3) -res.TSGS$plot - - -## ------------------------------------------------------- -# longest drawdown for robust based portfolio -table.Drawdowns(res.TSGS$ret$GmvLOTSGS, top=1) - - -## ---- eval = FALSE-------------------------------------- -## user.covRob.Rocke <- function(R){ -## out <- list() -## robustCov <- RobStatTM::covRobRocke(X = R, maxit = 200, maxsteps = 10) -## out$sigma <- robustCov$cov -## out$mu <- robustCov$center -## return(out) -## } - - -## ---- eval = FALSE-------------------------------------- -## opt <- optimize.portfolio(returns, pspec, -## optimize_method = "CVXR", -## momentFUN = "user.covRob.Rocke") - - -## ---- eval = FALSE-------------------------------------- -## user.covRob.OGK <- function(R){ -## robustCov <- robustbase::covOGK(x = R) -## return(list(mu = robustCov$center, sigma = robustCov$cov)) -## } - - -## ---- eval = FALSE-------------------------------------- -## opt <- optimize.portfolio(returns, pspec, -## optimize_method = "CVXR", -## momentFUN = "user.covMcd.OGK") - +## ----setup, include=FALSE------------------------------- +knitr::opts_chunk$set(echo = TRUE, fig.width = 6, fig.height = 4, fig.align = "center") + + +## ---- warning = FALSE, message = FALSE------------------ +library(PCRA) +library(PortfolioAnalytics) +library(CVXR) +library(xts) + + +## ------------------------------------------------------- +stocksCRSPweekly <- getPCRAData("stocksCRSPweekly") +dateRange <- c("2006-01-01", "2012-12-31") +stockItems <- c("Date", "TickerLast", "CapGroupLast", "Return", "MktIndexCRSP") +returnsAll <- selectCRSPandSPGMI("weekly", + dateRange = dateRange, + stockItems = stockItems, + factorItems = NULL, + subsetType = "CapGroupLast", + subsetValues = "SmallCap", + outputType = "xts") +returns <- returnsAll[,1:30] +MARKET <- returnsAll[, 107] +returns10 <- returnsAll[140:300, 21:30] +range(index(returns)) +range(index(returns10)) + + +## ------------------------------------------------------- +tsPlotMP(MARKET) + + +## ------------------------------------------------------- +tsPlotMP(returns[, 21:30]) + + +## ------------------------------------------------------- +tsPlotMP(returns10) + + +## ------------------------------------------------------- +funds <- colnames(returns10) +pspec <- portfolio.spec(funds) +pspec <- add.constraint(pspec, type="full_investment") +pspec <- add.constraint(pspec, type="long_only") +pspec <- add.objective(pspec, type="risk", name="var") + + +## ------------------------------------------------------- +opt <- optimize.portfolio(returns10, pspec, optimize_method = "CVXR") + + +## ------------------------------------------------------- +opt + + +## ------------------------------------------------------- +outCovClassic <- opt.outputMvo(opt, returns10, digits = 3, frequency = "weekly") +(WtsCovClassic <- outCovClassic$Wgts) + + +## ---- eval = FALSE-------------------------------------- +## custom.covRob.MM <- function(R, ...){ +## out <- list() +## if(hasArg(tol)) tol = match.call(expand.dots = TRUE)$tol else tol = 1e-4 +## if(hasArg(maxit)) maxit = match.call(expand.dots = TRUE)$maxit else maxit = 50 +## robustCov <- RobStatTM::covRobMM(X=R, tol=tol, maxit=maxit) +## out$sigma <- robustCov$cov +## out$mu <- robustCov$center +## return(out) +## } + + +## ------------------------------------------------------- +opt <- optimize.portfolio(returns10, pspec, + optimize_method = "CVXR", + momentFUN = "custom.covRob.MM", + maxit = 100, tol = 1e-5) +outCovRobMM <- opt.outputMvo(opt, returns10, digits = 3, frequency = "weekly") +(WtsCovRobMM <- outCovRobMM$Wgts) + + +## ---- eval = FALSE-------------------------------------- +## custom.covRob.Rocke <- function(R, ...){ +## out <- list() +## if(hasArg(tol)) tol = match.call(expand.dots = TRUE)$tol else tol = 1e-4 +## if(hasArg(maxit)) maxit = match.call(expand.dots = TRUE)$maxit else maxit = 50 +## if(hasArg(initial)) initial = match.call(expand.dots = TRUE)$initial else initial = 'K' +## if(hasArg(maxsteps)) maxsteps = match.call(expand.dots = TRUE)$maxsteps else maxsteps = 5 +## if(hasArg(propmin)) propmin = match.call(expand.dots = TRUE)$propmin else propmin = 2 +## if(hasArg(qs)) qs = match.call(expand.dots = TRUE)$qs else qs = 50 +## +## robustCov <- RobStatTM::covRobRocke(X = R, initial = initial, maxsteps = maxsteps, propmin = propmin, +## qs = qs, tol = tol, maxit = maxit) +## +## out$sigma <- robustCov$cov +## out$mu <- robustCov$center +## return(out) +## } + + +## ------------------------------------------------------- +opt <- optimize.portfolio(returns10, pspec, + optimize_method = "CVXR", + momentFUN = "custom.covRob.Rocke", + tol = 1e-5, maxit =100, maxsteps = 7) +outCovRobRocke <- opt.outputMvo(opt, returns10, digits = 3, frequency = "weekly") +(WtsCovRobRocke <- outCovRobRocke$Wgts) + + +## ---- eval = FALSE-------------------------------------- +## custom.covRob.Mcd <- function(R, ...){ +## +## if(hasArg(control)) control = match.call(expand.dots = TRUE)$control else control = MycovRobMcd() +## if(hasArg(alpha)) alpha = match.call(expand.dots = TRUE)$alpha else alpha = control$alpha +## if(hasArg(nsamp)) nsamp = match.call(expand.dots = TRUE)$nsamp else nsamp = control$nsamp +## if(hasArg(nmini)) nmini = match.call(expand.dots = TRUE)$nmini else nmini = control$nmini +## if(hasArg(kmini)) kmini = match.call(expand.dots = TRUE)$kmini else kmini = control$kmini +## if(hasArg(scalefn)) scalefn = match.call(expand.dots = TRUE)$scalefn else scalefn = control$scalefn +## if(hasArg(maxcsteps)) maxcsteps = match.call(expand.dots = TRUE)$maxcsteps +## else maxcsteps = control$maxcsteps +## +## if(hasArg(initHsets)) initHsets = match.call(expand.dots = TRUE)$initHsets +## else initHsets = control$initHsets +## +## if(hasArg(seed)) seed = match.call(expand.dots = TRUE)$seed else seed = control$seed +## if(hasArg(tolSolve)) tolSolve = match.call(expand.dots = TRUE)$tolSolve else tolSolve = control$tolSolve +## if(hasArg(wgtFUN)) wgtFUN = match.call(expand.dots = TRUE)$wgtFUN else wgtFUN = control$wgtFUN +## +## if(hasArg(use.correction)) use.correction = match.call(expand.dots = TRUE)$use.correction +## else use.correction = control$use.correction +## +## robustMCD <- robustbase::covMcd(x = R, alpha = alpha, +## nsamp = nsamp, nmini = nmini, +## kmini = kmini, seed = seed, +## tolSolve = tolSolve, scalefn = scalefn, +## maxcsteps = maxcsteps, +## initHsets = initHsets, +## wgtFUN = wgtFUN, use.correction = use.correction) +## +## return(list(mu = robustMCD$center, sigma = robustMCD$cov)) +## } + + +## ------------------------------------------------------- +opt <- optimize.portfolio(returns10, pspec, + optimize_method = "CVXR", + momentFUN = "custom.covRob.Mcd", + alpha = 0.75, nsamp = 600) +outCovRobMcd <- opt.outputMvo(opt, returns10, digits = 3, frequency = "weekly") +(WtsCovRobMcd <- outCovRobMcd$Wgts) + + +## ---- eval = FALSE-------------------------------------- +## MycovRobMcd <- function(alpha = 1/2, +## nsamp = 500, nmini = 300, kmini = 5, +## scalefn = "hrv2012", maxcsteps = 200, +## seed = NULL, tolSolve = 1e-14, +## wgtFUN = "01.original", beta, +## use.correction = TRUE +## ){ +## if(missing(beta) || !is.numeric(beta)) +## beta <- 0.975 +## +## return(list(alpha = alpha, nsamp = nsamp, +## nmini = as.integer(nmini), kmini = as.integer(kmini), +## seed = as.integer(seed), +## tolSolve = tolSolve, scalefn = scalefn, +## maxcsteps = as.integer(maxcsteps), +## wgtFUN = wgtFUN, beta = beta, +## use.correction = use.correction)) +## } + + +## ---- eval = FALSE-------------------------------------- +## covMcd.params <- MycovRobMcd(alpha = 0.75, nsamp = 600) +## opt <- optimize.portfolio(returns, pspec, +## optimize_method = "CVXR", +## momentFUN = "custom.covRob.Mcd", +## control = covMcd.params) + + +## ---- eval = FALSE-------------------------------------- +## custom.covRob.TSGS <- function(R, ...){ +## if(hasArg(control)) control = match.call(expand.dots = TRUE)$control else control = MycovRobTSGS() +## if(hasArg(filter)) filter = match.call(expand.dots = TRUE)$filter else filter = control$filter +## +## if(hasArg(partial.impute)) partial.impute = match.call(expand.dots = TRUE)$partial.impute +## else partial.impute = control$partial.impute +## +## if(hasArg(tol)) tol = match.call(expand.dots=TRUE)$tol else tol=control$tol +## if(hasArg(maxiter)) maxiter = match.call(expand.dots = TRUE)$maxiter else maxiter = control$maxiter +## if(hasArg(loss)) loss = match.call(expand.dots = TRUE)$loss else loss = control$loss +## if(hasArg(init)) init = match.call(expand.dots = TRUE)$init else init = control$init +## +## tsgsRob <- GSE::TSGS(x = R, filter = filter, +## partial.impute = partial.impute, tol = tol, +## maxiter = maxiter, method = loss, +## init = init) +## +## return(list(mu = tsgsRob@mu, sigma = tsgsRob@S)) +## +## } + + +## ------------------------------------------------------- +opt <- optimize.portfolio(returns10, pspec, + optimize_method = "CVXR", + momentFUN = "custom.covRob.TSGS") +outCovRobTSGS <- opt.outputMvo(opt, returns10, digits = 3, frequency = "weekly") +(WtsCovRobTSGS <- outCovRobTSGS$Wgts) + + +## ---- eval = F------------------------------------------ +## MycovRobTSGS <- function(filter = c("UBF-DDC","UBF","DDC","UF"), +## partial.impute = FALSE, tol = 1e-4, maxiter = 150, +## loss = c("bisquare","rocke"), +## init = c("emve", "qc", "huber", "imputed", "emve_c")){ +## +## filter <- match.arg(filter) +## loss <- match.arg(loss) +## init <- match.arg(init) +## +## return(list(filter = filter, partial.impute = partial.impute, +## tol = tol, maxiter = as.integer(maxiter), +## loss = loss,init)) +## } + + +## ------------------------------------------------------- +dat <- data.frame(rbind(WtsCovClassic, WtsCovRobMM, WtsCovRobRocke, + WtsCovRobMcd, WtsCovRobTSGS)) +print.data.frame(dat) + + +## ------------------------------------------------------- +dat.mat <- rbind(outCovClassic[2:4], outCovRobMM[2:4], outCovRobRocke[2:4], + outCovRobMcd[2:4], outCovRobTSGS[2:4]) +dat <- as.data.frame(dat.mat) +row.names(dat) <- c("GmvLOcovClassic", "GmvLOcovRobMM", "GmvLOcovRobRocke", + "GmvLOcovRobMcd", "GmvLOcovRobTSGS") +print.data.frame(dat) + + +## ------------------------------------------------------- +# Plot function +robPlot <- function(GMV, MARKET, plot=1){ + # Optimize Portfolio at Monthly Rebalancing and 5-Year Training + if(plot == 1){ + momentEstFun = 'custom.covRob.Rocke' + name = "GmvLOCovRobRocke" + }else if(plot == 2){ + momentEstFun = 'custom.covRob.Mcd' + name = "GmvLOCovMcd" + }else if(plot == 3){ + momentEstFun = 'custom.covRob.TSGS' + name = "GmvLOTSGS" + }else{ + print("plot should be 1, 2 or 3") + return() + } + + bt.gmv.rob <- optimize.portfolio.rebalancing(returns, pspec, + optimize_method = "CVXR", + rebalance_on = "weeks", + training_period = 100, + momentFUN = momentEstFun) + + # Extract time series of portfolio weights + wts.gmv.rob <- extractWeights(bt.gmv.rob) + # Compute cumulative returns of portfolio + GMV.rob <- Return.rebalancing(returns, wts.gmv.rob) + + # Combine GMV.LO and MARKET cumulative returns + ret.comb <- na.omit(merge(GMV.rob, GMV, MARKET, all=F)) + names(ret.comb) <- c(name, "GmvLO", "MARKET") + + plot <- backtest.plot(ret.comb, colorSet = c("darkgreen", "black", + "red"), ltySet = c(1,2,3)) + + return(list(ret = ret.comb, plot = plot)) +} + + + +## ------------------------------------------------------- +bt.gmv <- optimize.portfolio.rebalancing(returns, pspec, + optimize_method = "CVXR", + rebalance_on="weeks", + training_period = 100) +# Extract time series of portfolio weights +wts.gmv <- extractWeights(bt.gmv) +# Compute cumulative returns of portfolio +GMV <- Return.rebalancing(returns, wts.gmv) + +res.covRob <- robPlot(GMV=GMV, MARKET=MARKET, plot=1) +res.covRob$plot + + +## ------------------------------------------------------- +table.Drawdowns(res.covRob$ret$GmvLOCovRobRocke, top=1) + + +## ------------------------------------------------------- +table.Drawdowns(res.covRob$ret$GmvLO, top=1) + + +## ------------------------------------------------------- +table.Drawdowns(res.covRob$ret$MARKET, top=1) + + +## ------------------------------------------------------- +set.seed(1234) +res.covMcd = robPlot(GMV=GMV, MARKET=MARKET, plot=2) +res.covMcd$plot + + +## ------------------------------------------------------- +# longest drawdown for robust based portfolio +table.Drawdowns(res.covMcd$ret$GmvLOCovMcd, top=1) + + +## ------------------------------------------------------- +res.TSGS = robPlot(GMV=GMV, MARKET=MARKET, plot=3) +res.TSGS$plot + + +## ------------------------------------------------------- +# longest drawdown for robust based portfolio +table.Drawdowns(res.TSGS$ret$GmvLOTSGS, top=1) + + +## ---- eval = FALSE-------------------------------------- +## user.covRob.Rocke <- function(R){ +## out <- list() +## robustCov <- RobStatTM::covRobRocke(X = R, maxit = 200, maxsteps = 10) +## out$sigma <- robustCov$cov +## out$mu <- robustCov$center +## return(out) +## } + + +## ---- eval = FALSE-------------------------------------- +## opt <- optimize.portfolio(returns, pspec, +## optimize_method = "CVXR", +## momentFUN = "user.covRob.Rocke") + + +## ---- eval = FALSE-------------------------------------- +## user.covRob.OGK <- function(R){ +## robustCov <- robustbase::covOGK(x = R) +## return(list(mu = robustCov$center, sigma = robustCov$cov)) +## } + + +## ---- eval = FALSE-------------------------------------- +## opt <- optimize.portfolio(returns, pspec, +## optimize_method = "CVXR", +## momentFUN = "user.covMcd.OGK") + +## opt$moment_values From 4e4f0751ecec6f3e100c59190509299da90ae991 Mon Sep 17 00:00:00 2001 From: xinran Date: Fri, 11 Oct 2024 23:52:08 -0700 Subject: [PATCH 2/4] small change to fix R CMD Check Warn and Note --- DESCRIPTION | 2 +- ..._JPM2024MinDdownsideRisk.R => demo_JPM2024MinDownsideRisk.R} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename demo/{demo_JPM2024MinDdownsideRisk.R => demo_JPM2024MinDownsideRisk.R} (100%) diff --git a/DESCRIPTION b/DESCRIPTION index 8f4c696a..4ea09887 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -16,7 +16,7 @@ Authors@R: c( person(given="Xiaokang",family="Feng",role="ctb") , person(given="Yifu",family="Kang",role="ctb") ) Version: 3.0.0 -Date: 2024-08-20 +Date: 2024-10-11 Maintainer: Brian G. Peterson Description: Portfolio optimization and analysis routines and graphics. Depends: diff --git a/demo/demo_JPM2024MinDdownsideRisk.R b/demo/demo_JPM2024MinDownsideRisk.R similarity index 100% rename from demo/demo_JPM2024MinDdownsideRisk.R rename to demo/demo_JPM2024MinDownsideRisk.R From 6abd6a21eb85e454d3da65a3669c96e4b7a4aea5 Mon Sep 17 00:00:00 2001 From: xinran Date: Sun, 13 Oct 2024 18:52:52 -0700 Subject: [PATCH 3/4] update README to md --- README | 92 ----------------------------------------------- README.md | 105 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 105 insertions(+), 92 deletions(-) delete mode 100644 README create mode 100644 README.md diff --git a/README b/README deleted file mode 100644 index b664c47c..00000000 --- a/README +++ /dev/null @@ -1,92 +0,0 @@ -This V2.1 version of PortfolioAnalytics is an update to the substantial V2.0 -version that was released on 2024-07-03. We first describe the V2.0 features, -then discuss the R demo capability, and finally we describe the additional -V2.1 features. - -# 2.0 Features - -A major feature of 2.0 is the integration of the CVXR solver R package -for convex optimization. CVXR supports eleven solver packages, each of -which supports solvers for one or more of the following optimization -problems: LP, QP, SOCP, SDP, EXP, MIP. See the Table near the beginning -of the document "Convex Optimization in R" at https://cvxr.rbind.io/. -Thus, with PortfolioAnalytics 2.0, users are able to use any one of a -variety of solvers available in CVXR for their portfolio optimization -problems. - -A particular use of CVXR in PortfolioAnalytics 2.0 is for computing Minimum -Coherent Second Moment (MinCSM) portfolios, which are second-order cone -programming (SOCP) optimization problems. This is quite a new capability -that is not available in other portfolio optimization software products. -Details are provided in the Vignette "cvxrPortfolioAnalytics". - -Another important feature of PortfolioAnalytics 2.0, is that it contains -functionality for computing outliers-robust minimum variance (MV) optimal -portfolios based on any one of several robust covariance matrix estimators -that are not much influenced by outliers Details are provided in the Vignette -"robustCovMatForPA". - -New PortfolioAnalytics Functions: - -1. meancsm.efficient.frontier (create Mean-CSM efficient frontier) utility function -2. meanrisk.efficient.frontier (generate multiple efficient frontiers for portfolios with the same constraint object. -3. extract_risk (extract the risk value, e.g., StdDev or ES or CSM, based on the weights of a portfolio) -4. chart.EfficientFrontierCompare (Overlay the efficient frontiers of different minRisk portfolio objects on a single plot) -5. backtest.plot (based on Peter Carl's code, generate plots of the cumulative returns and/or drawdown for back-testing) -6. opt.outputMvo (converts output of `optimize.portfolio` to a list of the portfolio weights, mean, volatility and Sharpe Ratio) -7. plotFrontiers (plot frontiers based on the result of `meanvar.efficient.frontier`, `meanetl.efficient.frontier` or `meancsm.efficient.frontier`) - - -Enhanced PortfolioAnalytics Functions: - -1. optimize.portfolio (enhanced with CVXR solvers, CSM objective, customizable arg `momentFUN=` and output `~$moment_values`) -2. optimize.portfolio.rebalancing (enhanced with CVXR solvers, CSM objective and customizable arg `momentFUN=`) -3. create.EfficientFrontier (enhanced with type `mean-CSM` and `mean-risk`, and customizable arg `momentFUN=`) - - -Support S3 Methods for CVXR: - -1. print.optimize.portfolio.CVXR -2. extractStats.optimize.portfolio.CVXR - - -Custom Moment Functions for Robust Covariance Matrices: - -1. custom.covRob.MM -2. custom.covRob.Rocke -3. custom.covRob.Mcd -4. custom.covRob.TSGS -5. MycovRobMcd -6. MycovRobTSGS - - -New Vignettes and their Code Functions in the demo Folder: - -1. cvxrPortfolioAnalytics: CRAN title = "CVXR for PortfolioAnalytics". -2. demo_cvxrPortfolioAnalytics.R -3. robustCovMatForPA: CRAN title = "Robust Covariance Matrices for PortfolioAnalytics" -4. demo_robustCovMatForPA.R - -# New 2.1 Features - -xxx - -# Bug Reportin - -Please contribute with bug fixes, comments, and testing scripts! - -Please take your data and disguise it when submitting, or use data sets like -"edhec" like we do in the demos or or like "stocksCRSP" and "factorsSPGMI" in -the PCRA package or with your constraints and other objectives modified to -demonstrate your problem on public data. - -Please report any bugs or issues on the PortfolioAnalytics GitHub page at -https://github.com/braverock/PortfolioAnalytics/issues - -# Acknowledgements - -The bulk of the work in creating PortfolioAnalytics 2.0 was done by Xinran Zhao, -along with contributions from Yifu Kang, under the support of a 2022 Google -Summer of Code (GSOC 2022). Xinran and Yifu were mentored in GSOC 2022 by -Professor Doug Martin and Professor Steve Murray in the Applied Mathematics -Department at the University of Washington. diff --git a/README.md b/README.md new file mode 100644 index 00000000..4a9a2b76 --- /dev/null +++ b/README.md @@ -0,0 +1,105 @@ +README +================ + +This V2.1 version of PortfolioAnalytics is an update to the substantial +V2.0 version that was released on 2024-07-03. We first describe the V2.0 +features, then discuss the R demo capability, and finally we describe +the additional V2.1 features. + +# 2.0 Features + +A major feature of 2.0 is the integration of the CVXR solver R package +for convex optimization. CVXR supports eleven solver packages, each of +which supports solvers for one or more of the following optimization +problems: LP, QP, SOCP, SDP, EXP, MIP. See the Table near the beginning +of the document “Convex Optimization in R” at . +Thus, with PortfolioAnalytics 2.0, users are able to use any one of a +variety of solvers available in CVXR for their portfolio optimization +problems. + +A particular use of CVXR in PortfolioAnalytics 2.0 is for computing +Minimum Coherent Second Moment (MinCSM) portfolios, which are +second-order cone programming (SOCP) optimization problems. This is +quite a new capability that is not available in other portfolio +optimization software products. Details are provided in the Vignette +“cvxrPortfolioAnalytics”. + +Another important feature of PortfolioAnalytics 2.0, is that it contains +functionality for computing outliers-robust minimum variance (MV) +optimal portfolios based on any one of several robust covariance matrix +estimators that are not much influenced by outliers Details are provided +in the Vignette “robustCovMatForPA”. + +New PortfolioAnalytics Functions: + +1. meancsm.efficient.frontier (create Mean-CSM efficient frontier) + utility function +2. meanrisk.efficient.frontier (generate multiple efficient frontiers + for portfolios with the same constraint object. +3. extract_risk (extract the risk value, e.g., StdDev or ES or CSM, + based on the weights of a portfolio) +4. chart.EfficientFrontierCompare (Overlay the efficient frontiers of + different minRisk portfolio objects on a single plot) +5. backtest.plot (based on Peter Carl’s code, generate plots of the + cumulative returns and/or drawdown for back-testing) +6. opt.outputMvo (converts output of `optimize.portfolio` to a list of + the portfolio weights, mean, volatility and Sharpe Ratio) +7. plotFrontiers (plot frontiers based on the result of + `meanvar.efficient.frontier`, `meanetl.efficient.frontier` or + `meancsm.efficient.frontier`) + +Enhanced PortfolioAnalytics Functions: + +1. optimize.portfolio (enhanced with CVXR solvers, CSM objective, + customizable arg `momentFUN=` and output `~$moment_values`) +2. optimize.portfolio.rebalancing (enhanced with CVXR solvers, CSM + objective and customizable arg `momentFUN=`) +3. create.EfficientFrontier (enhanced with type `mean-CSM` and + `mean-risk`, and customizable arg `momentFUN=`) + +Support S3 Methods for CVXR: + +1. print.optimize.portfolio.CVXR +2. extractStats.optimize.portfolio.CVXR + +Custom Moment Functions for Robust Covariance Matrices: + +1. custom.covRob.MM +2. custom.covRob.Rocke +3. custom.covRob.Mcd +4. custom.covRob.TSGS +5. MycovRobMcd +6. MycovRobTSGS + +New Vignettes and their Code Functions in the demo Folder: + +1. cvxrPortfolioAnalytics: CRAN title = “CVXR for PortfolioAnalytics”. +2. demo_cvxrPortfolioAnalytics.R +3. robustCovMatForPA: CRAN title = “Robust Covariance Matrices for + PortfolioAnalytics” +4. demo_robustCovMatForPA.R + +# New 2.1 Features + +xxx + +# Bug Reportin + +Please contribute with bug fixes, comments, and testing scripts! + +Please take your data and disguise it when submitting, or use data sets +like “edhec” like we do in the demos or or like “stocksCRSP” and +“factorsSPGMI” in the PCRA package or with your constraints and other +objectives modified to demonstrate your problem on public data. + +Please report any bugs or issues on the PortfolioAnalytics GitHub page +at + +# Acknowledgements + +The bulk of the work in creating PortfolioAnalytics 2.0 was done by +Xinran Zhao, along with contributions from Yifu Kang, under the support +of a 2022 Google Summer of Code (GSOC 2022). Xinran and Yifu were +mentored in GSOC 2022 by Professor Doug Martin and Professor Steve +Murray in the Applied Mathematics Department at the University of +Washington. From cba86510084d20b5f0ebc9460fb508f4c446df0e Mon Sep 17 00:00:00 2001 From: xinran Date: Sun, 13 Oct 2024 18:53:33 -0700 Subject: [PATCH 4/4] README rmd --- README.Rmd | 98 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 README.Rmd diff --git a/README.Rmd b/README.Rmd new file mode 100644 index 00000000..1ada786c --- /dev/null +++ b/README.Rmd @@ -0,0 +1,98 @@ +--- +title: "README" +output: github_document +--- + +This V2.1 version of PortfolioAnalytics is an update to the substantial V2.0 +version that was released on 2024-07-03. We first describe the V2.0 features, +then discuss the R demo capability, and finally we describe the additional +V2.1 features. + +# 2.0 Features + +A major feature of 2.0 is the integration of the CVXR solver R package +for convex optimization. CVXR supports eleven solver packages, each of +which supports solvers for one or more of the following optimization +problems: LP, QP, SOCP, SDP, EXP, MIP. See the Table near the beginning +of the document "Convex Optimization in R" at https://cvxr.rbind.io/. +Thus, with PortfolioAnalytics 2.0, users are able to use any one of a +variety of solvers available in CVXR for their portfolio optimization +problems. + +A particular use of CVXR in PortfolioAnalytics 2.0 is for computing Minimum +Coherent Second Moment (MinCSM) portfolios, which are second-order cone +programming (SOCP) optimization problems. This is quite a new capability +that is not available in other portfolio optimization software products. +Details are provided in the Vignette "cvxrPortfolioAnalytics". + +Another important feature of PortfolioAnalytics 2.0, is that it contains +functionality for computing outliers-robust minimum variance (MV) optimal +portfolios based on any one of several robust covariance matrix estimators +that are not much influenced by outliers Details are provided in the Vignette +"robustCovMatForPA". + +New PortfolioAnalytics Functions: + +1. meancsm.efficient.frontier (create Mean-CSM efficient frontier) utility function +2. meanrisk.efficient.frontier (generate multiple efficient frontiers for portfolios with the same constraint object. +3. extract_risk (extract the risk value, e.g., StdDev or ES or CSM, based on the weights of a portfolio) +4. chart.EfficientFrontierCompare (Overlay the efficient frontiers of different minRisk portfolio objects on a single plot) +5. backtest.plot (based on Peter Carl's code, generate plots of the cumulative returns and/or drawdown for back-testing) +6. opt.outputMvo (converts output of `optimize.portfolio` to a list of the portfolio weights, mean, volatility and Sharpe Ratio) +7. plotFrontiers (plot frontiers based on the result of `meanvar.efficient.frontier`, `meanetl.efficient.frontier` or `meancsm.efficient.frontier`) + + +Enhanced PortfolioAnalytics Functions: + +1. optimize.portfolio (enhanced with CVXR solvers, CSM objective, customizable arg `momentFUN=` and output `~$moment_values`) +2. optimize.portfolio.rebalancing (enhanced with CVXR solvers, CSM objective and customizable arg `momentFUN=`) +3. create.EfficientFrontier (enhanced with type `mean-CSM` and `mean-risk`, and customizable arg `momentFUN=`) + + +Support S3 Methods for CVXR: + +1. print.optimize.portfolio.CVXR +2. extractStats.optimize.portfolio.CVXR + + +Custom Moment Functions for Robust Covariance Matrices: + +1. custom.covRob.MM +2. custom.covRob.Rocke +3. custom.covRob.Mcd +4. custom.covRob.TSGS +5. MycovRobMcd +6. MycovRobTSGS + + +New Vignettes and their Code Functions in the demo Folder: + +1. cvxrPortfolioAnalytics: CRAN title = "CVXR for PortfolioAnalytics". +2. demo_cvxrPortfolioAnalytics.R +3. robustCovMatForPA: CRAN title = "Robust Covariance Matrices for PortfolioAnalytics" +4. demo_robustCovMatForPA.R + +# New 2.1 Features + +xxx + +# Bug Reportin + +Please contribute with bug fixes, comments, and testing scripts! + +Please take your data and disguise it when submitting, or use data sets like +"edhec" like we do in the demos or or like "stocksCRSP" and "factorsSPGMI" in +the PCRA package or with your constraints and other objectives modified to +demonstrate your problem on public data. + +Please report any bugs or issues on the PortfolioAnalytics GitHub page at +https://github.com/braverock/PortfolioAnalytics/issues + +# Acknowledgements + +The bulk of the work in creating PortfolioAnalytics 2.0 was done by Xinran Zhao, +along with contributions from Yifu Kang, under the support of a 2022 Google +Summer of Code (GSOC 2022). Xinran and Yifu were mentored in GSOC 2022 by +Professor Doug Martin and Professor Steve Murray in the Applied Mathematics +Department at the University of Washington. +