[Returnanalytics-commits] r1985 - pkg/PortfolioAnalytics/sandbox/attribution

noreply at r-forge.r-project.org noreply at r-forge.r-project.org
Tue Jun 5 22:38:47 CEST 2012


Author: braverock
Date: 2012-06-05 22:38:47 +0200 (Tue, 05 Jun 2012)
New Revision: 1985

Added:
   pkg/PortfolioAnalytics/sandbox/attribution/logLinking.R
   pkg/PortfolioAnalytics/sandbox/attribution/logLinkingZoo.R
   pkg/PortfolioAnalytics/sandbox/attribution/periodApplyEZ.R
   pkg/PortfolioAnalytics/sandbox/attribution/relativeAttribution.R
   pkg/PortfolioAnalytics/sandbox/attribution/relativeAttributionWithoutFactors.R
Log:
- commit code for linking and attribution contributed by Eric Zivot
- roxygenize code
- TODO move/merge period.apply changes into xts/quantmod

Added: pkg/PortfolioAnalytics/sandbox/attribution/logLinking.R
===================================================================
--- pkg/PortfolioAnalytics/sandbox/attribution/logLinking.R	                        (rev 0)
+++ pkg/PortfolioAnalytics/sandbox/attribution/logLinking.R	2012-06-05 20:38:47 UTC (rev 1985)
@@ -0,0 +1,70 @@
+## logLinking.r
+##
+## purpose: Aggregates performance attribution effects over time to produce a multiperiod summary.
+##
+## authors: Eric Zivot
+## created: June 5, 2012
+
+
+
+
+#' Logarithmic Linking
+#' 
+#' Aggregates performance attribution effects over time to produce a
+#' multiperiod summary.
+#' 
+#' Transforms to a multiperiod arithmetic decomposition by distributing the
+#' residual proportionately. Creates linking coefficients \code{k_t / k} and
+#' applies to given \code{component} to combine arithmetic attribution effects
+#' over time. If \code{weighted.benchmark.returns} is zero for each \code{p}
+#' date, then the function returns absolute arithmetic attribution effect,
+#' e.g., factor returns or idiosyncratic returns from factor model.
+#' 
+#' @param weighted.portfolio.returns \code{n x p} data frame containing asset
+#' ID (as rownames) and weighted portfolio returns for \code{p} dates
+#' @param weighted.benchmark.returns \code{m x p} containing benchmark ID (as
+#' rownames) and weighted benchmark returns for \code{p} dates
+#' @param component data frame containing ID and attribution component for
+#' \code{p} dates (e.g., \code{n x p} for manager selection or \code{m x p}
+#' strategy allocation)
+#' @return Returns a list of two objects of class "\code{numeric}" after
+#' applying the linking coefficient from the logarithmic method: \item{linked}{
+#' combined \code{component} over time } \item{linked.total}{ sum of combined
+#' \code{component} over time }
+#' @author Eric Zivot
+#' @seealso \code{\link{relativeAttribution}}
+#' @references Christopherson, J., Carino, D., and Ferson, W. (2009)
+#' \emph{Portfolio Performance Measurement and Benchmarking}, McGrall-Hill.
+#' @examples
+#' 
+#' 
+#' 
+logLinking <- function(weighted.portfolio.returns, weighted.benchmark.returns, component){
+## inputs
+## weighted.portfolio.returns	n x p data frame containing asset ID (as rownames) and weighted portfolio returns for p dates
+## weighted.benchmark.returns	m x p data frame containing benchmark ID (as rownames) and weighted benchmark returns for p dates
+## component data frame containing ID and attribution component for p dates (e.g., manager selection or strategy allocation)
+## outputs
+## list of combined components over time after applying the linking coefficient from the logarithmic method
+
+require(PerformanceAnalytics)
+
+logCoeff = data.frame((log(1+colSums(weighted.portfolio.returns))
+      - log(1+colSums(weighted.benchmark.returns)))
+      /(colSums(weighted.portfolio.returns) - colSums(weighted.benchmark.returns)),
+      (log(1+Return.cumulative(colSums(weighted.portfolio.returns)))
+      - log(1+Return.cumulative(colSums(weighted.benchmark.returns))))
+      /(Return.cumulative(colSums(weighted.portfolio.returns)) - Return.cumulative(colSums(weighted.benchmark.returns))))
+colnames(logCoeff) = c("k_t","K")
+logCoeff = data.frame(logCoeff, logCoeff$k_t/logCoeff$K)
+colnames(logCoeff) = c("k_t","K","B")
+
+linked = data.frame(component)
+for(i in 1:nrow(logCoeff)){
+      linked[,i] = as.matrix(component[,i])%*%logCoeff$B[i]
+}
+
+ans = list("linked" = rowSums(linked),
+            "linked.total" = sum(rowSums(linked)))
+return(ans)
+}

