Workshop 3, Financial Modeling and Programming

Author

Alberto Dorantes, Ph.D.

Published

November 19, 2025

Abstract
This is an INDIVIDUAL workshop. In this workshop we review the basics of portfolio theory and portfolio optimization. We learn how to program estimations for portfolio return and risk, and portfolio optimization.

0.1 General Directions for each workshop

You have to work on Google Colab for all your workshops. In Google Colab, you MUST LOGIN with your @tec.mx account and then create a google colab document for each workshop.

You must share each Colab document (workshop) with the following account:

  • cdorante@tec.mx

You must give Edit privileges to these accounts.

In Google Colab you can work with Python or R notebooks. The default is Python notebooks.

Your Notebook will have a default name like “Untitled2.ipynb”. Click on this name and change it to “W1-Programming-YourFirstName-YourLastname”.

In your Workshop Notebook you have to:

  • You have to do all the challenges to get full credit for the workshop. The accuracy of the challenge will not significantly affect your grade; completion will have more weight for your workshop grade.

  • It is STRONGLY RECOMMENDED that you write your OWN NOTES as if this were your personal notebook to study for the FINAL EXAM. Your own workshop/notebook will be very helpful for your further study.

Once you finish your workshop, make sure that you RUN ALL CHUNKS. You can run each code chunk by clicking on the “Run” button located in the top-left section of each chunk. You can also run all the chunks in one-shot with Ctrl-F9. You have to submit to Canvas the web link of your Google Colab workshop.

1 What is a Portfolio?

A portfolio is a set of 2 or more financial assets. A financial asset can of any type such as stock, bond, risk-free instrument, derivative, commodity. The portfolio owner needs to decide how much money allocate to each individual asset. The main advantage of financial portfolios is the possibility to diversify risk, while maintaining an expected rate of return.

In this workshop we review practical easy examples of 2-asset and 3-asset portfolios with the purpose to illustrate portfolio theory and portfolio optimization.

It is recommended that you review the lecture notes posted in the course site where portfolio theory, matrix algebra, and portfolio optimization are explain in more detail.

2 Calculating historical returns and risk of a portfolio

2.1 Historical return of a portfolio

Let’s start with an example of calculating historical returns of a 2-asset portfolio. Imagine that we want to calculate how much return you would have realized if you had invested in the following portfolio between January 2019 to December 2020:

Wal Mart: 70%

Tesla: 30%

We start downloading historical monthly prices from Yahoo Finance from 2020 to Oct 2025:

import pandas as pd
import numpy as np
import yfinance as yf

tickers = ["WMT","TSLA"]
start_date = "2020-01-01"
end_date = "2025-10-31"

# Donwloading adjusted monthly prices:
prices = yf.download(tickers, start=start_date, end=end_date, interval="1mo",auto_adjust=True)["Close"]

[                       0%                       ]
[*********************100%***********************]  2 of 2 completed
prices.head()
Ticker           TSLA        WMT
Date                            
2020-01-01  43.371334  35.142193
2020-02-01  44.532665  33.051899
2020-03-01  34.933334  34.875149
2020-04-01  52.125332  37.474312
2020-05-01  55.666668  38.248161

Be aware that the yf.download function sort the columns alphabetically (not in the order I indicate).

Using the stock adjusted prices, I create a dataset with growth indices starting in $1. I divide each monthly price by the first monthly price:

growth_indices = prices / prices.iloc[0]

I create a function to do a time plot for all variables of a time-series data frame:

import matplotlib.pyplot as plt

def plot_time_series(df, title, y_label, legend_title='Legend'):
    """
    Generates and displays a time series plot from a DataFrame.
    Parameters:
    df (pandas.DataFrame): The DataFrame containing the time series data.
    title (str): The title of the plot.
    y_label (str): The label for the Y-axis.
    legend_title (str): The title for the legend.
    """
    plt.figure(figsize=(12, 6))
    ax = plt.gca()
    df.plot(ax=ax)
    plt.title(title)
    plt.xlabel('Date') # Assuming the DataFrame index is a datetime index for time series.
    plt.ylabel(y_label)
    plt.grid(True)
    plt.legend(title=legend_title)
    plt.show()

I plot both growth indexes:

plot_time_series(growth_indices, "$1 invested in each stock over time","Investment value", "Stock")

I create a data frame with the cumulative returns for each stock. The cumulative return is also called Holding-Period-Return (HPR), which is the percentage gained of an investment if you hold the investment from the beginning up to any point in time.

