修复之前版本里的一些bug,并完成CTA用数据记录工具(tick和分钟线)

This commit is contained in:
WOLF 2015-11-20 14:11:29 +08:00
parent 7d147515d6
commit 241808b45b
16 changed files with 353 additions and 176 deletions

View File

@ -1,14 +1,10 @@
{ {
"Test1": { "DR_IF1512": {
"strategyClassName": "TestStrategy", "strategyClassName": "DataRecorder",
"vtSymbol": "IF1511"
},
"Test3": {
"strategyClassName": "TestStrategy",
"vtSymbol": "IF1512" "vtSymbol": "IF1512"
}, },
"Test2": { "DR_IH1512": {
"strategyClassName": "TestStrategy", "strategyClassName": "DataRecorder",
"vtSymbol": "IH1511" "vtSymbol": "IH1512"
} }
} }

Binary file not shown.

View File

@ -0,0 +1,106 @@
# encoding: UTF-8
from ctaStrategyTemplate import *
from ctaObject import CtaBarData
########################################################################
class DataRecorder(CtaStrategyTemplate):
"""
纯粹用来记录历史数据的工具基于CTA策略
建议运行在实际交易程序外的一个vn.trader实例中
本工具会记录Tick和1分钟K线数据
"""
#----------------------------------------------------------------------
def __init__(self, ctaEngine, name, setting=None):
"""Constructor"""
super(DataRecorder, self).__init__(ctaEngine, name, setting)
self.strategyClassName = 'DataRecorder'
self.author = u'用Python的交易员'
self.tickDbName = 'VtTrader_Tick_Db'
self.barDbName = 'VtTrader_1Min_Db'
self.paramList.append('author')
# 数据记录相关
self.bar = None # K线数据对象
self.barMinute = -1 # 当前的分钟,初始化设为-1
#----------------------------------------------------------------------
def init(self):
"""初始化"""
self.writeCtaLog(u'数据记录工具%s初始化' %self.name)
#----------------------------------------------------------------------
def start(self):
"""启动策略(必须由用户继承实现)"""
self.writeCtaLog(u'数据记录工具%s启动' %self.name)
#----------------------------------------------------------------------
def stop(self):
"""停止策略(必须由用户继承实现)"""
self.writeCtaLog(u'数据记录工具%s停止' %self.name)
#----------------------------------------------------------------------
def onTick(self, tick):
"""收到行情TICK推送"""
# 收到Tick后首先插入到数据库里
self.insertTick(tick)
# 计算K线
tickMinute = tick.datetime.minute
if tickMinute != self.barMinute: # 如果分钟变了则把旧的K线插入数据库并生成新的K线
if self.bar:
self.onBar(self.bar)
bar = CtaBarData() # 创建新的K线目的在于防止之前K线对象在插入Mongo中被再次修改导致出错
bar.vtSymbol = tick.vtSymbol
bar.symbol = tick.symbol
bar.exchange = tick.exchange
bar.open = tick.lastPrice
bar.high = tick.lastPrice
bar.low = tick.lastPrice
bar.close = tick.lastPrice
bar.date = tick.date
bar.time = tick.time
bar.datetime = tick.datetime # K线的时间设为第一个Tick的时间
bar.volume = tick.volume
bar.openInterest = tick.openInterest
self.bar = bar # 这种写法为了减少一层访问,加快速度
self.barMinute = tickMinute # 更新当前的分钟
else: # 否则继续累加新的K线
bar = self.bar # 写法同样为了加快速度
bar.high = max(bar.high, tick.lastPrice)
bar.low = min(bar.low, tick.lastPrice)
bar.close = tick.lastPrice
bar.volume = bar.volume + tick.volume # 成交量是累加的
bar.openInterest = tick.openInterest # 持仓量直接更新
#----------------------------------------------------------------------
def onOrder(self, order):
"""收到委托变化推送"""
pass
#----------------------------------------------------------------------
def onTrade(self, trade):
"""收到成交推送"""
pass
#----------------------------------------------------------------------
def onBar(self, bar):
"""收到Bar推送"""
self.insertBar(bar)

View File