Added: pkg/PortfolioAnalytics/sandbox/attribution/logLinkingZoo.R
===================================================================
--- pkg/PortfolioAnalytics/sandbox/attribution/logLinkingZoo.R	                        (rev 0)
+++ pkg/PortfolioAnalytics/sandbox/attribution/logLinkingZoo.R	2012-06-05 20:38:47 UTC (rev 1985)
@@ -0,0 +1,82 @@
+# logLinkingZoo.r
+#
+# purpose: function to be passed to rollApplyEZ() for carino linking over
+#          user-specified attribution dates and aggregation periods
+#
+## authors: Eric Zivot 
+## created: June 5, 2012
+
+
+#' Log-linking Function For Use In rollApplyEZ
+#' 
+#' Function to be passed to rollApplyEZ() for carino linking over
+#' user-specified attribution dates and aggregation periods
+#' 
+#' %% ~~ If necessary, more details than the description above ~~
+#' 
+#' @param x \code{zoo} object containing data to be aggregated.
+#' @param asset.names Character vector of asset IDs
+#' @param strategy.names Character vector of strategy abbreviations
+#' @param component.names Character vector of component names. If
+#' \code{component.type="manager"} then \code{component.names} are asset IDs;
+#' if \code{component.type="strategy"} then \code{component.names} are strategy
+#' abbreviations.if \code{component.type="factor"} then \code{component.names}
+#' are factor IDs.
+#' @param component.type character string indicating type of attribution. Valid
+#' choices are \code{"manager"} for manager selection attribution;
+#' \code{"strategy"} for strategy allocation attribution; \code{"factor"} for
+#' factor attribution.
+#' @param return.out character string indicating output from log-linking
+#' function. Valid choices are \code{"linked"} for disaggregated results, and
+#' \code{"linked.total"} for total results.
+#' @return A numeric vector of attribution values with the same length as
+#' \code{component.names} if \code{return.out="linked"} or a numeric value
+#' giving total attribution if \code{return.out = "linked.total"}.
+#' @author Eric Zivot.
+#' @seealso \code{\link{logLinking}}
+#' @examples
+#' 
+#' ##---- Should be DIRECTLY executable !! ----
+#' ##-- ==>  Define data, use random,
+#' ##--	or do  help(data=index)  for the standard data sets.
+#' 
+#' 
+#' 
+logLinking.zoo <- function(x, asset.names, strategy.names,
+                           component.names, component.type = c("manager", "strategy", "factor"),
+                           return.out = c("linked", "linked.total")) {
+# Arguments
+# x               zoo object containing data to be aggregated.
+# asset.names     character vector of asset IDs
+# strategy.names  character vector of strategy abbreviations
+# component.names character vector of component names. If component.type="manager"
+#                 then component.names are asset IDs; if component.type="strategy"
+#                 then component.names are strategy abbreviations.
+# component.type  character string indicating type of attribution. Valid choices
+#                 are "manager" for manager selection attribution, and "strategy"
+#                 for strategy allocation attribution.
+# return.out      character string indicating output from log-linking function.
+#                 Valid choices are "linked" for disaggregated results, and "linked.total"
+#                 for total results.
+# Details
+# Value
+# A numeric vector of attribution values with the same length as component.names
+# if return.out="linked" or a numeric value giving total attribution if
+# return.out = "linked.total"
+  return.out = return.out[1]
+  component.type = component.type[1]
+  weighted.portfolio.returns = t(coredata(x[,asset.names,drop=FALSE]))
+  weighted.benchmark.returns = t(coredata(x[, strategy.names, drop=FALSE]))
+  component = t(coredata(x[, component.names, drop=FALSE]))
+  if (component.type == "manager") {
+    rownames(component) = asset.names
+  } else if (component.type == "strategy") {
+    rownames(component) = strategy.names
+  } else {
+    rownames(component) = component.names
+  }
+  carinoLinking = logLinking(weighted.portfolio.returns,
+                             weighted.benchmark.returns,
+                             component)
+  return(carinoLinking[[return.out]])
+}

Added: pkg/PortfolioAnalytics/sandbox/attribution/periodApplyEZ.R
===================================================================
--- pkg/PortfolioAnalytics/sandbox/attribution/periodApplyEZ.R	                        (rev 0)
+++ pkg/PortfolioAnalytics/sandbox/attribution/periodApplyEZ.R	2012-06-05 20:38:47 UTC (rev 1985)
@@ -0,0 +1,72 @@
+# periodApplyEZ.r
+#
+# purpose: Modified version of period.apply() to work with logLinking.zoo()
+#
+## authors: Eric Zivot
+## created: August 3, 2011
+## modified: August 3, 2011
+
+
+#' Apply Function Over Specified Interval
+#' 
+#' Modified version of period.apply() from package xts to work with
+#' logLinking.zoo
+#' 
+#' Similar to the rest of the apply family, calculate a specified functions
+#' value given a shifting set of data values. The primary difference is that it
+#' is that \code{period.apply.EZ} applies a function to non-overlapping
+#' intervals along a vector. This is a modified of the function
+#' \code{period.apply} in package xts. The modification allows the output to be
+#' either a vector with length of \code{INDEX} minus 1 or a matrix with number
+#' of rows length of \code{INDEX} minus 1. Useful for applying arbitrary
+#' functions over an entire data object by an aribirtary index, as when
+#' \code{INDEX} is the result of a call to \code{endpoints}.
+#' 
+#' 
+#' @param x data to apply \code{FUN} to
+#' @param INDEX numeric vector specifying indexing
+#' @param FUN an argument of type \code{function}
+#' @param \dots additional arguments for \code{FUN}
+#' @return A vector with length of INDEX minus 1 or a matrix with number of
+#' rows length of INDEX minus 1.
+#' @author Original code by Jeff Ryan. Modified by Eric Zivot.
+#' @seealso %% ~~objects to See Also as \code{\link{help}}, ~~~
+#' @examples
+#' 
+#' 
+period.apply.EZ <- function (x, INDEX, FUN, ...)
+{
+# TODO Brian should merge/move this into xts/quantmod.
+# Agruments
+# x       data to apply FUN to
+# INDEX   numeric vector specifying indexing
+# FUN     an argument of type function
+# ...     additional arguments for FUN
+# Details
+# Similar to the rest of the apply family, calculate a specified functions value
+# given a shifting set of data values. The primary difference is that it is that
+# period.apply applies a function to non-overlapping intervals along a vector.
+# This is a modified of the function period.apply in package xts. The modification
+# allows the output to be either a vector with length of INDEX minus 1 or a matrix
+# with number of rows length of INDEX minus 1.
+#
+# Useful for applying arbitrary functions over an entire data object by an
+# aribirtary index, as when INDEX is the result of a call to endpoints.
+#
+# Value
+# A vector with length of INDEX minus 1 or a matrix with number of rows length
+# of INDEX minus 1.
+    require(xts)
+    x <- try.xts(x, error = FALSE)
+    FUN <- match.fun(FUN)
+    xx <- sapply(1:(length(INDEX) - 1), function(y) {
+        FUN(x[(INDEX[y] + 1):INDEX[y + 1]], ...)
+    })
+    ## ghetto rigging to work with logLinking.zoo(). Allows output to be either
+    ## a vector or a matrix. period.apply() only gives vector result
+    if (is.matrix(xx)) {
+      reclass(t(xx), x[INDEX])
+    } else {
+      reclass(xx, x[INDEX])
+    }
+}

