Kontinuierliche Futures-Verträge für Backtestzwecke

Schriftsteller:Gutes, Erstellt: 2019-03-18 10:48:28, aktualisiert:

Kurzer Überblick über Futureskontrakte

Futures sind eine Form von Vertrag, der zwischen zwei Parteien zum Kauf oder Verkauf einer Menge eines zugrunde liegenden Vermögenswertes zu einem bestimmten Zeitpunkt in der Zukunft geschlossen wird. Dieses Datum wird als Lieferung oder Ablauf bezeichnet.

In der Praxis werden Futures an den Börsen (im Gegensatz zum Over The Counter - OTC-Handel) für standardisierte Mengen und Qualitäten des Basiswerts gehandelt. Die Preise werden täglich auf dem Markt markiert. Futures sind unglaublich flüssig und werden häufig für spekulative Zwecke verwendet. Während Futures oft zur Absicherung der Preise von landwirtschaftlichen oder industriellen Gütern verwendet wurden, kann ein Futures-Kontrakt auf jedem materiellen oder immateriellen Basiswert wie Aktienindizes, Zinssätzen von Devisenwerten gebildet werden.

Eine detaillierte Liste aller für Futures-Kontrakte an verschiedenen Börsen verwendeten Symbolcodes finden Sie auf der CSI Data-Website: Futures Factsheet.

Der Hauptunterschied zwischen einem Futures-Kontrakt und einem Aktienbesitz ist die Tatsache, dass ein Futures-Kontrakt aufgrund des Ablaufdatums ein begrenztes Verfügbarkeitsfenster hat. Zu jedem Zeitpunkt gibt es eine Vielzahl von Futures-Kontrakten auf demselben Basiswert, die alle mit unterschiedlichen Ablaufdaten ablaufen. Der Vertrag mit dem nächstgelegenen Ablaufdatum wird als Near-Kontrakt bezeichnet. Das Problem, dem wir als quantitative Händler gegenüberstehen, ist, dass wir zu jedem Zeitpunkt die Wahl zwischen mehreren Verträgen haben, mit denen wir handeln können.

Ziel dieses Artikels ist es, verschiedene Ansätze zur Konstruktion eines kontinuierlichen Vertragsstroms aus dieser Reihe von mehreren Serien zu skizzieren und die mit jeder Technik verbundenen Kompromisse hervorzuheben.

Abschluss eines fortlaufenden Futures-Vertrags

Die Hauptschwierigkeit beim Versuch, einen kontinuierlichen Vertrag aus den zugrunde liegenden Verträgen mit unterschiedlichen Lieferungen zu generieren, besteht darin, dass die Verträge oft nicht zu den gleichen Preisen gehandelt werden. Daher entstehen Situationen, in denen sie keine reibungslose Verschmelzung von einem zum nächsten ermöglichen. Dies ist auf Kontango- und Backwardation-Effekte zurückzuführen. Es gibt verschiedene Ansätze, um dieses Problem anzugehen, die wir jetzt diskutieren.

Gemeinsame Ansätze

Es gibt leider keine einzige standard Methode, Futures-Kontrakte in der Finanzindustrie zusammenzuschließen. Letztendlich hängt die gewählte Methode stark von der Strategie ab, mit der die Verträge und die Ausführungsmethode verwendet werden.

Zurück/vorwärts (Panama) Anpassung

Diese Methode verringert die Lücke zwischen mehreren Verträgen, indem sie jeden Vertrag so verschiebt, dass die einzelnen Lieferungen reibungslos mit den angrenzenden Verträgen verbunden sind.

Das Hauptproblem der Panama-Methode ist die Einführung einer Trendverzerrung, die zu einem großen Preisverfall führt. Dies kann zu negativen Daten für ausreichend historische Verträge führen. Darüber hinaus gibt es einen Verlust der relativen Preisunterschiede aufgrund einer absoluten Wertverschiebung. Dies bedeutet, dass die Renditen kompliziert zu berechnen sind (oder einfach falsch).