@ -9,100 +9,10 @@ from vtConstant import *
from vtGateway import VtSubscribeReq, VtOrderReq, VtCancelOrderReq, VtLogData from vtGateway import VtSubscribeReq, VtOrderReq, VtCancelOrderReq, VtLogData
from ctaConstant import * from ctaConstant import *
from ctaObject import *
from ctaStrategies import strategyClassDict from ctaStrategies import strategyClassDict
########################################################################
class StopOrder(object):
"""本地停止单"""
#----------------------------------------------------------------------
def __init__(self):
"""Constructor"""
self.vtSymbol = EMPTY_STRING
self.orderType = EMPTY_UNICODE
self.price = EMPTY_FLOAT
self.volume = EMPTY_INT
self.strategy = None # 下停止单的策略对象
self.stopOrderID = EMPTY_STRING # 停止单的本地编号
self.status = EMPTY_STRING # 停止单状态
########################################################################
class CtaBarData(object):
"""K线数据"""
#----------------------------------------------------------------------
def __init__(self):
"""Constructor"""
self.vtSymbol = EMPTY_STRING # vt系统代码
self.symbol = EMPTY_STRING # 代码
self.exchange = EMPTY_STRING # 交易所
self.open = EMPTY_FLOAT # OHLC
self.high = EMPTY_FLOAT
self.low = EMPTY_FLOAT
self.close = EMPTY_FLOAT
self.date = EMPTY_STRING # bar开始的时间日期
self.time = EMPTY_STRING # 时间
self.datetime = None # python的datetime时间对象
self.volume = EMPTY_INT # 成交量
self.openInterest = EMPTY_INT # 持仓量
########################################################################
class CtaTickData(object):
"""Tick数据"""
#----------------------------------------------------------------------
def __init__(self):
"""Constructor"""
self.vtSymbol = EMPTY_STRING # vt系统代码
self.symbol = EMPTY_STRING # 合约代码
self.exchange = EMPTY_STRING # 交易所代码
# 成交数据
self.lastPrice = EMPTY_FLOAT # 最新成交价
self.volume = EMPTY_INT # 最新成交量
self.openInterest = EMPTY_INT # 持仓量
self.upperLimit = EMPTY_FLOAT # 涨停价
self.lowerLimit = EMPTY_FLOAT # 跌停价
# tick的时间
self.date = EMPTY_STRING # 日期
self.time = EMPTY_STRING # 时间
self.datetime = None # python的datetime时间对象
# 五档行情
self.bidPrice1 = EMPTY_FLOAT
self.bidPrice2 = EMPTY_FLOAT
self.bidPrice3 = EMPTY_FLOAT
self.bidPrice4 = EMPTY_FLOAT
self.bidPrice5 = EMPTY_FLOAT
self.askPrice1 = EMPTY_FLOAT
self.askPrice2 = EMPTY_FLOAT
self.askPrice3 = EMPTY_FLOAT
self.askPrice4 = EMPTY_FLOAT
self.askPrice5 = EMPTY_FLOAT
self.bidVolume1 = EMPTY_INT
self.bidVolume2 = EMPTY_INT
self.bidVolume3 = EMPTY_INT
self.bidVolume4 = EMPTY_INT
self.bidVolume5 = EMPTY_INT
self.askVolume1 = EMPTY_INT
self.askVolume2 = EMPTY_INT
self.askVolume3 = EMPTY_INT
self.askVolume4 = EMPTY_INT
self.askVolume5 = EMPTY_INT
######################################################################## ########################################################################
class CtaEngine(object): class CtaEngine(object):
"""CTA策略引擎""" """CTA策略引擎"""
@ -266,7 +176,7 @@ class CtaEngine(object):
# 逐个推送到策略对象中 # 逐个推送到策略对象中
l = self.tickStrategyDict[tick.vtSymbol] l = self.tickStrategyDict[tick.vtSymbol]
for strategy in l: for strategy in l:
strategy.onTick(tick) strategy.onTick(ctaTick)
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def processOrderEvent(self, event): def processOrderEvent(self, event):
@ -366,6 +276,8 @@ class CtaEngine(object):
req.symbol = contract.symbol req.symbol = contract.symbol
req.exchange = contract.exchange req.exchange = contract.exchange
self.mainEngine.subscribe(req, contract.gatewayName) self.mainEngine.subscribe(req, contract.gatewayName)
else:
self.writeCtaLog(u'%s的交易合约%s无法找到' %(name, strategy.vtSymbol))
else: else:
self.writeCtaLog(u'存在策略对象重名:' + name) self.writeCtaLog(u'存在策略对象重名:' + name)

95
vn.trader/ctaObject.py Normal file
View File

