## A comprehensive guide to using Python for enhancing financial decision-making through quantitative analysis

In this blog, we will cover the below topics

- What is Capital Asset Pricing Model (CAPM)?
- Systematic risk and unsystematic risk
- Market returns and sensitivity
- Overvalued and undervalued stocks
- Calculation of the portfolio returns and beta (β)
- Assumptions of CAPM
- Implementing CAPM using Python

## What is a Capital Asset Pricing Model (CAPM)?

The Capital Asset Pricing Model is a mathematical model that calculates the expected return on a given investment by establishing a linear relationship with the risk of the market.

There are a few parameters that play a key role in determining the returns from the asset.

**Risk-free rate**

It is the theoretical rate of an investment that has zero risk. Eg: government bonds that are backed by the government meaning irrespective of the market conditions, macro/microeconomic conditions, the return is absolutely certain. Note that as a standard, the risk-free is taken as zero.

**Types of risks**

**Systematic risk**— This is the risk associated with the market as a whole and is not specific to any asset. eg: If the inflation is high then its effect will be reflected in all aspects of financials irrespective of the industry or sector. In case of recession, investments become riskier compare to the normal market conditions. In all such scenarios, a portfolio/fund manager tries to manage systematic risk and allocate investments for higher returns.**Unsystematic risk**— This risk is specific to an asset, unlike systematic risk. The reasons are business related specifically to a company. Eg: Labor-related issues impacting manufacturing, a business decision that had a negative impact on the company.

## Market return (rₘ)

This includes returns from all the assets in the market. A typical example in the Indian market would be **Sensex** which has the top 30 stocks or **Nifty **which has the top 50 stocks. These are indexes that measure the overall market movement/sentiment. The US equivalent would be S&P 500 which has the 500 largest US publicly traded companies. In calculating the expected returns using CAPM, the given asset is measured against such indexes.

**Sensitivity (β)**

The return from an asset (stock) depends on how sensitive the asset is relative to the market and this factor is known as β (beta). The β is the slope in the linear relation.

- If β = 1, then the asset’s return is the same as the market return
- If β > 1, then the asset’s return is higher than the market return. The asset is more volatile than the market.
- If β < 1, then the asset’s return is lesser than the market return indicating that the asset is less volatile than the market.

Now, that we understand various factors, let us put them in an equation.

rᵢ = rf + βᵢ * (rₘ−rf)

rᵢ = Expected return from the portfolio

rf = Risk-free return rate

rₘ = Market return

βᵢ = Risk relative to the market

(rₘ−rf) = Risk premium

**Example**: If the risk-free rate is zero, the β is 1.2 and the average market return is 12.5 then the expected return would be 15%

rᵢ = 0% + 1.2 * (12.5% — 0%) = 15%

This means investors should expect a 15% return for the additional risk taken.

## Interpreting the beta(β) of the portfolio

The equation in the previous section is the same as the equation of the line which is **y = mx + c **meaning

**there is a linear relation between the expected return and the β which is presented below.**

- The market β is always 1 which gives us a return of E(Rₘ) —
*dotted line* - The stocks that are above the lines are undervalued because, for a given risk, the returns are higher than the market returns
- The stocks that are below the lines are overvalued because, for a given risk, the returns are lower than the market returns

## Implementing CAPM using Python

In this section, we will apply our learning and build a CAPM model using python. We will consider the Indian stocks for this blog but the methodology would remain the same for U. S stocks / S&P 500.

**Load the libraries**

We will use ** nsepy **to load the data for all the stocks. The rest of the libraries has standard usage for data loading, data transformation, and visualization.

import numpy as np

import pandas as pd

import matplotlib.pyplot as plt

from datetime import date

from nsepy import get_history as gh

**Load the data and initial settings**

Let us select Tata Motors, Dabur, ICICI Bank, Wipro, Infosys, and NIFTY for the last 5 years’ data starting from Feb 2018 to Feb 2023 for this blog.

start_date = date(2018,2,2)

end_date = date(2023,2,2)

tickers = ['TATAMOTORS','DABUR', 'ICICIBANK','WIPRO','INFY']

def load_stock_data(start_date, end_date, ticker):

df = pd.DataFrame()

for i in range(len(ticker)):

data = gh(symbol=ticker[i],start= start_date,

end=end_date)[['Symbol','Close']]

...

...

return df

df_stock = load_stock_data(start_date, end_date, tickers)

df_nifty = gh(symbol = 'NIFTY',start = date(2018,2,2), end = date(2023,2,2), index= True)[['Close']]

df_nifty.rename(columns = {'Close':'NIFTY'}, inplace = True)

