Skip to content

Commit

Permalink
Merge pull request alpacahq#138 from PatrickAlphaVantage/master
Browse files Browse the repository at this point in the history
Added Alpha Vantage Integration
  • Loading branch information
ttt733 authored Jan 29, 2020
2 parents e68d9fd + f387be9 commit 517f939
Show file tree
Hide file tree
Showing 20 changed files with 2,609 additions and 18 deletions.
84 changes: 72 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,18 +53,18 @@ outlined below.

The Alpaca SDK will check the environment for a number of variables which can be used rather than hard-coding these into your scripts.

| Environment | default | Description |
| ----------- | ------- | ----------- |
| APCA_API_KEY_ID=<key_id> | | Your API Key |
| APCA_API_SECRET_KEY=<secret_key> | | Your API Secret Key |
| APCA_API_BASE_URL=url | https://api.alpaca.markets (for live)<br/>https://paper-api.alpaca.markets (for paper) | Specify the URL for API calls, *Default is live, you must specify this to switch to paper endpoint!* |
| APCA_API_DATA_URL=url | https://data.alpaca.markets | Endpoint for data API |
| APCA_RETRY_MAX=3 | 3 | The number of subsequent API calls to retry on timeouts |
| APCA_RETRY_WAIT=3 | 3 | seconds to wait between each retry attempt |
| APCA_RETRY_CODES=429,504 | 429,504 | comma-separated HTTP status code for which retry is attempted |
| POLYGON_WS_URL | wss://alpaca.socket.polygon.io/stocks | Endpoint for streaming polygon data. You likely don't need to change this unless you want to proxy it for example |
| POLYGON_KEY_ID | | Your Polygon key, if it's not the same as your Alpaca API key. Most users will not need to set this to access Polygon.|