@ -0,0 +1,95 @@
# encoding: UTF-8
from vtConstant import EMPTY_UNICODE, EMPTY_STRING, EMPTY_FLOAT, EMPTY_INT
########################################################################
class StopOrder(object):
"""本地停止单"""
#----------------------------------------------------------------------
def __init__(self):
"""Constructor"""
self.vtSymbol = EMPTY_STRING
self.orderType = EMPTY_UNICODE
self.price = EMPTY_FLOAT
self.volume = EMPTY_INT
self.strategy = None # 下停止单的策略对象
self.stopOrderID = EMPTY_STRING # 停止单的本地编号
self.status = EMPTY_STRING # 停止单状态
########################################################################
class CtaBarData(object):
"""K线数据"""
#----------------------------------------------------------------------
def __init__(self):
"""Constructor"""
self.vtSymbol = EMPTY_STRING # vt系统代码
self.symbol = EMPTY_STRING # 代码
self.exchange = EMPTY_STRING # 交易所
self.open = EMPTY_FLOAT # OHLC
self.high = EMPTY_FLOAT
self.low = EMPTY_FLOAT
self.close = EMPTY_FLOAT
self.date = EMPTY_STRING # bar开始的时间日期
self.time = EMPTY_STRING # 时间
self.datetime = None # python的datetime时间对象
self.volume = EMPTY_INT # 成交量
self.openInterest = EMPTY_INT # 持仓量
########################################################################
class CtaTickData(object):
"""Tick数据"""
#----------------------------------------------------------------------
def __init__(self):
"""Constructor"""
self.vtSymbol = EMPTY_STRING # vt系统代码
self.symbol = EMPTY_STRING # 合约代码
self.exchange = EMPTY_STRING # 交易所代码
# 成交数据
self.lastPrice = EMPTY_FLOAT # 最新成交价
self.volume = EMPTY_INT # 最新成交量
self.openInterest = EMPTY_INT # 持仓量
self.upperLimit = EMPTY_FLOAT # 涨停价
self.lowerLimit = EMPTY_FLOAT # 跌停价
# tick的时间
self.date = EMPTY_STRING # 日期
self.time = EMPTY_STRING # 时间
self.datetime = None # python的datetime时间对象
# 五档行情
self.bidPrice1 = EMPTY_FLOAT
self.bidPrice2 = EMPTY_FLOAT
self.bidPrice3 = EMPTY_FLOAT
self.bidPrice4 = EMPTY_FLOAT
self.bidPrice5 = EMPTY_FLOAT
self.askPrice1 = EMPTY_FLOAT
self.askPrice2 = EMPTY_FLOAT
self.askPrice3 = EMPTY_FLOAT
self.askPrice4 = EMPTY_FLOAT
self.askPrice5 = EMPTY_FLOAT
self.bidVolume1 = EMPTY_INT
self.bidVolume2 = EMPTY_INT
self.bidVolume3 = EMPTY_INT
self.bidVolume4 = EMPTY_INT
self.bidVolume5 = EMPTY_INT
self.askVolume1 = EMPTY_INT
self.askVolume2 = EMPTY_INT
self.askVolume3 = EMPTY_INT
self.askVolume4 = EMPTY_INT
self.askVolume5 = EMPTY_INT

View File

@ -2,9 +2,15 @@
''' '''
在本文件中引入所有希望在系统中使用的策略类 在本文件中引入所有希望在系统中使用的策略类
这个字典中保存了需要运行的策略的名称和策略类的映射关系
用户的策略类写好后先在该文件中引入并设置好名称然后
在CTA_setting.json中写入具体每个策略对象的类和合约设置
''' '''
from ctaStrategyTemplate import TestStrategy from ctaStrategyTemplate import TestStrategy
from ctaDataRecorder import DataRecorder
strategyClassDict = {} strategyClassDict = {}
strategyClassDict[u'TestStrategy'] = TestStrategy strategyClassDict['TestStrategy'] = TestStrategy
strategyClassDict['DataRecorder'] = DataRecorder

View File

@ -186,7 +186,7 @@ class TestStrategy(CtaStrategyTemplate):
self.lastPrice = EMPTY_FLOAT # 最新价 self.lastPrice = EMPTY_FLOAT # 最新价
# 参数和变量列表设置 # 参数和变量列表设置
self.paramList.append(u'author') self.paramList.append('author')
self.varList.append('pos') self.varList.append('pos')
self.varList.append('lastPrice') self.varList.append('lastPrice')

View File

@ -638,6 +638,7 @@ class CtpTdApi(TdApi):
# 持仓量 # 持仓量
pos.position = data['Position'] pos.position = data['Position']
pos.ydPosition = data['YdPosition']
# 持仓均价 # 持仓均价
if pos.position: if pos.position:

View File

