Calculating the Efficient Frontier with a Risk-Free Asset

So, I’ve been feeling a little bit bogged down on this efficient frontier topic, and I’m anxious to wrap things up with this post and move on to something more original!

In the previous two posts, I have demonstrated how to calculate the efficient frontier for any number of risky assets, and I’ve shown how to calculate the portfolio weights for each point on the efficient frontier.

In this post, I will conclude this series on the efficient frontier (finally!) by demonstrating how the frontier changes with the addition of a risk-free asset.

An example Octave script is provided for calculating and plotting the efficient frontier, capital allocation line, and tangency portfolio.

Tangency Portfolio with a Risk-Free Asset w/return R

The tangency portfolio is the intercept point if we draw a tangent line from the risk-free rate of return (on the y-axis) to the efficient frontier for risky assets. 

The equations used to calculate the portfolio weights, expected return, and variance for the tangency portfolio are shown in this section.

The variables used in these equations are described in more detail in the previous posts.  However, to review briefly, \mathbf{\bar{z}} is the vector of expected returns for the risky assets, and \mathbf{S} is the covariance matrix for the returns of these assets.  The values for A, B, C, and \Delta are intermediate values calculated using the portfolio statistics and the equations for these values are shown in my initial post on this topic.   The value R is the return on the risk-free asset.  The value \mathbf{w_{t}} is a vector showing the weight of each asset (weights sum to 1) in the tangency portfolio, and \bar{Z_{t}} and \sigma_{t}^{2} are the expected return and variance of the tangency portfolio.

\mathbf{w_{t}}=\frac{\mathbf{S^{-1}}\left ( \mathbf{\bar{z}}-R \mathbf{1}\right )}{B-AR}


