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!


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

The backtest can be run then as follows:

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)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.