Еще примеры для профилировщика событий в pyalgotrade

Я пытаюсь научиться внедрять собственные стратегии в профилировщик событий для pyalgotrade. Это пример по умолчанию, который они дают.

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)

введите описание изображения здесь Есть ли у кого-нибудь источник еще нескольких примеров?

Я пытаюсь выяснить, как eventprofiler получает и использует данные, хотя вызывается довольно много методов класса, и мне кажется, что это немного сложно анализировать.

Я хочу начать с простого и просто использовать price и volume. Одной из стратегий будет
if volume > 1000 and close < 50: event == True

Любая помощь будет оценена по достоинству.

P.s.: дополнительный вопрос: есть ли аналогичный профилировщик событий для zipline?

РЕДАКТИРОВАТЬ: благодаря user3666197 я смог внести изменения, которые хотел, однако я получаю эту ошибку:

Traceback (most recent call last):
  File "C:\Users\David\Desktop\Python\Coursera\Computational Finance\Week2\PyAlgoTrade\Bitfinex\FCT\FCT_single_event_test.py", line 43, in <module>
    main(True)
  File "C:\Users\David\Desktop\Python\Coursera\Computational Finance\Week2\PyAlgoTrade\Bitfinex\FCT\FCT_single_event_test.py", line 35, in main
    eventProfiler.run(feed, True)
  File "C:\Python27\lib\site-packages\pyalgotrade\eventprofiler.py", line 215, in run
    disp.run()
  File "C:\Python27\lib\site-packages\pyalgotrade\dispatcher.py", line 102, in run
    eof, eventsDispatched = self.__dispatch()
  File "C:\Python27\lib\site-packages\pyalgotrade\dispatcher.py", line 90, in __dispatch
    if self.__dispatchSubject(subject, smallestDateTime):
  File "C:\Python27\lib\site-packages\pyalgotrade\dispatcher.py", line 68, in __dispatchSubject
    ret = subject.dispatch() is True
  File "C:\Python27\lib\site-packages\pyalgotrade\feed\__init__.py", line 105, in dispatch
    self.__event.emit(dateTime, values)
  File "C:\Python27\lib\site-packages\pyalgotrade\observer.py", line 59, in emit
    handler(*args, **kwargs)
  File "C:\Python27\lib\site-packages\pyalgotrade\eventprofiler.py", line 172, in __onBars
    eventOccurred = self.__predicate.eventOccurred(instrument, self.__feed[instrument])
  File "C:\Python27\lib\site-packages\pyalgotrade\eventprofiler.py", line 89, in eventOccurred
    raise NotImplementedError()
NotImplementedError
[Finished in 1.9s]

Я просмотрел исходный файл «eventprofiler.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)

person David Hancock    schedule 19.05.2016    source источник
comment
лучше использовать копировать/вставить, чтобы избежать опечаток ››› stackoverflow.com/a/37442549/3666197 указал на один такой найденный в def eventOccoured(...) вместо eventOccured(...)   -  person user3666197    schedule 26.05.2016
comment
Я сделаю в следующий раз. Еще раз большое спасибо за ваш подробный ответ, это очень ценно.   -  person David Hancock    schedule 26.05.2016


Ответы (2)


Квантовый пролог:

Большое спасибо проф. Такеру БАЛЧ, GA-TECH [GA], и его команде за QSTK-инициативу и инновационные подходы к количественному финансовому моделированию. введите здесь описание изображения

Как eventprofiler получает данные?

Проще говоря, он получает доступ к полному feed как в eventprofiler.run( feed , ... ), так и в виде eventprofiler.Predicate-обернутого feed, где он получает весь фид -details право доступа к экземпляру .Predicate с помощью Class-параметра, чтобы можно было вычислить там реализованные все детали, необходимые для расчета стратегии. Разумно, не так ли?

Остальное делается путем повторного использования их методов класса.


Как построить свою?

Достаточно объявить соответствующим образом оборудованный 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

Остальное как всегда просто:

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

Квантовый эпилог:

Внимательный читатель заметил, что предлагаемый код не вызывает метод .getAdjClose(). Причина в том, что глубокое тестирование на исторических данных может быть искажено очень близкими корректировками при принятии решений во времена, когда корректировки еще не известны. Справедливая обязанность каждого профессионального количественного аналитика состоит в том, чтобы избегать любых способов заглянуть в будущее и тщательно решать, где необходимы корректировки в отношении оценки портфеля, если время владения инструментом подвергалось корректировке в течение его соответствующего жизненного цикла или нет.

person user3666197    schedule 19.05.2016
comment
Эй, большое спасибо за отличный ответ, это было очень полезно. Однако предложенный вами код дает ошибку. Не могли бы вы быстро взглянуть? - person David Hancock; 20.05.2016
comment
Извините за беспокойство, но я пытаюсь настроить EP для анализа bards[i], где i › -1. Однако я получаю IndexError. Если бы вы могли посмотреть, это было бы очень полезно bar-eg-ba" title="настройте профиль события в pyalgotrade, чтобы оглядываться назад дальше, чем на один бар, например, ba">stackoverflow.com/questions/37536998/ - person David Hancock; 31.05.2016

Бонусный ответ

Хотя мотивация вопроса ясна, есть несколько причин, по которым ответ не так однозначен, как может показаться.

Во-первых, как все работает:

eventprofiler в QSTK и pyalgotrade построен на основе DataSeries представления Маркет, где внешние данные вводятся (не сохраняются) через feed-механизм.

Подход zipline отличается и утверждает, что основная функциональность сосредоточена на его механизме моделирования на основе событий, который работает на уровне атомарной роли каждого ценового-QUOTE-тика (асинхронное поступление внешнего события). и локальная адаптивная обработка).

Последовательный характер обработки потока событий имеет некоторую привлекательность для имитации обратного тестирования in vitro.

Сильные стороны QSTK-исходного eventprofiler, напротив, основаны на обработке полных-длинных DataSeries-представлений сразу (или на каком-то умном итераторе, перевербированном или эффективном numpy stride-уловки и магия).

Это огромное концептуальное различие затрудняет создание такого же умного, быстрого, эффективного и простого в использовании инструмента, как QSTK eventprofiler, в среде обработки событий.

person user3666197    schedule 19.05.2016