| Environment | default | Description |
| -------------------------------- | -------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
| APCA_API_KEY_ID=<key_id> | | Your API Key |
| APCA_API_SECRET_KEY=<secret_key> | | Your API Secret Key |
| APCA_API_BASE_URL=url | https://api.alpaca.markets (for live)<br/>https://paper-api.alpaca.markets (for paper) | Specify the URL for API calls, *Default is live, you must specify this to switch to paper endpoint!* |
| APCA_API_DATA_URL=url | https://data.alpaca.markets | Endpoint for data API |
| APCA_RETRY_MAX=3 | 3 | The number of subsequent API calls to retry on timeouts |
| APCA_RETRY_WAIT=3 | 3 | seconds to wait between each retry attempt |
| APCA_RETRY_CODES=429,504 | 429,504 | comma-separated HTTP status code for which retry is attempted |
| POLYGON_WS_URL | wss://alpaca.socket.polygon.io/stocks | Endpoint for streaming polygon data. You likely don't need to change this unless you want to proxy it for example |
| POLYGON_KEY_ID | | Your Polygon key, if it's not the same as your Alpaca API key. Most users will not need to set this to access Polygon. |
| ALPHAVANTAGE_API_KEY=<key_id> | | Your Alpha Vantage API key. You can get [one for free here](https://www.alphavantage.co/support/#api-key). |

## REST

Expand Down Expand Up @@ -341,6 +341,66 @@ dict[symbol -> `Financials`] if `symbol` is a list of string.
Returns a `NewsList` entity for the symbol.


---
# Alpha Vantage API Service

In addition to Polygon is Alpha Vantage, for users without a live account (paper trading) or want to use the unique features of AV data. You can get a free key [here](https://www.alphavantage.co/support/#api-key) and the documentation is [here](https://www.alphavantage.co/documentation/). Premium keys are also available [here](https://www.alphavantage.co/premium/#intro)
This python SDK wraps their API service and seamlessly integrates it with the Alpaca
API. `alpaca_trade_api.REST.alpha_vantage` will be the `REST` object for Alpha Vantage.

The example below gives AAPL daily OHLCV data in a DataFrame format.

```py
import alpaca_trade_api as tradeapi

api = tradeapi.REST()
aapl = api.alpha_vantage.historic_quotes('AAPL', adjusted=True, output_format='pandas')
```

## alpha_vantage/REST
It is initialized through alpaca `REST` object.

### alpha_vantage/REST.get(params=None)
Customizable endpoint, where you can pass all keywords/paramters from the documentation:https://www.alphavantage.co/documentation/#

Returns the specific customized data.

### alpha_vantage/REST.historic_quotes(symbol, adjusted=False, outputsize='full', cadence='daily', output_format=None)
Returns a `csv`, `json`, or `pandas` object of historical OHLCV data.

### alpha_vantage/REST.intraday_quotes(symbol, interval='5min', outputsize='full', output_format=None)
Returns a `csv`, `json`, or `pandas` object of intraday OHLCV data.

### alpha_vantage/REST.current_quote(symbol)
Returns a `json` object with the current OHLCV data of the selected symbol.

### alpha_vantage/REST.last_quote(symbol)
Returns a `json` object with the current OHLCV data of the selected symbol (same as `current_quote`).

### alpha_vantage/REST.search_endpoint(keywords, datatype='json')
Returns a `csv`, `json`, or `pandas` object that contains the best-matching symbols and market information based on keywords of your choice.

### alpha_vantage/REST.company(symbol, datatype='json')
Same as `search_endpoint`.

### alpha_vantage/REST.historic_fx_quotes(from_symbol, to_symbol, outputsize='full', cadence='daily', output_format=None)
Returns a `csv`, `json`, or `pandas` object of historical OHLCV data for the currency pair.

### alpha_vantage/REST.intraday_fx_quotes(from_symbol, to_symbol, interval='5min', outputsize='full', output_format=None)
Returns a `csv`, `json`, or `pandas` object of intraday OHLCV data for the currency pair.

### alpha_vantage/REST.exchange_rate(from_currency, to_currency)
Returns a `json` object with the current OHLCV data of the selected currency pair (digital or physical)

### alpha_vantage/REST.historic_cryptocurrency_quotes(self, symbol, market, cadence='daily', output_format=None)
Returns a `csv`, `json`, or `pandas` object of historical OHLCV data for the cryptocurrency pair.

### alpha_vantage/REST.techindicators(self, techindicator='SMA', output_format='json', **kwargs)
Returns a `csv`, `json`, or `pandas` object with the data from the techindicator of choice.

### alpha_vantage/REST.sector()
Returns a `json` of the currrency sector performances.

## Support and Contribution

For technical issues particular to this module, please report the
Expand Down
1 change: 1 addition & 0 deletions alpaca_trade_api/alpha_vantage/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .rest import REST # noqa
225 changes: 225 additions & 0 deletions alpaca_trade_api/alpha_vantage/rest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
import requests
from alpha_vantage.timeseries import TimeSeries
from alpha_vantage.cryptocurrencies import CryptoCurrencies
from alpha_vantage.foreignexchange import ForeignExchange
from alpha_vantage.sectorperformance import SectorPerformances
from alpha_vantage.techindicators import TechIndicators
from alpaca_trade_api.common import get_alpha_vantage_credentials


class REST(object):

def __init__(self, api_key):
self._api_key = get_alpha_vantage_credentials(api_key)
self._session = requests.Session()
self._timeseries = TimeSeries(key=self._api_key)
self._cryptocurrencies = CryptoCurrencies(key=self._api_key)
self._foreignexchange = ForeignExchange(key=self._api_key)
self._sectorperformance = SectorPerformances(key=self._api_key)
self._techindicators = TechIndicators(key=self._api_key)

def _request(self, method, params=None):
url = 'https://www.alphavantage.co/query?'
params = params or {}
params['apikey'] = self._api_key
resp = self._session.request(method, url, params=params)
resp.raise_for_status()
return resp.json()

def get(self, params=None):
''' Customizable endpoint, where you can pass all
keywords/paramters from the documentation:
https://www.alphavantage.co/documentation/#
Returns:
pandas, csv, or json
'''
return self._request('GET', params=params)

def historic_quotes(self, symbol, adjusted=False, outputsize='full', cadence='daily', output_format=None):
''' Returns the one of the TIME_SERIES_* endpoints of the Alpha Vantage API.
Params:
symbol: The ticker to return
adjusted: Return the adjusted prices
cadence: Choose between ['daily', 'weekly', 'monthly'], to return the cadence
output_format: Choose between['json', 'csv', 'pandas']
Returns:
pandas, csv, or json
'''
if output_format:
self._timeseries.output_format = output_format
if cadence == 'daily':
data, _ = self._timeseries.get_daily_adjusted(
symbol=symbol, outputsize=outputsize) if adjusted else self._timeseries.get_daily(symbol=symbol, outputsize=outputsize)
if cadence == 'weekly':
data, _ = self._timeseries.get_weekly_adjusted(
symbol=symbol) if adjusted else self._timeseries.get_weekly(symbol=symbol)
if cadence == 'monthly':
data, _ = self._timeseries.get_monthly_adjusted(
symbol=symbol) if adjusted else self._timeseries.get_monthly(symbol=symbol)
return data

def intraday_quotes(self, symbol, interval='5min', outputsize='full', output_format=None):
''' Returns the TIME_SERIES_INTRADAY endpoint of the Alpha Vantage API.
Params:
symbol: The ticker to return
interval: Choose between['1min', '5min', '15min', '30min', '60min']
output_format: Choose between['json', 'csv', 'pandas']
Returns:
pandas, csv, or json
'''
if output_format:
self._timeseries.output_format = output_format
data, _ = self._timeseries.get_intraday(
symbol=symbol, interval=interval, outputsize=outputsize)
return data

def current_quote(self, symbol):
''' Returns the GLOBAL_QUOTE endpoint
of the Alpha Vantage API.
Params:
symbol: The ticker to return
output_format: Choose between['json', 'csv', 'pandas']
Returns:
pandas, csv, or json
'''
data, _ = self._timeseries.get_quote_endpoint(symbol=symbol)
return data

def last_quote(self, symbol):
return self.current_quote(symbol)

def company(self, symbol, datatype='json'):
return self.search_endpoint(symbol, datatype=datatype)

def search_endpoint(self, keywords, datatype='json'):
'''Search endpoint returns a list of possible companies
that correspond to keywords
Params:
datatype: csv, json, or pandas
keywords: ex. keywords=microsoft
Returns:
pandas, csv, or json
'''
params = {'function': 'SYMBOL_SEARCH',
'keywords': keywords, 'datatype': datatype}
return self.get(params)

def historic_fx_quotes(self, from_symbol, to_symbol, outputsize='full', cadence='daily', output_format=None):
''' Returns the one of the FX_* endpoints of the Alpha Vantage API.
Params:
from_currency: The symbol to convert
to_currency: The symbol to convert to
cadence: Choose between ['daily', 'weekly', 'monthly'], to return the cadence
output_format: Choose between['json', 'csv', 'pandas']
Returns:
pandas, csv, or json
'''
if output_format:
self._foreignexchange.output_format = output_format
if cadence == 'daily':
data, _ = self._foreignexchange.get_currency_exchange_daily(
from_symbol=from_symbol, to_symbol=to_symbol, outputsize=outputsize)
if cadence == 'weekly':
data, _ = self._foreignexchange.get_currency_exchange_weekly(
from_symbol=from_symbol, to_symbol=to_symbol, outputsize=outputsize)
if cadence == 'monthly':
data, _ = self._foreignexchange.get_currency_exchange_monthly(
from_symbol=from_symbol, to_symbol=to_symbol, utputsize=outputsize)
return data

def intraday_fx_quotes(self, from_symbol, to_symbol, interval='5min', outputsize='full', output_format=None):
''' Returns the FX_INTRADAY endpoint of the Alpha Vantage API.
Params:
from_currency: The symbol to convert
to_currency: The symbol to convert to
interval: Choose between['1min', '5min', '15min', '30min', '60min']
output_format: Choose between['json', 'csv', 'pandas']
Returns:
pandas, csv, or json
'''
if output_format:
self._foreignexchange.output_format = output_format
data, _ = self._foreignexchange.get_currency_exchange_intraday(
from_symbol=from_symbol, to_symbol=to_symbol, interval=interval, outputsize=outputsize)
return data

def exchange_rate(self, from_currency, to_currency):
''' Returns the exchange rate of two currencies, digital or physical.
CURRENCY_EXCHANGE_RATE endpoint of the Alpha Vantage API
Params:
from_currency: The symbol to convert
to_currency: The symbol to convert to
Returns:
json
'''
params = {'function': "CURRENCY_EXCHANGE_RATE",
'from_currency': from_currency, 'to_currency': to_currency}
data = self.get(params)
return data

def historic_cryptocurrency_quotes(self, symbol, market, cadence='daily', output_format=None):
''' Returns the one of the DIGITAL_CURRENCY_* endpoints of the Alpha Vantage API.
Params:
symbol: The cryptocurrency to return
market: The market it's being sold on
cadence: Choose between ['daily', 'weekly', 'monthly'], to return the cadence
output_format: Choose between['json', 'csv', 'pandas']
Returns:
pandas, csv, or json
'''
if output_format:
self._cryptocurrencies.output_format = output_format
if cadence == 'daily':
data, _ = self._cryptocurrencies.get_digital_currency_daily(
symbol=symbol, market=market)
if cadence == 'weekly':
data, _ = self._cryptocurrencies.get_digital_currency_weekly(
symbol=symbol, market=market)
if cadence == 'monthly':
data, _ = self._cryptocurrencies.get_digital_currency_monthly(
symbol=symbol, market=market)
return data

def techindicators(self, techindicator='SMA', output_format='json', **kwargs):
''' Returns the one of the technical indicator endpoints of the Alpha Vantage API.
Params:
techindicator: The technical indicator of choice
params: Each technical indicator has additional optional parameters
Returns:
pandas, csv, or json
'''
if output_format:
self._techindicators.output_format = output_format
params = {'function': techindicator}
for key, value in kwargs.items():
params[key] = value
data = self.get(params)
return data

def sector(self):
''' Returns the sector performances
Returns:
pandas, csv, or json
'''
data, _ = self._sectorperformance.get_sector()
return data
8 changes: 8 additions & 0 deletions alpaca_trade_api/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,14 @@ def get_polygon_credentials(alpaca_key=None):
return key_id


def get_alpha_vantage_credentials(alpha_vantage_key=None):
key_id = alpha_vantage_key or os.environ.get('ALPHAVANTAGE_API_KEY')
if key_id is None:
raise ValueError('Key ID must be given to access Alpha Vantage API'
' (env: ALPHAVANTAGE_API_KEY)')
return key_id


def get_api_version(api_version):
api_version = api_version or os.environ.get('APCA_API_VERSION')
if api_version is None:
Expand Down
2 changes: 2 additions & 0 deletions alpaca_trade_api/rest.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
Asset, Order, Position, BarSet, Clock, Calendar,
)
from . import polygon
from . import alpha_vantage

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -73,6 +74,7 @@ def __init__(
'APCA_RETRY_CODES', '429,504').split(',')]
self.polygon = polygon.REST(
self._key_id, 'staging' in self._base_url)
self.alpha_vantage = alpha_vantage.REST(self._key_id)

def _request(
self,
Expand Down
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
'websocket-client',
'websockets>=8.0',
'deprecated',
'alpha_vantage',
],
tests_require=[
'pytest',
Expand Down
Empty file.
14 changes: 14 additions & 0 deletions tests/test_alpha_vantage/test_data/global_quote
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"Global Quote": {
"01. symbol": "MSFT",
"02. open": "112.6300",
"03. high": "113.1700",
"04. low": "110.6400",
"05. price": "112.1300",
"06. volume": "29062853",
"07. latest trading day": "2018-10-05",
"08. previous close": "112.7900",
"09. change": "-0.6600",
"10. change percent": "-0.5852%"
}
}
Loading

0 comments on commit 517f939

Please sign in to comment.