[Returnanalytics-commits] r2557 - pkg/PortfolioAnalytics/R
noreply at r-forge.r-project.org
noreply at r-forge.r-project.org
Fri Jul 12 13:42:25 CEST 2013
Author: rossbennett34
Date: 2013-07-12 13:42:25 +0200 (Fri, 12 Jul 2013)
New Revision: 2557
Modified:
pkg/PortfolioAnalytics/R/constrained_objective.R
Log:
added penalty terms to constrained_objective for group, position_limit, turnover, and diversification constraints
Modified: pkg/PortfolioAnalytics/R/constrained_objective.R
===================================================================
--- pkg/PortfolioAnalytics/R/constrained_objective.R 2013-07-12 03:27:32 UTC (rev 2556)
+++ pkg/PortfolioAnalytics/R/constrained_objective.R 2013-07-12 11:42:25 UTC (rev 2557)
@@ -419,10 +419,10 @@
store_output <- try(get('.objectivestorage',pos='.GlobalEnv'), silent=TRUE)
if(inherits(store_output,"try-error")) storage <- FALSE else storage <- TRUE
- # may be replaced by fn_map later
+ # use fn_map to normalize the weights
if(isTRUE(normalize)){
- w <- fn_map(weights=w, portfolio=portfolio)$weights
- # end fn_map transformation
+ w <- fn_map(weights=w, portfolio=portfolio)$weights
+ # end fn_map transformation
} else {
# the user wants the optimization algorithm to figure it out
if(!is.null(constraints$max_sum) & constraints$max_sum != Inf ) {
@@ -438,19 +438,85 @@
# penalize weights outside min and max box constraints (can be caused by normalization)
if (!is.null(constraints$max)){
max <- constraints$max
- out <- out + sum(w[which(w > max[1:N])] - constraints$max[which(w > max[1:N])]) * penalty
+ # Only go to penalty term if any of the weights violate max
+ if(any(w > max)){
+ out <- out + sum(w[which(w > max[1:N])] - constraints$max[which(w > max[1:N])]) * penalty
+ }
}
if (!is.null(constraints$min)){
min <- constraints$min
- out <- out + sum(constraints$min[which(w < min[1:N])] - w[which(w < min[1:N])]) * penalty
+ # Only go to penalty term if any of the weights violate min
+ if(any(w < min)){
+ out <- out + sum(constraints$min[which(w < min[1:N])] - w[which(w < min[1:N])]) * penalty
+ }
}
- # TODO
# penalize weights that violate group constraints
+ if(!is.null(constraints$groups) & !is.null(constraints$cLO) & !is.null(constraints$cUP)){
+ groups <- constraints$groups
+ cLO <- constraints$cLO
+ cUP <- constraints$cUP
+ # Only go to penalty term if group constraint is violated
+ if(any(group_fail(w, groups, cLO, cUP))){
+ ngroups <- length(groups)
+ k <- 1
+ l <- 0
+ for(i in 1:ngroups){
+ j <- groups[i]
+ tmp_w <- w[k:(l+j)]
+ # penalize weights for a given group that sum to less than specified group min
+ grp_min <- cLO[i]
+ if(sum(tmp_w) < grp_min) {
+ out <- out + penalty * (grp_min - sum(tmp_w))
+ }
+ # penalize weights for a given group that sum to greater than specified group max
+ grp_max <- cUP[i]
+ if(sum(tmp_w) > grp_max) {
+ out <- out + penalty * (sum(tmp_w) - grp_max)
+ }
+ k <- k + j
+ l <- k - 1
+ }
+ }
+ } # End group constraint penalty
+
# penalize weights that violate max_pos constraints
+ if(!is.null(constraints$max_pos)){
+ max_pos <- constraints$max_pos
+ tolerance <- .Machine$double.eps^0.5
+ mult <- 1
+ # sum(abs(w) > tolerance) is the number of non-zero assets
+ nzassets <- sum(abs(w) > tolerance)
+ if(nzassets > max_pos){
+ # Do we need a small multiplier term here since (nzassets - max_pos)
+ # will be an integer and much larger than the weight penalty terms
+ out <- out + penalty * mult * (nzassets - max_pos)
+ }
+ } # End position_limit constraint penalty
+
# penalize weights that violate diversification constraint
+ if(!is.null(constraints$div_target)){
+ div_target <- constraints$div_target
+ div <- diversification(w)
+ mult <- 1
+ # only penalize if not within +/- 5% of target
+ if((div < div_target * 0.95) | (div > div_target * 1.05)){
+ out <- out + penalty * mult * abs(div - div_target)
+ }
+ } # End diversification constraint penalty
+
# penalize weights that violate turnover constraint
-
+ if(!is.null(constraints$turnover_target)){
+ turnover_target <- constraints$turnover_target
+ to <- turnover(w)
+ mult <- 1
+ # 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 * mult * abs(to - turnover_target)
+ }
+ } # End turnover constraint penalty
+
nargs <- list(...)
if(length(nargs)==0) nargs <- NULL
if (length('...')==0 | is.null('...')) {
More information about the Returnanalytics-commits
mailing list