Source code for allcoin.client

# coding=utf-8

import hashlib
import requests
import json
from operator import itemgetter
from .exceptions import AllcoinAPIException, AllcoinRequestException


[docs]class Client(object): API_URL = 'https://api.allcoin.com/api' API_VERSION = 'v1' ORDER_STATUS_UNFILLED = 0 ORDER_STATUS_PARTIALLY_FILLED = 1 ORDER_STATUS_FILLED = 2 ORDER_STATUS_CANCELLED = 10
[docs] def __init__(self, api_key, api_secret, requests_params=None): """Allcoin API Client constructor :param api_key: Api Key :type api_key: str. :param api_secret: Api Secret :type api_secret: str. :param requests_params: optional - Dictionary of requests params to use for all calls :type requests_params: dict. """ self.API_KEY = api_key self.API_SECRET = api_secret self.session = self._init_session() self._requests_params = requests_params
def _init_session(self): session = requests.session() session.headers.update({'Accept': 'application/json', 'User-Agent': 'allcoin/python'}) return session def _create_api_uri(self, path): return "{}/{}/{}".format(self.API_URL, self.API_VERSION, path) def _generate_signature(self, data): ordered_data = self._order_params(data) ordered_data.append(('secret_key', self.API_SECRET)) print("ordered data:{}".format(ordered_data)) query_string = '&'.join(["{}={}".format(d[0], d[1]) for d in ordered_data]) m = hashlib.md5(query_string.encode('utf-8')) return m.hexdigest().upper() def _order_params(self, data): """Convert params to list with signature as last element :param data: :return: """ has_signature = False params = [] for key, value in data.items(): if key == 'sign': has_signature = True else: params.append((key, value)) # sort parameters by key params.sort(key=itemgetter(0)) if has_signature: params.append(('sign', data['sign'])) return params def _request(self, method, path, signed, **kwargs): uri = self._create_api_uri(path) # set default requests timeout kwargs['timeout'] = 10 # add our global requests params if self._requests_params: kwargs.update(self._requests_params) data = kwargs.get('data', None) if data and isinstance(data, dict): kwargs['data'] = data if signed: # generate signature kwargs['data']['api_key'] = self.API_KEY kwargs['data']['sign'] = self._generate_signature(kwargs['data']) # sort get and post params to match signature order if data: # find any requests params passed and apply them if 'requests_params' in kwargs['data']: # merge requests params into kwargs kwargs.update(kwargs['data']['requests_params']) del(kwargs['data']['requests_params']) # sort post params kwargs['data'] = self._order_params(kwargs['data']) # if get request assign data array to params value for requests lib if data and method == 'get': kwargs['params'] = kwargs['data'] del(kwargs['data']) print(kwargs) response = getattr(self.session, method)(uri, **kwargs) return self._handle_response(response) def _handle_response(self, response): """Internal helper for handling API responses from the Binance server. Raises the appropriate exceptions when necessary; otherwise, returns the response. """ if not str(response.status_code).startswith('2'): raise AllcoinAPIException(response) try: res = response.json() if 'error_code' in res: raise AllcoinAPIException(response) return res except ValueError: raise AllcoinRequestException('Invalid Response: %s' % response.text) def _get(self, path, signed=False, **kwargs): return self._request('get', path, signed, **kwargs) def _post(self, path, signed=False, **kwargs): return self._request('post', path, signed, **kwargs) def _put(self, path, signed=False, **kwargs): return self._request('put', path, signed, **kwargs) def _delete(self, path, signed=False, **kwargs): return self._request('delete', path, signed, **kwargs) # Exchange Endpoints
[docs] def get_ticker(self, symbol): """Get the Ticker for the market :param symbol: required :type symbol: str .. code:: python ticker = client.get_ticker('eth_btc') :returns: API response .. code-block:: python { "date":"1410431279", "ticker":{ "buy":"33.15", "high":"34.15", "last":"33.15", "low":"32.05", "sell":"33.16", "vol":"10532696.39199642" } } :raises: AllcoinResponseException, BinanceAPIException """ params = { 'symbol': symbol } return self._get('ticker', data=params)
[docs] def get_order_book(self, symbol, size=None, merge=None): """Get the Order Book for the market :param symbol: required :type symbol: str :param size: Default 100; max 100 :type size: int :param merge: merge depth Default 1; max 100 :type merge: int .. code:: python # default book = client.get_order_book('eth_btc') # optional params book = client.get_order_book('eth_btc', size=5, merge=5) :returns: API response .. code-block:: python { "asks": [ [792, 5], [789.68, 0.018], [788.99, 0.042], [788.43, 0.036], [787.27, 0.02] ], "bids": [ [787.1, 0.35], [787, 12.071], [786.5, 0.014], [786.2, 0.38], [786, 3.217], [785.3, 5.322], [785.04, 5.04] ] } :raises: AllcoinResponseException, BinanceAPIException """ params = { 'symbol': symbol } if size: params['size'] = size if merge: params['merge'] = merge return self._get('depth', data=params)
[docs] def get_trades(self, symbol, since=None): """Get the last 600 trades with optional since transaction id parameter :param symbol: required :type symbol: str :param since: Transaction id (inclusive) :type since: int .. code:: python # default trades = client.get_trades('eth_btc') # default trades = client.get_trades('eth_btc', since=230433) :returns: API response .. code-block:: python [ { "date": "1367130137", "date_ms": "1367130137000", "price": 787.71, "amount": 0.003, "tid": "230433", "type": "sell" }, { "date": "1367130137", "date_ms": "1367130137000", "price": 787.65, "amount": 0.001, "tid": "230434", "type": "sell" }, { "date": "1367130137", "date_ms": "1367130137000", "price": 787.5, "amount": 0.091, "tid": "230435", "type": "sell" } ] :raises: AllcoinResponseException, BinanceAPIException """ params = { 'symbol': symbol } if since: params['since'] = since return self._get('trades', data=params)
[docs] def get_trade_history(self, symbol, since=None): """Get trade history - requires api key :param symbol: required :type symbol: str :param since: Transaction id (inclusive) :type since: int .. code:: python # default trades = client.get_trade_history('eth_btc') # default trades = client.get_trade_history('eth_btc', since=230433) :returns: API response .. code-block:: python [ { "date": 1367130137, "date_ms": 1367130137000, "price": 787.71, "amount": 0.003, "tid": "230433", "type": "sell" }, { "date": 1367130137, "date_ms": 1367130137000, "price": 787.65, "amount": 0.001, "tid": "230434", "type": "sell" }, { "date": 1367130137, "date_ms": 1367130137000, "price": 787.5, "amount": 0.091, "tid": "230435", "type": "sell" } ] :raises: AllcoinResponseException, BinanceAPIException """ params = { 'symbol': symbol } if since: params['since'] = since return self._post('trade_history', data=params, signed=True)
[docs] def get_klines(self, symbol, kline_type, size=None, since=None): """Get klines for a symbol :param symbol: required :type symbol: str :param kline_type: type of candlestick (1min, 3min, 5min, 15min, 30min, 1hour, 2hour, 4hour, 6hour, 12hour, 1day, 3day, 1week) :type kline_type: str :param size: number of klines to return :type size: int :param since: timestamp in ms to return from :type since: int .. code:: python # default klines = client.get_klines('eth_btc', '1min') # optional params klines = client.get_klines('eth_btc', '1hour', size=20, since=1417449600000) :returns: API response .. code-block:: python [ [ 1417449600000, # timestamp 2339.11, # open 2383.15, # high 2322, # low 2369.85, # close 83850.06 # volume ], [ 1417536000000, 2370.16, 2380, 2352, 2367.37, 17259.83 ] ] :raises: AllcoinResponseException, BinanceAPIException """ params = { 'symbol': symbol, 'type': kline_type } if size: params['size'] = size if since: params['since'] = since return self._get('kline', data=params)
# User information
[docs] def get_userinfo(self): """Get account info .. code:: python # default info = client.get_userinfo() :returns: API response .. code-block:: python { "info": { "funds": { "free": { "btc": "0", "usd": "0", "ltc": "0" }, "freezed": { "btc": "0", "usd": "0", "ltc": "0" } } }, "result": true } :raises: AllcoinResponseException, BinanceAPIException """ params = {} return self._post('userinfo', data=params, signed=True)
# Trading Endpoints
[docs] def create_order(self, symbol, side, price, amount): """Create an order :param symbol: required :type symbol: str :param side: order side buy/sell :type side: str :param price: order price :type price: str :param amount: order quantity :type amount: str .. code-block:: python # default order = client.create_order('eth_btc', 'buy', '0.2348', '100') :returns: API response .. code-block:: python { "order_id": "123456", "result": true } :raises: AllcoinResponseException, BinanceAPIException """ params = { 'symbol': symbol, 'type': side, 'price': price, 'amount': amount, } return self._post('trade', data=params, signed=True)
[docs] def create_buy_order(self, symbol, price, amount): """Create a buy order :param symbol: required :type symbol: str :param price: order price :type price: str :param amount: order quantity :type amount: str .. code-block:: python # default order = client.create_buy_order('eth_btc', '0.2348', '100') :returns: API response .. code-block:: python { "order_id": "123456", "result": true } :raises: AllcoinResponseException, BinanceAPIException """ return self.create_order(symbol, 'buy', price, amount)
[docs] def create_sell_order(self, symbol, price, amount): """Create a sell order :param symbol: required :type symbol: str :param price: order price :type price: str :param amount: order quantity :type amount: str .. code-block:: python # default order = client.create_buy_order('eth_btc', '0.2348', '100') :returns: API response .. code-block:: python { "order_id": "123456", "result": true } :raises: AllcoinResponseException, BinanceAPIException """ return self.create_order(symbol, 'sell', price, amount)
[docs] def batch_orders(self, symbol, order_data, order_type=None): """Create an order :param symbol: required :type symbol: str :param order_data: list of dictionaries of price, amount and type :type order_data: list of dicts :param order_type: optional buy/sell default used if type not set in order_data dict :type order_type: str .. code-block:: python order_data = [ { "price": "0.0123", "amount": "120", "type": "sell" }, { "price": "0.0112", "amount": "110" } ] order = client.create_order('eth_btc', order_data, type='buy') :returns: API response .. code-block:: python { "order_info":[ {"order_id":41724206}, {"error_code":10011,"order_id":-1}, {"error_code":10014,"order_id":-1} ], "result":true } :raises: AllcoinResponseException, BinanceAPIException """ params = { 'symbol': symbol, 'order_data': json.dumps(order_data, separators=(',', ':')) } if order_type: params['type'] = order_type return self._post('batch_trade', data=params, signed=True)
[docs] def cancel_order(self, symbol, order_id): """Cancel an order or up to 3 orders :param symbol: required :type symbol: str :param order_id: order ID (multiple orders are separated by a comma ',', 3 orders at most are allowed per request) :type order_id: str .. code-block:: python # single order order = client.cancel_order('eth_btc', '123456') # multiple orders order = client.cancel_order('eth_btc', '123456,123457,123557') :returns: API response .. code-block:: python # single order id { "order_id": "123456", "result": true } # multiple order ids { "success":"123456,123457", "error":"123458" } :raises: AllcoinResponseException, BinanceAPIException """ params = { 'symbol': symbol, 'order_id': order_id } return self._post('cancel_order', data=params, signed=True)
[docs] def get_order(self, symbol, order_id): """Get info about a particular order :param symbol: required :type symbol: str :param order_id: order ID to fetch :type order_id: str .. code-block:: python order = client.get_order('eth_btc', '123456') :returns: API response .. code-block:: python { "result": true, "orders": [ { "amount": 0.1, "avg_price": 0, # average transaction price "create_date": 1418008467000, # order time "deal_amount": 0, # filled quantity "order_id": 10000591, # order id "price": 500, # entrustment price "status": 0, # 0 = unfilled, 1 = partially filled, 2 = fully filled, 10 = cancelled "symbol": "btc_usd", "type": "sell" }, { "amount": 0.2, "avg_price": 0, "create_date": 1417417957000, "deal_amount": 0, "order_id": 10000724, "price": 0.1, "status": 0, "symbol": "btc_usd", "type": "buy" } ] } :raises: AllcoinResponseException, BinanceAPIException """ params = { 'symbol': symbol, 'order_id': order_id } return self._post('order_info', data=params, signed=True)
[docs] def get_open_orders(self, symbol): """Get info about all open orders :param symbol: required :type symbol: str .. code-block:: python order = client.get_open_orders('eth_btc') :returns: API response .. code-block:: python { "result": true, "orders": [ { "amount": 0.1, "avg_price": 0, # average transaction price "create_date": 1418008467000, # order time "deal_amount": 0, # filled quantity "order_id": 10000591, # order id "price": 500, # entrustment price "status": 0, # 0 = unfilled, 1 = partially filled, 2 = fully filled, 10 = cancelled "symbol": "btc_usd", "type": "sell" }, { "amount": 0.2, "avg_price": 0, "create_date": 1417417957000, "deal_amount": 0, "order_id": 10000724, "price": 0.1, "status": 0, "symbol": "btc_usd", "type": "buy" } ] } :raises: AllcoinResponseException, BinanceAPIException """ return self.get_order(symbol, order_id="-1")
[docs] def get_orders(self, symbol, order_status, order_ids): """Get info about multiple orders :param symbol: required :type symbol: str :param order_status: 0 for unfilled orders; 1 for filled orders :type order_status: int :param order_ids: order IDs to fetch (multiple orders are separated by ',', 50 orders at most are allowed per request) :type order_ids: str .. code-block:: python order = client.get_orders('eth_btc', 1) :returns: API response .. code-block:: python { "result": true, "orders": [ { "amount": 0.1, "avg_price": 0, # average transaction price "create_date": 1418008467000, # order time "deal_amount": 0, # filled quantity "order_id": 10000591, # order id "price": 500, # entrustment price "status": 0, # 0 = unfilled, 1 = partially filled, 2 = fully filled, 10 = cancelled "symbol": "btc_usd", "type": "sell" }, { "amount": 0.2, "avg_price": 0, "create_date": 1417417957000, "deal_amount": 0, "order_id": 10000724, "price": 0.1, "status": 0, "symbol": "btc_usd", "type": "buy" } ] } :raises: AllcoinResponseException, BinanceAPIException """ params = { 'symbol': symbol, 'type': order_status, 'order_id': order_ids } return self._post('orders_info', data=params, signed=True)
[docs] def get_order_history(self, symbol, order_status, page=1, limit=200): """Get history of orders for a symbol :param symbol: required :type symbol: str :param order_status: 0 for unfilled orders; 1 for filled orders :type order_status: int :param page: page to fetch :type page: int :param limit: amount on each page :type limit: int .. code-block:: python order = client.get_order_history('eth_btc', 1) :returns: API response .. code-block:: python [ { "current_page": 1, "orders": [ { "amount": 0, "avg_price": 0, "create_date": 1405562100000, "deal_amount": 0, "order_id": 0, "price": 0, "status": 2, "symbol": "btc_usd", "type": "sell” } ], "page_length": 1, "result": true, "total": 3 } ] :raises: AllcoinResponseException, BinanceAPIException """ params = { 'symbol': symbol, 'status': order_status, 'current_page': page, 'page_length': limit } return self._post('order_history', data=params, signed=True)