[Mod]完成火币接口的测试
This commit is contained in:
parent
a4614a6f27
commit
2faac219a0
@ -1,5 +1,4 @@
|
|||||||
{
|
{
|
||||||
"exchange": "huobi",
|
|
||||||
"accessKey": "",
|
"accessKey": "",
|
||||||
"secretKey": "",
|
"secretKey": "",
|
||||||
"symbols": ["btcusdt","ethusdt","ethbtc"]
|
"symbols": ["btcusdt","ethusdt","ethbtc"]
|
||||||
|
5
vnpy/trader/gateway/huobiGateway/HUOBI_connect.json
Normal file
5
vnpy/trader/gateway/huobiGateway/HUOBI_connect.json
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"accessKey": "",
|
||||||
|
"secretKey": "",
|
||||||
|
"symbols": ["btcusdt","ethusdt","ethbtc"]
|
||||||
|
}
|
@ -26,6 +26,18 @@ WEBSOCKET_MARKET_HOST = 'wss://api.huobi.pro/ws' # Global站行情
|
|||||||
WEBSOCKET_TRADE_HOST = 'wss://api.huobi.pro/ws/v1' # 资产和订单
|
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):
|
def _split_url(url):
|
||||||
"""
|
"""
|
||||||
@ -226,6 +238,7 @@ class HuobiRestApi(RestClient):
|
|||||||
|
|
||||||
self.accountid = '' #
|
self.accountid = '' #
|
||||||
self.cancelReqDict = {}
|
self.cancelReqDict = {}
|
||||||
|
self.orderBufDict = {}
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
def sign(self, request):
|
def sign(self, request):
|
||||||
@ -243,6 +256,9 @@ class HuobiRestApi(RestClient):
|
|||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
request.headers['Content-Type'] = 'application/json'
|
request.headers['Content-Type'] = 'application/json'
|
||||||
|
|
||||||
|
if request.data:
|
||||||
|
request.data = json.dumps(request.data)
|
||||||
|
|
||||||
return request
|
return request
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
@ -316,6 +332,25 @@ class HuobiRestApi(RestClient):
|
|||||||
path = '/v1/order/orders/place'
|
path = '/v1/order/orders/place'
|
||||||
self.addRequest('POST', path, self.onSendOrder,
|
self.addRequest('POST', path, self.onSendOrder,
|
||||||
data=params, extra=localID)
|
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
|
return vtOrderID
|
||||||
@ -323,7 +358,7 @@ class HuobiRestApi(RestClient):
|
|||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
def cancelOrder(self, cancelReq):
|
def cancelOrder(self, cancelReq):
|
||||||
""""""
|
""""""
|
||||||
localID = cancelOrderReq.orderID
|
localID = cancelReq.orderID
|
||||||
orderID = self.localOrderDict.get(localID, None)
|
orderID = self.localOrderDict.get(localID, None)
|
||||||
|
|
||||||
if orderID:
|
if orderID:
|
||||||
@ -333,7 +368,7 @@ class HuobiRestApi(RestClient):
|
|||||||
if localID in self.cancelReqDict:
|
if localID in self.cancelReqDict:
|
||||||
del self.cancelReqDict[localID]
|
del self.cancelReqDict[localID]
|
||||||
else:
|
else:
|
||||||
self.cancelReqDict[localID] = cancelOrderReq
|
self.cancelReqDict[localID] = cancelReq
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
def onQueryAccount(self, data, request): # type: (dict, Request)->None
|
def onQueryAccount(self, data, request): # type: (dict, Request)->None
|
||||||
@ -397,8 +432,8 @@ class HuobiRestApi(RestClient):
|
|||||||
orderID = d['id']
|
orderID = d['id']
|
||||||
strOrderID = str(orderID)
|
strOrderID = str(orderID)
|
||||||
|
|
||||||
self.localID += 1
|
self.gateway.localID += 1
|
||||||
localID = str(self.localID)
|
localID = str(self.gateway.localID)
|
||||||
|
|
||||||
self.orderLocalDict[strOrderID] = localID
|
self.orderLocalDict[strOrderID] = localID
|
||||||
self.localOrderDict[localID] = strOrderID
|
self.localOrderDict[localID] = strOrderID
|
||||||
@ -428,7 +463,7 @@ class HuobiRestApi(RestClient):
|
|||||||
if d['canceled-at']:
|
if d['canceled-at']:
|
||||||
order.cancelTime = datetime.fromtimestamp(d['canceled-at']/1000).strftime('%H:%M:%S')
|
order.cancelTime = datetime.fromtimestamp(d['canceled-at']/1000).strftime('%H:%M:%S')
|
||||||
|
|
||||||
self.orderDict[orderID] = order
|
self.orderDict[strOrderID] = order
|
||||||
self.gateway.onOrder(order)
|
self.gateway.onOrder(order)
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
@ -462,17 +497,24 @@ class HuobiRestApi(RestClient):
|
|||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
def onSendOrder(self, data, request): # type: (dict, Request)->None
|
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)
|
status = data.get('status', None)
|
||||||
|
|
||||||
if status == 'error':
|
if status == 'error':
|
||||||
msg = u'错误代码:%s, 错误信息:%s' %(data['err-code'], data['err-msg'])
|
msg = u'错误代码:%s, 错误信息:%s' %(data['err-code'], data['err-msg'])
|
||||||
self.gateway.writeLog(msg)
|
self.gateway.writeLog(msg)
|
||||||
return
|
|
||||||
|
order.status = STATUS_REJECTED
|
||||||
|
self.gateway.onOrder(order)
|
||||||
|
return
|
||||||
|
|
||||||
localID = request.extra
|
orderID = data['data']
|
||||||
orderID = data
|
strOrderID = str(orderID)
|
||||||
self.localOrderDict[localID] = orderID
|
|
||||||
|
self.localOrderDict[localID] = strOrderID
|
||||||
|
self.orderDict[strOrderID] = order
|
||||||
|
|
||||||
req = self.cancelReqDict.get(localID, None)
|
req = self.cancelReqDict.get(localID, None)
|
||||||
if req:
|
if req:
|
||||||
@ -551,7 +593,6 @@ class HuobiWebsocketApiBase(WebsocketClient):
|
|||||||
return
|
return
|
||||||
|
|
||||||
if 'err-msg' in packet:
|
if 'err-msg' in packet:
|
||||||
print(packet)
|
|
||||||
return self.onErrorMsg(packet)
|
return self.onErrorMsg(packet)
|
||||||
|
|
||||||
if "op" in packet and packet["op"] == "auth":
|
if "op" in packet and packet["op"] == "auth":
|
||||||
@ -664,7 +705,7 @@ class HuobiTradeWebsocketApi(HuobiWebsocketApiBase):
|
|||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
def onOrder(self, data):
|
def onOrder(self, data):
|
||||||
""""""
|
""""""
|
||||||
orderID = data['id']
|
orderID = data['order-id']
|
||||||
strOrderID = str(orderID)
|
strOrderID = str(orderID)
|
||||||
order = self.orderDict.get(strOrderID, None)
|
order = self.orderDict.get(strOrderID, None)
|
||||||
|
|
||||||
@ -690,102 +731,40 @@ class HuobiTradeWebsocketApi(HuobiWebsocketApiBase):
|
|||||||
|
|
||||||
dt = datetime.fromtimestamp(data['created-at']/1000)
|
dt = datetime.fromtimestamp(data['created-at']/1000)
|
||||||
order.orderTime = dt.strftime('%H:%M:%S')
|
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.tradedVolume += float(data['filled-amount'])
|
||||||
order.status = statusMapReverse.get(data['order-state'], STATUS_UNKNOWN)
|
order.status = statusMapReverse.get(data['order-state'], STATUS_UNKNOWN)
|
||||||
|
|
||||||
self.gateway.onOrder(order)
|
self.gateway.onOrder(order)
|
||||||
|
|
||||||
|
if float(data['filled-amount']):
|
||||||
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:
|
|
||||||
trade = VtTradeData()
|
trade = VtTradeData()
|
||||||
trade.gatewayName = self.gatewayName
|
trade.gatewayName = self.gatewayName
|
||||||
|
|
||||||
trade.tradeID = data['seq-id']
|
trade.tradeID = str(data['seq-id'])
|
||||||
trade.vtTradeID = '.'.join([trade.tradeID, trade.gatewayName])
|
trade.vtTradeID = '.'.join([trade.tradeID, trade.gatewayName])
|
||||||
|
|
||||||
trade.symbol = data['symbol']
|
trade.symbol = data['symbol']
|
||||||
trade.exchange = EXCHANGE_HUOBI
|
trade.exchange = EXCHANGE_HUOBI
|
||||||
trade.vtSymbol = '.'.join([trade.symbol, trade.exchange])
|
trade.vtSymbol = '.'.join([trade.symbol, trade.exchange])
|
||||||
|
trade.direction = order.direction
|
||||||
if 'buy' in data['order-type']:
|
trade.offset = order.offset
|
||||||
trade.direction = DIRECTION_LONG
|
|
||||||
else:
|
|
||||||
trade.direction = DIRECTION_SHORT
|
|
||||||
trade.offset = OFFSET_NONE
|
|
||||||
|
|
||||||
trade.orderID = order.orderID
|
trade.orderID = order.orderID
|
||||||
trade.vtOrderID = order.vtOrderID
|
trade.vtOrderID = order.vtOrderID
|
||||||
|
|
||||||
trade.price = float(data['price'])
|
trade.price = float(data['price'])
|
||||||
trade.volume = order.tradedVolume - oldTradedVolume
|
trade.volume = float(data['filled-amount'])
|
||||||
|
|
||||||
dt = datetime.fromtimestamp(d['created-at']/1000)
|
dt = datetime.now()
|
||||||
trade.tradeTime = dt.strftime('%H:%M:%S')
|
trade.tradeTime = dt.strftime('%H:%M:%S')
|
||||||
|
|
||||||
self.gateway.onTrade(trade)
|
self.gateway.onTrade(trade)
|
||||||
|
|
||||||
|
|
||||||
@ -905,4 +884,16 @@ class HuobiMarketWebsocketApi(HuobiWebsocketApiBase):
|
|||||||
|
|
||||||
if tick.bidPrice1:
|
if tick.bidPrice1:
|
||||||
newtick = copy(tick)
|
newtick = copy(tick)
|
||||||
self.gateway.onTick(newtick)
|
self.gateway.onTick(newtick)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
def printDict(d):
|
||||||
|
""""""
|
||||||
|
print('-' * 30)
|
||||||
|
l = d.keys()
|
||||||
|
l.sort()
|
||||||
|
for k in l:
|
||||||
|
print(type(k), k, d[k])
|
||||||
|
|
Loading…
Reference in New Issue
Block a user