From 2faac219a0ed0582f34b38d4c6a8fc92eb96c5e2 Mon Sep 17 00:00:00 2001 From: "vn.py" Date: Thu, 27 Dec 2018 16:44:44 +0800 Subject: [PATCH] =?UTF-8?q?[Mod]=E5=AE=8C=E6=88=90=E7=81=AB=E5=B8=81?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3=E7=9A=84=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/CryptoTrader/HUOBI_connect.json | 1 - .../gateway/huobiGateway/HUOBI_connect.json | 5 + .../gateway/huobiGateway/huobiGateway.py | 177 +++++++++--------- 3 files changed, 89 insertions(+), 94 deletions(-) create mode 100644 vnpy/trader/gateway/huobiGateway/HUOBI_connect.json diff --git a/examples/CryptoTrader/HUOBI_connect.json b/examples/CryptoTrader/HUOBI_connect.json index 8255a46f..a71346fa 100644 --- a/examples/CryptoTrader/HUOBI_connect.json +++ b/examples/CryptoTrader/HUOBI_connect.json @@ -1,5 +1,4 @@ { - "exchange": "huobi", "accessKey": "", "secretKey": "", "symbols": ["btcusdt","ethusdt","ethbtc"] diff --git a/vnpy/trader/gateway/huobiGateway/HUOBI_connect.json b/vnpy/trader/gateway/huobiGateway/HUOBI_connect.json new file mode 100644 index 00000000..a71346fa --- /dev/null +++ b/vnpy/trader/gateway/huobiGateway/HUOBI_connect.json @@ -0,0 +1,5 @@ +{ + "accessKey": "", + "secretKey": "", + "symbols": ["btcusdt","ethusdt","ethbtc"] +} \ No newline at end of file diff --git a/vnpy/trader/gateway/huobiGateway/huobiGateway.py b/vnpy/trader/gateway/huobiGateway/huobiGateway.py index 65d3b055..2c7a991d 100644 --- a/vnpy/trader/gateway/huobiGateway/huobiGateway.py +++ b/vnpy/trader/gateway/huobiGateway/huobiGateway.py @@ -26,6 +26,18 @@ WEBSOCKET_MARKET_HOST = 'wss://api.huobi.pro/ws' # Global站行情 WEBSOCKET_TRADE_HOST = 'wss://api.huobi.pro/ws/v1' # 资产和订单 +# 委托状态类型映射 +statusMapReverse = {} +statusMapReverse['pre-submitted'] = STATUS_UNKNOWN +statusMapReverse['submitting'] = STATUS_UNKNOWN +statusMapReverse['submitted'] = STATUS_NOTTRADED +statusMapReverse['partial-filled'] = STATUS_PARTTRADED +statusMapReverse['partial-canceled'] = STATUS_CANCELLED +statusMapReverse['filled'] = STATUS_ALLTRADED +statusMapReverse['canceled'] = STATUS_CANCELLED + + + #---------------------------------------------------------------------- def _split_url(url): """ @@ -226,6 +238,7 @@ class HuobiRestApi(RestClient): self.accountid = '' # self.cancelReqDict = {} + self.orderBufDict = {} #---------------------------------------------------------------------- def sign(self, request): @@ -243,6 +256,9 @@ class HuobiRestApi(RestClient): if request.method == "POST": request.headers['Content-Type'] = 'application/json' + if request.data: + request.data = json.dumps(request.data) + return request #---------------------------------------------------------------------- @@ -316,6 +332,25 @@ class HuobiRestApi(RestClient): path = '/v1/order/orders/place' self.addRequest('POST', path, self.onSendOrder, data=params, extra=localID) + + # 缓存委托 + order = VtOrderData() + order.gatewayName = self.gatewayName + + order.orderID = localID + order.vtOrderID = '.'.join([order.gatewayName, order.orderID]) + + order.symbol = orderReq.symbol + order.exchange = EXCHANGE_HUOBI + order.vtSymbol = '.'.join([order.symbol, order.exchange]) + + order.price = orderReq.price + order.totalVolume = orderReq.volume + order.direction = orderReq.direction + order.offset = OFFSET_NONE + order.status = STATUS_UNKNOWN + + self.orderBufDict[localID] = order # 返回订单号 return vtOrderID @@ -323,7 +358,7 @@ class HuobiRestApi(RestClient): #---------------------------------------------------------------------- def cancelOrder(self, cancelReq): """""" - localID = cancelOrderReq.orderID + localID = cancelReq.orderID orderID = self.localOrderDict.get(localID, None) if orderID: @@ -333,7 +368,7 @@ class HuobiRestApi(RestClient): if localID in self.cancelReqDict: del self.cancelReqDict[localID] else: - self.cancelReqDict[localID] = cancelOrderReq + self.cancelReqDict[localID] = cancelReq #---------------------------------------------------------------------- def onQueryAccount(self, data, request): # type: (dict, Request)->None @@ -397,8 +432,8 @@ class HuobiRestApi(RestClient): orderID = d['id'] strOrderID = str(orderID) - self.localID += 1 - localID = str(self.localID) + self.gateway.localID += 1 + localID = str(self.gateway.localID) self.orderLocalDict[strOrderID] = localID self.localOrderDict[localID] = strOrderID @@ -428,7 +463,7 @@ class HuobiRestApi(RestClient): if d['canceled-at']: order.cancelTime = datetime.fromtimestamp(d['canceled-at']/1000).strftime('%H:%M:%S') - self.orderDict[orderID] = order + self.orderDict[strOrderID] = order self.gateway.onOrder(order) #---------------------------------------------------------------------- @@ -462,17 +497,24 @@ class HuobiRestApi(RestClient): #---------------------------------------------------------------------- def onSendOrder(self, data, request): # type: (dict, Request)->None """""" - print('on send order', data) + localID = request.extra + order = self.orderBufDict[localID] status = data.get('status', None) + if status == 'error': msg = u'错误代码:%s, 错误信息:%s' %(data['err-code'], data['err-msg']) self.gateway.writeLog(msg) - return + + order.status = STATUS_REJECTED + self.gateway.onOrder(order) + return - localID = request.extra - orderID = data - self.localOrderDict[localID] = orderID + orderID = data['data'] + strOrderID = str(orderID) + + self.localOrderDict[localID] = strOrderID + self.orderDict[strOrderID] = order req = self.cancelReqDict.get(localID, None) if req: @@ -551,7 +593,6 @@ class HuobiWebsocketApiBase(WebsocketClient): return if 'err-msg' in packet: - print(packet) return self.onErrorMsg(packet) if "op" in packet and packet["op"] == "auth": @@ -664,7 +705,7 @@ class HuobiTradeWebsocketApi(HuobiWebsocketApiBase): #---------------------------------------------------------------------- def onOrder(self, data): """""" - orderID = data['id'] + orderID = data['order-id'] strOrderID = str(orderID) order = self.orderDict.get(strOrderID, None) @@ -690,102 +731,40 @@ class HuobiTradeWebsocketApi(HuobiWebsocketApiBase): dt = datetime.fromtimestamp(data['created-at']/1000) order.orderTime = dt.strftime('%H:%M:%S') + + if 'buy' in data['order-type']: + order.direction = DIRECTION_LONG + else: + order.direction = DIRECTION_SHORT + order.offset = OFFSET_NONE + + self.orderDict[strOrderID] = order order.tradedVolume += float(data['filled-amount']) order.status = statusMapReverse.get(data['order-state'], STATUS_UNKNOWN) - self.gateway.onOrder(order) - - trade = VtTradeData() - trade.gatewayName = self.gatewayName - - trade.tradeID = data['seq-id'] - trade.vtTradeID = '.'.join([trade.tradeID, trade.gatewayName]) - - trade.symbol = data['symbol'] - trade.exchange = EXCHANGE_HUOBI - trade.vtSymbol = '.'.join([trade.symbol, trade.exchange]) - trade.direction = order.direction - trade.offset = order.offset - trade.orderID = order.orderID - trade.vtOrderID = order.vtOrderID - - trade.price = float(data['price']) - trade.volume = float(data['filled-amount']) - - dt = datetime.now() - trade.tradeTime = dt.strftime('%H:%M:%S') - - self.gateway.onTrade(trade) - - #---------------------------------------------------------------------- - def onOrderOld(self, data): - """""" - orderID = data['id'] - strOrderID = str(orderID) - - newTrade = False - order = self.orderDict.get(strOrderID, None) - - if not order: - self.gateway.localID += 1 - localID = str(self.gateway.localID) - - self.orderLocalDict[strOrderID] = localID - self.localOrderDict[localID] = strOrderID - - order = VtOrderData() - order.gatewayName = self.gatewayName - - order.orderID = localID - order.vtOrderID = '.'.join([order.gatewayName, order.orderID]) - - order.symbol = data['symbol'] - order.exchange = EXCHANGE_HUOBI - order.vtSymbol = '.'.join([order.symbol, order.exchange]) - - order.price = float(data['order-price']) - order.totalVolume = float(data['order-amount']) - - dt = datetime.fromtimestamp(data['created-at']/1000) - order.orderTime = dt.strftime('%H:%M:%S') - else: - oldTradedVolume = order.tradedVolume - if oldTradedVolume != float(data['filled-amount']): - newTrade = True - - order.tradedVolume = float(data['filled-amount']) - order.status = statusMapReverse.get(data['order-state'], STATUS_UNKNOWN) - - self.gateway.onOrder(order) - - if newTrade: + if float(data['filled-amount']): trade = VtTradeData() trade.gatewayName = self.gatewayName - - trade.tradeID = data['seq-id'] + + trade.tradeID = str(data['seq-id']) trade.vtTradeID = '.'.join([trade.tradeID, trade.gatewayName]) - + trade.symbol = data['symbol'] trade.exchange = EXCHANGE_HUOBI trade.vtSymbol = '.'.join([trade.symbol, trade.exchange]) - - if 'buy' in data['order-type']: - trade.direction = DIRECTION_LONG - else: - trade.direction = DIRECTION_SHORT - trade.offset = OFFSET_NONE - + trade.direction = order.direction + trade.offset = order.offset trade.orderID = order.orderID trade.vtOrderID = order.vtOrderID trade.price = float(data['price']) - trade.volume = order.tradedVolume - oldTradedVolume - - dt = datetime.fromtimestamp(d['created-at']/1000) + trade.volume = float(data['filled-amount']) + + dt = datetime.now() trade.tradeTime = dt.strftime('%H:%M:%S') - + self.gateway.onTrade(trade) @@ -905,4 +884,16 @@ class HuobiMarketWebsocketApi(HuobiWebsocketApiBase): if tick.bidPrice1: newtick = copy(tick) - self.gateway.onTick(newtick) \ No newline at end of file + self.gateway.onTick(newtick) + + + +#---------------------------------------------------------------------- +def printDict(d): + """""" + print('-' * 30) + l = d.keys() + l.sort() + for k in l: + print(type(k), k, d[k]) + \ No newline at end of file