-
Notifications
You must be signed in to change notification settings - Fork 683
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
added tiingo csv response serialisation options #822
base: main
Are you sure you want to change the base?
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,6 +4,8 @@ | |
|
||
from pandas_datareader.base import _BaseReader | ||
|
||
TIINGO_API_URL_BASE = "https://api.tiingo.com" | ||
|
||
|
||
def get_tiingo_symbols(): | ||
""" | ||
|
@@ -34,11 +36,11 @@ class TiingoIEXHistoricalReader(_BaseReader): | |
---------- | ||
symbols : {str, List[str]} | ||
String symbol or list of symbols | ||
start : string, int, date, datetime, Timestamp | ||
start : {string, int, date, datetime, Timestamp} | ||
Starting date. Parses many different kind of date | ||
representations (e.g., 'JAN-01-2010', '1/1/10', 'Jan, 1, 1980'). Defaults to | ||
20 years before current date. | ||
end : string, int, date, datetime, Timestamp | ||
representations (e.g., 'JAN-01-2010', '1/1/10', 'Jan, 1, 1980'). | ||
Defaults to 20 years before current date. | ||
end : {string, int, date, datetime, Timestamp} | ||
Ending date | ||
retry_count : int, default 3 | ||
Number of times to retry query request. | ||
|
@@ -47,9 +49,13 @@ class TiingoIEXHistoricalReader(_BaseReader): | |
session : Session, default None | ||
requests.sessions.Session instance to be used | ||
freq : {str, None} | ||
Re-sample frequency. Format is # + (min/hour); e.g. "15min" or "4hour". | ||
If no value is provided, defaults to 5min. The minimum value is "1min". | ||
Units in minutes (min) and hours (hour) are accepted. | ||
Re-sample frequency. Format is #min/hour; e.g. "15min" or "4hour". | ||
If no value is provided, defaults to 5min. The minimum value is\ | ||
"1min". | ||
Units in minutes (min) and hours (hour) are accepted. | ||
response_format : str, default 'json' | ||
Format of response data returned by the underlying Tiingo REST API. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this accurate? Perhaps something like: "The format to use in the request tot he TIINGO API. "csv" results in smaller payload, less bandwidth, and may result in smaller charges for accessing the TIINGO API" There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sounds good - added wording along those lines. This would affect bandwidth limits and implicitly charges. |
||
Acceptable values: 'json', 'csv'. | ||
api_key : str, optional | ||
Tiingo API key . If not provided the environmental variable | ||
TIINGO_API_KEY is read. The API key is *required*. | ||
|
@@ -65,6 +71,7 @@ def __init__( | |
timeout=30, | ||
session=None, | ||
freq=None, | ||
response_format="json", | ||
api_key=None, | ||
): | ||
super().__init__( | ||
|
@@ -83,12 +90,15 @@ def __init__( | |
"environmental variable TIINGO_API_KEY." | ||
) | ||
self.api_key = api_key | ||
self.response_format = ( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You should raise ValueError if not one of the expected values. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good point - done! |
||
response_format if response_format in ["json", "csv"] else "json" | ||
) | ||
self._concat_axis = 0 | ||
|
||
@property | ||
def url(self): | ||
"""API URL""" | ||
_url = "https://api.tiingo.com/iex/{ticker}/prices" | ||
_url = TIINGO_API_URL_BASE + "/iex/{ticker}/prices" | ||
return _url.format(ticker=self._symbol) | ||
|
||
@property | ||
|
@@ -98,23 +108,30 @@ def params(self): | |
"startDate": self.start.strftime("%Y-%m-%d"), | ||
"endDate": self.end.strftime("%Y-%m-%d"), | ||
"resampleFreq": self.freq, | ||
"format": "json", | ||
"format": self.response_format, | ||
} | ||
|
||
def _get_crumb(self, *args): | ||
pass | ||
|
||
def _read_one_data(self, url, params): | ||
""" read one data from specified URL """ | ||
content_type = ( | ||
"application/json" if self.response_format == "json" else "text/csv" | ||
) | ||
headers = { | ||
"Content-Type": "application/json", | ||
"Content-Type": content_type, | ||
"Authorization": "Token " + self.api_key, | ||
} | ||
out = self._get_response(url, params=params, headers=headers).json() | ||
out = None | ||
if self.response_format == "json": | ||
out = self._get_response(url, params=params, headers=headers).json() | ||
elif self.response_format == "csv": | ||
out = self._read_url_as_StringIO(url, params=params, headers=headers) | ||
return self._read_lines(out) | ||
|
||
def _read_lines(self, out): | ||
df = pd.DataFrame(out) | ||
df = pd.DataFrame(out) if self.response_format == "json" else pd.read_csv(out) | ||
df["symbol"] = self._symbol | ||
df["date"] = pd.to_datetime(df["date"]) | ||
df = df.set_index(["symbol", "date"]) | ||
|
@@ -140,11 +157,11 @@ class TiingoDailyReader(_BaseReader): | |
---------- | ||
symbols : {str, List[str]} | ||
String symbol or list of symbols | ||
start : string, int, date, datetime, Timestamp | ||
start : {string, int, date, datetime, Timestamp} | ||
Starting date, timestamp. Parses many different kind of date | ||
representations (e.g., 'JAN-01-2010', '1/1/10', 'Jan, 1, 1980'). | ||
Default starting date is 5 years before current date. | ||
end : string, int, date, datetime, Timestamp | ||
end : {string, int, date, datetime, Timestamp} | ||
Ending date, timestamp. Same format as starting date. | ||
retry_count : int, default 3 | ||
Number of times to retry query request. | ||
|
@@ -154,6 +171,9 @@ class TiingoDailyReader(_BaseReader): | |
requests.sessions.Session instance to be used | ||
freq : {str, None} | ||
Not used. | ||
response_format : str, default 'json' | ||
Format of response data returned by the underlying Tiingo REST API. | ||
Acceptable values: 'json', 'csv'. | ||
api_key : str, optional | ||
Tiingo API key . If not provided the environmental variable | ||
TIINGO_API_KEY is read. The API key is *required*. | ||
|
@@ -169,6 +189,7 @@ def __init__( | |
timeout=30, | ||
session=None, | ||
freq=None, | ||
response_format="json", | ||
api_key=None, | ||
): | ||
super(TiingoDailyReader, self).__init__( | ||
|
@@ -186,12 +207,15 @@ def __init__( | |
"environmental variable TIINGO_API_KEY." | ||
) | ||
self.api_key = api_key | ||
self.response_format = ( | ||
response_format if response_format in ["json", "csv"] else "json" | ||
) | ||
self._concat_axis = 0 | ||
|
||
@property | ||
def url(self): | ||
"""API URL""" | ||
_url = "https://api.tiingo.com/tiingo/daily/{ticker}/prices" | ||
_url = TIINGO_API_URL_BASE + "/tiingo/daily/{ticker}/prices" | ||
return _url.format(ticker=self._symbol) | ||
|
||
@property | ||
|
@@ -200,23 +224,30 @@ def params(self): | |
return { | ||
"startDate": self.start.strftime("%Y-%m-%d"), | ||
"endDate": self.end.strftime("%Y-%m-%d"), | ||
"format": "json", | ||
"format": self.response_format, | ||
} | ||
|
||
def _get_crumb(self, *args): | ||
pass | ||
|
||
def _read_one_data(self, url, params): | ||
""" read one data from specified URL """ | ||
content_type = ( | ||
"application/json" if self.response_format == "json" else "text/csv" | ||
) | ||
headers = { | ||
"Content-Type": "application/json", | ||
"Content-Type": content_type, | ||
"Authorization": "Token " + self.api_key, | ||
} | ||
out = self._get_response(url, params=params, headers=headers).json() | ||
out = None | ||
if self.response_format == "json": | ||
out = self._get_response(url, params=params, headers=headers).json() | ||
elif self.response_format == "csv": | ||
out = self._read_url_as_StringIO(url, params=params, headers=headers) | ||
return self._read_lines(out) | ||
|
||
def _read_lines(self, out): | ||
df = pd.DataFrame(out) | ||
df = pd.DataFrame(out) if self.response_format == "json" else pd.read_csv(out) | ||
df["symbol"] = self._symbol | ||
df["date"] = pd.to_datetime(df["date"]) | ||
df = df.set_index(["symbol", "date"]) | ||
|
@@ -242,9 +273,9 @@ class TiingoMetaDataReader(TiingoDailyReader): | |
---------- | ||
symbols : {str, List[str]} | ||
String symbol or list of symbols | ||
start : string, int, date, datetime, Timestamp | ||
start : {string, int, date, datetime, Timestamp} | ||
Not used. | ||
end : string, int, date, datetime, Timestamp | ||
end : {string, int, date, datetime, Timestamp} | ||
Not used. | ||
retry_count : int, default 3 | ||
Number of times to retry query request. | ||
|
@@ -279,7 +310,7 @@ def __init__( | |
@property | ||
def url(self): | ||
"""API URL""" | ||
_url = "https://api.tiingo.com/tiingo/daily/{ticker}" | ||
_url = TIINGO_API_URL_BASE + "/tiingo/daily/{ticker}" | ||
return _url.format(ticker=self._symbol) | ||
|
||
@property | ||
|
@@ -300,9 +331,9 @@ class TiingoQuoteReader(TiingoDailyReader): | |
---------- | ||
symbols : {str, List[str]} | ||
String symbol or list of symbols | ||
start : string, int, date, datetime, Timestamp | ||
start : {string, int, date, datetime, Timestamp} | ||
Not used. | ||
end : string, int, date, datetime, Timestamp | ||
end : {string, int, date, datetime, Timestamp} | ||
Not used. | ||
retry_count : int, default 3 | ||
Number of times to retry query request. | ||
|
@@ -312,6 +343,9 @@ class TiingoQuoteReader(TiingoDailyReader): | |
requests.sessions.Session instance to be used | ||
freq : {str, None} | ||
Not used. | ||
response_format : str, default 'json' | ||
Format of response data returned by the underlying Tiingo REST API. | ||
Acceptable values: 'json', 'csv'. | ||
api_key : str, optional | ||
Tiingo API key . If not provided the environmental variable | ||
TIINGO_API_KEY is read. The API key is *required*. | ||
|
@@ -322,6 +356,33 @@ class TiingoQuoteReader(TiingoDailyReader): | |
the latest data available for each symbol. | ||
""" | ||
|
||
def __init__( | ||
self, | ||
symbols, | ||
start=None, | ||
end=None, | ||
retry_count=3, | ||
pause=0.1, | ||
timeout=30, | ||
session=None, | ||
freq=None, | ||
response_format="json", | ||
api_key=None, | ||
): | ||
super(TiingoQuoteReader, self).__init__( | ||
symbols, | ||
start, | ||
end, | ||
retry_count, | ||
pause, | ||
timeout, | ||
session, | ||
freq, | ||
response_format, | ||
api_key, | ||
) | ||
|
||
@property | ||
def params(self): | ||
return None | ||
"""Parameters to use in API calls""" | ||
return {"format": self.response_format} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you remove to \ and fix spacing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.