df_port = pd.concat([df_stock, df_nifty], axis = 1)

TATAMOTORS DABUR ICICIBANK WIPRO INFY

Date

2018-02-02 383.75 344.45 335.1 300.60 1143.25

2018-02-05 395.80 339.10 329.7 298.75 1138.20

2018-02-06 375.45 339.25 330.7 294.65 1107.75

.....

2023-01-31 452.10 557.75 831.90 398.85 1533.75

2023-02-01 446.65 561.95 847.95 402.40 1551.10

2023-02-02 444.80 554.45 857.90 409.45 1583.75

## Exploratory data analysis — EDA

Let’s visualize the price and returns trends of all the stock

plt.figure(figsize=(10, 10))

plt.subplots_adjust(hspace=0.5)

plt.suptitle("Daily closing prices", fontsize=18, y=0.95)

for n, ticker in enumerate(tickers):

ax = plt.subplot(3, 2, n + 1)

df_stock[ticker].plot(ax= ax)

ax.set_title(ticker.upper())

df_returns = df_port.pct_change().dropna().reset_index()

plt.figure(figsize=(10, 10))

plt.subplots_adjust(hspace=0.5)

plt.suptitle("Daily Returns", fontsize=18, y=0.95)

for n, ticker in enumerate(tickers):

ax = plt.subplot(3, 2, n + 1)

df_returns[ticker].plot(ax= ax)

ax.set_title(ticker.upper())

## Calculating alpha and beta (β)

There are 5 stocks in the portfolio and we will loop through each and calculate the coefficients. In the end, we will have a linear equation for each of the stocks and plot the regression line.

beta = []

alpha = []

for i in df_returns.columns:

if i != 'Date' and i != 'NIFTY':

df_returns.plot(kind = 'scatter', x = 'NIFTY', y = i)

b, a = np.polyfit(df_returns['NIFTY'], df_returns[i], 1)

plt.plot(df_returns['NIFTY'], b * df_returns['NIFTY'] + a, '-',

color = 'r')

beta.append(b)

alpha.append(a)

OUTPUT:

beta: [1.4488, 0.5953, 1.3592, 0.7008, 0.8208]

## Calculating the expected returns

We have all the required data like the risk-free rate, the beta(β), and the market return (Rₘ). Let’s calculate the returns for each of the stocks and also for the portfolio.

ER = []

rf = 0

rm = df_returns['NIFTY'].mean() * 252

print(f'Market return is {rm}%')

for i in beta:

ER_tmp = rf + (i * (rm-rf))

ER.append(ER_tmp)

print(f'Expected return based on CAPM for {i} is {ER_tmp}')

portfolio_weights = 1/len(tickers) * np.ones(len(tickers))

ER_portfolio = sum(ER * portfolio_weights)

print(f'Portfolio expected return is {round(ER_portfolio,2)} %')

OUTPUT:

Market return is 11.93%

Expected return based on CAPM for TATAMOTORS is 17.29 %

Expected return based on CAPM for DABUR is 7.1 %

Expected return based on CAPM for ICICIBANK is 16.22 %

Expected return based on CAPM for WIPRO is 8.36 %

Expected return based on CAPM for INFY is 9.8 %

Portfolio expected return is 11.76 %

The portfolio return is 11.76% which is mimicking the market (NIFTY) which is 11.93%. If we take the simple average of the five β values in the portfolio, it turns out to be 0.98 meaning the portfolio return would be marginally less than the market return.

## Assumptions of CAPM

- All investors are risk-averse by nature.
- There is some time period to evaluate information
- Risk and return are linearly related
- There are no additional costs
- The risk-free rate of return

## Closing thoughts

The CAPM can be used to determine if the stocks are fairly valued or not and is based on the modern portfolio theory. The simplicity of the models helps us understand the relationship between risk and returns which lets investors strike the right balance in investment decisions. In this blog, we learned the basics of the Capital Asset Pricing Model (CAPM), the factors involved, and the interpretation of the β. We accomplished all this in python right from the loading of the data, the EDA, calculating daily returns, and portfolio returns. There are many other models for building Asset Pricing models like the Three- factors, and five-factor models which are worth exploring.

Note that we didn’t optimize the portfolio, instead had equal weights for all the stocks in the portfolio (*just to keep it simple*). Please feel free to explore *How To Build A Financial Portfolio Using Python*** **for ideas to improve the portfolio returns further.

I hope you liked the article and found it helpful.

You can connect with me — on ** Linkedin** and

*Github*## Disclaimer

The blog is only educational and should not be used as professional advice for real-world financial decisions.