From 8e0f5344ac76dc9021704c91309c7c1485bdd0c6 Mon Sep 17 00:00:00 2001 From: 2xmm <2xmm.mike@gmail.com> Date: Sat, 17 Oct 2020 16:56:22 -0300 Subject: [PATCH 1/4] Add option to request data in csv format in get_dataframe method --- .../ticker_price_pandas_daily_csv.yaml | 62 +++++++++++ ...ily_equivalent_requesting_json_or_csv.yaml | 100 ++++++++++++++++++ ...er_price_pandas_daily_metric_name_csv.yaml | 62 +++++++++++ ...ce_pandas_weekly_multiple_tickers_csv.yaml | 94 ++++++++++++++++ tests/test_tiingo_pandas.py | 52 +++++++++ tiingo/api.py | 73 +++++++++---- 6 files changed, 423 insertions(+), 20 deletions(-) create mode 100644 tests/fixtures/ticker_price_pandas_daily_csv.yaml create mode 100644 tests/fixtures/ticker_price_pandas_daily_equivalent_requesting_json_or_csv.yaml create mode 100644 tests/fixtures/ticker_price_pandas_daily_metric_name_csv.yaml create mode 100644 tests/fixtures/ticker_price_pandas_weekly_multiple_tickers_csv.yaml diff --git a/tests/fixtures/ticker_price_pandas_daily_csv.yaml b/tests/fixtures/ticker_price_pandas_daily_csv.yaml new file mode 100644 index 0000000..d126abd --- /dev/null +++ b/tests/fixtures/ticker_price_pandas_daily_csv.yaml @@ -0,0 +1,62 @@ +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.13.0 + method: GET + uri: https://api.tiingo.com/tiingo/daily/GOOGL/prices?format=csv&resampleFreq=daily&startDate=2018-01-05&endDate=2018-01-19 + response: + body: + string: 'date,close,high,low,open,volume,adjClose,adjHigh,adjLow,adjOpen,adjVolume,divCash,splitFactor + + 2018-01-05,1110.29,1113.58,1101.8,1103.45,1493389,1110.29,1113.58,1101.8,1103.45,1493389,0.0,1.0 + + 2018-01-08,1114.21,1119.16,1110.0,1111.0,1148958,1114.21,1119.16,1110.0,1111.0,1148958,0.0,1.0 + + 2018-01-09,1112.79,1118.44,1108.2,1118.44,1335995,1112.79,1118.44,1108.2,1118.44,1335995,0.0,1.0 + + 2018-01-10,1110.14,1112.78,1103.98,1107.0,1027781,1110.14,1112.78,1103.98,1107.0,1027781,0.0,1.0 + + 2018-01-11,1112.05,1114.85,1106.48,1112.31,1102461,1112.05,1114.85,1106.48,1112.31,1102461,0.0,1.0 + + 2018-01-12,1130.65,1131.3,1108.01,1110.1,1914460,1130.65,1131.3,1108.01,1110.1,1914460,0.0,1.0 + + 2018-01-16,1130.7,1148.88,1126.66,1140.31,1783881,1130.7,1148.88,1126.66,1140.31,1783881,0.0,1.0 + + 2018-01-17,1139.1,1139.32,1123.49,1136.36,1353097,1139.1,1139.32,1123.49,1136.36,1353097,0.0,1.0 + + 2018-01-18,1135.97,1140.59,1124.46,1139.35,1333633,1135.97,1140.59,1124.46,1139.35,1333633,0.0,1.0 + + 2018-01-19,1143.5,1143.78,1132.5,1138.03,1418376,1143.5,1143.78,1132.5,1138.03,1418376,0.0,1.0 + + ' + headers: + allow: + - GET, HEAD, OPTIONS + content-length: + - '1062' + content-type: + - text/csv + date: + - Sat, 17 Oct 2020 19:30:04 GMT + server: + - nginx/1.14.0 (Ubuntu) + vary: + - Accept, Cookie, Origin + x-frame-options: + - SAMEORIGIN + status: + code: 200 + message: OK +version: 1 diff --git a/tests/fixtures/ticker_price_pandas_daily_equivalent_requesting_json_or_csv.yaml b/tests/fixtures/ticker_price_pandas_daily_equivalent_requesting_json_or_csv.yaml new file mode 100644 index 0000000..354565a --- /dev/null +++ b/tests/fixtures/ticker_price_pandas_daily_equivalent_requesting_json_or_csv.yaml @@ -0,0 +1,100 @@ +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.13.0 + method: GET + uri: https://api.tiingo.com/tiingo/daily/GOOGL/prices?format=json&resampleFreq=daily&startDate=2018-01-05&endDate=2018-01-19 + response: + body: + string: '[{"date":"2018-01-05T00:00:00.000Z","close":1110.29,"high":1113.58,"low":1101.8,"open":1103.45,"volume":1493389,"adjClose":1110.29,"adjHigh":1113.58,"adjLow":1101.8,"adjOpen":1103.45,"adjVolume":1493389,"divCash":0.0,"splitFactor":1.0},{"date":"2018-01-08T00:00:00.000Z","close":1114.21,"high":1119.16,"low":1110.0,"open":1111.0,"volume":1148958,"adjClose":1114.21,"adjHigh":1119.16,"adjLow":1110.0,"adjOpen":1111.0,"adjVolume":1148958,"divCash":0.0,"splitFactor":1.0},{"date":"2018-01-09T00:00:00.000Z","close":1112.79,"high":1118.44,"low":1108.2,"open":1118.44,"volume":1335995,"adjClose":1112.79,"adjHigh":1118.44,"adjLow":1108.2,"adjOpen":1118.44,"adjVolume":1335995,"divCash":0.0,"splitFactor":1.0},{"date":"2018-01-10T00:00:00.000Z","close":1110.14,"high":1112.78,"low":1103.98,"open":1107.0,"volume":1027781,"adjClose":1110.14,"adjHigh":1112.78,"adjLow":1103.98,"adjOpen":1107.0,"adjVolume":1027781,"divCash":0.0,"splitFactor":1.0},{"date":"2018-01-11T00:00:00.000Z","close":1112.05,"high":1114.85,"low":1106.48,"open":1112.31,"volume":1102461,"adjClose":1112.05,"adjHigh":1114.85,"adjLow":1106.48,"adjOpen":1112.31,"adjVolume":1102461,"divCash":0.0,"splitFactor":1.0},{"date":"2018-01-12T00:00:00.000Z","close":1130.65,"high":1131.3,"low":1108.01,"open":1110.1,"volume":1914460,"adjClose":1130.65,"adjHigh":1131.3,"adjLow":1108.01,"adjOpen":1110.1,"adjVolume":1914460,"divCash":0.0,"splitFactor":1.0},{"date":"2018-01-16T00:00:00.000Z","close":1130.7,"high":1148.88,"low":1126.66,"open":1140.31,"volume":1783881,"adjClose":1130.7,"adjHigh":1148.88,"adjLow":1126.66,"adjOpen":1140.31,"adjVolume":1783881,"divCash":0.0,"splitFactor":1.0},{"date":"2018-01-17T00:00:00.000Z","close":1139.1,"high":1139.32,"low":1123.49,"open":1136.36,"volume":1353097,"adjClose":1139.1,"adjHigh":1139.32,"adjLow":1123.49,"adjOpen":1136.36,"adjVolume":1353097,"divCash":0.0,"splitFactor":1.0},{"date":"2018-01-18T00:00:00.000Z","close":1135.97,"high":1140.59,"low":1124.46,"open":1139.35,"volume":1333633,"adjClose":1135.97,"adjHigh":1140.59,"adjLow":1124.46,"adjOpen":1139.35,"adjVolume":1333633,"divCash":0.0,"splitFactor":1.0},{"date":"2018-01-19T00:00:00.000Z","close":1143.5,"high":1143.78,"low":1132.5,"open":1138.03,"volume":1418376,"adjClose":1143.5,"adjHigh":1143.78,"adjLow":1132.5,"adjOpen":1138.03,"adjVolume":1418376,"divCash":0.0,"splitFactor":1.0}]' + headers: + allow: + - GET, HEAD, OPTIONS + content-length: + - '2349' + content-type: + - application/json + date: + - Sat, 17 Oct 2020 19:37:30 GMT + server: + - nginx/1.14.0 (Ubuntu) + vary: + - Accept, Cookie, Origin + x-frame-options: + - SAMEORIGIN + status: + code: 200 + message: OK +- 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.13.0 + method: GET + uri: https://api.tiingo.com/tiingo/daily/GOOGL/prices?format=csv&resampleFreq=daily&startDate=2018-01-05&endDate=2018-01-19 + response: + body: + string: 'date,close,high,low,open,volume,adjClose,adjHigh,adjLow,adjOpen,adjVolume,divCash,splitFactor + + 2018-01-05,1110.29,1113.58,1101.8,1103.45,1493389,1110.29,1113.58,1101.8,1103.45,1493389,0.0,1.0 + + 2018-01-08,1114.21,1119.16,1110.0,1111.0,1148958,1114.21,1119.16,1110.0,1111.0,1148958,0.0,1.0 + + 2018-01-09,1112.79,1118.44,1108.2,1118.44,1335995,1112.79,1118.44,1108.2,1118.44,1335995,0.0,1.0 + + 2018-01-10,1110.14,1112.78,1103.98,1107.0,1027781,1110.14,1112.78,1103.98,1107.0,1027781,0.0,1.0 + + 2018-01-11,1112.05,1114.85,1106.48,1112.31,1102461,1112.05,1114.85,1106.48,1112.31,1102461,0.0,1.0 + + 2018-01-12,1130.65,1131.3,1108.01,1110.1,1914460,1130.65,1131.3,1108.01,1110.1,1914460,0.0,1.0 + + 2018-01-16,1130.7,1148.88,1126.66,1140.31,1783881,1130.7,1148.88,1126.66,1140.31,1783881,0.0,1.0 + + 2018-01-17,1139.1,1139.32,1123.49,1136.36,1353097,1139.1,1139.32,1123.49,1136.36,1353097,0.0,1.0 + + 2018-01-18,1135.97,1140.59,1124.46,1139.35,1333633,1135.97,1140.59,1124.46,1139.35,1333633,0.0,1.0 + + 2018-01-19,1143.5,1143.78,1132.5,1138.03,1418376,1143.5,1143.78,1132.5,1138.03,1418376,0.0,1.0 + + ' + headers: + allow: + - GET, HEAD, OPTIONS + content-length: + - '1062' + content-type: + - text/csv + date: + - Sat, 17 Oct 2020 19:37:31 GMT + server: + - nginx/1.14.0 (Ubuntu) + vary: + - Accept, Cookie, Origin + x-frame-options: + - SAMEORIGIN + status: + code: 200 + message: OK +version: 1 diff --git a/tests/fixtures/ticker_price_pandas_daily_metric_name_csv.yaml b/tests/fixtures/ticker_price_pandas_daily_metric_name_csv.yaml new file mode 100644 index 0000000..d126abd --- /dev/null +++ b/tests/fixtures/ticker_price_pandas_daily_metric_name_csv.yaml @@ -0,0 +1,62 @@ +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.13.0 + method: GET + uri: https://api.tiingo.com/tiingo/daily/GOOGL/prices?format=csv&resampleFreq=daily&startDate=2018-01-05&endDate=2018-01-19 + response: + body: + string: 'date,close,high,low,open,volume,adjClose,adjHigh,adjLow,adjOpen,adjVolume,divCash,splitFactor + + 2018-01-05,1110.29,1113.58,1101.8,1103.45,1493389,1110.29,1113.58,1101.8,1103.45,1493389,0.0,1.0 + + 2018-01-08,1114.21,1119.16,1110.0,1111.0,1148958,1114.21,1119.16,1110.0,1111.0,1148958,0.0,1.0 + + 2018-01-09,1112.79,1118.44,1108.2,1118.44,1335995,1112.79,1118.44,1108.2,1118.44,1335995,0.0,1.0 + + 2018-01-10,1110.14,1112.78,1103.98,1107.0,1027781,1110.14,1112.78,1103.98,1107.0,1027781,0.0,1.0 + + 2018-01-11,1112.05,1114.85,1106.48,1112.31,1102461,1112.05,1114.85,1106.48,1112.31,1102461,0.0,1.0 + + 2018-01-12,1130.65,1131.3,1108.01,1110.1,1914460,1130.65,1131.3,1108.01,1110.1,1914460,0.0,1.0 + + 2018-01-16,1130.7,1148.88,1126.66,1140.31,1783881,1130.7,1148.88,1126.66,1140.31,1783881,0.0,1.0 + + 2018-01-17,1139.1,1139.32,1123.49,1136.36,1353097,1139.1,1139.32,1123.49,1136.36,1353097,0.0,1.0 + + 2018-01-18,1135.97,1140.59,1124.46,1139.35,1333633,1135.97,1140.59,1124.46,1139.35,1333633,0.0,1.0 + + 2018-01-19,1143.5,1143.78,1132.5,1138.03,1418376,1143.5,1143.78,1132.5,1138.03,1418376,0.0,1.0 + + ' + headers: + allow: + - GET, HEAD, OPTIONS + content-length: + - '1062' + content-type: + - text/csv + date: + - Sat, 17 Oct 2020 19:30:04 GMT + server: + - nginx/1.14.0 (Ubuntu) + vary: + - Accept, Cookie, Origin + x-frame-options: + - SAMEORIGIN + status: + code: 200 + message: OK +version: 1 diff --git a/tests/fixtures/ticker_price_pandas_weekly_multiple_tickers_csv.yaml b/tests/fixtures/ticker_price_pandas_weekly_multiple_tickers_csv.yaml new file mode 100644 index 0000000..7e1d652 --- /dev/null +++ b/tests/fixtures/ticker_price_pandas_weekly_multiple_tickers_csv.yaml @@ -0,0 +1,94 @@ +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.13.0 + method: GET + uri: https://api.tiingo.com/tiingo/daily/GOOGL/prices?format=csv&resampleFreq=weekly&startDate=2018-01-05&endDate=2018-01-19 + response: + body: + string: 'date,close,high,low,open,volume,adjClose,adjHigh,adjLow,adjOpen,adjVolume,divCash,splitFactor + + 2018-01-05,1110.29,1113.58,1053.02,1053.02,5889084,1110.29,1113.58,1053.02,1053.02,5889084,0.0,1.0 + + 2018-01-12,1130.65,1131.3,1103.98,1111.0,6529655,1130.65,1131.3,1103.98,1111.0,6529655,0.0,1.0 + + 2018-01-19,1143.5,1148.88,1123.49,1140.31,5888987,1143.5,1148.88,1123.49,1140.31,5888987,0.0,1.0 + + ' + headers: + allow: + - GET, HEAD, OPTIONS + content-length: + - '385' + content-type: + - text/csv + date: + - Sat, 17 Oct 2020 19:45:21 GMT + server: + - nginx/1.14.0 (Ubuntu) + vary: + - Accept, Cookie, Origin + x-frame-options: + - SAMEORIGIN + status: + code: 200 + message: OK +- 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.13.0 + method: GET + uri: https://api.tiingo.com/tiingo/daily/AAPL/prices?format=csv&resampleFreq=weekly&startDate=2018-01-05&endDate=2018-01-19 + response: + body: + string: 'date,close,high,low,open,volume,adjClose,adjHigh,adjLow,adjOpen,adjVolume,divCash,splitFactor + + 2018-01-05,175.0,175.37,169.26,170.16,99095223,42.1719535342792,42.2611170931803,40.7887134583549,41.0055977908169,396380892,0.0,1.0 + + 2018-01-12,177.09,177.36,173.0,174.35,107548622,42.6756071507743,42.7406724505129,41.6899883510303,42.0153148497233,430194488,0.0,1.0 + + 2018-01-19,178.46,180.1,175.07,177.9,122974060,43.0057533012998,43.4009647515639,42.1888223156929,42.8708030499901,491896240,0.0,1.0 + + ' + headers: + allow: + - GET, HEAD, OPTIONS + content-length: + - '494' + content-type: + - text/csv + date: + - Sat, 17 Oct 2020 19:45:22 GMT + server: + - nginx/1.14.0 (Ubuntu) + vary: + - Accept, Cookie, Origin + x-frame-options: + - SAMEORIGIN + status: + code: 200 + message: OK +version: 1 diff --git a/tests/test_tiingo_pandas.py b/tests/test_tiingo_pandas.py index 7d22ba7..0f23c72 100644 --- a/tests/test_tiingo_pandas.py +++ b/tests/test_tiingo_pandas.py @@ -38,6 +38,16 @@ class TestTiingoWithPython(TestCase): assert len(prices.columns) == 2 assert len(prices.index) == 3 + @vcr.use_cassette('tests/fixtures/ticker_price_pandas_weekly_multiple_tickers_csv.yaml') + def test_return_pandas_format_multiple(self): + """Test that valid pandas format is returned when specified""" + tickers = ["GOOGL", "AAPL"] + prices = self._client.get_dataframe(tickers, startDate='2018-01-05', + endDate='2018-01-19', metric_name='adjClose', frequency='weekly', fmt='csv') + self.assertTrue(isinstance(prices, pd.DataFrame)) + assert len(prices.columns) == 2 + assert len(prices.index) == 3 + @vcr.use_cassette('tests/fixtures/ticker_price_pandas_daily.yaml') def test_return_pandas_daily(self): """Test that valid pandas format is returned when specified""" @@ -46,6 +56,18 @@ class TestTiingoWithPython(TestCase): self.assertTrue(isinstance(prices, pd.DataFrame)) assert len(prices.columns) == 12 + @vcr.use_cassette('tests/fixtures/ticker_price_pandas_daily_csv.yaml') + def test_return_pandas_daily_csv(self): + """Test that valid pandas format is returned when specified and csv data requested""" + prices = self._client.get_dataframe("GOOGL", + startDate='2018-01-05', endDate='2018-01-19', + frequency='daily', fmt='csv') + self.assertTrue(isinstance(prices, pd.DataFrame)) + self.assertTrue(isinstance(prices.index, pd.DatetimeIndex)) + assert prices.index.tz.zone == 'UTC' + assert len(prices) == 10 + assert len(prices.columns) == 12 + @vcr.use_cassette('tests/fixtures/ticker_price_pandas_daily_metric_name.yaml') def test_return_pandas_daily(self): """Test that one column is returned when a metric name is specified""" @@ -55,6 +77,36 @@ class TestTiingoWithPython(TestCase): self.assertTrue(isinstance(prices, pd.Series)) assert len(prices.index) == 10 + @vcr.use_cassette('tests/fixtures/ticker_price_pandas_daily_metric_name_csv.yaml') + def test_return_pandas_daily_metric_name_csv(self): + """Test that one column is returned when a metric name is specified and csv data requested + Request unadjusted close column to ensure data remains constant in case GOOGL splits + or distributes dividends. + """ + prices = self._client.get_dataframe("GOOGL", startDate='2018-01-05', metric_name='close', + endDate='2018-01-19', frequency='daily', fmt='csv') + self.assertTrue(isinstance(prices, pd.Series)) + self.assertTrue(isinstance(prices.index, pd.DatetimeIndex)) + assert prices.index.tz.zone == 'UTC' + assert prices.values.tolist() == [ + 1110.29,1114.21,1112.79,1110.14,1112.05, + 1130.65,1130.7,1139.1,1135.97,1143.5] + assert len(prices.index) == 10 + + @vcr.use_cassette('tests/fixtures/ticker_price_pandas_daily_equivalent_requesting_json_or_csv.yaml') + def test_price_pandas_daily_equivalent_requesting_json_or_csv(self): + """Test that equivalent data is returned when specifying reuqest format in json or csv. + """ + prices_json = self._client.get_dataframe("GOOGL", + startDate='2018-01-05', endDate='2018-01-19', + metric_name='close', frequency='daily') + + prices_csv = self._client.get_dataframe("GOOGL", + startDate='2018-01-05', endDate='2018-01-19', + metric_name='close', frequency='daily', fmt='csv') + + self.assertTrue(prices_json.equals(prices_csv)) + @vcr.use_cassette('tests/fixtures/intraday_price.yaml') def test_intraday_ticker_price(self): """Test the EOD Prices Endpoint with data param""" diff --git a/tiingo/api.py b/tiingo/api.py index e402b41..9486240 100644 --- a/tiingo/api.py +++ b/tiingo/api.py @@ -166,6 +166,47 @@ class TiingoClient(RestClient): else: return "iex/{}/prices".format(ticker) + def _request_pandas(self, ticker, metric_name, params): + """ + Return data for ticker as a pandas.DataFrame if metric_name is not + specified or as a pandas.Series if metric_name is specified. + + :param ticker (string): ticker to be requested + :param params (dict): a dictionary containing valid resampleFreq + and format strings per the Tiingo api + :param 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, + this parameter is required. + """ + url = self._get_url(ticker, params['resampleFreq']) + response = self._request('GET', url, params=params) + if params['format'] == 'csv': + if sys.version_info < (3, 0): # python 2 + from StringIO import StringIO + else: # python 3 + from io import StringIO + + df = pd.read_csv(StringIO(response.content.decode('utf-8'))) + else: + df = pd.DataFrame(response.json()) + + df.set_index('date', inplace=True) + + if metric_name is not None: + prices = df[metric_name] + else: + prices = df + + prices.index = pd.to_datetime(prices.index) + + # Localize to UTC to ensure equivalence between data returned in json format and + # csv format. Data requested in csv format does not include a timezone. + if prices.index.tz is None: + prices.index = prices.index.tz_localize('UTC') + + return prices + def get_ticker_price(self, ticker, startDate=None, endDate=None, fmt='json', frequency='daily'): @@ -205,7 +246,8 @@ class TiingoClient(RestClient): return response.content.decode("utf-8") def get_dataframe(self, tickers, - startDate=None, endDate=None, metric_name=None, frequency='daily'): + startDate=None, endDate=None, metric_name=None, + frequency='daily', fmt='json'): """ Return a pandas.DataFrame of historical prices for one or more ticker symbols. @@ -225,6 +267,7 @@ class TiingoClient(RestClient): all of the available data will be returned. In the event of a list of tickers, this parameter is required. frequency (string): Resample frequency (defaults to daily). + fmt (string): 'csv' or 'json' """ valid_columns = {'open', 'high', 'low', 'close', 'volume', 'adjOpen', 'adjHigh', 'adjLow', @@ -238,7 +281,7 @@ class TiingoClient(RestClient): Please provide a metric_name, or call this method with one ticker at a time.""") params = { - 'format': 'json', + 'format': fmt, 'resampleFreq': frequency } if startDate: @@ -248,28 +291,18 @@ class TiingoClient(RestClient): if pandas_is_installed: if type(tickers) is str: - stock = tickers - url = self._get_url(stock, frequency) - response = self._request('GET', url, params=params) - df = pd.DataFrame(response.json()) - if metric_name is not None: - prices = df[metric_name] - prices.index = df['date'] - else: - prices = df - prices.index = df['date'] - del (prices['date']) + prices = self._request_pandas( + ticker=tickers, params=params, metric_name=metric_name) else: prices = pd.DataFrame() for stock in tickers: - url = self._get_url(stock, frequency) - response = self._request('GET', url, params=params) - df = pd.DataFrame(response.json()) - df.index = df['date'] - df.rename(index=str, columns={metric_name: stock}, inplace=True) - prices = pd.concat([prices, df[stock]], axis=1, sort=True) - prices.index = pd.to_datetime(prices.index) + ticker_series = self._request_pandas( + ticker=stock, params=params, metric_name=metric_name) + ticker_series = ticker_series.rename(stock) + prices = pd.concat([prices, ticker_series], axis=1, sort=True) + return prices + else: error_message = ("Pandas is not installed, but .get_ticker_price() was " "called with fmt=pandas. In order to install tiingo with " From df738097b6c4a8b180b212898a152407e3710c7c Mon Sep 17 00:00:00 2001 From: 2xmm <2xmm.mike@gmail.com> Date: Sat, 17 Oct 2020 17:13:46 -0300 Subject: [PATCH 2/4] Update HISTORY.rst --- HISTORY.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/HISTORY.rst b/HISTORY.rst index 6bf8404..9b7c2fe 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -5,6 +5,7 @@ History 0.13.0 (2019-11-XX - Unreleased) -------------------------------- * Minor: Address Pandas Future Warning for sorting in pd.concat (#392) +* Feature: Add option to request data in csv format in get_dataframe method potentially boosting speed up to 4-5x. (#523) 0.12.0 (2019-10-20) -------------------- From bba8a59341fca06aa9c5368a91329d4a0acd37b2 Mon Sep 17 00:00:00 2001 From: 2xmm <2xmm.mike@gmail.com> Date: Thu, 22 Oct 2020 10:44:40 -0300 Subject: [PATCH 3/4] Add name to AUTHORS.rst --- AUTHORS.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/AUTHORS.rst b/AUTHORS.rst index fcc5a57..e700171 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -15,3 +15,4 @@ Contributors * Stephen Clark * Davis Thames * Nima Yazdanmehr +* Michael MacCormack \ No newline at end of file From 7e6af79adf594cc8159b21cb920f85b3f0efd36f Mon Sep 17 00:00:00 2001 From: 2xmm <2xmm.mike@gmail.com> Date: Thu, 22 Oct 2020 10:56:29 -0300 Subject: [PATCH 4/4] Update comment regarding timezone inclusion for csv requests. --- tiingo/api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tiingo/api.py b/tiingo/api.py index 9486240..0b59ea5 100644 --- a/tiingo/api.py +++ b/tiingo/api.py @@ -201,7 +201,7 @@ class TiingoClient(RestClient): prices.index = pd.to_datetime(prices.index) # Localize to UTC to ensure equivalence between data returned in json format and - # csv format. Data requested in csv format does not include a timezone. + # csv format. Tiingo daily data requested in csv format does not include a timezone. if prices.index.tz is None: prices.index = prices.index.tz_localize('UTC')