Statistische Arbitrage durch kointegrierte Aktien (Teil 5): Screening
Einführung
Wir begannen diese Serie mit einer Heuristik, um einige Aktien aus der Halbleiterindustrie zu finden, die – zum Zeitpunkt der Erstellung dieses Artikels – eine hohe Korrelation mit NVDA (Nvidia Corporation) aufwiesen. Dann haben wir einige kointegrierte Aktien herausgefiltert, die wir in unserem Datenbank-Setup und den entsprechenden Beispielen verwendet haben. Diese Aktien waren unser „Portfolio“, und es war gut für Demonstrationszwecke und zum besseren Verständnis des Prozesses.
Nun, da wir einen Metatrader 5 Service implementiert haben, um unsere Datenbank kontinuierlich zu aktualisieren, und unser Expert Advisor auch in der Lage ist, sich selbst in Echtzeit ohne Unterbrechungen zu aktualisieren, ist es an der Zeit, mit dem Aufbau eines echten Portfolios von kointegrierten Aktien zu beginnen. Es ist an der Zeit, mit dem Screening zu beginnen.
„Screening bezeichnet den Prozess des Filterns eines großen Universums von Aktien oder anderen Finanzinstrumenten, um diejenigen herauszufiltern, die bestimmte vom Anleger oder Händler festgelegte Kriterien oder Parameter erfüllen. Dieser Prozess ist von entscheidender Bedeutung, um die Vielzahl der verfügbaren Optionen einzugrenzen und sich auf diejenigen zu konzentrieren, die mit einer bestimmten Anlagestrategie oder einem bestimmten Handelsziel übereinstimmen.“ (Investing.com).
Bei unserer Strategie handelt es sich um eine Strategie der Rückkehr zum Mittelwert (mean-reversion), eine Art statistische Arbitrage, bei der Nasdaq-Aktien, die mit Nvidia kointegriert sind, entsprechend ihrer Portfoliogewichtung gleichzeitig gekauft und verkauft werden, um Marktneutralität zu erreichen. Unser umfangreiches Angebot an Optionen umfasst alle Nasdaq-Aktien. die spezifischen Kriterien, die erfüllt werden müssen, sind
- die Kointegrationsstärke, wie sie sich aus dem Engle-Granger- und dem Johansen-Test ergibt,
- die Stabilität der Portfoliogewichte,
- die Qualität der Stationarität der Streuung, wie sie durch den ADF- und den KPSS-Test angezeigt wird,
- die Liquidität der Vermögenswerte.
Diese vier Kriterien genügen uns, um ein Punktesystem zu erstellen. Ein Scoring-System sollte uns einen Handelsvorteil verschaffen, der sich aus der Identifizierung von Aktiengruppen ergibt, deren Kurse sich auf lange Sicht stabil und vorhersehbar gemeinsam bewegen. Wir brauchen ein Punktesystem, weil nicht jedes Paar oder jede Gruppe für unsere Zwecke geeignet ist. Wenn wir einfach jede mögliche Kombination von Aktien testen, mit Hunderten oder Tausenden von Aktien, explodiert die Zahl der möglichen Paare und Körbe. Wir dürfen nicht vergessen, dass wir diesen statistischen Arbitrage-Rahmen für den durchschnittlichen Einzelhändler entwickeln, der über ein Konsumenten-Notebook und eine normale Netzwerkbandbreite verfügt. Wenn wir anfangen, jede mögliche Kombination zu testen, wird der Prozess von Anfang an sehr rechenintensiv. Durch ein Scoring-System vermeiden wir es, unser Geld in Paaren oder Gruppen zu riskieren, die nur kurzfristig korreliert sind oder die aufgrund geringer Liquidität oder Transaktionskosten nicht handelbar sind.
Vielleicht ist die bessere Analogie für einen Screening-Prozess mit einem Scoring-System die eines Trichters: Wir fangen breit an und eliminieren allmählich ungeeignete Kandidaten, indem wir zunächst nach Sektor- und Branchenähnlichkeit ausschließen und dann nach Korrelation, Kointegration und Stationarität scoren. Schließlich eliminieren wir diejenigen, die nach unserem Risiko-/Geldmanagement nicht handelbar sind. Dieses Verfahren erhöht die Wahrscheinlichkeit, Warenkörbe zu finden, die nicht nur statistisch signifikant, sondern auch wirtschaftlich sinnvoll und handelbar sind.
Screening und Scoring verwandeln die riesige Liste aller in unserem Broker verfügbaren Aktien in eine gezielte Auswahl von Chancen. Es spart Zeit und Ressourcen für die ebenso kritischen Schritte des Backtests und des Demokonto-Handels.
Abb. 1 veranschaulicht das Flussdiagramm unseres Screening-Prozesses.

