Portfolio Construction and Optimization with R

Kyle Balkissoon

KKB Research and Development

2016-10-26

Introduction

At the end of this presentation you will know how to the following

  • Get Data
  • Process Data
  • Create Portfolio objectives
  • Optimize Portfolios
  • Analyse Portfolios
  • Case Study: Stance Equity

Get Data

Before we can do anything we need data, some good R libraries for getting data are:

library(Quandl) # see Quandl.com for more info
library(quantmod) #Has preconfigured api with yahoo info
##Quandl - Note requires assignment, type xts is xtensible time series
SPTSXComp=Quandl("YAHOO/INDEX_GSPTSE",type='xts')

##quantmod - assigns to object named GSPTSE - automatically in xts/zoo
 getSymbols("^GSPTSE")

A realistic case - US SP500 Sectors

symbol_list = c('XLF','XLE','XLU','XLK','XLB','XLP','XLY','XLI','XLV')

getSymbols(symbol_list, from = '1990-01-01')
getSymbols("SPY",from='1990-01-01')

Preprocess Data into Returns

library(PerformanceAnalytics)
securities_matrix = NULL
for( sym in symbol_list){
  securities_matrix = merge.xts(securities_matrix,
                     Return.calculate(Ad(get(paste(sym))),
                                                 method='discrete'))}
securities_matrix=securities_matrix[complete.cases(securities_matrix)]
SPYReturn=Return.calculate(Ad(SPY),method='discrete')

Introduction to PerformanceAnalytics

  • Library to compute many functions in return space
  • Used by hedge funds, proprietary trading firms, mutual funds, SMA's and banks
  • Robust tools for measuring portfolio and security performance with all the standard risk metrics.

Have a look at our data

chart.CumReturns(securities_matrix)

plot of chunk unnamed-chunk-7

Portfolio Objective creation

Coming up with an objective function is non-trivial, the issue is that any potential function needs to capture the risk-return preferences of the investor in a coherent manner. Key issues in objective formulation:

  • Parameter Estimation
  • Alignment of objectives of function with client
  • Directional Preference
  • Smoothness
  • Computational difficulty

Some common and not so common objectives

  • Minimum Variance
  • Max Sharpe Ratio
  • Minimize Expected Tail Loss
  • Max Return / Expected Tail Loss

PortfolioAnalytics - Tools for Creating and Optimizing Portfolios

  • Library to create and optimize portfolios
  • Initially built for hedge funds, trading firms and equity funds
  • Used heavily by practictioners for portfolio specification and optimization

An Example of PortfolioAnalytics - Minimum Variance

library(PortfolioAnalytics)
MinimumVariancePortfolio=portfolio.spec(
  assets=colnames(securities_matrix))

MinimumVariancePortfolio=add.objective(
  portfolio=MinimumVariancePortfolio,
  type='risk',
  name='StdDev')

An Example of PortfolioAnalytics - Setting up Constraints

MinimumVariancePortfolio=add.constraint(
  portfolio = MinimumVariancePortfolio,
  type="full_investment")

MinimumVariancePortfolio=add.constraint(
  portfolio = MinimumVariancePortfolio,
  type="long_only")

MinimumVariancePortfolio=add.constraint(
  portfolio = MinimumVariancePortfolio,
  type="box",
  min=0,max=0.3)

Optimization with PortfolioAnalytics

  • Easy to use with optimize.portfolio calls
  • Can work with many optimizers default is DEoptim
OptimizedPortfolioMinVariance=optimize.portfolio(
  R=securities_matrix,
  portfolio=MinimumVariancePortfolio,
  trace=TRUE)

Analysing our portfolio

chart.Weights(OptimizedPortfolioMinVariance)

plot of chunk unnamed-chunk-12

Mean Variance Optimization

MeanVariancePortfolio=add.objective(
  portfolio=MinimumVariancePortfolio,
  type='return',
  name='mean')
OptimizedPortfolioMeanVariance=optimize.portfolio(
  R=securities_matrix,
  portfolio=MeanVariancePortfolio,
  trace=TRUE)

Analysing our portfolio

chart.Weights(OptimizedPortfolioMeanVariance)

plot of chunk unnamed-chunk-16

Risk to Return Analysis

chart.RiskReward(OptimizedPortfolioMeanVariance,
                return.col = 'mean',
                risk.col = 'StdDev',
                main='Risk to Return Plot of various Portfolio Combinations')

Risk to Return Analysis - Plot

