185 lines
6.5 KiB
Python
185 lines
6.5 KiB
Python
|
# encoding: UTF-8
|
|||
|
|
|||
|
'''
|
|||
|
Wind Python API的gateway接入
|
|||
|
'''
|
|||
|
|
|||
|
from copy import copy
|
|||
|
|
|||
|
try:
|
|||
|
from WindPy import w
|
|||
|
except ImportError:
|
|||
|
print(u'请先安装WindPy接口')
|
|||
|
|
|||
|
from vtGateway import *
|
|||
|
|
|||
|
# 交易所类型映射
|
|||
|
exchangeMap = {}
|
|||
|
exchangeMap[EXCHANGE_SSE] = 'SH'
|
|||
|
exchangeMap[EXCHANGE_SZSE] = 'SZ'
|
|||
|
exchangeMap[EXCHANGE_CFFEX] = 'CFE'
|
|||
|
exchangeMap[EXCHANGE_SHFE] = 'SHF'
|
|||
|
exchangeMap[EXCHANGE_DCE] = 'DCE'
|
|||
|
exchangeMap[EXCHANGE_CZCE] = 'CZC'
|
|||
|
exchangeMap[EXCHANGE_UNKNOWN] = ''
|
|||
|
exchangeMapReverse = {v:k for k,v in exchangeMap.items()}
|
|||
|
|
|||
|
|
|||
|
########################################################################
|
|||
|
class WindGateway(VtGateway):
|
|||
|
"""Wind接口"""
|
|||
|
# 订阅wsq时传入的字段列表
|
|||
|
wsqParamMap = {}
|
|||
|
wsqParamMap['rt_last'] = 'lastPrice'
|
|||
|
wsqParamMap['rt_last_vol'] = 'volume'
|
|||
|
wsqParamMap['rt_oi'] = 'openInterest'
|
|||
|
|
|||
|
wsqParamMap['rt_open'] = 'openPrice'
|
|||
|
wsqParamMap['rt_high'] = 'highPrice'
|
|||
|
wsqParamMap['rt_low'] = 'lowPrice'
|
|||
|
wsqParamMap['rt_pre_close'] = 'preClosePrice'
|
|||
|
|
|||
|
wsqParamMap['rt_high_limit'] = 'upperLimit'
|
|||
|
wsqParamMap['rt_low_limit'] = 'lowerLimit'
|
|||
|
|
|||
|
wsqParamMap['rt_bid1'] = 'bidPrice1'
|
|||
|
wsqParamMap['rt_bid2'] = 'bidPrice2'
|
|||
|
wsqParamMap['rt_bid3'] = 'bidPrice3'
|
|||
|
wsqParamMap['rt_bid4'] = 'bidPrice4'
|
|||
|
wsqParamMap['rt_bid5'] = 'bidPrice5'
|
|||
|
|
|||
|
wsqParamMap['rt_ask1'] = 'askPrice1'
|
|||
|
wsqParamMap['rt_ask2'] = 'askPrice2'
|
|||
|
wsqParamMap['rt_ask3'] = 'askPrice3'
|
|||
|
wsqParamMap['rt_ask4'] = 'askPrice4'
|
|||
|
wsqParamMap['rt_ask5'] = 'askPrice5'
|
|||
|
|
|||
|
wsqParamMap['rt_bsize1'] = 'bidVolume1'
|
|||
|
wsqParamMap['rt_bsize2'] = 'bidVolume2'
|
|||
|
wsqParamMap['rt_bsize3'] = 'bidVolume3'
|
|||
|
wsqParamMap['rt_bsize4'] = 'bidVolume4'
|
|||
|
wsqParamMap['rt_bsize5'] = 'bidVolume5'
|
|||
|
|
|||
|
wsqParamMap['rt_asize1'] = 'askVolume1'
|
|||
|
wsqParamMap['rt_asize2'] = 'askVolume2'
|
|||
|
wsqParamMap['rt_asize3'] = 'askVolume3'
|
|||
|
wsqParamMap['rt_asize4'] = 'askVolume4'
|
|||
|
wsqParamMap['rt_asize5'] = 'askVolume5'
|
|||
|
|
|||
|
wsqParam = ','.join(wsqParamMap.keys())
|
|||
|
|
|||
|
#----------------------------------------------------------------------
|
|||
|
def __init__(self, eventEngine, gatewayName='Wind'):
|
|||
|
"""Constructor"""
|
|||
|
super(WindGateway, self).__init__(eventEngine, gatewayName)
|
|||
|
|
|||
|
self.w = w # Wind API对象
|
|||
|
self.connected = False # 连接状态
|
|||
|
|
|||
|
# Wind的wsq更新采用的是增量更新模式,每次推送只会更新发生变化的字段
|
|||
|
# 而vt中的tick是完整更新,因此需要本地维护一个所有字段的快照
|
|||
|
self.tickDict = {}
|
|||
|
|
|||
|
self.registerEvent()
|
|||
|
|
|||
|
#----------------------------------------------------------------------
|
|||
|
def connect(self):
|
|||
|
"""连接"""
|
|||
|
# 由于w.start方法会阻塞较长时间
|
|||
|
# 因此设计为异步模式,交给事件处理线程去处理
|
|||
|
# 另外w.start和WingIDE的debug模块有冲突,会导致异常退出
|
|||
|
event = Event(type_=EVENT_WIND_CONNECTREQ)
|
|||
|
self.eventEngine.put(event)
|
|||
|
|
|||
|
#----------------------------------------------------------------------
|
|||
|
def subscribe(self, subscribeReq):
|
|||
|
"""订阅行情"""
|
|||
|
windSymbol = '.'.join([subscribeReq.symbol, exchangeMap[subscribeReq.exchange]])
|
|||
|
data = self.w.wsq(windSymbol, self.wsqParam, func=self.wsqCallBack)
|
|||
|
|
|||
|
#----------------------------------------------------------------------
|
|||
|
def sendOrder(self, orderReq):
|
|||
|
"""发单"""
|
|||
|
log = VtLogData()
|
|||
|
log.gatewayName = self.gatewayName
|
|||
|
log.logContent = u'Wind接口未实现发单功能'
|
|||
|
self.onLog(log)
|
|||
|
|
|||
|
#----------------------------------------------------------------------
|
|||
|
def cancelOrder(self, cancelOrderReq):
|
|||
|
"""撤单"""
|
|||
|
log = VtLogData()
|
|||
|
log.gatewayName = self.gatewayName
|
|||
|
log.logContent = u'Wind接口未实现撤单功能'
|
|||
|
self.onLog(log)
|
|||
|
|
|||
|
#----------------------------------------------------------------------
|
|||
|
def getAccount(self):
|
|||
|
"""查询账户资金"""
|
|||
|
log = VtLogData()
|
|||
|
log.gatewayName = self.gatewayName
|
|||
|
log.logContent = u'Wind接口未实现查询账户功能'
|
|||
|
self.onLog(log)
|
|||
|
|
|||
|
#----------------------------------------------------------------------
|
|||
|
def getPosition(self):
|
|||
|
"""查询持仓"""
|
|||
|
log = VtLogData()
|
|||
|
log.gatewayName = self.gatewayName
|
|||
|
log.logContent = u'Wind接口未实现查询持仓功能'
|
|||
|
self.onLog(log)
|
|||
|
|
|||
|
#----------------------------------------------------------------------
|
|||
|
def close(self):
|
|||
|
self.w.stop()
|
|||
|
|
|||
|
#----------------------------------------------------------------------
|
|||
|
def registerEvent(self):
|
|||
|
"""注册事件监听"""
|
|||
|
self.eventEngine.register(EVENT_WIND_CONNECTREQ, self.wConnect)
|
|||
|
|
|||
|
#----------------------------------------------------------------------
|
|||
|
def wsqCallBack(self, data):
|
|||
|
"""收到wsq推送"""
|
|||
|
windSymbol = data.Codes[0]
|
|||
|
if windSymbol in self.tickDict:
|
|||
|
tick = self.tickDict[windSymbol]
|
|||
|
else:
|
|||
|
tick = VtTickData()
|
|||
|
tick.gatewayName = self.gatewayName
|
|||
|
symbolSplit = windSymbol.split('.')
|
|||
|
tick.symbol = symbolSplit[0]
|
|||
|
tick.exchange = exchangeMapReverse[symbolSplit[1]]
|
|||
|
tick.vtSymbol = '.'.join([tick.symbol, tick.exchange])
|
|||
|
self.tickDict[windSymbol] = tick
|
|||
|
|
|||
|
dt = data.Times[0]
|
|||
|
tick.time = dt.strftime('%H:%M:%S')
|
|||
|
tick.date = dt.strftime('%Y%m%d')
|
|||
|
|
|||
|
# 采用遍历的形式读取数值
|
|||
|
fields = data.Fields
|
|||
|
values = data.Data
|
|||
|
d = tick.__dict__
|
|||
|
for n, field in enumerate(fields):
|
|||
|
field = field.lower()
|
|||
|
key = self.wsqParamMap[field]
|
|||
|
value = values[n][0]
|
|||
|
d[key] = value
|
|||
|
|
|||
|
newtick = copy(tick)
|
|||
|
self.onTick(newtick)
|
|||
|
|
|||
|
#----------------------------------------------------------------------
|
|||
|
def wConnect(self, event):
|
|||
|
"""利用事件处理线程去异步连接Wind接口"""
|
|||
|
result = self.w.start()
|
|||
|
|
|||
|
log = VtLogData()
|
|||
|
log.gatewayName = self.gatewayName
|
|||
|
|
|||
|
if not result.ErrorCode:
|
|||
|
log.logContent = u'Wind接口连接成功'
|
|||
|
else:
|
|||
|
log.logContent = u'Wind接口连接失败,错误代码%d' %result.ErrorCode
|
|||
|
self.onLog(log)
|