イベント駆動バックテスト Python - Part II

作者: リン・ハーン優しさ作成日: 2019-03-23 09:13:33, 更新日:

事件駆動バックテストの概念について説明しました.このシリーズの残りの記事は,全体的なシステムを構成する個々のクラス階層に焦点を当てます.この記事では,イベントとオブジェクト間の情報通信に使用する方法について検討します.

前回の記事で議論したように,取引システムは,外側と内側の2つのウィンドウを使用します.内側ウィンドウは,メモリ内のキューからイベントのキャプチャを処理し,その後,次のアクションのために適切なコンポーネントにルーティングされます.このインフラストラクチャには,4種類のイベントがあります:

  • MarketEvent - 外部の whileループが新しい"ハートビート"を開始するときに起動する.DataHandlerオブジェクトが現在追跡されている任意のシンボルの市場データの新しい更新を受け取るときに発生する.新しい取引信号を生成するStrategyオブジェクトを起動するために使用される.イベントオブジェクトには単に他の構造なしの市場イベントであることを識別する要素が含まれています.
  • SignalEvent - 戦略オブジェクトは,新しいSignalEventsを作成するために市場データを利用します. SignalEventには,ティッカーシンボル,生成時のタイムスタンプ,方向 (長または短) が含まれています. SignalEventsは,ポートフォリオオブジェクトによって取引方法に関するアドバイスとして使用されます.
  • OrderEvent - ポートフォリオオブジェクトがSignalEventsを受信すると,リスクとポジションサイジングの観点から,ポートフォリオのより広い文脈でそれらを評価します.これは最終的にExecutionHandlerに送信されるOrderEventsにつながります.
  • FillEvent - ExecutionHandler が OrderEvent を受信すると,注文を処理しなければならない.注文が処理されたら,購入または販売のコスト,および手数料やスリップなどの取引コストを記述する FillEvent を生成する.

親クラスは Event と呼ばれる.これはベースクラスで,機能や特定のインターフェースを提供していない.後の実装では, Event オブジェクトはより複雑なものを開発する可能性があり,したがって,クラス階層を作成することで,そのようなシステムの設計を将来的に証明しています.

# event.py

class Event(object):
    """
    Event is base class providing an interface for all subsequent 
    (inherited) events, that will trigger further events in the 
    trading infrastructure.   
    """
    pass

MarketEventは,Eventから継承され,それがMARKET型イベントであることを自認する以上のことを提供する.

# event.py

class MarketEvent(Event):
    """
    Handles the event of receiving a new market update with 
    corresponding bars.
    """

    def __init__(self):
        """
        Initialises the MarketEvent.
        """
        self.type = 'MARKET'

SignalEvent は,ポートフォリオ オブジェクトに助言するために,ティッカーシンボル,生成のタイムスタンプ,方向が必要です.

# event.py

class SignalEvent(Event):
    """
    Handles the event of sending a Signal from a Strategy object.
    This is received by a Portfolio object and acted upon.
    """
    
    def __init__(self, symbol, datetime, signal_type):
        """
        Initialises the SignalEvent.

        Parameters:
        symbol - The ticker symbol, e.g. 'GOOG'.
        datetime - The timestamp at which the signal was generated.
        signal_type - 'LONG' or 'SHORT'.
        """
        
        self.type = 'SIGNAL'
        self.symbol = symbol
        self.datetime = datetime
        self.signal_type = signal_type

OrderEvent は SignalEvent の上記プロパティに加え,数値フィールドを含んでいるため, OrderEvent は SignalEvent より少し複雑である.数値は Portfolio 制約によって決定される.また,OrderEvent には print_order (注) メソッドがあり,必要に応じてコンソールに情報を出力するために使用される.

# event.py

class OrderEvent(Event):
    """
    Handles the event of sending an Order to an execution system.
    The order contains a symbol (e.g. GOOG), a type (market or limit),
    quantity and a direction.
    """

    def __init__(self, symbol, order_type, quantity, direction):
        """
        Initialises the order type, setting whether it is
        a Market order ('MKT') or Limit order ('LMT'), has
        a quantity (integral) and its direction ('BUY' or
        'SELL').

        Parameters:
        symbol - The instrument to trade.
        order_type - 'MKT' or 'LMT' for Market or Limit.
        quantity - Non-negative integer for quantity.
        direction - 'BUY' or 'SELL' for long or short.
        """
        
        self.type = 'ORDER'
        self.symbol = symbol
        self.order_type = order_type
        self.quantity = quantity
        self.direction = direction

    def print_order(self):
        """
        Outputs the values within the Order.
        """
        print "Order: Symbol=%s, Type=%s, Quantity=%s, Direction=%s" % \
            (self.symbol, self.order_type, self.quantity, self.direction)

FillEventは,最も複雑なイベントです.注文が完了した時のタイムスタンプ,注文のシンボルと取引所,取引された株の量,購入の実際の価格,発生した手数料を含む.

コミションは,インタラクティブ・ブローカーズ・コミッションを用いて計算される.米国APIの注文では,このコミッションは1つの注文につき最低1.30USDで,取引規模が500株未満または上であるかどうかに基づいて,1株あたり0.013USDまたは0.08USDの固定金利である.

# event.py

class FillEvent(Event):
    """
    Encapsulates the notion of a Filled Order, as returned
    from a brokerage. Stores the quantity of an instrument
    actually filled and at what price. In addition, stores
    the commission of the trade from the brokerage.
    """

    def __init__(self, timeindex, symbol, exchange, quantity, 
                 direction, fill_cost, commission=None):
        """
        Initialises the FillEvent object. Sets the symbol, exchange,
        quantity, direction, cost of fill and an optional 
        commission.

        If commission is not provided, the Fill object will
        calculate it based on the trade size and Interactive
        Brokers fees.

        Parameters:
        timeindex - The bar-resolution when the order was filled.
        symbol - The instrument which was filled.
        exchange - The exchange where the order was filled.
        quantity - The filled quantity.
        direction - The direction of fill ('BUY' or 'SELL')
        fill_cost - The holdings value in dollars.
        commission - An optional commission sent from IB.
        """
        
        self.type = 'FILL'
        self.timeindex = timeindex
        self.symbol = symbol
        self.exchange = exchange
        self.quantity = quantity
        self.direction = direction
        self.fill_cost = fill_cost

        # Calculate commission
        if commission is None:
            self.commission = self.calculate_ib_commission()
        else:
            self.commission = commission

    def calculate_ib_commission(self):
        """
        Calculates the fees of trading based on an Interactive
        Brokers fee structure for API, in USD.

        This does not include exchange or ECN fees.

        Based on "US API Directed Orders":
        https://www.interactivebrokers.com/en/index.php?f=commission&p=stocks2
        """
        full_cost = 1.3
        if self.quantity <= 500:
            full_cost = max(1.3, 0.013 * self.quantity)
        else: # Greater than 500
            full_cost = max(1.3, 0.008 * self.quantity)
        full_cost = min(full_cost, 0.5 / 100.0 * self.quantity * self.fill_cost)
        return full_cost

次の記事では,同じクラスインターフェースを通じて,歴史的なバックテストとライブ取引の両方を可能にする市場 DataHandler クラスの階層をどのように開発するかについて検討します.


もっと