Since the growth_indices are growth factors of the form (1+Return), then if I subtract 1 from the growth_indices I will get the HPR month by month:

HPR = growth_indices - 1 
HPR.head()
Ticker          TSLA       WMT
Date                          
2020-01-01  0.000000  0.000000
2020-02-01  0.026776 -0.059481
2020-03-01 -0.194552 -0.007599
2020-04-01  0.201838  0.066362
2020-05-01  0.283490  0.088383

I will calculate the historical cumulative return (HPR) I would’ve gained if I had invested in a portfolio composed of these stocks with the following allocation: 70% for WMT, and 70% for TSLA.

I set the weight for each stock to form a portfolio:

# Since TSLA is the first column, then w1 will be the TSLA weight:
w1 = 0.30
w2 = 0.70
# The columns appear in alphabetical order:
HPR.columns
Index(['TSLA', 'WMT'], dtype='object', name='Ticker')

The holding period return for each month of this portfolio would be the weighted average of the holding period stock returns:

PortfolioHPR_t=0.7*HPR1_t+0.3*HPR2_t

When we buy a portfolio, the initial weights we allocate constantly change over time according to the valuation of each stock (stock price) and the # of shares.

For example, if stock 1 had a much higher return than stock 2, then the weight w1 will increase to more than 70% and weight w2 will be less than 30%.

We can calculate the holding-period portfolio return for all months as follows:

HPR['PORT'] = w1 * HPR['TSLA'] + w2 * HPR['WMT']
HPR.head()
Ticker          TSLA       WMT      PORT
Date                                    
2020-01-01  0.000000  0.000000  0.000000
2020-02-01  0.026776 -0.059481 -0.033604
2020-03-01 -0.194552 -0.007599 -0.063685
2020-04-01  0.201838  0.066362  0.107005
2020-05-01  0.283490  0.088383  0.146915

I can visualize the historical holding returns for the stocks and the portfolio :

plot_time_series(HPR, "Cumulative return over time","HPR", "Instrument")

2.2 Historical risk (volatility) of a portfolio

Historical portfolio risk is calculated using historical period returns (not cumulative or HPR). In this case, we need to calculate historical monthly returns of the portfolio, and then we can calculate its standard deviation as a measure of monthly volatility.

Another important measure for portfolio risk is Value at Risk, but we will not cover that measure in this workshop.

I recommend to use the continuously compounded (cc) returns to calculate the standard deviation of returns. The main reason is that cc returns behave more like a normal distribution, and also because cc returns are more conservative measure than simple returns: for negative returns, cc returns have higher magnitude, and for positive returns, cc returns are less than simple returns.

In this example, to calculate the portoflio historical monthly returns I need to use an index as a substitute for its value or price. I can construct this index from the HPR. If I add 1 to the HPR I will get a factor growth of $1.00 over time, which can be treated as a price or portfolio value by month:

Since the HPR dataset already has the cumulative return for both stocks and the portfolio, then:

# I re-generate growth_indices for the HPR dataest to calculate the indices for both stocks and the Portfolio:
growth_indices = (1 + HPR) 

Then, we can calculate the continuously compounded returns (log returns) for the stocks and the portfolio. I use the growth_indices dataset:

log_prices = np.log(growth_indices) # I calculate the log of the indices
ccr = log_prices.diff(1).dropna() # I calculate the log return, equal to the log of the price minus its log value of the previous month

We can calculate descriptive statistics of the portfolio cc returns:

ccr.describe()
Ticker       TSLA        WMT       PORT
count   69.000000  69.000000  69.000000
mean     0.034115   0.015326   0.023819
std      0.191828   0.056253   0.116386
min     -0.457813  -0.173432  -0.277649
25%     -0.100372  -0.017390  -0.056334
50%      0.026275   0.015039   0.016480
75%      0.171905   0.053695   0.090154
max      0.554719   0.121099   0.318830

Remember that in Finance, the standard deviation of period returns is usually called volatility. I can calculate monthly portfolio volatility as:

# Monthly volatility is the standard deviation of monthly returns
port_monthly_vol = ccr.std() 
print(port_monthly_vol)
Ticker
TSLA    0.191828
WMT     0.056253
PORT    0.116386
dtype: float64
# I can annualize volatility by multiplying the monthly volatility times the squared root of 12 (12 months in a ayear)
port_annual_vol = np.sqrt(12)*port_monthly_vol
print(port_annual_vol)
Ticker
TSLA    0.664513
WMT     0.194865
PORT    0.403171
dtype: float64
# I calculate mean monthly return:

