zoukankan      html  css  js  c++  java
  • OKEX API v1 SDK基于 Python 实现

    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    # Note: it is okex v1. okex v3 api has many bugs, for example kline don't support 1hour when set start or end 
    # https://www.cnblogs.com/fangbei/p/okex-api-v1.html
    import time,datetime import json import math import hashlib,hmac import numpy as np import websocket import sys from base.exchange import EXCHANGE class OKEX(EXCHANGE): _api_url = "https://www.okex.com" _ws_url = "wss://real.okex.com:10441/websocket" ''' 初始化 def __init__(self, apikey="", secret=""): self.__apikey = apikey self.__secret = secret ''' # 货币对列表 def markets(self): url = self._api_url + '/v2/spot/markets/products' result = self.http_request(url) list = [] for item in result["data"]: if item["online"] == 1: temp = item["symbol"].split("_") list.append({'symbol': item["symbol"], 'base': temp[0].upper(), 'quote': temp[1].upper()}) return list # 精度 def precisions(self): url = self._api_url + '/api/spot/v3/instruments' result = self.http_request(url) dict = {} for item in result: symbol = item["base_currency"] + "_" + item["quote_currency"] filter_dict = {} filter_dict['price'] = abs(round(math.log(float(item["tick_size"]), 10))) filter_dict['quantity'] = abs(round(math.log(float(item["size_increment"]), 10))) dict[symbol] = filter_dict return dict # 获取行情 def ticker(self, symbol = 'btc_usdt'): url = self._api_url + '/api/v1/ticker.do?symbol=%s'%(self._x_symbol(symbol)) result = self.http_request(url) dict = {'bid': float(result["ticker"]["buy"]), 'ask': float(result["ticker"]["sell"]), 'last': float(result["ticker"]["last"])} return dict # 获取市场深度 def depth(self, symbol = 'btc_usdt'): url = self._api_url + '/api/v1/depth.do?symbol=%s'%(self._x_symbol(symbol)) depth = self.http_request(url) depth['asks'].sort(key=lambda x:x[0], reverse=False) depth['bids'].sort(key=lambda x:x[0], reverse=True) return depth #标准格式,不用转换 # # 获取交易信息(60条) def trades(self, symbol = 'btc_usdt', limit = 60): url = self._api_url + '/api/v1/trades.do?symbol=%s'%(self._x_symbol(symbol)) # print(url) result = self.http_request(url) list = [] for item in result: list.append({'id': int(item["tid"]), 'time': item["date_ms"], 'price': item["price"], 'quantity': item["amount"], 'direction': item["type"]}) return list # 获取的K线数据 def kline(self, symbol = 'btc_usdt', interval = '1hour', limit = 120, start = None, end = None): xdict = { "1min":"1min", "3min":"3min", "5min":"5min", "10min":"", "15min":"15min", "30min":"30min", "1hour":"1hour", "2hour":"2hour", "3hour":"", "4hour":"4hour", "6hour":"6hour", "8hour":"", "12hour":"12hour", "1day":"1day", "3day":"3day", "1week":"1week", "2week":"", "1month":"" } if not xdict[interval]: print('不支持的K线周期 %s not support %s'%(self._exchange, interval)) return None url = self._api_url + '/api/v1/kline.do?symbol=%s&type=%s&size=%s'%(self._x_symbol(symbol), xdict[interval], limit) if start: #如果指定了size,则优先size url += '&since=%s'%(start) + "000" #毫秒级时间戳 print(url) result = self.http_request(url) npa = np.array(result, dtype='float64') if (npa.shape[0] < 60): self._x_print(symbol, sys._getframe().f_code.co_name, interval + " 数组维度过小" + str(npa.shape[0])) stamp, open, high, low, close, volume = npa.T[0] / 1000, npa.T[1], npa.T[2], npa.T[3], npa.T[4], npa.T[5] return stamp, open, high, low, close, volume # 获取用户账户资产信息 def account(self): url = self._api_url + '/api/v1/userinfo.do' params = { 'api_key' : self._apikey } params['sign'] = self.signature(params) result = self.http_request(url, "POST", params) dict = {} i = 1 for item in result["info"]["funds"]["free"]: dict[item.upper()] = {'free': float(result["info"]["funds"]["free"][item]), 'locked': float(result["info"]["funds"]["freezed"][item]), 'total': float(result["info"]["funds"]["free"][item]) + float(result["info"]["funds"]["freezed"][item])} return dict # 下单 {'result': True, 'orderid': 342856847} def order(self, symbol, side, type, quantity=None, price=None): if side not in ["BUY", "SELL"] or type not in ["LIMIT", "MARKET"]: raise Exception("ERROR params side %s type %s"%(side, type)) return url = self._api_url + '/api/v1/trade.do' # 买卖类型:限价单(buy/sell) 市价单(buy_market/sell_market) new_type = "_".join([side, type]).lower() if type == "MARKET" else side.lower() params = { 'api_key' :self._apikey, 'symbol' :self._x_symbol(symbol), 'type' :new_type, 'price' :price, 'amount' :quantity } params.pop('amount') if side in ["BUY"] and type in ["MARKET"] else None #市价买单不传amount params.pop('price') if side in ["SELL"] and type in ["MARKET"] else None #市价卖单不传price # print(params) params['sign'] = self.signature(params) result = self.http_request(url, "POST", params) if 'result' in result: return {'result': result['result'], 'orderid': result['order_id']} elif 'error_code' in result: return {'result': False, 'errcode': result['error_code'], 'errmsg': "https://github.com/okcoin-okex/API-docs-OKEx.com/tree/master/API-For-Spot-CN"} else: return result # 撤销订单 {'result': True} def order_cancel(self, symbol, orderid): url = self._api_url + '/api/v1/cancel_order.do' params = { 'api_key' :self._apikey, 'symbol' :self._x_symbol(symbol), 'order_id' :orderid } params['sign'] = self.signature(params) result = self.http_request(url, "POST", params) return {'result': result['result']} # 查询订单 def order_query(self, symbol, orderid): url = self._api_url + '/api/v1/order_info.do' params = { 'api_key' :self._apikey, 'symbol' :self._x_symbol(symbol), 'order_id' :orderid } params['sign'] = self.signature(params) result = self.http_request(url, "POST", params) # print(result) types = { 0:"SUBMITTED", 1:"PARTIALLY_FILLED", 2:"FILLED", -1:"CANCELED", 4:"OTHER" } # print(len(result["orders"])) > 0 if (result["result"]): dict = { 'symbol': result["orders"][0]["symbol"], 'orderid': result["orders"][0]["order_id"], 'price': result["orders"][0]["price"], 'avg_price':result["orders"][0]["avg_price"], 'quantity': result["orders"][0]["amount"], 'status': types[result["orders"][0]["status"]], 'type': result["orders"][0]["type"], 'time': result["orders"][0]["create_date"], } return dict else: return {'result': False, 'errcode': result["error_code"], 'errmsg': "empty data"} # 签名函数 def signature(self, params): sign = '' for key in sorted(params.keys()): sign += key + '=' + str(params[key]) +'&' data = sign+'secret_key='+self._secret return hashlib.md5(data.encode("utf8")).hexdigest().upper() # websocket 连接 https://www.cnblogs.com/fangbei/p/okex-api-v1.html def websocket_conn(self): try: self.ws = websocket.create_connection(self._ws_url) time.sleep(1) except: print("WebSocket Connect Error %s" %(self._exchange)) else: return self.ws # websocket订阅函数,目前支持ticker, depth两种频道 def websocket_sub(self, symbol = 'BTC_USDT', channel="depth"): if channel == "depth": channel = channel + "_5" sub = {"event": "addChannel", "channel": '_'.join(['ok_sub_spot', self._x_symbol(symbol), channel])} # print(sub) self.ws.send(json.dumps(sub)) return self.ws # websocket 接收数据格式化,格式和REST统一 ''' while True: data = exchange.websocket_fmt(channel, ws.recv()) print(data) ''' def websocket_fmt(self, channel, data): result = json.loads(data)[0] dict = {} if channel == "depth" and "channel" in result and "depth" in result["channel"]: # print(result) bids, asks = [], [] for i in range(len(result["data"]["bids"])): bids.append(list(map(float, [result["data"]["bids"][i][0], result["data"]["bids"][i][1]]))) asks.append(list(map(float, [result["data"]["asks"][i][0], result["data"]["asks"][i][1]]))) dict = {'asks': asks, 'bids': bids} # self.print_depth(dict) if channel == "ticker" and "channel" in result and "ticker" in result["channel"]: dict = {'bid': float(result["data"]["buy"]), 'ask': float(result["data"]["sell"]), 'last': float(result["data"]["last"])} if 'event' in result: pong = {"event" : "pong"} self.ws.send(json.dumps(pong)) return dict # websocket 接收数据 带 币种 组成字典,用于同频道多个币种的订阅,如三角套利 def websocket_fmt_multi(self, channel, data): result = json.loads(data)[0] dict = {} if 'event' in result: pong = {"event" : "pong"} self.ws.send(json.dumps(pong)) if channel == "depth" and "data" in result and "depth" in result["channel"] and "bids" in result["data"] and "asks" in result["data"]: symbol = result['channel'].split("spot_")[-1].split("_depth")[0].upper() # symbol = result['channel'].replace("_depth_5","").replace("ok_sub_spot_","").upper() values = self.websocket_fmt(channel, data) dict = {symbol: values} return dict
  • 相关阅读:
    未来开发构想:
    3种方式遍历repeater中的CheckBox全选
    [常见面试题]一条Sql语句:取出表A中第31到第40记录,ID可能不是连续的
    mpc源代码下载,编译,调试
    哈希表(Hashtable)使用
    ASP.NET常用代码
    [转]Erwin4.1.4与PowerDesign9.5
    Three things everyone should know to improve object retrieval
    Learning the parts of objects by nonnegative matrix factorization (Letters to Nature)
    js 钟表
  • 原文地址:https://www.cnblogs.com/bitquant/p/okex-api-v1.html
Copyright © 2011-2022 走看看