From 6b53725dcac65a26c5c1ca2b9c15a2d395ee896b Mon Sep 17 00:00:00 2001 From: Koen werklaptop Date: Wed, 23 Oct 2024 21:27:02 +0200 Subject: [PATCH] Add columns param to get_ticker_price, including tests --- .../ticker_price_with_multiple_columns.yaml | 27 +++++++++++++++ .../ticker_price_with_volume_column.yaml | 27 +++++++++++++++ tests/test_tiingo.py | 34 +++++++++++++++++-- tests/test_tiingo_pandas.py | 18 ++++++++++ tiingo/api.py | 7 ++-- 5 files changed, 109 insertions(+), 4 deletions(-) create mode 100644 tests/fixtures/ticker_price_with_multiple_columns.yaml create mode 100644 tests/fixtures/ticker_price_with_volume_column.yaml diff --git a/tests/fixtures/ticker_price_with_multiple_columns.yaml b/tests/fixtures/ticker_price_with_multiple_columns.yaml new file mode 100644 index 0000000..352cc78 --- /dev/null +++ b/tests/fixtures/ticker_price_with_multiple_columns.yaml @@ -0,0 +1,27 @@ +interactions: +- request: + body: null + headers: + Accept: ['*/*'] + Accept-Encoding: ['gzip, deflate'] + Authorization: [Token 0000000000000000000000000000000000000000] + Connection: [keep-alive] + Content-Type: [application/json] + User-Agent: [tiingo-python-client 0.5.0] + method: GET + uri: https://api.tiingo.com/tiingo/daily/GOOGL/prices?format=json&resampleFreq=daily&columns=open,high,low,close,volume + response: + body: {string: '[{"close":165.14,"date":"2024-10-22T00:00:00+00:00","high":165.77,"low":162.98,"open":162.98,"volume":16568121}]'} + headers: + Allow: ['GET, HEAD, OPTIONS'] + Content-Length: ['1982'] + Content-Type: [application/json] + Date: ['Wed, 23 Oct 2024 02:42:06 GMT'] + Server: [nginx/1.10.1] + Vary: ['Accept, Cookie'] + X-Frame-Options: [SAMEORIGIN] + status: {code: 200, message: OK} +version: 1 + + + diff --git a/tests/fixtures/ticker_price_with_volume_column.yaml b/tests/fixtures/ticker_price_with_volume_column.yaml new file mode 100644 index 0000000..fe8f1a7 --- /dev/null +++ b/tests/fixtures/ticker_price_with_volume_column.yaml @@ -0,0 +1,27 @@ +interactions: +- request: + body: null + headers: + Accept: ['*/*'] + Accept-Encoding: ['gzip, deflate'] + Authorization: [Token 0000000000000000000000000000000000000000] + Connection: [keep-alive] + Content-Type: [application/json] + User-Agent: [tiingo-python-client 0.5.0] + method: GET + uri: https://api.tiingo.com/tiingo/daily/GOOGL/prices?format=json&resampleFreq=daily&columns=volume + response: + body: {string: '[{"date":"2024-10-22T00:00:00+00:00","volume":16568121}]'} + headers: + Allow: ['GET, HEAD, OPTIONS'] + Content-Length: ['1001'] + Content-Type: [application/json] + Date: ['Wed, 23 Oct 2024 02:42:06 GMT'] + Server: [nginx/1.10.1] + Vary: ['Accept, Cookie'] + X-Frame-Options: [SAMEORIGIN] + status: {code: 200, message: OK} +version: 1 + + + diff --git a/tests/test_tiingo.py b/tests/test_tiingo.py index 5500141..2cf4c65 100644 --- a/tests/test_tiingo.py +++ b/tests/test_tiingo.py @@ -55,7 +55,7 @@ class TestTickerPrices(TestCase): def test_ticker_metadata_as_object(self): metadata = self._client.get_ticker_metadata("GOOGL", fmt="object") assert metadata.ticker == "GOOGL" # Access property via ATTRIBUTE - assert metadata.name # (contrast with key access above + assert metadata.name # (contrast with key access above @vcr.use_cassette('tests/fixtures/ticker_price.yaml') def test_ticker_price(self): @@ -68,7 +68,7 @@ class TestTickerPrices(TestCase): def test_ticker_price(self): """Test that weekly frequency works""" prices = self._client.get_ticker_price("GOOGL", startDate='2018-01-05', - endDate='2018-01-19', frequency='weekly') + endDate='2018-01-19', frequency='weekly') assert len(prices) == 3 assert prices[0].get('adjClose') @@ -98,6 +98,34 @@ class TestTickerPrices(TestCase): rows = list(reader) assert len(rows) > 2 # more than 1 day of data + @vcr.use_cassette('tests/fixtures/ticker_price_with_volume_column.yaml') + def test_ticker_price_with_volume_column(self): + """Confirm that CSV endpoint works""" + prices = self._client.get_ticker_price("GOOGL", + columns="volume", + fmt='json') + assert len(prices) == 1 + assert prices[0].get('date') + assert not prices[0].get('high') + assert not prices[0].get('low') + assert not prices[0].get('open') + assert not prices[0].get('close') + assert prices[0].get('volume') + + @vcr.use_cassette('tests/fixtures/ticker_price_with_multiple_columns.yaml') + def test_ticker_price_with_multiple_columns(self): + """Confirm that CSV endpoint works""" + prices = self._client.get_ticker_price("GOOGL", + columns="open,high,low,close,volume", + fmt='json') + assert len(prices) == 1 + assert prices[0].get('date') + assert prices[0].get('high') + assert prices[0].get('low') + assert prices[0].get('open') + assert prices[0].get('close') + assert prices[0].get('volume') + @vcr.use_cassette('tests/fixtures/intraday_price.yaml') def test_intraday_ticker_price(self): """Test the EOD Prices Endpoint with data param""" @@ -149,6 +177,7 @@ class TestTickerPrices(TestCase): endDate="2018-01-02", frequency="1.5mins") + # tiingo/news class TestNews(TestCase): @@ -227,6 +256,7 @@ class TestNews(TestCase): with self.assertRaises(RestClientError): assert self._client.get_bulk_news(file_id="1", fmt="object") + # FUNDAMENTALS ENDPOINTS class TestFundamentals(TestCase): diff --git a/tests/test_tiingo_pandas.py b/tests/test_tiingo_pandas.py index add9731..da7b9d4 100644 --- a/tests/test_tiingo_pandas.py +++ b/tests/test_tiingo_pandas.py @@ -114,6 +114,24 @@ class TestTiingoWithPython(TestCase): frequency="30Min") self.assertGreater(len(prices), 1) + @vcr.use_cassette('tests/fixtures/ticker_price_with_volume_column.yaml') + def test_get_dataframe_with_volume_column(self): + """Confirm that CSV endpoint works""" + prices = self._client.get_dataframe("GOOGL", + columns="volume", + fmt='json') + assert len(prices) == 1 + assert len(prices.columns) == 2 + + @vcr.use_cassette('tests/fixtures/ticker_price_with_multiple_columns.yaml') + def test_get_dataframe_with_multiple_columns(self): + """Confirm that CSV endpoint works""" + prices = self._client.get_dataframe("GOOGL", + columns="open,high,low,close,volume", + fmt='json') + assert len(prices) == 1 + assert len(prices.columns) == 6 + def test_metric_name_column_error(self): with self.assertRaises(APIColumnNameError): self._client.get_dataframe(['GOOGL', 'AAPL'], startDate='2018-01-05', diff --git a/tiingo/api.py b/tiingo/api.py index 5ca3862..8c157fa 100644 --- a/tiingo/api.py +++ b/tiingo/api.py @@ -219,7 +219,7 @@ class TiingoClient(RestClient): return prices def get_ticker_price( - self, ticker, startDate=None, endDate=None, fmt="json", frequency="daily" + self, ticker, startDate=None, endDate=None, columns=None, fmt="json", frequency="daily" ): """By default, return latest EOD Composite Price for a stock ticker. On average, each feed contains 3 data sources. @@ -231,6 +231,7 @@ class TiingoClient(RestClient): ticker (string): Unique identifier for stock ticker startDate (string): Start of ticker range in YYYY-MM-DD format endDate (string): End of ticker range in YYYY-MM-DD format + columns (string): Comma separated parameter specifying which columns to retrieve (to include volume) fmt (string): 'csv' or 'json' frequency (string): Resample frequency """ @@ -244,6 +245,8 @@ class TiingoClient(RestClient): params["startDate"] = startDate if endDate: params["endDate"] = endDate + if columns: + params["columns"] = columns # TODO: evaluate whether to stream CSV to cache on disk, or # load as array in memory, or just pass plain text @@ -279,7 +282,7 @@ class TiingoClient(RestClient): tickers (string/list): One or more unique identifiers for a stock ticker. startDate (string): Start of ticker range in YYYY-MM-DD format. endDate (string): End of ticker range in YYYY-MM-DD format. - columns (string): Comma seperated parameter specifying which columns to retrieve (to include volume) + columns (string): Comma separated parameter specifying which columns to retrieve (to include volume) metric_name (string): Optional parameter specifying metric to be returned for each ticker. In the event of a single ticker, this is optional and if not specified all of the available data will be returned. In the event of a list of tickers,