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

noreply at r-forge.r-project.org noreply at r-forge.r-project.org
Fri Jul 5 18:54:52 CEST 2013


Author: rossbennett34
Date: 2013-07-05 18:54:52 +0200 (Fri, 05 Jul 2013)
New Revision: 2505

Modified:
   pkg/PortfolioAnalytics/R/constraint_fn_map.R
   pkg/PortfolioAnalytics/sandbox/testing_fn_map.R
Log:
Revising fn_map function for rp_transform with position limits. Penalize diversification and turnover only if outside +/- 5%

Modified: pkg/PortfolioAnalytics/R/constraint_fn_map.R
===================================================================
--- pkg/PortfolioAnalytics/R/constraint_fn_map.R	2013-07-05 15:26:00 UTC (rev 2504)
+++ pkg/PortfolioAnalytics/R/constraint_fn_map.R	2013-07-05 16:54:52 UTC (rev 2505)
@@ -156,8 +156,9 @@
   # check leverage constraints
   if(!is.null(min_sum) & !is.null(max_sum)){
     if(!(sum(tmp_weights) >= min_sum & sum(tmp_weights) <= max_sum)){
-      print("leverage constraint violated, transforming weights.")
-      tmp_weights <- rp_transform(tmp_weights, min_sum, max_sum, min, max, groups, cLO, cUP, 500)
+      tmp_weights <- rp_transform(tmp_weights, min_sum, max_sum, min, max, groups, cLO, cUP, max_pos, 500)
+      # print("leverage constraint violated, transforming weights.")
+      # print(tmp_weights)
       # tmp_weights <- txfrm_weight_sum_constraint(tmp_weights, min_sum, max_sum)
     }
   }
@@ -165,8 +166,9 @@
   # check box constraints
   if(!is.null(min) & !is.null(max)){
     if(!(all(tmp_weights >= min) & all(tmp_weights <= max))){
-      print("box constraints violated, transforming weights.")
-      tmp_weights <- rp_transform(tmp_weights, min_sum, max_sum, min, max, groups, cLO, cUP, 500)
+      tmp_weights <- rp_transform(tmp_weights, min_sum, max_sum, min, max, groups, cLO, cUP, max_pos, 500)
+      # print("box constraints violated, transforming weights.")
+      # print(tmp_weights)
       # tmp_weights <- txfrm_box_constraint(tmp_weights, min, max)
     }
   }
@@ -174,8 +176,9 @@
   # check group constraints
   if(!is.null(groups) & !is.null(cLO) & !is.null(cUP)){
     if(any(group_fail(tmp_weights, groups, cLO, cUP))){
-      print("group constraints violated, transforming weights.")
-      tmp_weights <- rp_transform(tmp_weights, min_sum, max_sum, min, max, groups, cLO, cUP, 500)
+      tmp_weights <- rp_transform(tmp_weights, min_sum, max_sum, min, max, groups, cLO, cUP, max_pos, 500)
+      # print("group constraints violated, transforming weights.")
+      # print(tmp_weights)
       # tmp_weights <- txfrm_group_constraint(tmp_weights, groups, cLO, cUP)
     }
   }
@@ -183,25 +186,35 @@
   # check position_limit constraints
   if(!is.null(max_pos)){
     if(!(sum(abs(tmp_weights) > tolerance) <= max_pos)){
+      tmp_weights <- rp_transform(tmp_weights, min_sum, max_sum, min, max, groups, cLO, cUP, max_pos, 500)
       # print("position_limit constraint violated, transforming weights.")
+      # print(tmp_weights)
       # tmp_weights <- txfrm_position_limit_constraint(tmp_weights, max_pos, nassets)
     }
   }
   
   # check diversification constraint
   if(!is.null(div_target)){
-    print("transform or penalize to meet diversification target")
     # penalize instead of transform?
     div <- diversification(tmp_weights)
-    out = out + penalty * abs(multiplier) * abs(div - div_target)
+    # only penalize if not within +/- 5% of target
+    if((div < div_target * .95) | (div > div_target * 1.05)){
+      # print("transform or penalize to meet diversification target")
+      out = out + penalty * abs(multiplier) * abs(div - div_target)
+    }
   }
   