@ -30,6 +30,13 @@ EVENT_CTA_LOG = 'eCtaLog' # CTA相关的日志事件
# Wind接口相关 # Wind接口相关
EVENT_WIND_CONNECTREQ = 'eWindConnectReq' # Wind接口请求连接事件 EVENT_WIND_CONNECTREQ = 'eWindConnectReq' # Wind接口请求连接事件
# 20151020后更新
# LTS Gateway相关
EVENT_LTS_SF = 'eLtsSf.' # SF基金查询推送事件
# 分级A算法相关
EVENT_FUNDA_DATA = 'eFaData.' # 分级A基金更新事件
EVENT_FUNDA_LOG = 'eFaLog' # 分级A算法日志事件
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def test(): def test():

View File

@ -321,7 +321,7 @@ class LtsMdApi(MdApi):
tick.lastPrice = data['LastPrice'] tick.lastPrice = data['LastPrice']
tick.volume = data['Volume'] tick.volume = data['Volume']
tick.openInterest = data['OpenInterest'] tick.openInterest = data['OpenInterest']
tick.tickTime = '.'.join([data['UpdateTime'], str(data['UpdateMillisec']/100)]) tick.time = '.'.join([data['UpdateTime'], str(data['UpdateMillisec']/100)])
tick.date = data['TradingDay'] tick.date = data['TradingDay']
tick.openPrice = data['OpenPrice'] tick.openPrice = data['OpenPrice']
@ -392,7 +392,7 @@ class LtsMdApi(MdApi):
"""订阅合约""" """订阅合约"""
req = {} req = {}
req['InstrumentID'] = str(subscribeReq.symbol) req['InstrumentID'] = str(subscribeReq.symbol)
req['ExchangeID'] = str(subscribeReq.exchange) req['ExchangeID'] = exchangeMap.get(str(subscribeReq.exchange), '')
# 这里的设计是,如果尚未登录就调用了订阅方法 # 这里的设计是,如果尚未登录就调用了订阅方法
# 则先保存订阅请求,登录完成后会自动订阅 # 则先保存订阅请求,登录完成后会自动订阅
@ -579,7 +579,7 @@ class LtsTdApi(TdApi):
# 保存代码和报单号 # 保存代码和报单号
order.symbol = data['InstrumentID'] order.symbol = data['InstrumentID']
order.exchange = exchangeMapReverse[data['ExchangeID']] order.exchange = exchangeMapReverse.get(data['ExchangeID'], '')
order.vtSymbol = '.'.join([order.symbol, order.exchange]) order.vtSymbol = '.'.join([order.symbol, order.exchange])
order.orderID = data['OrderRef'] order.orderID = data['OrderRef']
@ -613,7 +613,7 @@ class LtsTdApi(TdApi):
order.status = STATUS_UNKNOWN order.status = STATUS_UNKNOWN
# 价格、报单量等数值 # 价格、报单量等数值
order.price = data['LimitPrice'] order.price = float(data['LimitPrice'])
order.totalVolume = data['VolumeTotalOriginal'] order.totalVolume = data['VolumeTotalOriginal']
order.tradedVolume = data['VolumeTraded'] order.tradedVolume = data['VolumeTraded']
order.orderTime = data['InsertTime'] order.orderTime = data['InsertTime']
@ -636,7 +636,7 @@ class LtsTdApi(TdApi):
# 保存代码和报单号 # 保存代码和报单号
trade.symbol = data['InstrumentID'] trade.symbol = data['InstrumentID']
trade.exchange = exchangeMapReverse[data['ExchangeID']] trade.exchange = exchangeMapReverse.get(data['ExchangeID'], '')
trade.vtSymbol = '.'.join([trade.symbol, trade.exchange]) trade.vtSymbol = '.'.join([trade.symbol, trade.exchange])
trade.tradeID = data['TradeID'] trade.tradeID = data['TradeID']
@ -652,7 +652,7 @@ class LtsTdApi(TdApi):
trade.offset = offsetMapReverse.get(data['OffsetFlag'], '') trade.offset = offsetMapReverse.get(data['OffsetFlag'], '')
# 价格、报单量等数值 # 价格、报单量等数值
trade.price = data['Price'] trade.price = float(data['Price'])
trade.volume = data['Volume'] trade.volume = data['Volume']
trade.tradeTime = data['TradeTime'] trade.tradeTime = data['TradeTime']
@ -764,10 +764,10 @@ class LtsTdApi(TdApi):
req = {} req = {}
req['InstrumentID'] = orderReq.symbol req['InstrumentID'] = str(orderReq.symbol)
req['LimitPrice'] = str(orderReq.price) # LTS里的价格是字符串 req['LimitPrice'] = str(orderReq.price) # LTS里的价格是字符串
req['VolumeTotalOriginal'] = orderReq.volume req['VolumeTotalOriginal'] = int(orderReq.volume)
req['ExchangeID'] = orderReq.exchange req['ExchangeID'] = exchangeMap.get(orderReq.exchange, '')
# 下面如果由于传入的类型本接口不支持,则会返回空字符串 # 下面如果由于传入的类型本接口不支持,则会返回空字符串
try: try:
@ -1063,7 +1063,17 @@ class LtsQryApi(QryApi):
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def onRspQrySFInstrument(self, data, error, n, last): def onRspQrySFInstrument(self, data, error, n, last):
"""SF合约查询回报""" """SF合约查询回报"""
pass event1 = Event(type_=EVENT_LTS_SF)
event1.dict_['data'] = data
self.gateway.eventEngine.put(event1)
symbol = data['InstrumentID']
exchange = exchangeMapReverse[data['ExchangeID']]
vtSymbol = '.'.join([symbol, exchange])
event2 = Event(type_=EVENT_LTS_SF + vtSymbol)
event2.dict_['data'] = data
self.gateway.eventEngine.put(event2)
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def onRspQryInstrumentUnitMargin(self, data, error, n, last): def onRspQryInstrumentUnitMargin(self, data, error, n, last):
@ -1133,11 +1143,12 @@ class LtsQryApi(QryApi):
# 保存代码 # 保存代码
pos.symbol = data['InstrumentID'] pos.symbol = data['InstrumentID']
pos.exchange = data['ExchangeID'] pos.exchange = exchangeMapReverse.get(data['ExchangeID'], '')
pos.vtSymbol = '.'.join([pos.symbol, pos.exchange]) pos.vtSymbol = '.'.join([pos.symbol, pos.exchange])
# 方向和持仓冻结数量 # 方向和持仓冻结数量
pos.direction = posiDirectionMapReverse.get(data['PosiDirection'], '') pos.direction = posiDirectionMapReverse.get(data['PosiDirection'], '')
if pos.direction == DIRECTION_NET or pos.direction == DIRECTION_LONG: if pos.direction == DIRECTION_NET or pos.direction == DIRECTION_LONG:
pos.frozen = data['LongFrozen'] pos.frozen = data['LongFrozen']
elif pos.direction == DIRECTION_SHORT: elif pos.direction == DIRECTION_SHORT:
@ -1145,6 +1156,7 @@ class LtsQryApi(QryApi):
# 持仓量 # 持仓量
pos.position = data['Position'] pos.position = data['Position']
pos.ydPosition = data['YdPosition']
# 持仓均价 # 持仓均价
if pos.position: if pos.position:

