Gordon Growth Model -Valuing a Company with Python

The Gordon Growth Model (GGM) is a tool used to value a firm. This theory assumes that a company is worth the sum of all future dividend payments discounted to the value of today (i.e.present value). It can also be called Dividend Discount Model. In this article, we are going to learn how to value a company using the Gordon Growth Model with Python.

Gordon Growth Model with Python
Photo by Aditya Vyas on Unsplash

What is the Gordon Growth Model?

The Gordon Growth model (GGM) is a well known valuation model used to value companies based on the present value of future dividends. It assumes that the current value of a company is the sum of all future dividends discounted to the present value.

One of the advantages of the GGM model is that it is quite straightforward to calculate. Below we can see the Gordon Growth Model forumula.

How to value a company with the Gordon Growth Model and Python
Gordon Growth Model to value a company

To calculate our model, we only need three elements:

  • Dividends (Do): Dividends payed out by a company. We can easily obtain the latest Dividends paid by a company (Do) by looking into the public company annual/quarterly reports.
  • Growth (g): Is the constant growth rate expected for dividends. One approach to calculate g would be to take historical dividends. That is, to take the last two or three dividends paid by a company, calculate the growth and use it as a proxy for constant growth. The problem with this approach is that if a company keeps its dividend payout constant year over year, the growth rate in our calculation will be zero. To overcome this problem, we will follow a different approach and use the sustainable growth rate instead. The sustainable growth rate is the rate of growth that a company can achieve without having to finance growth with additional equity.
  • Cost of equity (ke): We will use the capital asset pricing model (CAPM) to estimate the required cost of equity. If you want to learn more about the CAPM model, I recommend you to have a look at the following article.

Gordon Growth Model Assumptions

There are a few assumptions the model use. We need to keep them in mind:

  • The dividend growth rate is constant along the years.
  • Dividends is the core of shareholder wealth.
  • Cost of equity must be bigger than the dividend growth. Otherwise, our model will be giving us negative values.

What do we need to calculate the Gordon Growth Model

We will be using a free API, financialmodelingpre, and Pandas Data Reader to retrieve company information and market data. Below is the required data to come up with a company valuation using the GGM model:

  • Latest company dividend
  • To calculate the cost of equity (ke), through the CAPM model, we will need:
    • Company Beta (B) . It can be extracted from financialmodelingprep API.
    • Risk free rate (RF). We will use 1 Year-Treasury Bill as our model risk free rate.
    • Market expected return (ERm). We will calculate the S&P 500 return for the latest year as a proxy for our market expected return. Another approach would be to take the excess historical annual return for U.S. stocks.
  • To compute the sustainable growth rate we will need the payout ratio and the Return on Equity (ROE).

CAPM Model:

Expected Return (i.e cost of equity) = Rf + B (ERm – Rf )

How to calculate the Gordon Growth Model with Python

Now that we know a bit more about the GGM model (or Dividend Discount Model), let’s start building our script.

The idea is to build a Python function that will take a company ticker as an argument. The function will return the company value as a result (i.e. stock price).

import requests

def valuecompany(quote):
 #getting the latest dividend
   dividend = 
requests.get(f'https://financialmodelingprep.com/api/v3/financials/income-statement/{quote}?apikey=your_api_key')
    dividend = dividend.json()
    dividend = dividend['financials']
    Dtoday = float(dividend[0]['Dividend per Share'])
    print(Dtoday)


valuecompany('JNJ')
#Return:
3.47931249313
3.47 is the dividend paid by Johnson & Johnson in the latest year

In our first part of the function, we make an http call to the API end point to retrieve the dividend value of the company passed as an argument. In our example, we have passed the ticker for Johnson & Johnson (Note that the API recognise the company by the ticker).

As shown in the code, we parse the first element of the financial list, which contains a dictionary. Within this dictionary, we extract the value of the key “Dividend per Share”. We store the value in a variable call Dtoday after converting it into a float.

If you are not familiar on how to parse dictionaries in Python, I recommend you to have a look at the following article.

Note that we need an API key from financialmodelingprep to run the code. You can get one for free upon registration.

Parsing API with Python
Parsing API with Python

Great, we have the first part of our model. Next, we need to calculate the Sustainable Growth rate. The formula to compute the rate is as follows:

SGR = Return on Equity * (1 – Dividend payout ratio)

We can obtain Return on Equity (ROE) and Dividend Payout Ratio from the company key metrics API end point. To extract the values, we need to parse the metrics dictionary and extract the values for the keys ROE and payout_ratio:

     metrics = requests.get(f'https://financialmodelingprep.com/api/v3/company-key-metrics/{quote}?apikey=your_api_key')
    metrics = metrics.json()

    ROE = float(metrics['metrics'][0]['ROE'])
    payout_ratio = float(metrics['metrics'][0]['Payout Ratio'])

    sustgrwothrate = ROE*(1-payout_ratio)
    print(sustgrwothrate)

#Result
0.097024
The sustainable growth rate for JNJ is of 9.7%

Now we have calculated the sustainable growth rate as well. Finally, we can calculate the cost of equity by using the CAPM model:

Calculating Cost of Equity (Ke) in Python:

The first element that we need in order to calculate the cost of equity (ke) through CAPM is the Risk free rate. We will use 1-year Treasury Bills as a proxy since Treasury bills are considered risk free securities.

We will use Pandas DataReader and FRED as the data provider. The web.DataReader method will return a Pandas DataFrame containing a time series with the interest rates provided by 1 year T-bills.

