Portfolio Rebalancing with End-of-Period Weights
Summary
The document explains why a manual portfolio-rebalancing calculation may disagree with a portfolio-return package: weights are dated at the end of a period and apply to the next period's returns. In the example, weights recorded at one month-end are used to calculate the following month's return, after which the next set of month-end weights determines the subsequent holdings. When there is one return observation per period, the period portfolio return is the weighted sum of asset returns.
The response recommends aligning weight dates with the return periods before comparing calculations. It also distinguishes period returns from cumulative performance: cumulative return is obtained by geometrically linking period returns. The provided example demonstrates this timing convention with dated return and weight observations. The explanation assumes the weight and return observations correspond to the intended periods; it does not fully detail more frequent rebalancing, transaction costs, missing observations, or implementation choices that can affect package output.
Key ideas
- End-of-period weights specify the rebalance made after that period closes.
- Those weights become beginning-of-period holdings for the next return interval.
- With one return observation per period, portfolio return is the weighted sum of asset returns.
- Cumulative portfolio performance geometrically links period returns.
- Date alignment is essential when comparing manual calculations with software output.
Tags
Full text
# Rebalancing portfolio weights
# Rebalancing portfolio weights
I have a matrix of returns and weights for every time period.
```
returns<-rbind(c(-0.05,0.04,0.37),c(0.15,0.02,-0.07))
weights<-rbind(c(0.5,0.1,0.4),c(0.4,0.2,0.4))
```
I would like to rebalance the weights at the end of every time period:
To do so I first calculate percent change every month in the returns:
```
ones <- matrix(1,ncol=ncol(returns),nrow=nrow(returns))
add <- returns
percentChange <- ones+add
```
then I calculate the total change:
```
percentChangeSums <- rowSums(percentChange*weights)
```
then I calculate the weights after accounting for the returns:
```
WeightsBefore <- weights * percentChange
```
I calculate how much I should invest in the shares to have the original weights I wanted to maintain:
```
ShareAfter <- percentChangeSums * weights
```
Just to check that I still have the original weights:
```
WeightsAfter <- ShareAfter/percentChangeSums
rebalanced.weights <- ShareAfter
```
My goal is to do this without using any built in functions (e.g. the ones in the PerformanceAnalytics package).
The problem is that I get different results from the built in functions (`Return.portfolio()`).
What am I missing?
Update:
Based on XY's comment I modified my code:
```
return <- rbind(c(-5,4,37),c(15,2,-7))
weights <- rbind(c(0.5,0.1,0.4), c(0.5,0.1,0.4),c(0.5,0.1,0.4))
N=3
add <- return/100
ones <- matrix(1,ncol=N,nrow=nrow(return))
ShareAfter <- matrix(NA,ncol=N,nrow=nrow(return))
firstPeriodReturns <- weights[1,]*add[1,]
percentChange <- ones+add
WeightsBefore <- weights[1,] * percentChange[1,]
percentChangeSums <- sum(WeightsBefore)
ShareAfter[1,] <- percentChangeSums * weights[1,]
for (i in 2:nrow(return)){
WeightsBefore <- ShareAfter[i-1,] * percentChange[i,]
percentChangeSums <- sum(WeightsBefore)
ShareAfter[i,] <- percentChangeSums * weights[i,]
}
```
I still do not get the desired result. Can someone point me to whats missing?
Please note again I want to do this manually, not with a package.
## Answer by WaltS (score 2)
https://quant.stackexchange.com/a/19090
The calculation of rebalanced portfolio returns using `PerformanceAnalytics` functions makes use of what the package authors call "end-of-period" weights. As described in the documentation for `Return.portfolio`, the rebalancing uses the weights for the last trading day of the period to rebalance the portfolio after the markets close on that day. As an example, in the code below I've added dates to your weight and return data. Here the weights for 2015-05-31 specify the weights used to rebalance the portfolio following the close of trading on that date. These become the "beginning-of-period" weights for the trading period starting on 2015-06-01 and are the proper ones to use with the returns of 2015-06-30 to calculate the portfolio returns for the month of June. For this case, where the weights and returns have the same number of data points per period, returns for a period are just the scalar product of the asset returns and the weights. The code below also performs this calculation so you can compare the two methods.
From your post, it looked as though you might also be interested in the cumulative returns. The code below includes that calculation using both `PerformanceAnalytics` and direct calculations.
```
returns<-rbind(c(-0.05,0.04,0.37),c(0.15,0.02,-0.07))
weights<-rbind(c(0.5,0.1,0.4),c(0.4,0.2,0.4))
library(PerformanceAnalytics)
ret <- xts(returns, order.by= as.Date(c("2015-06-30", "2015-07-31")))
wts <- xts(weights, order.by= as.Date(c("2015-05-31","2015-06-30")))
# Period returns
returns_PA <- Return.portfolio(ret, wts)
returns_direct <- reclass(sapply(1:nrow(wts), function(n) ret[n,]%*%t(wts[n,])), ret)
# Cummulative returns
returns_PA_cum <- Return.cumulative(returns_PA)
returns_direct_cum <- prod(returns_direct+1) -1
```Shown in full with attribution under the source's licence. Licence: CC BY-SA 4.0 (Stack Exchange)
This summary was written by Stratmill's research agent from the original; it is not a copy of the source.