From c9c4b81ea4bf1c50cdeee0a70795bae8faef6317 Mon Sep 17 00:00:00 2001 From: msincenselee Date: Wed, 30 May 2018 11:20:08 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vnpy/api/binance/client.py | 11 +- vnpy/api/binance/exceptions.py | 10 +- vnpy/api/binance/vnbinance.py | 20 +- vnpy/trader/VT_setting.json | 2 +- .../gateway/binanceGateway/binanceGateway.py | 33 +- .../trader/gateway/okexGateway/okexGateway.py | 469 ++++++++++++------ 6 files changed, 375 insertions(+), 170 deletions(-) diff --git a/vnpy/api/binance/client.py b/vnpy/api/binance/client.py index b30df1ae..0f37fe2f 100644 --- a/vnpy/api/binance/client.py +++ b/vnpy/api/binance/client.py @@ -126,28 +126,32 @@ class Client(object): return params def _request(self, method, uri, signed, force_params=False, **kwargs): - data = kwargs.get('data', None) + #if data is None: + # kwargs['data'] = data if data and isinstance(data, dict): kwargs['data'] = data + if signed: + if data is None: + kwargs['data'] = {} # generate signature kwargs['data']['timestamp'] = int(time.time() * 1000) kwargs['data']['recvWindow'] = 20000 kwargs['data']['signature'] = self._generate_signature(kwargs['data']) - if data and (method == 'get' or force_params): kwargs['params'] = self._order_params(kwargs['data']) del(kwargs['data']) # kwargs["verify"] = False # I don't know whay this is error - + print('_request:method:{} uri:{},{}'.format(method, uri, kwargs)) response = getattr(self.session, method)(uri, **kwargs ) return self._handle_response(response , uri , **kwargs ) def _request_api(self, method, path, signed=False, version=PUBLIC_API_VERSION, **kwargs): uri = self._create_api_uri(path, signed, version) + return self._request(method, uri, signed, **kwargs) def _request_withdraw_api(self, method, path, signed=False, **kwargs): @@ -393,6 +397,7 @@ class Client(object): :raises: BinanceResponseException, BinanceAPIException """ + return self._get('depth', data=params) def get_recent_trades(self, **params): diff --git a/vnpy/api/binance/exceptions.py b/vnpy/api/binance/exceptions.py index 23bef301..40dd00f7 100644 --- a/vnpy/api/binance/exceptions.py +++ b/vnpy/api/binance/exceptions.py @@ -5,21 +5,25 @@ class BinanceAPIException(Exception): LISTENKEY_NOT_EXIST = '-1125' - def __init__(self, response): + def __init__(self, response, uri, **kwargs): json_res = response.json() self.status_code = response.status_code self.response = response self.code = json_res['code'] self.message = json_res['msg'] self.request = getattr(response, 'request', None) + self.kwargs = kwargs + self.uri = uri def __str__(self): # pragma: no cover return 'APIError(code=%s): %s' % (self.code, self.message) - class BinanceRequestException(Exception): - def __init__(self, message): + + def __init__(self, message, uri, **kwargs): self.message = message + self.kwargs = kwargs + self.uri = uri def __str__(self): return 'BinanceRequestException: %s' % self.message diff --git a/vnpy/api/binance/vnbinance.py b/vnpy/api/binance/vnbinance.py index 64f744f3..58495388 100644 --- a/vnpy/api/binance/vnbinance.py +++ b/vnpy/api/binance/vnbinance.py @@ -101,17 +101,16 @@ class BinanceSpotApi(object): self.active = True self.reqThread.start() - #---------------------------------------------------------------------- def processQueue(self): """处理请求队列中的请求""" while self.active: - try: - #req = self.reqQueue.get(block=True, timeout=0.001) # 获取请求的阻塞为一秒 - if len(self.reqQueue) == 0: - continue - (Type , req) = self.reqQueue[0] + #req = self.reqQueue.get(block=True, timeout=0.001) # 获取请求的阻塞为一秒 + if len(self.reqQueue) == 0: + continue + (Type , req) = self.reqQueue[0] + try: callback = req['callback'] reqID = req['reqID'] @@ -126,7 +125,12 @@ class BinanceSpotApi(object): print(u'processQueue exception:{},{}'.format(str(ex), traceback.format_exc()), file=sys.stderr) self.reqQueue.pop(0) sleep(0.1) + #except BinanceAPIException as ex: + # print(u'BinanceAPIException:{},{}'.format( str(ex),traceback.format_exc()),file=sys.stderr) + #except BinanceRequestException as ex: + # print(u'BinanceRequestException:{},{}'.format(str(ex), traceback.format_exc()), file=sys.stderr) except Exception as ex: + self.onAllError(ex,req,reqID) print(u'processQueue exception:{},{}'.format(str(ex), traceback.format_exc()), file=sys.stderr) #---------------------------------------------------------------------- @@ -227,7 +231,9 @@ class BinanceSpotApi(object): callback(data , req , reqID) except Exception as ex: - print(u'processQueue exception:{},{}'.format(str(ex), traceback.format_exc()), file=sys.stderr) + if req is not None or reqID is not None: + self.onAllError(ex, req, reqID) + print(u'processRequest exception:{},{}'.format(str(ex), traceback.format_exc()), file=sys.stderr) # pass #---------------------------------------------------------------------- diff --git a/vnpy/trader/VT_setting.json b/vnpy/trader/VT_setting.json index 8c59a6d1..fa3295eb 100644 --- a/vnpy/trader/VT_setting.json +++ b/vnpy/trader/VT_setting.json @@ -2,7 +2,7 @@ "fontFamily": "微软雅黑", "fontSize": 12, - "mongoHost": "mongodb://vnpy:vnpy@localhost", + "mongoHost": "localhost", "mongoPort": 27017, "mongoLogging": true, "darkStyle": true, diff --git a/vnpy/trader/gateway/binanceGateway/binanceGateway.py b/vnpy/trader/gateway/binanceGateway/binanceGateway.py index 8ef39c80..a5aefc74 100644 --- a/vnpy/trader/gateway/binanceGateway/binanceGateway.py +++ b/vnpy/trader/gateway/binanceGateway/binanceGateway.py @@ -16,7 +16,7 @@ import json from datetime import datetime , timedelta import time -from vnpy.api.binance import BinanceSpotApi +from vnpy.api.binance import BinanceSpotApi,BinanceAPIException,BinanceRequestException from vnpy.trader.vtGateway import * from vnpy.trader.vtFunction import getJsonPath from vnpy.trader.gateway.binanceGateway.DigitalCurrency import systemSymbolToVnSymbol , VnSymbolToSystemSymbol @@ -238,10 +238,26 @@ class BinanceApi(BinanceSpotApi): symbol = (req.vtSymbol.split('.'))[0] self.gateway.writeLog( "send order %s,%s,%s,%s" % (req.vtSymbol , str(req.direction) , str(req.price) , str(req.volume) )) - if req.direction == DIRECTION_LONG: - reqID = self.spotTrade(symbol_pair=symbol, type_="buy", price=float(req.price), amount=req.volume) - else: - reqID = self.spotTrade(symbol_pair=symbol, type_="sell", price=float(req.price), amount=req.volume) + + try: + reqID = self.spotTrade(symbol_pair=symbol, type_="buy" if req.direction == DIRECTION_LONG else "sell", price=float(req.price), amount=req.volume) + + except BinanceAPIException as ex: + self.gateway.writeError(content=ex.message, error_id=ex.code) + self.gateway.writeLog(traceback.format_exc()) + return None + except BinanceRequestException as ex: + self.gateway.writeError(content=ex.message) + self.gateway.writeLog(traceback.format_exc()) + return None + except Exception as ex: + self.gateway.writeError(str(ex)) + self.gateway.writeLog(traceback.format_exc()) + return None + + if reqID is None: + self.gateway.writeError(u'委托异常: %s,%s,%s,%s'.format(req.vtSymbol , str(req.direction) , str(req.price) , str(req.volume) )) + return None self.localID += 1 localID = str(self.localID) @@ -269,7 +285,7 @@ class BinanceApi(BinanceSpotApi): self.workingOrderDict[localID] = order self.reqToLocalID[reqID] = localID - # self.gateway.onOrder(order) + self.gateway.onOrder(order) # 返回委托号 return order.vtOrderID @@ -285,7 +301,8 @@ print ex.status_code, ex.message , ex.code , ex.request , ex.uri , ex.kwargs """ # ---------------------------------------------------------------------- def onAllError(self, ex , req , reqID): - self.gateway.writeError( ex.message + " " + ex.uri , ex.status_code) + + self.gateway.writeError(content=str(ex) + ' ' + getattr(ex,'uri',''),error_id=getattr(ex,'status_code',0)) # 判断是否应该是 发出的无效订单 localID = self.reqToLocalID.get( reqID , None) @@ -378,6 +395,8 @@ print ex.status_code, ex.message , ex.code , ex.request , ex.uri , ex.kwargs contract.size = float(volume_filter["stepSize"]) contract.priceTick = float(price_filter["tickSize"]) contract.productClass = PRODUCT_SPOT + contract.volumeTick = float(volume_filter["minQty"]) + self.gateway.onContract(contract) #---------------------------------------------------------------------- diff --git a/vnpy/trader/gateway/okexGateway/okexGateway.py b/vnpy/trader/gateway/okexGateway/okexGateway.py index 6dbee407..f98df5c3 100644 --- a/vnpy/trader/gateway/okexGateway/okexGateway.py +++ b/vnpy/trader/gateway/okexGateway/okexGateway.py @@ -23,7 +23,7 @@ from vnpy.api.okex.okexData import SPOT_TRADE_SIZE_DICT, SPOT_ERROR_DICT, FUTURE from vnpy.trader.vtGateway import * from vnpy.trader.vtFunction import getJsonPath from vnpy.trader.vtConstant import EXCHANGE_OKEX, DIRECTION_NET, PRODUCT_SPOT, DIRECTION_LONG, DIRECTION_SHORT, PRICETYPE_LIMITPRICE, PRICETYPE_MARKETPRICE, OFFSET_OPEN, OFFSET_CLOSE -from vnpy.trader.vtConstant import STATUS_CANCELLED, STATUS_NOTTRADED, STATUS_PARTTRADED, STATUS_ALLTRADED, STATUS_UNKNOWN, PRODUCT_FUTURES +from vnpy.trader.vtConstant import STATUS_CANCELLED, STATUS_NOTTRADED, STATUS_PARTTRADED, STATUS_ALLTRADED, STATUS_UNKNOWN, STATUS_REJECTED, PRODUCT_FUTURES from vnpy.trader.vtObject import VtErrorData # 价格类型映射 @@ -48,6 +48,7 @@ statusMap[-1] = STATUS_CANCELLED # 撤单 statusMap[0] = STATUS_NOTTRADED # 未成交 statusMap[1] = STATUS_PARTTRADED # 部分成交 statusMap[2] = STATUS_ALLTRADED # 全部成交 +statusMap[3] = STATUS_UNKNOWN statusMap[4] = STATUS_UNKNOWN # 未知状态 EVENT_OKEX_INDEX_FUTURE = "eFuture_Index_OKEX" @@ -122,7 +123,7 @@ class OkexGateway(VtGateway): # 启动查询 self.initQuery() - #self.startQuery() + self.startQuery() def writeLog(self, content): """ @@ -148,6 +149,9 @@ class OkexGateway(VtGateway): if self.logger: self.logger.error(content) + def checkStatus(self): + return self.spot_connected or self.futures_connected + # ---------------------------------------------------------------------- def subscribe(self, subscribeReq): """ @@ -169,13 +173,18 @@ class OkexGateway(VtGateway): self.writeError(u'期货接口未创建/未连接,无法调用subscribe') except Exception as ex: - self.onError(u'OkexGateway.subscribe 异常,请检查日志') + self.writeError(u'OkexGateway.subscribe 异常,请检查日志:{}'.format(str(ex))) self.writeLog(u'OkexGateway.subscribe Exception :{},{}'.format(str(ex), traceback.format_exc())) # ---------------------------------------------------------------------- def sendOrder(self, orderReq): """发单""" - if orderReq.symbol in SPOT_SYMBOL: + + # btc_usdt.OKEX => btc_usdt + order_req_symbol = orderReq.symbol + order_req_symbol = order_req_symbol.replace('.{}'.format(EXCHANGE_OKEX),'') + + if order_req_symbol in SPOT_SYMBOL: if self.api_spot and self.spot_connected: return self.api_spot.spotSendOrder(orderReq) else: @@ -207,8 +216,8 @@ class OkexGateway(VtGateway): # ---------------------------------------------------------------------- def qryOrderInfo(self): - #if self.spot_connected: - # self.api_spot.spotAllOrders() + if self.spot_connected: + self.api_spot.spotAllOrders() if self.futures_connected: self.api_futures.futureAllUnfinishedOrderInfo() @@ -234,8 +243,8 @@ class OkexGateway(VtGateway): """初始化连续查询""" if self.qryEnabled: # 需要循环的查询函数列表 - # self.qryFunctionList = [self.qryAccount, self.qryOrderInfo] - self.qryFunctionList = [self.qryOrderInfo] + self.qryFunctionList = [self.qryAccount, self.qryOrderInfo] + #self.qryFunctionList = [self.qryOrderInfo] # self.qryFunctionList = [] self.qryCount = 0 # 查询触发倒计时 @@ -319,10 +328,11 @@ class OkexSpotApi(WsSpotApi): self.cbDict = {} # 回调函数字典 self.tickDict = {} # 缓存最新tick字典 self.orderDict = {} # 委托单字典 + self.localOrderDict = {} # 本地缓存的order_dict,key 是 localNo.gatewayName self.channelSymbolMap = {} # 请求数据类型与合约的映射字典 - self.localNo = 0 # 本地委托号 + self.localNo = 1 # 本地委托号 self.localNoQueue = Queue() # 未收到系统委托号的本地委托号队列 self.localNoDict = {} # key为本地委托号,value为系统委托号 self.orderIdDict = {} # key为系统委托号,value为本地委托号 @@ -330,7 +340,6 @@ class OkexSpotApi(WsSpotApi): self.recordOrderId_BefVolume = {} # 记录的之前处理的量 - self.cache_some_order = {} self.tradeID = 0 # 已登记的品种对队列 @@ -396,7 +405,7 @@ class OkexSpotApi(WsSpotApi): elif channel_value == 'addChannel': channel_data = data.get('data', {}) result = channel_data.get('result', False) - channel_value = channel_data["channel"] + channel_value = channel_data.get('channel', "") if result: self.gateway.writeLog(u'功能订阅请求:{} 成功:'.format(channel_value)) continue @@ -428,7 +437,7 @@ class OkexSpotApi(WsSpotApi): error.gatewayName = self.gatewayName if 'data' in data and 'error_code' in data['data']: error_code =data['data']['error_code'] - error.errorMsg = u'SpotApi 出错:{}'.format(SPOT_ERROR_DICT.get(error_code)) + error.errorMsg = u'SpotApi 出错:{}'.format(SPOT_ERROR_DICT.get(str(error_code))) error.errorID = error_code else: error.errorMsg = str(data) @@ -452,10 +461,10 @@ class OkexSpotApi(WsSpotApi): # 重新连接 if self.active: def reconnect(): - while not self.gateway.connected: + while not self.gateway.spot_connected: self.gateway.writeLog(u'等待10秒后重新连接') sleep(10) - if not self.gateway.connected: + if not self.gateway.spot_connected: self.reconnect() t = Thread(target=reconnect) @@ -517,11 +526,11 @@ class OkexSpotApi(WsSpotApi): self.spotOrderInfo(symbol, '-1') # 对已经发送委托,根据orderid,发出查询请求 - for orderId in self.orderIdDict.keys(): - order = self.orderDict.get(orderId, None) - if order != None: - symbol_pair = (order.symbol.split('.'))[0] - self.spotOrderInfo(symbol_pair, orderId) + #for orderId in self.orderIdDict.keys(): + # order = self.orderDict.get(orderId, None) + # if order != None: + # symbol_pair = (order.symbol.split('.'))[0] + # self.spotOrderInfo(symbol_pair, orderId) # ---------------------------------------------------------------------- def onOpen(self, ws): @@ -540,10 +549,18 @@ class OkexSpotApi(WsSpotApi): self.spotUserInfo() # 尝试订阅一个合约对 - self.subscribeSingleSymbol("etc_usdt") - self.subscribeSingleSymbol("btc_usdt") - self.subscribeSingleSymbol("eth_usdt") - self.subscribeSingleSymbol("ltc_usdt") + if len(self.registerSymbolPairArray) == 0: + #self.subscribeSingleSymbol("etc_usdt") + #self.subscribeSingleSymbol("btc_usdt") + self.registerSymbolPairArray.add('eth_usdt') + self.registerSymbolPairArray.add('btc_usdt') + self.registerSymbolPairArray.add('ltc_usdt') + + for symbol_pair in self.registerSymbolPairArray: + # 发起品种行情订阅请求 + self.subscribeSingleSymbol(symbol_pair) + # 查询该品种对的订单 + self.spotOrderInfo(symbol_pair, '-1') self.gateway.writeLog(u'SpotApi初始化合约信息') @@ -562,9 +579,9 @@ class OkexSpotApi(WsSpotApi): # 更新至数据引擎的合约信息 contract = VtContractData() contract.gatewayName = self.gatewayName - contract.symbol = symbol #'.'.join([contract.symbol, contract.exchange]) contract.exchange = EXCHANGE_OKEX - contract.vtSymbol = symbol #'.'.join([contract.symbol, contract.exchange]) + contract.symbol = '.'.join([symbol, contract.exchange]) + contract.vtSymbol = contract.symbol contract.name = u'现货%s' % symbol contract.size = 1 # 现货是1:1 contract.priceTick = 0.0001 @@ -669,8 +686,8 @@ class OkexSpotApi(WsSpotApi): if symbol not in self.tickDict: tick = VtTickData() tick.exchange = EXCHANGE_OKEX - tick.symbol = symbol # '.'.join([symbol, tick.exchange]) - tick.vtSymbol = symbol #'.'.join([symbol, tick.exchange]) + tick.symbol = '.'.join([symbol, tick.exchange]) + tick.vtSymbol = '.'.join([symbol, tick.exchange]) tick.gatewayName = self.gatewayName self.tickDict[symbol] = tick @@ -811,7 +828,7 @@ class OkexSpotApi(WsSpotApi): tick.askPrice4, tick.askVolume4 = data['asks'][-4] tick.askPrice5, tick.askVolume5 = data['asks'][-5] - tick.date, tick.time = self.generateDateTime(data['timestamp']) + tick.date, tick.time,tick.datetime = self.generateDateTime(data['timestamp']) # print "Depth", tick.date, tick.time # 推送tick事件 @@ -848,8 +865,8 @@ class OkexSpotApi(WsSpotApi): for symbol, position in data_info_freezed.items(): pos = VtPositionData() pos.gatewayName = self.gatewayName - pos.symbol = symbol #+ "." + EXCHANGE_OKEX - pos.vtSymbol = symbol #+ "." + EXCHANGE_OKEX + pos.symbol = symbol + "." + EXCHANGE_OKEX + pos.vtSymbol = symbol + "." + EXCHANGE_OKEX pos.direction = DIRECTION_NET pos.frozen = float(position) pos.position = pos.frozen + float(data_info_free.get(symbol, 0)) @@ -910,8 +927,8 @@ ltc":"0","bt1":"0","bt2":"0","iota":"0","pay":"0","storj":"0","gnt":"0","snt":"0 if symbol in data_info_funds['free']: pos = VtPositionData() pos.gatewayName = self.gatewayName - pos.symbol = symbol # + "." + EXCHANGE_OKEX - pos.vtSymbol = symbol #+ "." + EXCHANGE_OKEX + pos.symbol = symbol + "." + EXCHANGE_OKEX + pos.vtSymbol = symbol + "." + EXCHANGE_OKEX pos.vtPositionName = symbol pos.direction = DIRECTION_NET @@ -1008,27 +1025,38 @@ nel': u'ok_sub_spot_etc_usdt_order'} def onSpotSubOrder(self, ws_data): """ 交易委托更新回报(发生部分成交/全部成交/拒单/撤销时,API推送的回报) - :param ws_data:ws推送的委托更新数据 + :param ws_data:ws推送的单个委托更新数据 :return: """ - data = ws_data("data") + self.gateway.writeLog(u'SpotApi.onSpotSubOrder:{}'.format(ws_data)) + data = ws_data.get("data") if data is None: return # 本地和系统委托号 - orderId = str(data['orderId']) + ok_order_id = str(data['orderId']) - localNo = self.orderIdDict.get(orderId, None) + localNo = self.orderIdDict.get(ok_order_id, None) if localNo == None: - self.gateway.writeError(u'订单与本地委托无关联,不处理') + self.gateway.writeError(u'onSpotSubOrder:ok_order_id:{}与本地委托无关联,'.format(ok_order_id)) self.gateway.writeLog(data) - return + + localNo = str(self.localNo) + if ok_order_id not in self.orderIdDict: + # orderId 不在本地缓存中,需要增加一个绑定关系 + while str(self.localNo) in self.localNoDict: + self.localNo += 1 + localNo = str(self.localNo) + self.localNoDict[localNo] = ok_order_id + self.orderIdDict[ok_order_id] = localNo + self.gateway.writeLog(u'onFutureOrderInfo add orderid: local:{}<=>okex:{}'.format(localNo, ok_order_id)) # 委托信息 - if orderId not in self.orderDict: + if ok_order_id not in self.orderDict: + self.gateway.writeLog(u'onSpotSubOrder:添加至委托单缓存:{}'.format(data)) order = VtOrderData() order.gatewayName = self.gatewayName - order.symbol = data['symbol'] # '.'.join([rawData['symbol'], EXCHANGE_OKEX]) + order.symbol = '.'.join([data['symbol'], EXCHANGE_OKEX]) order.vtSymbol = order.symbol order.orderID = localNo @@ -1037,18 +1065,23 @@ nel': u'ok_sub_spot_etc_usdt_order'} order.price = float(data['tradeUnitPrice']) order.totalVolume = float(data['tradeAmount']) order.direction, priceType = priceTypeMap[data['tradeType']] - - self.orderDict[orderId] = order + order.offset = OFFSET_OPEN if order.direction == DIRECTION_LONG else OFFSET_CLOSE + create_date, order.orderTime,_ = self.generateDateTime(data['createdDate']) + self.orderDict[ok_order_id] = order else: - order = self.orderDict[orderId] + order = self.orderDict[ok_order_id] order.tradedVolume = float(data['completedTradeAmount']) order.status = statusMap[data['status']] + if order.status == STATUS_CANCELLED: + dt = datetime.now() + order.cancelTime = dt.strftime("%H:%M:%S.%f") # 推送onOrder event + self.gateway.writeLog(u'onSpotSubOrder:发出OnOrder,vtOrderId={},orderStatus:{}'.format(order.vtOrderID,order.status)) self.gateway.onOrder(copy(order)) - bef_volume = self.recordOrderId_BefVolume.get(orderId, 0.0) + bef_volume = self.recordOrderId_BefVolume.get(ok_order_id, 0.0) now_volume = float(data['completedTradeAmount']) - bef_volume if now_volume > 0.000001: @@ -1072,6 +1105,7 @@ nel': u'ok_sub_spot_etc_usdt_order'} trade.tradeTime = datetime.now().strftime('%H:%M:%S') # 推送onTrade事件 + self.gateway.writeLog(u'onSpotSubOrder:发出onTrader,vtOrderId={}'.format(trade.vtOrderID)) self.gateway.onTrade(trade) # ---------------------------------------------------------------------- @@ -1101,9 +1135,12 @@ nel': u'ok_sub_spot_etc_usdt_order'} def onSpotOrderInfo(self, ws_data): """ 所有委托信息查询响应 - :param ws_data: + self.spotOrderInfo(symbol_pair, '-1')时,返回symbol_pair所有未完成订单 + self.spotOrderInfo(symbol_pair, orderId)时,返回symbol_pair、orderId的订单 + :param ws_data:orders 清单 :return: """ + self.gateway.writeLog(u'SpApi.onSpotOrderInfo:{}'.format(ws_data)) # 获取channel的数据 data = ws_data.get('data', {}) @@ -1111,26 +1148,41 @@ nel': u'ok_sub_spot_etc_usdt_order'} orders = data.get('orders', []) for data_order in orders: - self.localNo += 1 # 本地序列号自增长 - localNo = str(self.localNo) # int =》 str + ok_order_id = data_order.get('order_id') + if ok_order_id is None: + ok_order_id = data_order.get('orders_id') - order_id = data_order.get('order_id') # 服务端的委托单编号 - if order_id is None: - self.gateway.writeError(u'SpotApi.onSpotOrderInfo,取order_id/orderId异常,请查日志') - self.gateway.writeLog(u'data_order:{}'.format(data_order)) + if ok_order_id is None: + self.gateway.writeError(u'提取order_id出错') continue + ok_order_id = str(ok_order_id) - orderId = str(order_id) # int =》 str + localNo = str(self.localNo) - self.localNoDict[localNo] = orderId # 建立本地序列号与服务端序列号的相互映射 - self.orderIdDict[orderId] = localNo + if ok_order_id not in self.orderIdDict: + # orderId 不在本地缓存中,需要增加一个绑定关系 + while str(self.localNo) in self.localNoDict: + self.localNo += 1 + localNo = str(self.localNo) + # 绑定localNo 与 orderId + self.localNoDict[localNo] = ok_order_id + self.orderIdDict[ok_order_id] = localNo + self.gateway.writeLog(u'onFutureOrderInfo add orderid: local:{}<=>okex:{}'.format(localNo, ok_order_id)) + else: + # orderid在本地缓存中, + localNo = self.orderIdDict[ok_order_id] + # 检验 localNo是否在本地缓存,没有则补充 + if localNo not in self.localNoDict: + self.localNoDict[localNo] = ok_order_id + self.gateway.writeLog(u'onFutureOrderInfo update orderid: local:{}<=>okex:{}'.format(localNo, ok_order_id)) - if orderId not in self.orderDict: # 不在本地委托单缓存时,添加 + if ok_order_id not in self.orderDict: # 不在本地委托单缓存时,添加 + self.gateway.writeLog(u'onSpotOrderInfo:添加至委托单缓存:{}'.format(data_order)) order = VtOrderData() order.gatewayName = self.gatewayName # order.symbol = spotSymbolMap[d['symbol']] - order.symbol = data_order["symbol"] # '.'.join([d["symbol"], EXCHANGE_OKEX]) + order.symbol = '.'.join([data_order["symbol"], EXCHANGE_OKEX]) order.vtSymbol = order.symbol order.orderID = localNo @@ -1139,14 +1191,14 @@ nel': u'ok_sub_spot_etc_usdt_order'} order.price = data_order['price'] order.totalVolume = data_order['amount'] order.direction, priceType = priceTypeMap[data_order['type']] - - self.orderDict[orderId] = order + create_date, order.orderTime,_ = self.generateDateTime(data_order['create_date']) + self.orderDict[ok_order_id] = order else: - order = self.orderDict[orderId] # 使用本地缓存 + order = self.orderDict[ok_order_id] # 使用本地缓存 order.tradedVolume = data_order['deal_amount'] # 更新成交数量 order.status = statusMap[data_order['status']] # 更新成交状态 - + self.gateway.writeLog('orderId:{},tradedVolume:{},status:{}'.format(order.vtOrderID,order.tradedVolume,order.status)) self.gateway.onOrder(copy(order)) # 提交onOrder事件 # ---------------------------------------------------------------------- @@ -1166,17 +1218,27 @@ nel': u'ok_sub_spot_etc_usdt_order'} :param ws_data: :return: """ + self.gateway.writeLog(u'SpotApi.onSpotOrder:{}'.format(ws_data)) data = ws_data.get('data', {}) if 'error_code' in data: error_id = data.get('error_code') - self.gateway.writeError(u'SpotApi.onSpotOrder 委托返回错误:{}'.format(SPOT_ERROR_DICT.get(error_id)), error_id=error_id) + self.gateway.writeError(u'SpotApi.onSpotOrder 委托返回错误:{}'.format(SPOT_ERROR_DICT.get(str(error_id))), error_id=error_id) self.gateway.writeLog(ws_data) + localNo = self.localNoQueue.get_nowait() + self.gateway.writeLog(u'移除本地localNo:{}'.format(localNo)) + vtOrderId = '.'.join([self.gatewayName,localNo]) + order = self.localOrderDict.get(vtOrderId) + if order is not None: + order.status = STATUS_REJECTED + order.updateTime = datetime.now().strftime("%H:%M:%S.%f") + self.gateway.writeLog(u'发出OnOrder,拒单,vtOrderId={}'.format(vtOrderId)) + self.gateway.onOrder(order) return - orderId = data.get('order_id') + ok_order_id = data.get('order_id') - if orderId is None: + if ok_order_id is None: self.gateway.writeError(u'SpotApi.onSpotOrder 委托返回中,没有orderid') self.gateway.writeLog(ws_data) return @@ -1184,12 +1246,13 @@ nel': u'ok_sub_spot_etc_usdt_order'} # 从本地编号Queue中,FIFO,提取最早的localNo localNo = self.localNoQueue.get_nowait() if localNo is None: - self.gateway.writeError(u'SpotApi.onSportOrder,未找到本地LocalNo,检查日志') + self.gateway.writeError(u'SpotApi.onSpotOrder,未找到本地LocalNo,检查日志') self.gateway.writeLog(ws_data) return - self.localNoDict[localNo] = str(orderId) - self.orderIdDict[str(orderId)] = localNo + self.gateway.writeLog(u'SpotApi.onSpotOrder,绑定 local:{} <==> ok_order_id:{}'.format(localNo,ok_order_id)) + self.localNoDict[localNo] = str(ok_order_id) + self.orderIdDict[str(ok_order_id)] = localNo # ---------------------------------------------------------------------- """ @@ -1209,60 +1272,99 @@ nel': u'ok_sub_spot_etc_usdt_order'} :param ws_data: :return: """ + self.gateway.writeLog(u'SpotApi.onSpotCancelOrder()') data = ws_data.get('data', {}) if 'error_code' in data: error_id = data.get('error_code') - self.gateway.writeError(u'SpotApi.onSpotCancelOrder 委托返回错误:{}'.format(SPOT_ERROR_DICT.get(error_id)), error_id=error_id) + self.gateway.writeError(u'SpotApi.onSpotCancelOrder 委托返回错误:{}'.format(SPOT_ERROR_DICT.get(str(error_id))), error_id=error_id) self.gateway.writeLog(ws_data) return - orderId = data.get('order_id') - if orderId is None: - self.gateway.writeError(u'SpotApi.onSpotCancelOrder 委托返回中,没有orderid') + ok_order_id = data.get('order_id') + ok_result = data.get('result',False) + if ok_order_id is None: + self.gateway.writeError(u'SpotApi.onSpotCancelOrder 委托返回中,没有order_id') self.gateway.writeLog(ws_data) return - orderId = str(orderId) - localNo = self.orderIdDict[orderId] + if not ok_result: + self.gateway.writeError(u'SpotApi.onSpotCancelOrder 撤单失败') + self.gateway.writeLog(ws_data) + return - if orderId not in self.orderDict: + ok_order_id = str(ok_order_id) + localNo = self.orderIdDict[ok_order_id] + + if ok_order_id not in self.orderDict: + self.gateway.writeLog(u'onSpotCancelOrder,{}的订单不在self.orderDict,创建order对象'.format(ok_order_id)) order = VtOrderData() order.gatewayName = self.gatewayName - order.symbol = data['symbol'] # '.'.join([rawData['symbol'], EXCHANGE_OKEX]) + order.symbol = '.'.join([data['symbol'], EXCHANGE_OKEX]) order.vtSymbol = order.symbol order.orderID = localNo order.vtOrderID = '.'.join([self.gatewayName, order.orderID]) - self.orderDict[orderId] = order + self.orderDict[ok_order_id] = order else: - order = self.orderDict[orderId] + order = self.orderDict[ok_order_id] order.status = STATUS_CANCELLED + dt = datetime.now() + order.cancelTime = dt.strftime("%H:%M:%S.%f") self.gateway.onOrder(order) - del self.orderDict[orderId] - del self.orderIdDict[orderId] - del self.localNoDict[localNo] - - + # #self.gateway.writeLog(u'onSpotCancelOrder:删除self.orderDict[{}]'.format(ok_order_id)) + #del self.orderDict[ok_order_id] + #self.gateway.writeLog(u'移除 localno: {} <==> ok_order_id:{}'.format(localNo,ok_order_id)) + #del self.orderIdDict[ok_order_id] + #del self.localNoDict[localNo] +# # ---------------------------------------------------------------------- def spotSendOrder(self, req): - """发委托单""" + """ + 发出委托指令 + :param req: + :return: + """ + self.gateway.writeLog(u'SpotApi.spotSendOrder()') # 取得币币配对symbol_pair,如果上层在symbol后添加 .OKEX,需要去除 symbol = (req.symbol.split('.'))[0] + if not symbol in self.registerSymbolPairArray: + self.registerSymbolPairArray.add(symbol) + # 获取匹配okex的订单类型 type_ = priceTypeMapReverse[(req.direction, req.priceType)] # 本地委托号加1,并将对应字符串保存到队列中,返回基于本地委托号的vtOrderID self.localNo += 1 + + self.gateway.writeLog(u'localNo:{}'.format(self.localNo)) self.localNoQueue.put(str(self.localNo)) vtOrderID = '.'.join([self.gatewayName, str(self.localNo)]) + self.gateway.writeLog(u'创建本地Order对象,vtOrderId:{}'.format(vtOrderID)) + + # 创建本地order对象 + order = VtOrderData() + order.gatewayName = self.gatewayName + order.symbol = symbol + order.vtSymbol = order.symbol + order.orderID = self.localNo + order.vtOrderID = vtOrderID + order.price = req.price + order.totalVolume = req.volume + order.direction, priceType = priceTypeMap[type_] + order.offset = OFFSET_OPEN if req.direction == DIRECTION_LONG else OFFSET_CLOSE + order.status = STATUS_NOTTRADED + dt = datetime.now() + order.orderTime = dt.strftime("%H:%M:%S.%f") + self.localOrderDict[vtOrderID] = order # 调用ws api发送委托 + self.gateway.writeLog(u'调用ws api发送委托') self.spotTrade(symbol, type_, str(req.price), str(req.volume)) self.gateway.writeLog('SpotSendOrder:symbol:{},Type:{},price:{},volume:{}'.format(symbol, type_, str(req.price), str(req.volume))) @@ -1270,7 +1372,11 @@ nel': u'ok_sub_spot_etc_usdt_order'} # ---------------------------------------------------------------------- def spotCancel(self, req): - """撤单""" + """ + 发出撤单指令 + :param req: + :return: + """ # symbol = spotSymbolMapReverse[req.symbol][:4] symbol = (req.symbol.split('.'))[0] localNo = req.orderID @@ -1288,9 +1394,8 @@ nel': u'ok_sub_spot_etc_usdt_order'} """生成时间""" dt = datetime.fromtimestamp(float(s) / 1e3) time = dt.strftime("%H:%M:%S.%f") - date = dt.strftime("%Y%m%d") - return date, time - + date = dt.strftime("%Y-%m-%d") + return date, time, dt ######################################################################## class OkexFuturesApi(WsFuturesApi): @@ -1309,9 +1414,10 @@ class OkexFuturesApi(WsFuturesApi): self.cbDict = {} self.tickDict = {} self.orderDict = {} + self.localOrderDict = {} # 本地缓存的order_dict,key 是 localNo.gatewayName self.channelSymbolMap = {} - self.localNo = 0 # 本地委托号 + self.localNo = 1 # 本地委托号 self.localNoQueue = Queue() # 未收到系统委托号的本地委托号队列 self.localNoDict = {} # key为本地委托号,value为系统委托号 self.orderIdDict = {} # key为系统委托号,value为本地委托号 @@ -1319,12 +1425,11 @@ class OkexFuturesApi(WsFuturesApi): self.recordOrderId_BefVolume = {} # 记录的之前处理的量 - self.cache_some_order = {} self.tradeID = 0 self.registerSymbolPairArray = set([]) - self._use_leverage = "10" + self._use_leverage = "10" # 缺省使用的杠杆比率 self.bids_depth_dict = {} self.asks_depth_dict = {} @@ -1335,11 +1440,21 @@ class OkexFuturesApi(WsFuturesApi): # ---------------------------------------------------------------------- def setLeverage(self, __leverage): + """ + 设置杠杆比率 + :param __leverage: + :return: + """ self._use_leverage = __leverage # ---------------------------------------------------------------------- def onMessage(self, ws, evt): - """信息推送""" + """ + 信息推送的处理 + :param ws: + :param evt: + :return: + """ # str => json ws_data = self.readData(evt) @@ -1371,10 +1486,11 @@ class OkexFuturesApi(WsFuturesApi): login_data = data['data'] result = login_data['result'] if 'result' in login_data else False if result: - self.writeLog(u'login success: {}'.format(datetime.now())) + self.writeLog(u'登录成功: {}'.format(datetime.now())) self.gateway.futures_connected = True else: - print(u'login fail: {},data:{}'.format(datetime.now(), data)) + self.gateway.writeError(u'登录失败') + self.writeLog(u'登录失败: {},data:{}'.format(datetime.now(), data)) continue # 功能请求回复 @@ -1387,7 +1503,8 @@ class OkexFuturesApi(WsFuturesApi): self.writeLog(u'请求:{} 成功:'.format(channel_value)) continue else: - print(u'not data in :addChannel:{}'.format(data)) + self.gateway.writeError(u'addChannel回复数据没有data') + self.writeLog(u'not data in :addChannel:{}'.format(data)) # 其他回调/数据推送 callback = self.cbDict.get(channel_value) @@ -1395,14 +1512,16 @@ class OkexFuturesApi(WsFuturesApi): try: callback(data) except Exception as ex: - print(u'onMessage call back {} exception:{},{}'.format(channel_value, str(ex), + self.gateway.writeError(u'回调{}发生异常'.format(channel_value)) + self.writeLog(u'onMessage call back {} exception:{},{}'.format(channel_value, str(ex), traceback.format_exc())) else: - print(u'unkonw msg:{}'.format(data)) + self.gateway.writeError(u'出现无回调处理的数据') + self.writeLog(u'unkonw msg:{}'.format(data)) # ---------------------------------------------------------------------- def onError(self, ws, evt): - """错误推送""" + """重载WsFutureApi.onError错误Event推送""" error = VtErrorData() error.gatewayName = self.gatewayName error.errorMsg = str(evt) @@ -1410,30 +1529,36 @@ class OkexFuturesApi(WsFuturesApi): # #---------------------------------------------------------------------- def onErrorMsg(self, data): + """错误信息处理""" error = VtErrorData() error.gatewayName = self.gatewayName - error_code = str(data["data"]["error_code"]) - error.errorID = error_code - error.errorMsg = u'FutureApi Error:{}'.format(FUTURES_ERROR_DICT.get(error_code)) - self.gateway.onError(error) + if 'data' in data and 'error_code' in data['data']: + error_code = str(data["data"]["error_code"]) + error.errorID = error_code + error.errorMsg = u'FutureApi Error:{}'.format(FUTURES_ERROR_DICT.get(error_code)) + self.gateway.onError(error) # ---------------------------------------------------------------------- def reconnect(self): - while not self.gateway.connected_contract: + """ + 重连 + :return: + """ + while not self.gateway.futures_connected: self.writeLog(u'okex Api_contract 等待10秒后重新连接') - self.connect_Contract(self.apiKey, self.secretKey, self.trace) + self.connect(self.apiKey, self.secretKey, self.trace) sleep(10) - if not self.gateway.connected_contract: + if not self.gateway.futures_connected: self.reconnect() # ---------------------------------------------------------------------- def onClose(self, ws): """接口断开""" # 如果尚未连上,则忽略该次断开提示 - if not self.gateway.connected_contract: + if not self.gateway.futures_connected: return - self.gateway.connected_contract = False + self.gateway.futures_connected = False self.writeLog(u'服务器连接断开') # 重新连接 @@ -1450,7 +1575,11 @@ class OkexFuturesApi(WsFuturesApi): """ arr = symbol.split('.') symbol_pair = arr[0] - (symbol, contract_type, leverage) = symbol_pair.split(':') + l = symbol_pair.split(':') + if len(l) !=3: + self.gateway.writeError(u'合约代码{}错误:'.format(symbol)) + raise ValueError(u'合约代码{}错误:'.format(symbol)) + symbol, contract_type, leverage = l[0], l[1], l[2] symbol = symbol.replace("_usd", "") return (symbol_pair, symbol, contract_type, leverage) @@ -1513,8 +1642,8 @@ class OkexFuturesApi(WsFuturesApi): # ---------------------------------------------------------------------- def onOpen(self, ws): """连接成功""" - self.gateway.connected_contract = True - self.writeLog(u'服务器OKEX合约连接成功') + self.gateway.futures_connected = True + self.writeLog(u'服务器OKEX期货连接成功') self.initCallback() @@ -1533,7 +1662,7 @@ class OkexFuturesApi(WsFuturesApi): contract = VtContractData() contract.gatewayName = self.gatewayName - contract.symbol = use_symbol_name # + "." + EXCHANGE_OKEX + contract.symbol = use_symbol_name + "." + EXCHANGE_OKEX contract.exchange = EXCHANGE_OKEX contract.vtSymbol = contract.symbol contract.name = u'期货%s_%s_%s' % (symbol, use_contract_type, self._use_leverage) @@ -1544,7 +1673,7 @@ class OkexFuturesApi(WsFuturesApi): # print contract.vtSymbol , contract.name - quanyi_vtSymbol = symbol + "_usd_future_qy" # + "."+ EXCHANGE_OKEX + quanyi_vtSymbol = symbol + "_usd_future_qy" + "."+ EXCHANGE_OKEX contract = VtContractData() contract.gatewayName = self.gatewayName contract.symbol = quanyi_vtSymbol @@ -1715,7 +1844,7 @@ class OkexFuturesApi(WsFuturesApi): if symbol not in self.tickDict: tick = VtTickData() tick.exchange = EXCHANGE_OKEX - tick.symbol = symbol # '.'.join([symbol, tick.exchange]) + tick.symbol = '.'.join([symbol, tick.exchange]) tick.vtSymbol = tick.symbol tick.gatewayName = self.gatewayName @@ -1936,27 +2065,41 @@ h_this_week_usd'} data = ws_data.get('data', {}) error_code = data.get('error_code') if error_code is not None: - self.gateway.writeError(u'委托返回错误:{}'.format(FUTURES_ERROR_DICT.get(error_code)), error_id=error_code) + self.gateway.writeError(u'onFutureOrder委托返回错误:{}'.format(FUTURES_ERROR_DICT.get(error_code)), error_id=error_code) self.gateway.writeLog(ws_data) - return - orderId = data.get('order_id') + localNo = self.localNoQueue.get_nowait() + if localNo is None: + return - if orderId is None: - self.gateway.writeError(u'SpotApi.onFutureOrder 委托返回中,没有orderid') + self.gateway.writeLog(u'onFutureOrder移除本地localNo:{}'.format(localNo)) + vtOrderId = '.'.join([self.gatewayName,str(localNo)]) + order = self.localOrderDict.get(vtOrderId) + if order: + dt = datetime.now() + order.cancelTime = dt.strftime("%H:%M:%S.%f") + order.status = STATUS_REJECTED + self.gateway.writeLog(u'onFutureOrder发出OnOrder,拒单,vtOrderId={}'.format(vtOrderId)) + self.gateway.onOrder(order) + return + ok_order_id = data.get('order_id') + + if ok_order_id is None: + self.gateway.writeError(u'FuturesApi.onFutureOrder 委托返回中,没有orderid') self.gateway.writeLog(ws_data) return - orderId = str(orderId) + ok_order_id = str(ok_order_id) # 从本地编号Queue中,FIFO,提取最早的localNo localNo = self.localNoQueue.get_nowait() if localNo is None: - self.gateway.writeError(u'SpotApi.onSportOrder,未找到本地LocalNo,检查日志') + self.gateway.writeError(u'FuturesApi.onSportOrder,未找到本地LocalNo,检查日志') self.gateway.writeLog(ws_data) return - self.localNoDict[localNo] = orderId - self.orderIdDict[orderId] = localNo + self.gateway.writeLog(u'FuturesApi.onSportOrder,绑定 local:{} <==> ok_order_id:{}'.format(localNo, ok_order_id)) + self.localNoDict[localNo] = ok_order_id + self.orderIdDict[ok_order_id] = localNo # ---------------------------------------------------------------------- """ @@ -1977,30 +2120,32 @@ h_this_week_usd'} data = ws_data.get('data', {}) if 'error_code' in data: - error_id = data.get('error_code', 0) - - self.gateway.writeError(u'SpotApi.onFutureOrderCancel 委托返回错误:{}'.format(FUTURES_ERROR_DICT.get(error_code)), error_id=error_id) + error_code = data.get('error_code', 0) + self.gateway.writeError(u'SpotApi.onFutureOrderCancel 委托返回错误:{}'.format(FUTURES_ERROR_DICT.get(error_code)), error_id=error_code) self.gateway.writeLog(ws_data) return - orderId = data.get('order_id') - if orderId is None: + ok_order_id = data.get('order_id') + if ok_order_id is None: self.gateway.writeError(u'SpotApi.onFutureOrderCancel 委托返回中,没有orderid') self.gateway.writeLog(ws_data) return - orderId = str(orderId) + + ok_order_id = str(ok_order_id) # 获取本地委托流水号 - localNo = self.orderIdDict[orderId] + localNo = self.orderIdDict[ok_order_id] # 发送onOrder事件 - order = self.orderDict[orderId] + order = self.orderDict[ok_order_id] + dt = datetime.now() + order.cancelTime = dt.strftime("%H:%M:%S.%f") order.status = STATUS_CANCELLED self.gateway.onOrder(order) # 删除本地委托号与orderid的绑定 - del self.orderDict[orderId] - del self.orderIdDict[orderId] - del self.localNoDict[localNo] + #del self.orderDict[orderId] + #del self.orderIdDict[orderId] + #del self.localNoDict[localNo] ''' @@ -2192,8 +2337,8 @@ u'contracts': [], u'balance': 0, u'rights': 0}, u'xrp': {u'contracts': [], u'bal data = ws_data.get("data", {}) - for d in data.get('orders', []): - orderId = str(d['order_id']) + for order_data in data.get('orders', []): + orderId = str(order_data['order_id']) localNo = str(self.localNo) if orderId not in self.orderIdDict: @@ -2217,27 +2362,27 @@ u'contracts': [], u'balance': 0, u'rights': 0}, u'xrp': {u'contracts': [], u'bal if orderId not in self.orderDict: order = VtOrderData() order.gatewayName = self.gatewayName - contract_name = d["contract_name"] + contract_name = order_data["contract_name"] dic_info = self.contract_name_dict[contract_name] use_contract_type = dic_info["contract_type"] - order.symbol = '.'.join([d["symbol"] + ":" + use_contract_type + ":" + str(self._use_leverage)]) #, EXCHANGE_OKEX]) + order.symbol = '.'.join([order_data["symbol"] + ":" + use_contract_type + ":" + str(self._use_leverage)]) #, EXCHANGE_OKEX]) order.vtSymbol = order.symbol order.orderID = self.orderIdDict[orderId] # 更新orderId为本地的序列号 order.vtOrderID = '.'.join([self.gatewayName, order.orderID]) - order.price = d['price'] - order.totalVolume = d['amount'] - order.direction, offset = priceContractOffsetTypeMap[str(d['type'])] + order.price = order_data['price'] + order.totalVolume = order_data['amount'] + order.direction, offset = priceContractOffsetTypeMap[str(order_data['type'])] self.orderDict[orderId] = order - self.gateway.writeLog(u'新增本地orderDict缓存,okex orderId:{},order.orderid:{}'.format(orderId,order.orderID)) + self.gateway.writeLog(u'新增本地orderDict缓存,okex orderId:{},order.orderid:{}'.format(orderId, order.orderID)) else: order = self.orderDict[orderId] - order.tradedVolume = d['deal_amount'] - order.status = statusMap[int(d['status'])] + order.tradedVolume = order_data['deal_amount'] + order.status = statusMap[int(order_data['status'])] # 推送到OnOrder中 self.gateway.onOrder(copy(order)) @@ -2331,7 +2476,7 @@ user_id': 6548935, u'contract_id': 201802160040063L, u'price': 24.555, u'create_ order.tradedVolume = float(data['deal_amount']) order.status = statusMap[data['status']] self.orderDict[orderId] = order - self.gateway.writeLog(u'新增order,orderid:{},symbol:{},data:{}'.format(order.orderID,order.symbol),data) + self.gateway.writeLog(u'新增order,orderid:{},symbol:{},data:{}'.format(order.orderID,order.symbol,data)) else: # 更新成交数量/状态 order = self.orderDict[orderId] @@ -2617,22 +2762,48 @@ utureusd_positions'} :param req: :return: """ - symbol_pair, symbol, contract_type, leverage = self.dealSymbolFunc(req.symbol) + try: + (symbol_pair, symbol, contract_type, leverage) = self.dealSymbolFunc(req.symbol) + except Exception as ex: + self.gateway.writeError(u'请求合约代码格式错误:{}'.format(req.symbol)) + self.writeLog(u'futureSendOrder 请求合约代码格式错误:{},exception:{},{}'.format(req.symbol,str(ex),traceback.format_exc())) + return '' # print symbol_pair , symbol, contract_type , leverage type_ = priceContractTypeMapReverse[(req.direction, req.offset)] - + self.writeLog(u'futureSendOrder:{},{},{},{},{}'.format(symbol_pair, symbol, contract_type, leverage, type_)) # 本地委托号加1,并将对应字符串保存到队列中,返回基于本地委托号的vtOrderID self.localNo += 1 self.localNoQueue.put(str(self.localNo)) vtOrderID = '.'.join([self.gatewayName, str(self.localNo)]) + self.writeLog(u'futureSendOrder:创建本地订单:orderId:{}'.format(vtOrderID)) - # print symbol + "_usd", contract_type , type_ , str(req.price), str(req.volume) - self.futureTrade(symbol + "_usd", contract_type, type_, str(req.price), str(req.volume), - _lever_rate=self._use_leverage) + order = VtOrderData() + order.gatewayName = self.gatewayName + order.symbol = symbol + order.vtSymbol = order.symbol + order.orderID = self.localNo + order.vtOrderID = vtOrderID + order.price = req.price + order.totalVolume = req.volume + order.direction = req.direction + order.offset = req.offset + order.status = STATUS_NOTTRADED + dt = datetime.now() + order.orderTime = dt.strftime("%H:%M:%S.%f") + self.localOrderDict[vtOrderID] = order - return vtOrderID + self.writeLog(u'futureSendOrder 发送:symbol:{},合约类型:{},交易类型:{},价格:{},委托量:{}'. + format(symbol + "_usd", contract_type , type_ , str(req.price), str(req.volume))) + try: + self.futureTrade(symbol + "_usd", contract_type, type_, str(req.price), str(req.volume), + _lever_rate=self._use_leverage) + return vtOrderID + except Exception as ex: + self.gateway.writeError(u'futureSendOrder发送委托失败:{}'.format(str(ex))) + self.writeLog(u'futureSendOrder发送委托失败.{}'.format(traceback.format_exc())) + return '' # ---------------------------------------------------------------------- def futureCancel(self, req): """ @@ -2640,7 +2811,7 @@ utureusd_positions'} :param req: :return: """ - symbol_pair, symbol, contract_type, leverage = self.dealSymbolFunc(req.symbol) + (symbol_pair, symbol, contract_type, leverage) = self.dealSymbolFunc(req.symbol) localNo = req.orderID