Statistische Arbitrage durch kointegrierte Aktien (Teil 6): Bewertungssystem
Einführung
Wir haben unseren ersten Meilenstein für eine vollautomatische statistische Arbitrage-Pipeline durch kointegrierte Aktien erreicht. Wir haben Python-Klassen für die Kointegrationstests entwickelt, wir haben eine erste Datenbank eingerichtet und weiterentwickelt, und wir haben einen Expert Advisor, der zum Testen von Strategien eingesetzt werden kann. Mit etwas Code kann das Modell, das die Strategieparameter für den EA bereitstellt, sogar in Echtzeit aktualisiert werden, indem Daten aus der Datenbank abgerufen werden. Es war ein langer Weg bis zur Implementierung unseres statistischen Arbitrage-Systems für den durchschnittlichen individuellen Händler. Wir haben sogar ein schrittweises Verfahren für das Screening unserer Aktien aus dem gesamten Universum der an der Nasdaq notierten Unternehmen bis hin zu einem Dutzend halbleiterbezogener Titel definiert. Allerdings fehlt uns ein Bewertungssystem.
Mit dem Screening-Workflow im Hinterkopf sind wir nun bereit, ein Bewertungssystem zu definieren und es einem Backtest zu unterziehen. Im vorangegangenen Artikel wurden die möglichen Kriterien dafür skizziert.
- Stärke der Kointegration
- Anzahl der kointegrierenden Vektoren (Rang)
- Stabilität der Portfoliogewichte
- Angemessene Spreads
- Zeit bis zur Umkehrung
- Liquidität
- Transaktionskosten
Neben diesen Kriterien können wir zwei weitere hinzufügen, die in dieser Übersicht nicht erwähnt werden:
- Zeitrahmen (Datenhäufigkeit)
- Rückblick-Fenster
Die Frage ist: Wie findet man die Werte und wählt die Gewichtung der einzelnen Kriterien? Es scheint klar zu sein, dass wir am Ende eine Art „gewichtete Punktevergabe“ für jedes Kriterium haben werden, aber wie sollen sie gewichtet werden? Wie wählt man aus, welche von ihnen mehr Bedeutung hat als die anderen, wenn überhaupt? Wie lässt sich eine Hierarchie dieser Kriterien aufstellen? Was kommt zuerst und was kommt am Ende der Rangliste? Indem wir klar definieren, wie diese Kriterien zu gewichten sind, schließen wir die Lücke zwischen einer theoretischen Beschreibung eines Modells und einem testbaren, praktischen und potenziell nutzbaren Handelssystem.
Wir schlagen ein Bewertungssystem mit zwei Hauptkriterien vor: Ausschluss- und Klassifizierungskriterien.
Ausschlusskriterien sind Kriterien, die einen Korb disqualifizieren. Es spielt keine Rolle, wie gut der Korb bei anderen Faktoren abschneidet; wenn er bei diesen Kriterien einen bestimmten Schwellenwert nicht erreicht, sollte der Korb ans Ende der Reihe gestellt werden. Dieses Kriterium ist entscheidend.
Die Klassifizierungskriterien hingegen bilden die Grundlage für ein angemessenes Rangfolgesystem.
Neben diesen beiden Hauptkriterien, dem Ausschlusskriterium und dem Klassifizierungskriterium, gibt es noch zwei weitere Kriterien, die je nach unseren Handelszielen als Ausschlusskriterium oder als Klassifizierungskriterium dienen können. Es handelt sich um strategische Kriterien.
Bewertungssystem
Ausschlusskriterien
Mit den Ausschlusskriterien stellen wir sicher, dass wir nur Körbe bewerten, die tatsächlich handelbar sind. Selbst ein perfekter Korb ist aus statistischer Sicht wertlos, wenn er effizient gehandelt werden kann. Wir sollten in Erwägung ziehen, ihnen ein hohes negatives Gewicht beizumessen.
Aber warum werden sie nicht in dem Screening-Filter ausgeschlossen, den wir im vorherigen Artikel gesehen haben? Denn die Werte, die diesen Kriterien zugrunde liegen, sind nicht in Stein gemeißelt. Sie können und werden sich wahrscheinlich im Laufe der Zeit ändern. Deshalb haben wir einen ersten Screening-Filter. Dabei wählen wir die Wertpapiere aus, die in unsere breit angelegte Strategie als Ganzes passen (Märkte, Sektoren, Branchen usw.). In einem zweiten Schritt durchlaufen diese Wertpapiere dann unseren Bewertungsfilter. Während der Screening-Schritt eine Auswahl unter Tausenden von potenziellen Bewerbern trifft, bestimmt der Bewertungsschritt, welcher von einer relativ kleinen Anzahl von Bewerbern der bessere ist. Definitionsgemäß muss die Bewertung uns sagen, was unser ideales Paar oder unser idealer Korb ist, um jetzt gehandelt zu werden.
Liquidität – Liquidität ist ein unverzichtbares Kriterium, da Spreads, die illiquide Aktien betreffen, teuer im Handel sein können. Wir brauchen vernünftige Spreads, und zwar nicht nur für Stat Arb. Das in einem bestimmten Zeitraum gehandelte Volumen ist der offensichtlichste Indikator für die Liquidität eines Wertpapiers. Je größer das Volumen, desto größer die Liquidität, was in direktem Zusammenhang mit den Spreads steht.
Aus der Metatrader 5-Dokumentation erfahren wir, dass Handelsvolumina für dezentrale Märkte wie Devisen und zentralisierte Märkte wie Aktien unterschiedliche Bedeutungen haben:
„Auf dem Devisenmarkt bedeutet ‚Volumen‘ die Anzahl der Ticks (Preisänderungen), die in einem bestimmten Zeitintervall aufgetreten sind. Bei Aktien bezeichnet das Volumen das Volumen der ausgeführten Handelsgeschäfte (in Kontrakten oder in Geld).“
Das gehandelte Volumen und die damit verbundenen Spreads sind nicht die einzigen Faktoren, die wir bei der Bewertung der Liquidität eines Wertpapiers in Betracht ziehen sollten. Auch die Markttiefe muss berücksichtigt werden, wenn wir mit außergewöhnlich hohen Volumina handeln würden, was hier nicht der Fall ist. Daher werden wir uns nicht mit dem DOM für das System von stat arb unserer individuellen Händler befassen.
Transaktionskosten – Es gibt mindestens drei Kostenfaktoren, die sich auf die Gesamttransaktionskosten auswirken können, abhängig von der Börse, dem Broker und den in unserem Korb enthaltenen Vermögenswerten:
- Provisionen und/oder Gebühren
- den Spread
- und den erwarteten Schlupf.
Der Spread für liquide Nasdaq-Aktien wie Apple (AAPL), Microsoft (MSFT) und Nvidia (NVDA) beträgt zum Zeitpunkt der Erstellung dieses Artikels in der Regel nur 0,01 $ pro Aktie, kann aber bei weniger liquiden Aktien größer sein. In diesem Bewertungssystem können wir diesen Wert für die liquidesten Titel annehmen und für die weniger liquiden Titel auf den maximalen Spread von 0,05 $ erhöhen.
Wenn ich mich nicht irre, ist bei den meisten Brokern die Angabe der maximal zulässigen Slippage (die Abweichung vom letzten notierten Kurs) eine Funktion, die nur für professionelle Konten zur Verfügung steht, sodass sie außerhalb des Anwendungsbereichs von unserem Stat Arb liegt, das sich an den (nicht-professionellen) individuellen Händler richtet. Aufgrund dieser Einschränkung müssen wir in unseren Backtests einen gewissen erwarteten Slippage berücksichtigen. Wir können von 0,05% des Handelswertes pro Auftrag ausgehen.
Was schließlich die Provisionen und/oder Gebühren anbelangt, so ist zu bedenken, dass viele Makler zwar provisionsfreie Handelsgeschäfte anbieten, aber dennoch regulatorische und Börsengebühren anfallen können. In unseren Backtests können wir eine Schätzung von 0,005 $ pro Aktie verwenden.
Der Einfachheit halber können wir in unseren Backtests die Gesamtkosten für „rein und raus“ (Kauf + Verkauf) mit 0,1 % des gehandelten Wertes veranschlagen. Diese Vereinfachung sollte die Spreads, eventuelle Slippage und Provisionen/Gebühren insgesamt erfassen. Ich möchte jedoch klarstellen, dass es sich hierbei um Näherungswerte handelt, die auf meinen eigenen Erfahrungen beruhen, und dass Ihre Erfahrungen von diesen Zahlen stark abweichen können. Wie immer sollten Sie also auch bei diesem Thema Ihre Sorgfaltspflicht erfüllen.
Klassifizierungskriterien
Die Klassifizierungskriterien sind diejenigen, die unsere Korbkandidaten in eine richtige Rangfolge bringen.
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 ein einziger stabiler Spread. Leichter zu überwachen.
- Rang > 1 bedeutet, dass mehrere Spreads möglich sind. Flexibler, aber auch komplexer.
Stabilität der Portfoliogewichte – Wir können stark schwankende Hedge-Ratios über verschiedene Stichprobenfenster hinweg vermeiden. Sie kann ein Hinweis auf fragile Beziehungen sein.
Zeit bis zur Umkehrung – Wir können die Halbwertszeit der mittleren Umkehrung berechnen, um zu beurteilen, wie schnell der Spread zum Gleichgewicht zurückkehrt.
Strategische Kriterien
Die Datenhäufigkeit (Zeitrahmen) und der Rückblickzeitraum sind eher eine strategische Entscheidung als ein quantitatives Kriterium für die Bewertung. Dabei geht es weniger darum, dass der eine „besser“ ist als der andere, sondern vielmehr um die Übereinstimmung mit unserer Handelsstrategie. Eine Strategie für einen langen Zeithorizont könnte tägliche Daten verwenden, während eine Strategie für kürzere Zeiträume Intraday-Daten verwenden würde. Wir „gewichten“ dieses Kriterium also nicht unbedingt in gleicher Weise wie die anderen. Stattdessen werden wir ihn als Vorauswahlfilter verwenden. Wir entscheiden zunächst, ob wir eine langfristige oder eine kurzfristige Strategie verfolgen und suchen dann nach Körben mit der entsprechenden Datenfrequenz. Die Häufigkeit der Daten kann sich auf die Aktualität der Signale, das Rauschen und die Transaktionskosten auswirken. Es handelt sich also um eine grundlegende Entscheidung, die sich auf die Bewertung der anderen Kriterien auswirkt.
Datenhäufigkeit (täglich, untertägig) – tägliche Daten sind für Strategien mit langem Zeithorizont üblich, während tagesinterne Daten kurzfristige Chancen erfassen können. Eine höhere Frequenz verbessert die Aktualität der Signale, erhöht jedoch das Rauschen und die Transaktionskosten.
Lookback Window für Stabilität – die Wahl der Länge des historischen Fensters für Korrelations- und Kointegrationstests ist entscheidend. Kurze Zeitfenster passen sich schnell an sich ändernde Marktbedingungen an, können aber vorübergehende, instabile Beziehungen erfassen. Lange Zeiträume liefern stabilere Schätzungen, können aber veraltet sein, wenn sich die Wirtschaftslage ändert.
Ein praktischer Ansatz besteht darin, mehrere Fensterlängen zu testen (z. B. 60, 120, 250 Handelstage) und zu bewerten, wie stabil die Kointegrationsergebnisse über die verschiedenen Zeiträume hinweg bleiben.
Wir können auch rollierende Fenster verwenden, um die Hedge-Ratios ständig zu aktualisieren und zu testen, ob die Beziehung auch außerhalb der Stichprobe besteht.
Verwechseln Sie diese strategische Wahl des Rückblickzeitraums nicht mit der obigen Bewertung der Stabilität der Rückblickfenster. Hier werden wir NICHT die Stabilität über verschiedene Lookback-Fenster hinweg bewerten; stattdessen wählen wir aus, welchen Lookback wir als Grundlage für unseren Mittelwert, die Standardabweichung und die Häufigkeit der Parameteraktualisierungen durch den EA verwenden. Insbesondere ist zu beachten, dass es keinen inneren Zusammenhang zwischen dem Handelszeitraum und dem Rückblickzeitraum gibt. Aus der Sicht des Handels ist es durchaus akzeptabel, dass wir in einem täglichen Zeitrahmen handeln und Intraday-Lookback-Perioden verwenden. Diese Kombination birgt in der Tat einige unerwartete Möglichkeiten, wie wir gleich sehen werden.
Einrichtung eines Bewertungssystems
Liquidität
Mit diesen Kriterien sind wir bereit, unsere Körbe zu bewerten. Wir können damit beginnen, die Aktien zu eliminieren, die nicht in unsere Strategie passen, d. h. die mit geringer Liquidität. Es ist ein Ausschlusskriterium. Solange wir jedoch nicht im Voraus sagen können, dass wir Aktien, die in einem bestimmten Zeitraum weniger als X Volumen/Kontrakte handeln, nicht berücksichtigen, ist die Liquidität ein relatives Maß. Wir brauchen eine Referenz für hohe/mittlere/niedrige Liquidität; wir müssen einen Schwellenwert dafür festlegen, was in einem bestimmten Zeitraum akzeptabel ist und was nicht.
Liquidität und folglich vernünftige Spreads sollten in dem speziellen Fall des Beispiels, das wir hier seit Beginn der Serie verwenden, also bei Nasdaq-Aktien, kein Problem darstellen. In der Regel handelt es sich um Aktien mit relativ hoher Liquidität. Doch selbst unter diesen relativ hochliquiden Aktien sind einige liquider als andere. Außerdem müssen wir berücksichtigen, dass wir irgendwann aus irgendeinem Grund nicht-Nasdaq-Aktien oder sogar speziell Small Caps prüfen/bewerten. Dann ist die Liquidität sicherlich ein zu berücksichtigender Faktor.
Fahren wir mit unseren bereits gefilterten Aktien aus der Halbleiterindustrie fort. Zum Zeitpunkt der Erstellung dieses Berichts sind dreiundsechzig Symbole in unserer Datenbank gespeichert. (Wenn Sie diese Serie nicht verfolgen, werfen Sie bitte einen Blick auf den vorherigen Artikel, um den Kontext zu erfahren, wie wir nach dem Screening hierher gekommen sind).
![]()
Abb. 1 – Screenshot der Datenbankschnittstelle im Metaeditor mit der Symbolanzahl der Tabelle market_data
Wie gesagt, dürften alle Nasdaq-Aktien relativ liquide Wertpapiere sein. Das ist der Hauptgrund, warum wir sie bei der Entwicklung der Merkmale unseres statistischen Arbitrage-Systems für den durchschnittlichen individuellen Händler ausgewählt haben. Wir wollen aber wissen, welche aus der Untergruppe der Halbleiter die am meisten gehandelten sind und welche die am wenigsten gehandelten.
![]()
Abb. 2 – Screenshot der Datenbankschnittstelle im Metaeditor mit den liquidesten Halbleiteraktien
Hier gibt es keine Überraschungen. Wie erwartet ist Nvidia die meistgehandelte und liquideste Aktie in der Halbleiterbranche und zum Zeitpunkt der Erstellung dieses Berichts eine der meistgehandelten Aktien der Welt. Diese Informationen sind jedoch von geringem Wert. Wir brauchen einen Durchschnittswert für jedes Symbol, damit wir sie im Verhältnis zueinander bewerten können.
![]()
Abb. 3 – Screenshot der Datenbankschnittstelle im Metaeditor mit dem durchschnittlichen Handelsvolumen für Halbleiteraktien
Denken Sie daran, dass Sie für den Forex-Markt hier das Tick-Volumen und nicht das reale Volumen verwenden würden.
Jetzt haben wir etwas Nützliches. Wenn Sie mit SQL nicht vertraut sind, sollten Sie sich diese einfache Abfrage vielleicht merken, denn Sie werden sie in kleinen Variationen noch oft brauchen.
SELECT
s.symbol_id,
s.ticker, -- symbol name
ROUND(AVG(md.real_volume)) AS avg_real_volume_int
FROM market_data AS md
JOIN symbol AS s
ON md.symbol_id = s.symbol_id
GROUP BY s.symbol_id, s.ticker
ORDER BY avg_real_volume_int DESC; ROUND und AVG sind zwei eingebaute SQLite-Funktionen. Wie Sie an den Namen erkennen können, verwenden wir AVG, um das durchschnittliche reale Volumen zu berechnen. Er wird als Gleitkommawert zurückgegeben. Die Funktion ROUND rundet das Ergebnis auf die nächste Ganzzahl.
Die JOIN-Klausel wird verwendet, um jede Marktdatenzeile mit ihren Symbol-Metadaten zu verknüpfen, sodass wir den Symbolnamen aus der Symbol-ID erhalten. Schließlich verwenden wir GROUP BY, damit das Ergebnis nur eine Zeile pro Symbol enthält.
Die Kointegrationsstärke
Nachdem wir nun unsere Aktiensymbole aus der Halbleiterindustrie nach Liquidität geordnet haben, ist es an der Zeit, ihre Kointegrationsstärke zu überprüfen. Wie bei den vorangegangenen Tests (Korrelation, Kointegration und Stationarität) werden auch die Ergebnisse dieses Kointegrationsstärke-Rankings zur weiteren Verwendung und zum Vergleich in einer separaten Tabelle gespeichert. Denken Sie daran, dass wir bei der Implementierung des maschinellen Lernens alle Daten speichern, die in der Zukunft nützlich sein können oder werden.
Die neue Tabelle coint_rank hat diese Form.

