Skip to content

Return.portfolio contribution documentation incorrect.

2 messages · Ilya Kipnis, Eric Zivot

#
So, I'm trying to replicate Return.portfolio, since I intend to port it
over into Python, and while I understand most of the calculations, there's
one thing that bugs me, namely contribution. Here's my MRE:

getSymbols(c('SPY', 'TLT'), from = '1990-01-01')

R = na.omit(cbind(Return.calculate(Ad(SPY)), Return.calculate(Ad(TLT))))
R_na <- cbind(Return.calculate(Ad(SPY)), Return.calculate(Ad(TLT)))

out <- Return.portfolio(R = R,
                        weights = c(1, .6), verbose = TRUE, rebalance_on =
NA, contribution = FALSE)

r_calc <- cbind(R, 0)
cumprods <- cumprod(1+r_calc)

# EOP.Value
eop.value <- cumprods * matrix(rep(c(1, .6, -.6), nrow(tmp)), ncol = 3,
byrow = TRUE)
print(tail(round(eop.value-out$EOP.Value), 6))


# BOP.Value
bop.value <- eop.value/(1+r_calc)
print(tail(round(bop.value-out$BOP.Value), 6))


# EOP.Weight
eop.weight <- eop.value/rowSums(eop.value)
print(tail(round(eop.weight-out$EOP.Weight), 6))

# BOP.Weight
bop.weight <- bop.value/rowSums(bop.value)
print(tail(round(bop.weight-out$BOP.Weight), 6))

In all cases, everything matches up besides the contributions. When I
implement what's defined in the functionality, namely:

contribution: The per period contribution to portfolio return of each
asset. Contribution is calculated as BOP weight times the period's return
divided by BOP value. Period contributions are summed across the individual
assets to calculate portfolio return

So, contribution should be:

contrib <- bop.weight*r_calc/bop.value

Which gives me the following result:

tail(contrib)

            SPY.Adjusted  TLT.Adjusted X0
2021-06-07 -1.200836e-04 -0.0003804248  0
2021-06-08  2.642538e-05  0.0008710532  0
2021-06-09 -1.845971e-04  0.0010924038  0
2021-06-10  5.746216e-04  0.0007415750  0
2021-06-11  2.031949e-04 -0.0001984059  0
2021-06-14  2.750417e-04 -0.0009408983  0

Yet, the *actual* contribution, as defined by Return.portfolio, is:

 tail(out$contribution)
            SPY.Adjusted  TLT.Adjusted Residual
2021-06-07 -0.0008054887 -0.0007500412        0
2021-06-08  0.0001770824  0.0017120802        0
2021-06-09 -0.0012372908  0.0021622383        0
2021-06-10  0.0038457437  0.0014807881        0
2021-06-11  0.0013662344 -0.0003985565        0
2021-06-14  0.0018523718 -0.0018870209        0

Which clearly does not match.

Is the documentation incorrect, or am I misunderstanding something?
#
Hey Ilya,
I go over the Return.portfolio() calculations by hand in my online computational finance book (see https://bookdown.org/compfinezbook/introcompfinr/portfolios-and-portfolio-returns.html ). This might help you find out where you are going wrong with your calculations below. 
Cheers,
Eric

-----Original Message-----
From: R-SIG-Finance <r-sig-finance-bounces at r-project.org> On Behalf Of Ilya Kipnis
Sent: Tuesday, June 15, 2021 4:56 AM
To: r-sig-finance <r-sig-finance at r-project.org>
Subject: [R-SIG-Finance] Return.portfolio contribution documentation incorrect.

So, I'm trying to replicate Return.portfolio, since I intend to port it over into Python, and while I understand most of the calculations, there's one thing that bugs me, namely contribution. Here's my MRE:

getSymbols(c('SPY', 'TLT'), from = '1990-01-01')

R = na.omit(cbind(Return.calculate(Ad(SPY)), Return.calculate(Ad(TLT)))) R_na <- cbind(Return.calculate(Ad(SPY)), Return.calculate(Ad(TLT)))

out <- Return.portfolio(R = R,
                        weights = c(1, .6), verbose = TRUE, rebalance_on = NA, contribution = FALSE)

r_calc <- cbind(R, 0)
cumprods <- cumprod(1+r_calc)

# EOP.Value
eop.value <- cumprods * matrix(rep(c(1, .6, -.6), nrow(tmp)), ncol = 3, byrow = TRUE) print(tail(round(eop.value-out$EOP.Value), 6))


# BOP.Value
bop.value <- eop.value/(1+r_calc)
print(tail(round(bop.value-out$BOP.Value), 6))


# EOP.Weight
eop.weight <- eop.value/rowSums(eop.value) print(tail(round(eop.weight-out$EOP.Weight), 6))

# BOP.Weight
bop.weight <- bop.value/rowSums(bop.value) print(tail(round(bop.weight-out$BOP.Weight), 6))

In all cases, everything matches up besides the contributions. When I implement what's defined in the functionality, namely:

contribution: The per period contribution to portfolio return of each asset. Contribution is calculated as BOP weight times the period's return divided by BOP value. Period contributions are summed across the individual assets to calculate portfolio return

So, contribution should be:

contrib <- bop.weight*r_calc/bop.value

Which gives me the following result:

tail(contrib)

            SPY.Adjusted  TLT.Adjusted X0
2021-06-07 -1.200836e-04 -0.0003804248  0
2021-06-08  2.642538e-05  0.0008710532  0
2021-06-09 -1.845971e-04  0.0010924038  0
2021-06-10  5.746216e-04  0.0007415750  0
2021-06-11  2.031949e-04 -0.0001984059  0
2021-06-14  2.750417e-04 -0.0009408983  0

Yet, the *actual* contribution, as defined by Return.portfolio, is:

 tail(out$contribution)
            SPY.Adjusted  TLT.Adjusted Residual
2021-06-07 -0.0008054887 -0.0007500412        0
2021-06-08  0.0001770824  0.0017120802        0
2021-06-09 -0.0012372908  0.0021622383        0
2021-06-10  0.0038457437  0.0014807881        0
2021-06-11  0.0013662344 -0.0003985565        0
2021-06-14  0.0018523718 -0.0018870209        0

Which clearly does not match.

Is the documentation incorrect, or am I misunderstanding something?


_______________________________________________
R-SIG-Finance at r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-sig-finance
-- Subscriber-posting only. If you want to post, subscribe first.
-- Also note that this is not the r-help list where general R questions should go.