# 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)

}

###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){
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))

###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

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