[Returnanalytics-commits] r2032 - pkg/PortfolioAnalytics/sandbox/attribution/R
noreply at r-forge.r-project.org
noreply at r-forge.r-project.org
Mon Jun 18 18:55:19 CEST 2012
Author: ababii
Date: 2012-06-18 18:55:18 +0200 (Mon, 18 Jun 2012)
New Revision: 2032
Modified:
pkg/PortfolioAnalytics/sandbox/attribution/R/attribution.R
Log:
- fixed bug with total attribution effects in the output (excess returns)
Modified: pkg/PortfolioAnalytics/sandbox/attribution/R/attribution.R
===================================================================
--- pkg/PortfolioAnalytics/sandbox/attribution/R/attribution.R 2012-06-18 16:53:58 UTC (rev 2031)
+++ pkg/PortfolioAnalytics/sandbox/attribution/R/attribution.R 2012-06-18 16:55:18 UTC (rev 2032)
@@ -7,12 +7,14 @@
#' on the sector-based approach to the attribution. The workhorse is the
#' Brinson model that explains the arithmetic difference between portfolio and
#' benchmark returns. That is it breaks down the arithmetic excess returns at
-#' one level. The attribution effects can be computed for several periods.
-#' The multi-period summary is obtained using one of linking methods: Carino,
-#' Menchero, GRAP, Frongello. It also allows to break down the geometric excess
-#' returns, which link naturally over time. Finally, it annualizes
-#' arithmetic and geometric excess returns similarly to the portfolio and/or
-#' benchmark returns annualization.
+#' one level. If returns and weigths are available at the lowest level (e.g.
+#' for individual instruments), the aggregation up to the chosen level from the
+#' hierarchy can be done using Return.level function. The attribution effects
+#' can be computed for several periods. The multi-period summary is obtained
+#' using one of linking methods: Carino, Menchero, GRAP, Frongello. It also
+#' allows to break down the geometric excess returns, which link naturally
+#' over time. Finally, it annualizes arithmetic and geometric excess returns
+#' similarly to the portfolio and/or benchmark returns annualization.
#'
#' The arithmetic exess returns are decomposed into the sum of allocation,
#' selection and interaction effects across \deqn{n} sectors:
@@ -117,12 +119,12 @@
Rb = Rb[2:nrow(Rb)]
}
- # Compute attribution effects
+ # Compute attribution effects (Brinson, Hood and Beebower model)
allocation = (wp - wb) * Rb
selection = wb * (Rp - Rb)
interaction = (wp - wb) * (Rp - Rb)
- # Get total attribution effects ???
+ # Get total attribution effects
n = ncol(allocation) # number of segments
allocation = cbind(allocation, rowSums(allocation))
names(allocation)[n + 1] = "Total"
@@ -130,81 +132,77 @@
names(selection)[n + 1] = "Total"
interaction = cbind(interaction, rowSums(interaction))
names(interaction)[n + 1] = "Total"
- total = allocation + selection + interaction
- # Get total portfolio returns and annualized excess returns
+ # Get total portfolio returns
rp = reclass(rowSums(Rp * wp), Rp)
rb = reclass(rowSums(Rb * wb), Rb)
names(rp) = "Total"
names(rb) = "Total"
- rp.a = prod(1 + rp) - 1
- rb.a = prod(1 + rb) - 1
-
- aer.a = rp.a - rb.a # Arithmetic (annualized) excess returns
- ger.a = (1 + rp.a) / (1 + rb.a) - 1 # Geometric (annualized) excess returns
- excess.return = as.matrix(c(aer.a, ger.a))
- rownames(excess.return) = c("Arithmetic", "Geometric")
-
-
+
# Adjust attribution effects using one of linking methods
if (linking == "carino"){
allocation = Carino(rp, rb, allocation)
selection = Carino(rp, rb, selection)
interaction = Carino(rp, rb, interaction)
- total = Carino(rp, rb, total)
}
if (linking == "menchero"){
allocation = Menchero(rp, rb, allocation)
selection = Menchero(rp, rb, selection)
interaction = Menchero(rp, rb, interaction)
- total = Menchero(rp, rb, total)
}
if (linking == "grap"){
allocation = Grap(rp, rb, allocation)
selection = Grap(rp, rb, selection)
interaction = Grap(rp, rb, interaction)
- total = Grap(rp, rb, total)
}
if (linking == "frongello"){
- allocation = Frongello(Rp, wp, Rb, wb, allocation)
- selection = Frongello(Rp, wp, Rb, wb, selection)
- interaction = Frongello(Rp, wp, Rb, wb, interaction)
- total = Frongello(Rp, wp, Rb, wb, total)
+ allocation = Frongello(rp, rb, allocation)
+ selection = Frongello(rp, rb, selection)
+ interaction = Frongello(rp, rb, interaction)
}
if (geometric == TRUE){
attrib = Attribution.geometric(Rp, wp, Rb, wb)
}
+ # Annualize excess returns
+
+ rp.a = prod(1 + rp) - 1
+ rb.a = prod(1 + rb) - 1
+ if (geometric == FALSE){
+ excess.returns = rp - rb
+ aer.a = as.matrix(rp.a - rb.a) # Arithmetic (annualized) excess returns
+ rownames(aer.a) = "Total arithmetic"
+ excess.returns = rbind(as.matrix(excess.returns), aer.a)
+ }
+
# Select the appropriate result corresponding to the chosen method
result = list()
- result[[1]] = allocation
- result[[2]] = selection
- result[[3]] = total
+ result[[1]] = excess.returns
+ result[[2]] = allocation
+ result[[3]] = selection
if (geometric == FALSE){
if (method == "top.down"){ # Top-down attribution
- result[[2]] = result[[2]] + interaction
+ result[[3]] = result[[3]] + interaction
}
if (method == "bottom.up"){ # Bottom-up attribution
- result[[1]] = result[[1]] + interaction
+ result[[2]] = result[[2]] + interaction
}
if (method == "none"){
- result[[4]] = result[[3]]
- result[[3]] = interaction
+ result[[4]] = interaction
}
} else{
result = attrib
}
- result[[length(result) + 1]] = excess.return
# Label the output
if (method == "none" & geometric == FALSE){
- names(result) = c("Allocation", "Selection", "Interaction", "Total", "Annualized excess returns")
+ names(result) = c("Excess returns", "Allocation", "Selection", "Interaction")
} else{
- names(result) = c("Allocation", "Selection", "Total", "Annualized excess returns")
+ names(result) = c("Excess returns", "Allocation", "Selection")
}
return(result)
}
\ No newline at end of file
More information about the Returnanalytics-commits
mailing list