Abb. 4 – Screenshot mit den Feldern und Datentypen der Tabelle coint_rank
Die Tabellendefinition ist sehr ähnlich zu dem, was wir bis hierher gemacht haben. Wir verwenden weiterhin den Testzeitstempel als Primärschlüssel, da Zeitstempel eine Art natürlicher Schlüssel in unserer Domäne sind. Wir verwenden weiterhin SQLite-Tabellen mit STRICT, um Überraschungen mit falschen Datentypen zu vermeiden, und wir behalten die üblichen Überprüfungen in den TEXT-Feldern bei, wenn die zulässigen Eingaben im Voraus bekannt sind, wie die Kointegrationsmethode und die Zeitrahmen. Die nachstehende Definition enthält Anmerkungen zum besseren Verständnis.
-- Cointegration ranking results (STRICT mode with lookback and timestamp uniqueness) CREATE TABLE coint_rank ( tstamp INTEGER PRIMARY KEY, -- Unix timestamp (UTC seconds since epoch) timeframe TEXT CHECK ( timeframe IN ( 'M1','M2','M3','M4','M5','M6','M10','M12','M15','M20','M30', 'H1','H2','H3','H4','H6','H8','H12','D1','W1','MN1' ) ) NOT NULL, lookback INTEGER NOT NULL, -- Lookback period (calendar days) assets TEXT NOT NULL, -- e.g., 'AAPL, MSFT' or 'AAPL, MSFT, GOOG' method TEXT CHECK ( method IN ('Engle-Granger', 'Johansen') ) NOT NULL, strength_stat REAL, -- Engle-Granger: ADF statistic; Johansen: trace statistic p_value REAL, -- Only for Engle-Granger eigen_strength REAL, -- Johansen eigenvalue indicator rank_score REAL, -- Combined ranking score -- Allow multiple test runs for the same combo but unique by timestamp CONSTRAINT coint_rank_unique_combo UNIQUE (timeframe, lookback, assets, tstamp) ) STRICT; CREATE INDEX idx_coint_rank_timeframe_lookback ON coint_rank (timeframe, lookback);
Wir verwenden eine UNIQUE-Beschränkung für die Kombination tstamp/timeframe/lookback/assets, sodass wir wissen, dass wir für jedes dieser Paare nur eine Bewertung des Kointegrationsrangs zu jedem Zeitstempel haben werden. Beachten Sie, dass tstamp zwar bereits per Definition eindeutig ist, da es sich um den Primärschlüssel der Tabelle handelt, aber wenn wir ihn aus der UNIQUE-Kombination herauslassen, können wir nicht mehr als einen Lauf für jede Kombination aus Zeitrahmen, Rückblick und Vermögenswerten einfügen. Dies würde gegen die UNIQUE-Beschränkung verstoßen. Durch die Aufnahme des Zeitstempels in die Kombination können wir dieselbe Kombination mit verschiedenen Zeitstempeln speichern, um die Stabilität der Kointegration im Zeitverlauf zu überprüfen. Später können wir die Ergebnisse nach Datum filtern oder aggregieren. Dies wird für unsere Backtest-Protokolle nützlich sein, da jeder Lauf in sich abgeschlossen, mit einem Zeitstempel versehen und nachvollziehbar ist. Da wir hauptsächlich nach Zeitrahmen und Rückblicken abfragen werden, haben wir einen Index für diese beiden Spalten erstellt, um die Abläufe zu beschleunigen.
Statistik der Stärke für den Engle-Granger-Test
Die Funktionsweise der Engle-Granger- und Johansen-Kointegrationstests haben wir bereits in früheren Teilen dieser Serie ausführlich erläutert, sodass wir diese Informationen hier nicht wiederholen. Erinnern wir uns einfach daran, dass sie messen, wie eng sich ein Paar oder eine Gruppe von Aktien langfristig zusammen bewegt. Das heißt, sie messen, wie stark das Preisverhältnis zwischen diesen Vermögenswerten im Laufe der Zeit anhält. Das Feld strength_stat speichert das numerische Ergebnis des Kointegrationstests, sowohl für den Engle-Granger als auch für den Johansen-Test.
Für den Engle-Granger-Test wird in diesem Feld die ADF-Statistik (Augmented Dickey-Fuller) gespeichert, die auf dem Spread zwischen den beiden Vermögenswerten angewendet wird. Auch hier haben wir die Besonderheiten des ADF-Stationaritätstests und seine Interpretation bereits in früheren Artikeln dieser Reihe vorgestellt und werden uns hier nicht wiederholen. Es genügt, sich daran zu erinnern, dass geprüft wird, ob der Spread zwischen den beiden Vermögenswerten um einen Mittelwert schwankt und nicht abdriftet. Das heißt, es wird geprüft, ob der Spread stationär ist. Für den Engle-Granger-Kointegrationstest sagt uns dieses Feld also, „wie sehr“ der Spread stationär ist.
Wenn Sie unserer Argumentation aus den vorangegangenen Teilen folgen, sollte inzwischen klar sein, dass die Kointegration umso stärker ist, je kleiner die ADF-Statistik ist; ein „negativeres“ strength_stat-Feld für den Engle-Granger-Test bedeutet, dass der Spread „stabiler“ ist.
Stärkenstatistik für den Johansen-Test
Wenn nicht ein Paar von Vermögenswerten, sondern ein Korb von drei oder mehr Vermögenswerten getestet wird, ist der Johansen-Kointegrationstest das Instrument, das wir zur Erstellung unserer gewichteten Portfolios verwenden, d. h. von linearen Kombinationen, die im Laufe der Zeit stabil bleiben. Wir haben diesen Test und die Interpretation seiner Ergebnisse bereits in früheren Artikeln beschrieben. Auch hier ersparen wir Ihnen Zeit, indem wir Sie auffordern, diese Artikel zu lesen. Für diesen Test wird im Feld strength_stat in unserer Datenbank die „Spur-Statistik“ gespeichert. Je höher die Spur-Statistik, desto stärker ist der Beweis, dass eine Kombination dieser Vermögenswerte ein stabiles langfristiges Gleichgewicht bildet. Je größer die strength_stat, desto stärker ist der Beweis, dass dieser Korb im Gleichgewicht zusammenrückt.
Das beigefügte Python-Skript folgt der folgenden Logik, um zu entscheiden, wann welcher Test verwendet werden soll und wie die Ergebnisse ermittelt werden sollen.
try: if len(basket) == 2: y0, y1 = sub_prices.iloc[:, 0], sub_prices.iloc[:, 1] score, p_value, _ = coint(y0, y1) results.append({ "assets": basket, "method": "Engle-Granger", "strength_stat": float(score), "p_value": float(p_value), "eigen_strength": None }) else: johansen_res = coint_johansen(sub_prices, det_order, k_ar_diff) max_eig = float(max(johansen_res.eig)) results.append({ "assets": basket, "method": "Johansen", "strength_stat": float(max(johansen_res.lr1)), "p_value": None, "eigen_strength": max_eig })
Nachstehend finden Sie eine visuelle Darstellung der Logik.

