Building an Investing Model with Python

Building a model based on financial ratios with Python

Jose Manu (CodingFun)
Towards Data Science

--

During this post, we are going to build an investment model to find out attractive stocks based on financial ratios using Python. We will screen all technology related stocks in the Nasdaq exchange. Then, we will get the main financial ratios for each stock. Finally, based on a custom ranking criteria, we will build a model to find the most attractive stocks.

Photo by Burst from Pexels

Let’s start with the Python code to build our investment model:

Investment Model with Python

As in my previous posts, I will be using financialmodelingprep API which offers a few free API calls per month upon registration. Below are the main steps that we will follow to build our investment model based on financial ratios:

  1. Make a Get request to the financial API to extract the ticker of all companies trading in Nasdaq and meeting our selection criteria (i.e. Technology sector and bigger than a particular size)
  2. Loop through each of the companies screened in point 1 and extract the financial ratios
  3. Append each of the ratios for each of the companies into a Python dictionary and create a Pandas DataFrame
  4. Set up an investment model ranking criteria and come up with a list of most attractive stocks according to our model

1. Extracting Nasdaq Tickers

As already covered in one of my previous posts (i.e. see how to find high dividend paying stocks), we will extract and append each of the company tickers trading in NASDAQ into a Python list. Note that you will need to create an account in financialmodelingprep in order to get an API with a few free API calls per day.

It is a good idea to select companies operating in the same sector and with similar size. That will ensure that the companies can be compared between them. Therefore, we select companies operating in the Technological sector with a market capitalisation of more than $10 billion.

