[Returnanalytics-commits] r3210 - pkg/PortfolioAnalytics/R
noreply at r-forge.r-project.org
noreply at r-forge.r-project.org
Mon Oct 7 08:09:55 CEST 2013
Author: rossbennett34
Date: 2013-10-07 08:09:54 +0200 (Mon, 07 Oct 2013)
New Revision: 3210
Modified:
pkg/PortfolioAnalytics/R/extract.efficient.frontier.R
pkg/PortfolioAnalytics/R/optFUN.R
pkg/PortfolioAnalytics/R/optimize.portfolio.R
Log:
Adding functionality to maximize mean / ETL using ROI solvers.
Modified: pkg/PortfolioAnalytics/R/extract.efficient.frontier.R
===================================================================
--- pkg/PortfolioAnalytics/R/extract.efficient.frontier.R 2013-10-07 01:54:19 UTC (rev 3209)
+++ pkg/PortfolioAnalytics/R/extract.efficient.frontier.R 2013-10-07 06:09:54 UTC (rev 3210)
@@ -226,7 +226,7 @@
maxret <- extractObjectiveMeasures(tmp)$mean
# run the optimization to get the return at the min ETL portfolio
- tmp <- optimize.portfolio(R=R, portfolio=portfolio, optimize_method="ROI")
+ tmp <- optimize.portfolio(R=R, portfolio=portfolio, optimize_method="ROI", ef=TRUE)
stats <- extractStats(tmp)
minret <- stats["mean"]
@@ -242,7 +242,7 @@
stopifnot("package:foreach" %in% search() || require("foreach",quietly = TRUE))
out <- foreach(i=1:length(ret_seq), .inorder=TRUE, .combine=rbind, .errorhandling='remove') %dopar% {
portfolio$objectives[[mean_idx]]$target <- ret_seq[i]
- extractStats(optimize.portfolio(R=R, portfolio=portfolio, optimize_method="ROI"))
+ extractStats(optimize.portfolio(R=R, portfolio=portfolio, optimize_method="ROI", ef=TRUE))
}
colnames(out) <- names(stats)
return(structure(out, class="frontier"))
Modified: pkg/PortfolioAnalytics/R/optFUN.R
===================================================================
--- pkg/PortfolioAnalytics/R/optFUN.R 2013-10-07 01:54:19 UTC (rev 3209)
+++ pkg/PortfolioAnalytics/R/optFUN.R 2013-10-07 06:09:54 UTC (rev 3210)
@@ -708,3 +708,81 @@
# constraints=L_constraint(L=Amat, dir=dir, rhs=rhs))
# roi.result <- ROI_solve(x=opt.prob, solver="quadprog")
}
+
+
+mean_etl_opt <- function(R, constraints, moments, target, alpha, tol=.Machine$double.eps^0.5, maxit=50){
+ # This function returns the target mean return that maximizes mean / etl (i.e. starr)
+
+ # if all(moments$mean == 0) then the user did not specify mean as an objective,
+ # and we just want to return the target mean return value
+ if(all(moments$mean == 0)) return(target)
+
+ fmean <- matrix(moments$mean, ncol=1)
+
+ # can't use optimize.portfolio here, this function is called inside
+ # optimize.portfolio and will throw an error message about nesting too deeply
+
+ # Find the maximum return
+ max_ret <- maxret_opt(R=R, moments=moments, constraints=constraints, target=NA)
+ max_mean <- as.numeric(-max_ret$out)
+
+ # Find the starr at the maximum etl portfolio
+ ub_etl <- etl_opt(R=R, constraints=constraints, moments=moments, target=max_mean, alpha=alpha)
+ ub_weights <- matrix(ub_etl$weights, ncol=1)
+ ub_mean <- as.numeric(t(ub_weights) %*% fmean)
+ ub_etl <- as.numeric(ub_etl$out)
+ # starr at the upper bound
+ ub_starr <- ub_mean / ub_etl
+
+ # Find the starr at the minimum etl portfolio
+ lb_etl <- etl_opt(R=R, constraints=constraints, moments=moments, target=NA, alpha=alpha)
+ lb_weights <- matrix(lb_etl$weights)
+ lb_mean <- as.numeric(t(lb_weights) %*% fmean)
+ lb_etl <- as.numeric(lb_etl$out)
+ # starr at the lower bound
+ lb_starr <- lb_mean / lb_etl
+
+ # want to find the return that maximizes mean / etl
+ i <- 1
+ while((abs(ub_starr - lb_starr) > tol) & (i < maxit)){
+ # bisection method to find the maximum mean / etl
+
+ print(i)
+ print(ub_starr)
+ print(lb_starr)
+ print("**********")
+ # Find the starr at the mean return midpoint
+ new_ret <- (lb_mean + ub_mean) / 2
+ mid <- etl_opt(R=R, constraints=constraints, moments=moments, target=new_ret, alpha=alpha)
+ mid_weights <- matrix(mid$weights, ncol=1)
+ mid_mean <- as.numeric(t(mid_weights) %*% fmean)
+ mid_etl <- as.numeric(mid$out)
+ mid_starr <- mid_mean / mid_etl
+ # tmp_starr <- mid_starr
+
+ if(mid_starr > ub_starr){
+ # if mid_starr > ub_starr then mid_starr becomes the new upper bound
+ ub_mean <- mid_mean
+ ub_starr <- mid_starr
+ new_ret <- (lb_mean + ub_mean) / 2
+ mid <- etl_opt(R=R, constraints=constraints, moments=moments, target=new_ret, alpha=alpha)
+ mid_weights <- matrix(mid$weights, ncol=1)
+ mid_mean <- as.numeric(t(mid_weights) %*% fmean)
+ mid_etl <- as.numeric(mid$out)
+ mid_starr <- mid_mean / mid_etl
+ }
+ if(mid_starr > lb_starr){
+ # if mid_starr > lb_starr then mid_starr becomes the new lower bound
+ lb_mean <- mid_mean
+ lb_starr <- mid_starr
+ new_ret <- (lb_mean + ub_mean) / 2
+ mid <- etl_opt(R=R, constraints=constraints, moments=moments, target=new_ret, alpha=alpha)
+ mid_weights <- matrix(mid$weights, ncol=1)
+ mid_mean <- as.numeric(t(mid_weights) %*% fmean)
+ mid_etl <- as.numeric(mid$out)
+ mid_starr <- mid_mean / mid_etl
+ }
+ i <- i + 1
+ }
+ return(new_ret)
+}
Modified: pkg/PortfolioAnalytics/R/optimize.portfolio.R
===================================================================
--- pkg/PortfolioAnalytics/R/optimize.portfolio.R 2013-10-07 01:54:19 UTC (rev 3209)
+++ pkg/PortfolioAnalytics/R/optimize.portfolio.R 2013-10-07 06:09:54 UTC (rev 3210)
@@ -795,7 +795,12 @@
}
}
if( any(c("CVaR", "ES", "ETL") %in% names(moments)) ) {
+ if(hasArg(ef)) ef=match.call(expand.dots=TRUE)$ef else ef=FALSE
# Minimize sample ETL/ES/CVaR if CVaR, ETL, or ES is specified as an objective
+ if(length(moments) == 2 & all(moments$mean != 0) & ef==FALSE){
+ # This is called by meanetl.efficient.frontier and we do not want that, need to have ef==FALSE
+ target <- mean_etl_opt(R=R, constraints=constraints, moments=moments, target=target, alpha=alpha)
+ }
if(!is.null(constraints$max_pos)) {
# This is an MILP problem if max_pos is specified as a constraint
roi_result <- etl_milp_opt(R=R, constraints=constraints, moments=moments, target=target, alpha=alpha)
More information about the Returnanalytics-commits
mailing list