Abb. 5 – Flussdiagramm, das zeigt, wie das Feld strength_stat gefüllt wird, und seine vereinfachte Interpretation
Eigen-Stärke
Während der Engle-Granger-Test nur die ADF liefert, die wir im Feld strength_stat speichern, hat der Johansen-Test noch ein weiteres Maß, das uns bei der Auswertung hilft: die Stärke der Eigenwerte, die wir im Feld eigen_strength speichern. Für Körbe mit drei oder mehr Vermögenswerten findet der Johansen-Test lineare Kombinationen (die unsere Portfoliogewichte sein werden) derjenigen Vermögenswerte, die stabile langfristige Beziehungen bilden. Jede Kombination entspricht einem kointegrierenden Vektor, und jeder Kombination ist ein Eigenwert zugeordnet. Der Eigenwert misst, wie „stark“ diese spezifische kointegrierende Beziehung ist und wie eng die Vermögenswerte entlang dieser Gleichgewichtsrichtung zusammenlaufen. Ein größerer Eigenwert bedeutet, dass die Vermögenswerte eine stabilere langfristige Beziehung aufweisen und dass kleine Abweichungen vom Gleichgewicht tendenziell schneller korrigiert werden.
In unserem beigefügten Skript nehmen wir den maximalen Eigenwert aller erkannten Vektoren:
else: johansen_res = coint_johansen(sub_prices, det_order, k_ar_diff) max_eig = float(max(johansen_res.eig)) results.append({ "assets": basket, "method": "Johansen", "strength_stat": float(max(johansen_res.lr1)), "p_value": None, "eigen_strength": max_eig })
Die Johansen-Spurenstatistik (strength_stat) gibt an, wie eng die Gruppe zusammenhängt, d. h. wie stabil die Beziehungen sind. Der maximale Eigenwert (eigen_strength) sagt uns, wie stabil die stabilste Beziehung unter ihnen ist. Ein hoher Wert von eigen_strength sagt uns also, dass sich die Gruppe in einer sehr engen Formation bewegt, während ein niedriger Wert von eigen_strength uns sagt, dass sie leichter auseinander driftet, selbst wenn sie kointegriert ist.
Punktzahl der Ränge
Das Feld rank_score ist die abschließende zusammenfassende Metrik, die unser Bewertungsskript erstellt und die darüber entscheidet, welche Körbe am stärksten aussehen und die Aufmerksamkeit der Händler verdienen. Nachdem wir die Kointegrationstests durchgeführt haben, benötigen wir eine einzige vergleichbare Zahl für alle Ergebnisse, unabhängig davon, ob sie von Engle-Granger-Paaren oder Johansen-Körben stammen. Diese einzelne Zahl ist der rank_score. Wir können uns den rank_score als einen normalisierten Kointegrationsstärke-Index vorstellen, der es uns ermöglicht, alle unsere Kandidatenbeziehungen von der stärksten zur schwächsten zu sortieren und zu ordnen.
Sie finden sie in diesem Teil unseres beigefügten Skripts der Punktewertung:
df = pd.DataFrame(results) df["rank_score"] = df.apply(lambda row: -row["p_value"] if row["method"] == "Engle-Granger" else row["eigen_strength"], axis=1) df = df.sort_values("rank_score", ascending=False).reset_index(drop=True)
Für den Engle-Granger-Test (Paare) ergibt der Test einen p-Wert. Kleinere p-Werte bedeuten einen stärkeren Nachweis der Kointegration. Um stärkere Paare in der endgültigen Rangliste höher zu sortieren, negieren wir den p-Wert:
rank_score = −p_value
So wird ein p-Wert von 0,01 zu -0,01, der über einem schwächeren Wert wie -0,20 liegt. Je niedriger der p-Wert ist, desto höher (weniger negativ) ist der rank_score, sodass das Paar als stärker kointegriert eingestuft wird.
Für Johansen (Körbe) ergibt der Test nicht einen einzigen p-Wert, sondern mehrere Eigenwerte. Unser Skript nimmt den größten Eigenwert, der in eigen_strength gespeichert ist, und verwendet ihn direkt als rank_score.
rank_score=eigen_strength
Ein höherer Eigenwert bedeutet einen höheren rank_score, also einen stärkeren Korb.
Der Einfachheit halber und um die Analyse zu erleichtern, stellt der rank_score alle Paare und Körbe auf dieselbe Seite. Es spielt keine Rolle, aus welchem Test sie stammen, sondern nur, wie stark die Beziehung ist. Wir können SQL verwenden, um die Ergebnisse nach Belieben zu filtern (das ist ja der Hauptgrund, warum wir eine Datenbank verwenden, nicht wahr?). Wenn wir nach rank_score (absteigend) sortieren, stehen die stabilsten und statistisch signifikantesten Preisbeziehungen an der Spitze unserer Liste.
![]()
Abb. 6 – Screenshot der Datenbankschnittstelle im Metaeditor mit der Tabelle coint_rank mit Vermögenswerten aus der Halbleiterindustrie
Hier haben wir die zehn liquidesten Vermögenswerte aus Abbildung 3 ausgewählt und das beigefügte Kointegrations-Ranking-Skript für alle Kombinationen von zwei, drei und vier Symbolen, alle für den H4-Zeitrahmen, ausgeführt. Dieser Zeitrahmen ist Teil unserer strategischen Kriterien. Abbildung 6 oben zeigt den ersten Lauf, den wir für den 60-Tage-Rückblick durchgeführt haben. Die blaue Markierung im Metaeditor zeigt die Ebene, auf der die Rangfolge von Johansen- zu Engle-Granger-Werten übergeht. Die Ergebnismenge ist vollständig, es wurden noch keine Filter angewendet.
Sie werden feststellen, dass es 375 Ergebnisse für diesen einzigen Lauf gibt (diese Tabelle war vor dem Lauf leer). Dies ist die Anzahl der möglichen Kombinationen (nicht Permutationen) für 10 Symbole, gruppiert nach 2, 3 oder 4. Behalten Sie diese Zahl im Hinterkopf, wenn Sie Ihre eigenen Tests durchführen, denn Sie müssen die „kombinatorische Explosion“ berücksichtigen, mit der Sie möglicherweise zu tun haben. Das ist der Grund, warum ich mich hier für einen einzigen Zeitrahmen entschieden habe, abgesehen davon, dass es sich um unsere „strategischen Kriterien“ zu Demonstrationszwecken handelt. Das ist auch der Grund, warum ich die Anzahl der Symbole pro Korb auf vier begrenzt habe. Später müssen wir für mehrere Rückblickszeiträume testen, denn ohne den Vergleich zwischen mehreren Rückblickszeiträumen ist dieses Ranking wenig hilfreich oder zumindest sehr anfällig. Wenn wir mehr Symbole und Zeitrahmen einbeziehen, benötigen wir viel mehr Ressourcen, sowohl in Bezug auf Rechenleistung, Zeit als auch Daten. Behalten Sie dies im Hinterkopf und passen Sie die Zahlen so an, dass Sie Ihre Ressourcen an Ihre Ziele anpassen und nicht umgekehrt.
Hier haben wir die Oberseite desselben Tisches.
![]()
Abb. 7 – Screenshot der Datenbankschnittstelle im Metaeditor, der den oberen Teil der Tabelle coint_rank zeigt
Man beachte, dass der obere Teil der Tabelle von Johansen-Ergebnissen dominiert wird. Dies ist zu erwarten, da es tendenziell stärkere Beziehungen findet als Engle-Granger. Berücksichtigen Sie aber auch, dass wir hier eine winzige Stichprobe mit nur einem Zeitrahmen (H4) und einem Rückblickzeitraum (60 Tage) haben.
Doch selbst bei dieser begrenzten Stichprobe zeichnen sich einige Muster ab, wie das mit den drei Linien in Abbildung 7 hervorgehobene. Wir haben sechs Symbole in drei Körben mit je vier Symbolen, aber die Änderung eines Symbols hat kaum Auswirkungen auf das Ergebnis. Dies könnte darauf hindeuten, dass die anderen drei Symbole, die sich im Korb nicht verändern (NVDA, MU und ASX), die „wahre Quelle“ der Kointegration sind. Dann finden wir dieses Trio, das fünf Zeilen weiter unten einen eigenen Korb bildet, sodass die Kointegration schwächer ist, als wenn die anderen im Korb vertreten wären. Warum? Es war nicht zu erwarten, dass sie die solide Basis der Kointegration bilden würden? Nun, ich kenne die Antwort noch nicht. Aber ich bin mir sicher, dass wir bei der Analyse dieser zehn Symbole im Laufe unserer Entwicklung viele solcher Muster und andere, noch „unerwartetere“, finden werden. Und viele von ihnen werden handelbare Muster sein, die wir ohne die Hilfe der Datenanalyse nicht finden könnten. Das ist die Schönheit der statistischen Arbitrage und in diesem Zusammenhang die Schönheit des datengesteuerten Handels im Allgemeinen.
Wir werden viel Zeit haben, um nach diesen Mustern in unseren Daten zu suchen, sowohl manuell als auch durch die Visualisierung der Ergebnisse in Diagrammen. Konzentrieren wir uns zunächst auf unser ursprüngliches Ziel, diesen Arbeitsablauf zu automatisieren, um die von uns erstellte Strategietabelle zu füttern, die die „einzige Quelle der Wahrheit“ für unseren Expert Advisor darstellt.
Sobald unsere Tabelle coint_rank mit den Daten der zehn liquidesten Symbole für den H4-Zeitrahmen und die Rückblickzeiträume von einem bis sechs Monaten gefüllt ist, steht der Korb mit dem höchsten Kointegrationsgrad bei der Sortierung nach absteigendem rank_score an erster Stelle der Ergebnisse.
Erinnern Sie sich daran, dass unsere ursprüngliche Handelshypothese nach Aktien sucht, die mit NVDA kointegriert sind. Überprüfen wir es also.

