From 9315f7b61da506ec9db36757a25c65b28ae75a6e Mon Sep 17 00:00:00 2001 From: ValueRaider Date: Mon, 24 Oct 2022 13:34:57 +0100 Subject: [PATCH 1/5] Add Ticker._fetch_ticker_tz() for faster tz fetch --- yfinance/base.py | 47 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 41 insertions(+), 6 deletions(-) diff --git a/yfinance/base.py b/yfinance/base.py index 01a9151be..c9798fa4f 100644 --- a/yfinance/base.py +++ b/yfinance/base.py @@ -159,7 +159,7 @@ def history(self, period="1mo", interval="1d", if start or period is None or period.lower() == "max": # Check can get TZ. Fail => probably delisted - tz = self._get_ticker_tz() + tz = self._get_ticker_tz(proxy, timeout) if tz is None: # Every valid ticker has a timezone. Missing = problem err_msg = "No timezone found, symbol certainly delisted" @@ -533,7 +533,7 @@ def _fix_unit_mixups(self, df, interval, tz_exchange): return df - def _get_ticker_tz(self): + def _get_ticker_tz(self, proxy=None, timeout=None): if not self._tz is None: return self._tz @@ -545,10 +545,7 @@ def _get_ticker_tz(self): tz = None if tz is None: - try: - tz = self.info["exchangeTimezoneName"] - except KeyError: - return None + tz = self._fetch_ticker_tz(proxy, timeout) if utils.is_valid_timezone(tz): # info fetch is relatively slow so cache timezone @@ -559,6 +556,44 @@ def _get_ticker_tz(self): self._tz = tz return tz + def _fetch_ticker_tz(self, proxy=None, timeout=None): + # Query Yahoo for basic price data just to get returned timezone + + params = {"range":"1wk", "interval":"1d"} + + # setup proxy in requests format + if proxy is not None: + if isinstance(proxy, dict) and "https" in proxy: + proxy = proxy["https"] + proxy = {"https": proxy} + + # Getting data from json + url = "{}/v8/finance/chart/{}".format(self._base_url, self.ticker) + + session = self.session or _requests + try: + data = session.get(url=url, params=params, proxies=proxy, headers=utils.user_agent_headers, timeout=timeout) + if "Will be right back" in data.text or data is None: + return None + data = data.json() + except Exception: + data = None + + fail = False + if data is None or not type(data) is dict: + fail = True + elif type(data) is dict and 'status_code' in data.keys(): + fail = True + elif not "chart" in data or data["chart"]["result"] is None or not data["chart"]["result"]: + fail = True + if fail: + return None + + try: + return data["chart"]["result"][0]["meta"]["exchangeTimezoneName"] + except: + return None + def _get_info(self, proxy=None): # setup proxy in requests format From fe1c705e2451ffbfdb1d7eeda89d3ed2388b7b9c Mon Sep 17 00:00:00 2001 From: ValueRaider Date: Mon, 24 Oct 2022 13:45:25 +0100 Subject: [PATCH 2/5] Simplify Ticker._fetch_ticker_tz() --- yfinance/base.py | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/yfinance/base.py b/yfinance/base.py index c9798fa4f..035bc7ccd 100644 --- a/yfinance/base.py +++ b/yfinance/base.py @@ -558,7 +558,7 @@ def _get_ticker_tz(self, proxy=None, timeout=None): def _fetch_ticker_tz(self, proxy=None, timeout=None): # Query Yahoo for basic price data just to get returned timezone - + params = {"range":"1wk", "interval":"1d"} # setup proxy in requests format @@ -576,20 +576,6 @@ def _fetch_ticker_tz(self, proxy=None, timeout=None): if "Will be right back" in data.text or data is None: return None data = data.json() - except Exception: - data = None - - fail = False - if data is None or not type(data) is dict: - fail = True - elif type(data) is dict and 'status_code' in data.keys(): - fail = True - elif not "chart" in data or data["chart"]["result"] is None or not data["chart"]["result"]: - fail = True - if fail: - return None - - try: return data["chart"]["result"][0]["meta"]["exchangeTimezoneName"] except: return None From 2623ba967d8e71b789b643c0efbb97abc7f8cd50 Mon Sep 17 00:00:00 2001 From: ValueRaider Date: Mon, 24 Oct 2022 13:46:39 +0100 Subject: [PATCH 3/5] Simplify Ticker._fetch_ticker_tz() - 2 --- yfinance/base.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/yfinance/base.py b/yfinance/base.py index 035bc7ccd..ff887803c 100644 --- a/yfinance/base.py +++ b/yfinance/base.py @@ -573,8 +573,6 @@ def _fetch_ticker_tz(self, proxy=None, timeout=None): session = self.session or _requests try: data = session.get(url=url, params=params, proxies=proxy, headers=utils.user_agent_headers, timeout=timeout) - if "Will be right back" in data.text or data is None: - return None data = data.json() return data["chart"]["result"][0]["meta"]["exchangeTimezoneName"] except: From df11fcdb37b1f14b05502c96b41bef35d984b32a Mon Sep 17 00:00:00 2001 From: ValueRaider Date: Tue, 25 Oct 2022 13:59:51 +0100 Subject: [PATCH 4/5] Improve Ticker._fetch_ticker_tz() ; Change timeout default to 10 --- tests/ticker.py | 36 ++++++++++++++++++++++++++++++++++++ yfinance/base.py | 18 ++++++++++-------- yfinance/multi.py | 6 +++--- yfinance/tickers.py | 4 ++-- 4 files changed, 51 insertions(+), 13 deletions(-) create mode 100644 tests/ticker.py diff --git a/tests/ticker.py b/tests/ticker.py new file mode 100644 index 000000000..8844e1b2d --- /dev/null +++ b/tests/ticker.py @@ -0,0 +1,36 @@ +from .context import yfinance as yf + +import unittest + +import requests_cache +session = requests_cache.CachedSession("/home/gonzo/.cache/yfinance.cache") + +class TestTicker(unittest.TestCase): + def setUp(self): + self.session = session + + def tearDown(self): + pass + + + def test_getTz(self): + tkrs = [] + tkrs.append("IMP.JO") + tkrs.append("BHG.JO") + tkrs.append("SSW.JO") + tkrs.append("BP.L") + tkrs.append("INTC") + test_run = False + for tkr in tkrs: + # First step: remove ticker from tz-cache + yf.utils.tz_cache.store(tkr, None) + + # Test: + dat = yf.Ticker(tkr, session=self.session) + tz = dat._get_ticker_tz(debug_mode=False, proxy=None, timeout=None) + + self.assertIsNotNone(tz) + + +if __name__ == '__main__': + unittest.main() diff --git a/yfinance/base.py b/yfinance/base.py index ff887803c..4bac07b26 100644 --- a/yfinance/base.py +++ b/yfinance/base.py @@ -103,7 +103,7 @@ def stats(self, proxy=None): def history(self, period="1mo", interval="1d", start=None, end=None, prepost=False, actions=True, auto_adjust=True, back_adjust=False, repair=False, keepna=False, - proxy=None, rounding=False, timeout=None, **kwargs): + proxy=None, rounding=False, timeout=10, **kwargs): """ :Parameters: period : str @@ -139,7 +139,7 @@ def history(self, period="1mo", interval="1d", timeout: None or float If not None stops waiting for a response after given number of seconds. (Can also be a fraction of a second e.g. 0.01) - Default is None. + Default is 10 seconds. **kwargs: dict debug: bool Optional. If passed as False, will suppress @@ -159,7 +159,7 @@ def history(self, period="1mo", interval="1d", if start or period is None or period.lower() == "max": # Check can get TZ. Fail => probably delisted - tz = self._get_ticker_tz(proxy, timeout) + tz = self._get_ticker_tz(debug_mode, proxy, timeout) if tz is None: # Every valid ticker has a timezone. Missing = problem err_msg = "No timezone found, symbol certainly delisted" @@ -533,7 +533,7 @@ def _fix_unit_mixups(self, df, interval, tz_exchange): return df - def _get_ticker_tz(self, proxy=None, timeout=None): + def _get_ticker_tz(self, debug_mode, proxy, timeout): if not self._tz is None: return self._tz @@ -545,7 +545,7 @@ def _get_ticker_tz(self, proxy=None, timeout=None): tz = None if tz is None: - tz = self._fetch_ticker_tz(proxy, timeout) + tz = self._fetch_ticker_tz(debug_mode, proxy, timeout) if utils.is_valid_timezone(tz): # info fetch is relatively slow so cache timezone @@ -556,10 +556,10 @@ def _get_ticker_tz(self, proxy=None, timeout=None): self._tz = tz return tz - def _fetch_ticker_tz(self, proxy=None, timeout=None): + def _fetch_ticker_tz(self, debug_mode, proxy, timeout): # Query Yahoo for basic price data just to get returned timezone - params = {"range":"1wk", "interval":"1d"} + params = {"range":"1d", "interval":"1d"} # setup proxy in requests format if proxy is not None: @@ -575,7 +575,9 @@ def _fetch_ticker_tz(self, proxy=None, timeout=None): data = session.get(url=url, params=params, proxies=proxy, headers=utils.user_agent_headers, timeout=timeout) data = data.json() return data["chart"]["result"][0]["meta"]["exchangeTimezoneName"] - except: + except Exception as e: + if debug_mode: + print("Failed to get ticker '{}' reason: {}".format(self.ticker, e)) return None diff --git a/yfinance/multi.py b/yfinance/multi.py index 7f598f87d..7b1f5d7c6 100644 --- a/yfinance/multi.py +++ b/yfinance/multi.py @@ -32,7 +32,7 @@ def download(tickers, start=None, end=None, actions=False, threads=True, ignore_tz=True, group_by='column', auto_adjust=False, back_adjust=False, repair=False, keepna=False, progress=True, period="max", show_errors=True, interval="1d", prepost=False, - proxy=None, rounding=False, timeout=None, **kwargs): + proxy=None, rounding=False, timeout=10, **kwargs): """Download yahoo tickers :Parameters: tickers : str, list @@ -198,7 +198,7 @@ def _download_one_threaded(ticker, start=None, end=None, auto_adjust=False, back_adjust=False, repair=False, actions=False, progress=True, period="max", interval="1d", prepost=False, proxy=None, - keepna=False, rounding=False, timeout=None): + keepna=False, rounding=False, timeout=10): data = _download_one(ticker, start, end, auto_adjust, back_adjust, repair, actions, period, interval, prepost, proxy, rounding, @@ -212,7 +212,7 @@ def _download_one(ticker, start=None, end=None, auto_adjust=False, back_adjust=False, repair=False, actions=False, period="max", interval="1d", prepost=False, proxy=None, rounding=False, - keepna=False, timeout=None): + keepna=False, timeout=10): return Ticker(ticker).history(period=period, interval=interval, start=start, end=end, prepost=prepost, diff --git a/yfinance/tickers.py b/yfinance/tickers.py index f50cc6539..e4b303852 100644 --- a/yfinance/tickers.py +++ b/yfinance/tickers.py @@ -49,7 +49,7 @@ def history(self, period="1mo", interval="1d", actions=True, auto_adjust=True, repair=False, proxy=None, threads=True, group_by='column', progress=True, - timeout=None, **kwargs): + timeout=10, **kwargs): return self.download( period, interval, @@ -64,7 +64,7 @@ def download(self, period="1mo", interval="1d", actions=True, auto_adjust=True, repair=False, proxy=None, threads=True, group_by='column', progress=True, - timeout=None, **kwargs): + timeout=10, **kwargs): data = multi.download(self.symbols, start=start, end=end, From 2dce6a705ce05317bb0e15b0a63ff9517e07a338 Mon Sep 17 00:00:00 2001 From: ValueRaider Date: Tue, 25 Oct 2022 14:01:44 +0100 Subject: [PATCH 5/5] Remove debug code --- tests/ticker.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/tests/ticker.py b/tests/ticker.py index 8844e1b2d..4b512651d 100644 --- a/tests/ticker.py +++ b/tests/ticker.py @@ -2,12 +2,9 @@ import unittest -import requests_cache -session = requests_cache.CachedSession("/home/gonzo/.cache/yfinance.cache") - class TestTicker(unittest.TestCase): def setUp(self): - self.session = session + pass def tearDown(self): pass @@ -26,7 +23,7 @@ def test_getTz(self): yf.utils.tz_cache.store(tkr, None) # Test: - dat = yf.Ticker(tkr, session=self.session) + dat = yf.Ticker(tkr) tz = dat._get_ticker_tz(debug_mode=False, proxy=None, timeout=None) self.assertIsNotNone(tz)