View File

@ -472,6 +472,7 @@ class PositionMonitor(BasicMonitor):
d['vtSymbol'] = {'chinese':u'名称', 'cellType':NameCell} d['vtSymbol'] = {'chinese':u'名称', 'cellType':NameCell}
d['direction'] = {'chinese':u'方向', 'cellType':DirectionCell} d['direction'] = {'chinese':u'方向', 'cellType':DirectionCell}
d['position'] = {'chinese':u'持仓量', 'cellType':BasicCell} d['position'] = {'chinese':u'持仓量', 'cellType':BasicCell}
d['ydPosition'] = {'chinese':u'昨持仓', 'cellType':BasicCell}
d['frozen'] = {'chinese':u'冻结量', 'cellType':BasicCell} d['frozen'] = {'chinese':u'冻结量', 'cellType':BasicCell}
d['price'] = {'chinese':u'价格', 'cellType':BasicCell} d['price'] = {'chinese':u'价格', 'cellType':BasicCell}
d['gatewayName'] = {'chinese':u'接口', 'cellType':BasicCell} d['gatewayName'] = {'chinese':u'接口', 'cellType':BasicCell}
@ -755,7 +756,7 @@ class TradingWidget(QtGui.QFrame):
def updateSymbol(self): def updateSymbol(self):
"""合约变化""" """合约变化"""
# 读取组件数据 # 读取组件数据
symbol = unicode(self.lineSymbol.text()) symbol = str(self.lineSymbol.text())
exchange = unicode(self.comboExchange.currentText()) exchange = unicode(self.comboExchange.currentText())
currency = unicode(self.comboCurrency.currentText()) currency = unicode(self.comboCurrency.currentText())
productClass = unicode(self.comboProductClass.currentText()) productClass = unicode(self.comboProductClass.currentText())
@ -866,7 +867,7 @@ class TradingWidget(QtGui.QFrame):
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def sendOrder(self): def sendOrder(self):
"""发单""" """发单"""
symbol = unicode(self.lineSymbol.text()) symbol = str(self.lineSymbol.text())
exchange = unicode(self.comboExchange.currentText()) exchange = unicode(self.comboExchange.currentText())
currency = unicode(self.comboCurrency.currentText()) currency = unicode(self.comboCurrency.currentText())
productClass = unicode(self.comboProductClass.currentText()) productClass = unicode(self.comboProductClass.currentText())