port_mean_ret = ccr.mean()
print(port_mean_ret)
Ticker
TSLA    0.034115
WMT     0.015326
PORT    0.023819
dtype: float64
# I calculate an annualize mean return:
port_annual_ret = 12 * port_mean_ret # Multiplying by 12 we anualize the monthly mean return  
print(port_annual_ret)
Ticker
TSLA    0.409378
WMT     0.183913
PORT    0.285833
dtype: float64

Note that the ccr dataset will end up with 3 columns: 2 for the stocks, and 1 for the portfolio we constructed. Then, all calculations

We can say that the annual volatility of this portfolio composed of 70% of Wal Mart and 30% of Tesla calculated from 2020 up to Oct 2025 was about 66.4513, 19.4865, 40.3171%.

We can complement this including the mean historical annual return of the portfolio. We can say that this portfolio had an average annual return of 40.9378, 18.3913, 28.5833%, and an annual volatility of 66.4513, 19.4865, 40.3171%.

We can also appreciate the historical risk of a portfolio if we do a Box Plot of its monthly returns. In this case, it is recommended to use SIMPLE returns instead of log returns. The main reason is that we humans understand simple returns, but not log returns!

I can create a dataset of historical simple monthly return using the log return dataset. Remember that simple returns can be calculated from log returns as follows:

R = e^{r} - 1 Where r is the log return (continuously compounded return), and R is simple return (simple % change of price)

Also, we can express the log return as a function of simple return:

r = log(1+R) Then, I create a historical dataset of simple return for the stocks and the portfolio:

R = np.exp(ccr) - 1 

I use this dataset to do the Box-Plot to better appreciate the historical movements of monthly returns over time:

plt.figure(figsize=(10, 6))
plt.boxplot(R, labels=R.columns) # Explicitly set labels for clarity
{'whiskers': [<matplotlib.lines.Line2D object at 0x00000241FB917250>, <matplotlib.lines.Line2D object at 0x00000241FB917390>, <matplotlib.lines.Line2D object at 0x00000241FB917B10>, <matplotlib.lines.Line2D object at 0x00000241FB917C50>, <matplotlib.lines.Line2D object at 0x00000241FB944410>, <matplotlib.lines.Line2D object at 0x00000241FB944550>], 'caps': [<matplotlib.lines.Line2D object at 0x00000241FB9174D0>, <matplotlib.lines.Line2D object at 0x00000241FB917610>, <matplotlib.lines.Line2D object at 0x00000241FB917D90>, <matplotlib.lines.Line2D object at 0x00000241FB917ED0>, <matplotlib.lines.Line2D object at 0x00000241FB944690>, <matplotlib.lines.Line2D object at 0x00000241FB9447D0>], 'boxes': [<matplotlib.lines.Line2D object at 0x00000241FB917110>, <matplotlib.lines.Line2D object at 0x00000241FB9179D0>, <matplotlib.lines.Line2D object at 0x00000241FB9442D0>], 'medians': [<matplotlib.lines.Line2D object at 0x00000241FB917750>, <matplotlib.lines.Line2D object at 0x00000241FB944050>, <matplotlib.lines.Line2D object at 0x00000241FB944910>], 'fliers': [<matplotlib.lines.Line2D object at 0x00000241FB917890>, <matplotlib.lines.Line2D object at 0x00000241FB944190>, <matplotlib.lines.Line2D object at 0x00000241FB944A50>], 'means': []}
plt.title('Box Plot of Monthly Returns for TSLA, WMT, and Portfolio (PORT)')
plt.ylabel('Monthly Returns')
plt.xlabel('Asset')
plt.grid(True)
plt.show()

The box contains the returns between the quartile 1 (Q1) and the quartile 3 (Q3), while the mean return is the red point and the mdian (Q2) is the mid vertical line.

Can you appreciate the risk of the stocks and the portfolio?

Which of these 3 instruments is more volatile?

Which of these 3 instruments have offered the highest returns?

Which of these 3 instruments you would have liked to own in this time period, and why?

It is very important to be aware of the granularity of the historical data used to calculate volatility and mean returns. Granularity of a dataset refers to the frequency of periods. In this case, we are using monthly returns, so the granularity is monthly.