Abb. 1. Konzeptuelles Flussdiagramm des Siebvorgangs
Definition des ursprünglichen Universums
Das letzte der vier oben genannten Kriterien – die Liquidität des Vermögens – wird in der Regel als erstes herangezogen, wenn man ganz von vorne anfängt. Die Liquidität wirkt sich nicht nur auf die Transaktionskosten (z. B. über den Spread) aus, sondern je nach Strategie auch auf die Handelbarkeit selbst. Da unsere Strategie von der Verfügbarkeit der Bestände für kurzfristige Operationen abhängt, ist die Liquidität ein Ausschlusskriterium.
Wir könnten mit einem großen Index wie dem S&P 500 oder Nasdaq-100 beginnen, der bereits nach Liquidität und Marktrelevanz filtert. Oder wir können ein nutzerdefiniertes Universum nach Kriterien wie Mindestmarktkapitalisierung, durchschnittliches Tagesvolumen oder enge Geld-Brief-Spannen erstellen. Beide Möglichkeiten wären gültig, um dieses ursprüngliche Universum zu definieren. Aber mein Hauptanliegen ist es, dass Sie, der Leser, der den Prozess anhand des beigefügten Beispielcodes nachmachen möchte, die einfachste und unkomplizierteste Erfahrung machen können. Ich verwende also den MetaQuotes-Demo-Server als Datenquelle, da ich davon ausgehe, dass er für alle Nutzer des Metatrader 5 frei verfügbar ist. Soweit ich sehen kann, verfügt der MetaQuotes-Demo-Server nicht über einen separaten Pfad (siehe unten) für die im S&P 500 oder im Nasdaq-100 gelisteten Aktien. Stattdessen bietet er einen Pfad für alle Nasdaq-Aktien.
Abb. 2. Das Symbolfenster des Metatrader 5 mit hervorgehobenem Nasdaq/Stock
Wenn wir uns dafür entscheiden, nur mit den Aktien des Nasdaq-100 zu beginnen, müssten wir eine kuratierte Liste von Aktien erstellen, die gepflegt werden müsste, wenn die Zusammensetzung des Index aktualisiert und/oder seine Gewichte neu gewichtet werden. Dann wären unsere Beispiele sehr schnell veraltet. Für unsere Zwecke hier ist der Pfad von Nasdaq/Stock eine ideale Wahl als Ausgangspunkt, als unser Ausgangsuniversum.
Es handelt sich um mehr als sechstausend Symbole!
Abb. 3. Anzahl der Symbole auf dem MetaQuotes-Demo-Server nach Gruppen
Filterung nach Sektoren und Branchen
Sobald wir das anfängliche Universum definiert haben, besteht der nächste Schritt darin, unser Marktwissen, unsere Erfahrung und unseren gesunden Menschenverstand einzusetzen, um das Feld einzugrenzen. Daraus lässt sich ablesen, dass Aktien aus demselben Sektor oder derselben Branche oft gemeinsame Einflussfaktoren haben, wie etwa die Zugehörigkeit zu derselben Lieferkette oder die Abhängigkeit von den Zinssätzen der Zentralbank. Diese gemeinsamen Triebkräfte erhöhen die Wahrscheinlichkeit, dass sich ihre Preise auf stabile Weise zusammen bewegen. So können beispielsweise Banken ähnlich auf Zinsänderungen reagieren, während Halbleiterunternehmen, um die es hier geht, von der weltweiten Chipnachfrage beeinflusst werden können.
Dieses nahezu intuitive Marktwissen und der gesunde Menschenverstand waren die Grundlage unserer Heuristik bei der Auswahl des ersten Korbs mit kointegrierten Nvidia-Aktien.
Da wir die gefilterten Aktien für unsere Datenanalyse zur Hand haben wollen, speichern wir sie mit den entsprechenden Metadaten in unserer Tabelle „Symbol“. Aber zuerst nehmen wir die Spalte „Quelle“ in unsere Tabelle auf, denn sowohl der Metatrader 5 Pfad als auch die
Die Metadaten des Symbols können und werden sich beim Wechsel des Brokers/Servers wahrscheinlich ändern. Bei der Analyse der Daten von verschiedenen Brokern müssen wir die Marktdaten nach Quelle filtern.
ALTER TABLE symbol ADD source TEXT CHECK(LENGTH(source) <= 50) DEFAULT ('MetaQuotes') NOT NULL; Und ein MQL5-Skript (SymbolImporter.mql5) zum Importieren der Symbole aus dem spezifischen Pfad in der Datenbank.
Abb. 4. Metatrader 5 Dialog für den Symbolimport mit Parametern
Das wird die Lücken füllen, die wir zu Beginn in der Datenbank hinterlassen haben, nämlich Vermögenswerttyp, Börse, Branche und Sektor. Außerdem wird die Quelle der Daten in das neu erstellte Feld oben eingefügt.
//+------------------------------------------------------------------+ //| Insert a symbol into the database | //+------------------------------------------------------------------+ bool InsertSymbol(int db_handle, string ticker, string source) { ResetLastError(); // Get symbol information string exchange = SymbolInfoString(ticker, SYMBOL_EXCHANGE); string asset_type = GetAssetType(ticker); string sector = SymbolInfoString(ticker, SYMBOL_SECTOR_NAME); string industry = SymbolInfoString(ticker, SYMBOL_INDUSTRY_NAME); string currency = SymbolInfoString(ticker, SYMBOL_CURRENCY_BASE); if(currency == "") currency = SymbolInfoString(ticker, SYMBOL_CURRENCY_PROFIT); // Prepare SQL insert statement (symbol_id is auto-generated by SQLite) string req = StringFormat( "INSERT INTO symbol(ticker, exchange, asset_type, sector, industry, currency, source)" " VALUES( '%s', '%s', '%s', '%s', '%s', '%s', '%s')", ticker, exchange, asset_type, sector, industry, currency, source); if(!DatabaseExecute(db_handle, req)) { printf("Failed to insert symbol: %d", GetLastError()); return false; } return true; }
Es wird versucht, den Asset-Typ aus dem Pfad zu ermitteln.
//+------------------------------------------------------------------+ //| Determine asset type based on symbol characteristics | //+------------------------------------------------------------------+ string GetAssetType(string symbol_name) { ResetLastError(); // Simple asset type detection - you may want to enhance this string description = SymbolInfoString(symbol_name, SYMBOL_DESCRIPTION); string path = SymbolInfoString(symbol_name, SYMBOL_PATH); if(StringFind(path, "Forex") != -1) return "Forex"; if(StringFind(path, "Stock") != -1) return "Stock"; if(StringFind(path, "Index") != -1) return "Index"; if(StringFind(path, "Future") != -1) return "Future"; if(StringFind(path, "CFD") != -1) return "CFD"; if(StringFind(path, "Crypto") != -1) return "Cryptocurrency"; // Fallback based on symbol name patterns if(StringLen(symbol_name) == 6 && StringFind(symbol_name, "USD") != -1) return "Forex"; if(StringFind(symbol_name, ".", 0) != -1) return "Stock"; return "Other"; }
Wenn alles gut geht, sollten Sie im Protokoll der Registerkarte Experten etwa Folgendes sehen.
Abb. 5. Metatrader 5 Experten-Registerkarte zeigt Symbolimport-Protokoll nach erfolgreichen Importen
Und wenn Sie Ihre Datenbank überprüfen, sollte sie alle an der Nasdaq notierten und auf diesem Server (in diesem Fall MetaQuotes-Demo) verfügbaren Aktien enthalten.
Abb. 6. Metaeditor-Datenbankschnittstelle mit einem Beispiel für die Metadaten von Nasdaq-Aktien
Wir können die Gesamtzahl der importierten Aktiensymbole mit der Anweisung SELECT count() überprüfen.
Abb. 7. Metaeditor-Datenbankschnittstelle mit Anzeige der Gesamtzahl der in die SQLite-Datenbank importierten Nasdaq-Aktien
Fast siebenhundert von ihnen kommen aus dem Technologiesektor.
Abb. 8. Metaeditor-Datenbankschnittstelle, die die Gesamtheit der Nasdaq-Aktien aus dem Technologiesektor anzeigt
Aber nur wenig mehr als sechzig sind aus der Halbleiterindustrie.
Abb. 9. Metaeditor-Datenbankschnittstelle, die die Gesamtheit der Nasdaq-Aktien aus der Halbleiterindustrie anzeigt
Diese dreiundsechzig Nasdaq-Aktien aus der Halbleiterindustrie sind diejenigen, die unsere Aufmerksamkeit verdienen. Später können wir neue Möglichkeiten erschließen, indem wir die Überschneidungen zwischen Sektoren und Branchen erforschen, aber jetzt müssen wir uns auf diejenigen konzentrieren, die eher dazu neigen, gemeinsam zu schwanken. Sie sind es, die es verdienen, dass wir uns um die Durchführung kontinuierlicher statistischer Tests bemühen.
Korrelationsanalyse
Nachdem wir unser anfängliches Universum nach Sektoren und Branchen eingegrenzt haben, müssen wir nun prüfen, ob sich die Aktien in der Praxis tatsächlich gemeinsam bewegen. Der einfachste Weg ist die Berechnung von Korrelationskoeffizienten. Seit Beginn dieser Reihe verwenden wir die Pearson-Korrelation, und wir werden sie auch weiterhin verwenden. Die Pearson-Korrelation ist schnell zu berechnen und einfach zu interpretieren, was sie zu einem praktischen Instrument für das Screening macht.
Wir haben im zweiten und dritten Artikel dieser Reihe viel über den Pearson-Korrelationstest gesprochen. Es hat keinen Sinn, diese Informationen hier zu wiederholen. Sie sind eingeladen, diese Artikel zu lesen, wenn Sie mit diesem Thema nicht vertraut sind. Nur eine Bemerkung sollte man sich merken:
Korrelation ist nicht dasselbe wie Kointegration. Bei Aktienkursen handelt es sich in der Regel um nicht-stationäre Zeitreihen, und nicht-stationäre Zeitreihen können kurzfristig stark korreliert sein, langfristig aber nicht kointegriert sein.
Der Spearman-Korrelationstest ist ebenfalls sehr gebräuchlich und hat einen klaren und spezifischen Verwendungszweck als ergänzende Prüfung, aber wir werden ihn im Moment nicht behandeln. Stattdessen werden wir später die Spearman-Korrelation als eine Verbesserung für diese speziellen Anwendungsfälle sehen.
Wir werden die Ergebnisse der Korrelationstests in einer speziellen Tabelle in unserer Datenbank speichern, einer Tabelle, die wenig überraschend „corr_pearson“ heißt.
-- corr_pearson definition CREATE TABLE corr_pearson ( tstamp INTEGER NOT NULL, ref_ticker TEXT CHECK(LENGTH(ref_ticker) <= 10) NOT NULL, corr_ticker TEXT CHECK(LENGTH(corr_ticker) <= 10) NOT NULL, timeframe TEXT CHECK(LENGTH(timeframe) <= 10) NOT NULL, lookback INTEGER NOT NULL, coefficient REAL NOT NULL, CONSTRAINT corr_pearson_pk PRIMARY KEY(tstamp, ref_ticker, corr_ticker) ) STRICT;
Technisch gesehen wäre es nicht notwendig, die Ergebnisse dieser vorläufigen Berechnungen zu speichern. Aber bei der statistischen Arbitrage ist DATA das A und O. Wir berechnen Korrelationskoeffizienten zwischen Halbleiteraktien und Nvidia Corp. auf dem H4-Zeitrahmen mit einer 180-Tage-Rückblickperiode. In Kürze werden wir sie aber auch für andere Zeitrahmen und Rückblickperioden berechnen. Wahrscheinlich werden wir diesen Prozess für andere Basissymbole als NVDA wiederholen. Im weiteren Verlauf unserer Datenanalyse werden wir über eine Menge verarbeiteter Daten für die Pearson-Korrelation, für die Engle-Granger- und Johansen-Kointegration und vielleicht für andere Zwischenberechnungen verfügen.
Sie ahnen es schon: All diese Berechnungen liefern wertvolle Informationen, die aufbewahrt, abgeglichen und später wiederverwendet werden können. Wenn wir es also ernst meinen mit der statistischen Arbitrage, sollten wir es uns zur Gewohnheit machen, keine flüchtigen Daten zu akzeptieren und nicht jedes Ergebnis einer Zwischenberechnung zu verwerfen. Lassen Sie uns alles speichern, was in Zukunft nützlich sein könnte. Und wenn Sie noch nicht überzeugt sind, denken Sie einfach an diese beiden Worte: MASCHINELLES LERNEN. Irgendwann werden wir sicher dort ankommen 😀 .
Abb. 10. Metaeditor-Datenbankschnittstelle mit Anzeige der Felder der Tabelle „corr_pearson“.
Sie werden feststellen, dass wir wieder einen zusammengesetzten Primärschlüssel haben, der jetzt den Einfügezeitstempel, den Referenzticker und den korrelierten Ticker verwendet. Dies ermöglicht es uns, den genauen Zeitpunkt zu ermitteln, zu dem der Korrelationskoeffizient für dieses spezifische Symbolpaar berechnet wurde. Auf diese Weise können wir die Korrelation für alle Symbole erneut berechnen, jetzt aber mit einem anderen Zeitrahmen.
Fig. 11. Metaeditor-Datenbankschnittstelle, die den „corr_pearson“ mit zwei verschiedenen Zeitrahmen sortiert zeigt
In Abb. 11 ist leicht zu erkennen, dass im gleichen Rückblickzeitraum die Korrelation für einige Symbole vom H4- zum D1-Zeitrahmen zunimmt, während sie für andere abnimmt. Erweitern Sie dies auf mehrere Zeitrahmen und Rückblickperioden, und schon haben wir ein leistungsstarkes Analyseinstrument. Außerdem sind diese Daten in gewissem Sinne einzigartig für Sie, denn Sie wählen aus, welche Symbole mit welchen Parametern analysiert werden sollen. Die Schlussfolgerungen, die Sie aus dieser Datenanalyse ziehen können, können Ihnen beim Handel einen Vorteil verschaffen oder auch nicht, aber darum geht es hier.
Später können wir die Entwicklung der Korrelation für jedes Symbol mit NVDA im Laufe der Zeit betrachten. Hier haben wir die Entwicklung der Korrelation zwischen Broadcom Inc. (AVGO) mit NVDA, von einem Jahr (252 Rückblickperioden) bis zu einem Monat (30 Rückblickperioden), über 180, 120, 90 und 60 Rückblickperioden. Da wir nach Koeffizienten ordnen, zeigen die Ergebnisse deutlich, dass D1 der bevorzugte Zeitrahmen für dieses Paar ist, dass die Korrelation abnimmt, wenn der Zeitrahmen kürzer wird, und dass die Korrelation unterhalb von 90 Rückblickperioden drastisch abnimmt. Das ist eine Menge an Informationen, und wir sind erst an der Oberfläche.
Anmerkung: Mit Ausnahme des Jahresrückblicks (252) verwende ich für die monatlichen Rückblickszeiträume gerundete Zahlen, um die Darstellung zu vereinfachen.
Abb. 12. Metaeditor-Datenbankschnittstelle, die die Entwicklung von „corr_pearson“ zwischen Broadcom Inc. (AVGO) und Nvidia Corp. (NVDA) von einem Jahr bis zu einem Monat Rückblickzeiträume in einem täglichen Zeitrahmen
Können Sie erkennen, wie wertvoll diese einfache Korrelationstabelle sein kann? Als einfaches Beispiel habe ich den H4-Zeitrahmen ausgeschlossen und nur die täglichen Korrelationen dargestellt. 
Abb. 13. Darstellung der Entwicklung der Pearson-Korrelation zwischen Broadcom Inc. (AVGO) und Nvidia Corp. (NVDA) von einem Jahr bis zu einem Monat Rückblickzeiträume in einem täglichen Zeitrahmen
Obwohl es gängige Praxis ist, die Korrelation als vorläufigen Filter zu verwenden, sagt sie nichts über die Kointegration aus. Wir können also nicht davon ausgehen, dass die Symbole mit geringer Korrelation zu Nvidia nicht kointegriert sind. Welchen Zweck hat also die Prüfung auf Korrelation? Sie hilft, Schwankungsmuster im Zeitverlauf zu verstehen. Wenn aber die Korrelation keine Garantie für Kointegration ist, wie können wir sie dann in der Praxis nutzen? Durch die Berechnung der Korrelation in kurzen Zeitrahmen und kurzen Rückblickszeiträumen bei gleichzeitiger Prüfung auf Kointegration in langen Zeitrahmen und Rückblickszeiträumen. Beachten Sie, dass kaufen und verkaufen hier relativ zueinander sind. Wie immer im Handel, auch im statistisch basierten Handel, gibt es kein Rezept. Sie sollten testen und experimentieren, backtesten und auswerten, um die beste Kombination zwischen den Parametern des Korrelationstests und des Kointegrationstests für jedes spezifische Paar oder jede Gruppe von Vermögenswerten zu finden. Setzen Sie Ihre Marktkenntnis, Ihren gesunden Menschenverstand und Ihre Rechenleistung klug ein. Verbessern und wiederholen.
Das Skript selbst ist nun als spezialisierte Python-Klasse strukturiert.
Abb. 14. Screenshot aus einem Editor für Python-Skripte, der die Methoden der Klasse zeigt
Lassen Sie uns nun sehen, wie wir die Kointegrationstests in unserem Screening-Prozess kombinieren können.
Kointegrationstests
Engle-Granger
Der Engle-Granger-Test ist einfach und leicht. Er war der erste Kointegrationstest, der in den 1980er Jahren unter Quant-Tradern populär wurde, und ist es immer noch, selbst nach dem Aufkommen des Johansen-Tests im nächsten Jahrzehnt (siehe unten). Wie bereits erwähnt, haben wir im zweiten und dritten Teil dieser Serie ausführlich über die Kointegrationstests gesprochen, sodass wir uns hier nicht wiederholen wollen, um Ihre Zeit zu sparen. Jetzt werden wir uns auf ihre Umsetzung und Verwendung im Screening-Prozess konzentrieren. Wenn Sie mit diesem Thema noch nicht vertraut sind, lesen Sie bitte diese beiden Artikel.
Denken Sie daran, dass bei zwei Vermögenswerten (Symbolen) in der Regel der Engle-Granger-Test angewendet wird. Sie prüft, ob die Residuen einer linearen Regression zwischen zwei Preisreihen stationär sind. Es ist jedoch auf eine einzige Kointegrationsbeziehung beschränkt, funktioniert also nur paarweise.
Wie bei der Pearson-Korrelation speichern wir die Ergebnisse des Engle-Granger-Kointegrationstests in einer eigenen Tabelle in unserer Datenbank, „coint_eg“.
-- coint_eg definition CREATE TABLE coint_eg ( tstamp INTEGER NOT NULL, ref_ticker TEXT CHECK(LENGTH(ref_ticker) <= 10) NOT NULL, coint_ticker TEXT CHECK(LENGTH(coint_ticker) <= 10) NOT NULL, timeframe TEXT CHECK(LENGTH(timeframe) <= 10) NOT NULL, lookback INTEGER NOT NULL, pvalue REAL NOT NULL, test_stat REAL NOT NULL, crit_val_1 REAL NOT NULL, crit_val_5 REAL NOT NULL, crit_val_10 REAL NOT NULL, hedge_ratio REAL, is_coint INTEGER NOT NULL, CONSTRAINT coint_eg_pk PRIMARY KEY(tstamp, ref_ticker, coint_ticker) ) STRICT;
Das Feld „is_coint“ ist ein BOOLEAN, aber SQLite hat keinen eigenen booleschen Datentyp. Stattdessen verwendet es INTEGER (oder INT), um boolesche Werte als 1 oder 0 zu speichern und akzeptiert TRUE oder FALSE als Eingabe.
„Im Gegensatz zu den meisten anderen SQL-Implementierungen gibt es in SQLite keinen eigenen BOOLEAN-Datentyp. Stattdessen werden TRUE und FALSE (normalerweise) als ganze Zahlen 1 bzw. 0 dargestellt.“ (SQLite docs)
Abb. 15. Die Metaeditor-Datenbankschnittstelle zeigt die Felder der Tabelle „coint_eg“.
Zum Zeitpunkt der Erstellung dieses Berichts ist unter allen zweiundsechzig Symbolen nur Aeluma Inc. (ALMU) ist kointegriert mit Nvidia Corp. (NVDA) auf dem täglichen Zeitrahmen für den Rückblickzeitraum von 365.
Abb. 16. Die Metaeditor-Datenbankschnittstelle zeigt die Felder der Tabelle „coint_eg“ mit einer kointegrierten NVDA-Aktie (ALMU)
Wie im obigen Beispiel „corr_pearson“ werden Sie feststellen, dass wir einen zusammengesetzten Primärschlüssel haben, der den Einfügezeitstempel, den Referenzticker und den korrelierten Ticker verwendet. Das hat den gleichen Grund. Indem wir den Zeitstempel des Kointegrationstests mit dem Referenzticker und dem eventuell kointegrierten Ticker verknüpfen, können wir die Kointegration für alle Symbole erneut testen, jetzt aber mit einem anderen Zeitrahmen und/oder Rückblickzeitraum.
Diese Tabelle bildet zusammen mit der nachfolgenden Tabelle „coint_joh“ den Kern unseres Screening-Prozesses. Lassen Sie uns zum Beispiel nach Gelegenheiten im H4-Zeitrahmen suchen.
Abb. 17. Die Metaeditor-Datenbankschnittstelle zeigt die Tabelle „coint_eg“ mit siebzehn Aktien, die mit Nvidia Corp. kointegriert sind. (NVDA) im H4-Zeitrahmen und unterschiedlichen Rückblickzeiträumen
Die Tabelle in Abb. 17 ist nach dem p-Wert sortiert. Zum Zeitpunkt der Erstellung dieses Berichts war das erste, Silicon Laboratories Inc. (SLAB), ist am stärksten mit NVDA kointegriert, wenn wir den 30-jährigen Rückblickzeitraum betrachten. Aber jede dieser Aktien ist ein guter Kandidat für den Paarhandel mit NVDA im H4-Zeitrahmen in ihren jeweiligen Rückblickperioden. Das heißt, zu diesem Zeitpunkt verfügen wir bereits über ein solides Portfolio von NVDA-Aktien für den Paarhandel mit ihren jeweiligen Absicherungsquoten. Wenn wir hier aufhören, haben wir ein nach Kointegrationsstärke geordnetes Portfolio, das nur noch auf Spread-Stationarität getestet und in Backtests validiert werden muss.
Johansen
Die Johansen-Methode wurde unmittelbar nach dem Engle-Granger-Test Ende der 1980er Jahre entwickelt. Im Jahrzehnt der 1990er Jahre wurde es zu einem Standardinstrument der Akademie und zu Beginn dieses Jahrhunderts schrittweise von den Quant-Teams der Hedge-Fonds in aller Welt übernommen.
Während der Engle-Granger-Test für zwei, und zwar nur für zwei Zeitreihen oder zwei Aktiva ausgelegt ist, ist der Johansen-Test für mehrere Zeitreihen ausgelegt, darunter auch nur zwei Zeitreihen. Dies macht es besonders leistungsfähig beim Screening von Körben mit zwei, drei, vier oder mehr Aktien, in denen mehrere verschiedene langfristige Beziehungen nebeneinander bestehen können.
Johansen erstellt zwei Hauptstatistiken: Spur und maximaler Eigenwert. Diese Statistiken bestimmen den Kointegrationsrang, d. h. die Anzahl der unabhängigen stationären Beziehungen zwischen den Vermögenswerten.
- Rang = 0: keine Kointegration.
- Rang = 1: eine stabile Streuung. Mit diesem Fall haben wir uns in allen Artikeln dieser Reihe beschäftigt.
- Rang > 1: mehrere unabhängige Streuungen, was uns mehr Flexibilität bei der Portfoliogestaltung bietet. Wir werden diesen Fall im Detail betrachten, wenn wir uns mit Saisonalität und Anomalien befassen.
Der Test liefert uns eine Reihe von Eigenvektoren, die mit diesen stationären Beziehungen verbunden sind. Jeder dieser Eigenvektoren gibt die Gewichte einer linearen Kombination der Bestände an, die im Zeitverlauf stationär ist. Diese Gewichte verwenden wir als Absicherungsquoten, d. h. als das Verhältnis, in dem wir die Vermögenswerte kombinieren, um einen synthetischen, mittelfristig umkehrenden Spread zu bilden. Indem er uns diese Hedge-Ratios zur Verfügung stellt, zeigt uns der Test, wie wir den Spread zwischen den kointegrierten Aktien aufbauen können. Wir haben diese Funktion im zweiten Artikel dieser Serie verwendet, als wir eine Gruppe von vier Aktien aus der Halbleiterindustrie einem Backtest unterzogen haben.
Wie bei den beiden vorangegangenen Tests werden wir eine eigene Tabelle verwenden, um sowohl die Parameter als auch die Ergebnisse des Johansen-Tests für die spätere Analyse zu speichern. Aber jetzt brauchen wir zwei Tabellen:
Erste Tabelle: eine Haupttabelle „coint_johansen_test“, in der die Metadaten der einzelnen Testläufe gespeichert werden.
-- coint_johansen_test definition CREATE TABLE coint_johansen_test ( test_id INTEGER PRIMARY KEY AUTOINCREMENT, tstamp INTEGER NOT NULL, timeframe TEXT CHECK(LENGTH(timeframe) <= 10) NOT NULL, lookback INTEGER NOT NULL, num_assets INTEGER NOT NULL, trace_stats_json TEXT NOT NULL, trace_crit_vals_json TEXT NOT NULL, eigen_stats_json TEXT NOT NULL, eigen_crit_vals_json TEXT NOT NULL, coint_rank INTEGER NOT NULL, CONSTRAINT coint_johansen_test_unique UNIQUE (tstamp, timeframe, lookback) ) STRICT;
Anstelle eines zusammengesetzten Primärschlüssels mit den Tickern der Handelsinstrumente, wie wir ihn für die Tabellen des Korrelationstests und des Engle-Granger-Kointegrationstests verwendet haben, wird jetzt eine einzige, automatisch inkrementierende test_id als Primärschlüssel in der Haupttabelle verwendet. Die Tabelle coint_johansen_test_assets (siehe unten) speichert dann eine Zeile für jede Anlage, die in einem bestimmten Testlauf enthalten ist. Auf diese Weise können wir eine beliebige Anzahl von Anlagen testen, ohne die Tabellenstruktur zu ändern. Wenn Sie daran interessiert sind, dieses Verfahren besser zu verstehen, schauen Sie sich bitte diesen Wikipedia Artikel über Datenbanknormalisierung an.
Die Einschränkung, dass der Testzeitstempel, der Zeitrahmen und der Rückblickzeitraum insgesamt eindeutig sein müssen, ermöglicht es uns, den Test für dieselben Symbole jederzeit mit unterschiedlichen Zeitrahmen und Rückblickzeiträumen zu wiederholen, und jede Testausgabe wird eindeutig sein.
Der Johansen-Test gibt mehrere Werte für die Trace- und Max-Eigenwert-Statistiken sowie deren kritische Werte aus. Die Speicherung in einzelnen Feldern wie trace_stat ist keine Option mehr. Stattdessen werden wir JSON-Spalten (trace_stats_json, trace_crit_vals_json usw.) verwenden, um das gesamte Array der Ergebnisse als Zeichenkette zu speichern. Wir verwenden JSON-formatierte Zeichenketten und ein TEXT-Feld, um die kritischen Werte und die Arrays der Ablaufverfolgungsstatistiken zu speichern, da SQLite selbst den Datentyp ARRAY nicht kennt. Wie wir mit dieser SQLite-Beschränkung umgehen und wie wir diese JSON-Strings in MQL5 lesen und parsen, lesen Sie bitte im vorherigen Artikel.
Im nächsten Schritt werden wir sehen, wie wir die kritischen Werte (trace_crit_vals_json) zu unserem Vorteil nutzen können, wenn wir Backtests mit einer Gruppe von Aktien mit diesem automatischen Screening durchführen. Denken Sie daran, dass dies die Werte sind, die wir mit der Trace-Statistik (trace_stats_json) vergleichen, um die Anzahl der kointegrierenden Beziehungen auf jedem Signifikanzniveau (1 %, 5 % bzw. 10 %) zu ermitteln.
Das boolesche Feld is_coint ist nicht mehr ausreichend. Das wichtigste Ergebnis eines Johansen-Tests für mehrere Vermögenswerte ist die Anzahl der kointegrierenden Beziehungen oder der Rang (r). Im neuen Feld coint_rank wird der ganzzahlige Wert des Ranges gespeichert.
Zweite Tabelle: „coint_johansen_test_assets“, um jeden Test mit den betreffenden Vermögenswerten zu verknüpfen.
-- coint_johansen_test_assets definition CREATE TABLE coint_johansen_test_assets ( test_id INTEGER NOT NULL, symbol_id INTEGER NOT NULL, CONSTRAINT coint_johansen_test_assets_pk PRIMARY KEY(test_id, symbol_id), CONSTRAINT coint_johansen_test_assets_test_fk FOREIGN KEY(test_id) REFERENCES coint_johansen_test(test_id) ON DELETE CASCADE, CONSTRAINT coint_johansen_test_assets_symbol_fk FOREIGN KEY(symbol_id) REFERENCES symbol(symbol_id) ON DELETE CASCADE ) STRICT;
Die Tabelle coint_johansen_test_assets verwendet symbol_id anstelle von ticker, um eine Fremdschlüsselbeziehung mit der Tabelle „symbol“ herzustellen. Auf diese Weise wird sichergestellt, dass die zu prüfenden Assets immer in unserem System vorhanden sind. Außerdem erhalten wir hier einige kostenlose Leistungssteigerungen, da es für Datenbanken im Allgemeinen effizienter ist, Joins auf Ganzzahlschlüsseln (symbol_id) als auf Textfeldern (ticker) durchzuführen. Zum jetzigen Zeitpunkt ist dies weder relevant noch steht es in unserem Fokus, bevor wir ein funktionierendes System haben. Aber es ist erwähnenswert, und wir zahlen nicht dafür. 🙂
Denken Sie schließlich daran, dass unsere Tabelle „market_data“ bereits mit der Tabelle „symbol“ verknüpft ist. Indem wir unsere Johansen-Tests mit der „Symbol“-Tabelle verbinden, stellen wir indirekt eine Verbindung zu unseren (irgendwann in der Zukunft) „kuratierten“ Marktdaten her, was die Konsistenz unserer Datenbank verbessert.
Aber wenn Sie der Argumentation folgen, werden Sie sich vielleicht fragen: Warum haben wir dann nicht dasselbe für die Ergebnisse der Pearson-Korrelation und des Engle-Granger-Kointegrationstests getan? Warum haben wir „ticker“ und nicht „symbol_id“ verwendet, um sie mit dem Rest unseres Systems zu verbinden?
Für diese Wahl gibt es zwei Gründe, von denen einer etwas eigenwillig ist. Das heißt, dass ich es vorziehe, dass Sie die Pearson-Korrelation und die Engle-Granger-Kointegrationstests für den Paarhandel so einfach wie möglich durchführen können, ohne sich um die Aufgabe kümmern zu müssen, vorher die Symbole aus Metatrader in die Datenbank zu importieren.
Der zweite Grund ist, dass der Johansen-Test unser Hauptinstrument im automatisierten System sein wird, während der Korrelations- und der Engle-Granger-Test auf ein manuelles Screening beschränkt sind, da wir mit Aktienkörben in unserem Portfolio arbeiten werden.
Abb. 18. Die Metaeditor-Datenbankschnittstelle zeigt die Felder der Tabelle „coint_johansen_test“.
Abb. 18 oben zeigt die Johansen-Kointegrationstesttabelle mit allen Feldern und einem Test mit den Kointegrationsvektoren, die wir als Absicherungsquoten oder Portfoliogewichte verwenden würden. In der nachstehenden Abbildung 19 ist dies besser zu erkennen.
Abb. 19. Metaeditor-Datenbankschnittstelle, die die Felder der Tabelle „coint_johansen_test“ mit einem positiven Test auf Kointegration zusammen mit den empfohlenen Absicherungsquoten (Portfoliogewichten) anzeigt
Abb. 20. Die Metaeditor-Datenbankschnittstelle zeigt die Tabelle „coint_johansen_test“ mit sieben positiven Kointegrationstests mit unterschiedlichen Kointegrationsrängen im Zeitrahmen D1 und verschiedenen Rückblickszeiträumen
Hier haben wir bereits ein solides Portfolio von kointegrierten Aktien aus der Halbleiterindustrie für alle gängigen Rückblickszeiträume, von einem Monat bis zu einem Jahr, einem halben Jahr, einem Quartal usw. Jede Gruppe von Aktien aus demselben Rückblickzeitraum kann als Teil eines Aktienkorbs getestet werden.
Dies sind die Daten, die in unserer „Strategie“-Tabelle verwendet werden, um unser Modell in Echtzeit zu aktualisieren, wie im vorherigen Artikel beschrieben. Hier liegt die Grundlage für die Backtests, den wir im nächsten Artikel durchführen werden.
Es ist wichtig zu verstehen, dass der Engle-Granger-Test durch den Johansen-Test nicht obsolet geworden ist. Beide suchen nach dem Gleichen – ob sich zwei oder mehr Preise langfristig gemeinsam bewegen – aber sie gehen auf unterschiedliche Weise vor. Engle-Granger ist einfacher und eignet sich für den Test von zwei Vermögenswerten gleichzeitig, während Johansen leistungsfähiger ist, wenn Sie mehrere Vermögenswerte zusammen testen wollen. In der Praxis sollten wir oft das verwenden, was der Situation am besten entspricht, und manchmal beide prüfen, um mehr Vertrauen in das Ergebnis zu haben.
Engle-Granger-Test
| ✔️Pros | ❌Cons |
|---|---|
|
|
Tabelle 1 – Liste der Vor- und Nachteile des Engle-Granger-Kointegrationstests
Johansen-Test
| ✔️Pros | ❌Cons |
|---|---|
|
|
Tabelle 2 – Liste der Vor- und Nachteile des Johansen-Kointegrationstests
Als Faustregel gilt: Für eine schnelle Prüfung von zwei Aktien verwenden Sie Engle-Granger; für tiefergehende Tests für Portfolios oder mehr als zwei Vermögenswerte verwenden Sie Johansen.
Der letzte Schritt vor der Erstellung eines Rankingsystems ist die Validierung der Stationarität der Streuung.
Validierung der Stationarität
Sobald wir eine kointegrierende Beziehung in einer Gruppe von Aktien für einen bestimmten Zeitrahmen und eine bestimmte Rückblickperiode festgestellt haben, besteht der letzte Schritt darin, zu überprüfen, ob der Spread wirklich stationär ist. Es ist die stationäre Eigenschaft, die garantiert, dass die Spanne um einen stabilen Mittelwert schwankt und nicht im Laufe der Zeit driftet. Dieser Schritt ist erforderlich, weil wir ohne Stationarität nicht sicher sein können, dass die Rückkehr zum Mittelwert eintritt, und diese Rückkehr zum Mittelwert ist der Kern unserer Strategie; hier liegen die Arbitragemöglichkeiten.
Die beiden Tests, die wir zur Überprüfung der Stationarität der Streuung verwenden, sind der ADF-Test (Augmented Dickey-Fuller) und der KPSS-Test (Kwiatkowski-Phillips-Schmidt-Shin). Die gemeinsame Interpretation der beiden Daten bietet eine solide Grundlage: Wenn sie übereinstimmen, ist dies ein starker Beweis dafür, dass die Spanne tatsächlich eine Rückkehr zum Mittelwert darstellt. Wenn die beiden nicht übereinstimmen, deutet dies oft auf ein instabiles Verhalten hin, und wir sollten vorsichtig sein: Es ist ein Warnsignal.
Wie bei allen vorangegangenen Tests gibt es auch hier eine eigene Tabelle, „coint_adf_kpss“, in der die Ergebnisse der Stationaritätstests gespeichert werden.
-- coint_adf_kpss definition CREATE TABLE "coint_adf_kpss" ( test_id INTEGER NOT NULL, symbol_id INTEGER NOT NULL, adf_stat REAL NOT NULL, adf_pvalue REAL NOT NULL, is_adf_stationary INTEGER NOT NULL, kpss_stat REAL NOT NULL, kpss_pvalue REAL NOT NULL, is_kpss_stationary INTEGER NOT NULL, CONSTRAINT coint_adf_kpss_pk PRIMARY KEY (test_id, symbol_id), CONSTRAINT coint_adf_kpss_test_fk FOREIGN KEY (test_id) REFERENCES coint_johansen_test(test_id) ON DELETE CASCADE, CONSTRAINT coint_adf_kpss_symbol_fk FOREIGN KEY (symbol_id) REFERENCES symbol(symbol_id) ON DELETE CASCADE ) STRICT;
Auch hier wird ein zusammengesetzter Primärschlüssel verwendet, aber jetzt ist es nicht mehr das Triplett Testlauf-Zeitstempel/Zeitrahmen/Lookback, das jeden Test eindeutig macht, sondern die Verbindung mit der Johansen-Test-ID und dem Symbol (die durch dieses Triplett eindeutig gemacht wird). Auf diese Weise verknüpfen wir die Stationaritätstests mit dem Johansen-Test, machen aber auch den ADF/KPSS-Test davon abhängig, dass der vorherige Kointegrationstest mindestens einen kointegrierten Vektor aufweist.
Diese Abhängigkeit von einem früheren Kointegrationstest mit mindestens einem kointegrierten Vektor ist im Python-Code explizit angegeben:
def get_coint_groups(self): """ Retrieves information for all Johansen tests with a cointegrating rank > 0. Returns a list of dictionaries, each containing test_id, timeframe, lookback, and a list of symbol_ids. """ if not self.conn: print("Database connection not established.") return [] try: query = """ SELECT test_id, timeframe, lookback FROM coint_johansen_test WHERE coint_rank > 0 """ df_tests = pd.read_sql_query(query, self.conn) if df_tests.empty: print("No cointegrated groups found in the database.") return []
Dies ist eine Designentscheidung. Theoretisch hindert uns nichts daran, ADF-Tests als eigenständiges Werkzeug auszuführen. Es ist nur so, dass es in unserer Pipeline keinen Sinn macht. In unserem Fall ist es ressourcenschonender, sie nur auf einer kointegrierten Gruppe laufen zu lassen, da wir sie sehr bald rund um die Uhr auf Tausenden von Aktien und verschiedenen Zeitrahmen/Lookback-Kombinationen laufen lassen werden.
Abb. 21. Die Metaeditor-Datenbankschnittstelle zeigt die Tabelle „coint_adf_kpss“ mit einem positiven Ergebnis sowohl für den ADF- als auch für den KPSS-Spread-Stationaritätstest
Aus der Test-ID (20) ergeben sich die Symbole, der Zeitrahmen und der Rückblickzeitraum, die beim Johansen-Kointegrationstest verwendet werden, sowie die Kointegrationsvektoren (Portfoliogewichte), die dieser Test liefert.
SELECT
t1.test_id,
t3.ticker,
t2.timeframe,
t2.lookback,
t2.coint_vectors_json
FROM coint_johansen_test_assets AS t1
JOIN coint_johansen_test AS t2
ON t1.test_id = t2.test_id
JOIN symbol AS t3
ON t1.symbol_id = t3.symbol_id
WHERE t1.test_id = 123;
Dies ist eine relativ teure Abfrage mit zwei JOIN-Operationen. Wir werden jedoch nur eine kleine Anzahl dieser Abfragen durchführen, und zwar nur dann, wenn wir eine Gruppe von Vermögenswerten finden, die in allen vorhergehenden Filtern qualifiziert wurde. Das heißt, diese Abfrage steht am Ende unserer Pipeline. Damit haben wir bereits unseren kointegrierten Aktienkorb mit einem stabilen Spread, den wir in unsere „Strategie“-Tabelle kopieren können. Der EA liest die „Strategie“-Tabelle, um seine eigenen Parameter in Echtzeit zu aktualisieren (siehe unseren vorherigen Artikel).
Abb. 22. Metaeditor-Datenbankschnittstelle, die die Tabelle „coint_johansen_test“ mit Details für eine bestimmte Test-ID mit positiven Ergebnissen sowohl für den ADF- als auch für den KPSS-Test zeigt
Da in diesem Beispiel sowohl der ADF- als auch der KPSS-Stationaritätstest für die Test-ID 20 positiv ausfallen, wissen wir, dass AMD, INTC, LAES, RMBS, TSM und WOLF im täglichen (D1) Zeitrahmen gehandelt werden können, wobei die jeweiligen Portfoliogewichte als „coint_vectors_json“ gespeichert sind.
Zu diesem Zeitpunkt hat sich unser Datenbankschema stark verändert.

