diff --git a/pyproject.toml b/pyproject.toml index 5d555aa..d5fc989 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "pricehist" -version = "1.4.12" +version = "1.4.10" description = "Fetch and format historical price data" authors = ["Chris Berkhout "] license = "MIT" diff --git a/src/pricehist/__init__.py b/src/pricehist/__init__.py index 2736991..738cf25 100644 --- a/src/pricehist/__init__.py +++ b/src/pricehist/__init__.py @@ -1 +1 @@ -__version__ = "1.4.12" +__version__ = "1.4.10" diff --git a/src/pricehist/sources/yahoo.py b/src/pricehist/sources/yahoo.py index 25d92fe..ce5cf7d 100644 --- a/src/pricehist/sources/yahoo.py +++ b/src/pricehist/sources/yahoo.py @@ -72,7 +72,6 @@ class Yahoo(BaseSource): data = self._data(series) quote = data["chart"]["result"][0]["meta"]["currency"] - offset = data["chart"]["result"][0]["meta"]["gmtoffset"] timestamps = data["chart"]["result"][0]["timestamp"] adjclose_data = data["chart"]["result"][0]["indicators"]["adjclose"][0] @@ -80,21 +79,19 @@ class Yahoo(BaseSource): amounts = {**adjclose_data, **rest_data} prices = [ - Price(date, amount) + Price(ts, amount) for i in range(len(timestamps)) - if (date := self._ts_to_date(timestamps[i] + offset)) <= series.end + if (ts := datetime.fromtimestamp(timestamps[i]).strftime("%Y-%m-%d")) + <= series.end if (amount := self._amount(amounts, series.type, i)) is not None ] return dataclasses.replace(series, quote=quote, prices=prices) - def _ts_to_date(self, ts) -> str: - return datetime.fromtimestamp(ts, tz=timezone.utc).date().isoformat() - def _amount(self, amounts, type, i): if type == "mid" and amounts["high"] != "null" and amounts["low"] != "null": return sum([Decimal(amounts["high"][i]), Decimal(amounts["low"][i])]) / 2 - elif amounts[type] != "null" and amounts[type][i] is not None: + elif amounts[type] != "null": return Decimal(amounts[type][i]) else: return None @@ -142,10 +139,11 @@ class Yahoo(BaseSource): raise exceptions.InvalidPair( series.base, series.quote, self, "Symbol not found." ) - elif code == 400 and "Data doesn't exist" in text: + if code == 400 and "Data doesn't exist" in text: raise exceptions.BadResponse( "No data for the given interval. Try requesting a larger interval." ) + elif code == 404 and "Timestamp data missing" in text: raise exceptions.BadResponse( "Data missing. The given interval may be for a gap in the data " @@ -164,10 +162,4 @@ class Yahoo(BaseSource): "The data couldn't be parsed. " ) from e - if "timestamp" not in data["chart"]["result"][0]: - raise exceptions.BadResponse( - "No data for the given interval. " - "There may be a problem with the symbol or the interval." - ) - return data diff --git a/tests/live.sh b/tests/live.sh index 157cdad..fc24c08 100755 --- a/tests/live.sh +++ b/tests/live.sh @@ -75,10 +75,10 @@ name="Alpha Vantage physical currency" cmd="pricehist fetch alphavantage AUD/EUR -s 2021-01-11 -e 2021-01-14" read -r -d '' expected < 9 -def test_fetch_skips_dates_with_nulls(src, type, with_null_ok): - series = src.fetch(Series("INR=X", "", type, "2017-07-10", "2017-07-12")) - assert series.prices[0] == Price("2017-07-10", Decimal("64.61170196533203125")) - assert series.prices[1] == Price("2017-07-12", Decimal("64.52559661865234375")) - assert len(series.prices) == 2 - - def test_fetch_to_future(src, type, recent_ok): series = src.fetch(Series("TSLA", "", type, "2021-01-04", "2100-01-08")) assert len(series.prices) > 0 diff --git a/tests/pricehist/sources/test_yahoo/inrx-with-null.json b/tests/pricehist/sources/test_yahoo/inrx-with-null.json deleted file mode 100644 index 5ae762e..0000000 --- a/tests/pricehist/sources/test_yahoo/inrx-with-null.json +++ /dev/null @@ -1,119 +0,0 @@ -{ - "chart": { - "result": [ - { - "meta": { - "currency": "INR", - "symbol": "INR=X", - "exchangeName": "CCY", - "fullExchangeName": "CCY", - "instrumentType": "CURRENCY", - "firstTradeDate": 1070236800, - "regularMarketTime": 1726284616, - "hasPrePostMarketData": false, - "gmtoffset": 3600, - "timezone": "BST", - "exchangeTimezoneName": "Europe/London", - "regularMarketPrice": 83.89, - "fiftyTwoWeekHigh": 83.89, - "fiftyTwoWeekLow": 83.89, - "regularMarketDayHigh": 83.89, - "regularMarketDayLow": 83.89, - "regularMarketVolume": 0, - "longName": "USD/INR", - "shortName": "USD/INR", - "chartPreviousClose": 64.6117, - "priceHint": 4, - "currentTradingPeriod": { - "pre": { - "timezone": "BST", - "start": 1726182000, - "end": 1726182000, - "gmtoffset": 3600 - }, - "regular": { - "timezone": "BST", - "start": 1726182000, - "end": 1726268340, - "gmtoffset": 3600 - }, - "post": { - "timezone": "BST", - "start": 1726268340, - "end": 1726268340, - "gmtoffset": 3600 - } - }, - "dataGranularity": "1d", - "range": "", - "validRanges": [ - "1d", - "5d", - "1mo", - "3mo", - "6mo", - "1y", - "2y", - "5y", - "10y", - "ytd", - "max" - ] - }, - "timestamp": [ - 1499641200, - 1499727600, - 1499814000, - 1499900400 - ], - "indicators": { - "quote": [ - { - "open": [ - 64.6155014038086, - null, - 64.55549621582031, - 64.46800231933594 - ], - "volume": [ - 0, - null, - 0, - 0 - ], - "low": [ - 64.41000366210938, - null, - 64.3499984741211, - 64.33999633789062 - ], - "close": [ - 64.61170196533203, - null, - 64.52559661865234, - 64.36499786376953 - ], - "high": [ - 64.6155014038086, - null, - 64.56999969482422, - 64.48419952392578 - ] - } - ], - "adjclose": [ - { - "adjclose": [ - 64.61170196533203, - null, - 64.52559661865234, - 64.36499786376953 - ] - } - ] - } - } - ], - "error": null - } -}