Calculate Dividend History in Python in Under 4 Minutes

James Peter Webb
JPA-Quant-Articles
Published in
4 min readSep 9, 2022

Many sites will lock the history of dividend payment, and growth of a stock, behind a paywall. But what if this could be done simply, for free, through python?

Generated by Wombo Art, a greate AI artwork tool.
Generated by Wombo Art

This framework project will include 4 steps:

  • Pull ticker data from Yahoo Finance using the yfinance module
  • Resample dividend payments
  • Calculate years of consecutive payment and growth
  • Plot price alongside dividend payments

Pulling Ticker Data

If you do not have yfinance or pandas installed, open your terminal (bonus points for using a virtual environment), and type pip install yfinance, and pip install pandas.

Next, from the yfinance module we can pull the full profile of a stock including historic data, but for this project, we will only be using the historic close price, and dividend payments.

import pandas as pd
import yfinance as yf
# INITIAL DATASETS
stock = yf.Ticker(ticker)
info = stock.info
close = info['previousClose']
dividends = stock.dividends

From these datasets, we can calculate everything we need. Initially we simply resample the payments and collect historic price. Then we check if the company pays a dividend, if so we then use a combination of cumulation and grouping functions in the line:

annual_count[‘Consecutive’] = (annual_income.groupby((annual_income <= annual_income.shift()).cumsum()).cumcount() + 1)

What this does is create a new column in the annual_count dataframe, that acts as a counter that will increase by 1 each row IF the annual income of the row below (the next year) is greater than or equal to, the previous year. This indicates either a growth in; or simply a consecutive payment of, dividend. All relevant data is then culminated into a dictionary ‘profile’ for the stock.

# ANNUAL DIVIDEND PAYMENTS, AND FULL PRICE HISTORY
annual_income = pd.Series(dividends.resample('Y').sum())
history = stock.history(period='max')['Close']
# ACCOUNT FOR NON-PAYING COMPANIES
if annual_income.empty is True:
print('No dividends')
current_yield = '0'
consec = 0
else:
annual_count = pd.DataFrame()
annual_count['Consecutive'] = (annual_income.groupby(
(annual_income <= annual_income.shift()).cumsum()).cumcount() + 1)
consec = list(annual_count['Consecutive'])[-2]
current_yield = info['dividendYield']
data_dict = {'Ticker': info['symbol'], 'Close': close,
'Current yield': current_yield,
'Consecutive': consec, 'Div Frame': dividends,
'Price Frame': history,
'Currency': info['currency']}

N.B. the line: consec = list(annual_count[‘Consecutive’])[-2], uses an index of -2, to remove the incomplete year we are currently in (as at the time of writing, the dividend payments due in the fourth quarter of have not been paid out)

Finally we can plot the data using some matplotlib magic, and see how companies have been doing with their dividend payments

Above is Legal & General Group, an English asset management firm in the FTSE 100, and in a total runtime of ~10 seconds, we can see that they have consecutively paid a dividend for 13 years, with a current yield of 7.62%

Within the data dictionary we created, we have access to their full price history, full dividend history, and consecutive years of payments.

Here we can see LGEN.L (note the London Stock Exchange suffix .L, non-US stocks will require exchange suffix specification) pays a biannual dividend, that pays ~70% of this dividend in April, interesting.

This script can also be used to monitor decreasing, un-increasing, or halted dividend payments as well.

Passing in General Motors (GM), the darling automotive stock of the 00’s, we can see the dividend stopped growing in 2017, hugely decreased in 2020, and completely ceased in 2021. We can also see that price action has returned to pre-2020 levels, yet the full dividend has not been restored, also interesting.

The last step of this project is to make this into a functional script.

import pandas as pd
import yfinance as yf

def dividend_data(ticker: str, visual: bool = False) -> dict:
stock = yf.Ticker(ticker)
info = stock.info
close = info['previousClose']
dividends = stock.dividends
annual_income = pd.Series(dividends.resample('Y').sum())
history = stock.history(period='max')['Close']
print(f"Stock: {info['symbol']}")
if annual_income.empty is True:
print('No divs')
current_yield = '0'
consec = 0
else:
annual_count = pd.DataFrame()
annual_count['Consecutive'] = (annual_income.groupby(
(annual_income <= annual_income.shift()).cumsum()).cumcount() + 1)
consec = list(annual_count['Consecutive'])[-2]
current_yield = info['dividendYield']
data_dict = {'Ticker': info['symbol'], 'Close': close,
'Current yield': current_yield, 'Consecutive': consec,
'Div Frame': dividends, 'Price Frame': history,
'Currency': info['currency']}
format_yield = info['dividendYield'] * 100
print(f"Dividend yield: {format_yield}%")
print(f'Consecutive dividend: {consec}')
if visual is True:
dividendVisual(data_dict)
else:
pass
return data_dict
if __name__ == '__main__':
data_dict = dividend_data('GM', visual=True)

The plotting script has been omitted from this article as it includes some of my own personal branding, enjoy!

--

--

James Peter Webb
JPA-Quant-Articles

Analyst at CryptoCompare, MSc FinTech and Investment, BSc Chemistry: Follow my projects in quantitative analysis and Christian finance.