[Returnanalytics-commits] r2472 - pkg/PortfolioAnalytics/R

noreply at r-forge.r-project.org noreply at r-forge.r-project.org
Sun Jun 30 01:06:17 CEST 2013


Author: rossbennett34
Date: 2013-06-30 01:06:16 +0200 (Sun, 30 Jun 2013)
New Revision: 2472

Added:
   pkg/PortfolioAnalytics/R/constraint_fnMap.R
Log:
adding constraint mapping function. Still needs a lot of work

Added: pkg/PortfolioAnalytics/R/constraint_fnMap.R
===================================================================
--- pkg/PortfolioAnalytics/R/constraint_fnMap.R	                        (rev 0)
+++ pkg/PortfolioAnalytics/R/constraint_fnMap.R	2013-06-29 23:06:16 UTC (rev 2472)
@@ -0,0 +1,102 @@
+#' Constraint mapping function
+#' 
+#' The purpose of the mapping function is to transform a weights vector
+#' that does not meet all the constraints into a weights vector that
+#' does meet the constraints, if one exists, hopefully with a minimum
+#' of transformation.
+
+#' I think our first step should be to test each constraint type, in
+#' some sort of hierarchy, starting with box constraints (almost all
+#' solvers support box constraints, of course), since some of the other
+#' transformations will violate the box constraints, and we'll need to
+#' transform back again.
+#' 
+#' @param weights vector of weights
+#' @param portfolio object of class portfolio
+#' @author Ross Bennett
+#' @export
+constraint_fnMap <- function(weights, portfolio) {
+  
+  if (!is.portfolio(portfolio)) {
+    stop("Portfolio passed in is not of class portfolio")
+  }
+  
+  for(constraint in portfolio$constraints) {
+    # Check for enabled constraints
+    if(constraint$enabled){
+      
+      ## box constraint
+      if(inherits(constraint, "box_constraint")){
+        # TODO
+      } # box constraint
+      
+      ## weight_sum constraint
+      if(inherits(constraint, "weight_sum_constraint")){
+        min_sum <- constraint$min_sum
+        max_sum <- constraint$max_sum
+        print(min_sum)
+        print(max_sum)
+        # 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 }
+      } # weight_sum constraint
+      
+      ## group constraint
+      if(inherits(constraint, "group_constraint")){
+        groups <- constraint$groups
+        cLO <- constraint$cLO
+        cUP <- constraint$cUP
+        print(groups)
+        print(cLO)
+        print(cUP)
+        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
+          }
+          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?
+        # Re-normalizing the weights will get us *close* to satisfying the group constraints.
+        # Maybe then add a penalty in constrained objective for violation of group constraints?
+      } # group constraint
+      
+      # Turnover constraints
+      # TODO
+      
+      # Diversification constraints
+      # TODO
+    }
+  }
+  return(weights)
+}
+
+# library(PortfolioAnalytics)
+# data(edhec)
+# ret <- edhec[, 1:4]
+# funds <- colnames(ret)
+# 
+# pspec <- portfolio.spec(assets=funds)
+# pspec <- add.constraint(portfolio=pspec, type="weight_sum", min_sum=0.99, max_sum=1.01, enabled=TRUE)
+# pspec <- add.constraint(portfolio=pspec, type="box", enabled=TRUE)
+# pspec <- add.constraint(portfolio=pspec, type="group", groups=c(2,2), group_min=c(0.1, 0.2), group_max=c(0.3, 0.8), enabled=TRUE)
+# 
+# weights <- c(0.15, 0.2, 0.15, 0.5)
+# sum(weights)
+# 
+# (w <- constraint_fnMap(weights, pspec))
+# sum(w)



More information about the Returnanalytics-commits mailing list