Abb. 23. Entity-Relationship-Diagramm (ERD), das die Schema-Version statarb-0.3 darstellt.
Sie haben vielleicht bemerkt, dass wir noch keine Datenbankindizes haben. Dies ist beabsichtigt. Da wir uns für einen Bottom-up-Stil entschieden haben, können wir vorerst nur vermuten (und das mit ziemlicher Sicherheit), wo wir Indizes benötigen, um unsere meistgenutzten und/oder anspruchsvolleren Abfragen zu beschleunigen (wie die auf zusammengesetzte Primärschlüssel, bei denen ein Paar ein TEXT-Feld ist). Um jedoch ein Überdenken und Overengineering zu vermeiden, werden wir sie erst dann hinzufügen, wenn wir sicher wissen, welche Abfragen besonders anspruchsvoll und/oder am häufigsten verwendet werden.
Korbauswahl – Aufbau eines Punktesystems
Die in Abbildung 22 dargestellte Gruppe von Aktien stellt einen einzigen Aktienkorb dar, der Teil unseres Portfolios sein soll. Und unser Portfolio wird voraussichtlich mindestens ein Dutzend dieser Körbe enthalten. Das liegt daran, dass wir ihn rotieren müssen, d. h. wir müssen Korb Nr. 1 immer dann durch Korb Nr. 2 ersetzen, wenn sich letzterer in Bezug auf die erwarteten Erträge als vielversprechender erweist als ersterer. Wir müssen über ein ausreichend großes Portfolio verfügen, um Marktveränderungen, Unternehmensereignisse und unsere eigenen Handelsentscheidungen (z. B. den Handel mit Aktie X einzustellen) berücksichtigen zu können.
Wir haben all dies aus einem Universum von ~10.000 Vermögenswerten herausgefiltert, das zu didaktischen Zwecken auch andere Arten von Vermögenswerten als Aktien umfasst, und zwar auf einen engen Korb von sechs Aktien, mit einem bestimmten Zeitrahmen und mit einer für einen bestimmten Rückblickzeitraum gültigen Kointegration. Wir haben jedes Detail erklärt, um Ihnen das Verständnis zu erleichtern, aber denken Sie daran, dass dieser Prozess ganztägig im automatisierten Modus abläuft und viele Kombinationen dieser drei Variablen (Symbol, Zeitrahmen und Rückblickzeitraum) testet. Aufgrund dieser Kombination können wir davon ausgehen, dass wir viel mehr als nur einen einzigen Korb haben werden. Wir müssen damit rechnen, dass Dutzende von Körben in der Schlange stehen und darauf warten, in unser Handelsportfolio aufgenommen zu werden. Wie können wir auswählen, welcher der nächste sein soll und welcher von ihnen an das Ende der Schlange geschickt werden soll? Die Antwort ist ein Ranking-System.
Dies sind einige der Kriterien für die Einstufung, die wir berücksichtigen können:
Stärke der Kointegration – Wir können die Johansen-Statistiken (Spur und maximaler Eigenwert) verwenden, um zu beurteilen, wie stark die Reihen kointegriert sind. Stärkere Teststatistiken deuten auf eine zuverlässigere langfristige Beziehung hin.
Anzahl der kointegrierenden Vektoren (Rang) – Anhand der Anzahl der kointegrierenden Vektoren können wir die gewünschte Komplexität des Systems, das wir aufbauen, beurteilen.
- Rang = 1 bedeutet eine einzige stabile Streuung. Leichter zu überwachen.
- Rang > 1 bedeutet, dass mehrere Streuungen möglich sind. Flexibler, aber auch komplexer.
Stabilität der Portfoliogewichte – Wir können stark schwankende Hedge-Quoten über verschiedene Stichprobenfenster hinweg vermeiden. Es kann ein Hinweis auf fragile Beziehungen sein.
Angemessene Spreads – Der Spread sollte wirtschaftlich angemessen sein. Wir sollten extrem große Positionen in einer Aktie vermeiden.
Zeit bis zur Umkehrung – Wir können die Halbwertszeit der mittleren Umkehrung berechnen, um zu beurteilen, wie schnell die Spanne zum Gleichgewicht zurückkehrt.
Liquidität – Die Liquidität ist ein unverzichtbares Kriterium, da der Handel mit illiquiden Aktien kostspielig sein kann.
Transaktionskosten – Dies ist ein sehr individuelles Ranking-Kriterium, da es von den Zielen und dem Handelssystem jedes Einzelnen abhängt, aber wir lassen es hier der Vollständigkeit halber stehen.
Wir können ein Punktesystem erstellen, indem wir alle oder einige der oben genannten Kriterien kombinieren. Zum Beispiel die Gewichtung der Kointegrationsstärke, die Stabilität der Portfoliogewichte und die mittlere Streuung. Letztendlich geht es bei der Korbauswahl darum, ein Gleichgewicht zwischen statistischer Filterung, Marktkenntnis und Handelbarkeit zu finden.
Dieses Punktesystem ist jedoch nur in der Praxis sinnvoll. Da sich unser nächster Artikel mit den Backtests des von uns entwickelten automatisierten Systems befasst, werden wir zunächst ein Scoring-System entwickeln und testen, das auf einigen der oben genannten Kriterien basiert. Auf diese Weise testen wir das Punktesystem selbst sowie den EA und seine verschiedenen Korbzusammensetzungen.
Schlussfolgerung
Wir haben gesehen, wie wir ein vereinfachtes Screening von Handelsinstrumenten für eine Handelsstrategie entwickeln können, die auf statistischer Arbitrage durch kointegrierte Aktien basiert. Wir sind von einem großen Universum von Tausenden von Symbolen ausgegangen, die auf der Handelsplattform bzw. dem Brokerserver verfügbar sind, und haben durch sukzessives Filtern einen einzigen Korb von sechs Aktien mit einem Kointegrationsvektor und einem stationären Spread erhalten.
Wir begannen mit der Filterung nach Wirtschaftszweigen und Branchen und wählten dann die am stärksten korrelierten aus der Halbleiterindustrie aus, um den endgültigen Korb auf der Grundlage des Johansen-Kointegrationstests und der ADF/KPSS-Stationaritätstests zu erstellen.
In diesem Prozess haben wir unsere Datenbank geändert, um spezielle Tabellen für die Speicherung der einzelnen Testergebnisse für die weitere Analyse einzurichten. Außerdem haben wir modulare Python-Klassen entwickelt, die die bisher verwendeten Skripte ersetzen.
An diesem Punkt sind wir bereit, mit unserem Scoring-System zu experimentieren, was wir im nächsten Schritt tun werden, während wir unser System mit der hier entwickelten Screening-Methode backtesten.
Eine etwas persönliche Anmerkung zum beigefügten Code
Der beigefügte Code, hauptsächlich in Python, wurde mit umfangreicher Unterstützung der integrierten KI-Assistenten in Metatrader 5, VS Code, und anderen geschrieben.
Ich sehe KI für die Code-Entwicklung als die anspruchsvollste Sprache unserer Zeit. Die Notwendigkeit von Programmierkenntnissen wird dadurch nicht aufgehoben. Stattdessen ist es erforderlich, dass der Entwickler ein klares Verständnis des Systems und auch ein klares Verständnis der so genannten Nutzeranforderungen hat. Man muss sehr gut wissen, wonach man fragen muss, wie man danach fragt, und vor allem muss der Entwickler wissen, wie er überprüfen kann, ob der vom Assistenten gelieferte Code den Anforderungen entspricht, d. h. ob der Code das tut, was von ihm erwartet wird. Dann fungiert der Assistent als Junior-Entwickler auf Steroiden oder sogar als Senior-Entwickler, je nach KI-Modell, Eingabeaufforderung und der jeweiligen Programmiersprache.
In Analogie dazu sehe ich KI für die Code-Entwicklung als die Erschaffung der Programmiersprache C: Sie macht die Notwendigkeit von Programmierkenntnissen nicht überflüssig; sie erleichtert dem Entwickler nur die Notwendigkeit, Assembler zu schreiben. Die KI-Assistenten sind bereits in der Lage, besseren Code in kürzerer Zeit zu schreiben, wobei Tests und Dokumentation kostenlos mitgeliefert werden.
In unserem Fall ist die relativ „einfache“ Programmiersprache Python oder MQL5.
| Dateiname | Beschreibung |
|---|---|
| Files\StatArb\schema-0.3.sql | SQL-Schema (DDL) für SQLite-Datenbank Version 0.3 |
| Scripts\StatArb\db-setup.mq5 | MQL5-Skript zur Einrichtung der Datenbank (liest die obige Schemadatei) |
| Scripts\StatArb\SymbolImporter.mq5 | MQL5 Skript zum Importieren von Symbol-Metadaten aus MetaTrader 5 in SQLite DB |
| coint_adf_kpss_to_db.py | Python-Klasse mit Methoden zur Durchführung der ADF- und KPSS-Stationaritätstests |
| coint_eg_to_db.py | Python-Klasse mit Methoden zur Durchführung des Engle-Granger-Kointegrationstests |
| coint_johansen_to_db.py | Python-Klasse mit Methoden zur Durchführung des Johansen-Kointegrationstests |
| corr_pearson_to_db.py | Python-Klasse mit Methoden zur Durchführung des Pearson-Korrelationstests |
Übersetzt aus dem Englischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/en/articles/19626
Warnung: Alle Rechte sind von MetaQuotes Ltd. vorbehalten. Kopieren oder Vervielfältigen untersagt.
Dieser Artikel wurde von einem Nutzer der Website verfasst und gibt dessen persönliche Meinung wieder. MetaQuotes Ltd übernimmt keine Verantwortung für die Richtigkeit der dargestellten Informationen oder für Folgen, die sich aus der Anwendung der beschriebenen Lösungen, Strategien oder Empfehlungen ergeben.
Die Übertragung der Trading-Signale in einem universalen Expert Advisor.
Die Grenzen des maschinellen Lernens überwinden (Teil 5): Ein kurzer Überblick über die Kreuzvalidierung von Zeitreihen
Eine alternative Log-datei mit der Verwendung der HTML und CSS
Vom Neuling zum Experten: Entmystifizierung versteckter Fibonacci-Retracement-Levels
- Freie Handelsapplikationen
- Über 8.000 Signale zum Kopieren
- Wirtschaftsnachrichten für die Lage an den Finanzmärkte
Sie stimmen der Website-Richtlinie und den Nutzungsbedingungen zu.