According to the Two-fund separation theorem of Modern Portfolio Theory, the investment problem can be decomposed into the following steps:
- Finding the optimal portfolio of risky assets
- Finding the best combination of this optimal risky portfolio and the risk free asset.
This post will concentrate on the second issue first. The problem of finding an optimal risky portfolio will be addressed in the next post.
[The Capital Allocation Line]
To simplify the procedure for finding the optimal combination of the risk free and the risky funds, one can first consider the return on a portfolio consisting of one risky asset and a risk free asset. The return on such a portfolio is simply:
The variance of this combined portfolio is given by:
These two results can be combined to yield the following expression :
This is the Capital Allocation Line (CAL) and represents the set of investment possibilities created by all combinations of the risky and riskless asset. The price of risk is the return premium per unit of portfolio risk and depends only on the prices of available securities. This ratio is also known as the Sharpe ratio. To illustrate how the CAL works, let us first set up some functions to [a] simulate random asset returns from a normal distribution and [b] calculate and draw the CAL connecting one risky asset with the risk free rate. These functions correspond to simulate.assets,CAL.line and DrawCAL as shown below.
############################################################################# # # Simulate asset returns from a normal distribution # ############################################################################# simulate.assets <- function(num.assets){ ret.matrix <- matrix(dimnames=list(c(seq(1,100)),c(paste('Asset',1:num.assets))),(rep(0,num.assets*100)),nrow=100,ncol=num.assets,byrow=FALSE) shock <- matrix(dimnames=list(c(seq(1,100)),c(paste('Asset',1:num.assets))),(rep(0,num.assets*100)),nrow=100,ncol=num.assets,byrow=FALSE) for(i in 1:num.assets){ ret.matrix[,i]=rnorm(100,mean=runif(1,-0.8,0.2),sd=runif(1,0.8,2)) shock[,i] <- rnorm(100,colMeans(ret.matrix)[i],apply(ret.matrix,2,sd)[i]) } sd.matrix <- apply(ret.matrix,2,sd) var.matrix <- var(ret.matrix) risk.free <- 0.02 mean.ret <- colMeans(ret.matrix) sim.assets <- list(ret.matrix,var.matrix,sd.matrix,risk.free,mean.ret,shock) return(sim.assets) }
############################################################################# # # Capital Allocation Line # ############################################################################# CAL.line <- function(type,risky.assets,optimised.portfolio){ if(type=='Assets' && is.null(risky.assets)==FALSE){ num.assets <- ncol(risky.assets[[1]]) asset.returns <- colMeans(risky.assets[[1]]) asset.risk <- risky.assets[[3]] } else if (type=='Sharpe' && is.null(optimised.portfolio)==FALSE){ num.assets <- 1 asset.returns <- optimised.portfolio[[4]][1] asset.risk <- optimised.portfolio[[4]][2] } total.risk <- seq(0,2,by=0.01) risk.free <- risky.assets[[4]] CAL.complete <- vector('list',num.assets) price.risk <-c() total.return <-matrix(rep(0,length(total.risk)*num.assets),nrow=length(total.risk),ncol=num.assets) for(i in 1:num.assets){ price.risk[i] <- (asset.returns[[i]]-risk.free)/asset.risk[i] total.return[,i] <- risk.free+(price.risk[i]*total.risk) CAL.complete[[i]]<-cbind(total.risk,total.return[,i]) colnames(CAL.complete[[i]]) <- c('Total Risk','Total Return') } return(CAL.complete) }
############################################################################# # # Draw Capital allocation Line (s) # ############################################################################# DrawCAL<-function(CAL,risky.assets,optimised.portfolio,legend.draw){ num.lines <- length(CAL) num.assets <- ncol(risky.assets[[1]]) plot.x.max <- max(risky.assets[[3]])+0.2 plot.y.min <- min(risky.assets[[5]])-1 plot.y.max <- max(risky.assets[[5]])+1 windows() par(xaxs="i", yaxs="i") if(num.lines==1 && is.null(optimised.portfolio)==FALSE){ plot(xlab='Standard Deviation',ylab='Expected Return',ylim=c(plot.y.min,plot.y.max),xlim=c(0,plot.x.max),CAL[[1]],col='red',type='l',main='Capital Allocation Line',cex.main=0.85,cex.lab=0.75,cex.axis=0.75,lwd=2) points(x=optimised.portfolio[[4]][2],y=(optimised.portfolio[[4]][1]),type='p',pch=9,col='dark blue',cex=1) } else if(num.lines==1 && is.null(optimised.portfolio)==TRUE){ plot(xlab='Standard Deviation',ylab='Expected Return',ylim=c(plot.y.min,plot.y.max),xlim=c(0,plot.x.max),CAL[[1]],col='red',type='l',main='Capital Allocation Line',cex.main=0.85,cex.lab=0.75,cex.axis=0.75,lwd=2) } else if(num.lines>1){ plot(xlab='Standard Deviation',ylab='Expected Return',ylim=c(plot.y.min,plot.y.max),xlim=c(0,plot.x.max),CAL[[1]],col='red',type='l',main='Capital Allocation Line',cex.main=0.85,cex.lab=0.75,cex.axis=0.75,lwd=2) for(i in 2:num.lines){ lines(CAL[[i]],col='red',type='l',lwd=2) } } points(x=0.01,y=risky.assets[[4]],type='p',pch=15,col='dark green',cex=1) points(x=risky.assets[[3]],y=risky.assets[[5]],type='p',pch=17,col='blue',cex=0.75) text(labels=1:num.assets,x=risky.assets[[3]],y=risky.assets[[5]],pos=3,col='blue',cex=0.65) legend(plot=legend.draw,title='Legend','bottomleft',pch=c(15,17,3,3,8,9,11),col=c('dark green','blue','red','dark orange','black','dark blue','purple'),legend=c('Risk free asset','Risky assets','Capital Allocation Line','Indifference Curves','Optimal Total Portfolio','Max Sharpe Portfolio','Min Variance Portfolio'),ncol=1,bg='white',bty='n',border='black',cex=0.65) }
To Implement these functions,let’s first simulate the data for one asset with100 timeseries observations drawn from a normal distribution with a mean and standard deviation that are themselves drawn from a uniform distribution. A risk free rate is also pre-specified at 0.02 and a simple CAL is drawn to connect these 2 assets as per the expression above.
#Capital Allocation Line sim.one <- simulate.assets(1) cal.one <-CAL.line('Assets',sim.one,NULL) DrawCAL(cal.one,sim.one,NULL,legend.draw=TRUE)
As mentioned above, the CAL is simply the combination of the risk free asset and the risky portfolio (which as of yet has been constrained to contain a single asset). The slope of the CAL is the Sharpe ratio and depicts the amount of excess portfolio return per unit of portfolio risk we can expect. Since every point on the CAL is an investment possibility of allocating wealth between the riskless asset and the risky portfolio (single asset in this case), what determines which of these combinations is optimal? The amount of capital an investor places in the risk free asset versus the risky portfolio is determined by the preferences for risk and return as captured by the utility function examined previously.
Mathematically, the objective of an investor is to find the weights of the risky portfolio that maximises the utility of portfolio returns. Or more succinctly :
The optimal weight for the risky portfolio is given by :
The optimal weight in the risk free asset is then simply (1-w*). Since the indifference curve and the CAL are drawn in the same risk/return space, let’s superimpose an indifference curve with a risk aversion parameter of 1 on the CAL as follows.
utility.contours('Assets',sim.one,1,NULL)
The total optimal portfolio results where investment opportunities as represented by the CAL meet the highest attainable indifference curve as represented by the orange contour. With a risk aversion parameter of 1, the investor exhibits his distaste for risk and places a large weight on the risk free asset versus the risky asset or portfolio. Another investor who is less risk averse (a risk aversion parameter of 0.5) would invest a larger portion of his capital in the risky asset versus the risk free asset and hence the total optimal portfolio is located closer to the simulated risky asset as below.
While the investor prefers to make investments consistent with the risk/return opportunities towards the northwestern corner of the plot – where blue indifference contours are drawn – the available investments as per the capital allocation line do not permit this.
So far we have constrained our risky portfolio to contain only one asset. There is nothing stopping us from simulating multiple risky assets and drawing the CAL between the risk free asset and each of these simulated assets as below.
sim.mult <- simulate.assets(20) cal.mult <- CAL.line('Assets',sim.mult,NULL) DrawCAL(cal.mult,sim.mult,NULL,legend.draw=T)
This post has dealt with the second half of the two fund theorem according to which any investment problem can be addressed by combining the risk free asset (riskless fund) and the risky portfolio (risky fund). So far we have constrained the number of assets contained in the risky portfolio. The task of finding the optimal risky portfolio, the second half of the theorem, shall be addressed in the next post.