We use iloc[-1] method to retrieve the latest element of the DataFrame since the latest element of our Pandas DataFrame Treasury contains the latest available interest rate.

    import pandas as pd
    #if you get an error after executing the code, try adding below:
    pd.core.common.is_list_like = pd.api.types.is_list_like

    import pandas_datareader.data as web
    import datetime

    start = datetime.datetime(2019, 2, 1)
    end = datetime.datetime(2020, 2, 27)

    Treasury = web.DataReader(['TB1YR'], 'fred', start, end)
    RF = float(Treasury.iloc[-1])
    RF = RF/100
    print(RF)

#Result:
0.0149 or 1.49%

Next, we need to get the beta for the company. It can be easily extracted from the API company profile end point:

 beta = requests.get(f'https://financialmodelingprep.com/api/v3/company/profile/{quote}?apikey=your_api_key')
    beta = beta.json()
    beta = float(beta['profile']['beta'])
    print(beta)

#Result:
0.70 is the Beta for JNJ

Finally, the last element we need to compute the cost of equity is the expected market return (i.e. what is known as market premium in the CAPM model).

We will use the index S&P 500 as a proxy for market return. Then, we will calculate the market return for the last year. That is the metric that we will use as a proxy for expected market return.

As shown in one of my other articles, we can easily retrieve S&P 500 prices and calculate the market return using Pandas DataReader and FRED as the data provider:

    start = datetime.datetime(2019, 2, 15)
    end = datetime.datetime(2020, 2, 15) 
    SP500 = web.DataReader(['sp500'], 'fred', start, end)

    #Drop all Not a number values using drop method.
    SP500.dropna(inplace = True)

    SP500yearlyreturn = (SP500['sp500'].iloc[-1]/ SP500['sp500'].iloc[0])-1
    print(SP500yearlyreturn)

# Result:
0.34666119528451844
The market return from the last year was around 34%

Note that we can use iloc in order to extract the first element of the Pandas DataFrame. I.e. iloc[0] contains the S&P 500 price from one year ago. On the other hand, iloc[-1] contains the most recent S&P 500 price.

Finally, we compute the yearly return using below formula to get the rate of return:

S&P 500 Return with Python
S&P 500 return with Python

Perfect! We have all required elements to calculate the cost of equity (Ke). Now we only need to apply the formula to get the Ke through the CAPM model.

ke = RF+(beta*(SP500yearlyreturn - RF))
print(ke)

#Response:
0.24735644374478466
24% is the cost of equity for JNJ

Putting all together and calculating the value of the company

Finally, we have all required elements to calculate the value of our company through the Gordon Growth model and Python.

In the case of Johnson & Johnson, we see that the stock price according to the model is $25.38 which is much lower than the current stock price of $150 per stock.

One of the problems of the Gordon Growth Model is that the returned value is very sensitive to the inputs of the model. For example, a slight increase/decrease in the cost of equity will have a big effect on the calculated value.

    DDM = (Dtoday*(1+sustgrwothrate))/(ke-sustgrwothrate)
    return DDM

#Result:
25.38 is the value of JNJ stock according to the DDM model

Gordon Growth Model limitations

During this post, we have built a model and valued a company using the Gordon Growth model. You can use this script to value any company by passing it as an argument of the function valuecompany. Python will do the work for you.

However, when using the Gordon Growth model to value a company, there are certain limitations to take into account and that will make the model not work:

  • Model will not work with companies not paying dividends
  • Cost of equity must be bigger than the dividend growth. Otherwise, our model will be giving us negative values (i.e. denominator, ke-g, will be negative)
  • Assuming constant dividend per share is not realistic in the real world. To overcome this, consider using a 2 or 3 stage Gordon Growth model to account for the different growth periods.

I hope that you have enjoy the read on how to calculate the Gordon Growth Model with Python! See below the whole code for your reference.

Check out the Python for Finance section of the code to find out new financial analysis tools posted every week!

import requests

def valuecompany(quote):
    #Latest dividend of the company
    dividend = requests.get(f'https://financialmodelingprep.com/api/v3/financials/income-statement/{quote}?apikey=your_api_key')
    dividend = dividend.json()
    dividend = dividend['financials']
    Dtoday = float(dividend[0]['Dividend per Share'])
    
    #ROE and PAyout Ratio
    metrics = requests.get(f'https://financialmodelingprep.com/api/v3/company-key-metrics/{quote}?apikey=your_api_key')
    metrics = metrics.json()

    ROE = float(metrics['metrics'][0]['ROE'])
    payout_ratio = float(metrics['metrics'][0]['Payout Ratio'])

    sustgrwothrate = ROE*(1-payout_ratio)
    print(sustgrwothrate)
    
     ##Cost of equity:

    #Risk Free Rate

    import pandas as pd
    #if you get an error after executing the code, try adding below:
    pd.core.common.is_list_like = pd.api.types.is_list_like

    import pandas_datareader.data as web
    import datetime

    start = datetime.datetime(2019, 2, 1)
    end = datetime.datetime(2020, 2, 27)

    Treasury = web.DataReader(['TB1YR'], 'fred', start, end)
    RF = float(Treasury.iloc[-1])
    RF = RF/100
    
    #Beta
    beta = requests.get(f'https://financialmodelingprep.com/api/v3/company/profile/{quote}?apikey=your_api_key')
    beta = beta.json()
    beta = float(beta['profile']['beta'])
    
    #Market Return
    start = datetime.datetime(2019, 1, 1)
    end = datetime.datetime(2020, 2, 27)

    SP500 = web.DataReader(['sp500'], 'fred', start, end)
    #Drop all Not a number values using drop method.
    SP500.dropna(inplace = True)

    SP500yearlyreturn = (SP500['sp500'].iloc[-1]/ SP500['sp500'].iloc[0])-1
   
    ke = RF+(beta*(SP500yearlyreturn - RF))
    
    DDM = (Dtoday*(1+sustgrwothrate))/(ke-sustgrwothrate)
    print(DDM)
    return DDM


valuecompany('JNJ')