Abb. 8 – Screenshot der Datenbankschnittstelle im Metaeditor mit der Tabelle coint_rank
Hier verwenden wir den LIKE-Operator aus SQLite, um nur die Körbe und Paare zu filtern, die NVDA an irgendeiner Stelle enthalten.
„Der LIKE-Operator führt einen Mustervergleich durch. Der Operand rechts vom LIKE-Operator enthält das Muster, und der linke Operand enthält die Zeichenfolge, die mit dem Muster verglichen werden soll. Ein Prozentzeichen (%) im LIKE-Muster passt auf jede Folge von null oder mehr Zeichen in der Zeichenkette.“ (Weitere Informationen finden Sie in den Dokumenten von SQLite.)
Wenn wir mit Paaren und nicht mit Körben handeln wollen, filtern wir nach der Methode des Kointegrationstests und fragen nur nach der Engle-Granger-Methode. (Wir hätten die obige Abfrage auch filtern und nur nach dem Johansen-Test fragen können, aber das war nicht nötig, da, wie gesagt, die Johansen-Ergebnisse über den Engle-Granger-Ergebnissen schweben).

Abb. 9 – Screenshot der Datenbankschnittstelle im Metaeditor mit der für den Engle-Granger-Test gefilterten Tabelle coint_rank
Wir sehen, dass wir mindestens einen starken Kandidaten für einen Korb mit 60-Tage-Rückblick und zwei gute Kandidaten für den Paarhandel haben, nämlich einen für den 180-Tage-Rückblick und einen für den 60-Tage-Rückblick. Bleiben wir beim Korb, denn das ist es, was wir getan haben, und lassen Sie die Paare für Ihre Experimente (im ersten Artikel dieser Serie finden Sie einen Paar-Handels-EA, um sie nach Belieben zu testen).
Für den Backtest des stärkeren Korbs benötigen wir die Portfoliogewichte. Wir werden das Skript coint_johansen_to_db.py verwenden, das wir im vorigen Artikel vorgestellt haben, um die Portfoliogewichte zu erhalten und gleichzeitig die Testergebnisse in der Datei coint_johansen_test für zukünftige Analysen zu speichern.
if __name__ == '__main__': analyzer = SymbolJohansenMulti() # Our best-ranked NVDA cointegrated basket analyzer.run_johansen_analysis( asset_tickers=['NVDA', 'INTC', 'AVGO', 'ASX'], timeframe='H4', lookback=60 )
Wenn alles gut geht, sollten Sie eine Ausgabe wie diese in Ihrem Terminal haben.
PS C:\...\StatArb\coint> python .\py\screening\coint_johansen_to_db.py
Successfully connected to the SQLite database.
Fetching data for symbol: NVDA...
Fetching data for symbol: INTC...
Fetching data for symbol: AVGO...
Fetching data for symbol: ASX...
Johansen test results for 4 assets:
Cointegrating rank: 1
Trace Statistics: [56.636209656616835, 14.38576476690755, 5.106951610164332, 1.355015009275225]
Max-Eigenvalue Statistics: [42.250444889709286, 9.278813156743219, 3.7519366008891066, 1.355015009275225]
Cointegrating Vectors: [1.0, -1.9598590335874817, -0.36649674991957104, 21.608207065113874]
Successfully stored Johansen test results for 4 assets with test_id: 21.
Database connection closed.
Analysis complete.
Der letzte Schritt besteht darin, diese Werte in unsere „Strategie“-Tabelle einzufügen, die von unserem Expert Advisor gelesen wird, und einen Backtest durchzuführen.
Der Backtest
Während die in Metatrader 5 integrierte SQLite-Datenbank beim Handel voll verfügbar ist, können wir SQLite-Datenbanken nicht aus dem Strategy Tester lesen. Ich nehme an, der Grund dafür ist, dass Strategy Tester einen separaten Agentenordner verwendet (was Sandboxing bedeutet). Während des Testens werden alle Dateioperationen im lokalen Ordner des Testagenten durchgeführt, nicht im regulären Terminal MQL5-Dateien. Wir könnten die Tabelle „strategy“ in eine CSV-Datei exportieren und sie zu Beginn des Backtests von OnInit() in den EA einlesen. Damit könnten wir zwar die Tabelle „Strategie“ lesen, aber wir wären immer noch nicht in der Lage, das Modell während des Backtestings in Echtzeit zu aktualisieren, was das Hauptziel der Datenbank als Modelldatenquelle ist. Aber, keine Panik! In einem Demokonto können wir überprüfen, wie sich die Echtzeit-Modellaktualisierungen verhalten. Für den Moment wollen wir die Modellparameter im EA fest einprogrammieren und jede Strategie einzeln backtesten.
Da wir MQL5 Algo Forge verwenden, den neuen Git-gestützten MQL5 Speicher, können wir die Änderungen, die wir in unserem EA vorgenommen haben, um diese Parameter einzubeziehen, leicht sehen.
// Input parameters input int InpUpdateFreq = 1; // Update frequency in minutes -input string InpDbFilename = "StatArb\\statarb-0.3.db"; // SQLite database filename -input string InpStrategyName = "CointNasdaq"; // Strategy name +input string InpDbFilename = "StatArb\\statarb-0.4.db"; // SQLite database filename +input string InpStrategyName = "CointNasdaq_H4_60"; // Strategy name input double InpEntryThreshold = 2.0; // Entry threshold (std dev) input double InpExitThreshold = 0.3; // Exit threshold (std dev) input double InpLotSize = 10.0; // Lot size per leg @@ -53,18 +53,40 @@ int OnInit() // Set a timer for spread, mean, stdev calculations // and strategy parameters update (check DB) EventSetTimer(InpUpdateFreq * 60); // min one minute -// Load strategy parameters from database - if(!LoadStrategyFromDB(InpDbFilename, - InpStrategyName, - symbols, - weights, - timeframe, - lookback_period)) +// check if we are backtesting + if(MQLInfoInteger(MQL_TESTER)) { - // Handle error - maybe use default values - printf("Error at " + __FUNCTION__ + " %s ", - getUninitReasonText(GetLastError())); - return INIT_FAILED; + Print("Running on tester"); + ArrayResize(symbols, 4); + ArrayResize(weights, 4); + //{"NVDA", "INTC", "AVGO", "ASX"}; + symbols[0] = "NVDA"; + symbols[1] = "INTC"; + symbols[2] = "AVGO"; + symbols[3] = "ASX"; + // {1.0, -1.9598590335874817, -0.36649674991957104, 21.608207065113874}; + weights[0] = 1.0; + weights[1] = -1.9598590335874817; + weights[2] = -0.36649674991957104; + weights[3] = 21.608207065113874; + timeframe = PERIOD_H4; + lookback_period = 60; + } + else + { + // Load strategy parameters from database + if(!LoadStrategyFromDB(InpDbFilename, + InpStrategyName, + symbols, + weights, + timeframe, + lookback_period))
Sie können sehen, dass wir den Dateinamen unserer Datenbank aktualisiert haben, um die Schemaänderungen widerzuspiegeln (wir haben die coint_rank-Tabelle hinzugefügt), und den Namen der Strategie, um den Kointegrationstest anzugeben, der ihre Parameter generiert hat, wodurch sie spezifischer wird.
Wir haben auch eine Prüfung hinzugefügt, um festzustellen, ob wir in der Strategy Tester-Umgebung arbeiten, d.h. ob wir einen Backtest durchführen. Wenn dies der Fall ist, werden wir die Parameter nicht aus der Datenbank beziehen. Stattdessen werden wir die fest kodierten Strategieparameter verwenden.
Dies sind die Backtest-Einstellungen und die dabei verwendeten Eingaben. Sie finden sowohl die Backtest-Konfigurationseinstellungen (.ini) als auch die Backtest-Eingabedateien (.set) am Ende dieses Artikels.