import requests
import pandas as pd
companies = []
demo = 'your api key'
marketcap = str(1000000000)url = (f'https://financialmodelingprep.com/api/v3/stock-screener?marketCapMoreThan={marketcap}&betaMoreThan=1&volumeMoreThan=10000&sector=Technology&exchange=NASDAQ&dividendMoreThan=0&limit=1000&apikey={demo}')#get companies based on criteria defined about
screener = requests.get(url).json()
print(screener)
[{'symbol': 'AAPL', 'companyName': 'Apple Inc.', 'marketCap': 1526030790000, 'sector': 'Technology', 'beta': 1.228499, 'pri
ce': 352.08, 'lastAnnualDividend': 3.08, 'volume': 42532806, 'exchange': 'Nasdaq Global Select', 'exchangeShortName': 'NASD
AQ'}, {'symbol': 'MSFT', 'companyName':....

2. Financial Ratios from Nasdaq Companies

Next, we extract all financial ratios from the Nasdaq companies that we obtained in the previous section. For our investment model, we will work with below selected financial ratios.

add selected companies to a list
for item in screener:
companies.append(item['symbol'])

#print(companies)
value_ratios ={}
#get the financial ratios
count = 0
for company in companies:
try:
if count <30:
count = count + 1
fin_ratios = requests.get(f'https://financialmodelingprep.com/api/v3/ratios/{company}?apikey={demo}').json()
value_ratios[company] = {}
value_ratios[company]['ROE'] = fin_ratios[0]['returnOnEquity']
value_ratios[company]['ROA'] = fin_ratios[0]['returnOnAssets']
value_ratios[company]['Debt_Ratio'] = fin_ratios[0]['debtRatio']
value_ratios[company]['Interest_Coverage'] = fin_ratios[0]['interestCoverage']
value_ratios[company]['Payout_Ratio'] = fin_ratios[0]['payoutRatio']
value_ratios[company]['Dividend_Payout_Ratio'] = fin_ratios[0]['dividendPayoutRatio']
value_ratios[company]['PB'] = fin_ratios[0]['priceToBookRatio']
value_ratios[company]['PS'] = fin_ratios[0]['priceToSalesRatio']
value_ratios[company]['PE'] = fin_ratios[0]['priceEarningsRatio']
value_ratios[company]['Dividend_Yield'] = fin_ratios[0]['dividendYield']
value_ratios[company]['Gross_Profit_Margin'] = fin_ratios[0]['grossProfitMargin']
#more financials on growth:https://financialmodelingprep.com/api/v3/financial-growth/AAPL?apikey=demo
growth_ratios = requests.get(f'https://financialmodelingprep.com/api/v3/financial-growth/{company}?apikey={demo}').json()
value_ratios[company]['Revenue_Growth'] = growth_ratios[0]['revenueGrowth']
value_ratios[company]['NetIncome_Growth'] = growth_ratios[0]['netIncomeGrowth']
value_ratios[company]['EPS_Growth'] = growth_ratios[0]['epsgrowth']
value_ratios[company]['RD_Growth'] = growth_ratios[0]['rdexpenseGrowth']

except:
pass
print(value_ratios)

Note that we have included an if statement to limit to 30 the number of companies for which we will include in our model. Feel free to remove this restriction.

And below we have a sample of the obtained response containing a list of financial ratios for all of our Nasdaq companies. We have added them to a Python dictionary in order to be able to access them easily.

Value Ratio Dictionary outcome:
{'AAPL': {'ROE': 0.6106445053487756, 'ROA': 0.16323009842961633, 'Debt_Ratio': 0.7326921031797611, 'Interest_Coverage': 18.382829977628635, 'Payout_Ratio': 0.25551976255972203, 'Dividend_Payout_Ratio': 0.25551976255972203, 'PB': 12.709658271815046, 'PS': 4.420393881402446, 'PE': 20.81351450883162, 'Dividend_Yield': 0.012276627402416805, 'Gross_Profit_Margin': 0.3781776810903472, 'Revenue_Growth': -0.020410775805267418, 'NetIncome_Growth': -0.07181132519191681, 'EPS_Growth': -0.003330557868442893, 'RD_Growth': 0.1391542568137117}, 'MSFT': {'ROE': 0.3834652594547054, 'ROA': 0.13693658482111698, 'Debt_Ratio': 0.6428970253632798, 'Interest_Coverage': 5.881980640357408, 'Payout_Ratio':0.35196228338430174, 'Dividend_Payout_Ratio': 0.3519622833843017, 'PB': 10.52384979966774, 'PS': 8.557532401484389, 'PE': 27.444076197757386, 'Dividend_Yield': 0.012824708722134454, 'Gross_Profit_Marg

3. Creating a Pandas DataFrame containing Financial Ratios

In the next step, we are going to convert the Python dictionary into a Pandas DataFrame. The reason for it is simply to benefit from all the nice capabilities offered by Pandas to work with our data:

DF = pd.DataFrame.from_dict(value_ratios,orient='index')
print(DF.head(4))
DataFrame with Financial Ratios

4. Creating our Ranking Investment Model

So far, we have managed to add all financial ratios for the selected Nasdaq companies into a Pandas DataFrame.

Now it is time to create our investment model to rank the stocks from more attractive to less attractive. The ranking criteria is totally up to us. I propose below ranking criteria for each of the financial ratios. Feel free to change them as per your preferences.

A positive number will indicate that the ratio is a good sign. The higher the number, the more relevant will that ratio be in our investment model. For example, ROE (return on equity) will have a bigger impact than ROA (return on assets) since 1.2 is bigger than 1.1.

On the other hand, a negative number will make the stock less attractive. For example, a higher Price to Book ratio (PB) may indicate that the company is overvalued. Therefore, I have allocated a negative number to the PB ratio.

In case that you want to learn more about financial ratios, please have a look at some of my previous posts explaining the majority of them.

#criteria ranking
ROE = 1.2
ROA = 1.1
Debt_Ratio = -1.1
Interest_Coverage = 1.05
Dividend_Payout_Ratio = 1.01
PB = -1.10
PS = -1.05
Revenue_Growth = 1.25
Net_Income_Growth = 1.10

In addition, and before calculating our ranking, we need to normalize the financial ratios to enable comparison across them:

#mean to enable comparison across ratios
ratios_mean = []
for item in DF.columns:
ratios_mean.append(DF[item].mean())
#divide each value in dataframe by mean to normalize values
DF = DF / ratios_mean

Great, we are almost there. The last step will be to add a new column into our Pandas DataFrame containing the ranking factor:

DF['ranking'] = DF['NetIncome_Growth']*Net_Income_Growth + DF['Revenue_Growth']*Revenue_Growth  + DF['ROE']*ROE + DF['ROA']*ROA + DF['Debt_Ratio'] * Debt_Ratio + DF['Interest_Coverage'] * Interest_Coverage + DF['Dividend_Payout_Ratio'] * Dividend_Payout_Ratio + DF['PB']*PB + DF['PS']*PS

Now, we can simply print the DataFrame including the ranking factor for each of the stocks in our investment model:

print(DF.sort_values(by=['ranking'],ascending=False))
Investment Model with Python

As we can see in the above picture, our investment models predict that CSCO will be the best stock to invest in as per our selected criteria with a ranking of 48 points. Of course, this is only a model and further analysis of the stock would be required before putting money into it.

Wrapping Up

We have covered quite a bit in this post. We have created an investment model based on key financial ratios and a customized ranking factor.

Such investment models are particularly helpful in order to preliminary identify a few potential good investments to focus our analysis on them. For example, we could analyse some of the financial ratios more in deep for some of our best ranked companies. We could apply the DuPont method to analyse the return on equity (ROE) . Or value the company using the Gordon Growth model.

One limitation of using financial ratios that I would like to highlight is the fact that financial ratios are mostly calculated using the latest available and public data. Therefore, if a company financials were published 3 months ago, financial ratios using balance sheet or income statement data may be outdated. Especially if there has been a material event impacting company operations.

Note from Towards Data Science’s editors: While we allow independent authors to publish articles in accordance with our rules and guidelines, we do not endorse each author’s contribution. You should not rely on an author’s works without seeking professional advice. See our Reader Terms for details.

Originally published at https://codingandfun.com on July 5, 2020.

--

--

Python for Finance. Learn step by step how to automate cool financial analysis tools.