[Returnanalytics-commits] r2587 - in pkg/PortfolioAnalytics: R man
noreply at r-forge.r-project.org
noreply at r-forge.r-project.org
Wed Jul 17 13:49:19 CEST 2013
Author: rossbennett34
Date: 2013-07-17 13:49:18 +0200 (Wed, 17 Jul 2013)
New Revision: 2587
Modified:
pkg/PortfolioAnalytics/R/constraint_fn_map.R
pkg/PortfolioAnalytics/man/rp_transform.Rd
Log:
modifying rp_transform and fn_map to take group_pos
Modified: pkg/PortfolioAnalytics/R/constraint_fn_map.R
===================================================================
--- pkg/PortfolioAnalytics/R/constraint_fn_map.R 2013-07-17 09:40:59 UTC (rev 2586)
+++ pkg/PortfolioAnalytics/R/constraint_fn_map.R 2013-07-17 11:49:18 UTC (rev 2587)
@@ -54,6 +54,7 @@
groups <- constraints$groups
cLO <- constraints$cLO
cUP <- constraints$cUP
+ group_pos <- constraints$group_pos
div_target <- constraints$div_target
turnover_target <- constraints$turnover_target
max_pos <- constraints$max_pos
@@ -77,7 +78,7 @@
if(!is.null(min_sum) & !is.null(max_sum)){
if(!(sum(tmp_weights) >= min_sum & sum(tmp_weights) <= max_sum)){
# Try to transform only considering leverage and box constraints
- tmp_weights <- try(rp_transform(tmp_weights, min_sum, max_sum, min, max, groups=NULL, cLO=NULL, cUP=NULL, max_pos=NULL, 500), silent=TRUE)
+ tmp_weights <- try(rp_transform(tmp_weights, min_sum, max_sum, min, max, groups=NULL, cLO=NULL, cUP=NULL, max_pos=NULL, group_pos=NULL, 500), silent=TRUE)
if(inherits(tmp_weights, "try-error")){
# Default to initial weights
tmp_weights <- weights
@@ -89,7 +90,7 @@
if(!is.null(tmp_min) & !is.null(tmp_max)){
if(!(all(tmp_weights >= tmp_min) & all(tmp_weights <= tmp_max))){
# Try to transform only considering leverage and box constraints
- tmp_weights <- try(rp_transform(tmp_weights, min_sum, max_sum, tmp_min, tmp_max, groups=NULL, cLO=NULL, cUP=NULL, max_pos=NULL, 500), silent=TRUE)
+ tmp_weights <- try(rp_transform(tmp_weights, min_sum, max_sum, tmp_min, tmp_max, groups=NULL, cLO=NULL, cUP=NULL, max_pos=NULL, group_pos=NULL, 500), silent=TRUE)
if(inherits(tmp_weights, "try-error")){
# Default to initial weights
tmp_weights <- weights
@@ -111,7 +112,7 @@
}
# Now try the transformation again
- tmp_weights <- try(rp_transform(tmp_weights, min_sum, max_sum, tmp_min, tmp_max, groups=NULL, cLO=NULL, cUP=NULL, max_pos=NULL, 500), silent=TRUE)
+ tmp_weights <- try(rp_transform(tmp_weights, min_sum, max_sum, tmp_min, tmp_max, groups=NULL, cLO=NULL, cUP=NULL, max_pos=NULL, group_pos, 500), silent=TRUE)
# Default to original weights if this fails again
if(inherits(tmp_weights, "try-error")) tmp_weights <- weights
i <- i + 1
@@ -130,9 +131,9 @@
# check group constraints
if(!is.null(groups) & !is.null(tmp_cLO) & !is.null(tmp_cUP)){
- if(any(group_fail(tmp_weights, groups, tmp_cLO, tmp_cUP))){
+ if(any(group_fail(tmp_weights, groups, tmp_cLO, tmp_cUP, group_pos))){
# Try to transform only considering leverage, box, and group constraints
- tmp_weights <- try(rp_transform(tmp_weights, min_sum, max_sum, tmp_min, tmp_max, groups, tmp_cLO, tmp_cUP, max_pos=NULL, 500), silent=TRUE)
+ tmp_weights <- try(rp_transform(tmp_weights, min_sum, max_sum, tmp_min, tmp_max, groups, tmp_cLO, tmp_cUP, max_pos=NULL, group_pos, 500), silent=TRUE)
if(inherits(tmp_weights, "try-error")){
# Default to initial weights
tmp_weights <- weights
@@ -141,8 +142,8 @@
i <- 1
# loop while constraints are violated and relax constraints
# Try to relax constraints up to 5 times
- while(((sum(tmp_weights) < min_sum | sum(tmp_weights) > max_sum) | (any(tmp_weights < tmp_min) | any(tmp_weights > tmp_max)) | any(group_fail(tmp_weights, groups, tmp_cLO, tmp_cUP))) & i <= 5){
- if(any(group_fail(tmp_weights, groups, tmp_cLO, tmp_cUP))){
+ while(((sum(tmp_weights) < min_sum | sum(tmp_weights) > max_sum) | (any(tmp_weights < tmp_min) | any(tmp_weights > tmp_max)) | any(group_fail(tmp_weights, groups, tmp_cLO, tmp_cUP, group_pos))) & i <= 5){
+ if(any(group_fail(tmp_weights, groups, tmp_cLO, tmp_cUP, group_pos))){
# I know which group failed, but not if it was cUP or cLO that was violated
# Maybe I can modify group_fail to report back what was violated and only relax cLO or cUP, not both
# This relaxes both cLO and cUP
@@ -150,7 +151,7 @@
tmp_cUP[group_fail(tmp_weights, groups, tmp_cLO, tmp_cUP)] <- tmp_cUP[group_fail(tmp_weights, groups, tmp_cLO, tmp_cUP)] + runif(1, 0.01, 0.05)
}
# Now try the transformation again
- tmp_weights <- try(rp_transform(tmp_weights, min_sum, max_sum, tmp_min, tmp_max, groups, tmp_cLO, tmp_cUP, max_pos=NULL, 500), silent=TRUE)
+ tmp_weights <- try(rp_transform(tmp_weights, min_sum, max_sum, tmp_min, tmp_max, groups, tmp_cLO, tmp_cUP, max_pos=NULL, group_pos, 500), silent=TRUE)
if(inherits(tmp_weights, "try-error")) tmp_weights <- weights
i <- i + 1
}
@@ -170,7 +171,7 @@
if(!is.null(tmp_max_pos)){
if(!(sum(abs(tmp_weights) > tolerance) <= tmp_max_pos)){
# Try to transform only considering leverage, box, group, and position_limit constraints
- tmp_weights <- try(rp_transform(tmp_weights, min_sum, max_sum, tmp_min, tmp_max, groups, tmp_cLO, tmp_cUP, tmp_max_pos, 500), silent=TRUE)
+ tmp_weights <- try(rp_transform(tmp_weights, min_sum, max_sum, tmp_min, tmp_max, groups, tmp_cLO, tmp_cUP, tmp_max_pos, group_pos, 500), silent=TRUE)
if(inherits(tmp_weights, "try-error")){
# Default to initial weights
tmp_weights <- weights
@@ -180,7 +181,7 @@
# increment tmp_max_pos by 1
tmp_max_pos <- tmp_max_pos + 1
# Now try the transformation again
- tmp_weights <- try(rp_transform(tmp_weights, min_sum, max_sum, tmp_min, tmp_max, groups, tmp_cLO, tmp_cUP, tmp_max_pos, 500), silent=TRUE)
+ tmp_weights <- try(rp_transform(tmp_weights, min_sum, max_sum, tmp_min, tmp_max, groups, tmp_cLO, tmp_cUP, tmp_max_pos, group_pos, 500), silent=TRUE)
if(inherits(tmp_weights, "try-error")) tmp_weights <- weights
i <- i + 1
}
@@ -321,11 +322,12 @@
#' @param cLO numeric or vector specifying minimum weight group constraints
#' @param cUP numeric or vector specifying minimum weight group constraints
#' @param max_pos maximum assets with non-zero weights
+#' @param group_pos vector specifying maximum number assets with non-zero weights per group
#' @param max_permutations integer: maximum number of iterations to try for a valid portfolio, default 200
#' @return named weighting vector
#' @author Peter Carl, Brian G. Peterson, Ross Bennett (based on an idea by Pat Burns)
#' @export
-rp_transform <- function(w, min_sum=0.99, max_sum=1.01, min, max, groups, cLO, cUP, max_pos=NULL, max_permutations=200){
+rp_transform <- function(w, min_sum=0.99, max_sum=1.01, min, max, groups, cLO, cUP, max_pos=NULL, group_pos=NULL, max_permutations=200){
# Uses logic from randomize_portfolio to "normalize" a weights vector to
# satisfy min_sum and max_sum while accounting for box and group constraints
# Modified from randomize_portfolio to trigger the while loops if any weights
@@ -336,6 +338,9 @@
tolerance=.Machine$double.eps^0.5
if(is.null(max_pos)) max_pos <- length(w)
+ if(!is.null(group_pos)) max_group_pos <- sum(group_pos)
+ max_assets <- min(max_pos, max_group_pos)
+
# 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).
@@ -354,7 +359,7 @@
# return w if all constraints are satisfied
if((sum(w) >= min_sum & sum(w) <= max_sum) &
(all(w >= tmp_min) & all(w <= max)) &
- (all(!group_fail(w, groups, cLO, cUP))) &
+ (all(!group_fail(w, groups, cLO, cUP, group_pos))) &
(sum(abs(w) > tolerance) <= max_pos)){
return(w)
}
@@ -362,7 +367,7 @@
# generate a sequence of weights based on min/max box constraints
weight_seq <- generatesequence(min=min(min), max=max(max), by=0.005)
# make sure there is a 0 in weight_seq
- if(!is.null(max_pos) & !is.element(0, weight_seq)) weight_seq <- c(0, weight_seq)
+ if((!is.null(max_pos) | !is.null(group_pos)) & !is.element(0, weight_seq)) weight_seq <- c(0, weight_seq)
# start the permutations counter
permutations <- 1
@@ -371,7 +376,7 @@
tmp_w <- w
# 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) {
+ 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, group_pos)) | (sum(abs(tmp_w) > tolerance) > max_pos)) & permutations <= max_permutations) {
permutations = permutations + 1
# check our box constraints on total portfolio weight
# reduce(increase) total portfolio size till you get a match
@@ -383,7 +388,7 @@
tmp_w <- w
tmp_min <- min
- random_index <- sample(1:length(tmp_w), max_pos)
+ random_index <- sample(1:length(tmp_w), max_assets)
# Get the index values that are not in random_index and set them equal to 0
full_index <- 1:length(tmp_w)
@@ -396,7 +401,7 @@
i = 1
# while sum of weights is less than min_sum or tmp_min/max box or group constraint is violated
- while ((sum(tmp_w) <= min_sum | any(tmp_w < tmp_min) | any(tmp_w > max) | any(group_fail(tmp_w, groups, cLO, cUP))) & i <= length(tmp_w)) {
+ while ((sum(tmp_w) <= min_sum | any(tmp_w < tmp_min) | any(tmp_w > max) | any(group_fail(tmp_w, groups, cLO, cUP, group_pos))) & i <= length(tmp_w)) {
# randomly permute and increase a random portfolio element
cur_index <- random_index[i]
cur_val <- tmp_w[cur_index]
@@ -415,7 +420,7 @@
# group_fail does not test for direction of violation, just that group constraints were violated
i = 1
# while sum of weights is greater than max_sum or tmp_min/max box or group constraint is violated
- while ((sum(tmp_w) >= max_sum | any(tmp_w < tmp_min) | any(tmp_w > max) | any(group_fail(tmp_w, groups, cLO, cUP))) & i <= length(tmp_w)) {
+ while ((sum(tmp_w) >= max_sum | any(tmp_w < tmp_min) | any(tmp_w > max) | any(group_fail(tmp_w, groups, cLO, cUP, group_pos))) & i <= length(tmp_w)) {
# randomly permute and decrease a random portfolio element
cur_index <- random_index[i]
cur_val <- tmp_w[cur_index]
@@ -489,7 +494,7 @@
grp.max <- cUP[i]
grp.pos <- group_pos[i]
# return TRUE if grp.min or grp.max is violated
- group_fail[i] <- ( sum(tmp.w) < grp.min | sum(tmp.w) > grp.max (sum(abs(tmp.w) > tolerance) > grp.pos))
+ group_fail[i] <- ( sum(tmp.w) < grp.min | sum(tmp.w) > grp.max | (sum(abs(tmp.w) > tolerance) > grp.pos))
k <- k + j
l <- k - 1
}
Modified: pkg/PortfolioAnalytics/man/rp_transform.Rd
===================================================================
--- pkg/PortfolioAnalytics/man/rp_transform.Rd 2013-07-17 09:40:59 UTC (rev 2586)
+++ pkg/PortfolioAnalytics/man/rp_transform.Rd 2013-07-17 11:49:18 UTC (rev 2587)
@@ -3,7 +3,7 @@
\title{Transform a weights vector to satisfy leverage, box, group, and position_limit constraints using logic from \code{randomize_portfolio}}
\usage{
rp_transform(w, min_sum = 0.99, max_sum = 1.01, min, max,
- groups, cLO, cUP, max_pos = NULL,
+ groups, cLO, cUP, max_pos = NULL, group_pos = NULL,
max_permutations = 200)
}
\arguments{
@@ -31,6 +31,9 @@
\item{max_pos}{maximum assets with non-zero weights}
+ \item{group_pos}{vector specifying maximum number assets
+ with non-zero weights per group}
+
\item{max_permutations}{integer: maximum number of
iterations to try for a valid portfolio, default 200}
}
More information about the Returnanalytics-commits
mailing list