Backtesting Equal-Weight Portfolios Sorted by Trailing Volatility
Summary
The document outlines a monthly portfolio strategy that ranks stocks by their trailing three-year return volatility, divides them into five groups, and equally weights the stocks in each group. The answer demonstrates one implementation approach in R using a backtesting function: calculate returns from recent prices, compute each asset’s standard deviation, sort assets by volatility, and assign equal weights to a selected set. The example selects the lowest-volatility assets, so it illustrates one portfolio rather than the full five-portfolio construction requested.
The example uses generated monthly prices for a universe of stocks and configures a 36-month burn-in before trading begins. Users are expected to replace the simulated prices with their own data. The document gives practical structure for signal calculation and backtest setup, but does not report performance results or address transaction costs, missing observations, survivorship bias, or how to form all five ranked groups. Those choices need to be handled when adapting the example for research.
Key ideas
- Trailing returns over a 36-month window can be used to estimate each stock’s volatility.
- Sorting stocks by estimated volatility supports the construction of volatility-ranked portfolios.
- Equal weights can be assigned to a selected group of stocks based on that ranking.
- A backtest needs an initial burn-in period long enough to calculate the trailing volatility signal.
- The example demonstrates a low-volatility selection and does not implement all five requested portfolios.
Tags
Full text
# How to construct stock portfolios in R
# How to construct stock portfolios in R
I need some help, since I can't find any good sources. I need the portfolios for my thesis.
I have 20 years of monthly stock returns for ~200 stocks. I want to create each month 5 equally weighted portfolios. The ranking for portfolios should be done based on each stocks past 3 year standard deviation from stock returns.
In total there would be 204 balancing periods (17 years =20 years - initial estimation period of 3 years).
I have some experience from using R and think it could be done there. Any suggestions? Thx!
## Answer by Enrico Schumann (score 1)
https://quant.stackexchange.com/a/36982
Here is an example that uses the `btest` function, which is in the PMwR package. The package is available from http://enricoschumann.net/R/packages/PMwR/index.htm or from https://github.com/enricoschumann/PMwR. (Disclosure: I am the package author.)
For the example, I create 240 random monthly prices of 200 assets. Just plug in your own data instead.
```
na <- 200 ## number of assets
no <- 20*12 ## number of observations
R <- array(rnorm(na*no, sd = 0.05), ## returns
dim = c(no, na))
P <- apply(rbind(0,R), 2, ## prices
function(x) cumprod(1+x))
```
The main input for running `btest` is a function that is called at any instant of time at which trading may take place, and which returns the desired position (or, alternatively, the desired weights). In the example, it may look as follows. The function selects the 50 assets with the lowest vol and equal-weights them:
```
vol_sort <- function() {
## number of assets in portfolio
k <- 50
## get prices for the last 36 months and
## compute returns
R <- returns(Close(n = 36))
## compute vols and select the k assets with
## the smallest vol
vols <- apply(R, 2, sd)
select <- order(vols)[1:k]
## compute an equal-weight portfolio of
## these assets
w <- numeric(length(vols))
w[select] <- 1/k
w
}
```
The backtest can be run then as follows:
```
library("PMwR")
result <- btest(prices = list(P),
signal = vol_sort,
b = 36, ## burn-in: drop 36 months
convert.weights = TRUE, ## since vol_sort returns weights,
## convert them into positions
initial.cash = 100)
```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.