By Ishan Shah
Value investment traces its origin back to Security Analysis and The Intelligent Investor books by Benjamin Graham in which he advocated detailed analysis of fundamental metrics to buy the stocks which are trading at a discount to its intrinsic value. Warren Buffet, one of the most famous students of Benjamin Graham, showed all of us the power of value investing to generate higher returns.
Investing In Value Stocks vs. Growth Stocks
According to a study by Brandes, value investing has substantially outperformed the market and growth stocks over long periods of time.
They have used a simple valuation metric such as P/E, P/B, and P/CF to identify value and growth stocks. 
One approach used was to sort all the stocks by P/B and then classify top 10% as the growth stocks and bottom 10% as the value stocks. They observed in the rolling 5-year periods that value stocks did much better than growth stocks.
Value outperformed Growth (Glamour) in more periods and longer stretches 
However, I believe much of the analysis conducted by value investors—reading financial statements and assessing relative valuations—can be done faster, more effectively, and across a wider group of securities through an automated process. Quantitative value investment strategy is an effort to identify the most robust long-term focused value stocks.
Quantitative value investment strategy approach can be defined in the following manner:
- Identify the full set of stocks
- Screen for value and quality
- Invest with conviction
A full list of stocks is defined from small cap to large cap and stocks with low liquidity and trading restrictions are excluded. Then filter based on various quantitative fundamental parameters to form a portfolio of cheapest and high-quality stocks. Let’s see how this can be done in Python.
Import The Libraries
The first step is to import the necessary libraries namely pandas, BeautifulSoup, and requests.
# For data manipulation import pandas as pd # To extract fundamental data from bs4 import BeautifulSoup as bs import requests
Define The Method To Extract Fundamental Data
Next is to use finviz.com to retrieve the base URL which stores the fundamental parameter of a stock and apply the ‘requests.get’ function on the URL which creates a response object. You can check whether the request was successfully executed by checking the status code. Then, BeautifulSoup library is used to pull data from that page.
def get_fundamental_data(df): for symbol in df.index: try: url = ("http://finviz.com/quote.ashx?t=" + symbol.lower()) soup = bs(requests.get(url).content, features='html5lib') for m in df.columns: df.loc[symbol,m] = fundamental_metric(soup,m) except Exception as e: print (symbol, 'not found') return df
Then, define a method to return the fundamental metric from the page. The required fundamental metric, along with the soup object is passed to this function and it returns the value of that fundamental metric.
def fundamental_metric(soup, metric): return soup.find(text = metric).find_next(class_='snapshot-td2').text
Define A List Of Stocks And The Fundamental Metrics
Here we define the list of stocks such as Amazon, Google, etc and stored it in stock_list and similarly, define the fundamental parameters required and store it in metric. The full list of the fundamental metrics available can be found at the finviz.com.
stock_list = ['AMZN','GOOG','PG','KO','IBM','DG','XOM','KO','PEP','MT','NL','ALDW','DCM','GSB','LPL'] metric = ['P/B', 'P/E', 'Forward P/E', 'PEG', 'Debt/Eq', 'EPS (ttm)', 'Dividend %', 'ROE', 'ROI', 'EPS Q/Q', 'Insider Own' ]
The get_fundamental_data function defined earlier is called and the fundamental metric returned is stored in the DataFrame for all the stocks.
df = pd.DataFrame(index=stock_list,columns=metric) df = get_fundamental_data(df) print df.head()
Based on these fundamental data, I have defined a Buffet-inspired stock screening model to identify stocks that will be part of my long portfolio. The criteria are:
1. Businesses which are quoted at low valuations
P/E < 20
P/B < 3
df = df[(df['P/E'].astype(float)<20) & (df['P/B'].astype(float) < 3)]
However, these ratios would differ from sector to sector for simplicity I’m using this numbers.
2. Businesses which have demonstrated earning power
EPS Q/Q > 10%
df['EPS Q/Q'] = df['EPS Q/Q'].map(lambda x: x[:-1]) df = df[df['EPS Q/Q'].astype(float) > 10]
3. Businesses earning good returns on equity while employing little or no debt
Debt/Eq < 1
ROE > 10%
df['ROE'] = df['ROE'].map(lambda x: x[:-1]) df = df[(df['Debt/Eq'].astype(float) < 1) & (df['ROE'].astype(float) > 10)]
4. Management having substantial ownership in the business
Insider own > 30%
df['Insider Own'] = df['Insider Own'].map(lambda x: x[:-1]) df = df[df['Insider Own'].astype(float) > 30] print df.head()
These are only some of the criteria. You may add more criteria to select stocks for your portfolios. Using Python, I was easily able to get data, create filters and identify the value stocks. However, this would have been very cumbersome to do in Excel.
You should be able to improve upon the edge that value investors can get through the addition of this simplistic quantitative value investment strategy.
Learn various aspects of Algorithmic Trading and join our strong base of leading alumni and connect with our global faculty. Check out the Executive Programme in Algorithmic Trading (EPAT™) that equips you with the required skill sets to be a successful trader via training modules like Statistics & Econometrics, Financial Computing & Technology, and Algorithmic & Quantitative Trading. Enroll now!
Disclaimer: All investments and trading in the stock market involve risk. Any decisions to place trades in the financial markets, including trading in stock or options or other financial instruments is a personal decision that should only be made after thorough research, including a personal risk and financial assessment and the engagement of professional assistance to the extent you believe necessary. The trading strategies or related information mentioned in this article is for informational purposes only.