Event-Driven Backtesting dengan Python - Bagian IV

Penulis:Kebaikan, Dibuat: 2019-03-25 14:24:46, Diperbarui:

Diskusi implementasi backtesting event-driven sebelumnya telah mempertimbangkan event-loop, hierarki kelas acara dan komponen penanganan data.

Sebuah objek Strategi merangkum semua perhitungan pada data pasar yang menghasilkan sinyal penasihat ke objek Portofolio. Pada tahap ini dalam pengembangan backtester yang didorong oleh peristiwa tidak ada konsep indikator atau filter, seperti yang ditemukan dalam perdagangan teknis.

Hierarki strategi relatif sederhana karena terdiri dari kelas dasar abstrak dengan satu metode virtual murni untuk menghasilkan objek SignalEvent. Untuk membuat hierarki Strategi perlu mengimpor NumPy, pandas, objek Queue, alat kelas dasar abstrak dan SignalEvent:

# strategy.py

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

dari abc import ABCMeta, metode abstrak

dari event import SignalEvent Kelas dasar abstrak Strategy hanya mendefinisikan metode virtual murni calculate_signals. Dalam kelas turunan ini digunakan untuk menangani generasi objek SignalEvent berdasarkan pembaruan data pasar:

# 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 dari Strategy ABC adalah sederhana. contoh pertama dari subclassing objek Strategy menggunakan strategi buy and hold untuk membuat kelas BuyAndHoldStrategy. Ini hanya pergi panjang dalam sekuritas tertentu pada tanggal tertentu dan menyimpannya dalam portofolio. Dengan demikian hanya satu sinyal per sekuritas yang pernah dihasilkan.

Pembuat (init) membutuhkan pengolah data pasar bar dan objek antrian acara acara:

# 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 inisialisasi BuyAndHoldStrategy anggota kamus yang dibeli memiliki seperangkat kunci untuk setiap simbol yang semuanya ditetapkan menjadi False. Setelah aset telah longed maka ini ditetapkan menjadi True. Pada dasarnya ini memungkinkan Strategi untuk mengetahui apakah itu di pasar 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

Metode virtual murni calculate_signals diimplementasikan secara konkret dalam kelas ini. Metode ini melingkar semua simbol dalam daftar simbol dan mengambil bar terbaru dari pengelola data bar. Kemudian memeriksa apakah simbol tersebut telah dibeli (yaitu apakah kita berada di pasar untuk simbol ini atau tidak) dan jika tidak menciptakan satu objek SignalEvent. Ini kemudian ditempatkan di antrian acara dan kamus yang dibeli diperbarui dengan benar menjadi True 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 sederhana tetapi cukup untuk menunjukkan sifat hierarki strategi yang didorong oleh peristiwa. Dalam artikel berikutnya kita akan mempertimbangkan strategi yang lebih canggih seperti perdagangan pasangan. Dalam artikel berikutnya kita akan mempertimbangkan bagaimana membuat hierarki portofolio yang melacak posisi kita dengan keuntungan dan kerugian (PnL).


Lebih banyak