Update Alphavantage source for changes in which endpoint is premium.

This commit is contained in:
Chris Berkhout 2022-11-24 15:14:42 +01:00
parent 09fbeb79cb
commit d6036c9d14
3 changed files with 14 additions and 24 deletions

View file

@ -51,8 +51,7 @@ class AlphaVantage(BaseSource):
"will list all digital and physical currency symbols.\n" "will list all digital and physical currency symbols.\n"
"The PAIR for stocks is the stock symbol only. The quote currency " "The PAIR for stocks is the stock symbol only. The quote currency "
f"will be determined automatically. {self._stock_symbols_message()}\n" f"will be determined automatically. {self._stock_symbols_message()}\n"
"The price type 'adjclose' is only available for stocks, and " "The price type 'adjclose' is only available for stocks.\n"
"requires an access key for which premium endpoints are unlocked.\n"
"Beware that digital currencies quoted in non-USD currencies may " "Beware that digital currencies quoted in non-USD currencies may "
"be converted from USD data at one recent exchange rate rather " "be converted from USD data at one recent exchange rate rather "
"than using historical rates.\n" "than using historical rates.\n"
@ -187,10 +186,9 @@ class AlphaVantage(BaseSource):
def _stock_data(self, series): def _stock_data(self, series):
output_quote = self._stock_currency(series.base) or "UNKNOWN" output_quote = self._stock_currency(series.base) or "UNKNOWN"
if series.type == "adjclose": # As of 2022-11-24 TIME_SERIES_DAILY_ADJUSTED is no longer premium, but
function = "TIME_SERIES_DAILY_ADJUSTED" # now TIME_SERIES_DAILY is. So, always use TIME_SERIES_DAILY_ADJUSTED.
else: function = "TIME_SERIES_DAILY_ADJUSTED"
function = "TIME_SERIES_DAILY"
params = { params = {
"function": function, "function": function,
@ -341,7 +339,7 @@ class AlphaVantage(BaseSource):
raise exceptions.RateLimit(data["Note"]) raise exceptions.RateLimit(data["Note"])
if ( if (
"Information" in data "Information" in data
and "ways to unlock premium" in data["Information"] and "unlock all premium endpoints" in data["Information"]
): ):
msg = "You were denied access to a premium endpoint." msg = "You were denied access to a premium endpoint."
raise exceptions.CredentialsError([self.API_KEY_NAME], self, msg) raise exceptions.CredentialsError([self.API_KEY_NAME], self, msg)

View file

@ -47,11 +47,11 @@ name="Alpha Vantage stocks"
cmd="pricehist fetch alphavantage TSLA -s 2021-01-04 -e 2021-01-08" cmd="pricehist fetch alphavantage TSLA -s 2021-01-04 -e 2021-01-08"
read -r -d '' expected <<END read -r -d '' expected <<END
date,base,quote,amount,source,type date,base,quote,amount,source,type
2021-01-04,TSLA,USD,729.7700,alphavantage,close 2021-01-04,TSLA,USD,729.77,alphavantage,close
2021-01-05,TSLA,USD,735.1100,alphavantage,close 2021-01-05,TSLA,USD,735.11,alphavantage,close
2021-01-06,TSLA,USD,755.9800,alphavantage,close 2021-01-06,TSLA,USD,755.98,alphavantage,close
2021-01-07,TSLA,USD,816.0400,alphavantage,close 2021-01-07,TSLA,USD,816.04,alphavantage,close
2021-01-08,TSLA,USD,880.0200,alphavantage,close 2021-01-08,TSLA,USD,880.02,alphavantage,close
END END
run_test "$name" "$cmd" "$expected" run_test "$name" "$cmd" "$expected"

View file

@ -48,9 +48,6 @@ search_url = re.compile(
r"https://www\.alphavantage\.co/query\?function=SYMBOL_SEARCH.*" r"https://www\.alphavantage\.co/query\?function=SYMBOL_SEARCH.*"
) )
stock_url = re.compile( stock_url = re.compile(
r"https://www\.alphavantage\.co/query\?function=TIME_SERIES_DAILY&.*"
)
adj_stock_url = re.compile(
r"https://www\.alphavantage\.co/query\?function=TIME_SERIES_DAILY_ADJUSTED.*" r"https://www\.alphavantage\.co/query\?function=TIME_SERIES_DAILY_ADJUSTED.*"
) )
physical_url = re.compile(r"https://www\.alphavantage\.co/query\?function=FX_DAILY.*") physical_url = re.compile(r"https://www\.alphavantage\.co/query\?function=FX_DAILY.*")
@ -69,12 +66,7 @@ rate_limit_json = (
premium_json = ( premium_json = (
'{ "Information": "Thank you for using Alpha Vantage! This is a premium ' '{ "Information": "Thank you for using Alpha Vantage! This is a premium '
"endpoint and there are multiple ways to unlock premium endpoints: (1) " "endpoint. You may subscribe to any of the premium plans at "
"become a holder of Alpha Vantage Coin (AVC), an Ethereum-based "
"cryptocurrency that provides various utility & governance functions "
"within the Alpha Vantage ecosystem (AVC mining guide: "
"https://www.alphatournament.com/avc_mining_guide/) to unlock all "
"premium endpoints, (2) subscribe to any of the premium plans at "
"https://www.alphavantage.co/premium/ to instantly unlock all premium " "https://www.alphavantage.co/premium/ to instantly unlock all premium "
'endpoints" }' 'endpoints" }'
) )
@ -117,7 +109,7 @@ def ibm_ok(requests_mock):
@pytest.fixture @pytest.fixture
def ibm_adj_ok(requests_mock): def ibm_adj_ok(requests_mock):
json = (Path(os.path.splitext(__file__)[0]) / "ibm-partial-adj.json").read_text() json = (Path(os.path.splitext(__file__)[0]) / "ibm-partial-adj.json").read_text()
requests_mock.add(responses.GET, adj_stock_url, body=json, status=200) requests_mock.add(responses.GET, stock_url, body=json, status=200)
yield requests_mock yield requests_mock
@ -304,7 +296,7 @@ def test_fetch_stock_known(src, type, search_ok, ibm_ok):
stock_req = ibm_ok.calls[1].request stock_req = ibm_ok.calls[1].request
assert search_req.params["function"] == "SYMBOL_SEARCH" assert search_req.params["function"] == "SYMBOL_SEARCH"
assert search_req.params["keywords"] == "IBM" assert search_req.params["keywords"] == "IBM"
assert stock_req.params["function"] == "TIME_SERIES_DAILY" assert stock_req.params["function"] == "TIME_SERIES_DAILY_ADJUSTED"
assert stock_req.params["symbol"] == "IBM" assert stock_req.params["symbol"] == "IBM"
assert stock_req.params["outputsize"] == "full" assert stock_req.params["outputsize"] == "full"
assert (series.base, series.quote) == ("IBM", "USD") assert (series.base, series.quote) == ("IBM", "USD")
@ -427,7 +419,7 @@ def test_fetch_stock_rate_limit(src, type, search_ok, requests_mock):
def test_fetch_stock_premium(src, search_ok, requests_mock): def test_fetch_stock_premium(src, search_ok, requests_mock):
requests_mock.add(responses.GET, adj_stock_url, body=premium_json) requests_mock.add(responses.GET, stock_url, body=premium_json)
with pytest.raises(exceptions.CredentialsError) as e: with pytest.raises(exceptions.CredentialsError) as e:
src.fetch(Series("IBM", "", "adjclose", "2021-01-04", "2021-01-08")) src.fetch(Series("IBM", "", "adjclose", "2021-01-04", "2021-01-08"))
assert "denied access to a premium endpoint" in str(e.value) assert "denied access to a premium endpoint" in str(e.value)