[Returnanalytics-commits] r2411 - in pkg/PortfolioAnalytics: R sandbox

noreply at r-forge.r-project.org noreply at r-forge.r-project.org
Mon Jun 24 00:20:50 CEST 2013


Author: rossbennett34
Date: 2013-06-24 00:20:50 +0200 (Mon, 24 Jun 2013)
New Revision: 2411

Added:
   pkg/PortfolioAnalytics/R/constraintsFUN.R
   pkg/PortfolioAnalytics/sandbox/testing_constrained_group.R
Log:
Adding function to impose group constraints on a vector of weights. Adding testing script for constrained_group in sandbox

Added: pkg/PortfolioAnalytics/R/constraintsFUN.R
===================================================================
--- pkg/PortfolioAnalytics/R/constraintsFUN.R	                        (rev 0)
+++ pkg/PortfolioAnalytics/R/constraintsFUN.R	2013-06-23 22:20:50 UTC (rev 2411)
@@ -0,0 +1,64 @@
+#' Generic function to impose group constraints on a vector of weights
+#' 
+#' This function gets group subsets of the weights vector and checks if the sum
+#' of the weights in that group violates the minimum or maximum value. If the 
+#' sum of weights in a given group violates its maximum or minimum value, the 
+#' group of weights is normalized to be equal to the minimum or maximum value.
+#' This group normalization causes the sum of weights to change. The weights
+#' vector is then normalized so that the min_sum and max_sum constraints are 
+#' satisfied. This "re-normalization" of the weights vector may then cause the
+#' group constraints to not be satisfied.
+#' 
+#' Group constraints are implemented in ROI solvers, but this function could
+#' be used in constrained_objective for random portfolios, DEoptim, pso, or 
+#' gensa solvers.
+#' 
+#' @param groups vector to group assets
+#' @param cLO vector of group weight minimums
+#' @param cUP vector of group weight maximums
+#' @param weights vector of weights
+#' @param min_sum minimum sum of weights
+#' @param max_sum maximum sum of weights
+#' @param normalize TRUE/FALSE to normalize the weights vector to satisfy the min_sum and max_sum constraints
+#' 
+#' @author Ross Bennett
+#' @export
+constrained_group_tmp <- function(groups, cLO, cUP, weights, min_sum, max_sum, normalize=TRUE){
+  # Modify the args later to accept a portfolio or constraint object
+  n.groups <- length(groups)
+  
+  k <- 1
+  l <- 0
+  for(i in 1:n.groups){
+    j <- groups[i]
+    tmp.w <- weights[k:(l+j)]
+    # normalize weights for a given group that sum to less than specified group min
+    grp.min <- cLO[i]
+    if(sum(tmp.w) < grp.min) {
+      weights[k:(l+j)] <- (grp.min / sum(tmp.w)) * tmp.w
+    }
+    # normalize weights for a given group that sum to greater than specified group max
+    grp.max <- cUP[i]
+    if(sum(tmp.w) > grp.max) {
+      weights[k:(l+j)] <- (grp.max / sum(tmp.w)) * tmp.w
+    }
+    # cat(sum(tmp.w), "\t", cLO[i], "\n")
+    # cat(k, " ", l+j, "\n")
+    k <- k + j
+    l <- k - 1
+  }
+  # Normalizing the weights inside the groups changes the sum of the weights.
+  # Should normalizing the sum of weights take place here or somewhere else?
+  
+  if(normalize){
+    # max_sum and min_sum normalization borrowed from constrained_objective
+    # Normalize to max_sum
+    if(sum(weights) > max_sum) { weights <- (max_sum / sum(weights)) * weights }
+    # Normalize to min_sum
+    if(sum(weights) < min_sum) { weights <- (min_sum / sum(weights)) * weights }
+  }
+  # "Re-normalizing" the weights causes some of the group constraints to
+  # be violated. Can this be addressed later with a penalty term for violating
+  # the group constraints? Or another way?
+  return(weights)
+}

Added: pkg/PortfolioAnalytics/sandbox/testing_constrained_group.R
===================================================================
--- pkg/PortfolioAnalytics/sandbox/testing_constrained_group.R	                        (rev 0)
+++ pkg/PortfolioAnalytics/sandbox/testing_constrained_group.R	2013-06-23 22:20:50 UTC (rev 2411)
@@ -0,0 +1,71 @@
+
+
+##### EX1 #####
+# first group exceeds cUP
+groups <- c(2, 1)
+cLO <- c(0.2, 0.10)
+cUP <- c(0.4, 0.55)
+
+weights <- c(0.15, 0.35, 0.50)
+sum(weights)
+
+(w <- constrained_group_tmp(groups, cLO, cUP, weights, 1, 1, TRUE))
+sum(w[1:2])
+sum(w)
+
+(w <- constrained_group_tmp(groups, cLO, cUP, weights, 1, 1, FALSE))
+# The group 1 cUP is met exactly, but the sume of weights are not equal to 1
+sum(w[1:2])
+sum(w)
+
+
+##### EX2 #####
+# The assets are grouped into 3 groups of 2
+# The sum of the weights for the first group assets must be between 0.05 and 0.35
+# The sum of the weights for the second group of assets must be between 0.10 and 0.45
+# The sum of the weights for the last group of assets must be between 0.05 and 0.25
+
+# first group exceeds cUP
+groups <- c(2, 2, 2)
+cLO <- c(0.05, 0.10, 0.05)
+cUP <- c(0.4, 0.45, 0.25)
+
+weights <- c(0.15, 0.30, 0.15, 0.25, 0.05, 0.10)
+sum(weights)
+
+(w <- constrained_group_tmp(groups, cLO, cUP, weights, 1, 1, TRUE))
+sum(w)
+
+##### Ex3 #####
+# The second group is below cLO
+groups <- c(2, 1, 3)
+cLO <- c(0.05, 0.10, 0.05)
+cUP <- c(0.4, 0.45, 0.65)
+
+weights <- c(0.15, 0.25, 0.08, 0.2, 0.22, 0.10)
+sum(weights)
+
+(w <- constrained_group_tmp(groups, cLO, cUP, weights, 1, 1, TRUE))
+sum(w)
+
+##### Ex4 #####
+# The second group is above cUP and the fourth group is below cLO
+groups <- c(2, 4, 3, 2)
+cLO <- c(0.05, 0.10, 0.05, 0.08)
+cUP <- c(0.4, 0.5, 0.65, 0.45)
+
+weights <- c(0.05, 0.1, 0.07, 0.2, 0.22, 0.10, 0.05, 0.08, 0.05, 0.04, 0.04)
+sum(weights[1:2])
+sum(weights[3:6])
+sum(weights[7:10])
+sum(weights[10:11])
+sum(weights)
+
+(w <- constrained_group_tmp(groups, cLO, cUP, weights, 1, 1, TRUE))
+sum(w[1:2])
+sum(w[3:6])
+sum(w[7:10])
+sum(w[10:11])
+
+# Group 2 cUP is being violated. Appears that normalizing at the end of the 
+# function is causing some of the group constraints to be violated



More information about the Returnanalytics-commits mailing list