From c209a7698b0979355fcd337acce890d82ef572d3 Mon Sep 17 00:00:00 2001 From: "vn.py" Date: Sun, 18 Mar 2018 20:14:02 +0800 Subject: [PATCH] =?UTF-8?q?[Add]=E6=B7=BB=E5=8A=A0huobiGateway?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vnpy/api/huobi/testmd.py | 4 +- vnpy/api/huobi/testtd.py | 8 +- vnpy/api/huobi/vnhuobi.py | 20 +- .../gateway/huobiGateway/HUOBI_connect.json | 6 + vnpy/trader/gateway/huobiGateway/__init__.py | 10 + .../gateway/huobiGateway/huobiGateway.py | 640 ++++++++++++++++++ 6 files changed, 677 insertions(+), 11 deletions(-) create mode 100644 vnpy/trader/gateway/huobiGateway/HUOBI_connect.json create mode 100644 vnpy/trader/gateway/huobiGateway/__init__.py create mode 100644 vnpy/trader/gateway/huobiGateway/huobiGateway.py diff --git a/vnpy/api/huobi/testmd.py b/vnpy/api/huobi/testmd.py index 688f00b1..89b320fc 100644 --- a/vnpy/api/huobi/testmd.py +++ b/vnpy/api/huobi/testmd.py @@ -53,7 +53,7 @@ from vnhuobi import DataApi api = DataApi() api.connect("wss://api.huobipro.com/ws") -#api.subscribeMarketDepth('ethusdt') +api.subscribeMarketDepth('ethusdt') #api.subscribeTradeDetail('ethusdt') -api.subscribeMarketDetail('ethusdt') +#api.subscribeMarketDetail('ethusdt') input() \ No newline at end of file diff --git a/vnpy/api/huobi/testtd.py b/vnpy/api/huobi/testtd.py index d7061863..b3b1f8cd 100644 --- a/vnpy/api/huobi/testtd.py +++ b/vnpy/api/huobi/testtd.py @@ -20,17 +20,17 @@ def testTrade(): print api.getTimestamp() - accountid = '' + #accountid = '' symbol = 'aaceth' #api.getAccounts() #api.getAccountBalance(accountid) #api.getOrders(symbol, 'pre-submitted,submitted,partial-filled,partial-canceled,filled,canceled') #api.getOrders(symbol, 'filled') - #api.getMatchResults(symbol) + print api.getMatchResults(symbol) - api.getOrder('2440401255') - api.getMatchResult('2440401255') + #api.getOrder('2440401255') + #api.getMatchResult('2440401255') #api.placeOrder(accountid, '2', symbol, 'sell-market', source='api') #api.cancelOrder('2440451757') diff --git a/vnpy/api/huobi/vnhuobi.py b/vnpy/api/huobi/vnhuobi.py index b838eefe..a21a9fd2 100644 --- a/vnpy/api/huobi/vnhuobi.py +++ b/vnpy/api/huobi/vnhuobi.py @@ -5,6 +5,7 @@ import hmac import base64 import hashlib import requests +import traceback from copy import copy from datetime import datetime from threading import Thread @@ -33,9 +34,7 @@ DEFAULT_POST_HEADERS = { 'Content-Type': 'application/json', 'Accept': 'application/json', 'Accept-Language': LANG, - "User-Agent": "Chrome/39.0.2171.71", 'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:53.0) Gecko/20100101 Firefox/53.0' - #'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:53.0) Gecko/20100101 Firefox/53.0' } @@ -93,6 +92,8 @@ class TradeApi(object): if mode: self.mode = mode + + return True #---------------------------------------------------------------------- def start(self, n=10): @@ -418,7 +419,7 @@ class TradeApi(object): def onGetSymbols(self, data, reqid): """查询代码回调""" #print reqid, data - for d in data['data']: + for d in data: print d #---------------------------------------------------------------------- @@ -523,9 +524,18 @@ class DataApi(object): return True except: - self.onError(u'行情服务器连接失败') + msg = traceback.format_exc() + self.onError(u'行情服务器连接失败:%s' %msg) return False + #---------------------------------------------------------------------- + def stop(self): + """停止""" + if self.active: + self.active = False + self.thread.join() + self.ws.close() + #---------------------------------------------------------------------- def sendReq(self, req): """发送请求""" @@ -569,7 +579,7 @@ class DataApi(object): #---------------------------------------------------------------------- def subscribeMarketDepth(self, symbol): """订阅行情深度""" - topic = 'market.%s.depth.step5' %symbol + topic = 'market.%s.depth.step0' %symbol self.subTopic(topic) #---------------------------------------------------------------------- diff --git a/vnpy/trader/gateway/huobiGateway/HUOBI_connect.json b/vnpy/trader/gateway/huobiGateway/HUOBI_connect.json new file mode 100644 index 00000000..7ce3c74c --- /dev/null +++ b/vnpy/trader/gateway/huobiGateway/HUOBI_connect.json @@ -0,0 +1,6 @@ +{ + "exchange": "hadax", + "accessKey": "请在火币网站获取", + "secretKey": "请在火币网站获取", + "symbols": ["aaceth"] +} \ No newline at end of file diff --git a/vnpy/trader/gateway/huobiGateway/__init__.py b/vnpy/trader/gateway/huobiGateway/__init__.py new file mode 100644 index 00000000..b6bb6efe --- /dev/null +++ b/vnpy/trader/gateway/huobiGateway/__init__.py @@ -0,0 +1,10 @@ +# encoding: UTF-8 + +from vnpy.trader import vtConstant +from huobiGateway import HuobiGateway + +gatewayClass = HuobiGateway +gatewayName = 'HUOBI' +gatewayDisplayName = u'火币' +gatewayType = vtConstant.GATEWAYTYPE_BTC +gatewayQryEnabled = True \ No newline at end of file diff --git a/vnpy/trader/gateway/huobiGateway/huobiGateway.py b/vnpy/trader/gateway/huobiGateway/huobiGateway.py new file mode 100644 index 00000000..aea78b43 --- /dev/null +++ b/vnpy/trader/gateway/huobiGateway/huobiGateway.py @@ -0,0 +1,640 @@ +# encoding: UTF-8 + +''' +vn.sec的gateway接入 +''' + +import os +import json +from datetime import datetime +from copy import copy +from math import pow + +from vnpy.api.huobi import TradeApi, DataApi +from vnpy.trader.vtGateway import * +from vnpy.trader.vtFunction import getJsonPath, getTempPath + + +# 以下为一些VT类型和SEC类型的映射字典 +priceTypeMap = {} +priceTypeMapReverse = {v: k for k, v in priceTypeMap.items()} + +# 方向类型映射 +directionMap = {} +#directionMap[DIRECTION_LONG] = DATA_TYPE.DFITCSEC_ED_Buy +#directionMap[DIRECTION_SHORT] = DATA_TYPE.DFITCSEC_ED_Sell +directionMapReverse = {v: k for k, v in directionMap.items()} + +# 开平类型映射 +offsetMap = {} +#offsetMap[OFFSET_OPEN] = DATA_TYPE.DFITCSEC_OCF_Open +#offsetMap[OFFSET_CLOSE] = DATA_TYPE.DFITCSEC_OCF_Close +offsetMapReverse = {v:k for k,v in offsetMap.items()} + + +# 委托状态类型映射 +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 print_dict(d): + """""" + print '-' * 30 + l = d.keys() + l.sort() + for k in l: + print '%s:%s' %(k, d[k]) + + +######################################################################## +class HuobiGateway(VtGateway): + """火币接口""" + + #---------------------------------------------------------------------- + def __init__(self, eventEngine, gatewayName='HUOBI'): + """Constructor""" + super(HuobiGateway, self).__init__(eventEngine, gatewayName) + + self.dataApi = HuobiDataApi(self) # 行情API + self.tradeApi = HuobiTradeApi(self) # 交易API + + self.mdConnected = False # 行情API连接状态,登录完成后为True + self.tdConnected = False # 交易API连接状态 + + self.qryEnabled = False # 是否要启动循环查询 + + self.fileName = self.gatewayName + '_connect.json' + self.filePath = getJsonPath(self.fileName, __file__) + + #---------------------------------------------------------------------- + def connect(self): + """连接""" + try: + f = file(self.filePath) + except IOError: + log = VtLogData() + log.gatewayName = self.gatewayName + log.logContent = u'读取连接配置出错,请检查' + self.onLog(log) + return + + # 解析json文件 + setting = json.load(f) + try: + exchange = str(setting['exchange']) + accessKey = str(setting['accessKey']) + secretKey = str(setting['secretKey']) + symbols = setting['symbols'] + except KeyError: + log = VtLogData() + log.gatewayName = self.gatewayName + log.logContent = u'连接配置缺少字段,请检查' + self.onLog(log) + return + + # 创建行情和交易接口对象 + self.dataApi.connect(exchange) + self.tradeApi.connect(exchange, accessKey, secretKey, symbols) + + # 初始化并启动查询 + self.initQuery() + + #---------------------------------------------------------------------- + def subscribe(self, subscribeReq): + """订阅行情""" + self.dataApi.subscribe(subscribeReq) + + #---------------------------------------------------------------------- + def sendOrder(self, orderReq): + """发单""" + return self.tradeApi.sendOrder(orderReq) + + #---------------------------------------------------------------------- + def cancelOrder(self, cancelOrderReq): + """撤单""" + self.tradeApi.cancelOrder(cancelOrderReq) + + #---------------------------------------------------------------------- + def qryPosition(self): + """查询持仓""" + self.tradeApi.qryPosition() + + #---------------------------------------------------------------------- + def qryTrade(self): + """查询成交""" + self.tradeApi.qryTrade() + + #---------------------------------------------------------------------- + def qryOrder(self): + """查询委托""" + self.tradeApi.qryOrder() + + #---------------------------------------------------------------------- + def close(self): + """关闭""" + if self.mdConnected: + self.dataApi.close() + if self.tdConnected: + self.tradeApi.close() + + #---------------------------------------------------------------------- + def initQuery(self): + """初始化连续查询""" + if self.qryEnabled: + # 需要循环的查询函数列表 + self.qryFunctionList = [ + self.qryPosition, + self.qryTrade, + self.qryOrder + ] + + self.qryCount = 0 # 查询触发倒计时 + self.qryTrigger = 1 # 查询触发点 + self.qryNextFunction = 0 # 上次运行的查询函数索引 + + self.startQuery() + + #---------------------------------------------------------------------- + def query(self, event): + """注册到事件处理引擎上的查询函数""" + self.qryCount += 1 + + if self.qryCount > self.qryTrigger: + # 清空倒计时 + self.qryCount = 0 + + # 执行查询函数 + function = self.qryFunctionList[self.qryNextFunction] + function() + + # 计算下次查询函数的索引,如果超过了列表长度,则重新设为0 + self.qryNextFunction += 1 + if self.qryNextFunction == len(self.qryFunctionList): + self.qryNextFunction = 0 + + #---------------------------------------------------------------------- + def startQuery(self): + """启动连续查询""" + self.eventEngine.register(EVENT_TIMER, self.query) + + #---------------------------------------------------------------------- + def setQryEnabled(self, qryEnabled): + """设置是否要启动循环查询""" + self.qryEnabled = qryEnabled + + +######################################################################## +class HuobiDataApi(DataApi): + """行情API实现""" + + #---------------------------------------------------------------------- + def __init__(self, gateway): + """Constructor""" + super(HuobiDataApi, self).__init__() + + self.gateway = gateway # gateway对象 + self.gatewayName = gateway.gatewayName # gateway对象名称 + + self.connectionStatus = False # 连接状态 + + self.tickDict = {} + + #---------------------------------------------------------------------- + def connect(self, exchange): + """连接服务器""" + if exchange == 'huobi': + url = 'wss://api.huobi.pro/ws' + else: + url = 'wss://api.hadax.com/ws' + + self.connectionStatus = super(HuobiDataApi, self).connect(url) + self.gateway.mdConnected = True + + if self.connectionStatus: + self.writeLog(u'行情服务器连接成功') + + #---------------------------------------------------------------------- + def subscribe(self, subscribeReq): + """订阅合约""" + if not self.connectionStatus: + return + + symbol = subscribeReq.symbol + if symbol in self.tickDict: + return + + tick = VtTickData() + tick.gatewayName = self.gatewayName + tick.symbol = symbol + tick.exchange = EXCHANGE_HUOBI + tick.vtSymbol = '.'.join([tick.symbol, tick.exchange]) + self.tickDict[symbol] = tick + + self.subscribeMarketDepth(symbol) + self.subscribeMarketDetail(symbol) + #self.subscribeTradeDetail(symbol) + + #---------------------------------------------------------------------- + def writeLog(self, content): + """发出日志""" + log = VtLogData() + log.gatewayName = self.gatewayName + log.logContent = content + self.gateway.onLog(log) + + #---------------------------------------------------------------------- + def onError(self, msg): + """错误推送""" + err = VtErrorData() + err.gatewayName = self.gatewayName + err.errorID = 'Data' + err.errorMsg = msg + self.gateway.onError(err) + + #---------------------------------------------------------------------- + def onMarketDepth(self, data): + """行情深度推送 """ + symbol = data['ch'].split('.')[1] + + tick = self.tickDict.get(symbol, None) + if not tick: + return + + tick.datetime = datetime.fromtimestamp(data['ts']/1000) + tick.date = tick.datetime.strftime('%Y%m%d') + tick.time = tick.datetime.strftime('%H:%M:%S.%f') + + bids = data['tick']['bids'] + for n in range(5): + l = bids[n] + tick.__setattr__('bidPrice' + str(n+1), l[0]) + tick.__setattr__('bidVolume' + str(n+1), l[1]) + + asks = data['tick']['asks'] + for n in range(5): + l = asks[n] + tick.__setattr__('askPrice' + str(n+1), l[0]) + tick.__setattr__('askVolume' + str(n+1), l[1]) + + #print '-' * 50 + #for d in data['tick']['asks']: + #print 'ask', d + + #for d in data['tick']['bids']: + #print 'bid', d + + #print '-' * 50 + #print 'ask5', tick.askPrice5, tick.askVolume5 + #print 'ask4', tick.askPrice4, tick.askVolume4 + #print 'ask3', tick.askPrice3, tick.askVolume3 + #print 'ask2', tick.askPrice2, tick.askVolume2 + #print 'ask1', tick.askPrice1, tick.askVolume1 + + #print 'bid1', tick.bidPrice1, tick.bidVolume1 + #print 'bid2', tick.bidPrice2, tick.bidVolume2 + #print 'bid3', tick.bidPrice3, tick.bidVolume3 + #print 'bid4', tick.bidPrice4, tick.bidVolume4 + #print 'bid5', tick.bidPrice5, tick.bidVolume5 + + if tick.lastPrice: + newtick = copy(tick) + self.gateway.onTick(tick) + + #---------------------------------------------------------------------- + def onTradeDetail(self, data): + """成交细节推送""" + print data + + #---------------------------------------------------------------------- + def onMarketDetail(self, data): + """市场细节推送""" + symbol = data['ch'].split('.')[1] + + tick = self.tickDict.get(symbol, None) + if not tick: + return + + tick.datetime = datetime.fromtimestamp(data['ts']/1000) + tick.date = tick.datetime.strftime('%Y%m%d') + tick.time = tick.datetime.strftime('%H:%M:%S.%f') + + t = data['tick'] + tick.openPrice = t['open'] + tick.highPrice = t['high'] + tick.lowPrice = t['low'] + tick.lastPrice = t['close'] + tick.volume = t['vol'] + + if tick.bidPrice1: + newtick = copy(tick) + self.gateway.onTick(tick) + + + +######################################################################## +class HuobiTradeApi(TradeApi): + """交易API实现""" + + #---------------------------------------------------------------------- + def __init__(self, gateway): + """API对象的初始化函数""" + super(HuobiTradeApi, self).__init__() + + self.gateway = gateway # gateway对象 + self.gatewayName = gateway.gatewayName # gateway对象名称 + + self.reqID = EMPTY_INT # 操作请求编号 + self.localID = EMPTY_INT # 订单编号 + + self.connectionStatus = False # 连接状态 + self.accountid = '' + + self.todayDate = datetime.now().strftime('%Y-%m-%d') + + self.orderDict = {} # 缓存委托数据的字典 + self.symbols = [] # 所有交易代码的字符串集合 + + self.qryTradeID = None # 查询起始成交编号 + self.tradeIDs = set() # 成交编号集合 + + self.qryOrderID = None # 查询起始委托编号 + + #---------------------------------------------------------------------- + def connect(self, exchange, accessKey, secretKey, symbols=''): + """初始化连接""" + if not self.connectionStatus: + self.symbols = symbols + + self.connectionStatus = self.init(exchange, accessKey, secretKey) + self.gateway.tdConnected = True + self.start() + self.writeLog(u'交易服务器连接成功') + + self.getSymbols() + + #---------------------------------------------------------------------- + def qryPosition(self): + """查询持仓""" + if self.accountid: + self.getAccountBalance(self.accountid) + + #---------------------------------------------------------------------- + def qryOrder(self): + """查询委托""" + states = 'pre-submitted,submitting,submitted,partial-filled,partial-canceled,filled,canceled' + for symbol in self.symbols: + self.getOrders(symbol, states, startDate=self.todayDate) + #print u'查询委托', self.qryOrderID + #self.getOrders(symbol, states, startDate=self.todayDate, from_=self.qryOrderID, direct='next') + + #---------------------------------------------------------------------- + def qryTrade(self): + """查询成交""" + for symbol in self.symbols: + self.getMatchResults(symbol, startDate=self.todayDate) + #self.getMatchResults(symbol, startDate=self.todayDate, from_=self.qryTradeID) + + #---------------------------------------------------------------------- + def sendOrder(self, orderReq): + """发单""" + self.localID += 1 + vtOrderID = '.'.join([self.gatewayName, str(self.localID)]) + + if orderReq.direction == DIRECTION_LONG: + type_ = 'buy-limit' + else: + type_ = 'sell-limit' + + self.placeOrder(self.accountid, + str(orderReq.volume), + orderReq.symbol, + type_, + price=str(orderReq.price), + source='api') + + # 返回订单号 + return vtOrderID + + #---------------------------------------------------------------------- + def cancelOrder(self, cancelOrderReq): + """撤单""" + super(HuobiTradeApi, self).cancelOrder(cancelOrderReq.orderID) + + #---------------------------------------------------------------------- + def writeLog(self, content): + """发出日志""" + log = VtLogData() + log.gatewayName = self.gatewayName + log.logContent = content + self.gateway.onLog(log) + + #---------------------------------------------------------------------- + def onError(self, msg, reqid): + """错误回调""" + err = VtErrorData() + err.gatewayName = self.gatewayName + err.errorID = 'Trade' + err.errorMsg = msg + self.gateway.onError(err) + + #---------------------------------------------------------------------- + def onGetSymbols(self, data, reqid): + """查询代码回调""" + for d in data: + contract = VtContractData() + contract.gatewayName = self.gatewayName + + contract.symbol = d['base-currency'] + d['quote-currency'] + contract.exchange = EXCHANGE_HUOBI + contract.vtSymbol = '.'.join([contract.symbol, contract.exchange]) + + contract.name = '/'.join([d['base-currency'].upper(), d['quote-currency'].upper()]) + contract.priceTick = 1 / pow(10, d['price-precision']) + contract.size = 1 / pow(10, d['amount-precision']) + contract.productClass = PRODUCT_SPOT + + self.gateway.onContract(contract) + + self.writeLog(u'交易代码查询成功') + self.getAccounts() + + #---------------------------------------------------------------------- + def onGetCurrencys(self, data, reqid): + """查询货币回调""" + pass + + #---------------------------------------------------------------------- + def onGetTimestamp(self, data, reqid): + """查询时间回调""" + print reqid, data + + #---------------------------------------------------------------------- + def onGetAccounts(self, data, reqid): + """查询账户回调""" + for d in data: + self.accountid = str(d['id']) + self.writeLog(u'交易账户%s查询成功' %self.accountid) + + #---------------------------------------------------------------------- + def onGetAccountBalance(self, data, reqid): + """查询余额回调""" + posDict = {} + + for d in data['list']: + symbol = d['currency'] + pos = posDict.get(symbol, None) + + if not pos: + pos = VtPositionData() + pos.gatewayName = self.gatewayName + pos.symbol = d['currency'] + pos.exchange = EXCHANGE_HUOBI + pos.vtSymbol = '.'.join([pos.symbol, pos.exchange]) + pos.direction = DIRECTION_LONG + pos.vtPositionName = '.'.join([pos.vtSymbol, pos.direction]) + + if d['type'] == 'trade': + pos.position = float(d['balance']) + else: + pos.frozen = float(d['balance']) + + posDict[symbol] = pos + + for pos in posDict.values(): + self.gateway.onPosition(pos) + + #---------------------------------------------------------------------- + def onGetOrders(self, data, reqid): + """查询委托回调""" + qryOrderID = None + + for d in data: + orderID = d['id'] + updated = False + + order = self.orderDict.get(orderID, None) + if not order: + updated = True + + order = VtOrderData() + order.gatewayName = self.gatewayName + + order.orderID = str(orderID) + order.vtOrderID = '.'.join([order.gatewayName, order.orderID]) + + order.symbol = d['symbol'] + order.exchange = EXCHANGE_HUOBI + order.vtSymbol = '.'.join([order.symbol, order.exchange]) + + order.price = float(d['price']) + order.totalVolume = float(d['amount']) + order.orderTime = datetime.fromtimestamp(d['created-at']/1000).strftime('%H:%M:%S') + + if 'buy' in d['type']: + order.direction = DIRECTION_LONG + else: + order.direction = DIRECTION_SHORT + order.offset = OFFSET_NONE + + # 数据更新,只有当成交数量或者委托状态变化时,才执行推送 + if d['canceled-at']: + order.cancelTime = datetime.fromtimestamp(d['canceled-at']/1000).strftime('%H:%M:%S') + + newTradedVolume = d['field-amount'] + newStatus = statusMapReverse.get(d['state'], STATUS_UNKNOWN) + + if newTradedVolume != order.tradedVolume or newStatus != order.status: + updated = True + order.tradedVolume = float(newTradedVolume) + order.status = newStatus + + # 只推送有更新的数据 + if updated: + self.gateway.onOrder(order) + + # 计算查询下标(即最早的未全成或撤委托) + if order.status not in [STATUS_ALLTRADED, STATUS_CANCELLED]: + if not qryOrderID: + qryOrderID = orderID + else: + qryOrderID = min(qryOrderID, orderID) + + # 更新查询下标 + if qryOrderID: + self.qryOrderID = qryOrderID + + #---------------------------------------------------------------------- + def onGetMatchResults(self, data, reqid): + """查询成交回调""" + for d in data: + tradeID = d['match-id'] + + # 成交仅需要推送一次,去重判断 + if tradeID in self.tradeIDs: + continue + self.tradeIDs.add(tradeID) + + # 查询起始编号更新 + self.qryTradeID = max(tradeID, self.qryTradeID) + + # 推送数据 + trade = VtTradeData() + trade.gatewayName = self.gatewayName + + trade.tradeID = str(tradeID) + trade.vtTradeID = '.'.join([trade.tradeID, trade.gatewayName]) + + trade.symbol = d['symbol'] + trade.exchange = EXCHANGE_HUOBI + trade.vtSymbol = '.'.join([trade.symbol, trade.exchange]) + + if 'buy' in d['type']: + trade.direction = DIRECTION_LONG + else: + trade.direction = DIRECTION_SHORT + trade.offset = OFFSET_NONE + + trade.orderID = str(d['order-id']) + trade.vtOrderID = '.'.join([trade.gatewayName, trade.orderID]) + trade.tradeID = str(d['match-id']) + trade.vtTradeID = '.'.join([trade.gatewayName, trade.tradeID]) + + trade.price = float(d['price']) + trade.volume = float(d['filled-amount']) + + dt = datetime.fromtimestamp(d['created-at']/1000) + trade.tradeTime = dt.strftime('%H:%M:%S') + + self.gateway.onTrade(trade) + + #---------------------------------------------------------------------- + def onGetOrder(self, data, reqid): + """查询单一委托回调""" + print reqid, data + + #---------------------------------------------------------------------- + def onGetMatchResult(self, data, reqid): + """查询单一成交回调""" + print reqid, data + + #---------------------------------------------------------------------- + def onPlaceOrder(self, data, reqid): + """委托回调""" + print reqid, data + + #---------------------------------------------------------------------- + def onCancelOrder(self, data, reqid): + """撤单回调""" + self.writeLog(u'委托撤单成功:%s' %data) + + #---------------------------------------------------------------------- + def onBatchCancel(self, data, reqid): + """批量撤单回调""" + print reqid, data