[Returnanalytics-commits] r2587 - in pkg/PortfolioAnalytics: R man

noreply at r-forge.r-project.org noreply at r-forge.r-project.org
Wed Jul 17 13:49:19 CEST 2013


Author: rossbennett34
Date: 2013-07-17 13:49:18 +0200 (Wed, 17 Jul 2013)
New Revision: 2587

Modified:
   pkg/PortfolioAnalytics/R/constraint_fn_map.R
   pkg/PortfolioAnalytics/man/rp_transform.Rd
Log:
modifying rp_transform and fn_map to take group_pos

Modified: pkg/PortfolioAnalytics/R/constraint_fn_map.R
===================================================================
--- pkg/PortfolioAnalytics/R/constraint_fn_map.R	2013-07-17 09:40:59 UTC (rev 2586)
+++ pkg/PortfolioAnalytics/R/constraint_fn_map.R	2013-07-17 11:49:18 UTC (rev 2587)
@@ -54,6 +54,7 @@
   groups <- constraints$groups
   cLO <- constraints$cLO
   cUP <- constraints$cUP
+  group_pos <- constraints$group_pos
   div_target <- constraints$div_target
   turnover_target <- constraints$turnover_target
   max_pos <- constraints$max_pos
@@ -77,7 +78,7 @@
   if(!is.null(min_sum) & !is.null(max_sum)){
     if(!(sum(tmp_weights) >= min_sum & sum(tmp_weights) <= max_sum)){
       # Try to transform only considering leverage and box constraints
-      tmp_weights <- try(rp_transform(tmp_weights, min_sum, max_sum, min, max, groups=NULL, cLO=NULL, cUP=NULL, max_pos=NULL, 500), silent=TRUE)
+      tmp_weights <- try(rp_transform(tmp_weights, min_sum, max_sum, min, max, groups=NULL, cLO=NULL, cUP=NULL, max_pos=NULL, group_pos=NULL, 500), silent=TRUE)
       if(inherits(tmp_weights, "try-error")){
         # Default to initial weights
         tmp_weights <- weights
@@ -89,7 +90,7 @@
   if(!is.null(tmp_min) & !is.null(tmp_max)){
     if(!(all(tmp_weights >= tmp_min) & all(tmp_weights <= tmp_max))){
       # Try to transform only considering leverage and box constraints
-      tmp_weights <- try(rp_transform(tmp_weights, min_sum, max_sum, tmp_min, tmp_max, groups=NULL, cLO=NULL, cUP=NULL, max_pos=NULL, 500), silent=TRUE)
+      tmp_weights <- try(rp_transform(tmp_weights, min_sum, max_sum, tmp_min, tmp_max, groups=NULL, cLO=NULL, cUP=NULL, max_pos=NULL, group_pos=NULL, 500), silent=TRUE)
       if(inherits(tmp_weights, "try-error")){
         # Default to initial weights
         tmp_weights <- weights
@@ -111,7 +112,7 @@
             }
             
             # Now try the transformation again
-            tmp_weights <- try(rp_transform(tmp_weights, min_sum, max_sum, tmp_min, tmp_max, groups=NULL, cLO=NULL, cUP=NULL, max_pos=NULL, 500), silent=TRUE)
+            tmp_weights <- try(rp_transform(tmp_weights, min_sum, max_sum, tmp_min, tmp_max, groups=NULL, cLO=NULL, cUP=NULL, max_pos=NULL, group_pos, 500), silent=TRUE)
             # Default to original weights if this fails again
             if(inherits(tmp_weights, "try-error")) tmp_weights <- weights
             i <- i + 1
@@ -130,9 +131,9 @@
   
   # check group constraints
   if(!is.null(groups) & !is.null(tmp_cLO) & !is.null(tmp_cUP)){
-    if(any(group_fail(tmp_weights, groups, tmp_cLO, tmp_cUP))){
+    if(any(group_fail(tmp_weights, groups, tmp_cLO, tmp_cUP, group_pos))){
       # Try to transform only considering leverage, box, and group constraints
-      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)
+      tmp_weights <- try(rp_transform(tmp_weights, min_sum, max_sum, tmp_min, tmp_max, groups, tmp_cLO, tmp_cUP, max_pos=NULL, group_pos, 500), silent=TRUE)
       if(inherits(tmp_weights, "try-error")){
         # Default to initial weights
         tmp_weights <- weights
@@ -141,8 +142,8 @@
           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))){
+          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, group_pos))) & i <= 5){
+            if(any(group_fail(tmp_weights, groups, tmp_cLO, tmp_cUP, group_pos))){
               # 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
@@ -150,7 +151,7 @@
               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), 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, group_pos, 500), silent=TRUE)
             if(inherits(tmp_weights, "try-error")) tmp_weights <- weights
             i <- i + 1
           }