Added: pkg/PortfolioAnalytics/sandbox/attribution/relativeAttribution.R
===================================================================
--- pkg/PortfolioAnalytics/sandbox/attribution/relativeAttribution.R	                        (rev 0)
+++ pkg/PortfolioAnalytics/sandbox/attribution/relativeAttribution.R	2012-06-05 20:38:47 UTC (rev 1985)
@@ -0,0 +1,152 @@
+## relativeAttribution.r
+##
+## purpose: Decompose relative portfolio returns into manager selection and
+##          strategy allocation components incorporating factor contributions
+##
+## authors: Eric Zivot
+## created: June 5, 2012
+##
+
+
+#' Relative Performance Attribution
+#' 
+#' Decompose relative returns into manager selection and strategy allocation
+#' components, and then into factor and idiosyncratic return contributions.
+#' 
+#' The Brinson model reflects a sector-based investment process and attributes
+#' portfolio return to manager selection and strategy allocation effects.
+#' Positive contributions are earned by overweighting outperforming
+#' managers/sectors and underweighting underperformers. In addition, the
+#' manager selection and strategy allocation effects are decomposed into factor
+#' and idiosyncratic return contributions as defined by a factor model.
+#' 
+#' @param portfolio.df \code{n x (3 + f)} data frame containing asset ID (as
+#' rownames), Strategy \code{n x 1}, Weight \code{n x 1}, Return \code{n x 1},
+#' exposure-weighted factor returns \code{n x f} whose column names are the
+#' factor IDs
+#' @param benchmark.df \code{m x (3 + f)} data frame containing benchmark ID
+#' (as rownames), Strategy \code{n x 1}, Weights \code{n x 1}, Returns \code{n
+#' x 1}, exposure-weighted factor returns \code{n x f} whose column names are
+#' factor IDs.
+#' @return Returns a list with the following components: \item{portfolio.ret}{
+#' \code{1 x 1} matrix containing portfolio return} \item{benchmark.ret}{
+#' \code{1 x 1} matrix containing benchmark return} \item{relative.ret}{
+#' \code{1 x 1} matrix containing relative return} \item{manager}{ \code{n x 1}
+#' data frame containing asset ID (as rownames) and \code{ManagerSelection} }
+#' \item{manager.total}{ numeric value of total \code{ManagerSelection}
+#' component} \item{manager.factor}{ \code{n x (1 + f)} data frame containing
+#' asset ID (as rownames) and ManagerSelection by \code{Idiosyncratic} \code{n
+#' x 1} and factor IDs \code{n x f}} \item{manager.factor.total}{ \code{n x 1}
+#' numeric object with asset ID (as rownames) and ManagerSelection component
+#' summed over all factor IDs} \item{manager.idiosyncratic.total}{ numeric
+#' value of ManagerSelection component summed over all Idiosyncratic values}
+#' \item{strategy}{ \code{n x 2} data frame containing benchmark ID (as
+#' rownames), \code{Strategy}, and \code{StrategyAllocation} }
+#' \item{strategy.total}{ numeric value of total StrategyAllocation component}
+#' \item{strategy.factor}{ \code{m x (1 + f)} data frame containing benchmark
+#' ID (as rownames) and StrategyAllocation by \code{Idiosyncratic} \code{m x 1}
+#' and factor IDs \code{m x f}} \item{strategy.factor.total}{ \code{m x 1}
+#' numeric object with benchmark ID (as rownames) and StrategyAllocation
+#' component summed over all factor IDs} \item{strategy.idiosyncratic.total}{
+#' numeric value of StrategyAllocation component summed over all Idiosyncratic
+#' values}
+#' @author Eric Zivot
+#' @seealso \code{\link{logLinking}}
+#' @references Davis, B. and Menchero, J. (2009) \emph{Beyond Brinson:
+#' Establishing the Link Between Sector and Factor Models}, MSCI Barra Research
+#' Insights.
+#' @examples
+#' 
+#' 
+#' 
+relativeAttribution <- function(portfolio.df, benchmark.df){
+## 
+## inputs:
+## portfolio.df	n x (3 + f) data frame containing asset ID (as rownames),
+##                          Strategy (n x 1), Weight (n x 1), Return (n x 1),
+##                          exposure-weighted factor returns (n x f) whose column
+##                          names are the factor IDs
+## benchmark.df	m x (3 + f) data frame containing benchmark ID (as rownames),
+##                          Strategy (n x 1), Weights (n x 1), Return (n x 1),
+##                          exposure-weighted factor returns (n x f) whose column
+##                          names are factor IDs.
+## 
+## outputs:
+## list with the following components:
+##  
+## portfolio.ret, matrix containing portfolio return
+## benchmark.ret, matrix containing benchmark return
+## relative.ret, matrix containing relative return
+## manager, data frame containing class ID (as rownames) and ManagerSelection
+## manager.total, numeric value of total ManagerSelection component
+## manager.factor, data frame containing class ID (as rownames) and ManagerSelection by Idiosyncratic and factor IDs
+## manager.factor.total, numeric object with class ID (as rownames) and ManagerSelection component summed over all factor IDs
+## manager.idiosyncratic.total, numeric value of ManagerSelection component summed over all Idiosyncratic values  
+## strategy, data frame containing benchmark ID (as rownames), Strategy, and StrategyAllocation
+## strategy.total, numeric value of total StrategyAllocation component
+## strategy.factor, data frame containing benchmark ID (as rownames) and StrategyAllocation by Idiosyncratic and factor IDs
+## strategy.factor.total, numeric object with benchmark ID (as rownames) and StrategyAllocation component summed over all factors IDs
+## strategy.idiosyncratic.total, numeric value of StrategyAllocation component summed over all Idiosyncratic values
+##
+require(plyr)
+
+## Compute benchmark, portfolio, and returns
+portfolio.ret = crossprod(portfolio.df$Weight, portfolio.df$Return)
+benchmark.ret = crossprod(benchmark.df$Weight, benchmark.df$Return)
+relative.ret = portfolio.ret - benchmark.ret
+
+## x is portfolio.df, y is benchmark.df
+colnames(benchmark.df) = paste(colnames(benchmark.df), ".y", sep="")
+colnames(benchmark.df)[1] = "Strategy"
+temp = join(portfolio.df,  benchmark.df, by = "Strategy")
+
+## Active returns by manager selection
+manager = data.frame(temp$Weight * (temp$Return  - temp$Return.y), row.names = rownames(temp))
+colnames(manager) = c("ManagerSelection")
+
+## Store factor names
+factor.names = colnames(portfolio.df[4:ncol(portfolio.df)])
+factor.names.y = paste(factor.names, ".y", sep="")
+
+## Manager selection by factor and idiosyncratic returns
+manager.factor = data.frame((temp$Return-rowSums(temp[,factor.names]) - (temp$Return.y-rowSums(temp[,factor.names.y])))*temp$Weight,
+                    (temp[,factor.names] - temp[,factor.names.y]) * temp$Weight)
+colnames(manager.factor) = c("Idiosyncratic", factor.names)
+
+## Active returns by strategy allocation
+strategy = data.frame(benchmark.df$Strategy, row.names = rownames(benchmark.df))
+colnames(strategy) = c("Strategy")
+for(i in 1:nrow(strategy)){
+      strategy$ActiveWeight[i] = sum(portfolio.df$Weight[portfolio.df$Strategy == strategy$Strategy[i]]) - benchmark.df$Weight[i]
+}
+strategy = data.frame(strategy, strategy$ActiveWeight * (benchmark.df$Return - benchmark.df$Weight%*%benchmark.df$Return))
+
+## Strategy allocation by factor and idiosyncratic returns
+tmp.mat = matrix(0, nrow(strategy), ncol(benchmark.df)-1)
+colnames(tmp.mat) = c("Strategy", "Idiosyncratic", factor.names)
+rownames(tmp.mat) = rownames(benchmark.df)
+strategy.factor = as.data.frame(tmp.mat)
+strategy.factor$Strategy = benchmark.df$Strategy
+strategy.factor$Idiosyncratic = (benchmark.df$Return - rowSums(benchmark.df[,factor.names.y]) - sum((benchmark.df$Return - rowSums(benchmark.df[,factor.names.y])) * benchmark.df$Weight)) * strategy$ActiveWeight
+for(i in 1:nrow(strategy)){
+      strategy.factor[i,factor.names] = colSums(benchmark.df[,factor.names.y] * benchmark.df$Weight)
+}
+strategy.factor[,factor.names] = (benchmark.df[,factor.names.y] - strategy.factor[,factor.names]) * strategy$ActiveWeight
+colnames(strategy) = c("Strategy", "ActiveWeight", "StrategyAllocation")
+
+ans = list("manager" = manager, 
+           "strategy" = strategy[,c("Strategy","StrategyAllocation")],
+           "strategy.active.weight" = strategy[,c("Strategy","ActiveWeight")],
+           "manager.factor" = manager.factor,
+           "strategy.factor" = strategy.factor,
+           "manager.factor.total" = rowSums(manager.factor[,factor.names]),
+           "manager.idiosyncratic.total" = sum(manager.factor$Idiosyncratic),
+           "strategy.factor.total" = rowSums(strategy.factor[,factor.names]),
+           "strategy.idiosyncratic.total" = sum(strategy.factor$Idiosyncratic),
+           "manager.total" = sum(manager$ManagerSelection),
+           "strategy.total" = sum(strategy$StrategyAllocation),
+           "portfolio.ret" = portfolio.ret,
+           "benchmark.ret" = benchmark.ret,
+           "relative.ret" = relative.ret)
+return(ans)
+}

