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) |