+  # check turnover constraint
   if(!is.null(turnover_target)){
-    # print("transform or penalize to meet turnover target")
     # penalize instead of transform
     to <- turnover(tmp_weights)
-    out = out + penalty * abs(multiplier) * abs(to - turnover_target)
+    # only penalize if not within +/- 5% of target
+    if((to < turnover_target * 0.95) | (to > turnover_target * 1.05)){
+      # print("transform or penalize to meet turnover target")
+      out = out + penalty * abs(multiplier) * abs(to - turnover_target)
+    }
   }
+  names(tmp_weights) <- names(weights)
   return(list(weights=tmp_weights, out=out))
 }
 
@@ -343,9 +356,24 @@
   tolerance=.Machine$double.eps^0.5
   if(is.null(max_pos)) max_pos <- length(w)
   
+  # 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).
+  tmp_min <- min
+  
+  # If weight_i = 0 and min_i > 0, then this will violate box constraints
+  # even though weight_i = 0 to satisfy position_limit constraints. Modify
+  # the tmp_min vector and set tmp_min_i equal to zero where weights_i = 0.
+  # If w is less than or equal to tolerance then it is essentially 0
+  if(any(abs(w) <= tolerance)){
+    if(any(tmp_min[which(abs(w) <= tolerance)] > 0)){
+      tmp_min[which(abs(w) <= tolerance)] <- -tolerance
+    }
+  }
+  
   # return w if all constraints are satisfied
   if((sum(w) >= min_sum & sum(w) <= max_sum) & 
-       (all(w >= min) & all(w <= max)) & 
+       (all(w >= tmp_min) & all(w <= max)) & 
        (all(!group_fail(weights, groups, cLO, cUP))) &
        (sum(abs(w) > tolerance) <= max_pos)){
     return(w)
@@ -362,11 +390,6 @@
   # create a temporary weights vector that will be modified in the while loops
   tmp_w <- w
   
-  # 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).
-  tmp_min <- min
-  
   # 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) {
     permutations = permutations + 1

Modified: pkg/PortfolioAnalytics/sandbox/testing_fn_map.R
===================================================================
--- pkg/PortfolioAnalytics/sandbox/testing_fn_map.R	2013-07-05 15:26:00 UTC (rev 2504)
+++ pkg/PortfolioAnalytics/sandbox/testing_fn_map.R	2013-07-05 16:54:52 UTC (rev 2505)
@@ -10,20 +10,25 @@
 pspec <- add.constraint(portfolio=pspec, type="box", min=0.05, max=0.65, enabled=T)
 pspec <- add.constraint(portfolio=pspec, type="group", groups=c(2, 2), 
                         group_min=c(0.08, 0.05), group_max=c(0.55, 0.85), enabled=T)
-pspec <- add.constraint(portfolio=pspec, type="turnover", turnover_target=0.4, enabled=T)
-pspec <- add.constraint(portfolio=pspec, type="diversification", div_target=0.6, enabled=T)
-pspec <- add.constraint(portfolio=pspec, type="position_limit", max_pos=3, enabled=F)
+pspec <- add.constraint(portfolio=pspec, type="turnover", turnover_target=0.4, enabled=F)
+pspec <- add.constraint(portfolio=pspec, type="diversification", div_target=0.6, enabled=F)
+pspec <- add.constraint(portfolio=pspec, type="position_limit", max_pos=3, enabled=T)
 portfolio <- pspec
 
 
-# leverage constraints are violated
+# leverage and position_limit constraints are violated
 weights <- c(0.15, 0.25, 0.4, 0.1)
 sum(weights)
 
 fn_map(weights, portfolio)
 
-# box constraints are violated
-weights <- c(0.05, 0.7, 0.1, 0.15)
+# box constraints are violated but postion_limit is already satisfied
+# issue because min vector does not have a zero value and weights[1] = 0
+# all constraints are satisfied so there should be no transformation
+# Is it reasonable to expect the user to have a min vector with zeros when using position_limit constraints? 
+# I try to catch this and modify the tmp_min vector so this does not trigger
+# violation of box constraints
+weights <- c(0, 0.55, 0.3, 0.15)
 sum(weights)
 
 fn_map(weights, portfolio)
@@ -34,4 +39,8 @@
 
 fn_map(weights, portfolio)
 
+# normalize weights from the equal weights seed portfolio
+weights <- portfolio$assets
+sum(weights)
 
+fn_map(weights, portfolio)



More information about the Returnanalytics-commits mailing list