Added: pkg/PortfolioAnalytics/sandbox/attribution/relativeAttributionWithoutFactors.R
===================================================================
--- pkg/PortfolioAnalytics/sandbox/attribution/relativeAttributionWithoutFactors.R	                        (rev 0)
+++ pkg/PortfolioAnalytics/sandbox/attribution/relativeAttributionWithoutFactors.R	2012-06-05 20:38:47 UTC (rev 1985)
@@ -0,0 +1,88 @@
+## relativeAttributionWithoutFactors.r
+##
+## purpose: Decompose relative portfolio returns into manager selection and
+##          strategy allocation components
+##
+## authors: Eric Zivot
+## created: June 5, 2012
+##
+
+
+#' Relative Performance Attribution
+#' 
+#' Decompose relative returns into manager selection and strategy allocation
+#' components.
+#' 
+#' The Brinson model reflects a sector-based investment process and attributes
+#' portfolio return to manager selection and strategy allocation effects.
+#' Positive contributions are earned by overweighting outperforming
+#' managers/sectors and underweighting underperformers.
+#' 
+#' @param portfolio.df \code{n x 3} data frame containing asset ID (as
+#' rownames), Strategy \code{n x 1}, Weight \code{n x 1}, Return \code{n x 1},
+#' @param benchmark.df \code{m x 3} data frame containing benchmark ID (as
+#' rownames), Strategy \code{n x 1}, Weights \code{n x 1}, Returns \code{n x
+#' 1},
+#' @return Returns a list with the following components: \item{portfolio.ret}{
+#' \code{1 x 1} matrix containing portfolio return} \item{benchmark.ret}{
+#' \code{1 x 1} matrix containing benchmark return} \item{relative.ret}{
+#' \code{1 x 1} matrix containing relative return} \item{manager}{ \code{n x 1}
+#' data frame containing asset ID (as rownames) and \code{ManagerSelection} }
+#' \item{manager.total}{ numeric value of total \code{ManagerSelection}
+#' component} \item{strategy}{ \code{n x 2} data frame containing benchmark ID
+#' (as rownames), \code{Strategy}, and \code{StrategyAllocation} }
+#' \item{strategy.total}{ numeric value of total StrategyAllocation component}
+#' @author Eric Zivot
+#' @seealso \code{\link{logLinking}}
+#' @references Davis, B. and Menchero, J. (2009) \emph{Beyond Brinson:
+#' Establishing the Link Between Sector and Factor Models}, MSCI Barra Research
+#' Insights.
+#' @examples
+#' 
+#' 
+#' 
+relativeAttributionWithoutFactors <- function(portfolio.df, benchmark.df){
+## 
+## inputs:
+## portfolio.df	n x 3 data frame containing asset ID (as rownames), strategy, weights, returns
+## benchmark.df	m x 3 data frame containing benchmark ID (as rownames), strategy, weights, returns
+## 
+## outputs:
+## list with the following components:
+##  manager, dataframe giving active returns by manager selection
+##  strategy, dataframe giving active returns by strategy allocation
+##
+require(plyr)
+
+## x is portfolio.df, y is benchmark.df
+temp = join(portfolio.df, benchmark.df, by = "Strategy")
+colnames(temp) = c("Strategy", "Weight.x", "Return.x", "Weight.y", "Return.y")
+
+## Active returns by manager selection
+manager = data.frame(temp$Weight.x * (temp$Return.x  - temp$Return.y), row.names = rownames(temp))
+colnames(manager) = c("ManagerSelection")
+
+## Active returns by strategy allocation
+strategy = data.frame(benchmark.df$Strategy, row.names = rownames(benchmark.df))
+colnames(strategy) = c("Strategy")
+for(i in 1:nrow(strategy)){
+      strategy$ActiveWeight[i] = sum(portfolio.df$Weight[portfolio.df$Strategy == strategy$Strategy[i]]) - benchmark.df$Weight[i]
+}
+strategy = data.frame(strategy, strategy$ActiveWeight * (benchmark.df$Return - benchmark.df$Weight%*%benchmark.df$Return))
+strategy$ActiveWeight = NULL
+colnames(strategy) = c("Strategy", "StrategyAllocation")
+
+# compute benchmark, portfolio and returns
+portfolio.ret = crossprod(portfolio.df$Weight, portfolio.df$Return)
+benchmark.ret = crossprod(benchmark.df$Weight, benchmark.df$Return)
+relative.ret = portfolio.ret - benchmark.ret
+
+ans = list("manager" = manager, 
+           "strategy" = strategy,
+           "manager.total" = sum(manager$ManagerSelection),
+           "strategy.total" = sum(strategy$StrategyAllocation),
+           "portfolio.ret" = portfolio.ret,
+           "benchmark.ret" = benchmark.ret,
+           "relative.ret" = relative.ret)
+return(ans)
+}



More information about the Returnanalytics-commits mailing list