#!/usr/bin/env python # coding: utf-8 # In[1]: import threading import requests import json import datetime from pathlib import Path class TickerInfo: """ TickerInfo can be used to get real-time financial information about assets listed in any global exchange. The module is powered with Yahoo Finance, and the tickers that can be used with TickerInfo are solely the ones permitted on Yahoo Finance. How to use TickerInfo? Instantiate TickerInfo as an object and call its functions for results. Consider the example code below: >>> tickerInfo = TickerInfo() >>> tickerInfo.get_current_price("GOOG") 1431.72 >>> tickerInfo,get_purchase_recommendation("GOOG") 1.3 """ def __init__(self): self.memoized_scraped_data = {} self.info_keys = {} self.SCRAPER_MAIN_URL_TAG = "finance_scrape_url_main" self.SCRAPER_URL_PARAMS_TAG = "finance_scrape_url_params" self.config = { "finance_scrape_url_main": "https://query2.finance.yahoo.com/v10/finance/quoteSummary/", "finance_scrape_url_params": "?formatted=true&lang=en-US®ion=US&modules=summaryProfile%2CfinancialData%2CrecommendationTrend%2CupgradeDowngradeHistory%2Cearnings%2CdefaultKeyStatistics%2CbalanceSheetHistory%2CassetProfile%2CcashflowStatementHistory%2CincomeStatementHistory%2CcalendarEvents&corsDomain=finance.yahoo.com" } def ____core_parse_helper(self, ticker): """ Scrapes Yahoo Finance to retrieve data about an asset ticker. :param ticker: (String) Asset ticker for globally listed companies, as supported by Yahoo Finance :return: (dict) Scraped data about asset ticker """ if not isinstance(ticker, str): raise TypeError("ticker parameter is not a String") query_url = self.config[self.SCRAPER_MAIN_URL_TAG] + ticker + self.config[self.SCRAPER_URL_PARAMS_TAG] summary_json_response = requests.get(query_url) final_scraped_information = {} json_loaded_summary = json.loads(summary_json_response.text) if json_loaded_summary is None \ or "quoteSummary" not in json_loaded_summary\ or "result" not in json_loaded_summary["quoteSummary"]\ or len(json_loaded_summary["quoteSummary"]["result"]) == 0: return None core = json_loaded_summary["quoteSummary"]["result"][0] processing_sets = [core[factor] for factor in core.keys()] if "calendarEvents" in core: if 'earnings' in core["calendarEvents"]: processing_sets.append(core["calendarEvents"]['earnings']) for ps in processing_sets: for x in list(ps.keys()): if isinstance(ps[x], dict): if len(ps[x]) == 0: ps[x] = None elif 'raw' in ps[x]: ps[x] = ps[x]['raw'] if isinstance(ps[x], list): ps[x] = [y['fmt'] for y in ps[x] if 'fmt' in y] final_scraped_information.update(ps) self.memoized_scraped_data[ticker] = ( datetime.datetime.now(), final_scraped_information ) self.info_keys[ticker] = final_scraped_information.keys() return final_scraped_information def __core_parse(self, ticker): """ Wrapper function on top of scraper function to assist with memoization process :param ticker: (String) Asset ticker for globally listed companies, as supported by Yahoo Finance :return: (dict) Scraped data about asset ticker """ if ticker in self.memoized_scraped_data: data_tuple = self.memoized_scraped_data[ticker] first_time = data_tuple[0] later_time = datetime.datetime.now() difference = later_time - first_time seconds_in_day = 24 * 60 * 60 if divmod(difference.days * seconds_in_day + difference.seconds, 60)[0] < 15: thread = threading.Thread(target=self.____core_parse_helper, args=(ticker,)) thread.start() return data_tuple[1] return self.____core_parse_helper(ticker) def get_available_data_tags(self, ticker): """ Returns a list of available data for an asset ticker, as found in Yahoo Finance. :param ticker: (String) Asset ticker for globally listed companies, as supported by Yahoo Finance :return: (list) tags available for an asset ticker; Returns None if the information is not available """ if not isinstance(ticker, str): raise TypeError("ticker parameter is not a String") if ticker not in self.info_keys: self.get_company_data(ticker) return self.info_keys[ticker] def get_data_from_tag(self, ticker, tag): """ Returns available data for an asset ticker and a provided tag, as found in Yahoo Finance. :param ticker: (String) Asset ticker for globally listed companies, as supported by Yahoo Finance :param tag: (String) Data tag that is to be retrieved from Yahoo Finance. For a list of available data tags call TickerInfo.get_available_data_tags(tag) :return: (int or String) data associated with asset ticker and provided tag; Returns None if the information is not available """ if not isinstance(ticker, str): raise TypeError("ticker parameter is not a String") if not isinstance(tag, str): raise TypeError("tag parameter is not a String") if ticker not in self.info_keys: self.get_company_data(ticker) # print("KYAS:" , self.memoized_scraped_data[ticker][1]) return self.memoized_scraped_data[ticker][1][tag] if tag in self.memoized_scraped_data[ticker][1] else None def get_company_data(self, ticker): """ Returns a dictionary of data associated with the asset ticker, as found in Yahoo Finance. For a list of available data tags call TickerInfo.get_available_data_tags(tag). :param ticker: (String) Asset ticker for globally listed companies, as supported by Yahoo Finance :return: (dict) data associated with asset ticker; Returns None if the information is not available """ if not isinstance(ticker, str): raise TypeError("ticker parameter is not a String") core = self.__core_parse(ticker) if core is None or len(core) == 0: return None beta = core["beta"] if "beta" in core else None if beta is None: beta = core["beta3Year"] if "beta3Year" in core else None del core["beta3Year"] core["beta"] = beta return core if core is None else core def get_industry(self, ticker): """ Returns the industry of the company that is represented by the asset ticker. If the ticker is not of a stock the function will return None :param ticker: (String) Asset ticker for globally listed companies, as supported by Yahoo Finance :return: (String) the industry of the company represented by the asset ticker; Returns None if the information is not available """ if not isinstance(ticker, str): raise TypeError("ticker parameter is not a String") core = self.__core_parse(ticker) return core if core is None else core["industry"] def get_sector(self, ticker): """ Returns the sector of the company that is represented by the asset ticker. If the ticker is not of a stock, the function will return None :param ticker: (String) Asset ticker for globally listed companies, as supported by Yahoo Finance :return: (String) the sector of the company represented by the asset ticker; Returns None if the information is not available """ if not isinstance(ticker, str): raise TypeError("ticker parameter is not a String") core = self.__core_parse(ticker) return core if core is None else core["sector"] def get_current_price(self, ticker): """ Returns the current price of the asset :param ticker: (String) Asset ticker for globally listed companies, as supported by Yahoo Finance :return: (int) current price; Returns None if the information is not available """ if not isinstance(ticker, str): raise TypeError("ticker parameter is not a String") core = self.__core_parse(ticker) return core if core is None else core["currentPrice"] def get_ytd(self, ticker): """ Returns the year-to-date return of the requested asset :param ticker: (String) Asset ticker for globally listed companies, as supported by Yahoo Finance :return: (int) year-to-date return; Returns None if the information is not available """ if not isinstance(ticker, str): raise TypeError("ticker parameter is not a String") core = self.__core_parse(ticker) print(core) return core if core is None else core['ytdReturn'] def get_beta(self, ticker): """ Provides the beta coefficient for a given asset ticker. If the asset is a bond, the function returns the 3-year beta coefficient :param ticker: (String) Asset ticker for globally listed companies, as supported by Yahoo Finance :return: (int) beta coefficient; Returns None if the information is not available """ core = self.__core_parse(ticker) beta = core["beta"] if "beta" in core else None if beta is None: beta = core["beta3Year"] if "beta3Year" in core else None return beta def get_purchase_recommendation(self, ticker): """ Provides analysts recommendation for purchasing a stock. 1 – Strong Buy 2 – Buy 3 – Hold 4 – Underperform 5 – Sell :param ticker: (String) Asset ticker for globally listed companies, as supported by Yahoo Finance :return: (int) the number representation of stock purchase recommendation; Returns None if the information is not available """ if not isinstance(ticker, str): raise TypeError("ticker parameter is not a String") core = self.__core_parse(ticker) return core if core is None else core["recommendationMean"] # In[ ]: from datax.tools.finance import TickerInfo # Demo 1: Basic Features # In[2]: # Setting up the demo tickerInfo = TickerInfo() stock_ticker = "AAPL" # This is the Apple's Stock Ticker (as listed in NASDAQ) # In[3]: # Gets the current stock price of AAPL stock tickerInfo.get_current_price(stock_ticker) # In[4]: # Gets the current beta coefficient of AAPL stock tickerInfo.get_beta(stock_ticker) # In[5]: # Gets the current purchase recommednation of AAPL stock tickerInfo.get_purchase_recommendation(stock_ticker) # In[6]: # Gets the industry of the company Apple tickerInfo.get_industry(stock_ticker) # In[7]: # Gets the sector of the company Apple tickerInfo.get_sector(stock_ticker) # Demo 2: Advanced Features # In[8]: # Gets all the financial and company-related statistics that are available len(tickerInfo.get_available_data_tags(stock_ticker)), tickerInfo.get_available_data_tags(stock_ticker) # In[9]: # Gets the associated information for the selected tag selected_tag = "fullTimeEmployees" tickerInfo.get_data_from_tag(stock_ticker, selected_tag) # In[15]: # Gets all the information available for AAPL import pandas as pd data = tickerInfo.get_company_data(stock_ticker) pd.Series(data) # In[ ]: