[Returnanalytics-commits] r3358 - pkg/PerformanceAnalytics/sandbox
noreply at r-forge.r-project.org
noreply at r-forge.r-project.org
Wed Apr 9 13:49:30 CEST 2014
Author: peter_carl
Date: 2014-04-09 13:49:29 +0200 (Wed, 09 Apr 2014)
New Revision: 3358
Added:
pkg/PerformanceAnalytics/sandbox/refactored.Portfolio.rebalancing.R
Log:
- incomplete first draft of refactored function
Added: pkg/PerformanceAnalytics/sandbox/refactored.Portfolio.rebalancing.R
===================================================================
--- pkg/PerformanceAnalytics/sandbox/refactored.Portfolio.rebalancing.R (rev 0)
+++ pkg/PerformanceAnalytics/sandbox/refactored.Portfolio.rebalancing.R 2014-04-09 11:49:29 UTC (rev 3358)
@@ -0,0 +1,161 @@
+#' Calculates weighted returns for a portfolio of assets
+#'
+#' Calculates weighted returns for a portfolio of assets.
+#'
+#' \code{Return.rebalancing} uses the date in the weights time series or matrix
+#' for xts-style subsetting of rebalancing periods. Rebalancing periods can be
+#' thought of as taking effect immediately after the close of the bar. So, a
+#' March 31 rebalancing date will actually be in effect for April 1. A
+#' December 31 rebalancing date will be in effect on Jan 1, and so forth. This
+#' convention was chosen because it fits with common usage, and because it
+#' simplifies xts Date subsetting via \code{endpoints}.
+#'
+#' \code{Return.rebalancing} will rebalance only on daily or lower frequencies.
+#' If you are rebalancing intraday, you should be using a trading/prices
+#' framework, not a weights-based return framework.
+#'
+#' @aliases Return.portfolio Return.rebalancing
+#' @param R an xts, vector, matrix, data frame, timeSeries or zoo object of
+#' asset returns
+#' @param beginning_weights a time series or single-row matrix/vector containing asset
+#' weights, as decimal percentages, treated as beginning of next period weights. See Details below.
+#' @param wealth.index TRUE/FALSE whether to return a wealth index, default
+#' FALSE
+#' @param contribution if contribution is TRUE, add the weighted return
+#' contributed by the asset in this period
+#' @param geometric utilize geometric chaining (TRUE) or simple/arithmetic chaining (FALSE) to aggregate returns,
+#' default TRUE
+#' @param \dots any other passthru parameters
+#' @return returns a time series of returns weighted by the \code{weights}
+#' parameter, possibly including contribution for each period
+#' @author Brian G. Peterson
+#' @seealso \code{\link{Return.calculate}} \cr
+#' @references Bacon, C. \emph{Practical Portfolio Performance Measurement and
+#' Attribution}. Wiley. 2004. Chapter 2\cr
+#' @keywords ts multivariate distribution models
+#' @examples
+#'
+#'
+#' data(edhec)
+#' data(weights)
+#'
+#' # calculate an equal weighted portfolio return
+#' round(Return.portfolio(edhec),4)
+#'
+#' # now return the contribution too
+#' round(Return.portfolio(edhec,contribution=TRUE),4)
+#'
+#' # calculate a portfolio return with rebalancing
+#' round(Return.rebalancing(edhec,weights),4)
+#'
+#' @export
+Return.rebalancing2 <- function (R, weights=NA, on=c(NA, 'years', 'quarters', 'months', 'weeks', 'days'), verbose=FALSE, ..., adj.capital=FALSE) {
+ on = on[1]
+ R = checkData(R, method="xts")
+ # find the right unit to subtract from the first return date to create a start date
+ freq = periodicity(R)
+ switch(freq$scale,
+ seconds = { stop("Use a returns series of daily frequency or higher.") },
+ minute = { stop("Use a returns series of daily frequency or higher.") },
+ hourly = { stop("Use a returns series of daily frequency or higher.") },
+ daily = { time_unit = "day" },
+ weekly = { time_unit = "week" },
+ monthly = { time_unit= "month" },
+ quarterly = { time_unit = "quarter" },
+ yearly = { time_unit = "year"}
+ )
+ start_date = seq(as.Date(index(R)[1]), length = 2, by = paste("-1", time_unit))[2]
+
+ if(is.na(weights)){
+ # generate equal weight vector for return columns
+ weights = rep(1/NCOL(R), NCOL(R))
+ }
+ if(is.vector(weights)) { # weights are a vector
+ if(is.na(endpoints)) { # and endpoints are not specified
+ # then use the weights only at the beginning of the returns series, without rebalancing
+ weights = xts(weights, order.by=as.Date(start_date))
+ }
+ else { # and endpoints are specified
+ # generate a time series of the given weights at the endpoints
+ weight_dates = c(as.Date(start_date),time(R[endpoints(R, on=on)]))
+ weights = xts(matrix(rep(1/NCOL(R), length(weight_dates)*NCOL(R)), ncol=NCOL(R)), order.by=weight_dates)
+ }
+ colnames(weights) = colnames(R)
+ }
+ else { # check the beginning_weights object for errors
+ # check that weights are given in a form that is probably a time series
+ weights = checkData(weights, method="xts")
+ # make sure that frequency(weights)<frequency(R) ?
+
+ # make sure the number of assets in R matches the number of assets in weights
+ if(CNOL(R) != NCOL(weights)){
+ if(NCOL(R) > NCOL(weights)){
+ R <- R[, 1:NCOL(weights)]
+ warning("number of assets in beginning_weights is less than number of columns in returns, so subsetting returns.")
+ } else {
+ stop("number of assets is greater than number of columns in returns object")
+ }
+ }
+ } # we should have good weights objects at this point
+
+ leverage = 1
+ # create an empty variables for storage
+ x.leverage = matrix(1, ncol=1)
+ x.starting_weights = NULL
+ x.ending_weights = matrix(NA, ncol=NCOL(weights))
+ x.contributions = matrix(NA, ncol=NCOL(weights))
+ x.portfolio_return = matrix(NA, ncol=1)
+ # loop over rebalance periods
+ start_date=index(weights)[1]
+ for(i in 1:NROW(weights)) {
+ # identify rebalance from and to dates (weights[i,], weights[i+1])
+ from = as.Date(index(weights[i,]))
+ to = as.Date(index(weights[i+1,]))
+ returns = R[paste0(from,"::",to)]
+ # get returns between rebalance dates
+ for(j in 1:NROW(returns)){
+ if(j==1) # if first period of rebalance
+ starting_weights = as.numeric(last(x.leverage,1)) * weights[i,]
+ else
+ starting_weights = last(x.ending_weights,1)
+ contributions = as.vector(starting_weights) * as.vector(returns[j,])
+ ending_weights = contributions + starting_weights # has the wrong date
+ portfolio_return = sum(contributions)
+ if(j==NROW(returns) & adj.capital==FALSE)
+ leverage = sum(last(ending_weights,1))
+ # store results
+ if(is.null(x.starting_weights))
+ x.starting_weights = starting_weights
+ else
+ x.starting_weights = rbind(x.starting_weights, starting_weights)
+# x.contributions = rbind(x.contributions, contributions)
+ if(is.null(x.contributions))
+ x.contributions = contributions
+ else
+ x.contributions = rbind(x.contributions, contributions)
+# x.ending_weights = rbind(x.ending_weights, ending_weights)
+ if(is.null(x.ending_weights))
+ x.ending_weights = ending_weights
+ else
+ x.ending_weights = rbind(x.ending_weights, ending_weights)
+# x.portfolio_return = rbind(x.portfolio_return, portfolio_return)
+ if(is.null(x.portfolio_return))
+ x.portfolio_return = portfolio_return
+ else
+ x.portfolio_return = rbind(x.portfolio_return, portfolio_return)
+# x.leverage = rbind(x.leverage, leverage)
+ if(is.null(x.leverage))
+ x.leverage = leverage
+ else
+ x.leverage = rbind(x.leverage, leverage)
+ }
+
+ # if verbose = TRUE
+ # return list
+ # else
+ # return portfolio_return time series
+ }
+ result=portfolio_returns
+ result<-reclass(result, R)
+ result
+}
\ No newline at end of file
More information about the Returnanalytics-commits
mailing list