How Rolling Rebalancing Uses a Fixed Lookback Window
Summary
The document explains why weights from PortfolioAnalytics’ rebalancing optimizer can differ from weights produced by a separate call to its portfolio optimizer. Rebalancing occurs at specified data endpoints, and at each endpoint the rolling window determines which observations enter that period’s optimization. The comparison must therefore use the same training data as the rebalancing call.
In the example, quarterly rebalancing uses the last twelve observations. The first manual comparison matches because it also optimizes over twelve observations. The later comparison does not: the manually selected date range contains thirty-seven observations, while the rolling rebalancing calculation still uses twelve. The discrepancy is thus attributed to unequal input windows, rather than an extra optimization calculation. The example clarifies the importance of aligning the sample window and endpoint schedule when checking rolling portfolio results. It does not discuss other settings or cases, so users should still confirm how their own data frequency and rebalancing parameters define each window.
Key ideas
- Rebalancing optimizations occur at endpoints determined by the return data and chosen schedule.
- A rolling window limits each optimization to the most recent specified observations.
- Manual comparisons match only when they use the same observations as the rebalancing step.
- A longer date range can produce different weights because it supplies a different training sample.
- Data frequency and rebalancing settings determine the windows used in practice.
Tags
Full text
# What is optimize.portfolio.rebalancing in R-package PortfolioAnalytics calculating?
# What is optimize.portfolio.rebalancing in R-package PortfolioAnalytics calculating?
I recently started using the R-package `PortfolioAnalytics` for performing some portfolio optimization. And I'm trying to get a grasp on what exactly the function `optimize.portfolio.rebalancing` is calculating. In particular, I'm wondering why the weights calculated (from the second period onwards) are different than the ones that I get when directly calling `optimize.portfolio`.
I was under the impression that `optimize.portfolio.rebalancing` was basically a "wrapper around `optimize.portfolio`" (from the manual), so I thought that the function simply calls `optimize.portfolio` repeatedly for periods of length `rolling_window`. But then, shouldn't the results be identical to what a manual call of `optimize.portfolio` with the exact same periods yields? Or is `optimize.portfolio.rebalancing` performing some additional calculations? What am I missing?
Here's a minimal example illustrating my question:
```
data("edhec")
returns <- edhec[, 1:4]
funds <- colnames(returns)
portfolio <- portfolio.spec(assets = funds)
portfolio <- add.constraint(portfolio = portfolio, type = "full_investment")
portfolio <- add.constraint(portfolio = portfolio, type = "long_only")
portfolio <- add.objective(portfolio = portfolio, type = "risk", name = "ES")
portfolio.rebalanced <- optimize.portfolio.rebalancing(R = returns,
portfolio = portfolio,
optimize_method = "ROI",
rebalance_on = "quarters",
training_period = 12,
rolling_window = 12)
# check, if optimize.portfolio gives the same results: first period
portfolio.optimized <- optimize.portfolio(R = returns["::1997-12-31",],
portfolio = portfolio,
optimize_method = "ROI")
portfolio.optimized
portfolio.rebalanced$opt_rebalancing$`1997-12-31`
# YES!
# but: last period
portfolio.optimized <- optimize.portfolio(R = returns["2006-08-31::2009-08-31",],
portfolio = portfolio,
optimize_method = "ROI")
portfolio.optimized
portfolio.rebalanced$opt_rebalancing$`2009-08-31`
# NO! What's wrong?
```
## Answer by Kyle Balkissoon (score 1)
https://quant.stackexchange.com/a/30203
It rebalances on endpoints(R), you passed it quarters, so every quarter as determined by endpoints(returns,'quarters') it will rebalance using the last 12 observations.
In your case there you called optimize portfolio on a dataset of 37 observations
```
nrow(edhec["2006-08-31::2009-08-31"])
[1] 37
```
This should explain the discrepancy between the two calls as one has a dataset of 12 vs 37.
While in your first test you called optimize portfolio on a dataset of 12 observations which in line with the optimize.portfolio.rebalancing call
```
nrow(edhec["::1997-12-31",])
[1] 12
```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.