An effective yet simple method of filtering and choosing the right stocks
People are now opting for sustainable ways of accomplishing things more than ever. This is encouraging from the standpoint of society, and at the same time, it’s a wonderful opportunity for investment. When the market size of sustainable investment is analyzed, it was estimated to be around 520 billion USD since most of the big and emerging companies are adopting sustainable methods of running their operations.
One of the important factors to measure the sustainable performance of a company is the ESG scores. ESG is the acronym for environmental, social, and governance. It is basically a quantitative measure of the social and environmental actions taken by the company for a sustainable future. In this article, we will construct a sustainable investment strategy with the help of ESG scores to choose the right stocks to invest in. Without further ado, let’s dive into the article.
Importing Packages
The first and foremost step of setting up the coding environment is to import the required packages. In this article, we are not going to use any fancy packages but rather three basic and widely used packages which are pandas for data manipulation, and requests for making API calls, and matplotlib for data visualization. The following code will import all the mentioned packages into our Python environment:
import requests
import pandas as pd
import matplotlib.pyplot as plt
plt.rcParams['figure.figsize'] = (10,5)
plt.style.use('fivethirtyeight')
If you haven’t installed any of the imported packages, make sure to do so using the pip command in your terminal. Before moving further, for extracting the data, we’ll be using the APIs of FinancialModelingPrep. So for the smooth execution of the upcoming code block, you need to have an FMP developer account which you can easily create using the link here.
Extracting S&P 500 Tickers
In this article, we will be picking the most sustainable stocks from the S&P 500 Index. In order to do that, we first need the list of stocks included in the index. Gone are the days of extracting the tickers from Wikipedia’s page using web scraping processes as now we have more accessible and diverse APIs. The following code extracts the 500 tickers available in the index using FMP’s one of the Market Indexes APIs:
api_key = 'YOUR API KEY'
api_url = f'https://financialmodelingprep.com/api/v3/historical/sp500_constituent?apikey={api_key}'
sp500_json = requests.get(api_url).json()
sp500_tickers = []
for i in range(len(sp500_json)):
ticker = sp500_json[i]['symbol']
sp500_tickers.append(ticker)
In this code, we are first saving the API key (remember to replace YOUR API KEY with your actual secret key) and URL into the respective variables, then, using the get function provided by the requests package, we are making an API call and stored the JSON response into a variable. After that, we are running a for-loop to get rid of the unwanted information that comes along with the JSON response and stored all the tickers to an empty list.
Extracting the ESG Scores
Now that we are having the list of all stocks in the S&P 500 index, we can extract the ESG scores of all the stocks. In order to do that, we are going to use FMP’s ESG score API. The following code extracts the S&P 500 stocks’ ESG scores:
esg_scores = pd.DataFrame(columns = ['ticker', 'esg_score'])
esg_scores['ticker'], esg_scores['esg_score'], esg_scores['environmental_score'], esg_scores['start_date'] = sp500_tickers, 1, 1, '2000-01-01'
for i in range(len(sp500_tickers)):
ticker = sp500_tickers[i]
api_url = f'https://financialmodelingprep.com/api/v4/esg-environmental-social-governance-data?symbol={ticker}&apikey={api_key}'
esg_json = requests.get(api_url).json()
if esg_json == []:
esg_scores = esg_scores.drop(i)
pass
else:
esg_df = pd.DataFrame(esg_json)
esg_scores['ticker'][i], esg_scores['esg_score'][i], esg_scores['environmental_score'][i], esg_scores['start_date'][i] = ticker, esg_df.ESGScore.mean(), esg_df.environmentalScore.mean(), esg_df.iloc[-1].date
esg_scores.head()
In the first two lines, we are creating a dataframe to store the ESG scores of the stocks. Then, we are using a for-loop to make API calls for each and every ticker and extract the ESG scores. This is the final dataframe:
Stock Selection
In this section, we are going to create certain conditions and filter the stocks based on them. This is our criteria: the ESG scores should be greater than 65, the environmental score should be greater than 75, and the company should be at least 10 years old.
Let’s break down the condition. Firstly, we are specifying the ESG scores must be higher than 65. Generally, a stock with an ESG score of 65 or greater than that, is considered good while a score of 50 or lesser than that, is considered relatively poor.
Secondly, the environmental score must be greater than 75. The reason behind the inclusion of this particular score is that the strategy we are trying to build here is a sustainable investment strategy and the environmental score is a direct reflection of the company’s efforts and actions towards conserving the environment.
Finally, it must be at least 10 years since the company has gone public. The purpose of this specific criteria is to ensure that the company is maintaining a good ESG score for a long time. The following code will implement this condition and filter the stocks:
esg_scores.start_date = pd.to_datetime(esg_scores.start_date)
esg_scores_sorted = esg_scores[(esg_scores.esg_score > 65) & (esg_scores.environmental_score > 75) & (esg_scores.start_date < '2013-01-01')]
portfolio = list(esg_scores_sorted.ticker)
esg_scores_sorted
The code is pretty straightforward and simple. We are passing our selection criteria to the ESG scores dataframe we created earlier to sort and filter the stocks. Here are the stocks that fulfilled the criteria:
Using our selection criteria, we were able to narrow down 500 stocks to just 3 stocks which are Atmos Energy Corporation, Acuity Brands Inc., and Chesapeake Energy. Now, let’s see if our portfolio makes a profit or not.
Extracting Historical Data
For the backtesting process, we first need to acquire the historical data of all the stocks in our portfolio. To extract the data, we will utilize the stock historical data endpoint provided by FMP and this can be easily done by using the following code:
def get_historical_prices(ticker, start_date):
api_key = 'YOUR API KEY'
api_url = f'https://financialmodelingprep.com/api/v3/historical-price-full/{ticker}?serietype=line&from={start_date}&apikey={api_key}'
hist_json = requests.get(api_url).json()['historical']
hist_df = pd.DataFrame(hist_json).iloc[::-1]
return hist_df.close, hist_df.date
hist_df = pd.DataFrame(columns = [portfolio])
for ticker in portfolio:
hist_df[ticker], hist_df['date'] = get_historical_prices(ticker, '2021-01-01')
hist_df = hist_df.dropna()
hist_df = hist_df.reset_index().drop('index', axis = 1)
hist_df = hist_df.set_index('date')
hist_df.index = [''.join(i) for i in hist_df.index]
hist_df.index = pd.to_datetime(hist_df.index)
hist_df.tail()
In the code, we are first defining a function named get_historical_prices which takes the symbol of the stock and the starting date as the parameters. This function returns the historical closing prices for a given stock. Then, we use a for-loop to iterate through our portfolio of stocks to extract the historical data of each stock. The extracted data is stored in a dataframe named hist_df . After performing some data manipulations, this is the final output:
Calculating Returns & Benchmark Comparison
Now that we are having the historical data of the stocks to work with, we can easily calculate and visualize the profit/loss of our portfolio. The following code does the same:
rets_df = hist_df.pct_change().dropna()
rets_df['total_ret'] = rets_df.sum(axis = 1)
rets_df.total_ret.cumsum().plot(legend = False, title = 'Portfolio Returns')
The code is pretty simple. We are first using the pct_change to calculate the returns of each stock and stored that in a new dataframe. Then, using the sum function, we are performing row-wise addition to arrive at the total returns of our portfolio. Finally, we are plotting the cumulative returns of our portfolio and this is what the graph looks like:
Amazing, looks like we’ve made a profit! But still, we don't want our strategies to just make a profit but rather be well-performing, and to test that out we have to make a comparison with the returns of benchmarks. SPY ETF would be the most suitable benchmark in our case since it tracks and measures the performance of the S&P 500 index. The following code draws a comparison between the returns of our strategy to that of SPY ETF:
spy_hist = pd.DataFrame(get_historical_prices('SPY', '2021-01-01')).T
spy_hist = spy_hist.set_index('date')
spy_hist.index = pd.to_datetime(spy_hist.index)
spy_rets = spy_hist.pct_change().rename(columns = {'close':'spy_returns'}).dropna()
portf_spy_rets = rets_df.join(spy_rets).iloc[:,-2:]
portf_spy_rets.cumsum().plot(title = 'Portfolio/SPY Returns Comparison')
The code is separated into three parts. The first part is about using the previously constructed function which is get_historical_prices to extract the historical closing prices of SPY ETF. In the second part, we are performing certain actions to clean and format the extracted data as well as calculate the returns of the ETF. Finally, the third part is plotting the SPY ETF returns against the returns of our portfolio and this is what the graph looks like:
Fantastic! It looks like we really did beat the benchmark with a substantial difference. So we can conclude that we built a pretty good strategy that is capable enough to outperform the SPY ETF.
Closing Notes
In this article, we learned to create a simple sustainable investment strategy to pick the right stocks to invest in and build a green portfolio that outperforms the SPY ETF benchmark. The whole process included extracting various types of financial data using FMP’s APIs, crafting the right criteria for filtering the stocks, and finally, strategy implementation, backtesting, and returns comparison.
In my opinion, sustainable investing is soaring and is about to reach its peak in the future. So combining this market force with powerful techs like Python and AI can really provide traders with an edge in the market.
An important note: Any of the information included in this article should not be perceived as any form of investment advice rather they are featured purely for educational and research purposes only.
With that being said, you’ve reached the end of the article. Also, a huge shoutout to FinancialModelingPrep for creating such a great and reliable platform for accessing various types of financial data ranging from fundamental data to ESG and sentiment scores of securities. Hope you learned something new from this article.