Optimizing the effective number of bets – an example using Canadian retail etfs

Hello all, It is Christmas time and that means family members wanting “stock market” advice. My usual response is not to do any analysis/advice for family members as I have a rather large extended family (by my last count over 100) and I just don’t think it’s appropriate.

So I have worked up a quick example to maximize the effective number of bets using canadian retail etf’s. I did this quick analysis for my mother ( the one person I can’t say no to), however I would not use this to invest directly as different situations will warrant different objectives and constraints.

First and foremost I would like to thank Ross Bennett for his great work on Portfolio Analytics.

The following code simply downloads some etfs and builds a portfolio that minimizes (1/effective number of bets) (so it maximizes the effective number of bets).

As always this is not investment advice and i’m not responsible for the use or misuse of this. This is sample dependent so garbage in and garbage out.

library(quantmod)
library(PerformanceAnalytics)
library(PortfolioAnalytics)
 
EffectiveBets = function(R, w) {
  
 
  # Perform PCA on the returns
  pca <- prcomp(R, cor = FALSE)
  evec <- pca$rotation[] #eigenvectors
  eigval <- pca$sdev^2 #eigenvalues
 
  # Calculate the factor return streams
  inv.evec <- solve(evec) #inverse of eigenvectors
 
  # Calculate your exposure to each factor
  factor.exposure <- inv.evec %*% w
 
  # Calculate the diversification distribution
  # The numerator is the variance concentration curve
  # The denominator is the total portfolio variance
  div.dist <- (factor.exposure^2)*eigval / sum((factor.exposure^2)*eigval)
 
  # Calculate the effective number of bets
  ENB <- exp(-sum(div.dist*log(div.dist)))
 
  return(ENB)
}
 
 
##Estimate the inv.evec and val first when using optimization w first for easy passing to deoptim
 
EffectiveBets_optim = function(weights,inv.evec,eigval){
  factor.exposure <- inv.evec %*% weights
 
  # Calculate the diversification distribution
  # The numerator is the variance concentration curve
  # The denominator is the total portfolio variance
  div.dist <- (factor.exposure^2)*eigval / sum((factor.exposure^2)*eigval)
 
  # Calculate the effective number of bets
  ENB <- exp(-sum(div.dist*log(div.dist)))
 
  return(1/ENB)
 
}
 
 
 
 
###Canadian ETF LISt
canadian_etfs=c("xiu","xsp","cbo","xsb","XBB","XCB","CPD","XRE","ZHY","CLF","PGL","ZIC")
 
getSymbols(paste0(canadian_etfs,".TO"),from='2000-01-01')
 
etf_name_list = paste0(toupper(canadian_etfs),".TO")
 
###Combine all into a "price matrix"
pricemat=NULL
start_dates = data.frame(etf_name=etf_name_list)
start_dates$date = NA
for(etfs in etf_name_list){
  step1 = Ad(get(paste0(etfs)))
  colnames(step1) = etfs
  pricemat = merge.xts(pricemat,step1)
  start_dates[start_dates$etf_name==etfs,]$date=as.Date(start(step1))
 
 
}
returnmat = ROC(pricemat,type="discrete")
 
 
 
##Fix return data
 
 
 
 
retmat= returnmat['2013-04-01/2015-01-01']
retmat[is.na(retmat)]=0
 
 
 
##Estimate inv.evec
pca <- prcomp(retmat, cor = FALSE)
evec <- pca$rotation[] #eigenvectors
eigval <- pca$sdev^2 #eigenvalues
 
# Calculate the factor return streams
inv.evec <- solve(evec) #inverse of eigenvectors
 
###Use Portfolio Analytics to quickly model the portfolio
moms_portfolio = portfolio.spec(assets=colnames(returnmat))
moms_portfolio = add.constraint(portfolio=moms_portfolio,type="full_investment")
moms_portfolio = add.constraint(portfolio=moms_portfolio,type="long_only")
moms_portfolio = add.objective(portfolio=moms_portfolio,name="EffectiveBets_optim",type="risk",arguments=list(inv.evec=inv.evec,eigval=eigval)) ###Place holder 
 
###Optimize (May want to switch to ROI or different optimizer if dealing with more securities)
 
optimal_portfolio = optimize.portfolio(retmat,moms_portfolio,optimize_method="DEoptim",
                                       search_size=5000, trace=TRUE, traceDE=0)

Created by Pretty R at inside-R.org

 

 

Advertisements

4 comments

  1. Sid Johnson · · Reply

    Kyle, you seem to be the only person on the net who has provided code for the effective bet approach, so thank you for that. When I run your code though, the term optimal_portfolio does not have the expected $weights and $out components. In fact, it only has the last five variables in the return values structure, as if it never ran the optimization. Is this code working correctly for you? Thanks

    1. Do you have the DEoptim library? As you need it for PortfolioAnalytics’s optimization.

      install.packages(“DEoptim”) should rectify that.

      I just ran the code and I have an output:

      optimal_portfolio$weights
      XIU.TO XSP.TO CBO.TO XSB.TO XBB.TO XCB.TO CPD.TO XRE.TO ZHY.TO CLF.TO PGL.TO ZIC.TO
      0.000 0.000 0.742 0.020 0.006 0.008 0.000 0.000 0.150 0.064 0.000 0.010

      1. Kyle, thanks much for your quick response. I did not have the package loaded, plus I had typed it, in my troubleshooting excursion, as DEOptim vs DEoptim. Looks like the package could use a little hardening. I’m still getting some errors and got a different set of weights, but you got me unstuck, and I should be able to sort it out. Thanks again!!

        Sid

        >

      2. Hey, DEoptim will yield different answers in the case of this trial as the number of iterations is low and it’s not tuned to converge on a more precise solution. This is for the purposes of exemplifying how to do it, if you’re planning to use code like this in production let me know as there is a fair amount of tuning required in both the estimation and the optimization. Shoot me an email at kyle at kkb.io

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: