# Python functions to determine if a given ticker symbol is an ETF

I am working on a stock analysis application in Python and I have the need to determine whether an input ticker symbol is an Exchange Traded Fund (ETF) or not. First I need to determine if the given ticker is even valid. Second I need to determine if it is an ETF or a company stock. So, I have some simple functions to request info from Yahoo! Finance (modified from ystockquote)

from urllib.request import Request, urlopen

def _yahoo_request(symbol, tag):
"""
Retrieve stock data from Yahoo! Finance.

Args:
symbol (str): Stock ticker symbol for company of interest.
tag (str): Yahoo! finance tag for a given property.

Returns:
str: The property requested.
"""
url = 'http://finance.yahoo.com/d/quotes.csv?s=%s&f=%s' % (symbol, tag)
request = Request(url)
response = urlopen(request)
return content


So to determine if a stock is valid, I check to see if it's name exists in Yahoo! Finance. Getting the name:

def get_name(symbol):
"""
Retrieve company name for given ticker.

Args:
symbol (str): Ticker symbol for a given company's stock.

Returns:
str: The company name. Returns 'N/A' if ticker not in Yahoo! Finance.
"""
return _yahoo_request(symbol, 'n')


and checking if it is a valid ticker:

def valid_ticker(ticker):
"""
Check whether given ticker is a valid stock symbol.

NOTE: Assumes that a stock is valid IF Yahoo! Finance returns a
name for the given ticker.

Args:
ticker (str): Ticker symbol in question.

Returns:
bool: True if valid ticker (returned name != 'N/A'),
otherwise False.
"""
ticker = ticker.upper()
return True if get_name(ticker) != 'N/A' else False


Finally, to determine if a given ticker is for an ETF or not, I will check the number of shares outstanding.

def get_shares_outstanding(symbol):
"""
Retrieve number of shares outstanding for given stock ticker.

Args:
symbol (str): Ticker symbol for a given company's stock.

Returns:
str: The company name.
"""
return _yahoo_request(symbol, 'j2')


This is not a valid data point for ETF's, so again, Yahoo! will return 'N/A'. So, if the response can be cast as an integer, the ticker is not an ETF.

def is_etf(ticker):
"""
Determine whether a given ticker symbol is for an Exchange

NOTE: Assumes that ticker is an ETF IF it is a valid ticker AND
Yahoo! Finance does not return a numeric value for 'shares
outstanding.'

Args:
ticker (str): Ticker symbol in question.

Returns:
bool: None if not a valid ticker, True if an etf (ticker is
valid and returned shares outstanding cannot be converted to
an int), otherwise False.
"""
ticker = ticker.upper()
if valid_ticker(ticker):
try:
int(get_shares_outstanding(ticker))
return False
except ValueError:
return True
else:
return None


Code is working as expected. Does this seem a reasonable way to check this? In particular the last function. Should I just use if get_shares_outstanding(ticker) == 'N/A': return True ?

Any time you're dealing with structured data, use a proper parser for it.

url = 'http://finance.yahoo.com/d/quotes.csv?s=%s&f=%s' % (symbol, tag)


In this case, you want urllib.parse.

Please use a context manager for:

request = Request(url)
response = urlopen(request)


eg.

with urlopen(Request(url)) as response:
...


Context managers are good. It's a shame they're so under-used. On older Pythons, you should use contextlib.closing instead.

I would generally merge these lines into a long return:

content = response.read().decode().strip().strip('"')
return content


Consider that in

ticker = ticker.upper()
return True if get_name(ticker) != 'N/A' else False


True if some_bool else False is just some_bool, so write

return get_name(ticker.upper()) != 'N/A'


• Good point on the context manager. Since this was a 'borrowed' function, I didn't even think about it. However, making that change and combining to a long return actually really trimmed down that function. Also, many thanks on the some_bool, That looks much better. The one item in your answer I don't understand is how you are proposing I use the urllib.parse. Could you add a quick snippet or explanation? Great stuff! – Christopher Pearson Jun 15 '15 at 2:35