Abb. 10 – Screenshot der Backtest-Einstellungen
Beachten Sie, dass wir den Backtest über einen Zeitraum von zweieinhalb Jahren, also seit Anfang 2023, durchgeführt haben, obwohl unsere Strategie eine Rückblicksperiode von 60 Tagen hat. Außerdem haben wir das Feld „Delays“ auf ideale Ausführung (Latenz Null) eingestellt, obwohl wir wissen, dass dies ein kritischer Faktor für statistische Arbitrage-Strategien sein kann.
Beide Entscheidungen hängen mit der Tatsache zusammen, dass das Hauptziel dieses ersten Backtests darin besteht, die langfristige Stabilität der Strategie zu bewerten, nicht ihre potenzielle Rentabilität. Warum also wurde der Rückblickzeitraum des Kointegrationstests nicht von vornherein auf zweieinhalb Jahre festgelegt? Da wir jetzt für die meisten Kointegrierten punkten, ziehen wir den Handel in Betracht. Langfristige Stabilität ist ein weiterer Faktor, der in unserem Bewertungssystem berücksichtigt werden muss, aber bei der Einstufung der Warenkörbe sind wir heute an den am stärksten kointegrierten Körben interessiert.
Wenn es um Null-Latenz geht, sollte es hier keinen Unterschied machen. Erinnern Sie sich noch daran, als wir uns entschieden, in höheren Zeitrahmen zu handeln, um den unfairen Wettbewerb mit die Statistik-Arbitrage der ‚big Player‘ zu vermeiden? Dort handelten wir im einminütigen Zeitrahmen. Jetzt befinden wir uns auf dem H4-Zeitrahmen, in einer entspannteren Swing-Trading-Umgebung.