\sigma _{t}^{2}=\mathbf{w_{t}^{'}Sw_{t}}=\frac{C-2RB+R^{2}A}{\left ( B-AR \right )^{2}}

Calculating a Point on the Capital Allocation Line

The Capital Allocation Line or CAL is the tangent line from the risk-free rate of return (on the y-axis) to the efficient frontier for risky assets. The points on this line represent the highest expected return we can get at a given level of risk when we have access to a risk-free asset. 

All points on this line are a combination of the tangency portfolio and the risk-free asset.  If the weight of the portfolio in the tangency portfolio is given as y then the weight in the risk-free asset must be 1-y.  The value of y can be calculated for any desired expected return, \bar{Z_{c}} on the CAL using this equation:


Using this y-value we can calculate the standard deviation at this point on the CAL:

\sigma_{c}= y\sigma_t

By combining these equations, we get the general equation for the CAL:

\bar{Z_c}=R+\left [ \frac{\bar{Z_t}-R}{\sigma_t} \right ]\sigma_c

Example Calculation using Octave

As an example, let’s consider the four risky assets used in the efficient frontier examples in the previous posts.  The expected return vector and covariance matrix for these assets is given here:

\mathbf{\bar{z}}=\begin{bmatrix} 14\\ 12\\ 15\\ 7 \end{bmatrix}

 \mathbf{S}=\begin{bmatrix} 185& 86.5& 80& 20\\ 86.5& 196& 76& 13.5\\ 80& 76& 411& -19\\ 20& 13.5& -19& 25 \end{bmatrix}

The risk-free rate will be assumed to be 3%, and the target return will be set to 14%.

If we implement the equations for the tangency portfolio and CAL in Octave, we can calculate the portfolio weights for the tangency portfolio (\mathbf{w_{t}}), and the weight of the total portfolio which should be in the tangency portfolio (y) and the risk-free asset (1-y) to achieve the target expected return.

The portfolio weights for the tangency portfolio are shown here:

\mathbf{w_{t}}=\begin{bmatrix} 0.1063\\ 0.0600\\ 0.1319\\ 0.7019 \end{bmatrix}

The weight in the tangency portfolio is:


Since this value is greater than 1, that means we have a short position in the risk-free asset with a weight of 1-y or -0.804.

Note that this is a somewhat unrealistic scenario since we cannot borrow at the true risk-free rate.  In practice our borrowing rate would be higher, and the actual risk-free rate would be used only for portfolios where we had a positive weight in the risk-free asset.

The plot of the efficient frontier, tangency portfolio, and the CAL are shown here:


Octave Code:

This Octave code will calculate and plot the efficient frontier, tangency portfolio and the CAL.  The script can be modified for a different set of assets by updating the expected returns vector, the covariance matrix, the target return, and the risk free rate.   The script will also work in Matlab.

clear all;
close all;

% Mean Variance Optimizer Inputs

% S is matrix of security covariances
S = [185 86.5 80 20; 86.5 196 76 13.5; 80 76 411 -19; 20 13.5 -19 25]

% Vector of security expected returns
zbar = [14; 12; 15; 7]

% Risk Free Asset Return
R = 3

% Target Return
mu_tar = 14

% Calculating Variables

% Unity vector..must have same length as zbar
unity = ones(length(zbar),1)

% Vector of security standard deviations
stdevs = sqrt(diag(S))

A = unity'*S^-1*unity
B = unity'*S^-1*zbar
C = zbar'*S^-1*zbar
D = A*C-B^2

% Calculate Lambda and Gamma
lambda_target = (C - mu_tar*B)/D;
gamma_target =  (mu_tar*A-B)/D;

% Efficient Frontier
mu = 1:200;
mu = mu/10;

minvar = ((A*mu.^2)-2*B*mu+C)/D;
minstd = sqrt(minvar);

title('Efficient Frontier with Individual Securities','fontsize',18)
ylabel('Expected Return (%)','fontsize',18)
xlabel('Standard Deviation (%)','fontsize',18)

% Global Minimum Variance Portfolio

% Mean and Variance of Global Minimum Variance Portfolio
mu_g = B/A
var_g = 1/A
std_g = sqrt(var_g)

% Minimum Variance Portfolio Weights
w_g = (S^-1*unity)/A

% Tangency Portfolio with a Risk Free Asset

% Expected Return of Tangency Portfolio
ztan = (C-B*R)/(B-A*R);

% Variance and Standard Deviation of Tangency Portfolio
vartan = (C-2*R*B + R^2*A)/((B-A*R)^2);
stdtan = sqrt(vartan);

% Weights for Tangency Portfolio
w_tan = (S^-1*(zbar - R*unity))/(B-A*R)

% Tangency Line
mu_tan = mu(mu >= R);
minvar_rf = (mu_tan-R).^2/(C-2*R*B+A*R^2);
minstd_rf = sqrt(minvar_rf);

% Weights for w_d (tangency when R=0)
w_d = (S^-1*zbar)/B;

% Target Return Portfolio w/and w/o Risk Free Asset

% Weights for portfolio with target return = 14%, w/o risk-free asset

w_s = (lambda_target*A)*w_g + (gamma_target*B)*w_d;

% Expected Return of Target Portfolio (should match target)
mu_s = w_s'*zbar;

% Variance and Standard Deviation of target portfolio
var_s = w_s'*S*w_s;
std_s = sqrt(var_s);

% Weights for portfolio with target return = 14%, w/risk free asset

y = (mu_tar - R)/(ztan-R);
stdtar = stdtan*y;

% Tangency Plot

text(0.5+std_g,mu_g,'Global Minimum Variance Portfolio','fontsize',12);
text(0.5+stdtan,ztan,'Tangency Portfolio','fontsize',12);
text(0.5+std_s,mu_s,'Target Return of 14% w/o Risk-Free Asset','fontsize',12);
text(stdtar-8,mu_tar+0.5,'Target Return of 14% w/Risk-Free Asset','fontsize',12);
title('Efficient Frontier with Tangency Portfolio','fontsize',18)
ylabel('Expected Return (%)','fontsize',18)
xlabel('Standard Deviation (%)','fontsize',18)

3 Responses to “Calculating the Efficient Frontier: Part 3”

  1. Hey CalcInv.

    Fantastic article series. As Frontcon (MatLab) is not implemented in Octave, these pages has been great inspiration.

    I have two questions. I would like to use this approach for a portfolio optimisation problem. But I need to evaluate on daily returns and stdev over daily returns (and in decimals instead of % – as in 0.10 instead of 10% etc.). I’m not sure how to do this trick. ( like transforming daily Sharpe to yearly with Yearly sharpe = Daily sharpe * sqrt(252)) – 252 trading days.

    Also how do you add constraints, eg. no short positions (negative weight). ?

    All the best!


    • Hi Christian,

      As long as the horizon (daily, monthly, yearly, etc) is consistent for both the expected return vector and the covariance matrix the program should still work. You should be able to do this with daily returns without any changes, and it should work with decimals returns….again as long as everything is consistent.

      The constraints problem is trickier. I don’t know of any non-iterative way to do the constrained optimization…i.e. I don’t think there is an easy modification you can make to the linear algebra equations. Instead I think you need to use some kind of iterative optimization technique.


  2. This looks very useful, thanks!

    I seem to have a problem running this with my data, in particular I often get very small numbers in my covariance matrix (sometimes it’s singular) and the efficient frontier doesn’t look right.

    If my assets are absolute weekly index prices am I correct in thinking that my expected returns are just the mean relative value of each index? E.g. I have zbar = [1.2; 13.51; 0.06; 0.88; 2.52]. And the covariance matrix is just cov(data) with data being the matrix of absolute prices, with each column being an asset, and each row a week? I’m not sure what I’m doing wrong, any help is appreciated.

Leave a Reply

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>