Verhältnismäßige Anpassung

Der Ansatz der Proportionalitätsanpassung ist ähnlich der Anpassungsmethode für die Abwicklung von Aktienspaltungen. Anstatt in den aufeinanderfolgenden Verträgen eine absolute Verschiebung einzunehmen, wird das Verhältnis des älteren Abwicklungspreises (Schließpreis) zum neueren offenen Preis verwendet, um die Preise historischer Verträge proportional anzupassen. Dies ermöglicht einen kontinuierlichen Strom ohne Unterbrechung der Berechnung der prozentuale Rendite.

Das Hauptproblem mit der proportionalem Anpassung ist, dass alle Handelsstrategien, die auf ein absolutes Preisniveau angewiesen sind, ebenfalls ähnlich angepasst werden müssen, um das richtige Signal auszuführen. Dies ist ein problematischer und fehleranfälliger Prozess. Daher ist diese Art von kontinuierlichem Strom oft nur für eine zusammengefasste statistische Analyse nützlich, im Gegensatz zu direkter Backtesting-Forschung.

Überholung/Perpetual-Serie

Der Kern dieses Ansatzes besteht darin, einen kontinuierlichen Vertrag von aufeinanderfolgenden Verträgen zu schaffen, indem ein linear gewichteter Anteil an jedem Vertrag über eine Anzahl von Tagen genommen wird, um einen reibungsloseren Übergang zwischen jedem zu gewährleisten.

Zum Beispiel betrachten wir fünf Glättungstage. Der Preis am Tag 1, P1, ist gleich 80% des Far-Kontraktpreises (F1) und 20% des Near-Kontraktpreises (N1). Ähnlich ist der Preis am Tag 2, P2=0.6×F2+0.4×N2. Am Tag 5 haben wir P5=0.0×F5+1.0×N5=N5 und der Vertrag wird dann einfach eine Fortsetzung des Near-Preises. So wird der Vertrag nach fünf Tagen reibungslos vom Far zu dem Near übergegangen.

Das Problem mit der Rollover-Methode ist, dass sie den Handel an allen fünf Tagen erfordert, was die Transaktionskosten erhöhen kann.

Es gibt andere, weniger verbreitete Ansätze, aber wir werden sie hier vermeiden.

Roll-Return-Formation in Python und Pandas

Der Rest des Artikels konzentriert sich auf die Implementierung der Perpetual-Series-Methode, da diese für Backtesting am besten geeignet ist.

Wir werden den WTI-Rohöl-Futures-Kontrakt near und far (Symbol CL) zusammenfügen, um eine kontinuierliche Preisreihe zu erzeugen. Zum Zeitpunkt des Schreibens (Januar 2014) ist der nahe Vertrag CLF2014 (Januar) und der weite Vertrag CLG2014 (Februar).

Für den Download von Futures-Daten habe ich das Quandl-Plugin verwendet. Stellen Sie sicher, dass Sie die richtige virtuelle Python-Umgebung auf Ihrem System eingestellt haben und installieren Sie das Quandl-Paket, indem Sie Folgendes in das Terminal eingeben:

import datetime
import numpy as np
import pandas as pd
import Quandl

Die Hauptarbeit erfolgt in der Funktion Futures_rollover_weights. Sie erfordert ein Startdatum (das erste Datum des nahen Vertrages), ein Wörterbuch der Vertragsabwicklungstermine (Verfallsdatum), die Symbole der Verträge und die Anzahl der Tage, an denen der Vertrag überholt werden muss (Standard auf fünf).