@@ -170,7 +171,7 @@
   if(!is.null(tmp_max_pos)){
     if(!(sum(abs(tmp_weights) > tolerance) <= tmp_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, tmp_min, tmp_max, groups, tmp_cLO, tmp_cUP, tmp_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, tmp_max_pos, group_pos, 500), silent=TRUE)
       if(inherits(tmp_weights, "try-error")){
         # Default to initial weights
         tmp_weights <- weights
@@ -180,7 +181,7 @@
             # increment tmp_max_pos by 1
             tmp_max_pos <- tmp_max_pos + 1
             # 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, tmp_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, tmp_max_pos, group_pos, 500), silent=TRUE)
             if(inherits(tmp_weights, "try-error")) tmp_weights <- weights
             i <- i + 1
           }
@@ -321,11 +322,12 @@
 #' @param cLO numeric or vector specifying minimum weight group constraints
 #' @param cUP numeric or vector specifying minimum weight group constraints
 #' @param max_pos maximum assets with non-zero weights
+#' @param group_pos vector specifying maximum number assets with non-zero weights per group
 #' @param max_permutations integer: maximum number of iterations to try for a valid portfolio, default 200
 #' @return named weighting vector
 #' @author Peter Carl, Brian G. Peterson, Ross Bennett (based on an idea by Pat Burns)
 #' @export
-rp_transform <- function(w, min_sum=0.99, max_sum=1.01, min, max, groups, cLO, cUP, max_pos=NULL, max_permutations=200){
+rp_transform <- function(w, min_sum=0.99, max_sum=1.01, min, max, groups, cLO, cUP, max_pos=NULL, group_pos=NULL, max_permutations=200){
   # Uses logic from randomize_portfolio to "normalize" a weights vector to 
   # satisfy min_sum and max_sum while accounting for box and group constraints
   # Modified from randomize_portfolio to trigger the while loops if any weights 
@@ -336,6 +338,9 @@
   tolerance=.Machine$double.eps^0.5
   if(is.null(max_pos)) max_pos <- length(w)
   
+  if(!is.null(group_pos)) max_group_pos <- sum(group_pos)
+  max_assets <- min(max_pos, max_group_pos)
+  
   # Create a temporary min vector that will be modified, because a feasible
   # portfolio is rarely created if all(min > 0). This is due to the while
   # loop that checks any(tmp_w < min).
@@ -354,7 +359,7 @@
   # return w if all constraints are satisfied
   if((sum(w) >= min_sum & sum(w) <= max_sum) & 
        (all(w >= tmp_min) & all(w <= max)) & 
-       (all(!group_fail(w, groups, cLO, cUP))) &
+       (all(!group_fail(w, groups, cLO, cUP, group_pos))) &
        (sum(abs(w) > tolerance) <= max_pos)){
     return(w)
   }
@@ -362,7 +367,7 @@
   # generate a sequence of weights based on min/max box constraints
   weight_seq <- generatesequence(min=min(min), max=max(max), by=0.005)
   # make sure there is a 0 in weight_seq
-  if(!is.null(max_pos) & !is.element(0, weight_seq)) weight_seq <- c(0, weight_seq)
+  if((!is.null(max_pos) | !is.null(group_pos)) & !is.element(0, weight_seq)) weight_seq <- c(0, weight_seq)
   
   # start the permutations counter
   permutations <- 1
@@ -371,7 +376,7 @@
   tmp_w <- w
   
   # while portfolio is outside min_sum/max_sum or tmp_min/max or group or postion_limit constraints and we have not reached max_permutations
-  while ((sum(tmp_w) <= min_sum | sum(tmp_w) >= max_sum | any(tmp_w < tmp_min) | any(tmp_w > max) | any(group_fail(tmp_w, groups, cLO, cUP)) | (sum(abs(tmp_w) > tolerance) > max_pos)) & permutations <= max_permutations) {
+  while ((sum(tmp_w) <= min_sum | sum(tmp_w) >= max_sum | any(tmp_w < tmp_min) | any(tmp_w > max) | any(group_fail(tmp_w, groups, cLO, cUP, group_pos)) | (sum(abs(tmp_w) > tolerance) > max_pos)) & permutations <= max_permutations) {
     permutations = permutations + 1
     # check our box constraints on total portfolio weight
     # reduce(increase) total portfolio size till you get a match
@@ -383,7 +388,7 @@
     tmp_w <- w
     tmp_min <- min
     
-    random_index <- sample(1:length(tmp_w), max_pos)
+    random_index <- sample(1:length(tmp_w), max_assets)
     
     # Get the index values that are not in random_index and set them equal to 0
     full_index <- 1:length(tmp_w)
@@ -396,7 +401,7 @@
     
     i = 1
     # while sum of weights is less than min_sum or tmp_min/max box or group constraint is violated
-    while ((sum(tmp_w) <= min_sum | any(tmp_w < tmp_min) | any(tmp_w > max) | any(group_fail(tmp_w, groups, cLO, cUP))) & i <= length(tmp_w)) {
+    while ((sum(tmp_w) <= min_sum | any(tmp_w < tmp_min) | any(tmp_w > max) | any(group_fail(tmp_w, groups, cLO, cUP, group_pos))) & i <= length(tmp_w)) {
       # randomly permute and increase a random portfolio element
       cur_index <- random_index[i]
       cur_val <- tmp_w[cur_index]
@@ -415,7 +420,7 @@
     # group_fail does not test for direction of violation, just that group constraints were violated
     i = 1 
     # while sum of weights is greater than max_sum or tmp_min/max box or group constraint is violated
-    while ((sum(tmp_w) >= max_sum | any(tmp_w < tmp_min) | any(tmp_w > max) | any(group_fail(tmp_w, groups, cLO, cUP))) & i <= length(tmp_w)) {
+    while ((sum(tmp_w) >= max_sum | any(tmp_w < tmp_min) | any(tmp_w > max) | any(group_fail(tmp_w, groups, cLO, cUP, group_pos))) & i <= length(tmp_w)) {
       # randomly permute and decrease a random portfolio element
       cur_index <- random_index[i]
       cur_val <- tmp_w[cur_index]
@@ -489,7 +494,7 @@
     grp.max <- cUP[i]
     grp.pos <- group_pos[i]
     # return TRUE if grp.min or grp.max is violated
-    group_fail[i] <- ( sum(tmp.w) < grp.min | sum(tmp.w) > grp.max (sum(abs(tmp.w) > tolerance) > grp.pos))
+    group_fail[i] <- ( sum(tmp.w) < grp.min | sum(tmp.w) > grp.max | (sum(abs(tmp.w) > tolerance) > grp.pos))
     k <- k + j
     l <- k - 1
   }

Modified: pkg/PortfolioAnalytics/man/rp_transform.Rd
===================================================================
--- pkg/PortfolioAnalytics/man/rp_transform.Rd	2013-07-17 09:40:59 UTC (rev 2586)
+++ pkg/PortfolioAnalytics/man/rp_transform.Rd	2013-07-17 11:49:18 UTC (rev 2587)
@@ -3,7 +3,7 @@
 \title{Transform a weights vector to satisfy leverage, box, group, and position_limit constraints using logic from \code{randomize_portfolio}}
 \usage{
   rp_transform(w, min_sum = 0.99, max_sum = 1.01, min, max,
-    groups, cLO, cUP, max_pos = NULL,
+    groups, cLO, cUP, max_pos = NULL, group_pos = NULL,
     max_permutations = 200)
 }
 \arguments{
@@ -31,6 +31,9 @@
 
   \item{max_pos}{maximum assets with non-zero weights}
 
+  \item{group_pos}{vector specifying maximum number assets
+  with non-zero weights per group}
+
   \item{max_permutations}{integer: maximum number of
   iterations to try for a valid portfolio, default 200}
 }



More information about the Returnanalytics-commits mailing list