前面介绍了PyAlgoTrade几个重要的模块后来了解一下PyAlgoTrade的执行流程,对PyAlgoTrade技术指标以及统计指标在后续的更加详细的介绍。
PyAlgoTrade 开大策略的步骤如下:
定义策略并实现onBars方法 class MyStrategy(strategy.BacktestingStrategy): def __init__(self, feed, instrument): super(MyStrategy, self).__init__(feed, 100000) self.__position = None self.__instrument = instrument self.getBroker().setCommission(backtesting.FixedPerTrade(5)) # 指数数据 # self.setUseAdjustedValues(False) self.__shortsma = ma.SMA(feed[instrument].getPriceDataSeries(), 4) self.__longsma = ma.SMA(feed[instrument].getPriceDataSeries(), 40) def onBars(self, bars): if len(self.__longsma) < 2: return bar = bars[self.__instrument] shares = self.getBroker().getShares(self.__instrument) if self.__shortsma[-1] > self.__shortsma[-2] and self.__shortsma[-1] > self.__longsma[-1] and self.__shortsma[ -2] < self.__longsma[-2]: self.marketOrder(self.__instrument, 100, True) if self.__longsma[-1] < self.__longsma[-2] and self.__shortsma[-1] < self.__longsma[-1] and self.__shortsma[ -2] > self.__longsma[-2]: self.marketOrder(self.__instrument, -1 * shares, True) 实例化策略并运行策略 feed = GenericBarFeed() trade_data = pd.read_csv(\'D:sh000001.csv\') feed.addBarsFromDataFrame("sh000001", trade_data) myStrategy = MyStrategy(feed, "sh000001") 运行策略 myStrategy.run()
下面对PyAlgoTrade运行过程进行简单的分析,PyAlgoTrade是基于事件驱动的回测框架,在对PyAlgoTrade进行分析之前先对事件驱动进行简要的说明。
class Event(object): def __init__(self): self.name = "tom" def getName(self): return self.name class JavaListen(object): def handleEvent(self, event): print "%s is learning java " %(event.getName()) class PythonListen(object): def handleEvent(self, event): print "%s is learning python " % (event.getName()) class EventDispatcher(object): def __init__(self): self.__observers = list() def registerEvent(self, eventlisten): self.__observers.append(eventlisten) def notifyAll(self, event): for eventListen in self.__observers: eventListen.handleEvent(event) # 事件分发器 dispatch = EventDispatcher() # 事件监听器 javaListen = JavaListen() pythonListen = PythonListen() # 向事件分发器中注册事件监听器 dispatch.registerEvent(javaListen) dispatch.registerEvent(pythonListen) # 事件源 event = Event() # 分发事件 dispatch.notifyAll(event)
由本例可以看出,我们需要一个事件分发器,然后将监听器注册到事件分发器中,当事件源触发事件时,由事件分发器负责向各个监听器分发,监听器负责执行事件处理方法,在PyAlgoTrade需要注意的是有些方法中在向事件分发器中注册监听器时并没有注册监听器,而是直接注册监听器方法,当需要分发时直接执行注册的方法。
在PyAlgoTrade回测框架中,事件驱动无处不在,再计算技术指标时,并不是先计算技术指标,而是在程序运行的工程中,当getValue时触发事件,随后通知所有的进行技术指标计算的监听器,计算指标,关于技术指标的计算将单独进行分析。
在PyAlgoTrade回测框架的回测流程:
看下面一段代码,在回测类初始化的时候向分发器dispatcher中注册了broker 和barFeed,在这里broker和barFeed担任监听器角色,于此同时向broker中注册了self.__onOrderEvent方法,想 barFeed中注册了self.__onBars方法,这2个方法在后面会详细介绍
def __init__(self, barFeed, broker): self.__dispatcher = dispatcher.Dispatcher() self.__broker.getOrderUpdatedEvent().subscribe(self.__onOrderEvent) self.__barFeed.getNewValuesEvent().subscribe(self.__onBars) self.__dispatcher.getStartEvent().subscribe(self.onStart) self.__dispatcher.getIdleEvent().subscribe(self.__onIdle) # It is important to dispatch broker events before feed events, specially if we\'re backtesting. self.__dispatcher.addSubject(self.__broker) self.__dispatcher.addSubject(self.__barFeed)
当运行交易策略时,myStrategy.run() =====》 self.__dispatcher.run()
dispatcher的run()方法如下:
def run(self): try: for subject in self.__subjects: subject.start() self.__startEvent.emit() while not self.__stop: eof, eventsDispatched = self.__dispatch() if eof: self.__stop = True elif not eventsDispatched: self.__idleEvent.emit() finally: for subject in self.__subjects: subject.stop() for subject in self.__subjects: subject.join()
在此方法中首先遍历运行subject.start()方法,这里的subject就是前面提到的再初始化的时候注册的broker 和barFeed,然后运行startEvent.emit(),这里的emit方法就是事件分发器分发的过程,在此过程中执行策略onStart方法,我们可以在定义交易类的时候实现侧方法,在回测开始的时候做一些事。
随后运行self.__dispatch()此方法时dispatcher的方法,在这里可以看到只要策略不停值,将反复执行这一过程。在此方法中主要的步骤如下:
if not eof: self.__currDateTime = smallestDateTime for subject in self.__subjects: if self.__dispatchSubject(subject, smallestDateTime): eventsDispatched = True return eof, eventsDispatched
在这里的subject就是前面提到过的broker 和barFeed。再来看__dispatchSubject方法
def __dispatchSubject(self, subject, currEventDateTime): ret = False # Dispatch if the datetime is currEventDateTime of if its a realtime subject. if not subject.eof() and subject.peekDateTime() in (None, currEventDateTime): ret = subject.dispatch() is True return ret
在此方法中运行subject.dispatch();在broker中直接pass,下面请看barFeed的dispatch()方法。
def dispatch(self): dateTime, values = self.getNextValuesAndUpdateDS() if dateTime is not None: self.__event.emit(dateTime, values) return dateTime is not None
请注意这里的self.getNextValuesAndUpdateDS()方法,在后续技术指标的解析过程中会涉及到此方法。
随后执行self.__event.emit(dateTime, values)方法,回过头看看在初始化策略类时self.__barFeed.getNewValuesEvent().subscribe(self.__onBars)
在初始化策略类之前初始化broker时
barFeed.getNewValuesEvent().subscribe(self.onBars)
这里getNewValuesEvent()返回的正是此event,在这行的emit方法时, 先执行broker中的onBars()方法,再策略类的__onBars方法。
在broker的onBars()代码如下:
def onBars(self, dateTime, bars): # 计算账户总资产 self.__fillStrategy.onBars(self, bars) # 获取有效订单 ordersToProcess = self.__activeOrders.values() # 执行订单 for order in ordersToProcess: self.__onBarsImpl(order, bars)
然后回到dispatcher继续执行dispatch()方法,至此在PyAlgoTrade回测框架的回测流程到此结束。
在这里我们可以看到,当获取新的bar的时候,先执行订单,然后计算统计指标,最后执行策略中定义的onBars()方法,由此也可以看出PyAlgoTrade在回测过程中t日产生信号,t+1日执行订单,也就是说根据昨天的数据和onBars()方法产生订单,在今天获取到新数据时以今日的收盘价执行订单进行买卖操作。
部分线上量化平台可选择t日的收盘价进行交易还是t+1日的开盘价进行交易。
感谢您的的耐心阅读,对你有所帮助是我最大的欣慰,如若有任何建议、意见或者自己不同的见解,提出来我们一起讨论。后续将对PyAlgoTrade框架中的回测框架等模块进行解析,请持续关注。