Skip to content

Commit

Permalink
Improve bad ticker handling ; Remove redundant get_earnings_history()
Browse files Browse the repository at this point in the history
  • Loading branch information
ValueRaider committed Nov 6, 2022
1 parent 9b169e6 commit b050692
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 48 deletions.
1 change: 0 additions & 1 deletion test_yfinance.py
Expand Up @@ -56,7 +56,6 @@ def test_attributes(self):
ticker.options
ticker.news
ticker.earnings_trend
ticker.earnings_history
ticker.earnings_dates
ticker.earnings_forecasts

Expand Down
48 changes: 45 additions & 3 deletions tests/ticker.py
Expand Up @@ -2,13 +2,18 @@

import unittest

# Create temp session
import requests_cache, tempfile
td = tempfile.TemporaryDirectory()

class TestTicker(unittest.TestCase):
def setUp(self):
pass
global td
self.td = td
self.session = requests_cache.CachedSession(self.td.name + '/' + "yfinance.cache")

def tearDown(self):
pass
self.session.close()

def test_getTz(self):
tkrs = ["IMP.JO", "BHG.JO", "SSW.JO", "BP.L", "INTC"]
Expand All @@ -17,11 +22,48 @@ def test_getTz(self):
yf.utils.get_tz_cache().store(tkr, None)

# Test:
dat = yf.Ticker(tkr)
dat = yf.Ticker(tkr, session=self.session)
tz = dat._get_ticker_tz(debug_mode=False, proxy=None, timeout=None)

self.assertIsNotNone(tz)

def test_badTicker(self):
# Check yfinance doesn't die when ticker delisted

tkr = "AM2Z.TA"
dat = yf.Ticker(tkr, session=self.session)
dat.history(period="1wk")
dat.history(start="2022-01-01")
dat.history(start="2022-01-01", end="2022-03-01")
yf.download([tkr], period="1wk")
dat.isin
dat.major_holders
dat.institutional_holders
dat.mutualfund_holders
dat.dividends
dat.splits
dat.actions
dat.shares
dat.info
dat.calendar
dat.recommendations
dat.earnings
dat.quarterly_earnings
dat.income_stmt
dat.quarterly_income_stmt
dat.balance_sheet
dat.quarterly_balance_sheet
dat.cashflow
dat.quarterly_cashflow
dat.recommendations_summary
dat.analyst_price_target
dat.revenue_forecasts
dat.sustainability
dat.options
dat.news
dat.earnings_trend
dat.earnings_dates
dat.earnings_forecasts

if __name__ == '__main__':
unittest.main()
66 changes: 22 additions & 44 deletions yfinance/base.py
Expand Up @@ -154,7 +154,7 @@ def history(self, period="1mo", interval="1d",
tz = self._get_ticker_tz(debug, proxy, timeout)
if tz is None:
# Every valid ticker has a timezone. Missing = problem
err_msg = "No timezone found, symbol certainly delisted"
err_msg = "No timezone found, symbol may be delisted"
shared._DFS[self.ticker] = utils.empty_df()
shared._ERRORS[self.ticker] = err_msg
if debug:
Expand Down Expand Up @@ -609,6 +609,11 @@ def _get_info(self, proxy=None):
ticker_url = "{}/{}".format(self._scrape_url, self.ticker)

# get info and sustainability
json_data = utils.get_json_data_stores(ticker_url, proxy, self.session)
if 'QuoteSummaryStore' not in json_data:
err_msg = "No summary info found, symbol may be delisted"
print('- %s: %s' % (self.ticker, err_msg))
return None
data = utils.get_json_data_stores(ticker_url, proxy, self.session)['QuoteSummaryStore']

# sustainability
Expand Down Expand Up @@ -822,14 +827,19 @@ def cleanup(data):
self._get_info(proxy)

# get fundamentals
fin_data = utils.get_json_data_stores(ticker_url + '/financials', proxy, self.session)
fin_data_quote = fin_data['QuoteSummaryStore']

# generic patterns
self._earnings = {"yearly": utils._pd.DataFrame(), "quarterly": utils._pd.DataFrame()}
self._financials = {}
for name in ["income", "balance-sheet", "cash-flow"]:
self._financials[name] = {"yearly":utils._pd.DataFrame(), "quarterly":utils._pd.DataFrame()}

fin_data = utils.get_json_data_stores(ticker_url + '/financials', proxy, self.session)
if not "QuoteSummaryStore" in fin_data:
err_msg = "No financials data found, symbol may be delisted"
print('- %s: %s' % (self.ticker, err_msg))
return None
fin_data_quote = fin_data['QuoteSummaryStore']

# generic patterns
for name in ["income", "balance-sheet", "cash-flow"]:
annual, qtr = self._create_financials_table(name, proxy)
if annual is not None:
Expand Down Expand Up @@ -1142,6 +1152,9 @@ def get_isin(self, proxy=None):

q = ticker
self.get_info(proxy=proxy)
if self._info is None:
# Don't print error message cause _get_info() will print one
return None
if "shortName" in self._info:
q = self._info['shortName']

Expand Down Expand Up @@ -1242,8 +1255,10 @@ def get_earnings_dates(self, proxy=None):
dates = _pd.concat([dates, data], axis=0)
page_offset += page_size

if dates is None:
raise Exception("No data found, symbol may be delisted")
if dates is None or dates.shape[0]==0:
err_msg = "No earnings dates found, symbol may be delisted"
print('- %s: %s' % (self.ticker, err_msg))
return None
dates = dates.reset_index(drop=True)

# Drop redundant columns
Expand Down Expand Up @@ -1277,40 +1292,3 @@ def get_earnings_dates(self, proxy=None):
self._earnings_dates = dates

return dates

def get_earnings_history(self, proxy=None):
if self._earnings_history:
return self._earnings_history

# setup proxy in requests format
if proxy is not None:
if isinstance(proxy, dict) and "https" in proxy:
proxy = proxy["https"]
proxy = {"https": proxy}

url = "{}/calendar/earnings?symbol={}".format(_ROOT_URL_, self.ticker)
session = self.session or _requests
data = session.get(
url=url,
proxies=proxy,
headers=utils.user_agent_headers
).text

if "Will be right back" in data:
raise RuntimeError("*** YAHOO! FINANCE IS CURRENTLY DOWN! ***\n"
"Our engineers are working quickly to resolve "
"the issue. Thank you for your patience.")

try:
# read_html returns a list of pandas Dataframes of all the tables in `data`
data = _pd.read_html(data)[0]
data.replace("-", _np.nan, inplace=True)

data['EPS Estimate'] = _pd.to_numeric(data['EPS Estimate'])
data['Reported EPS'] = _pd.to_numeric(data['Reported EPS'])
self._earnings_history = data
# if no tables are found a ValueError is thrown
except ValueError:
print("Could not find earnings history data for {}.".format(self.ticker))
return
return data

0 comments on commit b050692

Please sign in to comment.