Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add columns as parameter to get_dataframe #1057

Merged
merged 13 commits into from
Nov 17, 2024
1 change: 1 addition & 0 deletions HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ History
--------------------------------

* Dev: New config for readthedocs
* Feature: Add 'columns' parameter to 'get_dataframe' func (#1057)

0.15.6 (2024-05-25)
--------------------------------
Expand Down
27 changes: 27 additions & 0 deletions tests/fixtures/ticker_price_with_multiple_columns.yaml
Original file line number Diff line number Diff line change
@@ -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



27 changes: 27 additions & 0 deletions tests/fixtures/ticker_price_with_volume_column.yaml
Original file line number Diff line number Diff line change
@@ -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



34 changes: 32 additions & 2 deletions tests/test_tiingo.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ def test_ticker_metadata(self):
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):
Expand All @@ -68,7 +68,7 @@ def test_ticker_price(self):
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')

Expand Down Expand Up @@ -98,6 +98,34 @@ def test_ticker_price_with_csv(self):
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"""
Expand Down Expand Up @@ -149,6 +177,7 @@ def test_invalid_frequency_error(self):
endDate="2018-01-02",
frequency="1.5mins")


# tiingo/news
class TestNews(TestCase):

Expand Down Expand Up @@ -227,6 +256,7 @@ def test_news_bulk_as_objects(self):
with self.assertRaises(RestClientError):
assert self._client.get_bulk_news(file_id="1", fmt="object")


# FUNDAMENTALS ENDPOINTS
class TestFundamentals(TestCase):

Expand Down
18 changes: 18 additions & 0 deletions tests/test_tiingo_pandas.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,24 @@ def test_intraday_ticker_price(self):
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',
Expand Down
11 changes: 10 additions & 1 deletion tiingo/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ def _request_pandas(self, ticker, metric_name, params):
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.
Expand All @@ -231,6 +231,8 @@ def get_ticker_price(
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): Optional comma separated parameter specifying which columns to retrieve.
By default, 'date', 'open', 'close', 'high' and 'low' are retrieved. 'volume' is an extra option.
fmt (string): 'csv' or 'json'
frequency (string): Resample frequency
"""
Expand All @@ -244,6 +246,8 @@ def get_ticker_price(
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
Expand All @@ -262,6 +266,7 @@ def get_dataframe(
startDate=None,
endDate=None,
metric_name=None,
columns=None,
frequency="daily",
fmt="json",
):
Expand All @@ -278,6 +283,8 @@ def get_dataframe(
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): Optional comma separated parameter specifying which columns to retrieve.
By default, 'date', 'open', 'close', 'high' and 'low' are retrieved. 'volume' is an extra option.
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,
Expand Down Expand Up @@ -315,6 +322,8 @@ def get_dataframe(
params["startDate"] = startDate
if endDate:
params["endDate"] = endDate
if columns:
params["columns"] = columns

if pandas_is_installed:
if type(tickers) is str:
Expand Down