-
Notifications
You must be signed in to change notification settings - Fork 683
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #478 from bashtage/tiingo
ENH: Add readers for Tiingo data
- Loading branch information
Showing
8 changed files
with
294 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,5 +17,6 @@ Data Readers | |
quandl | ||
robinhood | ||
stooq | ||
tiingo | ||
tsp | ||
world-bank |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
Tiingo | ||
------ | ||
|
||
.. py:module:: pandas_datareader.tiingo | ||
.. autoclass:: TiingoDailyReader | ||
:members: | ||
:inherited-members: | ||
|
||
.. autoclass:: TiingoQuoteReader | ||
:members: | ||
:inherited-members: | ||
|
||
.. autoclass:: TiingoMetaDataReader | ||
:members: | ||
:inherited-members: | ||
|
||
.. autofunction:: get_tiingo_symbols |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
import os | ||
|
||
import pandas as pd | ||
import pytest | ||
|
||
from pandas_datareader.tiingo import TiingoDailyReader, TiingoMetaDataReader, \ | ||
TiingoQuoteReader | ||
|
||
TEST_API_KEY = os.getenv('TIINGO_API_KEY') | ||
|
||
syms = ['GOOG', ['GOOG', 'XOM']] | ||
ids = list(map(str, syms)) | ||
|
||
|
||
@pytest.fixture(params=syms, ids=ids) | ||
def symbols(request): | ||
return request.param | ||
|
||
|
||
@pytest.mark.skipif(TEST_API_KEY is None, reason="TIINGO_API_KEY not set") | ||
def test_tiingo_quote(symbols): | ||
df = TiingoQuoteReader(symbols=symbols).read() | ||
assert isinstance(df, pd.DataFrame) | ||
if isinstance(symbols, str): | ||
symbols = [symbols] | ||
assert df.shape[0] == len(symbols) | ||
|
||
|
||
@pytest.mark.skipif(TEST_API_KEY is None, reason="TIINGO_API_KEY not set") | ||
def test_tiingo_historical(symbols): | ||
df = TiingoDailyReader(symbols=symbols).read() | ||
assert isinstance(df, pd.DataFrame) | ||
if isinstance(symbols, str): | ||
symbols = [symbols] | ||
assert df.index.levels[0].shape[0] == len(symbols) | ||
|
||
|
||
@pytest.mark.skipif(TEST_API_KEY is None, reason="TIINGO_API_KEY not set") | ||
def test_tiingo_metadata(symbols): | ||
df = TiingoMetaDataReader(symbols=symbols).read() | ||
assert isinstance(df, pd.DataFrame) | ||
if isinstance(symbols, str): | ||
symbols = [symbols] | ||
assert df.shape[1] == len(symbols) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,191 @@ | ||
import os | ||
|
||
import pandas as pd | ||
|
||
from pandas_datareader.base import _BaseReader | ||
|
||
|
||
def get_tiingo_symbols(): | ||
""" | ||
Get the set of stock symbols supported by Tiingo | ||
Returns | ||
------- | ||
symbols : DataFrame | ||
DataFrame with symbols (ticker), exchange, asset type, currency and | ||
start and end dates | ||
Notes | ||
----- | ||
Reads https://apimedia.tiingo.com/docs/tiingo/daily/supported_tickers.zip | ||
""" | ||
url = 'https://apimedia.tiingo.com/docs/tiingo/daily/supported_tickers.zip' | ||
return pd.read_csv(url) | ||
|
||
|
||
class TiingoDailyReader(_BaseReader): | ||
""" | ||
Historical daily data from Tiingo on equities, ETFs and mutual funds | ||
Parameters | ||
---------- | ||
symbols : {str, List[str]} | ||
String symbol of like of symbols | ||
start : str, (defaults to '1/1/2010') | ||
Starting date, timestamp. Parses many different kind of date | ||
representations (e.g., 'JAN-01-2010', '1/1/10', 'Jan, 1, 1980') | ||
end : str, (defaults to today) | ||
Ending date, timestamp. Same format as starting date. | ||
retry_count : int, default 3 | ||
Number of times to retry query request. | ||
pause : float, default 0.1 | ||
Time, in seconds, of the pause between retries. | ||
session : Session, default None | ||
requests.sessions.Session instance to be used | ||
freq : {str, None} | ||
Not used. | ||
api_key : str, optional | ||
Tiingo API key . If not provided the environmental variable | ||
TIINGO_API_KEY is read. The API key is *required*. | ||
""" | ||
|
||
def __init__(self, symbols, start=None, end=None, retry_count=3, pause=0.1, | ||
timeout=30, session=None, freq=None, api_key=None): | ||
super(TiingoDailyReader, self).__init__(symbols, start, end, | ||
retry_count, pause, timeout, | ||
session, freq) | ||
if isinstance(self.symbols, str): | ||
self.symbols = [self.symbols] | ||
self._symbol = '' | ||
if api_key is None: | ||
api_key = os.environ.get('TIINGO_API_KEY', None) | ||
if api_key is None: | ||
raise ValueError('The tiingo API key must be provided either ' | ||
'through the api_key variable or through the ' | ||
'environmental variable TIINGO_API_KEY.') | ||
self.api_key = api_key | ||
self._concat_axis = 0 | ||
|
||
@property | ||
def url(self): | ||
"""API URL""" | ||
_url = 'https://api.tiingo.com/tiingo/daily/{ticker}/prices' | ||
return _url.format(ticker=self._symbol) | ||
|
||
@property | ||
def params(self): | ||
"""Parameters to use in API calls""" | ||
return {'startDate': self.start.strftime('%Y-%m-%d'), | ||
'endDate': self.end.strftime('%Y-%m-%d'), | ||
'format': 'json'} | ||
|
||
def _get_crumb(self, *args): | ||
pass | ||
|
||
def _read_one_data(self, url, params): | ||
""" read one data from specified URL """ | ||
headers = {'Content-Type': 'application/json', | ||
'Authorization': 'Token ' + self.api_key} | ||
out = self._get_response(url, params=params, headers=headers).json() | ||
return self._read_lines(out) | ||
|
||
def _read_lines(self, out): | ||
df = pd.DataFrame(out) | ||
df['symbol'] = self._symbol | ||
df['date'] = pd.to_datetime(df['date']) | ||
df = df.set_index(['symbol', 'date']) | ||
return df | ||
|
||
def read(self): | ||
"""Read data from connector""" | ||
dfs = [] | ||
for symbol in self.symbols: | ||
self._symbol = symbol | ||
try: | ||
dfs.append(self._read_one_data(self.url, self.params)) | ||
finally: | ||
self.close() | ||
return pd.concat(dfs, self._concat_axis) | ||
|
||
|
||
class TiingoMetaDataReader(TiingoDailyReader): | ||
""" | ||
Read metadata about symbols from Tiingo | ||
Parameters | ||
---------- | ||
symbols : {str, List[str]} | ||
String symbol of like of symbols | ||
start : str, (defaults to '1/1/2010') | ||
Not used. | ||
end : str, (defaults to today) | ||
Not used. | ||
retry_count : int, default 3 | ||
Number of times to retry query request. | ||
pause : float, default 0.1 | ||
Time, in seconds, of the pause between retries. | ||
session : Session, default None | ||
requests.sessions.Session instance to be used | ||
freq : {str, None} | ||
Not used. | ||
api_key : str, optional | ||
Tiingo API key . If not provided the environmental variable | ||
TIINGO_API_KEY is read. The API key is *required*. | ||
""" | ||
|
||
def __init__(self, symbols, start=None, end=None, retry_count=3, pause=0.1, | ||
timeout=30, session=None, freq=None, api_key=None): | ||
super(TiingoMetaDataReader, self).__init__(symbols, start, end, | ||
retry_count, pause, timeout, | ||
session, freq, api_key) | ||
self._concat_axis = 1 | ||
|
||
@property | ||
def url(self): | ||
"""API URL""" | ||
_url = 'https://api.tiingo.com/tiingo/daily/{ticker}' | ||
return _url.format(ticker=self._symbol) | ||
|
||
@property | ||
def params(self): | ||
return None | ||
|
||
def _read_lines(self, out): | ||
s = pd.Series(out) | ||
s.name = self._symbol | ||
return s | ||
|
||
|
||
class TiingoQuoteReader(TiingoDailyReader): | ||
""" | ||
Read quotes (latest prices) from Tiingo | ||
Parameters | ||
---------- | ||
symbols : {str, List[str]} | ||
String symbol of like of symbols | ||
start : str, (defaults to '1/1/2010') | ||
Not used. | ||
end : str, (defaults to today) | ||
Not used. | ||
retry_count : int, default 3 | ||
Number of times to retry query request. | ||
pause : float, default 0.1 | ||
Time, in seconds, of the pause between retries. | ||
session : Session, default None | ||
requests.sessions.Session instance to be used | ||
freq : {str, None} | ||
Not used. | ||
api_key : str, optional | ||
Tiingo API key . If not provided the environmental variable | ||
TIINGO_API_KEY is read. The API key is *required*. | ||
Notes | ||
----- | ||
This is a special case of the daily reader which automatically selected | ||
the latest data available for each symbol. | ||
""" | ||
|
||
@property | ||
def params(self): | ||
return None |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,3 +10,4 @@ matplotlib | |
ipython | ||
sphinx | ||
sphinx_rtd_theme | ||
requests-cache |