Pengujian Kembali yang Dikendalikan Acara dengan Python - Bahagian IV

Penulis:Kebaikan, Dicipta: 2019-03-25 14:24:46, Dikemas kini:

Perbincangan mengenai pelaksanaan backtesting yang didorong oleh peristiwa sebelum ini telah mempertimbangkan gelung peristiwa, hierarki kelas peristiwa dan komponen pengendalian data.

Objek Strategi merangkumi semua pengiraan pada data pasaran yang menghasilkan isyarat nasihat kepada objek Portfolio. Pada peringkat ini dalam pembangunan backtester yang didorong peristiwa tidak ada konsep penunjuk atau penapis, seperti yang terdapat dalam perdagangan teknikal. Ini juga merupakan calon yang baik untuk mewujudkan hierarki kelas tetapi berada di luar skop artikel ini.

Hierarki strategi agak mudah kerana ia terdiri daripada kelas asas abstrak dengan satu kaedah maya murni untuk menjana objek SignalEvent. Untuk membuat hierarki Strategi, perlu mengimport NumPy, pandas, objek Queue, alat kelas asas abstrak dan SignalEvent:

# strategy.py

import datetime
import numpy as np
import pandas as pd
import Queue

daripada abc import ABCMeta, abstrakmetod

daripada import peristiwa SignalEvent Kelas asas abstrak Strategi hanya mentakrifkan kaedah virtual murni calculate_signals. Dalam kelas turunan ini digunakan untuk mengendalikan penjanaan objek SignalEvent berdasarkan kemas kini data pasaran:

# 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()")

Definisi Strategy ABC adalah mudah. Contoh pertama kami untuk mengelaskan objek Strategy menggunakan strategi beli dan pegang untuk membuat kelas BuyAndHoldStrategy. Ini hanya panjang dalam sekuriti tertentu pada tarikh tertentu dan menyimpannya dalam portfolio. Oleh itu, hanya satu isyarat setiap sekuriti yang dihasilkan.

Pembina (mulakan) memerlukan pengendali data pasaran bar dan objek bar bar event queue:

# 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()

Pada permulaan BuyAndHoldStrategy ahli kamus yang dibeli mempunyai satu set kunci untuk setiap simbol yang semuanya ditetapkan kepada False. Setelah aset telah longed maka ini ditetapkan kepada True. Pada dasarnya ini membolehkan Strategi untuk mengetahui sama ada ia dalam pasaran atau tidak:

# 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

Cara virtual murni calculate_signals dilaksanakan secara konkrit dalam kelas ini. Kaedah ini mengelilingi semua simbol dalam senarai simbol dan mengambil bar terbaru dari pengendali data bar. Kemudian ia memeriksa sama ada simbol itu telah beli (iaitu sama ada kita berada di pasaran untuk simbol ini atau tidak) dan jika tidak mencipta objek SignalEvent tunggal. Ini kemudian diletakkan pada barisan acara dan kamus yang dibeli dikemas kini dengan betul kepada Benar untuk kunci simbol tertentu ini:

# 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

Ini jelas merupakan strategi yang mudah tetapi mencukupi untuk menunjukkan sifat hierarki strategi yang didorong oleh peristiwa. Dalam artikel seterusnya kita akan mempertimbangkan strategi yang lebih canggih seperti perdagangan pasangan. Dalam artikel seterusnya kita akan mempertimbangkan bagaimana untuk membuat hierarki portfolio yang mengesan kedudukan kita dengan keuntungan dan kerugian (PnL).


Lebih lanjut