[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