Then, we can have a better interpretation of portfolio volatility and portfolio return if we convert both values from monthly to annual. It is very common to report annual mean portfolio return and annual portfolio volatility based on monthly data.

To convert monthly portfolio mean return to annual portfolio mean return, we just multiply the monthly average return times 12.

However, to convert from monthly to annual volatility, we need to multiply by the squared root of the numbers of the periods in the year, in this case, 12.

In the following sections we review what is variance and standard deviation of returns, and how they are manually calculated.

2.2.1 What is variance of returns?

Variance of any variable is actually the arithmetic mean of squared deviations. A squared deviation is the value resulting from subtracting the value of the variable minus its mean, and the square the value.

The mean of returns is estimated as:

\bar{r} =\frac{r_{1}+r_{2}+...+r_{N}}{N}

The variance is estimated as:

VAR(r)=\frac{(r_{1}-\bar{r})^{2}+(r_{2}-\bar{r})^{2}+...+(r_{N}-\bar{r})^{2}}{N}

Variance is a measure of dispersion. The higher the variance, the more dispersed the values from its mean. It is hard to interpret the magnitude of variance. That is the reason why we need to calculate standard deviation, which is basically the squared root of the variance.

2.2.2 What is standard deviation?

Standard deviation of a variable is the squared root of the variance of the variable:

SD(r)=\sqrt{VAR(r)}

Then, the standard deviation of returns can be interpreted as a standardized average distance from each value of the variable from its mean.

The standard deviation of returns is called volatility. Then, volatility of returns tells us an idea of how much on average (above or below) the period returns move from its mean.

We can calculate volatility of a single stock, or volatility of a portfolio composed of 2 or more stocks.

2.3 Historical Sharpe ratio of a portfolio

The Sharpe ratio is a standardized measure of portfolio premium return after considering its volatility.

A premium return is the return above the risk-free rate. In Mexico the risk-free rate is the CETES; in the US, the risk-free rate is the Treasury Bills.

Then, the Sharpe ratio tells us how much portfolio returns (above the risk free rate) we can expect for each percent point of volatility. Let’s see the formula:

SharpeRatio=\frac{(PortfolioReturn-riskfreeRate)}{PortfolioVolatility}

3 Calculating expected portfolio return

Up to now we have calculated historical portfolio returns and risk. Here we review how to estimate future expected portfolio returns and risk based on Portfolio Theory developed by Harry Markowitz.

3.1 Calculating expected asset return

We will use the simpler method to estimate the expected return of each stock, which is the geometric mean of historical returns. Other methods to estimate expected stock return are a) the CAPM regression model, b) ARIMA models.

The geometric mean of historical returns is the average period return needed so that holding an investment at that geometric mean return per period, we will get the final holding return of the stock.

The mathematical formula of geometric mean return is:

GeomMean(1+R)=\sqrt[N]{(1+R_{1})(1+R_{2})...(1+R_{N})}-1

Where R_t is the historical return for period t. In this formula we have N historical periods (can be months)

Another easier way to calculate geometric mean of returns is to calculate the arithmetic mean of continuously compounded returns, and then convert the result to simple return by applying the exponential function:

ER=GeomMean(1+R)-1=e^{\bar{r}}-1

Where \bar{r} is the arithmetic mean of historical returns:

\bar{r}=\frac{r_{1}+r_{2}+...+r_{N}}{N}

3.2 EXERCISE - Calculate expected monthly return for WMT and TSLA

Calculate the expected monthly return of Wal Mart and Tesla using the price dataset, which has historical monthly prices for both stocks.

# Write the code 

Now that we have individual expected returns we can estimate the expected return of a portfolio composed of the stocks.

3.3 Calculating expected portfolio return

The expected portfolio returns is the weighted average of the individual expected return of the stocks of the portfolio.

Imagine we have a 2-stock portfolio composed as follows:

WalMart: 70%

Tesla: 30%

3.3.1 Method 1: weighted average using a sum of products

We use the weights (%) allocated for each asset to calculate the weighted average as the portfolio expected return:

ER[PORT] = w1 * ER_1+w2*ER_2

3.3.2 Method 2: weighted average using matrix algebra

Another way to calculate the expected return of a portfolio is using matrix algebra. This is a very useful method when we have many assets in the portfolio since it is very easy to compute.

If you do not remember how to multiply matrices, it is strongly recommended to review this (you can read Note 2 of Portfolio Theory).

