[#10] Add GDAX API

This commit is contained in:
Gavin.Chan
2017-12-31 01:19:04 +00:00
parent 7115b45a4a
commit 322b12b678
6 changed files with 194 additions and 9 deletions
+1 -1
View File
@@ -82,4 +82,4 @@ class BitmexApi(ExchangeApi):
# return self._send_request(
# command=name, http_method=http_method, params=kwargs,
# public_key=self._public_key, private_key=self._private_key)
raise NotImplementedError("request private is not implemented.")
raise NotImplementedError("request private is not implemented.")
+5 -4
View File
@@ -1,15 +1,17 @@
#!/bin/python
import requests
import hmac
import hashlib
import urllib
# import hmac
# import hashlib
# import urllib
import json
from functools import partial
from time import time
class ExchangeApi:
"""Exchange API connector.
"""
def __init__(self, public_key, private_key, logger=None):
"""Constructor.
@@ -135,7 +137,6 @@ class ExchangeApi:
"""
raise NotImplementedError("Not yet implemented.")
def _send_request(self, command, http_method, params=None, data=None,
public_method=False):
"""Send request.
+125
View File
@@ -0,0 +1,125 @@
#!/bin/python
# import requests
# import hmac
# import hashlib
# import urllib
# from functools import partial
from libcryptomarket.api.exchange_api import ExchangeApi
class GdaxApi(ExchangeApi):
"""GDAX API.
"""
def __init__(self, public_key=None, private_key=None, logger=None):
"""Constructor.
:param public_key: Public key.
:param private_key: Private key.
:param logger: Logger.
"""
ExchangeApi.__init__(self, public_key, private_key, logger)
@classmethod
def get_url(cls):
"""Get API url.
"""
return "https://api.gdax.com"
@classmethod
def get_public_calls(cls):
"""Get public API calls.
"""
return {
"products": "GET",
"products/book": "GET",
"products/trades": "GET",
"products/candles": "GET",
"currencies": "GET",
"time": "GET",
}
@classmethod
def get_private_calls(cls):
"""Get public API calls.
"""
return {
}
@classmethod
def translate_call_name(cls, name):
"""Translate API call name.
The class method name is always underscored (aligned with Python
standard.) This method is to translate underscored name to exchange
API call name.
:param name: Method name (underscored).
"""
return name.replace("_", "/")
def _request_public(self, name, http_method, **kwargs):
"""Request public API call.
:param name: Method name.
:param http_method: HTTP method (POST, GET, DELETE).
"""
if 'product_id' in kwargs.keys():
name = name.split('/')
name = [name[0]] + [kwargs['product_id']] + name[1:]
del kwargs['product_id']
return self._send_request(
command='/'.join(name), http_method=http_method,
public_method=True, params=kwargs)
else:
return self._send_request(
command=name, http_method=http_method,
public_method=True, params=kwargs)
def _request_private(self, name, http_method, **kwargs):
"""Request private API call.
:param name: Method name.
:param http_method: HTTP method (POST, GET, DELETE).
"""
raise NotImplementedError()
# @classmethod
# def _generate_auth(cls, public_key, private_key):
# """Generate authentication.
# :param public_key: Public key.
# :param private_key: Private key.
# """
# return None
# @classmethod
# def _generate_headers(cls, command, http_method, params, data,
# public_key, private_key):
# """Generate headers.
# :param command: Command.
# :param http_method: HTTP method, for example GET.
# :param params: Parameters.
# :param data: Data.
# :param public_key: Public key.
# :param private_key: Private key.
# """
# signature = hmac.new(private_key.encode(),
# urllib.parse.urlencode(data).encode(),
# digestmod=hashlib.sha512).hexdigest()
# header = {
# 'Key': public_key,
# 'Sign': signature
# }
# return header
# @classmethod
# def _format_data(cls, data):
# """Format the data to exchange desirable format.
# :param data: Data.
# """
# return data
+1 -1
View File
@@ -3,7 +3,7 @@ import requests
import hmac
import hashlib
import urllib
from functools import partial
# from functools import partial
from libcryptomarket.api.exchange_api import ExchangeApi
API_URL = "https://poloniex.com/public?command="
+57 -1
View File
@@ -1,5 +1,6 @@
from functools import partial
from datetime import datetime, timedelta
from time import sleep
import pandas as pd
@@ -45,6 +46,61 @@ def historical_ticker(source, symbol, period, start_time=None, end_time=None):
data.columns.name = symbol
return data
elif source_name == "gdax":
# Exchange validation
if (start_time is None) + (end_time is None) not in [0, 2]:
# Both start and end time must be provided
raise ValueError("Start and end time must be both provided")
request_func = partial(source.products_candles, product_id=symbol,
granularity=period)
if start_time is None and end_time is None:
# Just get the latest 300 ticks
data = request_func()
data.raise_for_status()
data = pd.DataFrame(data.json())
else:
# Safety net
last_datetime = start_time.timestamp()
data = []
while start_time <= end_time:
tmp_data = request_func(
start=start_time.isoformat(),
end=(start_time +
timedelta(seconds=period * 200)).isoformat())
tmp_data.raise_for_status()
tmp_data = pd.DataFrame(tmp_data.json())
# Append into data list
data.append(tmp_data)
# Check to exit
if last_datetime >= tmp_data.iloc[0, 0]:
# Same as the previous query
break
else:
last_datetime = tmp_data.iloc[0, 0]
start_time = datetime.fromtimestamp(last_datetime)
sleep(0.333)
if len(data) > 1:
data = pd.concat(data, axis=0)
else:
data = data[0]
data.columns = ['datetime', 'low', 'high', 'open', 'close', 'volume']
data['datetime'] = pd.to_datetime(data['datetime'], unit='s')
data = data.set_index('datetime').sort_index()
data = data[~data.index.duplicated(keep='first')]
return data
else:
raise ValueError("Source (%s [%s]) does not support historical ticker"
% (source, source_name))
% (source, source_name))
+5 -2
View File
@@ -87,7 +87,7 @@ def get_historical_prices(source='cryptocompare', symbol=None, exchange=None,
# Validate and transform to_time and from_time
if (to_time is not None and from_time is not None and
to_time <= from_time):
to_time <= from_time):
raise ValueError("From time should not be greater than or "
"equal to to time.")
@@ -96,7 +96,10 @@ def get_historical_prices(source='cryptocompare', symbol=None, exchange=None,
while from_time is None or to_time is None or from_time < to_time:
# Import and query
from libcryptomarket.api.bitmex_api import BitmexApi
exchange = BitmexApi(public_key=None, private_key=None, logger=None)
exchange = BitmexApi(
public_key=None,
private_key=None,
logger=None)
func = partial(exchange.trade_bucketed, symbol=symbol,
binSize=period)