View File

@ -5,6 +5,7 @@ import psutil
from uiBasicWidget import * from uiBasicWidget import *
from uiCtaWidget import CtaEngineManager from uiCtaWidget import CtaEngineManager
######################################################################## ########################################################################
class MainWindow(QtGui.QMainWindow): class MainWindow(QtGui.QMainWindow):
"""主窗口""" """主窗口"""
@ -18,6 +19,8 @@ class MainWindow(QtGui.QMainWindow):
self.eventEngine = eventEngine self.eventEngine = eventEngine
self.dataEngine = dataEngine self.dataEngine = dataEngine
self.widgetDict = {} # 用来保存子窗口的字典
self.initUi() self.initUi()
#---------------------------------------------------------------------- #----------------------------------------------------------------------
@ -80,6 +83,9 @@ class MainWindow(QtGui.QMainWindow):
connectIbAction = QtGui.QAction(u'连接IB', self) connectIbAction = QtGui.QAction(u'连接IB', self)
connectIbAction.triggered.connect(self.connectIb) connectIbAction.triggered.connect(self.connectIb)
connectDbAction = QtGui.QAction(u'连接数据库', self)
connectDbAction.triggered.connect(self.mainEngine.dbConnect)
testAction = QtGui.QAction(u'测试', self) testAction = QtGui.QAction(u'测试', self)
testAction.triggered.connect(self.testSubscribe) testAction.triggered.connect(self.testSubscribe)
@ -103,13 +109,20 @@ class MainWindow(QtGui.QMainWindow):
sysMenu.addAction(connectLtsAction) sysMenu.addAction(connectLtsAction)
sysMenu.addAction(connectWindAction) sysMenu.addAction(connectWindAction)
sysMenu.addAction(connectIbAction) sysMenu.addAction(connectIbAction)
sysMenu.addSeparator()
sysMenu.addAction(connectDbAction)
sysMenu.addSeparator()
sysMenu.addAction(testAction) sysMenu.addAction(testAction)
sysMenu.addAction(exitAction) sysMenu.addAction(exitAction)
functionMenu = menubar.addMenu(u'功能') functionMenu = menubar.addMenu(u'功能')
functionMenu.addAction(contractAction) functionMenu.addAction(contractAction)
functionMenu.addAction(ctaAction)
# 算法相关
algoMenu = menubar.addMenu(u'算法')
algoMenu.addAction(ctaAction)
# 帮助
helpMenu = menubar.addMenu(u'帮助') helpMenu = menubar.addMenu(u'帮助')
helpMenu.addAction(aboutAction) helpMenu.addAction(aboutAction)
@ -165,51 +178,55 @@ class MainWindow(QtGui.QMainWindow):
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def testSubscribe(self): def testSubscribe(self):
"""测试订阅""" """测试订阅"""
req = VtSubscribeReq() api = self.mainEngine.gatewayDict['LTS'].qryApi
req.symbol = 'GOOG' api.reqID += 1
req.productClass = PRODUCT_EQUITY api.reqQryOFInstrument({}, api.reqID)
req.exchange = EXCHANGE_SMART
req.currency = CURRENCY_USD
self.mainEngine.subscribe(req, 'IB')
req.symbol = 'AAPL' #req = VtSubscribeReq()
self.mainEngine.subscribe(req, 'IB') #req.symbol = 'GOOG'
#req.productClass = PRODUCT_EQUITY
#req.exchange = EXCHANGE_SMART
#req.currency = CURRENCY_USD
#self.mainEngine.subscribe(req, 'IB')
req.symbol = 'YHOO' #req.symbol = 'AAPL'
self.mainEngine.subscribe(req, 'IB') #self.mainEngine.subscribe(req, 'IB')
req.symbol = 'MSFT' #req.symbol = 'YHOO'
self.mainEngine.subscribe(req, 'IB') #self.mainEngine.subscribe(req, 'IB')
req.symbol = 'GE' #req.symbol = 'MSFT'
self.mainEngine.subscribe(req, 'IB') #self.mainEngine.subscribe(req, 'IB')
#req.symbol = 'GE'
#self.mainEngine.subscribe(req, 'IB')
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def openAbout(self): def openAbout(self):
"""打开关于""" """打开关于"""
try: try:
self.aboutW.show() self.widgetDict['aboutW'].show()
except AttributeError: except KeyError:
self.aboutW = AboutWidget(self) self.widgetDict['aboutW'] = AboutWidget(self)
self.aboutW.show() self.widgetDict['aboutW'].show()
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def openContract(self): def openContract(self):
"""打开合约查询""" """打开合约查询"""
try: try:
self.contractM.show() self.widgetDict['contractM'].show()
except AttributeError: except KeyError:
self.contractM = ContractMonitor(self.mainEngine.dataEngine) self.widgetDict['contractM'] = ContractMonitor(self.mainEngine.dataEngine)
self.contractM.show() self.widgetDict['contractM'].show()
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def openCta(self): def openCta(self):
"""打开CTA组件""" """打开CTA组件"""
try: try:
self.ctaM.show() self.widgetDict['ctaM'].show()
except AttributeError: except KeyError:
self.ctaM = CtaEngineManager(self.mainEngine.ctaEngine, self.eventEngine) self.widgetDict['ctaM'] = CtaEngineManager(self.mainEngine.ctaEngine, self.eventEngine)
self.ctaM.show() self.widgetDict['ctaM'].show()
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def closeEvent(self, event): def closeEvent(self, event):
@ -219,6 +236,8 @@ class MainWindow(QtGui.QMainWindow):
QtGui.QMessageBox.No, QtGui.QMessageBox.No) QtGui.QMessageBox.No, QtGui.QMessageBox.No)
if reply == QtGui.QMessageBox.Yes: if reply == QtGui.QMessageBox.Yes:
for widget in self.widgetDict.values():
widget.close()
self.mainEngine.exit() self.mainEngine.exit()
event.accept() event.accept()
else: else:

View File

@ -49,19 +49,19 @@ OPTION_CALL = u'看涨期权'
OPTION_PUT = u'看跌期权' OPTION_PUT = u'看跌期权'
# 交易所类型 # 交易所类型
EXCHANGE_SSE = u'SSE' # 上交所 EXCHANGE_SSE = 'SSE' # 上交所
EXCHANGE_SZSE = u'SZSE' # 深交所 EXCHANGE_SZSE = 'SZSE' # 深交所
EXCHANGE_CFFEX = u'CFFEX' # 中金所 EXCHANGE_CFFEX = 'CFFEX' # 中金所
EXCHANGE_SHFE = u'SHFE' # 上期所 EXCHANGE_SHFE = 'SHFE' # 上期所
EXCHANGE_CZCE = u'CZCE' # 郑商所 EXCHANGE_CZCE = 'CZCE' # 郑商所
EXCHANGE_DCE = u'DCE' # 大商所 EXCHANGE_DCE = 'DCE' # 大商所
EXCHANGE_UNKNOWN = 'UNKNOWN'# 未知交易所 EXCHANGE_UNKNOWN = 'UNKNOWN'# 未知交易所
EXCHANGE_NONE = '' # 空交易所 EXCHANGE_NONE = '' # 空交易所
EXCHANGE_SMART = u'SMART' # IB智能路由股票、期权 EXCHANGE_SMART = 'SMART' # IB智能路由股票、期权
EXCHANGE_GLOBEX = u'GLOBEX' # CME电子交易平台 EXCHANGE_GLOBEX = 'GLOBEX' # CME电子交易平台
EXCHANGE_IDEALPRO = u'IDEALPRO' # IB外汇ECN EXCHANGE_IDEALPRO = 'IDEALPRO' # IB外汇ECN
# 货币类型 # 货币类型
CURRENCY_USD = 'USD' # 美元 CURRENCY_USD = 'USD' # 美元

View File