Matrix multiplication is used to compute sum of products or sum of multiplications.

For example, the way to estimate the expected return of our portfolio is the following:

ERPort=t\left(W\right)*ER

The transposed of a matrix or a vector is the conversion of the rows by columns and columns by rows. Transposing is like rotating a vector or a matrix 90 degrees:

t\left(\left[\begin{array}{c} w_1\\ w_2 \end{array}\right]\right)=\left[\begin{array}{cc} w_1 & w_2\end{array}\right]

Then, the previous matrix multiplication was:

\begin{bmatrix}w_{1} & w_{2}\end{bmatrix}*\begin{bmatrix}ER_{1}\\ ER_{2} \end{bmatrix}

\begin{bmatrix}w_1 & w_2\end{bmatrix}*\begin{bmatrix}ER_1\\ ER_2 \end{bmatrix}=w_1*ER_1+w_2*ER_2

With this multiplication we got the same expected portfolio return as above.

ERPort=\begin{bmatrix}w_{1} & w_{2}\end{bmatrix}*\begin{bmatrix}ER_{1}\\ ER_{2} \end{bmatrix}

3.4 EXERCISE - Calculate Expected return of the Portfolio

Using both methods, write code to calculate the Expected Return of the Portfolio composed of:

30% Tesla and 70% Walmart

You have to get the same result using both methods.

Briefly explain your code

4 Expected portfolio risk

Before we calculate the expected portfolio risk we need to understand what is the expected portfolio variance.

According to Portfolio Theory, the expected variance of a 2-asset portfolio returns is given by:

VAR(PortReturns)=w_{1}^{2}VAR(r_{1})+w_{2}^{2}VAR(r_{2})+2w_{1}w_{2}COV(r_{1},r_{2})

r_1 refers to returns of stock 1, and r_2 refers to returns of stock 2.

COV(r_1,r_2) is the covariance of return 1 and return 2.

Check the lecture note Basics of Portfolio Theory-Note 1 to understand why this is the way to estimate the expected variance of a 2-asset portfolio.

It is worth to remember what is covariance.

4.1 What is covariance of 2 stock returns?

The covariance of 2 stock returns is the arithmetic mean of the product return deviations. A deviation is the difference between the stock return in a period t and its mean. Here is the formula:

COV(r_{1},r_{2})=\frac{(r_{(1,1)}-\bar{r_{1}})(r_{(2,1)}-\bar{r_{2}})+(r_{(1,2)}-\bar{r_{1}})(r_{(2,2)}-\bar{r_{2}})+(r_{(1,3)}-\bar{r_{1}})(r_{(2,3)}-\bar{r_{2}})+...}{N}

Were:

r_{(1,1)} is the return of stock 1 in the period 1

r_{(2,1)} is the return of stock 2 in the period 1

Then:

r_{(i,j)} is the return of stock i in the period j

\bar{r_{1}} is the average return of stock 1

\bar{r_{2}} is the average return of stock 2

Then, in the numerator we have a sum of product deviations. Each product deviation is the deviation of the stock 1 return multiplied by the deviation of the stock 2 return.

The covariance is a measure of linear relationship between 2 variables. If covariance between stock return 1 and stock return 2 is positive this means that both stock returns are positively related. In other words, when stock 1 return moves up it is likely that stock 2 return moves up and vice versa; both returns move in the same direction (not always, but mostly).

If covariance is negative that means that stock 1 return is negatively related to stock 2 return; when stock 1 return moves up it is likely that stock 2 return moves down.

Covariance can be a negative or positive number (it is not limited to any number). It is very difficult to interpret the magnitude of covariance. It is much more intuitive if we standardize covariance.

The standardization of the covariance is called correlation.

4.2 What is correlation of 2 stock returns?

Correlation of 2 stock returns is also a measure of linear relationship between both returns. The difference compared to covariance is that the possible values of correlation is between -1 and +1, and the correlation gives us a percentage of linear relationship.

Correlation between 2 returns is the covariance between the 2 returns divided by the product of standard deviation of return 1 and standard deviation of return 2.

We calculate correlation as follows:

CORR(r_{1},r_{2})=\frac{COV(r_{1},r_{2})}{SD(r_{1})SD(r_{2})}

Correlation has the following possible values:

-1<=CORR(r_{1},r_{2})<=+1

4.3 Expected variance of a portfolio

Now we can calculate the expected variance of our portfolio according to the previous formula:

