Kiểm tra ngược dựa trên sự kiện với Python - Phần IV

Tác giả:Tốt, Tạo: 2019-03-25 14:24:46, Cập nhật:

Trong bài viết này, chúng tôi sẽ phác thảo một hệ thống phân cấp lớp chiến lược. Các đối tượng chiến lược lấy dữ liệu thị trường làm đầu vào và tạo ra các sự kiện tín hiệu giao dịch làm đầu ra.

Một đối tượng chiến lược bao gồm tất cả các tính toán trên dữ liệu thị trường tạo ra các tín hiệu tư vấn cho một đối tượng danh mục đầu tư. Ở giai đoạn này trong sự phát triển backtester dựa trên sự kiện không có khái niệm về một chỉ số hoặc bộ lọc, chẳng hạn như những gì được tìm thấy trong giao dịch kỹ thuật.

Trật tự phân cấp chiến lược tương đối đơn giản vì nó bao gồm một lớp cơ sở trừu tượng với một phương pháp ảo thuần túy duy nhất để tạo ra các đối tượng SignalEvent. Để tạo ra hệ thống phân cấp chiến lược, cần phải nhập NumPy, panda, đối tượng Queue, các công cụ lớp cơ sở trừu tượng và SignalEvent:

# strategy.py

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

từ abc nhập khẩu ABCMeta, abstractmethod

từ sự kiện nhập SignalEvent Các lớp cơ sở trừu tượng Chiến lược chỉ đơn giản là xác định một phương thức calculate_signals ảo thuần túy. Trong các lớp phái sinh, nó được sử dụng để xử lý việc tạo các đối tượng SignalEvent dựa trên các cập nhật dữ liệu thị trường:

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

Định nghĩa của Strategy ABC rất đơn giản. Ví dụ đầu tiên của chúng tôi về phân loại đối tượng Strategy sử dụng một chiến lược mua và giữ để tạo lớp BuyAndHoldStrategy. Điều này đơn giản là mua dài trong một chứng khoán cụ thể vào một ngày nhất định và giữ nó trong danh mục đầu tư. Do đó, chỉ có một tín hiệu mỗi chứng khoán được tạo ra.

Nhà chế tạo (init) yêu cầu các thanh xử lý dữ liệu thị trường và các đối tượng hàng đợi sự kiện sự kiện:

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

Khi khởi động BuyAndHoldStrategy, thành viên từ điển đã mua có một tập các khóa cho mỗi biểu tượng đều được đặt thành False. Một khi tài sản đã được longed thì điều này được đặt thành True. Về cơ bản, điều này cho phép Chiến lược biết liệu nó có trong thị trường hay không:

# 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

Phương pháp ảo thuần túy calculate_signals được thực hiện cụ thể trong lớp này. Phương pháp này lặp qua tất cả các biểu tượng trong danh sách biểu tượng và lấy thanh mới nhất từ bộ xử lý dữ liệu thanh. Sau đó nó kiểm tra xem biểu tượng đó đã được bought (tức là liệu chúng ta có đang trong thị trường cho biểu tượng này hay không) và nếu không tạo ra một đối tượng SignalEvent duy nhất. Điều này sau đó được đặt vào hàng đợi sự kiện và từ điển mua được cập nhật chính xác thành True cho khóa biểu tượng cụ thể này:

# 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

Đây rõ ràng là một chiến lược đơn giản nhưng nó đủ để chứng minh bản chất của một phân cấp chiến lược dựa trên sự kiện. Trong các bài viết tiếp theo chúng ta sẽ xem xét các chiến lược phức tạp hơn như giao dịch cặp. Trong bài viết tiếp theo chúng ta sẽ xem xét cách tạo một phân cấp danh mục đầu tư theo dõi các vị trí của chúng ta với lợi nhuận và lỗ (PnL).


Thêm nữa