Abb. 11 – Screenshot mit den Backtest-Eingaben
Abbildung 11 zeigt, dass wir einige Optimierungen vorgenommen haben, um die beste Einstiegs- und Ausstiegsschwelle zu wählen, die beide als Standardabweichungen vom Mittelwert berechnet werden. Die 6,9 bzw. 0,1 waren die im Backtest verwendeten Werte.
Dies sind die Ergebnisse des Backtests.

Abb.12 – Backtest-Bericht mit den resultierenden Statistiken
Der EA eröffnete 160 Trades mit einem Durchschnitt von 4,7/Monat in 34 Monaten. Sagen wir, im Durchschnitt ein Handelsgeschäft pro Woche, was eine gute Haltezeit für einen Swing-Trade sein sollte. Außerdem ist der durchschnittliche Gewinn (1.479,02) höher als der durchschnittliche Verlust (-1.369,62), bei einem minimalen Saldoabzug (1,27%). Obwohl die Rentabilität nicht das Hauptziel des Backtests war, klingt das Gesamtbild vielversprechend.

Abb. 13 – Backtest mit der Kapital-/Saldenkurve
Die Kapital-/Saldenkurve ist etwas besser, als ich erwartet hatte, denn es wurde um den 24. November herum profitabel, und der Rückblickzeitraum unseres Kointegrationstests war sehr kurz (60 Tage).

