def generateBarDict(self, onBar, xmin=0, onXminBar=None, size=100, alignment='sharp', marketClose=(23, 59)): if xmin: variable = "bg%sDict" % xmin variable2 = "am%sDict" % xmin else: variable = "bgDict" variable2 = "amDict" bgDict = { sym: BarGenerator(onBar, xmin, onXminBar, alignment=alignment, marketClose=marketClose) for sym in self.symbolList } amDict = {sym: ArrayManager(size) for sym in self.symbolList} setattr(self, variable, bgDict) setattr(self, variable2, amDict)
def __init__(self, omEngine, eventEngine): self.omEngine = omEngine self.mainEngine = omEngine.mainEngine self.strategyEngine = omEngine.strategyEngine self.eventEngine = eventEngine self.portfolio = omEngine.portfolio self.bg = BarGenerator(self.onVixBar) self.active = False self.queue = Queue() self.thread = Thread(target=self.run) self.vixDict = OrderedDict() self.timerDict = dict() for chain in self.portfolio.chainDict.values(): self.vixDict[chain.symbol] = OmVixCalculator(chain) self.registerEvent() self.start()
def onInit(self): self.symbol = self.symbolList[0] self.generateBarDict(self.onBar,size = self.size) # self.generateBarDict(self.onBar,3,self.on3MinBar,size =self.size) # self.generateBarDict(self.onBar,5,self.on5MinBar,size =self.size) # self.generateBarDict(self.onBar,30,self.on30MinBar,size =self.size) self.generateBarDict(self.onBar,60,self.on60MinBar,size =self.size) self.bgDayDict= BarGenerator(self.onCandle,marketClose =(14,59)) self.bgWeekDict = BarGenerator(self.onWCandle) self.bgMonDict = BarGenerator(self.onMCandle) self.amweekDict = ArrayManager(25) self.ammonDict = ArrayManager(6) for s in self.symbolList: kline = self.loadHistoryBar(s,'1min', since = '20180410') for index, bar in enumerate(kline): self.onBar(bar)
class BarStrategy(CtaTemplate): # 策略参数 size = 800 transactionPrice = {} tradable = False # 参数列表,保存了参数的名称 paramList = ['className'] # 变量列表,保存了变量的名称 varList = ['inited', 'trading', 'posDict', 'transactionPrice'] # 同步列表,保存了需要保存到数据库的变量名称 syncList = ['posDict','eveningDict'] #---------------------------------------------------------------------- def __init__(self, ctaEngine, setting): super(BarStrategy, self).__init__(ctaEngine, setting) self.lots = setting['lots'] #---------------------------------------------------------------------- def onInit(self): self.symbol = self.symbolList[0] self.generateBarDict(self.onBar,size = self.size) # self.generateBarDict(self.onBar,3,self.on3MinBar,size =self.size) # self.generateBarDict(self.onBar,5,self.on5MinBar,size =self.size) # self.generateBarDict(self.onBar,30,self.on30MinBar,size =self.size) self.generateBarDict(self.onBar,60,self.on60MinBar,size =self.size) self.bgDayDict= BarGenerator(self.onCandle,marketClose =(14,59)) self.bgWeekDict = BarGenerator(self.onWCandle) self.bgMonDict = BarGenerator(self.onMCandle) self.amweekDict = ArrayManager(25) self.ammonDict = ArrayManager(6) for s in self.symbolList: kline = self.loadHistoryBar(s,'1min', since = '20180410') for index, bar in enumerate(kline): self.onBar(bar) #---------------------------------------------------------------------- def onStart(self): """启动策略(必须由用户继承实现)""" def onStop(self): self.putEvent() def onRestore(self): """恢复策略(必须由用户继承实现)""" def onTick(self, tick): """收到行情TICK推送(必须由用户继承实现)""" self.bgDict[tick.vtSymbol].updateTick(tick) # --------------------------------------------------------------------- def onBar(self, bar): # self.bg3Dict[self.symbol].updateBar(bar) # self.bg5Dict[self.symbol].updateBar(bar) # self.bg30Dict[self.symbol].updateBar(bar) self.bg60Dict[self.symbol].updateBar(bar) self.bgDayDict.updateCandle(bar) # self.writeCtaLog('onBar: %s '%bar.__dict__) #---------------------------------------------------------------------- # def on3MinBar(self, bar): # # self.writeCtaLog('on----------6666666666666666------------Bar: %s '%bar.datetime) # self.am3Dict[self.symbol].updateBar(bar) # def on5MinBar(self, bar): # # self.writeCtaLog('on----------6666666666666666------------Bar: %s '%bar.datetime) # self.am5Dict[self.symbol].updateBar(bar) # def on30MinBar(self, bar): # # self.writeCtaLog('on----------6666666666666666------------Bar: %s '%bar.datetime) # self.am30Dict[self.symbol].updateBar(bar) def on60MinBar(self, bar): # self.writeCtaLog('on----------6666666666666666------------Bar: %s '%bar.datetime) self.am60Dict[self.symbol].updateBar(bar) #---------------------------------------------------------------------- def onCandle(self,Candle): """Daily Candles""" # self.writeCtaLog('on----------dayyyyyyyyyyy------------Bar: %s '%bar.datetime) self.bgWeekDict.updateWCandle(Candle) self.bgMonDict.updateMCandle(Candle) def onWCandle(self,Candle): """Week Candles""" self.amweekDict.updateBar(Candle) # if self.amweekDict.inited: # print(self.amweekDict.DataFrame()) # self.writeCtaLog('on----------xxxxxxxxxxxxxxxxxxx------------Bar: %s '%Candle.datetime) def onMCandle(self,Candle): """Month Candles""" self.ammonDict.updateBar(Candle) if self.ammonDict.inited: print(self.ammonDict.DataFrame()) self.writeCtaLog('on----------MMMMMMMMMMMMMMMMMMM------------Bar: %s '%Candle.datetime) #---------------------------------------------------------------------- def onOrder(self, order): """收到委托变化推送(必须由用户继承实现)""" pass #---------------------------------------------------------------------- def onTrade(self, trade): """收到成交推送(必须由用户继承实现)""" pass #---------------------------------------------------------------------- def onStopOrder(self, so): """停止单推送""" pass
def generateHFBar(self, xSecond, size=60): self.hfDict = { sym: BarGenerator(self.onHFBar, xSecond=xSecond) for sym in self.symbolList } self.amhfDict = {sym: ArrayManager(size) for sym in self.symbolList}
def __init__(self, ctaEngine, setting): """Constructor""" super(NewMacdStrategy, self).__init__(ctaEngine, setting) self.bg = BarGenerator(self.onBar) self.am = ArrayManager()
class NewMacdStrategy(CtaTemplate): """New MACD策略Demo""" className = 'NewMacdStrategy' author = u'liu_hao' # 策略参数 initDays = 10 # 初始化数据所用的天数 barIndex = 0 MacdList = [] barDataList = [] ema12 = EMPTY_FLOAT ema26 = EMPTY_FLOAT diff = EMPTY_FLOAT dea9 = EMPTY_FLOAT macd = EMPTY_FLOAT beforeMacd = EMPTY_FLOAT newMacd = EMPTY_FLOAT # 策略变量 lowBand = -0.0009 upBand = 0.0011 fixprice = 0.6 ontrade = 0 adjustNum = 2700 # 参数列表,保存了参数的名称 paramList = [ 'name', 'className', 'author', 'vtSymbol', 'initDays', 'barIndex', 'MacdList', 'barDataList', 'ema12', 'ema26', 'diff', 'dea9', 'macd', 'beforeMacd', 'newMacd' ] # 变量列表,保存了变量的名称 varList = ['lowBand', 'upBand', 'fixprice', 'adjustNum'] # 同步列表,保存了需要保存到数据库的变量名称 syncList = ['pos'] # ---------------------------------------------------------------------- def __init__(self, ctaEngine, setting): """Constructor""" super(NewMacdStrategy, self).__init__(ctaEngine, setting) self.bg = BarGenerator(self.onBar) self.am = ArrayManager() # 注意策略类中的可变对象属性(通常是list和dict等),在策略初始化时需要重新创建, # 否则会出现多个策略实例之间数据共享的情况,有可能导致潜在的策略逻辑错误风险, # 策略类中的这些可变对象属性可以选择不写,全都放在__init__下面,写主要是为了阅读 # 策略时方便(更多是个编程习惯的选择) # ---------------------------------------------------------------------- def onInit(self): """初始化策略(必须由用户继承实现)""" self.writeCtaLog(u'new MACD演示策略初始化') initData = self.loadBar(self.initDays) for bar in initData: self.onBar(bar) self.putEvent() def onStart(self): """启动策略(必须由用户继承实现)""" self.writeCtaLog(u'new MACD演示策略启动') self.putEvent() def onStop(self): """停止策略(必须由用户继承实现)""" self.writeCtaLog(u'new MACD演示策略停止') self.putEvent() def onTick(self, tick): """收到行情TICK推送(必须由用户继承实现)""" self.bg.updateTick(tick) def onBar(self, bar): """收到Bar推送(必须由用户继承实现)""" am = self.am am.updateBar(bar) if not am.inited: return if self.barIndex == 0: self.ema12 = bar.close self.ema26 = bar.close self.diff = 0 self.dea9 = 0 else: self.ema12 = self.ema(self.ema12, bar.close, 12) self.ema26 = self.ema(self.ema26, bar.close, 26) self.diff = self.ema12 - self.ema26 self.dea9 = self.ema(self.dea9, self.diff, 9) self.macd = self.diff - self.dea9 if self.barIndex < 34: self.newMacd = 0 else: self.newMacd = self.macd / am.closeArray[-35] self.MacdList.append(self.beforeMacd) # 做多买入 crossLowpBand = (self.beforeMacd < self.lowBand) and (self.newMacd > self.lowBand) # 做多止损 crossLimitLowBand = self.newMacd <= 1.2 * self.lowBand # 做空买入 crossUpBand = (self.beforeMacd > self.upBand) and (self.newMacd < self.upBand) # 做空止损 crossLimitUpBand = self.newMacd >= 1.2 * self.upBand if bar.datetime.time() < datetime.time(14, 55): if self.pos == 0: if crossLowpBand: self.buy(bar.close + self.fixprice, 1) self.log('buy : ' + str(bar.datetime) + " " + str(bar.close)) elif crossUpBand: self.short(bar.close - self.fixprice, 1) self.log('short : ' + str(bar.datetime) + " " + str(bar.close)) elif self.pos > 0: if self.newMacd >= 0: self.log('sell : ' + str(bar.datetime) + " " + str(bar.close) + " +") self.sell(bar.close - self.fixprice, 1) elif crossLimitLowBand: self.sell(bar.close - self.fixprice, 1) self.log('sell : ' + str(bar.datetime) + " " + str(bar.close) + " -") else: if self.newMacd <= 0: self.log('cover : ' + str(bar.datetime) + " " + str(bar.close) + " +") self.cover(bar.close + self.fixprice, 1) elif crossLimitUpBand: self.log('cover : ' + str(bar.datetime) + " " + str(bar.close) + " -") self.cover(bar.close + self.fixprice, 1) else: if self.pos > 0: self.log('sell : ' + str(bar.datetime) + " " + str(bar.close)) self.sell(bar.close - self.fixprice, 1) elif self.pos < 0: self.log('cover : ' + str(bar.datetime) + " " + str(bar.close)) self.cover(bar.close + self.fixprice, 1) if self.barIndex < 35: self.barIndex = self.barIndex + 1 self.beforeMacd = self.newMacd self.adjustParameter() # 发出状态更新事件 self.putEvent() def onOrder(self, order): pass def onTrade(self, trade): self.ontrade = 0 def onStopOrder(self, so): pass def ema(self, beforeValue, newData, days): temp = ((days - 1) * beforeValue + 2 * newData) / (days + 1) return temp def log(self, message): if True: print message def adjustParameter(self): if len(self.MacdList) < self.adjustNum: return else: tempList = self.MacdList[(-1 * self.adjustNum):] max_10_list = heapq.nlargest(500, tempList) min_10_list = heapq.nsmallest(500, tempList) self.upBand = sum(max_10_list) / len(max_10_list) self.lowBand = sum(min_10_list) / len(min_10_list)
def loadSetting(self): """加载配置""" with open(self.settingFilePath) as f: drSetting = json.load(f) # 如果working设为False则不启动行情记录功能 working = drSetting['working'] if not working: return # 加载收盘时间 if 'marketCloseTime' in drSetting: timestamp = drSetting['marketCloseTime'] self.marketCloseTime = datetime.strptime( timestamp, '%H:%M:%S').time() # Tick记录配置 if 'tick' in drSetting: l = drSetting['tick'] for setting in l: symbol = setting[0] gateway = setting[1] vtSymbol = symbol req = VtSubscribeReq() req.symbol = setting[0] # 针对LTS和IB接口,订阅行情需要交易所代码 if len(setting) >= 3: req.exchange = setting[2] vtSymbol = '.'.join([symbol, req.exchange]) # 针对IB接口,订阅行情需要货币和产品类型 if len(setting) >= 5: req.currency = setting[3] req.productClass = setting[4] self.mainEngine.subscribe(req, gateway) #tick = VtTickData() # 该tick实例可以用于缓存部分数据(目前未使用) #self.tickDict[vtSymbol] = tick self.tickSymbolSet.add(vtSymbol) # 保存到配置字典中 if vtSymbol not in self.settingDict: d = { 'symbol': symbol, 'gateway': gateway, 'tick': True } self.settingDict[vtSymbol] = d else: d = self.settingDict[vtSymbol] d['tick'] = True # 分钟线记录配置 if 'bar' in drSetting: l = drSetting['bar'] for setting in l: symbol = setting[0] gateway = setting[1] vtSymbol = symbol req = VtSubscribeReq() req.symbol = symbol if len(setting) >= 3: req.exchange = setting[2] vtSymbol = '.'.join([symbol, req.exchange]) if len(setting) >= 5: req.currency = setting[3] req.productClass = setting[4] self.mainEngine.subscribe(req, gateway) # 保存到配置字典中 if vtSymbol not in self.settingDict: d = {'symbol': symbol, 'gateway': gateway, 'bar': True} self.settingDict[vtSymbol] = d else: d = self.settingDict[vtSymbol] d['bar'] = True # 创建BarManager对象 self.bgDict[vtSymbol] = BarGenerator(self.onBar) # 主力合约记录配置 if 'active' in drSetting: d = drSetting['active'] self.activeSymbolDict = { vtSymbol: activeSymbol for activeSymbol, vtSymbol in d.items() }
class OmVixEngine(object): """波动率计算引擎""" def __init__(self, omEngine, eventEngine): self.omEngine = omEngine self.mainEngine = omEngine.mainEngine self.strategyEngine = omEngine.strategyEngine self.eventEngine = eventEngine self.portfolio = omEngine.portfolio self.bg = BarGenerator(self.onVixBar) self.active = False self.queue = Queue() self.thread = Thread(target=self.run) self.vixDict = OrderedDict() self.timerDict = dict() for chain in self.portfolio.chainDict.values(): self.vixDict[chain.symbol] = OmVixCalculator(chain) self.registerEvent() self.start() def start(self): """启动""" self.active = True self.thread.start() def stop(self): """关闭""" if self.active: self.active = False self.thread.join() def run(self): """运行入库的线程""" while self.active: try: dbName, collectionName, d = self.queue.get(block=True, timeout=1) try: self.mainEngine.dbInsert(dbName, collectionName, d) except DuplicateKeyError: pass except Empty: pass def registerEvent(self): """注册事件回调函数""" self.eventEngine.register(EVENT_TIMER, self.processTimerEvent) self.eventEngine.register(EVENT_OM_VIX, self.processOmVixEvent) def processTimerEvent(self, event): """处理定时事件""" for calculator in self.vixDict.values(): self.calcVix(calculator) def processOmVixEvent(self, event): """处理波动率数据事件""" vix = event.dict_['data'] self.onVixTick(vix) if self.bg: self.bg.updateTick(vix) print(vix.vtSymbol, vix.datetime.strftime('%Y%m%d %H:%M:%S.%f'), vix.lastPrice) def onVixTick(self, vix): """波动率tick更新""" self.insertData(TICK_DB_NAME, vix.vtSymbol, vix) def onVixBar(self, bar): """波动率bar更新""" self.insertData(MINUTE_DB_NAME, bar.vtSymbol, bar) def insertData(self, dbName, collectionName, data): """把数据放入入库队列""" self.queue.put((dbName, collectionName, data.__dict__)) def calcVix(self, calculator): """计算波指""" if self.active: tName = 'vixT.' + calculator.chain.symbol fIdxName = 'vixFIdx.' + calculator.chain.symbol vixName = 'vix.' + calculator.chain.symbol option = calculator.chain.optionDict.values()[0] if not calculator.t: self.timer(tName, 1, calculator.calcT, option) else: self.timer(tName, 60, calculator.calcT, option) if not calculator.fIdx: self.timer(fIdxName, 1, calculator.calcFIdx) else: self.timer(fIdxName, 12, calculator.calcFIdx) vix = self.timer(vixName, 0, calculator.calcVix) if vix: event = Event(type_=EVENT_OM_VIX) event.dict_['data'] = vix self.eventEngine.put(event) def timer(self, name, interval, func, *args, **kwargs): """自定义定时器""" if self.timerDict.get(name) is None: self.timerDict[name] = 0 if self.timerDict[name] > interval: res = func(*args, **kwargs) self.timerDict[name] = 0 return res self.timerDict[name] += 1