pyalgotrad中事件探查器的更多示例

2024-06-16 18:21:07 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试学习如何在pyalgotrade的事件探查器中实现自定义策略。This is the default example they give。在

from pyalgotrade           import eventprofiler
from pyalgotrade.technical import stats
from pyalgotrade.technical import roc
from pyalgotrade.technical import ma
from pyalgotrade.tools     import yahoofinance

#     Event inspired on an example from Ernie Chan's book:
#    'Algorithmic Trading: Winning Strategies and Their Rationale'

class BuyOnGap(eventprofiler.Predicate):
    def __init__(self, feed):
        stdDevPeriod = 90
        smaPeriod = 20
        self.__returns = {}
        self.__stdDev = {}
        self.__ma = {}
        for instrument in feed.getRegisteredInstruments():
            priceDS = feed[instrument].getAdjCloseDataSeries()
            #      Returns over the adjusted close values.
            self.__returns[instrument] = roc.RateOfChange(priceDS, 1)
            #      StdDev over those returns.
            self.__stdDev[instrument] = stats.StdDev(self.__returns[instrument], stdDevPeriod)
            #      MA over the adjusted close values.
            self.__ma[instrument] = ma.SMA(priceDS, smaPeriod)

    def __gappedDown(self, instrument, bards):
        ret = False
        if self.__stdDev[instrument][-1] != None:
            prevBar = bards[-2]
            currBar = bards[-1]
            low2OpenRet = (currBar.getAdjOpen() - prevBar.getAdjLow()) / float(prevBar.getAdjLow())
            if low2OpenRet < (self.__returns[instrument][-1] - self.__stdDev[instrument][-1]):
                ret = True
        return ret

    def __aboveSMA(self, instrument, bards):
        ret = False
        if self.__ma[instrument][-1] != None and bards[-1].getAdjOpen() > self.__ma[instrument][-1]:
            ret = True
        return ret

    def eventOccurred(self, instrument, bards):
        ret = False
        if self.__gappedDown(instrument, bards) and self.__aboveSMA(instrument, bards):
            ret = True
        return ret

def main(plot):
    instruments = ["AA", "AES", "AIG"]
    feed = yahoofinance.build_feed(instruments, 2008, 2009, ".")

    predicate = BuyOnGap(feed)
    eventProfiler = eventprofiler.Profiler(predicate, 5, 5)
    eventProfiler.run(feed, True)

    results = eventProfiler.getResults()
    print "%d events found" % (results.getEventCount())
    if plot:
        eventprofiler.plot(results)

if __name__ == "__main__":
    main(True)

enter image description here有没有人有更多的例子?

我试图弄清楚eventprofiler是如何接收和使用数据的,虽然有很多类方法被调用,但我发现分解它有点棘手。在

我想从简单开始,只使用price和{}。一种策略是
if volume > 1000 and close < 50: event == True

任何帮助都将不胜感激。在

附言:额外问题:是否有类似的事件探查器zipline?在

编辑:多亏了用户3666197,我能够进行我想要的更改,但是我得到了这个错误:

^{pr2}$

我已经看过消息来源了事件探查器.py“搞不清是什么。这是密码

from pyalgotrade import eventprofiler
from pyalgotrade.technical import stats
from pyalgotrade.technical import roc
from pyalgotrade.technical import ma
from pyalgotrade.barfeed import csvfeed

# Event inspired on an example from Ernie Chan's book:
# 'Algorithmic Trading: Winning Strategies and Their Rationale'

class single_event_strat( eventprofiler.Predicate ):
    def __init__(self,feed):
        self.__returns = {} # CLASS ATTR
        for inst in feed.getRegisteredInstruments():

            priceDS = feed[inst].getAdjCloseDataSeries() # STORE: priceDS ( a temporary representation )

            self.__returns[inst] = roc.RateOfChange( priceDS, 1 )
            # CALC:  ATTR <- Returns over the adjusted close values, consumed priceDS 
            #( could be expressed as self.__returns[inst] = roc.RateOfChange( ( feed[inst].getAdjCloseDataSeries() ), 1 ), 
            #but would be less readable

    def eventOccoured( self, instrument, aBarDS):
        if (aBarDS[-1].getVolume() > 1000 and aBarDS[-1].getClose() > 50 ):
            return True
        else: 
            return False