@ -7,10 +7,6 @@ from pymongo import MongoClient
from pymongo.errors import ConnectionFailure from pymongo.errors import ConnectionFailure
from eventEngine import * from eventEngine import *
from ctpGateway import CtpGateway
from ltsGateway import LtsGateway
#from windGateway import WindGateway
from ibGateway import IbGateway
from vtGateway import * from vtGateway import *
import uiBasicWidget import uiBasicWidget
from ctaEngine import CtaEngine from ctaEngine import CtaEngine
@ -35,15 +31,31 @@ class MainEngine(object):
self.gatewayDict = OrderedDict() self.gatewayDict = OrderedDict()
# 创建我们想要接入的接口对象 # 创建我们想要接入的接口对象
self.addGateway(CtpGateway, 'CTP') try:
self.gatewayDict['CTP'].setQryEnabled(True) from ctpGateway import CtpGateway
self.addGateway(CtpGateway, 'CTP')
self.gatewayDict['CTP'].setQryEnabled(True)
except Exception, e:
print e
self.addGateway(LtsGateway, 'LTS') try:
self.gatewayDict['LTS'].setQryEnabled(True) from ltsGateway import LtsGateway
self.addGateway(LtsGateway, 'LTS')
self.gatewayDict['LTS'].setQryEnabled(True)
except Exception, e:
print e
#self.addGateway(WindGateway, 'Wind') # 没有Wind的请注释掉这一行 try:
from windGateway import WindGateway
self.addGateway(WindGateway, 'Wind')
except Exception, e:
print e
self.addGateway(IbGateway, 'IB') try:
from ibGateway import IbGateway
self.addGateway(IbGateway, 'IB')
except Exception, e:
print e
# MongoDB数据库相关 # MongoDB数据库相关
self.dbClient = None # MongoDB客户端对象 self.dbClient = None # MongoDB客户端对象

View File

@ -33,11 +33,16 @@ class VtGateway(object):
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def onTrade(self, trade): def onTrade(self, trade):
"""成交信息推送""" """成交信息推送"""
# 因为成交通常都是事后才会知道成交编号,因此只需要推送通用事件 # 通用事件
event1 = Event(type_=EVENT_TRADE) event1 = Event(type_=EVENT_TRADE)
event1.dict_['data'] = trade event1.dict_['data'] = trade
self.eventEngine.put(event1) self.eventEngine.put(event1)
# 特定合约的成交事件
event2 = Event(type_=EVENT_TRADE+trade.vtSymbol)
event2.dict_['data'] = trade
self.eventEngine.put(event2)
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def onOrder(self, order): def onOrder(self, order):
"""订单变化推送""" """订单变化推送"""
@ -60,7 +65,7 @@ class VtGateway(object):
self.eventEngine.put(event1) self.eventEngine.put(event1)
# 特定合约代码的事件 # 特定合约代码的事件
event2 = Event(type_=EVENT_POSITION+position.vtPositionName) event2 = Event(type_=EVENT_POSITION+position.vtSymbol)
event2.dict_['data'] = position event2.dict_['data'] = position
self.eventEngine.put(event2) self.eventEngine.put(event2)
@ -287,6 +292,9 @@ class VtPositionData(VtBaseData):
self.price = EMPTY_FLOAT # 持仓均价 self.price = EMPTY_FLOAT # 持仓均价
self.vtPositionName = EMPTY_STRING # 持仓在vt系统中的唯一代码通常是vtSymbol.方向 self.vtPositionName = EMPTY_STRING # 持仓在vt系统中的唯一代码通常是vtSymbol.方向
# 20151020添加
self.ydPosition = EMPTY_INT # 昨持仓
######################################################################## ########################################################################
class VtAccountData(VtBaseData): class VtAccountData(VtBaseData):
@ -363,7 +371,7 @@ class VtContractData(VtBaseData):
######################################################################## ########################################################################
class VtSubscribeReq: class VtSubscribeReq(object):
"""订阅行情时传入的对象类""" """订阅行情时传入的对象类"""
#---------------------------------------------------------------------- #----------------------------------------------------------------------
@ -381,7 +389,7 @@ class VtSubscribeReq:
######################################################################## ########################################################################
class VtOrderReq: class VtOrderReq(object):
"""发单时传入的对象类""" """发单时传入的对象类"""
#---------------------------------------------------------------------- #----------------------------------------------------------------------
@ -405,7 +413,7 @@ class VtOrderReq:
######################################################################## ########################################################################
class VtCancelOrderReq: class VtCancelOrderReq(object):
"""撤单时传入的对象类""" """撤单时传入的对象类"""
#---------------------------------------------------------------------- #----------------------------------------------------------------------

View File

@ -3,7 +3,8 @@
''' '''
Wind Python API的gateway接入 Wind Python API的gateway接入
''' '''
from threading import Thread
from copy import copy
try: try:
from WindPy import w from WindPy import w
@ -166,7 +167,8 @@ class WindGateway(VtGateway):
value = values[n][0] value = values[n][0]
d[key] = value d[key] = value
self.onTick(tick) newtick = copy(tick)
self.onTick(newtick)
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def wConnect(self, event): def wConnect(self, event):