Equal-Weighted RETURNS not EQUALLY-Weighted in R

798 views Asked by At

Why is the following portfolio not returning the CORRECT % Return:

# Load the packages & download the Stock Symbols
library("xts");library("quantmod");library("PerformanceAnalytics")

e <- new.env()
getSymbols("NPTN;XLRN;PBH;DISCK", from="2014-12-31", env=e)
dataset1 <- CalculateReturns(do.call(merge, eapply(e, Ad)),"discrete")

# Make Equal Weight
EW <- reclass(dataset1 %*% rep(1/ncol(dataset1),ncol(dataset1)), match.to=dataset1) 

Find the Cumulative Sum of the Portfolio:

# I have tried the following both methods:
last(cumsum(na.omit(EW)))

or

Return.cumulative(EW,geometric=FALSE)

However the CORRECT Return should be the following:

# Assuming I purchased on 01-02-2015 at the close
dataset2 <- do.call(merge, eapply(e, Ad))
RETS <-(coredata(dataset2["2015-06-10",])/coredata((dataset2["2015-01-02",])))-1
# Since this is an equally-weighted portfolio:
sum(RETS)*(1/ncol(RETS))

The returns are understated by approximately : 18%

This has also been happening with other equal-weight portfolios but I cannot figure out the reason. Any help is appreciated

1

There are 1 answers

0
WaltS On BEST ANSWER

The daily returns for a portfolio formed by daily rebalancing are given by your EW, that is, each day the portfolio begins with the same specified weighting of each asset and then computes the daily return using that weighting. The cummulative return for the portfolio over a period may be calculated using

EW <- EW["2015-01-03/2015-06-10",]
ret1_rebal <- last(cumprod(EW+1)-1)
ret2_rebal <- Return.cumulative(EW,geometric=TRUE)

where the code for cummulative returns has been corrected from what was originally posted.

When a portfolio is not rebalanced, the returns for each asset individually acummulate over the period. The value of the portfolio at any time is the sum of these acummulated asset returns weighted by the initial allocation. This can be computed by

dataset1 <- dataset1["2015-01-03/2015-06-10",]
dataset3 <- reclass(cumprod(dataset1+1)-1, match.to=dataset1)
wts <- rep(1,ncol(dataset1))/ncol(dataset1)
EW_no_rebal <- dataset3%*%wts
last(EW_no_rebal)

Notice that last(EW_no_rebal) is equal to your calculation sum(RETS)*(1/ncol(RETS)) of portfolio return computed directly from prices.

> last(EW_no_rebal)
[1] 0.4586492
> sum(RETS)*(1/ncol(RETS))
[1] 0.4586492