def main(plot):
    feed = csvfeed.GenericBarFeed(0)

    feed.addBarsFromCSV('FCT', "FCT_daily_converted.csv")

    predicate = single_event_strat(feed)
    eventProfiler = eventprofiler.Profiler(predicate, 5, 5)
    eventProfiler.run(feed, True)

    results = eventProfiler.getResults()
    print "%d events found" % (results.getEventCount())
    if plot:
        eventprofiler.plot(results)

if __name__ == "__main__":
    main(True)

Tags: fromimportselftrueifdeffeedreturns
2条回答

答题奖金

虽然这个问题的动机是明确的,但有几个原因,为什么答案不像看上去那么直接。在

首先,事情是如何运作的:

^{pyalgotrade中的是建立在DataSeries市场表现的基础上的,其中外部数据通过feed-机制输入(不存储)。在

zipline方法是不同的和状态的,其核心功能集中在其基于事件的模拟引擎上,该引擎在每个price-QUOTE-tick(异步外部事件到达和本地响应处理)的原子角色级别上运行。在

事件流处理的连续性对模拟的体外回溯测试有一定的吸引力。在

源于QSTKeventprofiler的优点恰恰相反,它基于一次处理完整的-lengthDataSeries-表示(或者一些智能迭代器重写或高效的numpystride-技巧和魔术)。在

这种巨大的概念差异使得我们很难获得一个类似的智能+快速+高效+易于重用的工具,正如QSTKeventprofiler一样,在事件处理环境中。在

数量序幕:

Many thanks to prof. Tucker BALCH, GA-TECH [GA], and his team, for QSTK-initiative and the innovative approaches to Quantitative Finance Modelling. enter image description here

How the eventprofiler takes in data?

简单地说,它在^{feed中接收对完整feed, ... )的访问,同时也是一个eventprofiler.Predicate-wrappedfeed实例的访问权,其中通过一个类参数将所有提要的详细信息直接访问.Predicate实例中,从而能够计算出实现策略演算所需的所有细节。聪明,不是吗?

其余的是通过重用它们的类方法来完成的。在


如何建立自己的?在

声明一个适当配置的eventprofiler.Predicate就足够了,它将被注入到evenprofiler实例化中:

class DavidsSTRATEGY( eventprofiler.Predicate ):
      def __init__( self, feed ):                         # mandatory .__init__
          """                                               no need for this code
                                                            left here for didactic
                                                            purposes only
                                                            to show the principle

          self.__returns = {}                                         # CLASS ATTR

          for                inst in feed.getRegisteredInstruments():
              priceDS = feed[inst].getAdjCloseDataSeries()            # STORE: priceDS ( a temporary representation )
              self.__returns[inst] = roc.RateOfChange( priceDS, 1 )   # CALC:  ATTR <- Returns over the adjusted close values, consumed priceDS ( could be expressed as self.__returns[inst] = roc.RateOfChange( ( feed[inst].getAdjCloseDataSeries() ), 1 ), but would be less readable
          """

      def eventOccurred( self, instrument, aBarDS ):       # mandatory .eventOccured
          if (   aBarDS[-1].getVolume() > 1000             # "last" Bar's Volume >
             and aBarDS[-1].getClose()  <   50             # "last" Bar's Close  <
             ):
                 return True
          else:
                 return False

剩下的事情将一如既往地简单:

^{pr2}$

定量结语:

一位细心的读者注意到,建议的代码没有调用.getAdjClose()方法。理由是,深度回溯测试可能会被非常接近的调整所扭曲,在调整尚未可知的情况下做出决策。每一个专业的定量分析师都有责任避免任何窥视未来的手段,并仔细决定在需要调整的地方,就投资组合估值而言,一个工具持有时间是否在其各自的生命周期内经历了调整。在

相关问题 更多 >