
Feature Engineering mit Python und MQL5 (Teil II): Winkel des Preises
Modelle des maschinellen Lernens sind sehr empfindliche Instrumente. In dieser Artikelserie werden wir deutlich mehr darauf eingehen, wie sich die Transformationen, die wir auf unsere Daten anwenden, auf die Leistung unseres Modells auswirken. Ebenso reagieren unsere Modelle darauf, wie die Beziehung zwischen dem Input und dem Ziel vermittelt wird. Das bedeutet, dass wir möglicherweise neue Merkmale aus den uns vorliegenden Daten erstellen müssen, damit unser Modell effektiv lernen kann.
Es gibt keine Grenzen, wie viele neue Funktionen wir aus unseren Marktdaten erstellen können. Die Transformationen, die wir auf unsere Marktdaten anwenden, und alle neuen Merkmale, die wir aus den vorhandenen Daten erstellen, verändern unsere Fehlerquote. Wir wollen Ihnen dabei helfen, herauszufinden, welche Transformationen und Feature-Engineering-Techniken Ihre Fehlerquote näher an 0 bringen. Außerdem werden Sie feststellen, dass jedes Modell unterschiedlich von denselben Transformationen betroffen ist. In diesem Artikel finden Sie daher auch eine Anleitung, welche Transformationen Sie je nach Modellarchitektur wählen sollten.
Überblick über die Handelsstrategie
Wenn Sie das MQL5-Forum durchsuchen, werden Sie viele Beiträge finden, in denen die Frage gestellt wird, wie wir den Winkel berechnen können, der sich aus den Veränderungen der Preisniveaus ergibt. Die Intuition ist, dass Abwärtstrends zu negativen Winkeln führen, während Aufwärtstrends zu Winkeln größer als 0 führen. Die Idee ist zwar leicht zu verstehen, aber nicht so leicht umzusetzen. Es gibt viele Hindernisse, die von allen Mitgliedern unserer Gemeinschaft überwunden werden müssen, die daran interessiert sind, eine Strategie zu entwickeln, die den vom Preis gebildeten Winkel einbezieht. In diesem Artikel werden einige der wichtigsten Fragen beleuchtet, die zu klären sind, bevor Sie eine vollständige Investition Ihres Kapitals in Betracht ziehen sollten. Außerdem werden wir nicht nur die Mängel der Strategie kritisieren, sondern auch mögliche Lösungen vorschlagen, mit denen Sie die Strategie verbessern können.
Der Gedanke hinter der Berechnung des Winkels, der durch die Preisänderungen gebildet wird, ist, dass er eine Quelle der Bestätigung ist. Händler verwenden in der Regel Trendlinien, um den vorherrschenden Trend auf dem Markt zu erkennen. Trendlinien verbinden normalerweise 2 oder 3 extreme Kurspunkte mit einer geraden Linie. Wenn die Kurse die Trendlinie durchbrechen, sehen einige Händler dies als Zeichen der Marktstärke und schließen sich dem Trend an diesem Punkt an. Umgekehrt könnte ein Ausbruch aus der Trendlinie in die entgegengesetzte Richtung als Zeichen von Schwäche und einer Abschwächung des Trends gewertet werden.
Eine wesentliche Einschränkung der Trendlinien besteht darin, dass sie subjektiv definiert sind. Daher kann ein Händler seine Trendlinien willkürlich anpassen, um eine Analyse zu erstellen, die seine Perspektive unterstützt, selbst wenn seine Perspektive falsch ist. Daher ist es nur natürlich, dass man versucht, Trendlinien mit einem robusteren Ansatz zu definieren. Die meisten Händler hoffen, dies zu erreichen, indem sie die Steigung berechnen, die durch Veränderungen der Preisniveaus entsteht. Die Hauptannahme ist, dass die Kenntnis der Steigung gleichbedeutend ist mit der Kenntnis der Richtung der Trendlinie, die durch die Preisbewegung gebildet wird.
Damit sind wir bei der ersten Hürde angelangt, die es zu überwinden gilt: die Definition der Steigung. Die meisten Händler versuchen, die vom Preis erzeugte Steigung als Preisdifferenz geteilt durch die Zeitdifferenz zu definieren. Dieser Ansatz weist mehrere Einschränkungen auf. Erstens: Die Aktienmärkte sind über das Wochenende geschlossen. In unseren MetaTrader 5-Terminals wird die Zeit, die während der Schließung der Märkte verstrichen ist, nicht aufgezeichnet, sondern muss aus den vorliegenden Daten abgeleitet werden. Bei der Verwendung eines solchen einfachen Modells ist daher zu bedenken, dass das Modell nicht die Zeit berücksichtigt, die über das Wochenende verstrichen ist. Das bedeutet, dass unsere Schätzung der Steigung überhöht ist, wenn das Preisniveau über das Wochenende gestiegen ist.
Es sollte sofort klar sein, dass die mit unserem derzeitigen Ansatz berechnete Steigung sehr empfindlich in Bezug zu unserer Darstellung der Zeit reagiert. Wenn wir, wie bereits erwähnt, die Zeit, die über das Wochenende verstrichen ist, ignorieren, erhalten wir überhöhte Koeffizienten. Und wenn wir die Zeit über das Wochenende berücksichtigen, erhalten wir relativ kleinere Koeffizienten. Daher ist es nach unserem derzeitigen Modell möglich, bei der Analyse derselben Daten zwei verschiedene Steigungsberechnungen zu erhalten. Dies ist unerwünscht. Wir würden es vorziehen, wenn unsere Berechnung deterministisch wäre. Das bedeutet, dass unsere Berechnung der Steigung immer die gleiche ist, wenn wir die gleichen Daten analysieren.
Um diese Einschränkungen zu überwinden, möchte ich eine alternative Berechnung vorschlagen. Wir könnten stattdessen die vom Preis gebildete Steigung berechnen, indem wir die Differenz des Eröffnungskurses durch die Differenz des Schlusskurses teilen. Wir haben die Zeit auf der x-Achse ersetzt. Diese neue Menge gibt Aufschluss darüber, wie empfindlich der Schlusskurs auf Veränderungen des Eröffnungskurses reagiert. Wenn der absolute Wert dieser Größe > 1 ist, dann sagt uns das, dass große Veränderungen des Eröffnungskurses nur geringe Auswirkungen auf den Schlusskurs haben. Wenn der absolute Wert der Menge < 1 ist, bedeutet dies, dass kleine Änderungen des Eröffnungskurses große Auswirkungen auf den Schlusskurs haben können. Wenn der Koeffizient der Steigung negativ ist, bedeutet dies, dass sich der Eröffnungs- und der Schlusskurs in entgegengesetzte Richtungen bewegen.
Diese neue Größe hat jedoch ihre eigenen Einschränkungen, von denen eine für uns als Händler besonders interessant ist: Unsere neue Metrik reagiert empfindlich auf Doji-Kerzen. Doji-Kerzen werden gebildet, wenn der Eröffnungs- und der Schlusskurs einer Kerze sehr nahe beieinander liegen. Das Problem wird noch verschärft, wenn wir eine Ansammlung von Doji-Kerzen haben, wie in Abb. 1 unten dargestellt. Im besten Fall könnten diese Doji-Kerzen dazu führen, dass unsere Berechnungen mit 0 oder unendlich bewertet werden. Im schlimmsten Fall kann es jedoch zu Laufzeitfehlern kommen, weil wir versuchen, durch 0 zu dividieren.
Abb. 1: Eine Ansammlung von Doji-Kerzen
Überblick über die Methodik
Wir haben 10 000 Zeilen von M1-Daten des Paares USDZAR analysiert. Die Daten wurden mit Hilfe eines MQL5-Skripts von unserem MetaTrader 5-Terminal abgerufen. Wir haben zunächst die Steigung anhand der zuvor vorgeschlagenen Formel berechnet. Zur Berechnung des Neigungswinkels wurde die Umkehrung der trigonometrischen Funktion tan, arc-tan, verwendet. Die von uns berechnete Menge wies eine miserable Korrelation mit unseren Marktnotierungen auf.
Obwohl unsere Korrelationswerte nicht ermutigend waren, trainierten wir eine Auswahl von 12 verschiedenen KI-Modellen, um den zukünftigen Wert des USDZAR-Wechselkurses anhand von drei Gruppen von Eingabedaten vorherzusagen:
- OHLC-Kurse von unserem MetaTrader 5-Terminal
- Winkel und Neigung, die durch den Preis entstehen
- Eine Kombination aus allen 3.
Unser bestes Modell war die einfache lineare Regression unter Verwendung von OHLC. Es ist jedoch erwähnenswert, dass die Genauigkeit des linearen Modells gleich blieb, als wir die Eingaben von Gruppe 1 auf Gruppe 3 umstellten. Keines der von uns beobachteten Modelle schnitt in Gruppe 2 besser ab als in Gruppe 1. Allerdings schnitten nur 2 der von uns untersuchten Modelle am besten ab, wenn sie alle verfügbaren Daten verwendeten. Die Leistung des Algorithmus von KNeighbors hat sich dank unserer neuen Funktionen um 20 % verbessert. Diese Beobachtung veranlasst uns zu der Frage, welche weiteren Verbesserungen wir erzielen können, wenn wir unsere Daten auf andere Weise sinnvoll transformieren.
Wir haben die Parameter von KNeighbors erfolgreich angepasst, ohne die Trainingsdaten zu übererfüllen, und unser Modell in das ONNX-Format exportiert, um es in unseren KI-gestützten Expert Advisor einzubinden.
Abrufen der benötigten Daten
Das folgende Skript holt die benötigten Daten von unserem MetaTrader 5 Terminal und speichert sie im CSV-Format. Ziehen Sie das Skript einfach per Drag & Drop auf einen beliebigen Markt, den Sie analysieren möchten, und schon können Sie uns folgen.
//+------------------------------------------------------------------+ //| ProjectName | //| Copyright 2020, CompanyName | //| http://www.companyname.net | //+------------------------------------------------------------------+ #property copyright "Gamuchirai Zororo Ndawana" #property link "https://www.mql5.com/en/users/gamuchiraindawa" #property version "1.00" #property script_show_inputs //+------------------------------------------------------------------+ //| Script Inputs | //+------------------------------------------------------------------+ input int size = 100000; //How much data should we fetch? //+------------------------------------------------------------------+ //| On start function | //+------------------------------------------------------------------+ void OnStart() { //--- File name string file_name = "Market Data " + Symbol() +".csv"; //--- Write to file int file_handle=FileOpen(file_name,FILE_WRITE|FILE_ANSI|FILE_CSV,","); for(int i= size;i>=0;i--) { if(i == size) { FileWrite(file_handle,"Time","Open","High","Low","Close"); } else { FileWrite(file_handle,iTime(Symbol(),PERIOD_CURRENT,i), iOpen(Symbol(),PERIOD_CURRENT,i), iHigh(Symbol(),PERIOD_CURRENT,i), iLow(Symbol(),PERIOD_CURRENT,i), iClose(Symbol(),PERIOD_CURRENT,i) ); } } //--- Close the file FileClose(file_handle); } //+------------------------------------------------------------------+
Explorative Datenanalyse
Um unsere Analyse zu beginnen, importieren wir zunächst die benötigten Bibliotheken.
import numpy as np import pandas as pd import seaborn as sns import matplotlib.pyplot as plt
Jetzt werden wir die Marktdaten einlesen.
#Read in the data data = pd.read_csv("Market Data USDZAR.csv")
Unsere Daten sind in der falschen Reihenfolge angeordnet, kehren wir sie um.
#The data is in reverse order, correct that data = data[::-1]
Legen wir fest, wie weit wir in die Zukunft vorausschauen wollen.
#Define the forecast horizon look_ahead = 20
Wenden wir die Berechnung der Steigung an. Leider ergibt die Berechnung der Steigung nicht immer eine reelle Zahl. Dies ist eine der Einschränkungen unseres derzeitigen Algorithmus. Denken Sie daran, dass wir eine Entscheidung darüber treffen müssen, wie wir mit den fehlenden Werten in unserem Datenrahmen umgehen. Vorerst werden alle fehlenden Werte im Datenrahmen gelöscht.
#Calculate the angle formed by the changes in price, using a ratio of high and low price. #Then calculate arctan to realize the angle formed by the changes in pirce data["Slope"] = (data["Close"] - data["Close"].shift(look_ahead))/(data["Open"] - data["Open"].shift(look_ahead)) data["Angle"] = np.arctan(data["Slope"]) data.describe()
Abb. 2: Unser Datenrahmen nach der Berechnung des durch den Preis entstandenen Winkels
Betrachten wir nun die Fälle, in denen unsere Steigungsberechnung auf unendlich ausgewertet wurde.
data.loc[data["Slope"] == np.inf]
Abb. 3: Unsere Aufzeichnungen über unendliche Steigungen stellen Fälle dar, in denen sich der Eröffnungskurs nicht verändert hat
In der folgenden Abbildung 4 haben wir zufällig einen der Fälle ausgewählt, in denen unsere Steigungsberechnung unendlich war. Die Grafik zeigt, dass diese Datensätze Preisschwankungen abbilden, wobei sich der Eröffnungspreis nicht verändert hat.
pt = 1807 y = data.loc[pt,"Open"] plt.plot(data.loc[(pt - look_ahead):pt,"Open"]) plt.axhline(y=y,color="red") plt.xlabel("Time") plt.ylabel("USDZAR Open Price") plt.title("A slope of INF means the price has not changed")
Abb. 3: Zur Visualisierung der Steigungswerte haben wir Folgendes berechnet
Für den Moment werden wir unsere Diskussion vereinfachen, indem wir alle fehlenden Werte weglassen.
data.dropna(inplace=True)
Setzen wir nun den Index unserer Daten zurück
data.reset_index(drop=True,inplace=True)
und zeichnen wir unsere Winkelberechnungen auf. Wie aus Abb. 4 ersichtlich ist, dreht sich unsere Winkelberechnung um 0, was dem Computer ein gewisses Gefühl für die Größenordnung vermitteln kann, denn je weiter wir uns von 0 entfernen, desto größer ist die Veränderung des Preisniveaus.
data.loc[:100,"Angle"].plot()
Abb. 4: Visualisierung der durch Preisänderungen entstehenden Winkel
Versuchen wir nun, das Rauschen in der neuen Eigenschaft, das wir erstellt haben, zu schätzen. Als Rauschen bezeichnen wir die Anzahl der Fälle, in denen der durch den Preis geschaffene Winkel abnahm, das Preisniveau jedoch im gleichen Zeitraum anstieg. Diese Eigenschaft ist unerwünscht, denn im Idealfall wünschen wir uns eine Menge, die im Einklang mit dem Preisniveau steigt und sinkt. Leider bewegt sich unsere neue Berechnung die Hälfte der Zeit im Gleichschritt mit dem Preis, und die andere Hälfte bewegen sie sich unabhängig voneinander.
Um dies zu quantifizieren, haben wir einfach die Anzahl der Zeilen gezählt, in denen die Steigung des Preises zunahm und das künftige Preisniveau abnahm. Diese Zahl wurde dann durch die Gesamtzahl der Fälle geteilt, in denen die Steigung zunahm. Daraus ergibt sich, dass die Kenntnis des zukünftigen Wertes der Steigung der Linie nur sehr wenig über die Veränderungen des Preisniveaus aussagt, die im selben Prognosehorizont eingetreten wären.
#How clean are the signals generated? 1 - (data.loc[(data["Slope"] < data["Slope"].shift(-look_ahead)) & (data["Close"] > data["Close"].shift(-look_ahead))].shape[0] / data.loc[(data["Slope"] < data["Slope"].shift(-look_ahead))].shape[0])
Übersetzt aus dem Englischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/en/articles/16124





- 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.