Portfolio Optimisation in R
For this tutorial, both minimum-variance and mean-variance will be taught. The PortfolioAnalytics package will be used extensively throughout as it allows for a simple workflow for portfolio optimisations. The first part of the code is to define that a portfolio optimisation problem exists. The only variable that needs to be defined is the names of the components of the portfolio. It will then print out a summary of the portfolio defined so far.
1port <- portfolio.spec(assets = colnames((stockReturns)))
2port
3## **************************************************
4## PortfolioAnalytics Portfolio Specification
5## **************************************************
6##
7## Call:
8## portfolio.spec(assets = colnames((stockReturns)))
9##
10## Number of assets: 2
11## Asset Names
12## [1] "AAPL.Adjusted" "GOOG.Adjusted"
13
Next, you’d want to add some constraints to the portfolio. Popular ones would be full_investment, meaning that the sum of the assets must equal 100%, weight_sum, which constrains the total weight of the portfolio to a specific percentage, box, which allows for a minimum and maximum weight for individual assets, and long_only, where assets weights can only be positive. In this example, full_weights, long_only and box will be used. When you print a summary of the port object, it will now show the constraints.
1port <- add.constraint(portfolio = port,
2 type = "full_investment")
3port <- add.constraint(portfolio = port,
4 type = "long_only")
5port <- add.constraint(portfolio = port,
6 type = "box",
7 min = 0.0,
8 max = 0.7)
9port
10## **************************************************
11## PortfolioAnalytics Portfolio Specification
12## **************************************************
13##
14## Call:
15## portfolio.spec(assets = colnames((stockReturns)))
16##
17## Number of assets: 2
18## Asset Names
19## [1] "AAPL.Adjusted" "GOOG.Adjusted"
20##
21## Constraints
22## Enabled constraint types
23## - full_investment
24## - long_only
25## - box
26
Finally, you’ll want to add the objective metric to optimise. To do this, add.objective is used. To maximise the objective, one specifies the type argument to “return”; to minimise the objective, one specifies the type argument to “risk”. The first example will be for a minimum variance portfolio, so the type will be risk and the metric (argument name) that we are looking to minimise is the standard deviation. To reduce code, the portfolio port will be duplicated for portMinVar.
1portMinVar <- port
2portMinVar <- add.objective(portfolio = portMinVar,
3 type = "risk",
4 name = "StdDev")
5portMinVar
6## **************************************************
7## PortfolioAnalytics Portfolio Specification
8## **************************************************
9##
10## Call:
11## portfolio.spec(assets = colnames((stockReturns)))
12##
13## Number of assets: 2
14## Asset Names
15## [1] "AAPL.Adjusted" "GOOG.Adjusted"
16##
17## Constraints
18## Enabled constraint types
19## - full_investment
20## - long_only
21## - box
22##
23## Objectives:
24## Enabled objective names
25## - StdDev
26
Now the objective has been added. To do it for mean-variance, there would be 2 objectives: maximise returns (mean sample returns) whilst minimising standard deviation. Below is the example code:
1portMeanVar <- port
2portMeanVar <- add.objective(portfolio = portMeanVar,
3 type = "risk",
4 name = "StdDev")
5portMeanVar <- add.objective(portfolio = portMeanVar,
6 type = "return",
7 name = "mean")
8portMeanVar
9## **************************************************
10## PortfolioAnalytics Portfolio Specification
11## **************************************************
12##
13## Call:
14## portfolio.spec(assets = colnames((stockReturns)))
15##
16## Number of assets: 2
17## Asset Names
18## [1] "AAPL.Adjusted" "GOOG.Adjusted"
19##
20## Constraints
21## Enabled constraint types
22## - full_investment
23## - long_only
24## - box
25##
26## Objectives:
27## Enabled objective names
28## - StdDev
29## - mean
30
You will notice that there are now two objectives. Finally, the portfolios are going to be optimised and the returns compared. The arguments are the portfolio specified, the returns of each asset and the optimisation method. Generally, random works best as it is a global optimisation problem. One can then extract the weights and create portfolio returns using the Return.portfolio function.
1set.seed(10260)
2minVarOpt <- optimize.portfolio(R = stockReturns,
3 portfolio = portMinVar,
4 optimize_method = "random")
5## Leverage constraint min_sum and max_sum are restrictive,
6## consider relaxing. e.g. 'full_investment' constraint should be min_sum=0.99 and max_sum=1.01
7## Warning: executing %dopar% sequentially: no parallel backend registered
8extractWeights(minVarOpt)
9## AAPL.Adjusted GOOG.Adjusted
10## 0.43 0.57
11minVarReturns <- Return.portfolio(stockReturns, weight = extractWeights(minVarOpt), rebalance_on = "months")
12table.AnnualizedReturns(R = minVarReturns, Rf = 0.1/250)
13## portfolio.returns
14## Annualized Return 0.1745
15## Annualized Std Dev 0.2100
16## Annualized Sharpe (Rf=10.08%) 0.2951
17
Let’s repeat for mean-variance optimisation and compare performance.
1set.seed(10260)
2meanVarOpt <- optimize.portfolio(R = stockReturns,
3 portfolio = portMeanVar,
4 optimize_method = "random")
5## Leverage constraint min_sum and max_sum are restrictive,
6## consider relaxing. e.g. 'full_investment' constraint should be min_sum=0.99 and max_sum=1.01
7extractWeights(meanVarOpt)
8## AAPL.Adjusted GOOG.Adjusted
9## 0.44 0.56
10meanVarReturns <- Return.portfolio(stockReturns, weight = extractWeights(meanVarOpt), rebalance_on = "months")
11optimisedPortfolioReturns <- cbind(minVarReturns, meanVarReturns)
12colnames(optimisedPortfolioReturns) <- c("Minimum Variance", "Mean Variance")
13table.AnnualizedReturns(R = optimisedPortfolioReturns, Rf = 0.1/252)
14## Minimum Variance Mean Variance
15## Annualized Return 0.1745 0.1749
16## Annualized Std Dev 0.2100 0.2100
17## Annualized Sharpe (Rf=10%) 0.2991 0.3007
18
Unlock Premium Content
Upgrade your account to access the full article, downloads, and exercises.
You'll get access to:
- Access complete tutorials and examples
- Download source code and resources
- Follow along with practical exercises
- Get in-depth explanations