
MQL5-Assistent-Techniken, die Sie kennen sollten (Teil 57): Überwachtes Lernen mit gleitendem Durchschnitt und dem stochastischen Oszillator
Einführung
Dies ist eine Fortsetzung unseres Blicks auf einfache Muster, die mit dem MQL-Assistenten zusammengestellten Expert Advisors implementiert werden können. In erster Linie geht es dabei immer um die Erprobung von Ideen. Für die spätere Implementierung und die Nutzung des Live-Kontos können manuell zusammengestellte Expert Advisors verwendet werden, nachdem sie über einen längeren Zeitraum getestet wurden. Mit Hilfe von Assistenten zusammengestellte Expert Advisors ermöglichen jedoch schnelle Testläufe mit weniger Vorab-Code.
Maschinelles Lernen ist derzeit in aller Munde, und wir haben einige spezifische Aspekte davon in früheren Artikeln dieser Serie behandelt. Wir werden in diesem und in zukünftigen Artikeln weiterhin auf einige dieser eher technischen Merkmale eingehen, sie werden jedoch im Hintergrund stehen, da wir uns mehr auf die bekannteren und etablierten Indikatormuster konzentrieren werden.
Darüber hinaus werden unsere Artikel im Rahmen des maschinellen Lernens die 3 Hauptzweige des Lernens in jeweils separaten Artikeln in einem Zyklus behandeln. Zu Beginn werden wir uns mit der Überwachung oder dem überwachten Lernen befassen, und unsere Indikatormuster werden aus der Kombination eines Trendindikators und eines Momentum-Indikators bestehen. Wir werden uns mit dem gleitenden Durchschnitt und dem Stochastik-Indikator befassen.
Beim überwachten Lernen versuchen wir, jedes Muster in einem eigenen neuronalen Netz zu implementieren. Diese sind, wie in jüngsten Artikeln dargelegt, in Python besser kodiert und trainiert als MQL5. Die Effizienzgewinne sind unübersehbar. In Python ist es auch problemlos möglich, nach einer Trainingssitzung eine Kreuzvalidierung durchzuführen, und so werden wir diese für jedes Muster durchführen.
Während die Kreuzvalidierung in Python durch den Vergleich des Verlustwerts des Testlaufs mit dem Verlustwert der letzten Trainingsepoche geteilt wird, ist dies allein, obwohl es wichtig ist, unzureichend, um die Kreuzvalidierung der aktuellen Gewichte und Verzerrungen des Netzes zu bewerten.
Wir werden daher im MetaTrader 5-Strategietester mit den exportierten ONNX-Netzwerken Vorwärtstests durchführen. In diesem Beitrag werden die Preise oder x- und y-Datensätze, die vom MetaTrader 5 an Python gesendet werden, um das Training zu beginnen, für das Jahr 2023 für das Paar EUR JPY sein. Daher wird der Vorwärtstest für dasselbe Symbol, aber für das Jahr 2024 erfolgen. Wir führen unsere Analyse im täglichen Zeitrahmen durch.
Die Kombination des gleitenden Durchschnitts (MA) mit dem Stochastik-Oszillator kann eine Vielzahl von Handelssignalen erzeugen. Für unsere Test– und Untersuchungszwecke werden wir nur die 10 besten Signalmuster betrachten, die Händler verwenden können, wenn diese Indikatoren kombiniert werden.
Herangehensweise mit maschinellen Lerntypen
Eine Pipeline für maschinelles Lernen kann als diese 3 miteinander verbundenen Phasen betrachtet werden: Überwachung, Verstärkung und Schlussfolgerung. Lassen Sie uns die Definitionen der einzelnen Begriffe zusammenfassen.
Überwachtes Lernen (auch bekannt als Trainingsphase) – das Modell lernt historische Muster auf der Grundlage von gekennzeichneten Daten (unabhängige oder Eingabedaten, die oft mit x gekennzeichnet sind, und unabhängige Prognosedaten, die ebenfalls oft mit y gekennzeichnet sind).
In der Zwischenzeit kann das Verstärkungslernen (das als Lern- und Optimierungsphase in der Anwendung betrachtet werden kann) als eine Phase betrachtet werden, in der sich das Modell durch die Interaktion mit seiner Umgebung und die Optimierung seiner Aktionen für langfristige Belohnungen selbst verfeinert (fast wie Backpropagation bei einem Vorwärtslauf).
Und schließlich das Inferenz-Lernen (auch bekannt als die Phase des unüberwachten Lernens) – hier verallgemeinert das Modell die Ergebnisse früherer Lernprozesse und wendet das Gelernte auf neue Daten und Probleme an.
Betrachten wir zur Veranschaulichung, wie diese 3 Phasen bei der Bearbeitung verschiedener Problemstellungen miteinander verknüpft werden können. Wir werden Fälle von Wetterinformationssystemen und Finanzzeitreihenvorhersagen betrachten.
Supervision:
Ziel des überwachten Lernens ist es, aus markierten Daten ein Vorhersagemodell zu erstellen. Dieser Prozess umfasst die Erfassung und Vorverarbeitung historischer Daten. Darauf folgt die Merkmalsextraktion, die als eine Form der Normalisierung der historischen Daten auf einen Bereich oder ein Format verstanden werden könnte, das in das neuronale Netz oder das Trainingsmodell eingegeben werden kann. Danach wird das Modell mit LSTMs, XGBoost oder Transformatoren anhand von gelabelten Daten trainiert. Etikettierung bedeutet, dass wir die unabhängigen Daten (Vorläuferdaten, die bekannt sind und für die Vorhersage verwendet werden) und die abhängigen Daten (die Daten, die wir vorhersagen wollen) mit unterschiedlichen Etiketten versehen. Das ursprüngliche Ziel ist hier die Verlustminimierung, d. h. die Differenz zwischen Vorhersage und tatsächlichem Ergebnis soll so gering wie möglich sein, und zwar mithilfe des Gradientenabstiegs.
Beim überwachten Lernen kann die Kreuzvalidierung einbezogen werden, und ihre Ergebnisse können den Einsatz des Modells in vollem Umfang rechtfertigen. Bei den drei Stufen, die wir hier untersuchen, wäre die letzte Stufe des überwachten Lernens die Modellauswahl und die Abstimmung der Hyperparameter, bei der im Wesentlichen die optimale Lernrate und die Größe der Trainingsserie auf der Grundlage der besten Ergebnisse ausgewählt werden. Auch die Architektur hinsichtlich der Aktivierungsarten und sogar der Schichtgrößen wird gewählt, wenn diese Optionen in dieser Trainingsphase getestet wurden.
Zur Veranschaulichung ein Beispiel für ein Wettervorhersagesystem: Die Daten wären vergangene Temperaturen, Luftfeuchtigkeit oder Luftdruck; das Modell könnte ein Random-Forest- oder CNN-basiertes Modell sein; das Ergebnis wäre ein System zur Vorhersage von Temperaturtrends. Bei finanziellen Zeitreihen wären die Prognosedaten historische Preise mit Feature Engineering, um Indikatorwerte zu erhalten; das Modell könnte LSTM sein; Verlustfunktion MSE; und das Ergebnis wäre ein trainiertes Modell, das den nächsten Preis auf der Grundlage vergangener Beobachtungen vorhersagt.
Verstärkung:
Nach der Durchführung des überwachten Lernens, das größtenteils auf markierten historischen Daten beruht, stellt sich die Frage, ob das Modell in der Lage sein wird, auch mit aktuellen oder zukünftigen Daten zu arbeiten. Oder wird sie sich sogar anpassen können, wenn sich die Bedingungen in Zukunft von dem unterscheiden, was sie gelernt hat? Um dies zu beantworten, wird Reinforcement Learning (Verstärkungslernen) eingesetzt. Statische Modelle haben es in dynamischen Umgebungen in der Regel schwer, weshalb Reinforcement Learning dabei hilft, den Entscheidungsprozess in Zukunft zu optimieren.
Das Ziel von RL ist es daher, die Prognosen zu verbessern, indem die Entscheidungsfindung auf der Grundlage von Rückmeldungen optimiert wird. Anders ausgedrückt: Sobald wir, sagen wir, ein neuronales Netz haben, das Preisänderungen vorhersagt, würden wir dann fortfahren, Politik- und Wertnetzwerke zu entwickeln, die in der Lage sind, diese Preisänderungen als Zustände zu nutzen. Wir sind also in einer Position, in der wir mit der Einführung von Zuständen und Handlungen Preisänderungen von Händleraktionen trennen.
Diese Beispiele beziehen sich auf die Vorhersage von Finanzzeitreihen. Ginge es um das Wetter, wie wir es oben dargestellt haben, dann könnten die Zustände und Maßnahmen die Niederschlagsmenge und die Menge der Aussaat bzw. des Anbaus einer wichtigen Kultur sein. Ein greifbareres und erwünschtes Ergebnis der finanziellen Zeitreihenprognose sind häufig Gewinne/Verluste aus Maßnahmen, die im Anschluss an die Prognosen des Netzes getroffen werden. Für unser Wetterbeispiel könnten dies die Erträge der Hauptfrucht sein.
Der zuvor beschriebene RL-Prozess umfasst nicht nur das Training und die Aktualisierung des Kritiker-Netzwerks, damit wir unsere Gewinn-/Verlustposition besser antizipieren können, sondern liefert auch Deltas, die eine weitere Feinabstimmung der Gewichte und Verzerrungen des Politik-Netzwerks ermöglichen.
Der RL-Prozess umfasst folgende Schritte: Agent-Umwelt-Setup, in dem Zustände, Aktionen und Belohnungen definiert werden. Wie bereits erwähnt, würden diese aus dem in der Überwachungsphase trainierten Modell fließen oder bestimmt werden (wie in den Abbildungen oben gezeigt). Dann gibt es noch das Politik-Lernen, bei dem ein Akteursnetzwerk oder ein gleichwertiger Algorithmus optimiert wird, um Zustände den erforderlichen Aktionen zuzuordnen. Außerdem ein belohnungsbasierter Optimierungsmechanismus, der die Form eines Wertalgorithmus oder eines kritischen Netzes annehmen kann, das die Vorhersagen auf der Grundlage der langfristigen Rentabilität anpasst. Und schließlich ein Agent, der ein Gleichgewicht zwischen Exploration (das Ausprobieren verschiedener politischer Einstellungen mit dem Ziel, etwas Neues zu lernen) und Exploitation (das Festhalten an dem, was in der Vergangenheit gut funktioniert hat) herstellt.
Anhand von Beispielen können wir zeigen, was hier mit Wetter- und Finanzprognosen wie oben in der Überwachungsphase geschieht. Bei der Wettervorhersage in der Überwachungsphase sagt das anfängliche Modell die Niederschläge auf der Grundlage von Temperatur, Luftfeuchtigkeit usw. voraus und gibt die von uns gesuchten prognostizierten Niederschläge aus. Da diese Niederschlagsmenge entscheidend dafür ist, ob wir unsere Pflanzen anbauen sollten, führt RL eine Entscheidungsebene der Interpretation ein. Die Ausgabe der Regenvorhersage wird in Zustände gegossen. Wenn diese Zustände unterschiedliche Niederschläge in verschiedenen Regionen oder zu verschiedenen Zeitpunkten vorhersagen, kann ihre Interpretation bei der Entscheidung, ob gepflanzt werden soll, auf eine Belohnung hin optimiert werden, die in diesem Fall der Ernteertrag wäre. Das Ergebnis wäre ein Vorhersagemodell, das sich in Reaktion auf reale Wetterveränderungen selbst verbessert. Wenn also die Betreuungsphase die Schule war, dann ist die Verstärkung die Ausbildung am Arbeitsplatz.
Für die Finanzprognose hätten wir in der Überwachungsphase Preisänderungen aus dem Modell prognostiziert, das als unser Zustand fungiert. Diese Veränderungen können immer noch ein mehrdimensionaler Vektor sein, wenn sie zum Beispiel mehr als einen Zeitrahmen umfassen. Die Aktionen sind die, die der Händler oder der Expert Advisor durchführt, d.h. entweder kaufen, verkaufen oder neutral bleiben. Auf der Grundlage der für jeden Zustand ergriffenen Maßnahmen (Preisänderungen) würden wir dann durch ein kritisches Netzwerk oder einen Algorithmus die Zustände und Maßnahmen auf die erwarteten Gewinne für jeden Zustand abbilden. Danach kann die Strategie (Zuordnung von Zuständen zu Aktionen) schrittweise aktualisiert werden, indem ein Gleichgewicht zwischen Exploration und Nutzung hergestellt wird, um die Ergebnisse des Modells in der Überwachungsphase (die wir als Zustände darstellen) besser zu interpretieren.
Dieses Training-On-The-Job bedeutet jedoch, dass es standardmäßig sehr langsam erfolgt, da die Live-Daten nur in einem sehr lauwarmen Tempo durchsickern. Wenn Sie also ein überwachtes Training über einen Zeitraum von 10 Jahren durchgeführt haben, würde ein Verstärkungstraining über einen Zeitraum von 1 Jahr auf dem Papier auch 1 Jahr dauern! Daher ist eine Simulation oder eine aufwändigere Umweltklasse erforderlich.
Indem wir die Bedingungen von Live-Daten auf einem Satz historischer Daten simulieren, beschleunigen wir nicht nur das Tempo des Reinforcement Learning, sondern decken auch viel mehr Daten ab, was uns belastbarere Modelle liefern sollte.
Für die Vorhersage von Finanzreihen bedeutet dies, dass wir Testläufe mit denselben Daten durchführen können, die wir in der Überwachungsphase verwendet haben, aber jetzt die RL-Netze für den Gewinn optimieren, indem wir uns auf die Maßnahmen stützen, die aufgrund der Zustandsvorhersagen (oder Preisänderungen) ergriffen werden, die mit dem Netz in der Überwachungsphase gemacht wurden.
Schlussfolgerung:
Nachdem wir zwei Modelle erhalten haben, eines für die Erstellung der Basisprognosen (beim überwachten Lernen) und eines für die bessere Interpretation und Anwendung dieser Prognosen (beim verstärkten Lernen), kommen wir zur dritten Phase, der Inferenz, in der wir im Wesentlichen dieses Wissen und diese Modelle auf einen anderen Bereich oder, wie in unserem Fall, auf ein anderes Handelssymbol anwenden.
Dies wird auch als Verallgemeinerung auf ungesehene Daten bezeichnet. Die Anwendung von gelerntem Wissen in realen Umgebungen, die Verfeinerung des Wissens im Laufe der Zeit und die Erkennung von unbekannten Mustern ohne die Verwendung von Etiketten in den Daten. Graphen und Auto-Encoder spielen in dieser Phase eine sehr wichtige Rolle, ebenso wie das Clustering.
In diesen 3 Phasen wird die Überlastung der Rechner mit jedem weiteren Schritt verringert. Das wiederum ist im Grunde genommen die Rechtfertigung für diese Phasen. Methoden, die unüberwachtes Lernen einsetzen, wurden bisher in dieser Serie behandelt, aber ich werde sie vielleicht bald wieder aufgreifen, um zu sehen, wie sie das Verstärkungslernen fortsetzen können. Auch wenn RL bei der Vorhersage eigenständig eingesetzt werden kann, soll in diesen Phasen deutlich gemacht werden, dass es effizienter sein kann, es zusammen mit anderen Lernmethoden einzusetzen.
Die Kombination des gleitenden Durchschnitts (MA) mit dem Stochastik-Oszillator kann eine Vielzahl von Handelssignalen erzeugen. Wir untersuchen die 10 wichtigsten Signalmuster, die sich aus der Kombination dieser Indikatoren ergeben und von Händlern genutzt werden können.
Kreuzen der gleitenden Durchschnitte + Stochastic überkauft/überverkauft
Dieses Muster, das sich aus der Kombination eines Trendfolgeindikators (MA) und eines Momentum-Oszillators (der Stochastik) ergibt, liefert in der Regel Setups mit hoher Wahrscheinlichkeit. Das Kaufsignal ist ein Aufwärtskreuzen (bei dem der schnelle MA über den langsamen MA kreuzt), um einen potenziellen Aufwärtstrend zu bestätigen, während der Stochastik-Oszillator unter 20 liegt. Dies deutet in der Regel darauf hin, dass der Vermögenswert überverkauft ist und der Kurs bereit für eine Umkehr ist. Das Verkaufssignal ist umgekehrt ein Abwärts-Kreuzen. Dies deutet darauf hin, dass der Quick MA den Lagging MA von oben nach unten kreuzt, was an sich schon ein potenzieller Abwärtstrendindikator ist. Da dies auch durch den Stochastik untermauert wird, der über der 80er-Marke liegt, was ein Zeichen für überkaufte Bedingungen ist, handelt es sich um ein starkes Verkaufssignal.
Mit unserem leicht veränderten Signalklassenformat, bei dem wir Indikatorwerte als Merkmale für Netze verwenden, haben wir nun eine Solomusterfunktion, die wir wie folgt kodieren:
//+------------------------------------------------------------------+ //| Check for Pattern. | //+------------------------------------------------------------------+ double CSignal_MA_STO::IsPattern(int Index, ENUM_POSITION_TYPE T) { vectorf _x = Get(Index, m_time.GetData(X()), m_close, m_ma, m_ma_lag, m_sto); vectorf _y(1); _y.Fill(0.0); ResetLastError(); if(!OnnxRun(m_handles[Index], ONNX_NO_CONVERSION, _x, _y)) { printf(__FUNCSIG__ + " failed to get y forecast, err: %i", GetLastError()); return(double(_y[0])); } //printf(__FUNCSIG__+" y: "+DoubleToString(_y[0],2)); if(T == POSITION_TYPE_BUY && _y[0] > 0.5f) { _y[0] = 2.0f * (_y[0] - 0.5f); } else if(T == POSITION_TYPE_SELL && _y[0] < 0.5f) { _y[0] = 2.0f * (0.5f - _y[0]); } return(double(_y[0])); }
Wir fügen eine Datei „57_X.mqh“ bei, die eine Funktion zum Abrufen der Werte des gleitenden Durchschnitts und die Stochastik enthält, die als Inputs für unsere Netzwerke dienen. Wir ziehen bis zu 10 verschiedene Muster in Betracht. Das bedeutet, dass wir bis zu 10 verschiedene Netze nutzen werden. Unsere Funktion in dieser Include-Datei, „Get“, wird daher auch bis zu 10 verschiedene Datensätze zurückgeben, einen für jedes Netzwerk.
„Get“ gibt einen Vektor vom Typ float (vectorf) zurück, den wir leicht in ein ONNX-Netzwerk eingeben können. Dieselbe Funktion kann als Alternative zur MetaTrader 5-Importbibliothek in Python verwendet werden, die eine Normalisierung des Preises in ein ähnliches Format wie das hier angebotene erfordern würde, bevor das Netzwerk es als Eingabe verwenden kann. Unser Netzwerk in Python wird einfach sein und kann wie folgt kodiert werden:
class SimpleNeuralNetwork(nn.Module): def __init__(self): super(SimpleNeuralNetwork, self).__init__() self.fc1 = nn.Linear(feature_size, 256) # Input layer to hidden layer 1 self.fc2 = nn.Linear(256, 256) # Hidden layer 1 to hidden layer 2 self.fc3 = nn.Linear(256, state_size) # Hidden layer 2 to output layer self.sigmoid = nn.Sigmoid() def forward(self, x): x = self.sigmoid(self.fc1(x)) # Activation for hidden layer 1 x = self.sigmoid(self.fc2(x)) # Activation for hidden layer 2 x = self.fc3(x) # Output layer (no activation) return x
Die Parameter „feature_size“ und „state_size“ sind die Eingangs- und Ausgangsgrößen unseres Netzes. Die Ausgabe wird für alle 10 Muster einheitlich sein, da wir einen Wert im Bereich von 0,0 bis 1,0 anstreben. Alles, was unter 0,5 liegt, wird als prognostizierte negative Veränderung interpretiert, alles über 0,5 als positiv und 0,5 als unverändert.
Bei der Festlegung der Merkmale werden jedoch keine Standardvektorgrößen für die Eingabe verwendet, da jedes Muster eine unterschiedliche Anzahl von Bedingungen haben kann. Bei diesem Muster, unserem ersten, sind es 4. Daher weisen wir dem Netz den Eingangsvektor in der Funktion „Get“ wie folgt zu.
if(Index == 0) { if(CopyBuffer(M.Handle(), 0, T, 2, _ma) >= 2 && CopyBuffer(M_LAG.Handle(), 0, T, 2, _ma_lag) >= 2 && CopyBuffer(S.Handle(), 0, T, 1, _sto_k) >= 1) { _v[0] = ((_ma_lag[1] > _ma[1] && _ma_lag[0] < _ma[0]) ? 1.0f : 0.0f); _v[1] = ((_sto_k[0] <= 20.0) ? 1.0f : 0.0f); _v[2] = ((_sto_k[0] >= 80.0) ? 1.0f : 0.0f); _v[3] = ((_ma_lag[1] < _ma[1] && _ma_lag[0] > _ma[0]) ? 1.0f : 0.0f); } }
Die Bedingungen für das Aufwärts-Muster sind 2, eine für jeden Indikator, und das gleiche gilt für das Abwärts-Muster. Bei der Festlegung des Eingangsvektors wird einfach geprüft, ob jede der Bedingungen erfüllt ist. Da diese Bedingungen spiegelbildlich oder boolesch sind, können maximal 2 Bedingungen gleichzeitig erfüllt sein.
Dennoch sind alle in dem Vektor aufgeführt, da dies für das Netz aufschlussreich sein könnte. Außerdem könnten diese 4 Bedingungen im Fall von Muster-0 weiter in 6 aufgeteilt werden, da die erste Bedingung 2 Argumente sowie die 4. benötigt. Der Leser kann damit experimentieren, da diese Quelle am Ende des Artikels beigefügt ist.
Ein Trainings– und Testlauf in Python protokolliert die folgenden Verlustwerte für beide Läufe:
Epoch 10/10, Train Loss: 0.2498
Test Loss: 0.2593
Der Testverlustwert ist kleiner als der Anfangsverlustwert für die 1. Epoche (nicht angegeben), aber immer noch größer als der Verlustwert der zehnten Epoche. Die für Training und Validierung verwendeten Preisdaten beziehen sich ausschließlich auf das Jahr 2023. Wir versuchen daher, einen Vorwärtstest für das Jahr 2024 durchzuführen, nachdem wir für Muster-0 im Jahr 2023 geeignete Schwellenwerte für Öffnen/Schließen und Muster festgelegt haben. Daraus ergibt sich der folgende Bericht.
Wir gehen, wenn auch nur mit Kaufpositionen. Ein Training mit größeren Datensätzen ist notwendig, um zu sehen, ob ein solcher Weg auch mit kurzen Handelsgeschäfte möglich ist. Außerdem werden bei diesem Vorwärtstest Trainingsgewichte über einen Zeitraum von 80 % des Jahres 2023 verwendet, nicht über das gesamte Jahr. Sie gelten jedoch für das gesamte Jahr 2024.
Kurs kreuzt MA + Stochastic bestätigt Trend
Unser nächstes Muster verwendet die Logik des Kreuzens der Kurse des MAs und die Richtung des Stochastik, um die Kauf- und Verkaufs-Bedingungen festzulegen. Ein Kaufsignal liegt vor, wenn der Kurs den gleitenden Durchschnitt überschreitet und die Stochastik %K den %D kreuzt oder darüber liegt. Ein Verkaufssignal wäre also, wenn der Kurs unter den gleitenden Durchschnitt fällt und der %K unter dem %D liegt.
Sobald die Preisdaten importiert und so formatiert sind, dass sie in unser Netzwerk eingegeben werden können, sieht der Eingabevektor ähnlich aus wie die Ausgabe unserer „Get“-Funktion (siehe unten):
else if(Index == 1) { if(C.GetData(T, 2, _c) >= 2 && CopyBuffer(M.Handle(), 0, T, 2, _ma) >= 2 && CopyBuffer(S.Handle(), 0, T, 2, _sto_k) >= 2 && CopyBuffer(S.Handle(), 1, T, 2, _sto_d) >= 2) { _v[0] = ((_c[1] < _ma[1] && _c[0] > _ma[0]) ? 1.0f : 0.0f); _v[1] = ((_sto_k[1] < _sto_d[1] && _sto_k[0] > _sto_d[0]) ? 1.0f : 0.0f); _v[2] = ((_sto_k[1] > _sto_d[1] && _sto_k[0] < _sto_d[0]) ? 1.0f : 0.0f); _v[3] = ((_c[1] > _ma[1] && _c[0] < _ma[0]) ? 1.0f : 0.0f); } }
Wir verwenden die Größe 4, aber es gibt insgesamt mehr als 4 Bedingungen, da, wie oben erwähnt, einige Bedingungen mehr als 1 benötigen. In diesem Fall benötigen alle 4 Bedingungen 2 Argumente, was bedeutet, dass wir eine Eingabe der Größe 8 für das Netz hätten verwenden können.
Das Training des Netzes erfolgt über die Funktion Train (siehe unten):
# Train function def Train(model, train_loader, optimizer, loss_fn, epochs): device = T.device('cuda:0' if T.cuda.is_available() else 'cpu') model.to(device) for epoch in range(epochs): model.train() train_loss = 0.0 for batch_idx, (data, target) in enumerate(tqdm(train_loader, desc=f"Epoch {epoch + 1}/{epochs} (Train)")): # Step 1: Ensure proper tensor dimensions data = data.view(-1, 1, feature_size) # Step 2: Verify dimensions expected_shape = [feature_size] actual_shape = list(data.shape[2:]) if actual_shape != (expected_shape): raise RuntimeError(f"Invalid spatial dimensions after reshaping. Got {data.shape[2:]}, expected {[x_data.shape[1]]}") # Step 3: Move to device and forward pass data, target = data.to(device), target.to(device) optimizer.zero_grad() output = model(data) target = target.view(-1, 1, state_size) loss = loss_fn(output, target) # Step 4: Backpropagation loss.backward() optimizer.step() train_loss += loss.item() train_loss /= len(train_loader) print(f"Epoch {epoch + 1}/{epochs}, Train Loss: {train_loss:.4f}")
Train verwendet das Jahr 2023 präsentieren sich mit den folgenden Verlustfunktionsprotokollen:
Epoch 10/10, Train Loss: 0.2491
Test Loss: 0.2592
Ein Blick in die Zukunft für das Jahr 2024 ergibt folgenden Bericht:
Wir erhalten eine vielversprechende Vorwärtstest, die jedoch im Vergleich zu den Kaufpositionen etwas zu wenige Verkaufspositionen aufweist. Weitere Schulungen sollten dies beheben. Dieses Muster erfasst frühe Trendbewegungen, da das Ziel der Preis ist, der den MA kreuzt, was einen Trendwechsel signalisieren könnte und weniger als 2 MAs, die sich kreuzen, verzögern sollte, wie wir in Muster-0 gesehen haben. Außerdem werden viele falsche Ausbrüche herausgefiltert, da die Stochastik als Bestätigung verwendet wird, was dazu beiträgt, vorzeitige Abschlüsse zu vermeiden.
Auch dieses Muster hat seine Schwächen und Beschränkungen. Erstens kann die nachlaufende Natur des MA, insbesondere wenn längere Periodenlängen verwendet werden, den Einstieg in den Handel verzögern. Wir verwenden standardmäßig eine Periodenlänge von 8 für den Tages-Zeitrahmen, aber dies ist ein optimierbarer Parameter für die nutzerdefinierte Signalklasse, sodass der Leser eine Feinabstimmung vornehmen kann, um das zu erreichen, was funktioniert. Zweitens ist der Stochastik-Oszillator dafür berüchtigt, dass er sehr unruhig ist, insbesondere bei schwankenden Märkten. Dies kann zu einer Vielzahl von Fehlbestätigungen führen. In Situationen, in denen sich ein Vermögenswert bereits in einem starken Trend befindet, könnte das Warten auf ein Kreuzen des MA zu vielen verpassten frühen Einstiegen führen.
Was die Optimierung der Indikatorperioden anbelangt, so wird ein schneller MA im Bereich unter 20 Perioden zwangsläufig schneller auf Preisänderungen reagieren als beispielsweise ein längerer Zeitraum im Bereich von 50 bis 200. Die Nutzer müssen also den Zeitrahmen berücksichtigen, den sie nutzen, um zu entscheiden, ob sie schnelle Reaktionen wünschen oder Stabilität und mehr Sicherheit, bevor sie Änderungen akzeptieren.
Auch für die Stochastik (5,3,3) bietet schnellere Einstellungen, aber die erzeugten Signale sind zwangsläufig verrauscht. Langsamere Einstellungen wie z. B. (14,5,5) könnten als angemessener erachtet werden, aber auch dies ist etwas, das man zusammen mit dem Zeitrahmen, den man verwendet, in Betracht ziehen sollte. In der nutzerdefinierten Signalklasse, die wir für diese Tests verwenden, haben wir eine Standardindikatorperiode für den gleitenden Durchschnitt und den Stochastik-Oszillator verwendet. Diese sind anpassbar, aber zur Veranschaulichung, wenn unsere MA-Periode N ist, dann wird der stochastische Oszillator (N,3,3) und der langsame oder nachlaufende MA 2 x N sein.
Volumenspitzen können auch zur weiteren Bestätigung eines Kreuzens der MA oder der Stärke eines Ausbruchs verwendet werden. Unterstützungs- und Widerstandsniveaus können ebenfalls verwendet werden, um die Zuverlässigkeit des Musters weiter zu erhöhen.
Steigung des gleitenden Durchschnitts + Stochastic Trendbestätigung
Dieses Muster konzentriert sich auf die Trendrichtung durch die Verwendung der MA-Steigung, während das Momentum durch den Stochastic bestätigt wird. Ein Kaufsignal liegt vor, wenn der gleitende Durchschnitt aufwärts tendiert UND die Stochastik über 50 und steigend ist. Das Verkaufssignal ist das Gegenteil. Der gleitende Durchschnitt ist abwärts gerichtet, während die Stochastik unter 50 liegt und fällt. Auf diese Weise ruft unsere „Get“-Funktion einen Eingabevektor ab, der auf diese Bedingungen überprüft:
else if(Index == 2) { if(C.GetData(T, 2, _c) >= 2 && CopyBuffer(M.Handle(), 0, T, 2, _ma) >= 2 && CopyBuffer(S.Handle(), 0, T, 2, _sto_k) >= 2) { _v[0] = ((_ma[1] < _ma[0]) ? 1.0f : 0.0f); _v[1] = ((_sto_k[1] < _sto_k[0] && _sto_k[1] >= 50.0) ? 1.0f : 0.0f); _v[2] = ((_sto_k[1] > _sto_k[0] && _sto_k[1] <= 50.0) ? 1.0f : 0.0f); _v[3] = ((_ma[1] > _ma[0]) ? 1.0f : 0.0f); } }
Dies ist das erste der 10 Muster, bei denen wir den zweiten stochastischen Puffer alias %K verwenden. Er hinkt dem Hauptpuffer (%D) immer hinterher und seine Verwendung hier hilft, die Neigung des Oszillators zu bestätigen. Sobald die Vektoren dieser Daten für das Jahr 2023 für EUR und JPY in Python exportiert sind, trainieren wir das oben genannte einfache Netzwerk mit der ebenfalls oben genannten Funktion „Train“. Das Testen oder die Kreuzvalidierung würde von einer Funktion durchgeführt werden, die unserer obigen Funktion „Train“ sehr ähnlich ist und die wir als „Test“-Funktion bezeichnet haben. Sein Python-Listing lautet wie folgt:
# Test function def Test(model, test_loader, optimizer, loss_fn, epochs): device = T.device('cuda:0' if T.cuda.is_available() else 'cpu') model.to(device) with T.no_grad(): test_loss = 0.0 for batch_idx, (data, target) in enumerate(tqdm(test_loader, desc=f"Loss at {test_loss} in (Test)")): # Step 1: Ensure proper tensor dimensions data = data.view(-1, 1, feature_size) ... # Step 3: Move to device and forward pass data, target = data.to(device), target.to(device) optimizer.zero_grad() output = model(data) target = target.view(-1, 1, 1) #print(f"target: {target.shape}, plus output: {output.shape}") loss = loss_fn(output, target) test_loss += loss.item() test_loss /= len(test_loader) print(f"Test Loss: {test_loss:.4f}")
Die Vergleichswerte für Training- und Testverluste entsprechen dem, was oben für die Muster-0 und -1 mitgeteilt wurde, und werden daher hier nicht veröffentlicht. Ein Vorwärtstest für das Jahr 2024 im Strategietester von MetaTrader liefert uns den folgenden Bericht:
Unser Muster ist in der Lage, einen steigenden Spaziergang zu geben, da nur Käufe stattfinden. Das Training auf größeren Datensätzen sollte dieses Problem lösen. Muster-2 ist jedoch ein guter Filter für schwankende Märkte. Die MA-Steigung stellt sicher, dass nur dann gehandelt wird, wenn ein klarer Trend vorliegt. Die Bestätigung der Trendstärke erfolgt dann durch den Stochastik Oszillator, da die relative Position zum Schwellenwert von 50 das Momentum des vorherrschenden Trends bestätigt. Im Großen und Ganzen gibt es auch eine Verringerung der Verzögerung, da man nicht wie bei den obigen Mustern auf MA-Überkreuzungen warten muss. Das bedeutet, dass dieses Muster ein gutes Zeichen für eine Trendbeschleunigung ist.
Zu seinen Hauptschwächen gehört die langsame Reaktion auf Trendumkehrungen, da die Neigung eines gleitenden Durchschnitts nach einer Trendumkehr eine gewisse Zeit brauchen kann, um sich zu verschieben oder zu verändern. Auch die Stochastik kann in diesen Situationen dazu neigen, späte Signale zu geben. Wenn ein Trend bereits im Gange ist, kann das Warten auf die Bestätigung des Stochastiks dazu führen, dass ein früher Einstieg verpasst wird. Im Allgemeinen ist dieses Muster auch für Seitwärtsmärkte ungeeignet, da es stark von Trends abhängt.
Die Kombination mit zusätzlichen Filtern wie dem ADX (Average Directional Index) kann helfen, starke Trends zu bestätigen. Auch die Überprüfung auf Preisausbrüche oder Rücksetzer sollte die Genauigkeit verbessern. Praktische Anwendungsfälle könnten Forex sein (was wir hier testen), oder Aktien, da dieses Muster helfen kann, Fortsetzungstrends nach kleinen Rückschritten zu erkennen, oder Kryptowährungen und Rohstoffe, da es nützlich ist, um durch Momentum ausgelöste Bewegungen in Vermögenswerten wie Gold oder Bitcoin zu erkennen.
Abprall vom MA mit stochastischer Divergenz
Dieses Muster funktioniert durch die Kombination der dynamischen Unterstützungen/Widerstände des gleitenden Durchschnittspreises mit der Momentum-Divergenz des Stochastik-Oszillators, um potenzielle Umkehrungen zu erkennen, bevor sie eintreten. Ein Kaufsignal liegt vor, wenn der Kurs von einem steigenden MA abprallt (der in diesem Fall als Unterstützung fungieren würde) und der Stochastik-Oszillator eine Aufwärts-Divergenz aufweist, d. h. der Kurs ein niedrigeres Tief erreicht, während der Oszillator ein höheres Tief erreicht.
Ein Verkaufssignal liegt vor, wenn der Kurs einen abwärts gerichteten MA, der als Widerstand wirkt, zurückweist und der Stochastik-Oszillator eine rückläufige Divergenz anzeigt, bei der der Kurs ein höheres Hoch, die Stochastik aber ein niedrigeres Hoch erreicht. Die Implementierung in MQL5 und die Definition des Inputs für das Netz, das dieses Muster verarbeitet, wird wie folgt gehandhabt:
else if(Index == 3) { _v.Init(6); _v.Fill(0.0); if(C.GetData(T, 3, _c) >= 3 && CopyBuffer(M.Handle(), 0, T, 3, _ma) >= 3 && CopyBuffer(S.Handle(), 0, T, 3, _sto_k) >= 3) { _v[0] = ((_c[2] > _c[1] && _c[1] < _c[0] && _c[0] < _c[2] && _ma[1] >= _c[1]) ? 1.0f : 0.0f); _v[1] = ((_sto_k[2] > _sto_k[1] && _sto_k[1] < _sto_k[0] && _sto_k[1] >= 40.0) ? 1.0f : 0.0f); _v[2] = ((_ma[2] > _ma[0]) ? 1.0f : 0.0f); _v[3] = ((_ma[2] < _ma[0]) ? 1.0f : 0.0f); _v[4] = ((_sto_k[2] < _sto_k[1] && _sto_k[1] > _sto_k[0] && _sto_k[1] <= 60.0) ? 1.0f : 0.0f); _v[5] = ((_c[2] < _c[1] && _c[1] > _c[0] && _c[0] > _c[2] && _ma[1] <= _c[1]) ? 1.0f : 0.0f); } }
Die Werte der Verlustfunktion für die Trainings– und Testvalidierung unterscheiden sich nicht sehr von den Logs der ersten beiden Muster, deren Logs gemeinsam genutzt wurden. Die Testverlustfunktion ist kleiner als die Verlustfunktion aus dem Training bei der ersten Epoche, aber sie ist immer noch kleiner als die Verlustfunktion bei der zehnten Epoche. Ein Bericht über das Jahr 2024, nach der Ausbildung im Jahr 2023, sieht wie folgt aus
Ein positiver Vorwärtstest ist immer ein gutes Zeichen, vorausgesetzt, dass sowohl Kauf- und Verkaufs-Positionen in ausgewogener Weise eröffnet werden. Dies ist hier nicht der Fall. Muster-3 eignet sich jedoch gut für die frühzeitige Erkennung von Umkehrbewegungen, da die Stochastik-Divergenz in der Regel Trendumkehrungen signalisiert, bevor der Kurs reagiert. Außerdem wird vermieden, dem Trend hinterherzujagen, sodass Händler, anstatt spät einzusteigen, in der Nähe des dynamischen Unterstützungs-/Widerstandsniveaus einsteigen. Es eignet sich auch gut für Märkte, die sich in einem Trend befinden, da der Anstieg des MA den Trend bestätigen würde, während die Divergenz vor einer Erschöpfung warnt.
Schwächen und Beschränkungen sind seine falschen Signale, wenn die Märkte stark tendieren. Denn in diesen Situationen reicht eine Divergenz allein oft nicht aus, um eine Umkehr zu bewirken. Weitere Nachteile sind der nachlaufende MA-Effekt, da der MA-Bounce nicht immer perfekt mit dem Zeitpunkt der Divergenz übereinstimmt, und die Notwendigkeit einer Bestätigung zur Verbesserung der Genauigkeit.
Muster-3 kann durch die Kombination mit Kerzen-Mustern (wie Pin Bars oder Engulfing Bars) auf MA-Ebene optimiert werden, um das Setup zu verstärken. Auch Volumenspitzen können zur Bestätigung einer Divergenz herangezogen werden.
MA als dynamischer Unterstützung/Widerstand + Kreuzen der Stochastic
Unsere Muster-4-Strategie ist eine Mischung aus Trendfolge (bei Verwendung von MA für die Richtung sowie Unterstützung/Widerstand) und Momentum-Bestätigung (die durch Überprüfung auf Stochastik-Kreuz erfolgt), um brauchbare Kauf– und Verkaufssignale zu erzeugen.
Ein Kaufsignal liegt vor, wenn sich der Kurs über einem aufwärts gerichteten MA hält und die Stochastik %K über dem %D kreuzt. Dieses Aufwärts-Muster trägt dazu bei, eine Reihe von wichtigen Voraussetzungen für eine Kaufposition zu schaffen. Erstens dient es als Trendbestätigung, da ein aufwärts gerichteter MA sicherstellt, dass die platzierten Handelsgeschäfte mit der vorherrschenden Marktrichtung übereinstimmen.
Zweitens bietet das Kreuzen die Stochastik einen auf das Momentum abgestimmten Einstiegszeitpunkt. Dies liegt daran, dass eine Verschiebung der Dynamik häufig einen erneuten Kaufdruck bestätigt. Voreilige Einstiege bei jeder MA-Berührung werden vermieden, da das Kreuzen die Stochastik sicherstellt, dass vor dem Kauf ein Momentum vorhanden ist. Falsche Signale werden somit reduziert. Ein möglicher Nachteil ist, dass er frühe Ausbrüche verpassen kann, da er beide Bedingungen abwartet, was leicht zu verzögerten Einstiegen führt.
Ein Verkaufssignal liegt vor, wenn der Kurs unter einem abwärts gerichteten gleitenden Durchschnitt bleibt und die Stochastik %K unter den %D kreuzt. Dieser bietet ähnlich wie sein Aufwärts-Pendant eine Trendbestätigung, ist ein momentumbasierter Ein– oder Ausstieg, es gibt keine verfrühten Einstiege, und schwache Signale werden herausgefiltert. Ein potenzieller Nachteil ist, dass der Kurs in unruhigen Märkten den MA durchbrechen kann, bevor er seine Abwärtsbewegung wieder aufnimmt. Dies ist besonders wichtig, da bei den meisten Handelssymbolen der Abwärtstrend volatiler ist als der Aufwärtstrend. Wir implementieren dies wie folgt in MQL5:
else if(Index == 4) { if(C.GetData(T, 2, _c) >= 2 && CopyBuffer(M.Handle(), 0, T, 2, _ma) >= 2 && CopyBuffer(S.Handle(), 0, T, 2, _sto_k) >= 2 && CopyBuffer(S.Handle(), 1, T, 2, _sto_d) >= 2) { _v[0] = ((_sto_k[1] < _sto_d[1] && _sto_k[0] > _sto_d[0]) ? 1.0f : 0.0f); _v[1] = ((_ma[1] < _c[1] && _ma[0] < _c[0] && _ma[1] < _ma[0]) ? 1.0f : 0.0f); _v[2] = ((_ma[1] > _c[1] && _ma[0] > _c[0] && _ma[1] > _ma[0]) ? 1.0f : 0.0f); _v[3] = ((_sto_k[1] > _sto_d[1] && _sto_k[0] < _sto_d[0]) ? 1.0f : 0.0f); } }
Wir weisen den Eingangsvektor dem Netzwerk zu, das dieses Muster verarbeitet, in 4 Dimensionen. Wie bei früheren Mustern oben gezeigt, kann dieser Vektor expliziter gestaltet werden, indem jedes der Argumente innerhalb einer Bedingung als Teil der Eingaben dargestellt wird. Ein Vorwärtslauf für das Netz, das nur auf Muster-4 trainiert wurde, ergibt folgende Ergebnisse:
Dieses Muster sollte in trendfolgenden Märkten in Ordnung sein, wird aber in Szenarien, in denen die Spanne begrenzt ist, Probleme bereiten. Obwohl wir einen günstigen Vorwärtstest haben, ist es wichtig, mit größeren Datensätzen zu testen, um sicherzustellen, dass wir sowohl Kauf- als auch Verkaufspositionen platzieren können, und nicht nur die Kaufpositionen, wie oben berichtet.
Stochastic überkauft/überverkaufte Umkehr nahe MA
Muster-5 verbindet Trendfolge mit dem MA als dynamische Unterstützung/Widerstand und Momentum-Umkehr mit der Stochastik. Ein Kaufsignal liegt vor, wenn die Stochastik den Schwellenwert von 20 übersteigt, während der Kurs durch den MA unterstützt wird. Dieses Muster bietet eine dynamische Unterstützungsvalidierung, da der MA als Unterstützungszone fungiert und sicherstellt, dass der Preis innerhalb eines bestehenden Aufwärtstrends abprallt. Das Überschreiten der 20er-Marke durch den Stochastic deutet ebenfalls darauf hin, dass das Abwärts-Momentum nachlässt und die Käufer auf den Markt kommen. Die Verwendung von zwei Indikatoren vermeidet nicht nur einen verfrühten Einstieg, sondern stellt auch ein Setup mit hoher Wahrscheinlichkeit dar. Der potenzielle Nachteil besteht darin, dass sich der Kurs in starken Abwärtstrends vorübergehend am MA halten kann, bevor er nach unten ausbricht.
Ein Verkaufssignal liegt vor, wenn die Stochastik unter 80 kreuzt, während sich der Kurs nahe dem Widerstand eines abwärts gerichteten gleitenden Durchschnitts befindet. Dies dient auch als dynamische Widerstandsvalidierung, da der MA als Widerstandszone fungiert, die als Beweis dafür dient, dass der Preis nicht höher gestiegen ist. Die überkaufte Reversal Confirmation deutet auf ein nachlassendes Aufwärts-Momentum hin und darauf, dass die Verkäufer im Kommen sind. Auch hier gilt, dass die Verwendung von zwei Indikatoren verfrühte Ausstiege/Einstiege vermeidet und schwache Pullbacks herausfiltert. Ein potenzieller Nachteil des Abwärts-Signals von Muster-5 ist, dass sich der Kurs bei starken Abwärtstrends oberhalb des MA konsolidieren kann, bevor er nach unten ausbricht, was zu späten Ausstiegen oder verpassten Pips führen kann.
Wir implementieren dies wie folgt in MQL5:
else if(Index == 5) { if(C.GetData(T, 3, _c) >= 3 && CopyBuffer(M.Handle(), 0, T, 3, _ma) >= 3 && CopyBuffer(S.Handle(), 0, T, 2, _sto_k) >= 2) { _v[0] = ((_sto_k[1] < 20.0 && _sto_k[0] > 20.0) ? 1.0f : 0.0f); _v[1] = ((_c[2] > _c[1] && _c[1] < _c[0] && _c[1] >= _ma[1]) ? 1.0f : 0.0f); _v[2] = ((_c[2] < _c[1] && _c[1] > _c[0] && _c[1] <= _ma[1]) ? 1.0f : 0.0f); _v[3] = ((_sto_k[1] > 80.0 && _sto_k[0] < 80.0) ? 1.0f : 0.0f); } }
Unsere MQL5-Musterimplementierungen für diesen Artikel zielen darauf ab, einen Eingangsvektor für ein neuronales Netz zu setzen oder zu definieren. Wir definieren diese Eingangsvektoren einfach als eine Sammlung von 0en und 1en, wobei eine 1 bedeutet, dass eine bestimmte lange oder kurze Bedingung erfüllt ist. Die Indizes für Kauf- und Verkaufs-Bedingungen sind getrennt, was technisch gesehen bedeutet, dass es nicht möglich ist, einen Eingabevektor zu haben, der mit Einsen gefüllt ist, da die Kauf- und Verkaufs-Bedingungen sich immer gegenseitig spiegeln.
Außerdem kann die Bedingung bei jedem Index weiter detailliert oder verlängert werden, indem jedes der Argumente in der Bedingung einen eigenen Index einnimmt. Dies würde zu wesentlich längeren Eingangsvektoren führen, was wir jedoch nicht untersucht haben. Da wir das Jahr 2023 testen und trainieren, ist dies ein Vorwärtstest für das Jahr 2024. Das erzeugt folgenden Bericht:
Wir sind in der Lage, mit Muster-5 vorwärts zu gehen, allerdings mit einer Einschränkung. Es wurden nur Kaufpositionen platziert! Dies liegt vor allem daran, dass das Training auf begrenzten/kleinen Datensätzen erfolgt, sodass die Netzwerkausgaben auf diese kleine Stichprobe verzerrt werden. Das Training mit größeren Datensätzen sollte hier Abhilfe schaffen.
Goldenes Kreuz/Todeskreuz + Stochastik-Bestätigung
Muster-6 verwendet das Goldene Kreuz/Todeskreuz, bei dem der MA der schnellere mit kürzerer Periodenlänge den langsameren MA kreuzt, und die Dynamik wird auch dadurch bestätigt, dass die Stochastik die 50er-Marke überschreitet. Das Kaufsignal ist das Goldene Kreuz des MA der kürzeren Periode, das von unten nach oben über den MA der längeren Periode verläuft, während die Stochastik über 50 liegt und steigt. Das Verkaufssignal ist das Todeskreuz, bei dem der MA der kürzeren Periode den MA der längeren Periode von oben kreuzt, um darunter zu schließen, während die Stochastik unter 50 liegt und fällt. Wir setzen die Eingänge für das Netz von Muster-6 wie folgt:
else if(Index == 6) { if(CopyBuffer(M.Handle(), 0, T, 2, _ma_lag) >= 2 && CopyBuffer(M.Handle(), 0, T, 2, _ma) >= 2 && CopyBuffer(S.Handle(), 0, T, 2, _sto_k) >= 2 && CopyBuffer(S.Handle(), 0, T, 2, _sto_d) >= 2) { _v[0] = ((_ma_lag[1] > _ma[1] && _ma_lag[0] < _ma[0]) ? 1.0f : 0.0f); _v[1] = ((50.0 <= _sto_d[0] && _sto_k[0] > _sto_d[0]) ? 1.0f : 0.0f); _v[2] = ((50.0 >= _sto_d[0] && _sto_k[0] < _sto_d[0]) ? 1.0f : 0.0f); _v[3] = ((_ma_lag[1] > _ma[1] && _ma_lag[0] < _ma[0]) ? 1.0f : 0.0f); } }
In unserer verwendeten Quelle ist der Handle „_ma“ der gleitende Durchschnitt mit kürzerer Periode, dem wir in unserem Training die Periode 8 zugewiesen haben. Der Durchschnitt mit längerer Periode hat das Handle „_ma_lag“ und seine Periodenlänge ist doppelt so groß wie die des kürzeren mit einer Länge von 16. Ein Vorwärtstest in das Jahr 2024 nach dem Training im Jahr 2023 ergibt diesen Bericht:
Muster-6 scheitert nicht nur an der Rentabilität, sondern auch am Gleichgewicht zwischen Kauf- und Verkaufs-Positionen. Dies kann jedoch durch umfangreiche Schulungen und Tests weiter ausgebaut werden, bevor es abgeschrieben wird.
Stochastic Extreme Umkehrung + MA Trendbestätigung
Muster-7 verwendet die Stochastik bei extremen Niveaus zusammen mit der relativen Position des Preises zum MA, um seine Einstiegssignale zu definieren. Ein Kaufsignal liegt vor, wenn die Stochastik unter 10 liegt und anfängt, nach oben zu drehen, während der Kurs über einem aufwärts gerichteten gleitenden Durchschnitt liegt. Ein Verkaufssignal ist ein Abschwung bei einem Niveau über 90, wenn der Kurs unter einem abwärts gerichteten gleitenden Durchschnitt liegt. Wir bilden dies wie folgt auf ein Netzwerk von MQL5 ab:
else if(Index == 7) { if(C.GetData(T, 2, _c) >= 2 && CopyBuffer(M.Handle(), 0, T, 2, _ma) >= 2 && CopyBuffer(S.Handle(), 0, T, 3, _sto_k) >= 3) { _v[0] = ((_ma[0] > _ma[1] && _c[0] > _ma[0]) ? 1.0f : 0.0f); _v[1] = ((_sto_k[0] > _sto_k[1] && _sto_k[1] < _sto_k[2] && _sto_k[2] <= 10.0) ? 1.0f : 0.0f); _v[2] = ((_sto_k[0] < _sto_k[1] && _sto_k[1] > _sto_k[2] && _sto_k[2] >= 90.0) ? 1.0f : 0.0f); _v[3] = ((_ma[0] < _ma[1] && _c[0] < _ma[0]) ? 1.0f : 0.0f); } }
Wir verwenden hier ausschließlich den %K-Handle für die Stochastik und prüfen lediglich, ob eine n-förmige Umkehrung für die Aufwärts-Bedingungen oder eine u-förmige Umkehrung für die Abwärts-Bedingungen vorliegt, wenn diese extrem sind. Ein Vorwärtstest gibt uns den folgenden Bericht:
Aus unseren obigen Ergebnissen geht hervor, dass dieses Muster auch nicht für ein Jahr auf der Grundlage von Tests aus dem Vorjahr fortgeschrieben werden kann. Und er platziert nur Verkaufspositionen. Die Platzierung von einseitigen Handelsgeschäften in einem Vorwärtstest kann bedenklich sein. Da unsere Ausgabe ein skalarer Float-Wert im Bereich von 0,0 bis 1,0 ist, bedeutet dies, dass alle Vorhersagen unter 0,5 lagen. Das Testen/Trainieren auf größeren Datensätzen ist wichtig, um dies zu beheben.
Stochastischer Ausbruch mit MA-Bestätigung
Unser vorletztes Muster, Muster-8, kombiniert den stochastischen Schwellenwert von 50 mit Kurs-MA-Überschreitungen. Ein Kaufsignal liegt vor, wenn die Dynamik zunimmt, was dadurch angezeigt wird, dass der Stochastik-Oszillator den Schwellenwert von 50 von unten nach oben durchbricht und der Kurs gleichzeitig den MA in ähnlicher Weise durchbricht, um ebenfalls darüber zu schließen. Verkaufen ist der umgekehrte Fall, wenn der Oszillator unter 50 fällt und der Kurs die MA-Unterstützung durchbricht. Dies ist sicherlich ein Muster, das nicht viele Handelsgeschäfte generiert, wenn wir es ähnlich wie in den vorherigen Artikeln anwenden würden. Wir prüfen nun jedoch separat die MA- und Stochastik-Bedingungen für Aufwärts- und Abwärts-Signale. Dies wird in MQL5 wie folgt durchgeführt:
else if(Index == 8) { if(C.GetData(T, 2, _c) >= 2 && CopyBuffer(M.Handle(), 0, T, 2, _ma) >= 2 && CopyBuffer(S.Handle(), 0, T, 2, _sto_k) >= 2 && CopyBuffer(S.Handle(), 1, T, 2, _sto_d) >= 2) { _v[0] = ((_c[1] < _ma[1] && _c[0] > _ma[0]) ? 1.0f : 0.0f); _v[1] = ((_sto_k[1] < 50.0 && _sto_k[0] > 50.0) ? 1.0f : 0.0f); _v[2] = ((_sto_k[1] > 50.0 && _sto_k[0] < 50.0) ? 1.0f : 0.0f); _v[3] = ((_c[1] > _ma[1] && _c[0] < _ma[0]) ? 1.0f : 0.0f); } }
Unser Eingangsvektor für das Muster-8-Netz hat nun eine höhere Wahrscheinlichkeit, dass mindestens eine der beiden Bedingungen - steigend oder fallend - vorliegt oder registriert wird. Der Grund dafür ist, dass das System nicht nur beide Indikatoren verarbeitet, sondern auch Prognosen abgibt, wenn nur einer von ihnen die Zielmuster registriert. Ein Vorwärtstest ergibt folgendes:
Es scheint, dass dieses Muster funktioniert, was sehr ermutigend ist. Hier sind einige wichtige Vorbehalte zu nennen. Erstens werden diese Testläufe mit Kurszielen (Take-Profits) und ohne Stop-Loss durchgeführt. Es stimmt, dass ein Stop-Loss niemals einen Ausstiegskurs garantiert, aber man braucht eine Strategie, um für erfolglose Handelsgeschäfte gerüstet zu sein. Zweitens haben wir das letzte Jahr trainiert und das darauf folgende Jahr getestet, was ein relativ kurzes Testfenster ist. Längere Testzeiträume mit qualitativ hochwertigen Brokerdaten werden oft bevorzugt.
Gleitender Durchschnitts-Squeeze mit Stochastic-Ausbruch
Unser letztes Muster, 10, nutzt die Kompression des gleitenden Durchschnitts, um eine niedrige Volatilität zu erkennen, und das Stochastik-Momentum, um Ausbrüche aus diesen Bedingungen zu erkennen. Ein Kaufsignal liegt vor, wenn sich zwei MAs, ein schneller und ein langsamer, über einen längeren Zeitraum hinweg zusammendrängen und danach ein Aufschwung zu verzeichnen ist, der sich in der Stochastik zeigt, die sich deutlich über 50 bewegt. Bei einem Abwärts-Signal werden dieselben Bedingungen registriert, wobei die erste Änderung darin besteht, dass bei einem Aufwärts-Squeeze der kürzere MA über dem längeren MA liegt, während dies bei einem Verkaufssignal umgekehrt ist und der Stochastikwert für den Verkauf deutlich unter die 50er-Marke fällt (anstatt zu steigen).
Wir rufen den Eingangsvektor des Netzes wie folgt aus MQL5 ab:
else if(Index == 9) { if(CopyBuffer(M.Handle(), 0, T, 3, _ma) >= 3 && CopyBuffer(M_LAG.Handle(), 0, T, 3, _ma_lag) >= 3 && CopyBuffer(S.Handle(), 0, T, 2, _sto_k) >= 2) { _v[0] = ((_ma_lag[0] < _ma[0] && fabs(fabs(_ma_lag[2] - _ma[2]) - fabs(_ma_lag[0] - _ma[0])) <= fabs(_ma[2] - _ma[0])) ? 1.0f : 0.0f); _v[1] = ((_sto_k[1] <= 45.0 && _sto_k[0] >= 55.0) ? 1.0f : 0.0f); _v[2] = ((_sto_k[1] >= 55.0 && _sto_k[0] <= 45.0) ? 1.0f : 0.0f); _v[3] = ((_ma_lag[0] > _ma[0] && fabs(fabs(_ma_lag[2] - _ma[2]) - fabs(_ma_lag[0] - _ma[0])) <= fabs(_ma[2] - _ma[0])) ? 1.0f : 0.0f); } }
Und die Ergebnisse sind wie folgt:
Auch Muster-9 scheint keine Beine zu haben, obwohl es möglich ist, sowohl Kauf- als auch Verkaufspositionen zu platzieren. Auf einer gleichgewichteten Basis sollte es nicht weiter untersucht werden, da wir einige Muster oben haben, die günstige Spaziergänge hatten, aber diese Entscheidung ist bis zu den Händlern und wie viel mehr Tests er bereit ist zu tun.
Schlussfolgerung
Wir haben uns nicht damit beschäftigt, Muster zu kombinieren oder verschiedene Muster herauszupicken, um ein einheitliches System zu schaffen. Das ist etwas, das zwangsläufig gefährlich ist, wie wir in früheren Artikeln, insbesondere im letzten, festgestellt haben. Um mehrere Muster gleichzeitig zu verwenden, muss der Händler mit ihnen vertraut sein, da sie sich gegenseitig aufheben können. Wenn bei der Nachverfolgung magische Zahlen verwendet werden, könnte dies helfen, aber es könnten immer noch Probleme mit Margengrenzen bestehen. Im nächsten Teil werden wir uns ansehen, wie das Verstärkungslernen auf dem bisher Erreichten aufbauen kann.
Datei | Beschreibung |
---|---|
57_0.onnx | Muster-0-Netz |
57_1.onnx | Muster-1 |
57_2.onnx | Muster-2 |
57_3.onnx | Muster-3 |
57_4.onnx | Muster-4 |
57_5.onnx | Muster-5 |
57_6.onnx | Muster-6 |
57_7.onnx | Muster-7 |
57_8.onnx | Muster-8 |
57_9.onnx | Muster-9 |
SignalWZ_57.mqh | Signalklassen-Datei |
57_X.mqh | Signaldatei zur Verarbeitung von Netzwerkeingängen |
wz_57.mq5 | Zeigt das Einbinden der verwendeten Dateien zur Erstellung des Expert Advisors |
Übersetzt aus dem Englischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/en/articles/17479
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.





- 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.
Hallo, ein Anhang fehlt SignalWZ_57.mqh
Ja, ich hatte auch das gleiche Problem mit der fehlenden Datei SignalWZ_57.mqh.