diff --git a/vn.trader/CTA_setting.json b/vn.trader/CTA_setting.json index 3e8805eb..8c245b0b 100644 --- a/vn.trader/CTA_setting.json +++ b/vn.trader/CTA_setting.json @@ -1,14 +1,10 @@ { - "Test1": { - "strategyClassName": "TestStrategy", - "vtSymbol": "IF1511" - }, - "Test3": { - "strategyClassName": "TestStrategy", + "DR_IF1512": { + "strategyClassName": "DataRecorder", "vtSymbol": "IF1512" }, - "Test2": { - "strategyClassName": "TestStrategy", - "vtSymbol": "IH1511" + "DR_IH1512": { + "strategyClassName": "DataRecorder", + "vtSymbol": "IH1512" } } \ No newline at end of file diff --git a/vn.trader/ContractData.vt b/vn.trader/ContractData.vt index d36ef311..aa5465a9 100644 Binary files a/vn.trader/ContractData.vt and b/vn.trader/ContractData.vt differ diff --git a/vn.trader/ctaDataRecorder.py b/vn.trader/ctaDataRecorder.py new file mode 100644 index 00000000..7731c4c7 --- /dev/null +++ b/vn.trader/ctaDataRecorder.py @@ -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) + + + \ No newline at end of file diff --git a/vn.trader/ctaEngine.py b/vn.trader/ctaEngine.py index 81c4e64d..bf2539be 100644 --- a/vn.trader/ctaEngine.py +++ b/vn.trader/ctaEngine.py @@ -9,100 +9,10 @@ from vtConstant import * from vtGateway import VtSubscribeReq, VtOrderReq, VtCancelOrderReq, VtLogData from ctaConstant import * +from ctaObject import * 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): """CTA策略引擎""" @@ -266,7 +176,7 @@ class CtaEngine(object): # 逐个推送到策略对象中 l = self.tickStrategyDict[tick.vtSymbol] for strategy in l: - strategy.onTick(tick) + strategy.onTick(ctaTick) #---------------------------------------------------------------------- def processOrderEvent(self, event): @@ -366,6 +276,8 @@ class CtaEngine(object): req.symbol = contract.symbol req.exchange = contract.exchange self.mainEngine.subscribe(req, contract.gatewayName) + else: + self.writeCtaLog(u'%s的交易合约%s无法找到' %(name, strategy.vtSymbol)) else: self.writeCtaLog(u'存在策略对象重名:' + name) diff --git a/vn.trader/ctaObject.py b/vn.trader/ctaObject.py new file mode 100644 index 00000000..38f64384 --- /dev/null +++ b/vn.trader/ctaObject.py @@ -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 + diff --git a/vn.trader/ctaStrategies.py b/vn.trader/ctaStrategies.py index ce5fa40b..50cd0d74 100644 --- a/vn.trader/ctaStrategies.py +++ b/vn.trader/ctaStrategies.py @@ -2,9 +2,15 @@ ''' 在本文件中引入所有希望在系统中使用的策略类 + +这个字典中保存了需要运行的策略的名称和策略类的映射关系, +用户的策略类写好后,先在该文件中引入,并设置好名称,然后 +在CTA_setting.json中写入具体每个策略对象的类和合约设置。 ''' from ctaStrategyTemplate import TestStrategy +from ctaDataRecorder import DataRecorder strategyClassDict = {} -strategyClassDict[u'TestStrategy'] = TestStrategy \ No newline at end of file +strategyClassDict['TestStrategy'] = TestStrategy +strategyClassDict['DataRecorder'] = DataRecorder \ No newline at end of file diff --git a/vn.trader/ctaStrategyTemplate.py b/vn.trader/ctaStrategyTemplate.py index 5ea0a619..790e5f55 100644 --- a/vn.trader/ctaStrategyTemplate.py +++ b/vn.trader/ctaStrategyTemplate.py @@ -186,7 +186,7 @@ class TestStrategy(CtaStrategyTemplate): self.lastPrice = EMPTY_FLOAT # 最新价 # 参数和变量列表设置 - self.paramList.append(u'author') + self.paramList.append('author') self.varList.append('pos') self.varList.append('lastPrice') diff --git a/vn.trader/ctpGateway.py b/vn.trader/ctpGateway.py index c2b92ef3..9810f94a 100644 --- a/vn.trader/ctpGateway.py +++ b/vn.trader/ctpGateway.py @@ -638,6 +638,7 @@ class CtpTdApi(TdApi): # 持仓量 pos.position = data['Position'] + pos.ydPosition = data['YdPosition'] # 持仓均价 if pos.position: diff --git a/vn.trader/eventType.py b/vn.trader/eventType.py index 4b52dcbc..10cfd10c 100644 --- a/vn.trader/eventType.py +++ b/vn.trader/eventType.py @@ -30,6 +30,13 @@ EVENT_CTA_LOG = 'eCtaLog' # CTA相关的日志事件 # 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(): diff --git a/vn.trader/ltsGateway.py b/vn.trader/ltsGateway.py index 8f4134ce..1ce7a264 100644 --- a/vn.trader/ltsGateway.py +++ b/vn.trader/ltsGateway.py @@ -321,7 +321,7 @@ class LtsMdApi(MdApi): tick.lastPrice = data['LastPrice'] tick.volume = data['Volume'] 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.openPrice = data['OpenPrice'] @@ -392,7 +392,7 @@ class LtsMdApi(MdApi): """订阅合约""" req = {} 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.exchange = exchangeMapReverse[data['ExchangeID']] + order.exchange = exchangeMapReverse.get(data['ExchangeID'], '') order.vtSymbol = '.'.join([order.symbol, order.exchange]) order.orderID = data['OrderRef'] @@ -613,7 +613,7 @@ class LtsTdApi(TdApi): order.status = STATUS_UNKNOWN # 价格、报单量等数值 - order.price = data['LimitPrice'] + order.price = float(data['LimitPrice']) order.totalVolume = data['VolumeTotalOriginal'] order.tradedVolume = data['VolumeTraded'] order.orderTime = data['InsertTime'] @@ -636,7 +636,7 @@ class LtsTdApi(TdApi): # 保存代码和报单号 trade.symbol = data['InstrumentID'] - trade.exchange = exchangeMapReverse[data['ExchangeID']] + trade.exchange = exchangeMapReverse.get(data['ExchangeID'], '') trade.vtSymbol = '.'.join([trade.symbol, trade.exchange]) trade.tradeID = data['TradeID'] @@ -652,7 +652,7 @@ class LtsTdApi(TdApi): trade.offset = offsetMapReverse.get(data['OffsetFlag'], '') # 价格、报单量等数值 - trade.price = data['Price'] + trade.price = float(data['Price']) trade.volume = data['Volume'] trade.tradeTime = data['TradeTime'] @@ -764,10 +764,10 @@ class LtsTdApi(TdApi): req = {} - req['InstrumentID'] = orderReq.symbol + req['InstrumentID'] = str(orderReq.symbol) req['LimitPrice'] = str(orderReq.price) # LTS里的价格是字符串 - req['VolumeTotalOriginal'] = orderReq.volume - req['ExchangeID'] = orderReq.exchange + req['VolumeTotalOriginal'] = int(orderReq.volume) + req['ExchangeID'] = exchangeMap.get(orderReq.exchange, '') # 下面如果由于传入的类型本接口不支持,则会返回空字符串 try: @@ -1059,11 +1059,21 @@ class LtsQryApi(QryApi): def onRspQryOFInstrument(self, data, error, n, last): """OF合约查询回报""" pass - + #---------------------------------------------------------------------- def onRspQrySFInstrument(self, data, error, n, last): """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): @@ -1133,11 +1143,12 @@ class LtsQryApi(QryApi): # 保存代码 pos.symbol = data['InstrumentID'] - pos.exchange = data['ExchangeID'] + pos.exchange = exchangeMapReverse.get(data['ExchangeID'], '') pos.vtSymbol = '.'.join([pos.symbol, pos.exchange]) # 方向和持仓冻结数量 pos.direction = posiDirectionMapReverse.get(data['PosiDirection'], '') + if pos.direction == DIRECTION_NET or pos.direction == DIRECTION_LONG: pos.frozen = data['LongFrozen'] elif pos.direction == DIRECTION_SHORT: @@ -1145,6 +1156,7 @@ class LtsQryApi(QryApi): # 持仓量 pos.position = data['Position'] + pos.ydPosition = data['YdPosition'] # 持仓均价 if pos.position: diff --git a/vn.trader/uiBasicWidget.py b/vn.trader/uiBasicWidget.py index 2d042b88..0359cbc1 100644 --- a/vn.trader/uiBasicWidget.py +++ b/vn.trader/uiBasicWidget.py @@ -472,6 +472,7 @@ class PositionMonitor(BasicMonitor): d['vtSymbol'] = {'chinese':u'名称', 'cellType':NameCell} d['direction'] = {'chinese':u'方向', 'cellType':DirectionCell} d['position'] = {'chinese':u'持仓量', 'cellType':BasicCell} + d['ydPosition'] = {'chinese':u'昨持仓', 'cellType':BasicCell} d['frozen'] = {'chinese':u'冻结量', 'cellType':BasicCell} d['price'] = {'chinese':u'价格', 'cellType':BasicCell} d['gatewayName'] = {'chinese':u'接口', 'cellType':BasicCell} @@ -755,7 +756,7 @@ class TradingWidget(QtGui.QFrame): def updateSymbol(self): """合约变化""" # 读取组件数据 - symbol = unicode(self.lineSymbol.text()) + symbol = str(self.lineSymbol.text()) exchange = unicode(self.comboExchange.currentText()) currency = unicode(self.comboCurrency.currentText()) productClass = unicode(self.comboProductClass.currentText()) @@ -866,7 +867,7 @@ class TradingWidget(QtGui.QFrame): #---------------------------------------------------------------------- def sendOrder(self): """发单""" - symbol = unicode(self.lineSymbol.text()) + symbol = str(self.lineSymbol.text()) exchange = unicode(self.comboExchange.currentText()) currency = unicode(self.comboCurrency.currentText()) productClass = unicode(self.comboProductClass.currentText()) diff --git a/vn.trader/uiMainWindow.py b/vn.trader/uiMainWindow.py index c8cd53ca..0b6c52ce 100644 --- a/vn.trader/uiMainWindow.py +++ b/vn.trader/uiMainWindow.py @@ -5,6 +5,7 @@ import psutil from uiBasicWidget import * from uiCtaWidget import CtaEngineManager + ######################################################################## class MainWindow(QtGui.QMainWindow): """主窗口""" @@ -18,6 +19,8 @@ class MainWindow(QtGui.QMainWindow): self.eventEngine = eventEngine self.dataEngine = dataEngine + self.widgetDict = {} # 用来保存子窗口的字典 + self.initUi() #---------------------------------------------------------------------- @@ -78,7 +81,10 @@ class MainWindow(QtGui.QMainWindow): connectWindAction.triggered.connect(self.connectWind) 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.triggered.connect(self.testSubscribe) @@ -103,15 +109,22 @@ class MainWindow(QtGui.QMainWindow): sysMenu.addAction(connectLtsAction) sysMenu.addAction(connectWindAction) sysMenu.addAction(connectIbAction) + sysMenu.addSeparator() + sysMenu.addAction(connectDbAction) + sysMenu.addSeparator() sysMenu.addAction(testAction) sysMenu.addAction(exitAction) functionMenu = menubar.addMenu(u'功能') functionMenu.addAction(contractAction) - functionMenu.addAction(ctaAction) + # 算法相关 + algoMenu = menubar.addMenu(u'算法') + algoMenu.addAction(ctaAction) + + # 帮助 helpMenu = menubar.addMenu(u'帮助') - helpMenu.addAction(aboutAction) + helpMenu.addAction(aboutAction) #---------------------------------------------------------------------- def initStatusBar(self): @@ -165,51 +178,55 @@ class MainWindow(QtGui.QMainWindow): #---------------------------------------------------------------------- def testSubscribe(self): """测试订阅""" - req = VtSubscribeReq() - req.symbol = 'GOOG' - req.productClass = PRODUCT_EQUITY - req.exchange = EXCHANGE_SMART - req.currency = CURRENCY_USD - self.mainEngine.subscribe(req, 'IB') + api = self.mainEngine.gatewayDict['LTS'].qryApi + api.reqID += 1 + api.reqQryOFInstrument({}, api.reqID) - req.symbol = 'AAPL' - self.mainEngine.subscribe(req, 'IB') + #req = VtSubscribeReq() + #req.symbol = 'GOOG' + #req.productClass = PRODUCT_EQUITY + #req.exchange = EXCHANGE_SMART + #req.currency = CURRENCY_USD + #self.mainEngine.subscribe(req, 'IB') - req.symbol = 'YHOO' - self.mainEngine.subscribe(req, 'IB') + #req.symbol = 'AAPL' + #self.mainEngine.subscribe(req, 'IB') - req.symbol = 'MSFT' - self.mainEngine.subscribe(req, 'IB') + #req.symbol = 'YHOO' + #self.mainEngine.subscribe(req, 'IB') - req.symbol = 'GE' - self.mainEngine.subscribe(req, 'IB') + #req.symbol = 'MSFT' + #self.mainEngine.subscribe(req, 'IB') + + #req.symbol = 'GE' + #self.mainEngine.subscribe(req, 'IB') #---------------------------------------------------------------------- def openAbout(self): """打开关于""" try: - self.aboutW.show() - except AttributeError: - self.aboutW = AboutWidget(self) - self.aboutW.show() + self.widgetDict['aboutW'].show() + except KeyError: + self.widgetDict['aboutW'] = AboutWidget(self) + self.widgetDict['aboutW'].show() #---------------------------------------------------------------------- def openContract(self): """打开合约查询""" try: - self.contractM.show() - except AttributeError: - self.contractM = ContractMonitor(self.mainEngine.dataEngine) - self.contractM.show() + self.widgetDict['contractM'].show() + except KeyError: + self.widgetDict['contractM'] = ContractMonitor(self.mainEngine.dataEngine) + self.widgetDict['contractM'].show() #---------------------------------------------------------------------- def openCta(self): """打开CTA组件""" try: - self.ctaM.show() - except AttributeError: - self.ctaM = CtaEngineManager(self.mainEngine.ctaEngine, self.eventEngine) - self.ctaM.show() + self.widgetDict['ctaM'].show() + except KeyError: + self.widgetDict['ctaM'] = CtaEngineManager(self.mainEngine.ctaEngine, self.eventEngine) + self.widgetDict['ctaM'].show() #---------------------------------------------------------------------- def closeEvent(self, event): @@ -218,7 +235,9 @@ class MainWindow(QtGui.QMainWindow): u'确认退出?', QtGui.QMessageBox.Yes | 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() event.accept() else: diff --git a/vn.trader/vtConstant.py b/vn.trader/vtConstant.py index a6db91a1..0cfe46bd 100644 --- a/vn.trader/vtConstant.py +++ b/vn.trader/vtConstant.py @@ -49,19 +49,19 @@ OPTION_CALL = u'看涨期权' OPTION_PUT = u'看跌期权' # 交易所类型 -EXCHANGE_SSE = u'SSE' # 上交所 -EXCHANGE_SZSE = u'SZSE' # 深交所 -EXCHANGE_CFFEX = u'CFFEX' # 中金所 -EXCHANGE_SHFE = u'SHFE' # 上期所 -EXCHANGE_CZCE = u'CZCE' # 郑商所 -EXCHANGE_DCE = u'DCE' # 大商所 +EXCHANGE_SSE = 'SSE' # 上交所 +EXCHANGE_SZSE = 'SZSE' # 深交所 +EXCHANGE_CFFEX = 'CFFEX' # 中金所 +EXCHANGE_SHFE = 'SHFE' # 上期所 +EXCHANGE_CZCE = 'CZCE' # 郑商所 +EXCHANGE_DCE = 'DCE' # 大商所 EXCHANGE_UNKNOWN = 'UNKNOWN'# 未知交易所 EXCHANGE_NONE = '' # 空交易所 -EXCHANGE_SMART = u'SMART' # IB智能路由(股票、期权) -EXCHANGE_GLOBEX = u'GLOBEX' # CME电子交易平台 -EXCHANGE_IDEALPRO = u'IDEALPRO' # IB外汇ECN +EXCHANGE_SMART = 'SMART' # IB智能路由(股票、期权) +EXCHANGE_GLOBEX = 'GLOBEX' # CME电子交易平台 +EXCHANGE_IDEALPRO = 'IDEALPRO' # IB外汇ECN # 货币类型 CURRENCY_USD = 'USD' # 美元 diff --git a/vn.trader/vtEngine.py b/vn.trader/vtEngine.py index 3cf12e5f..d34b5708 100644 --- a/vn.trader/vtEngine.py +++ b/vn.trader/vtEngine.py @@ -7,10 +7,6 @@ from pymongo import MongoClient from pymongo.errors import ConnectionFailure from eventEngine import * -from ctpGateway import CtpGateway -from ltsGateway import LtsGateway -#from windGateway import WindGateway -from ibGateway import IbGateway from vtGateway import * import uiBasicWidget from ctaEngine import CtaEngine @@ -35,15 +31,31 @@ class MainEngine(object): self.gatewayDict = OrderedDict() # 创建我们想要接入的接口对象 - self.addGateway(CtpGateway, 'CTP') - self.gatewayDict['CTP'].setQryEnabled(True) + try: + from ctpGateway import CtpGateway + self.addGateway(CtpGateway, 'CTP') + self.gatewayDict['CTP'].setQryEnabled(True) + except Exception, e: + print e - self.addGateway(LtsGateway, 'LTS') - self.gatewayDict['LTS'].setQryEnabled(True) + try: + 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数据库相关 self.dbClient = None # MongoDB客户端对象 diff --git a/vn.trader/vtGateway.py b/vn.trader/vtGateway.py index a095c8fb..daed5259 100644 --- a/vn.trader/vtGateway.py +++ b/vn.trader/vtGateway.py @@ -33,10 +33,15 @@ class VtGateway(object): #---------------------------------------------------------------------- def onTrade(self, trade): """成交信息推送""" - # 因为成交通常都是事后才会知道成交编号,因此只需要推送通用事件 + # 通用事件 event1 = Event(type_=EVENT_TRADE) event1.dict_['data'] = trade self.eventEngine.put(event1) + + # 特定合约的成交事件 + event2 = Event(type_=EVENT_TRADE+trade.vtSymbol) + event2.dict_['data'] = trade + self.eventEngine.put(event2) #---------------------------------------------------------------------- def onOrder(self, order): @@ -60,7 +65,7 @@ class VtGateway(object): self.eventEngine.put(event1) # 特定合约代码的事件 - event2 = Event(type_=EVENT_POSITION+position.vtPositionName) + event2 = Event(type_=EVENT_POSITION+position.vtSymbol) event2.dict_['data'] = position self.eventEngine.put(event2) @@ -286,6 +291,9 @@ class VtPositionData(VtBaseData): self.frozen = EMPTY_INT # 冻结数量 self.price = EMPTY_FLOAT # 持仓均价 self.vtPositionName = EMPTY_STRING # 持仓在vt系统中的唯一代码,通常是vtSymbol.方向 + + # 20151020添加 + self.ydPosition = EMPTY_INT # 昨持仓 ######################################################################## @@ -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): """撤单时传入的对象类""" #---------------------------------------------------------------------- @@ -418,9 +426,9 @@ class VtCancelOrderReq: self.orderID = EMPTY_STRING # 报单号 self.frontID = EMPTY_STRING # 前置机号 self.sessionID = EMPTY_STRING # 会话号 - - - + + + diff --git a/vn.trader/windGateway.py b/vn.trader/windGateway.py index dc87c607..53d90653 100644 --- a/vn.trader/windGateway.py +++ b/vn.trader/windGateway.py @@ -3,7 +3,8 @@ ''' Wind Python API的gateway接入 ''' -from threading import Thread + +from copy import copy try: from WindPy import w @@ -166,7 +167,8 @@ class WindGateway(VtGateway): value = values[n][0] d[key] = value - self.onTick(tick) + newtick = copy(tick) + self.onTick(newtick) #---------------------------------------------------------------------- def wConnect(self, event):