[Returnanalytics-commits] r1992 - pkg/PortfolioAnalytics/sandbox/attribution
noreply at r-forge.r-project.org
noreply at r-forge.r-project.org
Thu Jun 7 11:40:52 CEST 2012
Author: ababii
Date: 2012-06-07 11:40:52 +0200 (Thu, 07 Jun 2012)
New Revision: 1992
Modified:
pkg/PortfolioAnalytics/sandbox/attribution/attrib.RData
pkg/PortfolioAnalytics/sandbox/attribution/attribution.R
Log:
- fixed bugs in Carino and Menchero linking when portfolio and benchmark returns are equal
- fixed bug with GRAP when there are less then 4 periods
- fixed bugs with computation and output of geometric attribution
- corrected examples
Modified: pkg/PortfolioAnalytics/sandbox/attribution/attrib.RData
===================================================================
(Binary files differ)
Modified: pkg/PortfolioAnalytics/sandbox/attribution/attribution.R
===================================================================
--- pkg/PortfolioAnalytics/sandbox/attribution/attribution.R 2012-06-06 21:05:34 UTC (rev 1991)
+++ pkg/PortfolioAnalytics/sandbox/attribution/attribution.R 2012-06-07 09:40:52 UTC (rev 1992)
@@ -72,8 +72,15 @@
# Adjust attribution effects using one of linking methods
if (linking == "carino"){
- # Carino linking #!!! Correct for equal portfolio and benchmark returns
- kt = (log(1 + rp) - log(1 + rb)) / (rp - rb) # Carino factors
+ # Carino linking
+ kt = rp
+ for (t in 1:nrow(kt)){
+ if (rp[t] == rb[t]){
+ kt[t] = 1 / (1 + rp[t]) # Carino factors if portfolio and benchmark returns are equal
+ } else{
+ kt[t] = (log(1 + rp[t]) - log(1 + rb[t])) / (rp[t] - rb[t]) # if different
+ }
+ }
k = (log(1 + rp.a) - log(1 + rb.a)) / (rp.a - rb.a)
for(i in 1:ncol(allocation)){
allocation[, i] = allocation[, i] * kt / k
@@ -83,9 +90,15 @@
}
if (linking == "menchero"){
- # Menchero linking #!!! Correct for equal portfolio and benchmark returns
- M = ((rp.a - rb.a) / nrow(Rp)) / ((1 + rp.a)^(1 / nrow(Rp)) - (1 + rb.a)^(1 / nrow(Rp)))
- at = (rp.a - rb.a - M * sum(rp - rb)) * (rp - rb) / sum((rp - rb)^2)
+ # Menchero linking
+ T = nrow(Rp)
+ if (rp.a == rb.a){
+ M = (1 + rb.a)^((T - 1) / T)
+ at = 0
+ } else{
+ M = ((rp.a - rb.a) / T) / ((1 + rp.a)^(1 / T) - (1 + rb.a)^(1 / T))
+ at = (rp.a - rb.a - M * sum(rp - rb)) * (rp - rb) / sum((rp - rb)^2)
+ }
for(i in 1:ncol(allocation)){
allocation[, i] = allocation[, i] * (M + at)
selection[, i] = selection[, i] * (M + at)
@@ -96,13 +109,21 @@
if (linking == "grap"){
# GRAP linking
G = rp
- G[1] = prod(1 + rb[2:length(rp)])
- G[nrow(rp)] = prod(1 + rp[1:(length(rp) - 1)])
- for(i in 2:(nrow(Rp) - 1)){ # !!! Fix. Works only if t>3
- r = 1 + rp[1:(i-1)]
- b = 1 + rb[(i+1):(nrow(Rp))]
- G[i] = apply(r, 2, prod) * apply(b, 2, prod)
+ T = nrow(Rp)
+ G[1] = prod(1 + rb[2:T]) #GRAP factor for the first period
+ if (T == 2){
+ G[2] = (1 + rp[1])
}
+ if (T > 2){
+ G[T] = prod(1 + rp[1:(T - 1)]) #GRAP factor for the last period
+ }
+ if (T > 3){
+ for(i in 2:(T - 1)){
+ r = 1 + rp[1:(i-1)]
+ b = 1 + rb[(i+1):T]
+ G[i] = apply(r, 2, prod) * apply(b, 2, prod)
+ }
+ }
for(i in 1:ncol(allocation)){
allocation[, i] = allocation[, i] * G
selection[, i] = selection[, i] * G
@@ -152,17 +173,18 @@
result[[1]] = allocation
result[[2]] = selection
result[[3]] = total
- if (method == "top.down"){ # Top-down attribution
- result[[2]] = result[[2]] + interaction
+ if (linking != "geometric"){
+ if (method == "top.down"){ # Top-down attribution
+ result[[2]] = result[[2]] + interaction
+ }
+ if (method == "bottom.up"){ # Bottom-up attribution
+ result[[1]] = result[[1]] + interaction
+ }
+ if (method == "simple"){
+ result[[4]] = result[[3]]
+ result[[3]] = interaction
+ }
}
- if (method == "bottom.up"){ # Bottom-up attribution
- result[[1]] = result[[1]] + interaction
- }
- if (method == "simple"){
- result[[4]] = result[[3]]
- result[[3]] = interaction
- }
-
# Label the output
if (method == "simple" & linking != "geometric"){
names(result) = c("Allocation", "Selection", "Interaction", "Total")
@@ -176,10 +198,6 @@
data(attrib) # !!! Load attrib.RData workspace
require(FinancialInstrument)
require(PerformanceAnalytics)
-Rp <- Return.level(Rp, wp, h, level = "Sector") # Sector-level attribution
-Rb <- Return.level(Rb, wb, h, level = "Sector")
-wp <- Weight.level(Rp, wp, h, level = "Sector")
-wb <- Weight.level(Rb, wb, h, level = "Sector")
attribution(Rp, wp, Rb, wb, method = "top.down", linking = "carino")
attribution(Rp, wp, Rb, wb, method = "bottom.up", linking = "menchero")
attribution(Rp, wp, Rb, wb, method = "simple", linking = "grap")
More information about the Returnanalytics-commits
mailing list