Abb.14 Backtest-Bericht mit Angabe der Tage und Zeiten des Handelseintritts
“Bei der Sichtung der Daten von Straus entdeckte Laufer bestimmte wiederkehrende Handelssequenzen, die auf dem Wochentag basieren. So folgte die Kursentwicklung am Montag häufig der vom Freitag, während am Dienstag eine Umkehr zu früheren Trends zu beobachten war. Laufer entdeckte auch, dass der Handel des Vortages oft die Aktivität des nächsten Tages vorhersagen kann, was er als Vierundzwanzig-Stunden-Effekt bezeichnete. Das Medallion-Modell begann damit, am späten Freitag zu kaufen, wenn es einen klaren Aufwärtstrend gab, und dann am frühen Montag zu verkaufen, um den so genannten Wochenend-Effekt auszunutzen.“ (aus dem Buch von Gregory Zuckerman, The Man Who Solved the Market: How Jim Simmons launched the quant revolution, New York, NY: Portfolio/Penguin, 2019)
Haben Sie das Muster im obigen Eintrag nach Stunden bemerkt? Alle 160 Geschäfte wurden zur gleichen Stunde eröffnet, um genau zu sein um 16:30 Uhr.
Ich gehe davon aus, dass wir im Strategy Tester von der UTC-Zeit sprechen.
“Während der Tests ist die lokale Zeit TimeLocal() immer gleich der Serverzeit TimeTradeServer(). Im Gegenzug ist die Serverzeit immer gleich der Zeit, die der GMT-Zeit entspricht – TimeGMT(). Auf diese Weise werden alle diese Funktionen während des Testens zur gleichen Zeit angezeigt.“ (Die Grundlagen des Testens in Metatrader 5)
Um ehrlich zu sein, finde ich es ziemlich seltsam, dass alle Berufe die gleiche Öffnungszeit haben. Das kann wahr sein, ebenso wie es auf ein unerwartetes Verhalten von EA zurückzuführen sein kann. Wie dem auch sei, dies ist der Börsenschluss der Londoner Börse, und solche Muster können wir erwarten, wenn wir Daten für statistische Arbitrage analysieren, wie das obige Zitat zeigt.

