diff --git a/tests/ticker.py b/tests/ticker.py index eae159245..181036490 100644 --- a/tests/ticker.py +++ b/tests/ticker.py @@ -703,6 +703,10 @@ def test_fast_info(self): fast_info_keys = sorted(list(fast_info_keys)) key_rename_map = {} + key_rename_map["currency"] = "currency" + key_rename_map["quote_type"] = "quoteType" + key_rename_map["timezone"] = "exchangeTimezoneName" + key_rename_map["last_price"] = ["currentPrice", "regularMarketPrice"] key_rename_map["open"] = ["open", "regularMarketOpen"] key_rename_map["day_high"] = ["dayHigh", "regularMarketDayHigh"] @@ -710,11 +714,9 @@ def test_fast_info(self): key_rename_map["previous_close"] = ["previousClose"] key_rename_map["regular_market_previous_close"] = ["regularMarketPreviousClose"] - # preMarketPrice - key_rename_map["fifty_day_average"] = "fiftyDayAverage" key_rename_map["two_hundred_day_average"] = "twoHundredDayAverage" - key_rename_map["year_change"] = "52WeekChange" + key_rename_map["year_change"] = ["52WeekChange", "fiftyTwoWeekChange"] key_rename_map["year_high"] = "fiftyTwoWeekHigh" key_rename_map["year_low"] = "fiftyTwoWeekLow" @@ -724,7 +726,6 @@ def test_fast_info(self): key_rename_map["market_cap"] = "marketCap" key_rename_map["shares"] = "sharesOutstanding" - key_rename_map["timezone"] = "exchangeTimezoneName" for k in list(key_rename_map.keys()): if '_' in k: @@ -737,6 +738,7 @@ def test_fast_info(self): # Loose tolerance for averages, no idea why don't match info[]. Is info wrong? custom_tolerances = {} + custom_tolerances["year_change"] = 1.0 # custom_tolerances["ten_day_average_volume"] = 1e-3 custom_tolerances["ten_day_average_volume"] = 1e-1 # custom_tolerances["three_month_average_volume"] = 1e-2 diff --git a/yfinance/base.py b/yfinance/base.py index 1a6e9f51c..c9395c615 100644 --- a/yfinance/base.py +++ b/yfinance/base.py @@ -60,6 +60,7 @@ def __init__(self, tickerBaseObject): self._md = None self._currency = None + self._quote_type = None self._exchange = None self._timezone = None @@ -88,19 +89,19 @@ def __init__(self, tickerBaseObject): # attrs = utils.attributes(self) # self.keys = attrs.keys() # utils.attributes is calling each method, bad! Have to hardcode - orig_keys = ["currency", "exchange", "timezone"] - orig_keys += ["shares", "market_cap"] - orig_keys += ["last_price", "previous_close", "open", "day_high", "day_low"] - orig_keys += ["regular_market_previous_close"] - orig_keys += ["last_volume"] - orig_keys += ["fifty_day_average", "two_hundred_day_average", "ten_day_average_volume", "three_month_average_volume"] - orig_keys += ["year_high", "year_low", "year_change"] + _properties = ["currency", "quote_type", "exchange", "timezone"] + _properties += ["shares", "market_cap"] + _properties += ["last_price", "previous_close", "open", "day_high", "day_low"] + _properties += ["regular_market_previous_close"] + _properties += ["last_volume"] + _properties += ["fifty_day_average", "two_hundred_day_average", "ten_day_average_volume", "three_month_average_volume"] + _properties += ["year_high", "year_low", "year_change"] # Because released before fixing key case, need to officially support # camel-case but also secretly support snake-case - base_keys = [k for k in orig_keys if not '_' in k] + base_keys = [k for k in _properties if not '_' in k] - sc_keys = [k for k in orig_keys if '_' in k] + sc_keys = [k for k in _properties if '_' in k] self._sc_to_cc_key = {k:utils.snake_case_2_camelCase(k) for k in sc_keys} self._cc_to_sc_key = {v:k for k,v in self._sc_to_cc_key.items()} @@ -145,7 +146,7 @@ def toJSON(self, indent=4): def _get_1y_prices(self, fullDaysOnly=False): if self._prices_1y is None: - self._prices_1y = self._tkr.history(period="380d", auto_adjust=False, debug=False) + self._prices_1y = self._tkr.history(period="380d", auto_adjust=False, debug=False, keepna=True) self._md = self._tkr.get_history_metadata() try: ctp = self._md["currentTradingPeriod"] @@ -221,6 +222,17 @@ def currency(self): self._currency = md["currency"] return self._currency + @property + def quote_type(self): + if self._quote_type is not None: + return self._quote_type + + if self._tkr._history_metadata is None: + self._get_1y_prices() + md = self._tkr.get_history_metadata() + self._quote_type = md["instrumentType"] + return self._quote_type + @property def exchange(self): if self._exchange is not None: @@ -261,6 +273,8 @@ def last_price(self): self._last_price = self._get_exchange_metadata()["regularMarketPrice"] else: self._last_price = float(prices["Close"].iloc[-1]) + if _np.isnan(self._last_price): + self._last_price = self._get_exchange_metadata()["regularMarketPrice"] return self._last_price @property @@ -306,7 +320,12 @@ def open(self): if self._open is not None: return self._open prices = self._get_1y_prices() - self._open = None if prices.empty else float(prices["Open"].iloc[-1]) + if prices.empty: + self._open = None + else: + self._open = float(prices["Open"].iloc[-1]) + if _np.isnan(self._open): + self._open = None return self._open @property @@ -314,7 +333,12 @@ def day_high(self): if self._day_high is not None: return self._day_high prices = self._get_1y_prices() - self._day_high = None if prices.empty else float(prices["High"].iloc[-1]) + if prices.empty: + self._day_high = None + else: + self._day_high = float(prices["High"].iloc[-1]) + if _np.isnan(self._day_high): + self._day_high = None return self._day_high @property @@ -322,7 +346,12 @@ def day_low(self): if self._day_low is not None: return self._day_low prices = self._get_1y_prices() - self._day_low = None if prices.empty else float(prices["Low"].iloc[-1]) + if prices.empty: + self._day_low = None + else: + self._day_low = float(prices["Low"].iloc[-1]) + if _np.isnan(self._day_low): + self._day_low = None return self._day_low @property diff --git a/yfinance/scrapers/quote.py b/yfinance/scrapers/quote.py index e2a83486f..6bbb9d664 100644 --- a/yfinance/scrapers/quote.py +++ b/yfinance/scrapers/quote.py @@ -7,14 +7,15 @@ from yfinance.data import TickerData -info_retired_keys_price = {"currentPrice", "dayHigh", "dayLow", "open", "previousClose", "volume"} +info_retired_keys_price = {"currentPrice", "dayHigh", "dayLow", "open", "previousClose", "volume", "volume24Hr"} info_retired_keys_price.update({"regularMarket"+s for s in ["DayHigh", "DayLow", "Open", "PreviousClose", "Price", "Volume"]}) -info_retired_keys_price.update({"fiftyTwoWeekLow", "fiftyTwoWeekHigh", "fiftyTwoWeekChange", "fiftyDayAverage", "twoHundredDayAverage"}) +info_retired_keys_price.update({"fiftyTwoWeekLow", "fiftyTwoWeekHigh", "fiftyTwoWeekChange", "52WeekChange", "fiftyDayAverage", "twoHundredDayAverage"}) info_retired_keys_price.update({"averageDailyVolume10Day", "averageVolume10days", "averageVolume"}) info_retired_keys_exchange = {"currency", "exchange", "exchangeTimezoneName", "exchangeTimezoneShortName"} info_retired_keys_marketCap = {"marketCap"} info_retired_keys_symbol = {"symbol"} -info_retired_keys = info_retired_keys_price | info_retired_keys_exchange | info_retired_keys_marketCap | info_retired_keys_symbol +info_retired_keys_misc = {"quoteType"} +info_retired_keys = info_retired_keys_price | info_retired_keys_exchange | info_retired_keys_marketCap | info_retired_keys_symbol | info_retired_keys_misc PRUNE_INFO = True