Skip to content

Commit

Permalink
Prep for 2.1.3 (#178)
Browse files Browse the repository at this point in the history
* Fixing pypi badge

* Fixing typo on README

* Use ==/!= to compare str, bytes, and int literals

Identity is not the same thing as equality in Python so use ==/!= to compare str, bytes, and int literals. In Python >= 3.8, these instances will raise SyntaxWarnings so it is best to fix them now. https://docs.python.org/3.8/whatsnew/3.8.html#porting-to-python-3-8

$ python
```
>>> pandas = "panda"
>>> pandas += "s"
>>> pandas == "pandas"
True
>>> pandas is "pandas"
False
```

* added rapidapi key integration

Co-authored-by: Igor Tavares <igorborgest@gmail.com>
Co-authored-by: Christian Clauss <cclauss@me.com>
Co-authored-by: Patrick Collins <patrick.collins@alphavantage.co>
  • Loading branch information
4 people committed Jan 16, 2020
1 parent c6fab0f commit 0a7a65d
Show file tree
Hide file tree
Showing 6 changed files with 70 additions and 20 deletions.
14 changes: 11 additions & 3 deletions README.md
@@ -1,7 +1,7 @@
# alpha_vantage

[![Build Status](https://travis-ci.org/RomelTorres/alpha_vantage.png?branch=master)](https://travis-ci.org/RomelTorres/alpha_vantage)
[![PyPI version](https://badge.fury.io/py/alpha_vantage.svg)](https://badge.fury.io/py/alpha_vantage)
[![PyPI version](https://badge.fury.io/py/alpha-vantage.svg)](https://badge.fury.io/py/alpha-vantage)
[![Documentation Status](https://readthedocs.org/projects/alpha-vantage/badge/?version=latest)](http://alpha-vantage.readthedocs.io/en/latest/?badge=latest)
[![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/RomelTorres/alpha_vantage.svg)](http://isitmaintained.com/project/RomelTorres/alpha_vantage "Average time to resolve an issue")
[![Percentage of issues still open](http://isitmaintained.com/badge/open/RomelTorres/alpha_vantage.svg)](http://isitmaintained.com/project/RomelTorres/alpha_vantage "Percentage of issues still open")
Expand All @@ -13,6 +13,8 @@ Vantage (http://www.alphavantage.co/). It requires a free API key, that can be r

## News

* From version 2.1.3 onwards, [rapidAPI](https://rapidapi.com/alphavantage/api/alpha-vantage-alpha-vantage-default) key integration is now available.
* From version 2.1.0 onwards, error logging of bad API calls has been made more apparent.
* From version 1.9.0 onwards, the urllib was substituted by pythons request library that is thread safe. If you have any error, post an issue.
* From version 1.8.0 onwards, the column names of the data frames have changed, they are now exactly what alphavantage gives back in their json response. You can see the examples in better detail in the following git repo: https://github.com/RomelTorres/av_example
* From version 1.6.0, pandas was taken out as a hard dependency.
Expand All @@ -24,7 +26,7 @@ pip install alpha_vantage
```
Or install with pandas support, simply install pandas too:
```shell
pip install alpha_vantage, pandas
pip install alpha_vantage pandas
```

If you want to install from source, then use:
Expand All @@ -41,6 +43,12 @@ ts = TimeSeries(key='YOUR_API_KEY')
# Get json object with the intraday data and another with the call's metadata
data, meta_data = ts.get_intraday('GOOGL')
```
You may also get a key from [rapidAPI](https://rapidapi.com/alphavantage/api/alpha-vantage-alpha-vantage-default). Use your rapidAPI key for the key variable, and set ```rapidapi=True```

```python
ts = TimeSeries(key='YOUR_API_KEY',rapidapi=True)
```

Internally there is a retries counter, that can be used to minimize connection errors (in case that the API is not able to respond in time), the default is set to
5 but can be increased or decreased whenever needed.
```python
Expand Down Expand Up @@ -193,7 +201,7 @@ nosetests
The code documentation can be found at https://alpha-vantage.readthedocs.io/en/latest/

## Contributing
Contributing is always welcome, since sometimes I am busy. Just contact me on how best you can contribute.
Contributing is always welcome. Just contact us on how best you can contribute, add an issue, or make a PR.

## TODOs:
* The integration tests are not being run at the moment within travis, gotta fix them to run.
Expand Down
29 changes: 21 additions & 8 deletions alpha_vantage/alphavantage.py
Expand Up @@ -22,8 +22,10 @@ class AlphaVantage(object):
_ALPHA_VANTAGE_DIGITAL_CURRENCY_LIST = \
"https://www.alphavantage.co/digital_currency_list/"

_RAPIDAPI_URL = "https://alpha-vantage.p.rapidapi.com/query?"

def __init__(self, key=None, output_format='json',
treat_info_as_error=True, indexing_type='date', proxy=None):
treat_info_as_error=True, indexing_type='date', proxy=None, rapidapi=False):
""" Initialize the class
Keyword Arguments:
Expand All @@ -38,6 +40,8 @@ def __init__(self, key=None, output_format='json',
output_format is 'pandas'
proxy: Dictionary mapping protocol or protocol and hostname to
the URL of the proxy.
rapidapi: Boolean describing whether or not the API key is
through the RapidAPI platform or not
"""
if key is None:
key = os.getenv('ALPHAVANTAGE_API_KEY')
Expand All @@ -48,9 +52,16 @@ def __init__(self, key=None, output_format='json',
'ALPHAVANTAGE_API_KEY. Get a free key '
'from the alphavantage website: '
'https://www.alphavantage.co/support/#api-key')
self.headers = {}
if rapidapi:
self.headers = {
'x-rapidapi-host': "alpha-vantage.p.rapidapi.com",
'x-rapidapi-key': key
}
self.rapidapi = rapidapi
self.key = key
self.output_format = output_format
if self.output_format is 'pandas' and not _PANDAS_FOUND:
if self.output_format == 'pandas' and not _PANDAS_FOUND:
raise ValueError("The pandas library was not found, therefore can "
"not be used as an output format, please install "
"manually")
Expand Down Expand Up @@ -109,8 +120,8 @@ def _call_wrapper(self, *args, **kwargs):
# key for it and for its meta data.
function_name, data_key, meta_data_key = func(
self, *args, **kwargs)
url = "{}function={}".format(AlphaVantage._ALPHA_VANTAGE_API_URL,
function_name)
base_url = AlphaVantage._RAPIDAPI_URL if self.rapidapi else AlphaVantage._ALPHA_VANTAGE_API_URL
url = "{}function={}".format(base_url, function_name)
for idx, arg_name in enumerate(argspec.args[1:]):
try:
arg_value = args[idx]
Expand Down Expand Up @@ -139,10 +150,12 @@ def _call_wrapper(self, *args, **kwargs):
raise ValueError("Output format: {} not recognized, only json,"
"pandas and csv are supported".format(
self.output_format.lower()))
apikey_parameter = "" if self.rapidapi else "&apikey={}".format(
self.key)
if self._append_type:
url = '{}&apikey={}&datatype={}'.format(url, self.key, oformat)
url = '{}{}&datatype={}'.format(url, apikey_parameter, oformat)
else:
url = '{}&apikey={}'.format(url, self.key)
url = '{}{}'.format(url, apikey_parameter)
return self._handle_api_call(url), data_key, meta_data_key
return _call_wrapper

Expand All @@ -162,7 +175,7 @@ def _format_wrapper(self, *args, **kwargs):
if 'json' in self.output_format.lower() or 'pandas' \
in self.output_format.lower():
data = call_response[data_key]

if meta_data_key is not None:
meta_data = call_response[meta_data_key]
else:
Expand Down Expand Up @@ -268,7 +281,7 @@ def _handle_api_call(self, url):
meta_data_key: The key for getting the meta data information out
of the json object
"""
response = requests.get(url, proxies=self.proxy)
response = requests.get(url, proxies=self.proxy, headers=self.headers)
if 'json' in self.output_format.lower() or 'pandas' in \
self.output_format.lower():
json_response = response.json()
Expand Down
4 changes: 2 additions & 2 deletions docs/conf.py
Expand Up @@ -55,9 +55,9 @@
# built documents.
#
# The short X.Y version.
version = u'2.1.2'
version = u'2.1.3'
# The full version, including alpha/beta/rc tags.
release = u'2.1.2'
release = u'2.1.3'

# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Expand Up @@ -11,7 +11,7 @@

setup(
name='alpha_vantage',
version='2.1.2',
version='2.1.3',
author='Romel J. Torres',
author_email='romel.torres@gmail.com',
license='MIT',
Expand Down
15 changes: 13 additions & 2 deletions test_alpha_vantage/test_alphavantage.py
Expand Up @@ -53,6 +53,19 @@ def test_handle_api_call(self, mock_request):
self.assertIsInstance(
data, dict, 'Result Data must be a dictionary')

@requests_mock.Mocker()
def test_rapidapi_key(self, mock_request):
""" Test that the rapidAPI key calls the rapidAPI endpoint
"""
ts = TimeSeries(key=TestAlphaVantage._API_KEY_TEST, rapidapi=True)
url = "https://alpha-vantage.p.rapidapi.com/query?function=TIME_SERIES_INTRADAY&symbol=MSFT&interval=1min&outputsize=full&datatype=json"
path_file = self.get_file_from_url("mock_time_series")
with open(path_file) as f:
mock_request.get(url, text=f.read())
data, _ = ts.get_intraday(
"MSFT", interval='1min', outputsize='full')
self.assertIsInstance(
data, dict, 'Result Data must be a dictionary')

@requests_mock.Mocker()
def test_time_series_intraday(self, mock_request):
Expand Down Expand Up @@ -83,7 +96,6 @@ def test_time_series_intraday_pandas(self, mock_request):
self.assertIsInstance(
data, df, 'Result Data must be a pandas data frame')


@requests_mock.Mocker()
def test_time_series_intraday_date_indexing(self, mock_request):
""" Test that api call returns a pandas data frame with a date as index
Expand Down Expand Up @@ -214,4 +226,3 @@ def test_batch_quotes_pandas(self, mock_request):
data, _ = ts.get_batch_stock_quotes(symbols=('MSFT', 'FB', 'AAPL'))
self.assertIsInstance(
data, df, 'Result Data must be a pandas dataframe')

26 changes: 22 additions & 4 deletions test_alpha_vantage/test_integration_alphavantage.py
Expand Up @@ -19,6 +19,7 @@ class TestAlphaVantage(unittest.TestCase):
"""
_API_KEY_TEST = os.environ['API_KEY']
_API_EQ_NAME_TEST = 'MSFT'
_RAPIDAPI_KEY_TEST = os.getenv("RAPIDAPI_KEY")

def setUp(self):
"""
Expand Down Expand Up @@ -62,6 +63,19 @@ def test_key_none(self):
except ValueError:
self.assertTrue(True)

def test_rapidapi_key_with_get_daily(self):
"""RapidAPI calls must return the same data as non-rapidapi calls
"""
# Test rapidAPI calls are the same as regular ones
ts_rapidapi = TimeSeries(
key=TestAlphaVantage._RAPIDAPI_KEY_TEST, rapidapi=True)
ts = TimeSeries(key=TestAlphaVantage._API_KEY_TEST)
rapidapi_data, rapidapi_metadata = ts_rapidapi.get_daily(
symbol=TestAlphaVantage._API_EQ_NAME_TEST)
data, metadata = ts.get_daily(
symbol=TestAlphaVantage._API_EQ_NAME_TEST)
self.assertTrue(rapidapi_data == data)

def test_get_daily_is_format(self):
"""Result must be a dictionary containing the json data
"""
Expand Down Expand Up @@ -136,7 +150,8 @@ def test_get_currency_exchange_intraday_json(self):
def test_get_currency_exchange_intraday_pandas(self):
"""Test that we get a dictionary containing pandas data
"""
fe = ForeignExchange(key=TestAlphaVantage._API_KEY_TEST, output_format='pandas')
fe = ForeignExchange(
key=TestAlphaVantage._API_KEY_TEST, output_format='pandas')
self._assert_result_is_format(fe.get_currency_exchange_intraday,
output_format='pandas',
from_symbol='USD',
Expand All @@ -155,7 +170,8 @@ def test_get_currency_exchange_daily_json(self):
def test_get_currency_exchange_daily_pandas(self):
"""Test that we get a dictionary containing pandas data
"""
fe = ForeignExchange(key=TestAlphaVantage._API_KEY_TEST, output_format='pandas')
fe = ForeignExchange(
key=TestAlphaVantage._API_KEY_TEST, output_format='pandas')
self._assert_result_is_format(fe.get_currency_exchange_daily,
output_format='pandas',
from_symbol='USD',
Expand All @@ -174,7 +190,8 @@ def test_get_currency_exchange_weekly_json(self):
def test_get_currency_exchange_weekly_pandas(self):
"""Test that we get a dictionary containing pandas data
"""
fe = ForeignExchange(key=TestAlphaVantage._API_KEY_TEST, output_format='pandas')
fe = ForeignExchange(
key=TestAlphaVantage._API_KEY_TEST, output_format='pandas')
self._assert_result_is_format(fe.get_currency_exchange_weekly,
output_format='pandas',
from_symbol='USD',
Expand All @@ -192,7 +209,8 @@ def test_get_currency_exchange_monthly_json(self):
def test_get_currency_exchange_monthly_pandas(self):
"""Test that we get a dictionary containing pandas data
"""
fe = ForeignExchange(key=TestAlphaVantage._API_KEY_TEST, output_format='pandas')
fe = ForeignExchange(
key=TestAlphaVantage._API_KEY_TEST, output_format='pandas')
self._assert_result_is_format(fe.get_currency_exchange_monthly,
output_format='pandas',
from_symbol='USD',
Expand Down

0 comments on commit 0a7a65d

Please sign in to comment.