def futures_rollover_weights(start_date, expiry_dates, contracts, rollover_days=5):
    """This constructs a pandas DataFrame that contains weights (between 0.0 and 1.0)
    of contract positions to hold in order to carry out a rollover of rollover_days
    prior to the expiration of the earliest contract. The matrix can then be
    'multiplied' with another DataFrame containing the settle prices of each
    contract in order to produce a continuous time series futures contract."""

    # Construct a sequence of dates beginning from the earliest contract start
    # date to the end date of the final contract
    dates = pd.date_range(start_date, expiry_dates[-1], freq='B')

    # Create the 'roll weights' DataFrame that will store the multipliers for
    # each contract (between 0.0 and 1.0)
    roll_weights = pd.DataFrame(np.zeros((len(dates), len(contracts))),
                                index=dates, columns=contracts)
    prev_date = roll_weights.index[0]

    # Loop through each contract and create the specific weightings for
    # each contract depending upon the settlement date and rollover_days
    for i, (item, ex_date) in enumerate(expiry_dates.iteritems()):
        if i < len(expiry_dates) - 1:
            roll_weights.ix[prev_date:ex_date - pd.offsets.BDay(), item] = 1
            roll_rng = pd.date_range(end=ex_date - pd.offsets.BDay(),
                                     periods=rollover_days + 1, freq='B')

            # Create a sequence of roll weights (i.e. [0.0,0.2,...,0.8,1.0]
            # and use these to adjust the weightings of each future
            decay_weights = np.linspace(0, 1, rollover_days + 1)
            roll_weights.ix[roll_rng, item] = 1 - decay_weights
            roll_weights.ix[roll_rng, expiry_dates.index[i+1]] = decay_weights
        else:
            roll_weights.ix[prev_date:, item] = 1
        prev_date = ex_date
    return roll_weights

Jetzt, da die Gewichtungsmatrix erstellt wurde, ist es möglich, dies auf die einzelnen Zeitreihen anzuwenden. Die Hauptfunktion lädt die nahen und fernen Verträge herunter, erstellt einen einzigen Datenrahmen für beide, konstruiert die Rollover-Gewichtungsmatrix und erzeugt schließlich eine kontinuierliche Reihe beider Preise, entsprechend gewichtet:

if __name__ == "__main__":
    # Download the current Front and Back (near and far) futures contracts
    # for WTI Crude, traded on NYMEX, from Quandl.com. You will need to 
    # adjust the contracts to reflect your current near/far contracts 
    # depending upon the point at which you read this!
    wti_near = Quandl.get("OFDP/FUTURE_CLF2014")
    wti_far = Quandl.get("OFDP/FUTURE_CLG2014")
    wti = pd.DataFrame({'CLF2014': wti_near['Settle'],
                        'CLG2014': wti_far['Settle']}, index=wti_far.index)

    # Create the dictionary of expiry dates for each contract
    expiry_dates = pd.Series({'CLF2014': datetime.datetime(2013, 12, 19),
                              'CLG2014': datetime.datetime(2014, 2, 21)}).order()

    # Obtain the rollover weighting matrix/DataFrame
    weights = futures_rollover_weights(wti_near.index[0], expiry_dates, wti.columns)

    # Construct the continuous future of the WTI CL contracts
    wti_cts = (wti * weights).sum(1).dropna()

    # Output the merged series of contract settle prices
    wti_cts.tail(60)

Die Ausgabe ist wie folgt:

2013-10-14 102.230 2013-10-15 101.240 2013-10-16 102.330 2013-10-17 100.620 2013-10-18 100.990 2013-10-21 99,760 2013-10-22 98.470 2013-10-23 97.000 2013-10-24 97.240 2013-10-25 97.950 Ich... Ich... 2013-12-24 99,220 2013-12-26 99,550 2013-12-27 100.320 2013-12-30 99,290 2013-12-31 98 420 2014-01-02 95.440 2014-01-03 93.960 2014-01-06 93.430 2014-01-07 93.670 2014-01-08 92.330 Länge: 60, dTyp: Schwimmer64

Es ist zu sehen, dass die Reihe nun über die beiden Verträge kontinuierlich ist. Der nächste Schritt besteht darin, dies für mehrere Lieferungen über verschiedene Jahre abhängig von Ihren Backtesting-Bedürfnissen durchzuführen.


Mehr