A discussão da implementação de backtesting orientado por eventos já considerou o ciclo de eventos, a hierarquia de classes de eventos e o componente de manuseio de dados.
Um objeto de estratégia encapsula todos os cálculos sobre dados de mercado que geram sinais de aconselhamento para um objeto de carteira.
A hierarquia de estratégia é relativamente simples, pois consiste em uma classe base abstrata com um único método virtual puro para gerar objetos SignalEvent.
# strategy.py
import datetime
import numpy as np
import pandas as pd
import Queue
de abc import ABCMeta, abstractmethod
de importação de evento SignalEvent A classe base abstrata Strategy simplesmente define um método virtual puro calculate_signals.
# strategy.py
class Strategy(object):
"""
Strategy is an abstract base class providing an interface for
all subsequent (inherited) strategy handling objects.
The goal of a (derived) Strategy object is to generate Signal
objects for particular symbols based on the inputs of Bars
(OLHCVI) generated by a DataHandler object.
This is designed to work both with historic and live data as
the Strategy object is agnostic to the data source,
since it obtains the bar tuples from a queue object.
"""
__metaclass__ = ABCMeta
@abstractmethod
def calculate_signals(self):
"""
Provides the mechanisms to calculate the list of signals.
"""
raise NotImplementedError("Should implement calculate_signals()")
A definição de Estratégia ABC é simples. Nosso primeiro exemplo de subclasse do objeto Estratégia faz uso de uma estratégia de compra e retenção para criar a classe BuyAndHoldStrategy. Isso simplesmente vai longo em um determinado valor em uma determinada data e mantém-lo dentro da carteira. Assim, apenas um sinal por valor é gerado.
O fabricante (Iniciar) requer que o processador de dados do mercado de barras e o objeto da fila de eventos:
# strategy.py
class BuyAndHoldStrategy(Strategy):
"""
This is an extremely simple strategy that goes LONG all of the
symbols as soon as a bar is received. It will never exit a position.
It is primarily used as a testing mechanism for the Strategy class
as well as a benchmark upon which to compare other strategies.
"""
def __init__(self, bars, events):
"""
Initialises the buy and hold strategy.
Parameters:
bars - The DataHandler object that provides bar information
events - The Event Queue object.
"""
self.bars = bars
self.symbol_list = self.bars.symbol_list
self.events = events
# Once buy & hold signal is given, these are set to True
self.bought = self._calculate_initial_bought()
Na inicialização da BuyAndHoldStrategy, o membro do dicionário comprado tem um conjunto de chaves para cada símbolo que estão todas definidas em Falso.
# strategy.py
def _calculate_initial_bought(self):
"""
Adds keys to the bought dictionary for all symbols
and sets them to False.
"""
bought = {}
for s in self.symbol_list:
bought[s] = False
return bought
O método virtual puro calculate_signals é implementado concretamente nesta classe. O método percorre todos os símbolos da lista de símbolos e recupera a última barra do manipulador de dados de barras. Em seguida, verifica se esse símbolo foi
# strategy.py
def calculate_signals(self, event):
"""
For "Buy and Hold" we generate a single signal per symbol
and then no additional signals. This means we are
constantly long the market from the date of strategy
initialisation.
Parameters
event - A MarketEvent object.
"""
if event.type == 'MARKET':
for s in self.symbol_list:
bars = self.bars.get_latest_bars(s, N=1)
if bars is not None and bars != []:
if self.bought[s] == False:
# (Symbol, Datetime, Type = LONG, SHORT or EXIT)
signal = SignalEvent(bars[0][0], bars[0][1], 'LONG')
self.events.put(signal)
self.bought[s] = True
Esta é claramente uma estratégia simples, mas é suficiente para demonstrar a natureza de uma hierarquia de estratégia orientada por eventos. Nos artigos subsequentes, consideraremos estratégias mais sofisticadas, como um comércio de pares.