Merge remote-tracking branch 'refs/remotes/vnpy/master'
Conflicts: vn.trader/ContractData.vt vn.trader/ctaEngine.py vn.trader/ctaStrategies.py vn.trader/ltsGateway.py vn.trader/uiBasicWidget.py vn.trader/uiMainWindow.py vn.trader/vtConstant.py vn.trader/vtEngine.py
This commit is contained in:
commit
64f772e650
@ -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"
|
||||
}
|
||||
}
|
106
vn.trader/ctaDataRecorder.py
Normal file
106
vn.trader/ctaDataRecorder.py
Normal 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)
|
||||
|
||||
|
||||
|
@ -10,100 +10,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策略引擎"""
|
||||
@ -174,8 +84,10 @@ class CtaEngine(object):
|
||||
req.direction = DIRECTION_LONG
|
||||
req.offset = OFFSET_CLOSE
|
||||
|
||||
|
||||
# 3.调用主引擎的发单接口进行发单,保存OrderID与策略映射关系
|
||||
vtOrderID = self.mainEngine.sendOrder(req) # 发单
|
||||
vtOrderID = self.mainEngine.sendOrder(req, contract.gatewayName) # 发单
|
||||
|
||||
self.orderDict[vtOrderID] = strategy # 保存vtOrderID和策略的映射关系
|
||||
|
||||
return vtOrderID
|
||||
@ -308,7 +220,7 @@ class CtaEngine(object):
|
||||
|
||||
l = self.tickStrategyDict[tick.vtSymbol]
|
||||
for strategy in l:
|
||||
strategy.onTick(tick)
|
||||
strategy.onTick(ctaTick)
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
|
||||
@ -434,7 +346,8 @@ class CtaEngine(object):
|
||||
|
||||
# 5.调用主引擎的订阅接口
|
||||
self.mainEngine.subscribe(req, contract.gatewayName)
|
||||
|
||||
else:
|
||||
self.writeCtaLog(u'%s的交易合约%s无法找到' %(name, strategy.vtSymbol))
|
||||
else:
|
||||
self.writeCtaLog(u'存在策略对象重名:' + name)
|
||||
|
||||
|
95
vn.trader/ctaObject.py
Normal file
95
vn.trader/ctaObject.py
Normal 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
|
||||
|
@ -2,10 +2,18 @@
|
||||
|
||||
'''
|
||||
在本文件中引入所有希望在系统中使用的策略类
|
||||
当作配置文件,每次增加删除策略时,需要维护此字典
|
||||
|
||||
|
||||
这个字典中保存了需要运行的策略的名称和策略类的映射关系,
|
||||
用户的策略类写好后,先在该文件中引入,并设置好名称,然后
|
||||
在CTA_setting.json中写入具体每个策略对象的类和合约设置。
|
||||
|
||||
'''
|
||||
|
||||
from ctaStrategyTemplate import TestStrategy
|
||||
from ctaDataRecorder import DataRecorder
|
||||
|
||||
strategyClassDict = {}
|
||||
strategyClassDict[u'TestStrategy'] = TestStrategy
|
||||
|
||||
strategyClassDict['TestStrategy'] = TestStrategy
|
||||
strategyClassDict['DataRecorder'] = DataRecorder
|
||||
|
@ -190,7 +190,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')
|
||||
|
@ -640,6 +640,7 @@ class CtpTdApi(TdApi):
|
||||
|
||||
# 持仓量
|
||||
pos.position = data['Position']
|
||||
pos.ydPosition = data['YdPosition']
|
||||
|
||||
# 持仓均价
|
||||
if pos.position:
|
||||
|
@ -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():
|
||||
|
@ -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,9 +392,9 @@ class LtsMdApi(MdApi):
|
||||
"""订阅合约"""
|
||||
req = {}
|
||||
req['InstrumentID'] = str(subscribeReq.symbol)
|
||||
req['ExchangeID'] = str(subscribeReq.exchange)
|
||||
|
||||
|
||||
req['ExchangeID'] = exchangeMap.get(str(subscribeReq.exchange), '')
|
||||
|
||||
# 这里的设计是,如果尚未登录就调用了订阅方法
|
||||
# 则先保存订阅请求,登录完成后会自动订阅
|
||||
if self.loginStatus:
|
||||
@ -582,7 +582,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']
|
||||
@ -616,7 +616,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']
|
||||
@ -639,7 +639,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']
|
||||
@ -655,7 +655,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']
|
||||
|
||||
@ -772,10 +772,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:
|
||||
@ -1067,11 +1067,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):
|
||||
@ -1141,11 +1151,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:
|
||||
@ -1153,6 +1164,7 @@ class LtsQryApi(QryApi):
|
||||
|
||||
# 持仓量
|
||||
pos.position = data['Position']
|
||||
pos.ydPosition = data['YdPosition']
|
||||
|
||||
# 持仓均价
|
||||
if pos.position:
|
||||
|
@ -473,6 +473,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}
|
||||
@ -761,7 +762,7 @@ class TradingWidget(QtGui.QFrame):
|
||||
"""合约变化"""
|
||||
|
||||
# 读取组件数据
|
||||
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())
|
||||
@ -923,7 +924,8 @@ 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())
|
||||
|
@ -6,6 +6,7 @@ from uiBasicWidget import *
|
||||
|
||||
from uiCtaWidget import CtaEngineManager
|
||||
|
||||
|
||||
########################################################################
|
||||
class MainWindow(QtGui.QMainWindow):
|
||||
"""主窗口"""
|
||||
@ -19,6 +20,8 @@ class MainWindow(QtGui.QMainWindow):
|
||||
self.eventEngine = eventEngine
|
||||
self.dataEngine = dataEngine
|
||||
|
||||
self.widgetDict = {} # 用来保存子窗口的字典
|
||||
|
||||
self.initUi()
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
@ -90,7 +93,10 @@ class MainWindow(QtGui.QMainWindow):
|
||||
|
||||
|
||||
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)
|
||||
@ -124,16 +130,25 @@ class MainWindow(QtGui.QMainWindow):
|
||||
|
||||
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):
|
||||
@ -201,54 +216,58 @@ 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 = 'MSFT'
|
||||
#self.mainEngine.subscribe(req, 'IB')
|
||||
|
||||
req.symbol = 'GE'
|
||||
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):
|
||||
"""关闭事件"""
|
||||
@ -256,7 +275,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:
|
||||
|
@ -49,18 +49,20 @@ 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' # 美元
|
||||
|
@ -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,22 +31,44 @@ class MainEngine(object):
|
||||
self.gatewayDict = OrderedDict()
|
||||
|
||||
# 创建我们想要接入的接口对象
|
||||
self.addGateway(CtpGateway, 'CTP')
|
||||
self.gatewayDict['CTP'].setQryEnabled(True)
|
||||
|
||||
self.addGateway(CtpGateway, 'CTP_Prod')
|
||||
self.gatewayDict['CTP_Prod'].setQryEnabled(True)
|
||||
try:
|
||||
from ctpGateway import CtpGateway
|
||||
|
||||
self.addGateway(CtpGateway, 'CTP_Post')
|
||||
self.gatewayDict['CTP_Post'].setQryEnabled(True)
|
||||
self.addGateway(CtpGateway, 'CTP')
|
||||
self.gatewayDict['CTP'].setQryEnabled(True)
|
||||
|
||||
self.addGateway(CtpGateway, 'CTP_Test')
|
||||
self.gatewayDict['CTP_Test'].setQryEnabled(True)
|
||||
self.addGateway(CtpGateway, 'CTP_Prod')
|
||||
self.gatewayDict['CTP_Prod'].setQryEnabled(True)
|
||||
|
||||
self.addGateway(CtpGateway, 'CTP_Post')
|
||||
self.gatewayDict['CTP_Post'].setQryEnabled(True)
|
||||
|
||||
self.addGateway(CtpGateway, 'CTP_Test')
|
||||
self.gatewayDict['CTP_Test'].setQryEnabled(True)
|
||||
except Exception, e:
|
||||
print e
|
||||
|
||||
try:
|
||||
from ltsGateway import LtsGateway
|
||||
self.addGateway(LtsGateway, 'LTS')
|
||||
self.gatewayDict['LTS'].setQryEnabled(True)
|
||||
except Exception, e:
|
||||
print e
|
||||
|
||||
self.addGateway(LtsGateway, 'LTS')
|
||||
self.gatewayDict['LTS'].setQryEnabled(True)
|
||||
|
||||
try:
|
||||
from windGateway import WindGateway
|
||||
self.addGateway(WindGateway, 'Wind')
|
||||
except Exception, e:
|
||||
print e
|
||||
|
||||
try:
|
||||
from ibGateway import IbGateway
|
||||
self.addGateway(IbGateway, 'IB')
|
||||
except Exception, e:
|
||||
print e
|
||||
|
||||
#self.addGateway(WindGateway, 'Wind') # 没有Wind的请注释掉这一行
|
||||
|
||||
# MongoDB数据库相关
|
||||
self.dbClient = None # MongoDB客户端对象
|
||||
|
@ -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 # 会话号
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -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):
|
||||
|
Loading…
Reference in New Issue
Block a user