[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