plot of chunk unnamed-chunk-18

Backtesting with PortfolioAnalytics

MinimumVarianceBT=optimize.portfolio.rebalancing(R=securities_matrix,
                                                 MinimumVariancePortfolio,
                                                 rebalance_on = 'years',
                                                 training_period = 252,
                                                 rolling_window = 252)

Backtesting with PortfolioAnalytics

MeanVarianceBT=optimize.portfolio.rebalancing(R=securities_matrix,
                                              MeanVariancePortfolio,
                                              rebalance_on = 'years',
                                              training_period = 252,
                                              rolling_window = 252)

Using PerformanceAnalytics to compute portfolio returns

MinVariancePortfReturns=Return.rebalancing(R=securities_matrix,
                                           weights=extractWeights(MinimumVarianceBT))
colnames(MinVariancePortfReturns)=c('MinVariance')
MeanVariancePortfReturns=Return.rebalancing(R=securities_matrix,
                                            weights=extractWeights(MeanVarianceBT))
colnames(MeanVariancePortfReturns)=c('MeanVariance')
EqualWeightPortfReturns=Return.rebalancing(R=securities_matrix)
colnames(EqualWeightPortfReturns)=c('EqualWeight')

Analysing our portfolios

PortfolioComparisonData=merge.xts(MinVariancePortfReturns,
                                  MeanVariancePortfReturns,
                                  EqualWeightPortfReturns,
                                  SPYReturn)['2000-01-01/2016-10-25']
chart.CumReturns(PortfolioComparisonData,
                main='Performance of Various Strategies',
                legend.loc='topleft')

Analysing our portfolios Plot

plot of chunk unnamed-chunk-25

Analysing our portfolios - Functions

table.AnnualizedReturns(PortfolioComparisonData)
maxDrawdown(PortfolioComparisonData)
table.CAPM(PortfolioComparisonData[,1:3],
           PortfolioComparisonData[,4])[c(2,6,9,10,11,12),]

Analysing our portfolios - Total Return, Vol, Sharpe

MinVariance MeanVariance EqualWeight SPY.Adjusted
Annualized Return 0.0564 0.0643 0.0575 0.0419
Annualized Std Dev 0.1627 0.1584 0.1915 0.1994
Annualized Sharpe (Rf=0%) 0.3467 0.4061 0.3002 0.2101

Analysing our portfolios - Max Drawdown

MinVariance MeanVariance EqualWeight SPY.Adjusted
Worst Drawdown 0.4945 0.4447 0.5264 0.5519

Analysing our portfolios - CAPM

MinVariance to SPY.Adjusted MeanVariance to SPY.Adjusted EqualWeight to SPY.Adjusted
Beta 0.7503 0.7219 0.9177
Annualized Alpha 0.0225 0.0313 0.0183
Tracking Error 0.0810 0.0863 0.0586
Active Premium 0.0143 0.0222 0.0154
Information Ratio 0.1763 0.2575 0.2620
Treynor Ratio 0.0752 0.0891 0.0626

Case Study: Stance Equity

  • Portfolio built to incorporate any investor set of values
  • Investor can use values based screen to select any 250 stocks
  • ML model then intersects that list with top stocks from benchmark
  • Rebalanced quarterly to maximize diversification and minimize tail risk

Case Study: Stance Equity - Performance

plot of chunk unnamed-chunk-30

Case Study: Stance Equity - Analysis

Composite SP500TR.Adjusted
Cumulative Return 0.2748 0.2429
Annualized Return 0.0923 0.0823
Annualized Standard Deviation 0.0872 0.1095
Annualized Sharpe Ratio (Rf=0%) 1.0586 0.7516
Annualized Alpha 0.0415 0.0000
Beta 0.6056 1.0000
Worst Drawdown 0.0461 0.0836

Case Study: Stance Equity - Rolling Alpha

plot of chunk unnamed-chunk-32

Case Study: Stance Equity - Rolling Beta

plot of chunk unnamed-chunk-33

Case Study: Stance Equity - Rolling volatility

plot of chunk unnamed-chunk-34

Case Study: Stance Equity - Rolling Returns

plot of chunk unnamed-chunk-35

Case Study: Stance Equity - Rolling Sharpe Ratio

plot of chunk unnamed-chunk-36

The End

  • Thanks to all the authors, contributors, testers of the various R packages used
  • PortfolioAnalytics, PerformanceAnalytics,quantmod
  • Questions?