4.3.1 Method 1: using sum of products

In the case of a 2-asset portfolio, the sum of product is:

VAR(PortReturns)=w_{1}^{2}VAR(r_{1})+w_{2}^{2}VAR(r_{2})+2w_{1}w_{2}COV(r_{1},r_{2})

With more assets, this formula becomes more complicated.

See my Note: “Basics of Portfolio Theory Part 1”

4.3.2 Method 2: using matrix algebra

Another faster method to get the expected variance of a portfolio is by multiplying the following matrices:

t\left(W\right)*COV*W

Where:

W=\begin{bmatrix}w_{1}\\ w_{2} \end{bmatrix}

And COV is the Variance-Covariance matrix, which has the return variances in the diagonal and the pair correlations in the non-diagonal:

COV=\begin{bmatrix}VAR(r_{2}) & COV(r_{1},r_{2})\\ COV(r_{2},r_{1}) & VAR(r_{1}) \end{bmatrix}

4.4 Expected risk of a portfolio

To get the expected risk of a portfolio, we simply get the squared root of the expected variance:

PortRisk=SD(PortReturns)=\sqrt{VAR(PortReturns)}

4.5 EXERCISE - Calculate Expected Portfolio Variance with both methods

Write the code to calculate the Portfolio variance of the same portfolio of WMT and TSLA using both methods. Briefly explain your code and result

It is always good to review the correlation matrix of the asset returns of a portfolios. We can get the correlation matrix from the covariance matrix as follows:

# Write the code 

4.6 EXERCISE - Calculate the correlation matrix of the stocks

Write code to calculate the correlation matrix of both returns. Show your result and briefly explain

# Write the code 

4.7 EXERCISE - Calculate Portfolio expected Risk

Write code to calculate the Portfolio expected monthly and annual risk of the portfolio. Interpret your results.

# Write the code 

4.8 Drivers of Portfolio Diversification

Financial portfolios allow an investor to diversify the risk. The main drivers of portfolio diversification are:

  1. N - the number of financial assets. The more the financial assets, the higher the expected diversification.

  2. Combination of pair of correlations between asset returns. The less the correlation of the pair of assets, the more the diversification.

The first driver is just given by N, the number of assets.

The second driver can actually be manipulated by changing the weights allocated for each asset.

In the following section we illustrate how changing asset weights actually change both, the expected return of the portfolio and the expected portfolio volatility.

5 Risk-return space - set of feasible portfolios

Weight combination determines both expected risk and expected return of a portfolio. Let’s do an example with the same 2-asset portfolio:

5.1 Frontier of 2-asset portfolios

Let’s create a set of 11 portfolios where we change the weight assigned to the first stock from 0 to 1 changing by 0.10. We can create a matrix of weights, where each column represents one portfolio:

W=\begin{bmatrix}0 & 0.1 & 0.2 & 0.3 & 0.4 & 0.5 & 0.6 & 0.7 & 0.8 & 0.9\\ 1 & 0.9 & 0.8 & 0.7 & 0.6 & 0.5 & 0.4 & 0.3 & 0.2 & 0.1 \end{bmatrix}

We had already calculated the vector of expected return for each stock:

ER=\begin{bmatrix}ER_{1}\\ ER_{2} \end{bmatrix}=\begin{bmatrix}0.00775\\ 0.05588 \end{bmatrix}

Using the advantage of matrix algebra we can easily get the 11 portfolio expected returns as follows:

ERPortfolios=t(W)*ER

5.2 EXERCISE - Using Matrix Algebra calculate the expected return and risk

Using the previous 11 portfolio combinations, write code to calculate:

  • Expected monthly and annual return for the 11 portfolios

  • Expected monthly and annual risk for the 11 portfolios

# Write the code 

5.3 EXERCISE - Plot expected risk vs expected return of the 11 portfolios

# Write the code 

With your previous result, plot the expected risk and return of the 11 portfolios. Put expected risk in the X axis, and expected return in the Y axis.

Which portfolio has the lowest risk? Which portfolio has the highest expected return?

Explain this plot.

This plot is called the frontier of feasible portfolios of 2 assets.

Interestingly, for portfolios with 3 or more assets, the possibilities of feasible portfolios become will not be a nice frontier like this. The feasible portfolios will be in between a frontier. In other words, for these portfolios some feasible portfolios will not be efficient since there will be other feasible portfolios with the same level of expected risk, but with higher expected return.

