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

noreply at r-forge.r-project.org noreply at r-forge.r-project.org
Mon Jun 11 18:44:04 CEST 2012


Author: ababii
Date: 2012-06-11 18:44:03 +0200 (Mon, 11 Jun 2012)
New Revision: 2003

Modified:
   pkg/PortfolioAnalytics/sandbox/attribution/attribution.levels.R
Log:
- extended to the arbitrary number of levels. Didn't finish

Modified: pkg/PortfolioAnalytics/sandbox/attribution/attribution.levels.R
===================================================================
--- pkg/PortfolioAnalytics/sandbox/attribution/attribution.levels.R	2012-06-11 12:02:13 UTC (rev 2002)
+++ pkg/PortfolioAnalytics/sandbox/attribution/attribution.levels.R	2012-06-11 16:44:03 UTC (rev 2003)
@@ -1,14 +1,21 @@
-# 5-steps attribution (3-levels)
+# Multi-level attribution
+# TODO: find a way to make conformable returns at different levels
 attribution.levels <-
 function(Rp, Rb, wp, wb, h, ...)
 { # @author Andrii Babii
 
-    Rb = checkData(Rb)
     Rp = checkData(Rp)
-
+    Rb = checkData(Rb)
+    wp = Weight.transform(wp, Rp)
+    wb = Weight.transform(wb, Rb)
+    
     levels <- unlist(list(...))
     if (!is.null(levels)) stopifnot(is.character(levels))
-    
+
+    # Get portfolio and benchmark returns
+    r = Return.rebalancing(Rp, wp)
+    b = Return.rebalancing(Rb, wb)
+
     # Get returns and weights at all levels
     returns.p = list()
     weights.p = list()
@@ -20,17 +27,13 @@
         weights.p[[i]] = Weight.level(wp, h, level = levels[i])
         returns.b[[i]] = Return.level(Rb, wb, h, level = levels[i])
         weights.b[[i]] = Weight.level(wb, h, level = levels[i])
-        bs[[i]] = Return.rebalancing(weights.p[[i]], returns.b[[i]])   # semi-notional funds returns
+        bs[[i]] = reclass(rowSums(returns.b[[i]] * weights.p[[i]]), r)  # semi-notional funds returns
     } 
     names(returns.p) = levels
     names(weights.p) = levels
     names(returns.b) = levels
     names(weights.b) = levels
 
-    # Get portfolio and benchmark returns
-    r = Return.rebalancing(Rp, wp)
-    b = Return.rebalancing(Rb, wb)
-    
     # Total attribution effects
     allocation = list()
     allocation[[1]] = (1 + bs[[1]]) / (1 + b) - 1 # Allocation 1
@@ -41,33 +44,23 @@
     selection = (1 + r) / (1 + last(bs)[[1]]) - 1
     total = (1 + r) / (1 + b) - 1 # Total excess return
     
-    #level = list()
-    #level[[1]] = (weights.p[[1]] - weights.b[[1]]) * ((1 + returns.b[[1]]) / (1 + b) - 1)
-    #for (i in 2:length(levels)){
-    #    level[[i]] = (weights.p[[i]] - weights.b[[i]]) * ((1 + returns.b[[i]]) / (1 + returns.b[[i-1]]) - 1) * ((1 + returns.b[[i - 1]]) / (1 + bs[[i-1]]))
-    #}
+    # Transform portfolio, benchmark returns and semi-notional funds returns to conformable matrices for multi-level attribution
+    b = as.xts(matrix(rep(b, ncol(returns.b[[1]])), nrow(b), ncol(returns.b[[1]])), index(b))
+    r = as.xts(matrix(rep(r, ncol(last(returns.b)[[1]])), nrow(r), ncol(last(returns.b)[[1]])), index(r))
+   
+    for (i in 1:length(bs)){
+        bs[[i]] = as.xts(matrix(rep(bs[[i]], ncol(returns.p[[i]])), nrow(r), ncol(returns.p[[i]])), index(r))
+    }
 
-    # Level 1 attribution
-    l1 = (weights.p[[1]] - weights.b[[1]]) * ((1 + returns.b[[1]]) / (1 + b) - 1)
-    
-    # Level 2 attribution
-    l2 = (weights.p[[2]] - weights.b[[2]]) * ((1 + returns.b[[2]]) / (1 + returns.b[[1]]) - 1) * ((1 + returns.b[[1]]) / (1 + bs[[1]]))
-    
-    # Level 3 attribution
-    w = (weights.p[[3]] - weights.b[[3]])
-    a1 = 1 + returns.b[[2]]
-    b1 = ((1 + returns.b[[3]]) / (cbind(a1, a1, a1)) - 1)
-    b2 = ((1 + returns.b[[2]]) / (1 + bs[[2]]))
-    b2 = cbind(b2, b2, b2)
-    l3 = w * b1 * b2
+    # Attribution at each level
+    level = list()
+    level[[1]] = (weights.p[[1]] - weights.b[[1]]) * ((1 + returns.b[[1]]) / (1 + b) - 1)
+    for (i in 2:length(levels)){ # This does not work. Need to finish
+        level[[i]] = (weights.p[[i]] - weights.b[[i]]) * ((1 + returns.b[[i]]) / (1 + returns.b[[i-1]]) - 1) * ((1 + returns.b[[i-1]]) / (1 + bs[[i-1]]))
+    }
 
     # Security/Asset selection
-    w = weights.p[[3]]
-    a1 = cbind((1 + r), (1 + r), (1 + r)) 
-    b1 = a1 / (1 + returns.b[[3]]) - 1
-    a2 = cbind((1 + bs[[3]]), (1 + bs[[3]]), (1 + bs[[3]]))
-    b2 = (1 + returns.b[[3]]) / a2
-    select = w * b1 * b2
+    select = as.xts(as.data.frame(last(weights.p))) * ((1 + r) / (1 + as.xts(as.data.frame(last(returns.b)))) - 1) * ((1 + as.xts(as.data.frame(last(returns.b)))) / (1 + as.xts(as.data.frame(last(bs)))))
 
     result = list()
     general = cbind(allocation, selection, total)
@@ -79,11 +72,10 @@
     result[[5]] = select
     names(result) = c("Multi-level attribution", "Level 1 attribution", "Level 2 attribution", "Level 3 attribution", "Security selection")
     return(result)
-
 }
 
 # Example:
-data(attrib) # !!! Load attrib.RData workspace
+data(attrib)
 attribution.levels(Rp, wp, Rb, wb, h, c("type", "currency", "Sector"))
 
 



More information about the Returnanalytics-commits mailing list