# Quantitative Value Investing Strategy In Python

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. [1]

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 [2]

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.

### Approach

Quantitative value investment strategy approach can be defined in the following manner:

1. Identify the full set of stocks
2. Screen for value and quality
3. 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)
for m in df.columns:
df.loc[symbol,m] = fundamental_metric(soup,m)
except Exception as e:
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 getfundamentaldata 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.

### Next Step

Learn the importance of understanding ‘beta’ in the stock market and how we can use beta effectively to hedge against market risk. Read our post on 'Asset Beta & Market Beta In Python' to know more.

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.