An easy mistake with returns

[This article was first published on Portfolio Probe » R language, and kindly contributed to R-bloggers]. (You can report issue about the content on this page here)
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

When aggregating over both time and assets, the order of aggregation matters.


We have the weights for a portfolio and we want to use those and a matrix of returns over time to compute the (long-term) portfolio return.

“A tale of two returns” tells us that aggregation over time is easiest to do in log returns and aggregation over assets is done with simple returns.

An example of when you might do this task is in “Jackknifing portfolio decision returns”.


Some hypothetical data are used.

The prices for our example are:

      A  B  C
2007 24 48 54
2008 30 30 31
2009 45 38 63
2010 63 37 88
2011 95 36 97

The simple returns are:

             A           B          C
2008 0.2500000 -0.37500000 -0.4259259
2009 0.5000000  0.26666667  1.0322581
2010 0.4000000 -0.02631579  0.3968254
2011 0.5079365 -0.02702703  0.1022727

The log returns are:

             A           B           C
2008 0.2231436 -0.47000363 -0.55499684
2009 0.4054651  0.23638878  0.70914752
2010 0.3364722 -0.02666825  0.33420209
2011 0.4107422 -0.02739897  0.09737416

The initial weights — at the end of 2007 — are:

   A    B    C 
0.25 0.50 0.25

Right way

The starting ingredients are:

  • starting weights
  • log return matrix

The steps are:

  • sum the log returns for each asset
  • transform the time-aggregated log returns to simple returns
  • multiply by the weights and sum

At the end of the process we have the simple return for the portfolio over the whole time period.

This calculation gives us a simple return of 81.37%.

Wrong way

One easy way to get it wrong is to start with:

  • starting weights
  • simple returns over time

A wrong procedure is:

  • use the starting weights and the simple returns to collapse to portfolio returns at each time point
  • transform to log returns
  • aggregate across time by summing the log returns
  • transform to a simple return

The subtle error is in the first step.  It implicitly assumes that the weights are constant when in fact they change through time.

This calculation gives us a simple return of 57.44%.

Weights are mythical

Ultimately the problem is that weights are figments of our imagination.  The real things we have are positions and prices.  Weights are derived from these and change through time as prices change.

We can create the positions with approximately these weights for a portfolio worth one million:

    A     B     C 
10417 10417  4630

The calculation using the positions is merely to find the starting and ending value of the portfolio, then compute the return from those two numbers.  That gives us a simple return of 81.37%.

Appendix R

These calculations are easy in R.

base calculations

right <- sum(wt07 * (exp(colSums(logRet)) - 1))
wrong <- exp(sum(log(simpleRet %*% wt07 + 1))) - 1

The results are:

> right
[1] 0.8136574
> wrong
[1] 0.5743759

The positions are created with:

position0 <- round(1e6 * wt07 / priceMat[1,])

They are then used like:

> sum(position0 * priceMat[5,]) /
+   sum(position0 * priceMat[1,]) - 1
[1] 0.8136572

Portfolio Probe calculation

Portfolio Probe thinks of portfolios as their positions.

Getting either portfolio return is a single, simple command:


valuation(position0, priceMat[c language="(1,5),"][/c], 

valuation(position0, priceMat[c language="(1,5),"][/c], returns="log")

The weights at a single time point are found like:

> valuation(position0, priceMat[1,])$weight
       A        B        C 
0.249997 0.499994 0.250009

scraping the price matrix

Here is one way of getting the price matrix into your R session under Windows.

Highlight the price matrix — including the column names — from above and copy it.  Then do the command:

priceMat <- read.table(text=readClipboard(), header=TRUE)

Once you have the price matrix, you can easily calculate the two return matrices:

simpleRet <- tail(priceMat, -1) / head(priceMat, -1) - 1
logRet <- diff(log(priceMat))

To leave a comment for the author, please follow the link and comment on their blog: Portfolio Probe » R language. offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

Never miss an update!
Subscribe to R-bloggers to receive
e-mails with the latest R posts.
(You will not see this message again.)

Click here to close (This popup will not appear again)