[Returnanalytics-commits] r2524 - in pkg/PortfolioAnalytics: R sandbox
noreply at r-forge.r-project.org
noreply at r-forge.r-project.org
Tue Jul 9 01:53:40 CEST 2013
Author: rossbennett34
Date: 2013-07-09 01:53:39 +0200 (Tue, 09 Jul 2013)
New Revision: 2524
Modified:
pkg/PortfolioAnalytics/R/constraint_fn_map.R
pkg/PortfolioAnalytics/sandbox/testing_fn_map.R
Log:
Modified fn_map to relax group constraints. Updated testing_fn_map script with example
Modified: pkg/PortfolioAnalytics/R/constraint_fn_map.R
===================================================================
--- pkg/PortfolioAnalytics/R/constraint_fn_map.R 2013-07-08 20:51:21 UTC (rev 2523)
+++ pkg/PortfolioAnalytics/R/constraint_fn_map.R 2013-07-08 23:53:39 UTC (rev 2524)
@@ -59,6 +59,8 @@
tmp_weights <- weights
tmp_min <- min
tmp_max <- max
+ tmp_cLO <- cLO
+ tmp_cUP <- cUP
# step 2: check that the vector of weights satisfies the constraints,
# transform weights if constraint is violated
@@ -94,6 +96,7 @@
tmp_weights <- weights
i <- 1
# loop while constraints are violated and relax constraints
+ # try to relax constraints up to 5 times
while((sum(tmp_weights) < min_sum | sum(tmp_weights) > max_sum | any(tmp_weights < tmp_min) | any(tmp_weights > tmp_max)) & i <= 5){
# check if min is violated
if(any(tmp_weights < tmp_min)){
@@ -131,13 +134,36 @@
}
# check group constraints
- if(!is.null(groups) & !is.null(cLO) & !is.null(cUP)){
- if(any(group_fail(tmp_weights, groups, cLO, cUP))){
+ if(!is.null(groups) & !is.null(tmp_cLO) & !is.null(tmp_cUP)){
+ if(any(group_fail(tmp_weights, groups, tmp_cLO, tmp_cUP))){
# Try to transform only considering leverage, box, and group constraints
- tmp_weights <- try(rp_transform(tmp_weights, min_sum, max_sum, min, max, groups, cLO, cUP, max_pos=NULL, 500), silent=TRUE)
+ tmp_weights <- try(rp_transform(tmp_weights, min_sum, max_sum, tmp_min, tmp_max, groups, tmp_cLO, tmp_cUP, max_pos=NULL, 500), silent=TRUE)
if(inherits(tmp_weights, "try-error")){
# Default to initial weights
tmp_weights <- weights
+ i <- 1
+ # loop while constraints are violated and relax constraints
+ # Try to relax constraints up to 5 times
+ while(((sum(tmp_weights) < min_sum | sum(tmp_weights) > max_sum) | (any(tmp_weights < tmp_min) | any(tmp_weights > tmp_max)) | any(group_fail(tmp_weights, groups, tmp_cLO, tmp_cUP))) & i <= 5){
+ if(any(group_fail(tmp_weights, groups, tmp_cLO, tmp_cUP))){
+ # I know which group failed, but not if it was cUP or cLO that was violated
+ # Maybe I can modify group_fail to report back what was violated and only relax cLO or cUP, not both
+ # This relaxes both cLO and cUP
+ tmp_cLO[group_fail(tmp_weights, groups, tmp_cLO, tmp_cUP)] <- tmp_cLO[group_fail(tmp_weights, groups, tmp_cLO, tmp_cUP)] - runif(1, 0.01, 0.05)
+ tmp_cUP[group_fail(tmp_weights, groups, tmp_cLO, tmp_cUP)] <- tmp_cUP[group_fail(tmp_weights, groups, tmp_cLO, tmp_cUP)] + runif(1, 0.01, 0.05)
+ }
+ # Now try the transformation again
+ tmp_weights <- try(rp_transform(tmp_weights, min_sum, max_sum, tmp_min, tmp_max, groups, tmp_cLO, tmp_cUP, max_pos=NULL, 500))
+ if(inherits(tmp_weights, "try-error")) tmp_weights <- weights
+ i <- i + 1
+ }
+ # We have a feasible portfolio in terms of min_sum and max_sum,
+ # but were unable to produce a portfolio that satisfies group constraints
+ if(isTRUE(all.equal(tmp_weights, weights))){
+ # reset min and max to their original values and penalize later
+ tmp_cLO <- cLO
+ tmp_cUP <- cUP
+ }
# Other actions to consider
# relax constraints (rp_transform checks all constraints together so we may not know which constraint is too restrictive)
# different normalization method
@@ -153,7 +179,7 @@
if(!is.null(max_pos)){
if(!(sum(abs(tmp_weights) > tolerance) <= max_pos)){
# Try to transform only considering leverage, box, group, and position_limit constraints
- tmp_weights <- try(rp_transform(tmp_weights, min_sum, max_sum, min, max, groups, cLO, cUP, max_pos, 500), silent=TRUE)
+ tmp_weights <- try(rp_transform(tmp_weights, min_sum, max_sum, tmp_min, tmp_max, groups, tmp_cLO, tmp_cUP, max_pos, 500), silent=TRUE)
if(inherits(tmp_weights, "try-error")){
# Default to initial weights
tmp_weights <- weights
@@ -190,7 +216,7 @@
}
}
names(tmp_weights) <- names(weights)
- return(list(weights=tmp_weights, min=tmp_min, max=tmp_max, out=out))
+ return(list(weights=tmp_weights, min=tmp_min, max=tmp_max, cLO=tmp_cLO, cUP=tmp_cUP, out=out))
}
#' Transform weights that violate min or max box constraints
Modified: pkg/PortfolioAnalytics/sandbox/testing_fn_map.R
===================================================================
--- pkg/PortfolioAnalytics/sandbox/testing_fn_map.R 2013-07-08 20:51:21 UTC (rev 2523)
+++ pkg/PortfolioAnalytics/sandbox/testing_fn_map.R 2013-07-08 23:53:39 UTC (rev 2524)
@@ -60,3 +60,18 @@
# note how min has been changed
fn_map(weights, pspec)
+##### relaxing group constraints #####
+pspec <- portfolio.spec(assets=funds)
+
+pspec <- add.constraint(portfolio=pspec, type="full_investment", enabled=T)
+pspec <- add.constraint(portfolio=pspec, type="box", min=0.05, max=0.7, enabled=T)
+# Make group constraints too restrictive
+pspec <- add.constraint(portfolio=pspec, type="group", groups=c(2, 2),
+ group_min=c(0.05, 0.01), group_max=c(0.45, 0.55), enabled=T)
+
+# weights satisfy leverage and box constraints, but not group
+weights <- c(0.15, 0.05, 0.10, 0.7)
+
+# group constraints needs to be relaxed
+# note how cLO and cUP have been changed
+fn_map(weights, pspec)
More information about the Returnanalytics-commits
mailing list