Abb. 15 – Backtest-Bericht mit MFE und MAE
Sowohl der MFE als auch der MAE deuten darauf hin, dass wir für dieses System einen Schwellenwert für die Schließung von Positionen nach Haltezeit in Betracht ziehen sollten, was durch die unten aufgeführten maximalen und durchschnittlichen Positionshaltezeiten bestätigt wird. Weitere Informationen über MFE und MAE finden Sie in diesem großartigen Artikel über die Mathematik im Handel.

Abb. 16 – Backtest-Bericht mit Anzeige der Positionshaltezeiten
Es scheint, als hätten wir mindestens eine Stelle, die etwa 15 Wochen lang offen blieb! Und selbst die durchschnittliche Haltedauer einer Position von etwa einem Monat scheint für diese Art von Strategie etwas hoch zu sein.
Aber wir werden uns mit diesen Fragen noch beschäftigen. Inzwischen reicht es aus, wenn Sie die Grundsätze des Bewertungssystems verstehen und es an Ihren Stil und Ihre Handelsziele anpassen. Wie John Von Neumann einmal sagte: „Die Wahrheit ist ... viel zu kompliziert, um etwas anderes als Annäherungen zuzulassen.“
Viel Spaß beim Handeln!
Schlussfolgerung
In diesem Artikel schlagen wir ein Bewertungssystem für statistische Arbitrage durch kointegrierte Aktien vor. Es beginnt mit den strategischen Kriterien wie dem Zeitrahmen und dem Rückblickfenster für Kointegrationstests, dann werden Ausschlusskriterien wie Liquidität und Transaktionskosten angewandt, um Wertpapiere auszusondern, die die Handelskosten nicht wert sind oder die überhaupt nicht gehandelt werden können.
Schließlich wird die Rangfolge auf der Grundlage der Stärke der Kointegration, der Anzahl der Kointegrationsvektoren, der Stabilität der Portfoliogewichte und der Zeit bis zur Rückkehr zum Mittelwert ermittelt. Wir haben in diesem Artikel eine Beispielimplementierung für die ersten beiden Klassifizierungskriterien vorgestellt und die Stabilität der Portfoliogewichte und die Halbwertszeit der Mittelwertumkehr für den nächsten Teil vorgesehen.
Wir haben die Ergebnisse des Backtests auf der Grundlage der beiden Klassifizierungskriterien vorgestellt und kommentiert und die erforderlichen Dateien zur Reproduktion der Kointegrationstests und des Backtests selbst zur Verfügung gestellt, sodass die Leser sofort mit der vorgeschlagenen statistischen Arbitragestrategie und diesem Bewertungssystem beginnen können.
| Datei | Beschreibung |
|---|---|
| backtests\CointNasdaq.EURUSD.H4.20230101_20251019.000.ini | Einstellungen der Backtest-Konfiguration |
| backtests\CointNasdaq.set | Backtest-Eingänge (SET-Datei) |
| Experts\StatArb\CointNasdaq.mq5 | Expert Advisor MQL5 Quelldatei |
| Files\StatArb\schema-0.4.sql | Datenbankschema (SQL-Datei) |
| Include\StatArb\CointNasdaq.mqh | Expert Advisor MQH (Header) Datei |
| coint_ranker_auto.py | Python-Skript für das Ranking von Kointegrationsergebnissen |
Übersetzt aus dem Englischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/en/articles/20026
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.
Selbstoptimierende Expert Advisors in MQL5 (Teil 15): Identifizierung linearer Systeme
Eine alternative Log-datei mit der Verwendung der HTML und CSS
Der MQL5 Standard Library Explorer (Teil 2): Verbinden mit Bibliothekskomponenten
- 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.