完成vn.trader的直达期货接入,感谢量衍投资!
This commit is contained in:
parent
d3518ae929
commit
3c7745c7c1
@ -2,6 +2,11 @@
|
|||||||
|
|
||||||
'''
|
'''
|
||||||
vn.shzd的gateway接入
|
vn.shzd的gateway接入
|
||||||
|
|
||||||
|
1. 期权合约数量太多,为了方便起见默认接口只接收期货合约数据
|
||||||
|
2. 直达接口的撤单操作也被视作一个独立的委托,但是在vn.trader中选择忽略
|
||||||
|
3. 持仓全部平光后,再次查询时会没有该合约的推送(和CTP不同),为了避免最后平仓
|
||||||
|
不更新的情况,使用缓存机制来处理
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
|
||||||
@ -201,7 +206,7 @@ class ShzdGatewayApi(ShzdApi):
|
|||||||
self.accountNoList = [] # 账号列表
|
self.accountNoList = [] # 账号列表
|
||||||
|
|
||||||
self.tradeCallbacks = {} # 交易回调函数映射
|
self.tradeCallbacks = {} # 交易回调函数映射
|
||||||
self.marketCallbacks = {} # 行情回调函数映射
|
self.marketCallbacks = {} # 行情回调函数映射
|
||||||
|
|
||||||
# 委托相关
|
# 委托相关
|
||||||
self.localNo = EMPTY_INT # 本地委托号
|
self.localNo = EMPTY_INT # 本地委托号
|
||||||
@ -210,6 +215,13 @@ class ShzdGatewayApi(ShzdApi):
|
|||||||
self.localNoDict = {} # key为str(localNo),value为(SystemNo, OrderNo)
|
self.localNoDict = {} # key为str(localNo),value为(SystemNo, OrderNo)
|
||||||
self.cancelDict = {} # key为等待撤单的str(localNo),value为CancelOrderReq
|
self.cancelDict = {} # key为等待撤单的str(localNo),value为CancelOrderReq
|
||||||
|
|
||||||
|
# 委托号前缀
|
||||||
|
n = datetime.now()
|
||||||
|
self.orderPrefix = n.strftime("%H%M%S.")
|
||||||
|
|
||||||
|
# 持仓缓存
|
||||||
|
self.posDict = {} # key为vtPositionName,value为VtPositionData
|
||||||
|
|
||||||
self.initCallbacks()
|
self.initCallbacks()
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
@ -260,13 +272,12 @@ class ShzdGatewayApi(ShzdApi):
|
|||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
def onMarketData(self, data):
|
def onMarketData(self, data):
|
||||||
"""行情推送"""
|
"""行情推送"""
|
||||||
printDict(data)
|
|
||||||
tick = VtTickData()
|
tick = VtTickData()
|
||||||
tick.gatewayName = self.gatewayName
|
tick.gatewayName = self.gatewayName
|
||||||
|
|
||||||
tick.symbol = data['307']
|
tick.symbol = data['307']
|
||||||
tick.exchange = exchangeMapReverse.get(data['306'], EXCHANGE_UNKNOWN)
|
tick.exchange = exchangeMapReverse.get(data['306'], EXCHANGE_UNKNOWN)
|
||||||
tick.vtSymbol = '.'.join([tick.symbol, EXCHANGE_UNKNOWN])
|
tick.vtSymbol = '.'.join([tick.symbol, tick.exchange])
|
||||||
|
|
||||||
tick.volume = int(data['513'])
|
tick.volume = int(data['513'])
|
||||||
tick.openInterest = int(data['514'])
|
tick.openInterest = int(data['514'])
|
||||||
@ -284,9 +295,29 @@ class ShzdGatewayApi(ShzdApi):
|
|||||||
|
|
||||||
# 可以实现5档深度
|
# 可以实现5档深度
|
||||||
tick.bidPrice1 = float(data['500'])
|
tick.bidPrice1 = float(data['500'])
|
||||||
|
tick.bidPrice2 = float(data['515'])
|
||||||
|
tick.bidPrice3 = float(data['516'])
|
||||||
|
tick.bidPrice4 = float(data['517'])
|
||||||
|
tick.bidPrice5 = float(data['518'])
|
||||||
|
|
||||||
tick.bidVolume1 = int(data['501'])
|
tick.bidVolume1 = int(data['501'])
|
||||||
|
tick.bidVolume2 = int(data['519'])
|
||||||
|
tick.bidVolume3 = int(data['520'])
|
||||||
|
tick.bidVolume4 = int(data['521'])
|
||||||
|
tick.bidVolume5 = int(data['522'])
|
||||||
|
|
||||||
tick.askPrice1 = float(data['502'])
|
tick.askPrice1 = float(data['502'])
|
||||||
|
tick.askPrice2 = float(data['523'])
|
||||||
|
tick.askPrice3 = float(data['524'])
|
||||||
|
tick.askPrice4 = float(data['525'])
|
||||||
|
tick.askPrice5 = float(data['526'])
|
||||||
|
|
||||||
tick.askVolume1 = int(data['503'])
|
tick.askVolume1 = int(data['503'])
|
||||||
|
tick.askVolume2 = int(data['527'])
|
||||||
|
tick.askVolume3 = int(data['528'])
|
||||||
|
tick.askVolume4 = int(data['529'])
|
||||||
|
tick.askVolume5 = int(data['530'])
|
||||||
|
|
||||||
except ValueError:
|
except ValueError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -304,7 +335,7 @@ class ShzdGatewayApi(ShzdApi):
|
|||||||
|
|
||||||
if '410' in data and data['410'] == '1':
|
if '410' in data and data['410'] == '1':
|
||||||
self.gateway.writeLog(u'登录成功')
|
self.gateway.writeLog(u'登录成功')
|
||||||
self.qryContract()
|
#self.qryContract()
|
||||||
self.qryOrder()
|
self.qryOrder()
|
||||||
self.qryTrade()
|
self.qryTrade()
|
||||||
|
|
||||||
@ -329,7 +360,8 @@ class ShzdGatewayApi(ShzdApi):
|
|||||||
order.orderTime = data['346']
|
order.orderTime = data['346']
|
||||||
|
|
||||||
self.orderDict[order.orderID] = order
|
self.orderDict[order.orderID] = order
|
||||||
self.localNoDict[order.orderID] = (order['300'], order['301'])
|
self.localNoDict[order.orderID] = (data['300'], data['301'])
|
||||||
|
self.orderNoDict[data['301']] = order.orderID
|
||||||
|
|
||||||
# 委托查询
|
# 委托查询
|
||||||
if '315' in data:
|
if '315' in data:
|
||||||
@ -396,10 +428,18 @@ class ShzdGatewayApi(ShzdApi):
|
|||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
def onOrder(self, data):
|
def onOrder(self, data):
|
||||||
"""委托变化推送"""
|
"""委托变化推送"""
|
||||||
orderID = self.orderNoDict[data['301']]
|
orderID = self.orderNoDict.get(data['301'], None)
|
||||||
order = self.orderDict[orderID]
|
if orderID:
|
||||||
order.tradedVolume = int(data['315'])
|
order = self.orderDict[orderID]
|
||||||
self.gateway.onOrder(copy(order))
|
order.tradedVolume = int(data['315'])
|
||||||
|
|
||||||
|
if order.tradedVolume > 0:
|
||||||
|
if order.tradedVolume < order.totalVolume:
|
||||||
|
order.status = STATUS_PARTTRADED
|
||||||
|
else:
|
||||||
|
order.status = STATUS_ALLTRADED
|
||||||
|
|
||||||
|
self.gateway.onOrder(copy(order))
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
def onQryOrder(self, data):
|
def onQryOrder(self, data):
|
||||||
@ -427,9 +467,11 @@ class ShzdGatewayApi(ShzdApi):
|
|||||||
order.totalVolume = int(data['309'])
|
order.totalVolume = int(data['309'])
|
||||||
order.status = orderStatusMapReverse.get(data['405'], STATUS_UNKNOWN)
|
order.status = orderStatusMapReverse.get(data['405'], STATUS_UNKNOWN)
|
||||||
order.orderTime = data['346']
|
order.orderTime = data['346']
|
||||||
|
order.cancelTime = data['326']
|
||||||
|
|
||||||
self.orderDict[order.orderID] = order
|
self.orderDict[order.orderID] = order
|
||||||
self.localNoDict[order.orderID] = (data['300'], data['301'])
|
self.localNoDict[order.orderID] = (data['300'], data['301'])
|
||||||
|
self.orderNoDict[data['301']] = order.orderID
|
||||||
|
|
||||||
order.tradedVolume = int(data['315'])
|
order.tradedVolume = int(data['315'])
|
||||||
|
|
||||||
@ -448,20 +490,36 @@ class ShzdGatewayApi(ShzdApi):
|
|||||||
pos.exchange = exchangeMapReverse.get(data['306'], EXCHANGE_UNKNOWN)
|
pos.exchange = exchangeMapReverse.get(data['306'], EXCHANGE_UNKNOWN)
|
||||||
pos.vtSymbol = '.'.join([pos.symbol, pos.exchange])
|
pos.vtSymbol = '.'.join([pos.symbol, pos.exchange])
|
||||||
|
|
||||||
longPos = copy(pos)
|
# 多头仓位
|
||||||
longPos.direction = DIRECTION_LONG
|
longPosName = '.'.join([pos.vtSymbol, DIRECTION_LONG])
|
||||||
|
try:
|
||||||
|
longPos = self.posDict[longPosName]
|
||||||
|
except KeyError:
|
||||||
|
longPos = copy(pos)
|
||||||
|
longPos.direction = DIRECTION_LONG
|
||||||
|
longPos.vtPositionName = longPosName
|
||||||
|
self.posDict[longPosName] = longPos
|
||||||
|
|
||||||
longPos.position = int(data['442'])
|
longPos.position = int(data['442'])
|
||||||
longPos.price = float(data['443'])
|
longPos.price = float(data['443'])
|
||||||
longPos.vtPositionName = '.'.join([longPos.vtSymbol, longPos.direction])
|
|
||||||
|
|
||||||
shortPos = copy(pos)
|
# 空头仓位
|
||||||
shortPos.direction = DIRECTION_SHORT
|
shortPosName = '.'.join([pos.vtSymbol, DIRECTION_SHORT])
|
||||||
|
try:
|
||||||
|
shortPos = self.posDict[shortPosName]
|
||||||
|
except KeyError:
|
||||||
|
shortPos = copy(pos)
|
||||||
|
shortPos.direction = DIRECTION_SHORT
|
||||||
|
shortPos.vtPositionName = shortPosName
|
||||||
|
self.posDict[shortPosName] = shortPos
|
||||||
|
|
||||||
shortPos.position = int(data['445'])
|
shortPos.position = int(data['445'])
|
||||||
shortPos.price = float(data['446'])
|
shortPos.price = float(data['446'])
|
||||||
shortPos.vtPositionName = '.'.join([shortPos.vtSymbol, shortPos.direction])
|
|
||||||
|
# 所有持仓数据推送完成后才向事件引擎中更新持仓数据
|
||||||
self.gateway.onPosition(longPos)
|
if '410' in data and data['410'] == '1':
|
||||||
self.gateway.onPosition(shortPos)
|
for pos in self.posDict.values():
|
||||||
|
self.gateway.onPosition(pos)
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
def onQryAccount(self, data):
|
def onQryAccount(self, data):
|
||||||
@ -473,7 +531,8 @@ class ShzdGatewayApi(ShzdApi):
|
|||||||
account.accountID = data['11']
|
account.accountID = data['11']
|
||||||
account.vtAccountID = '.'.join([self.gatewayName, account.accountID])
|
account.vtAccountID = '.'.join([self.gatewayName, account.accountID])
|
||||||
account.preBalance = float(data['218'])
|
account.preBalance = float(data['218'])
|
||||||
account.available = float(data['203'])
|
account.balance = float(data['203'])
|
||||||
|
account.available = float(data['201'])
|
||||||
account.commission = float(data['221'])
|
account.commission = float(data['221'])
|
||||||
account.margin = float(data['212'])
|
account.margin = float(data['212'])
|
||||||
account.closeProfit = float(data['205'])
|
account.closeProfit = float(data['205'])
|
||||||
@ -497,7 +556,9 @@ class ShzdGatewayApi(ShzdApi):
|
|||||||
contract.size = float(data['336'])
|
contract.size = float(data['336'])
|
||||||
contract.priceTick = float(data['337'])
|
contract.priceTick = float(data['337'])
|
||||||
|
|
||||||
self.gateway.onContract(contract)
|
# 期权合约数量太多,为了方便起见默认接口只接收期货合约数据
|
||||||
|
if contract.productClass == PRODUCT_FUTURES:
|
||||||
|
self.gateway.onContract(contract)
|
||||||
|
|
||||||
if '410' in data and data['410'] == '1':
|
if '410' in data and data['410'] == '1':
|
||||||
self.gateway.writeLog(u'合约查询完成')
|
self.gateway.writeLog(u'合约查询完成')
|
||||||
@ -565,7 +626,7 @@ class ShzdGatewayApi(ShzdApi):
|
|||||||
req['401'] = priceTypeMap.get(orderReq.priceType, '')
|
req['401'] = priceTypeMap.get(orderReq.priceType, '')
|
||||||
|
|
||||||
self.localNo += 1
|
self.localNo += 1
|
||||||
req['305'] = str(self.localNo)
|
req['305'] = self.orderPrefix + str(self.localNo).rjust(10, '0')
|
||||||
|
|
||||||
self.shzdSendInfoToTrade(req)
|
self.shzdSendInfoToTrade(req)
|
||||||
|
|
||||||
@ -583,6 +644,7 @@ class ShzdGatewayApi(ShzdApi):
|
|||||||
order = self.orderDict[cancelReq.orderID]
|
order = self.orderDict[cancelReq.orderID]
|
||||||
|
|
||||||
req = {}
|
req = {}
|
||||||
|
req['msgtype'] = 'C'
|
||||||
req['12'] = self.userId
|
req['12'] = self.userId
|
||||||
req['11'] = self.accountNo
|
req['11'] = self.accountNo
|
||||||
req['300'] = systemNo
|
req['300'] = systemNo
|
||||||
@ -590,9 +652,11 @@ class ShzdGatewayApi(ShzdApi):
|
|||||||
req['306'] = exchangeMap.get(order.exchange, '')
|
req['306'] = exchangeMap.get(order.exchange, '')
|
||||||
req['307'] = order.symbol
|
req['307'] = order.symbol
|
||||||
req['308'] = directionMap.get(order.direction, '')
|
req['308'] = directionMap.get(order.direction, '')
|
||||||
req['309'] = str(order.volume)
|
req['309'] = str(order.totalVolume)
|
||||||
req['310'] = 0
|
req['310'] = str(order.price)
|
||||||
req['315'] = 0
|
req['315'] = str(order.tradedVolume)
|
||||||
|
|
||||||
|
self.shzdSendInfoToTrade(req)
|
||||||
else:
|
else:
|
||||||
self.cancelSet.add(cancelReq)
|
self.cancelSet.add(cancelReq)
|
||||||
|
|
||||||
@ -613,6 +677,11 @@ class ShzdGatewayApi(ShzdApi):
|
|||||||
req['12'] = self.userId
|
req['12'] = self.userId
|
||||||
req['11'] = self.accountNo
|
req['11'] = self.accountNo
|
||||||
self.shzdSendInfoToTrade(req)
|
self.shzdSendInfoToTrade(req)
|
||||||
|
|
||||||
|
# 清空持仓数据
|
||||||
|
for pos in self.posDict.values():
|
||||||
|
pos.price = 0
|
||||||
|
pos.position = 0
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
def qryContract(self):
|
def qryContract(self):
|
||||||
@ -650,34 +719,3 @@ def printDict(d):
|
|||||||
for k in l:
|
for k in l:
|
||||||
print k, ':', d[k]
|
print k, ':', d[k]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
|
|
||||||
api = TestApi()
|
|
||||||
|
|
||||||
# 初始化连接
|
|
||||||
api.initShZdServer()
|
|
||||||
|
|
||||||
# 注册前置机地址
|
|
||||||
print api.registerFront('222.73.119.230', 7003)
|
|
||||||
print api.registerMarket('222.73.119.230', 9003)
|
|
||||||
|
|
||||||
# 登录
|
|
||||||
sleep(1)
|
|
||||||
data = {}
|
|
||||||
data['msgtype'] = 'A'
|
|
||||||
data['12'] = 'demo000604'
|
|
||||||
data['16'] = '888888'
|
|
||||||
api.shzdSendInfoToTrade(data)
|
|
||||||
|
|
||||||
# 订阅行情
|
|
||||||
sleep(1)
|
|
||||||
data = {}
|
|
||||||
data['msgtype'] = 'MA'
|
|
||||||
data['11'] = '00010337'
|
|
||||||
data['201'] = '+'
|
|
||||||
data['307'] = "CME,6J1609"
|
|
||||||
api.shzdSendInfoToMarket(data)
|
|
||||||
|
|
||||||
raw_input()
|
|
@ -625,6 +625,7 @@ class TradingWidget(QtGui.QFrame):
|
|||||||
EXCHANGE_HKEX,
|
EXCHANGE_HKEX,
|
||||||
EXCHANGE_SMART,
|
EXCHANGE_SMART,
|
||||||
EXCHANGE_ICE,
|
EXCHANGE_ICE,
|
||||||
|
EXCHANGE_CME,
|
||||||
EXCHANGE_NYMEX,
|
EXCHANGE_NYMEX,
|
||||||
EXCHANGE_GLOBEX,
|
EXCHANGE_GLOBEX,
|
||||||
EXCHANGE_IDEALPRO]
|
EXCHANGE_IDEALPRO]
|
||||||
|
@ -122,7 +122,7 @@ class MainWindow(QtGui.QMainWindow):
|
|||||||
rmAction = QtGui.QAction(u'风险管理', self)
|
rmAction = QtGui.QAction(u'风险管理', self)
|
||||||
rmAction.triggered.connect(self.openRm)
|
rmAction.triggered.connect(self.openRm)
|
||||||
|
|
||||||
restoreAction = QtGui.QAction(u'还原窗口', self)
|
restoreAction = QtGui.QAction(u'还原', self)
|
||||||
restoreAction.triggered.connect(self.restoreWindow)
|
restoreAction.triggered.connect(self.restoreWindow)
|
||||||
|
|
||||||
# 创建菜单
|
# 创建菜单
|
||||||
|
@ -118,6 +118,7 @@ class MainEngine(object):
|
|||||||
try:
|
try:
|
||||||
from shzdGateway.shzdGateway import ShzdGateway
|
from shzdGateway.shzdGateway import ShzdGateway
|
||||||
self.addGateway(ShzdGateway, 'SHZD')
|
self.addGateway(ShzdGateway, 'SHZD')
|
||||||
|
self.gatewayDict['SHZD'].setQryEnabled(True)
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
print e
|
print e
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user