Skip to content

Commit 1763dbd

Browse files
addisonlynchbashtage
authored andcommitted
ENH: Add support for AlphaVantage API (#490)
* Added AlphaVantage readeres * DOCS: Cleanup AlphaVantage docs * Added AlphaVantage Quotes Reader * Updated AV tests * Updated AV docstrings, repaired names * DOCS: Added Alphavantage to readers index
1 parent 8a9ca74 commit 1763dbd

File tree

15 files changed

+855
-0
lines changed

15 files changed

+855
-0
lines changed

docs/source/readers/alphavantage.rst

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
AlphaVantage
2+
------------
3+
4+
.. py:module:: pandas_datareader.av.forex
5+
6+
.. autoclass:: AVForexReader
7+
:members:
8+
:inherited-members:
9+
10+
11+
.. py:module:: pandas_datareader.av.time_series
12+
13+
.. autoclass:: AVTimeSeriesReader
14+
:members:
15+
:inherited-members:
16+
17+
18+
.. py:module:: pandas_datareader.av.sector
19+
20+
.. autoclass:: AVSectorPerformanceReader
21+
:members:
22+
:inherited-members:
23+
24+
25+
.. py:module:: pandas_datareader.av.quotes
26+
27+
.. autoclass:: AVQuotesReader
28+
:members:
29+
:inherited-members:

docs/source/readers/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ Data Readers
44
.. toctree::
55
:maxdepth: 2
66

7+
alphavantage
78
fred
89
famafrench
910
bank-of-canada

docs/source/remote_data.rst

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ Currently the following sources are supported:
3333
- :ref:`Morningstar<remote_data.morningstar>`
3434
- :ref:`IEX<remote_data.iex>`
3535
- :ref:`Robinhood<remote_data.robinhood>`
36+
- :ref:`AlphaVantage<remote_data.alphavantage>`
3637
- :ref:`Enigma<remote_data.enigma>`
3738
- :ref:`Quandl<remote_data.quandl>`
3839
- :ref:`St.Louis FED (FRED)<remote_data.fred>`
@@ -146,6 +147,107 @@ year relative to today.
146147
f = web.DataReader('F', 'robinhood')
147148
f.head()
148149
150+
151+
.. _remote_data.alphavantage
152+
153+
AlphaVantage
154+
============
155+
156+
`AlphaVantage <https://www.alphavantage.co/documentation>`__ provides realtime
157+
equities and forex data. Free registration is required to get an API key.
158+
159+
Historical Time Series Data
160+
^^^^^^^^^^^^^^^^^^^^^^^^^^^
161+
162+
Through the
163+
`AlphaVantage <https://www.alphavantage.co/documentation>`__ Time Series
164+
endpoints, it is possible to obtain historical equities data for individual
165+
symbols. The following endpoints are available:
166+
167+
* ``av-daily`` - Daily Time Series
168+
* ``av-daily-adjusted`` - Daily Time Series (Adjusted)
169+
* ``av-weekly`` - Weekly Time Series
170+
* ``av-weekly-adjusted`` - Weekly Time Series (Adjusted)
171+
* ``av-monthly`` - Monthly Time Series
172+
* ``av-monthly-adjusted`` - Monthly Time Series (Adjusted)
173+
174+
.. ipython:: python
175+
176+
import os
177+
from datetime import datetime
178+
import pandas_datareader.data as web
179+
180+
f = web.DataReader("AAPL", "av-daily", start=datetime(2017, 2, 9),
181+
end=datetime(2017, 5, 24),
182+
access_key=os.getenv('ALPHAVANTAGE_API_KEY'))
183+
f.loc["2017-02-09"]
184+
185+
The top-level function ``get_data_alphavantage`` is also provided. This
186+
function will
187+
return the ``TIME_SERIES_DAILY`` endpoint for the symbol and date range
188+
provided.
189+
190+
Quotes
191+
^^^^^^
192+
193+
`AlphaVantage <https://www.alphavantage.co/documentation>`__ Batch Stock Quotes
194+
endpoint allows the retrieval of realtime stock quotes for up to 100 symbols at
195+
once. These quotes are accessible through the top-level function
196+
``get_quote_av``.
197+
198+
.. ipython:: python
199+
200+
import os
201+
from datetime import datetime
202+
import pandas_datareader.data as web
203+
204+
web.get_quote_av(["AAPL", "TSLA"])
205+
206+
207+
.. note:: Most quotes are only available during market hours.
208+
209+
Forex
210+
^^^^^
211+
212+
`AlphaVantage <https://www.alphavantage.co/documentation>`__ provides realtime
213+
currency exchange rates (for physical and digital currencies).
214+
215+
To request the exchange rate of physical or digital currencies, simply format
216+
as "FROM/TO" as in "USD/JPY".
217+
218+
.. ipython:: python
219+
220+
import os
221+
import pandas_datareader.data as web
222+
223+
f = web.DataReader("USD/JPY", "av-forex",
224+
access_key=os.getenv('ALPHAVANTAGE_API_KEY'))
225+
226+
Multiple pairs are are allowable:
227+
228+
.. ipython:: python
229+
230+
import os
231+
import pandas_datareader.data as web
232+
233+
f = web.DataReader(["USD/JPY", "BTC/CNY"], "av-forex",
234+
access_key=os.getenv('ALPHAVANTAGE_API_KEY'))
235+
236+
237+
Sector Performance
238+
^^^^^^^^^^^^^^^^^^
239+
240+
`AlphaVantage <https://www.alphavantage.co/documentation>`__ provides sector
241+
performances through the top-level function ``get_sector_performance_av``.
242+
243+
.. ipython:: python
244+
245+
import os
246+
import pandas_datareader.data as web
247+
248+
web.get_sector_performance_av().head()
249+
250+
149251
.. _remote_data.enigma:
150252

151253
Enigma

docs/source/whatsnew/v0.7.0.txt

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,28 @@ Highlights include:
1616
Enhancements
1717
~~~~~~~~~~~~
1818

19+
- A new data connector for data provided by
20+
`AlphaVantage <https://www.alphavantage.co/documentation>`__ was
21+
introduced to obtain Foreign Exchange (FX) data.
22+
(:issue:`389`)
23+
24+
- A new data connector for data provided by
25+
`AlphaVantage <https://www.alphavantage.co/documentation>`__ was
26+
introduced to obtain historical time series data.
27+
(:issue:`389`)
28+
29+
- A new data connector for data provided by
30+
`AlphaVantage <https://www.alphavantage.co/documentation>`__ was
31+
introduced to obtain sector performance data, accessed through the
32+
top-level function ``get_sector_performance_av``.
33+
(:issue:`389`)
34+
35+
- A new data connector for data provided by
36+
`AlphaVantage <https://www.alphavantage.co/documentation>`__ was
37+
introduced to obtain real-time Batch Stock Quotes through the
38+
top-level function ``get_quote_av``.
39+
(:issue:`389`)
40+
1941
.. _whatsnew_070.api_breaking:
2042

2143
Backwards incompatible API changes

pandas_datareader/av/__init__.py

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import os
2+
3+
from pandas_datareader.base import _BaseReader
4+
from pandas_datareader._utils import RemoteDataError
5+
6+
import pandas as pd
7+
8+
AV_BASE_URL = 'https://www.alphavantage.co/query'
9+
10+
11+
class AlphaVantage(_BaseReader):
12+
"""
13+
Base class for all AlphaVantage queries
14+
"""
15+
_format = 'json'
16+
17+
def __init__(self, symbols=None, start=None, end=None, retry_count=3,
18+
pause=0.001, session=None, api_key=None):
19+
super(AlphaVantage, self).__init__(symbols=symbols, start=start,
20+
end=end, retry_count=retry_count,
21+
pause=pause, session=session)
22+
if api_key is None:
23+
api_key = os.getenv('ALPHAVANTAGE_API_KEY')
24+
if not api_key or not isinstance(api_key, str):
25+
raise ValueError('The AlphaVantage API key must be provided '
26+
'either through the api_key variable or '
27+
'through the environment varaible '
28+
'ALPHAVANTAGE_API_KEY')
29+
self.api_key = api_key
30+
31+
@property
32+
def url(self):
33+
""" API URL """
34+
return AV_BASE_URL
35+
36+
@property
37+
def params(self):
38+
return {
39+
'function': self.function,
40+
'apikey': self.api_key
41+
}
42+
43+
@property
44+
def function(self):
45+
""" AlphaVantage endpoint function"""
46+
raise NotImplementedError
47+
48+
@property
49+
def data_key(self):
50+
""" Key of data returned from AlphaVantage """
51+
raise NotImplementedError
52+
53+
def _read_lines(self, out):
54+
try:
55+
df = pd.DataFrame.from_dict(out[self.data_key], orient='index')
56+
except KeyError:
57+
if "Error Message" in out:
58+
raise ValueError("The requested symbol {} could not be "
59+
"retrived. Check valid ticker"
60+
".".format(self.symbols))
61+
else:
62+
raise RemoteDataError()
63+
df = df[sorted(df.columns)]
64+
# df.sort_index(ascending=True, inplace=True)
65+
df.columns = [id[3:] for id in df.columns]
66+
return df

pandas_datareader/av/forex.py

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
from pandas_datareader.av import AlphaVantage
2+
3+
from pandas_datareader._utils import RemoteDataError
4+
5+
import pandas as pd
6+
7+
8+
class AVForexReader(AlphaVantage):
9+
"""
10+
Returns DataFrame of the AlphaVantage Foreign Exchange (FX) Exchange Rates
11+
data.
12+
13+
.. versionadded:: 0.7.0
14+
15+
Parameters
16+
----------
17+
symbols : string, array-like object (list, tuple, Series)
18+
Single currency pair (formatted 'FROM/TO') or list of the same.
19+
retry_count : int, default 3
20+
Number of times to retry query request.
21+
pause : int, default 0.5
22+
Time, in seconds, to pause between consecutive queries of chunks. If
23+
single value given for symbol, represents the pause between retries.
24+
session : Session, default None
25+
requests.sessions.Session instance to be used
26+
api_key : str, optional
27+
AlphaVantage API key . If not provided the environmental variable
28+
ALPHAVANTAGE_API_KEY is read. The API key is *required*.
29+
"""
30+
def __init__(self, symbols=None, retry_count=3, pause=0.5, session=None,
31+
api_key=None):
32+
33+
super(AVForexReader, self).__init__(symbols=symbols,
34+
start=None, end=None,
35+
retry_count=retry_count,
36+
pause=pause,
37+
session=session,
38+
api_key=api_key)
39+
self.from_curr = {}
40+
self.to_curr = {}
41+
self.optional_params = {}
42+
if isinstance(symbols, str):
43+
self.symbols = [symbols]
44+
else:
45+
self.symbols = symbols
46+
try:
47+
for pair in self.symbols:
48+
self.from_curr[pair] = pair.split('/')[0]
49+
self.to_curr[pair] = pair.split('/')[1]
50+
except Exception as e:
51+
print(e)
52+
raise ValueError("Please input a currency pair "
53+
"formatted 'FROM/TO' or a list of "
54+
"currency symbols")
55+
56+
@property
57+
def function(self):
58+
return 'CURRENCY_EXCHANGE_RATE'
59+
60+
@property
61+
def data_key(self):
62+
return 'Realtime Currency Exchange Rate'
63+
64+
@property
65+
def params(self):
66+
params = {
67+
'apikey': self.api_key,
68+
'function': self.function
69+
}
70+
params.update(self.optional_params)
71+
return params
72+
73+
def read(self):
74+
result = []
75+
for pair in self.symbols:
76+
self.optional_params = {
77+
'from_currency': self.from_curr[pair],
78+
'to_currency': self.to_curr[pair],
79+
}
80+
data = super(AVForexReader, self).read()
81+
result.append(data)
82+
df = pd.concat(result, axis=1)
83+
df.columns = self.symbols
84+
return df
85+
86+
def _read_lines(self, out):
87+
try:
88+
df = pd.DataFrame.from_dict(out[self.data_key], orient='index')
89+
except KeyError:
90+
raise RemoteDataError()
91+
df.sort_index(ascending=True, inplace=True)
92+
df.index = [id[3:] for id in df.index]
93+
return df

0 commit comments

Comments
 (0)