Let’s do an example of 4-asset portfolios.

6 CHALLENGE 1 - Risk-return space of 4-asset portfolios

Add add 2 stocks to our portfolio: Oracle (ORCL) and Freeport-McMoran, Inc (FCX).

You have to write code to create a data frame with historical monthly prices and returns for WMT, TSLA, ORCL and FCX from 2020 to Oct 2025.

You have to create many feasible portfolios with random weights, but with the condition that the sum of the weights must be 1 (100%). You have to create 1,000 random portfolios. Write the code to create a data structure to store these 1,000 portoflios, where each portfolio has 4 random weights.

Using matrix algebra you have to calculate:

  • Expected return for the 1,000 portfolios

  • Expected risk for the 1,000 portfolios

  • Plot the expected risk vs expected return of the 1,000 portfolios. Interpret this plot with your words

# Write the code 

The problem we have when we have 3 or more assets in a portfolio is that we need to find the efficient frontier to get only those portfolios that maximize the expected return for each level of expected risk.

Here is where we need to find optimization algorithms to do this.

In the lecture note Basics of Portfolio Theory - Part III I explain what type of optimization methods can be used.

Fortunately, we can use Python packages that already do these complicated optimization algorithms.

7 Portfolio optimization

Out of all feasible portfolios we might be interested in the following:

  1. The portfolio with the least expected risk of all - The Global Minimum Variance Portfolio (GMV)

  2. The efficient frontier - all portfolios that offer the highest expected return for any level of expected risk

  3. The tangent/optimal portfolio - The portfolio with the highest Sharpe Ratio

We will use the PyPortfolioOpt Python library:

Check the documentation here:

https://pyportfolioopt.readthedocs.io/en/latest/

8 CHALLENGE 2 - Portfolio Optimization

Using the same 4 stocks we used above, and allowing for short-sales, you have to do write the code to do the following estimations:

  • Calculate the Global Minimum Variance (GMV) Portfolio. Interpret your result

  • Calculate and show the Efficient Frontier. Interpret your result

  • Calculate the Tangent / Optimal Portfolio. Use an annual risk-free rate of 3%. Interpret your result.

  • Calculate the Capital Market Line. Use an annual risk-free rate of 3%. Interpret your result

In case you end up with one negative weight in any of the previous optimization (short position), calculate the corresponding portfolio without allowing for short sales.

# Write the code 

The Capital Market Line (CML) is the set of possible efficient portfolios represented in the line that goes from the risk-free rate to the tangent portfolio. One of the main findings of portfolio theory is that when we add 1 risk-free instrument to a portfolio composed of stocks, the new efficient frontier becomes the Capital Market Line (instead of the hyperbola), which is more efficient that the previous efficient frontier (the hyperbola).

Then, an investor can play between the tangent portfolio and the risk-free rate to move in the CML. If an investor has a middle-level aversion to risk, he/she might allocate 50% to the risk-free asset and the rest 50% in the tangent portfolio, locating the portfolio in a mid-point in the CML (the green line) between the risk-free rate and the tangent portfolio.

8.1 Assumptions of Portfolio Theory

The main assumption of portfolio theory is that all investors behave as rational participants all the time. In other words, they always maximize return and minimize risk using the available information disclosed to the market in a rational way. In other words, they act with no emotions, no fear and they always understand what happen in the market.

9 What if most of the investors are not rational all the time?

If most of the investors are not rational all the time, how can you take advantage of this and define a disruptive portfolio? Which trends, beliefs, fears, regulations, opportunities do you think that few investors are looking for, so that you can beat the rational optimized portfolio?

Based on your own set of beliefs and your understanding of portfolio risk-return trade-off, propose weights for a “disruptive” portfolio that might beat most of the optimized portfolios in the market?

10 W3 submission

The grade of this Workshop will be the following:

  • Complete (100%): If you submit an ORIGINAL and COMPLETE work with all the activities, with your notes, and with your OWN RESPONSES to questions

  • Incomplete (75%): If you submit an ORIGINAL work with ALL the activities but you did NOT RESPOND to the questions and/or you did not do all activities and respond to some of the questions.

  • Very Incomplete (10%-70%): If you complete from 10% to 75% of the workshop or you completed more but parts of your work is a copy-paste from other workshops.

  • Not submitted (0%)

Remember that you have to submit your Colab link file through Canvas BEFORE THE FIRST CLASS OF NEXT WEEK.