
Beispiel eines neuen Indikators und eines Conditional LSTM
Einführung
In der dynamischen Welt der Finanzmärkte sind Händler und Analysten immer auf der Suche nach neuen und kreativen Wegen, um sich einen Vorteil gegenüber ihren Konkurrenten zu verschaffen. In diesem Artikel wird eine neuartige Methode des automatisierten Handels untersucht, die die Vorhersagefähigkeiten des Deep Learning mit den Stärken der herkömmlichen technischen Analyse verbindet. Wir versuchen, eine stabile und flexible Handelstechnik zu entwickeln, die mit den Feinheiten der heutigen Märkte umgehen kann, indem wir ein komplexes neuronales Netzwerkmodell mit bedingtem Langzeitgedächtnis (Conditional Long Short-Term Memory, LSTM) mit einem proprietären technischen Indikator, dem Volatility Adjusted Momentum (VAM), kombinieren.
Technische Indikatoren werden in der Finanzbranche seit langem verwendet, um Trends und mögliche Handelsmöglichkeiten zu erkennen. Trotz ihrer Bedeutung reichen diese Indikatoren häufig nicht aus, um die Komplexität der Marktdynamik vollständig zu erfassen, insbesondere in Zeiten extremer Volatilität oder abrupter Veränderungen. Allerdings haben insbesondere Deep-Learning-Architekturen wie LSTMs ein erstaunliches Potenzial für maschinelle Lernmodelle zur Mustererkennung und Vorhersage in komplizierten, zeitabhängigen Daten gezeigt. Diese Modelle bieten jedoch nicht immer die Interpretierbarkeit und das domänenspezifische Wissen, das die herkömmliche technische Analyse bietet.
Unsere Strategie zielt darauf ab, diese Lücke zu schließen, indem wir die Vorteile beider Ansätze zusammenführen. In diesem Artikel wird ein neuartiges Instrument vorgestellt, der volatilitätsbereinigte Momentum-Indikator (VAM), der die Marktdynamik unter Berücksichtigung der zugrunde liegenden Volatilität zu messen versucht. Im Vergleich zu herkömmlichen Momentum-Indikatoren bietet dies ein detaillierteres Bild der Marktdynamik. VAM zielt darauf ab, durch Berücksichtigung der Volatilität verlässlichere Signale in einer Reihe von Marktszenarien - von ruhig bis stürmisch - zu liefern.
Um den VAM-Indikator zu verbessern, verwenden wir ein bedingtes LSTM-Modell, eine Art rekurrentes neuronales Netz, das auf die Verarbeitung sequenzieller Daten mit zusätzlichen Kontextdaten zugeschnitten ist. Da es auf der Grundlage historischer Kursdaten und technischer Indikatoren trainiert wird, kann dieses Modell komplizierte, nichtlineare Marktverknüpfungen erkennen, die herkömmlichen Analysetechniken entgehen könnten. Aufgrund der „bedingten“ Eigenschaft des LSTM kann das Modell mehr Marktvariablen berücksichtigen, was zu präziseren und kontextabhängigen Prognosen führen könnte.
Der Expert Advisor (EA), ein speziell entwickeltes automatisches Handelssystem, das den VAM-Indikator mit den Prognosen des Conditional LSTM-Modells kombiniert, ist das Gehirn hinter unserer Strategie. Dieser Expert Advisor (EA) ist in die bekannte MetaTrader 5-Plattform integriert und nutzt die Signale beider Komponenten, um Händlern dabei zu helfen, gut informierte Entscheidungen zu treffen. Darüber hinaus verfügt es über dynamische Risikomanagement-Funktionen, die Take-Profit- und Stop-Loss-Niveaus als Reaktion auf Marktschwankungen ändern.
In diesem Beitrag werden wir die theoretischen Grundlagen des Conditional LSTM und des VAM-Indikatormodells untersuchen und Einblicke in ihre jeweiligen Vorteile und die Möglichkeiten ihrer optimalen Kombination geben. Wir werden jeden Schritt der Erstellung und Umsetzung des EA durchgehen, einschließlich der Einrichtung der Daten, des Trainings des Modells und der Integration in die MetaTrader 5 Umgebung. Darüber hinaus werden wir die Ergebnisse einer umfassenden Optimierung und eines Backtestings vorstellen und die Effektivität der reinen VAM-Methode mit der kombinierten VAM- und Conditional LSTM-Methode vergleichen.
Wir werden über die Schwierigkeiten und Faktoren sprechen, die bei der Verschmelzung modernster Methoden des maschinellen Lernens mit der herkömmlichen technischen Analyse auftreten, wenn wir diese neuartige Handelsstrategie untersuchen. Wir versuchen, einen gründlichen Überblick über die praktischen Elemente der Einführung eines solchen Systems zu geben, einschließlich aller Aspekte von der Datenqualität und der Interpretierbarkeit der Modelle bis hin zu den rechnerischen Anforderungen der Ausführung komplizierter Modelle in Echtzeit-Handelssituationen.
Am Ende dieses Artikels werden die Leser ein gründliches Verständnis dafür haben, wie hochmoderne Techniken des maschinellen Lernens zur Ergänzung der traditionellen technischen Analyse eingesetzt werden können, um die Handelsergebnisse zu verbessern. Diese Untersuchung von VAM und Conditional (bedingtem) LSTM im automatisierten Handel bietet aufschlussreiche Informationen über die Zukunft des algorithmischen Handels, unabhängig von Ihrem Hintergrund als Händler, Datenwissenschaftler oder Forscher, der die Grenzen der quantitativen Finanzen untersucht.
Volatilitätsbereinigtes Momentum (VAM)
Das Kernkonzept der VAM besteht darin, die Marktvolatilität bei der Bewertung des Momentums zu berücksichtigen. Er berechnet die Differenz zwischen dem aktuellen Kurs und einem vergangenen Kurs (Momentum) und teilt sie dann durch das Produkt aus Volatilität und der Quadratwurzel aus der Momentum-Periode. Dieser Wert wird mit einem Faktor skaliert und gibt die Stärke der um die jüngste Marktvolatilität bereinigten Dynamik an.
Deep Learning-Modell
In diesem Artikel wird ein bedingtes LSTM-Modell verwendet, eine Art rekurrentes neuronales Netz (RNN), das sich für finanzielle Zeitreihendaten eignet. Dieses Modell verwendet historische Kursdaten und technische Indikatoren (wie den hier verwendeten MACD) als Input und sagt zukünftige Kursbewegungen voraus. Der Vorteil von Conditional LSTMs liegt in ihrer Fähigkeit, komplexe Beziehungen zwischen verschiedenen Marktfaktoren zu erfassen.
Der Expert Advisor (EA)
Die Erstellung eines EA, der die Vorhersagen des Deep-Learning-Modells mit VAM kombiniert, wird in dem Artikel beschrieben. Im Folgenden finden Sie eine Zusammenfassung der wichtigsten Merkmale:
- Initialisierung: Der EA lädt und konfiguriert die Eingabe- und Ausgabeparameter für das vortrainierte ONNX Deep Learning-Modell.
- Datenerfassung und Normalisierung: Der EA sammelt MACD-Werte und frühere Kursdaten. Bevor diese Variablen in das Deep-Learning-Modell eingegeben werden, werden sie normalisiert.
- VAM-Berechnung: Anhand historischer und aktueller Kursdaten berechnet der EA den VAM-Indikator.
- Handelslogik und Vorhersage: Der EA zieht eine Kursprognose aus dem Deep-Learning-Modell.
- Der EA startet einen Kauf, wenn VAM hoch ist und die Vorhersage auf einen Preisanstieg hindeutet.
- Im Gegensatz dazu eröffnet der EA ein Verkaufsgeschäft, wenn VAM niedrig ist und die Vorhersage einen Preisrückgang anzeigt.
Durch die dynamische Bestimmung von Stop-Loss- und Take-Profit-Levels auf Basis der Average True Range (ATR) steuert der EA das Risiko.
Ergebnisse:
In dem Artikel werden die Ergebnisse des Backtestings für den EA mit der VAM-Strategie mit und ohne Conditional LSTM erwähnt.
Erstellen wir einen neuen Indikator (VAM)
Was ist, wenn wir einen neuen Indikator erstellen, zum Beispiel diesen:
// Calcular Momentum double momentum = close_price - iClose(NULL, 0, momentum_period); // Calcular Volatilidad double volatility = iMA(NULL, 0, volatility_period, 0, MODE_SMA, PRICE_CLOSE); // Calcular VAM double vam =( momentum / (volatility * MathSqrt(momentum_period)))*10000;
Wir werden das Momentum und die Volatilität verwenden, um einen neuen Indikator zu erstellen, der den Namen VAM tragen wird.
Das Momentum wird durch das Produkt aus der Quadratwurzel der Momentum-Periode und der Volatilität geteilt.
Zu Skalierungszwecken wird das Ergebnis dann mit 10.000 multipliziert.
Durch die Berücksichtigung der Volatilität versucht der VAM-Indikator, die Dynamik zu quantifizieren. Er versucht, das Momentum über eine Reihe von Marktbedingungen hinweg auszugleichen, indem er das Momentum durch die Volatilität teilt. Die Quadratwurzel der Impulsperiode im Nenner hilft bei der Standardisierung des Indikators über verschiedene Zeiträume hinweg.
Ein positiver VAM-Wert weist auf eine Aufwärtsdynamik hin, während ein negativer Wert eine Abwärtsdynamik anzeigt. Das Ausmaß der VAM stellt die Stärke der Dynamik dar, bereinigt um die jüngste Marktvolatilität.
Dieser Indikator kann verwendet werden, um potenzielle Trendumkehrungen zu erkennen oder um die Stärke aktueller Markttrends unter Berücksichtigung der Marktvolatilität zu beurteilen.
Nur mit diesem Indikator können wir einen EA erstellen und prüfen, ob er profitabel ist oder nicht.
Die Strategie würde folgendermaßen aussehen:
void OnTick() { int bars = iBars(NULL, 0); if(bars < MathMax(momentum_period, MathMax(volatility_period, (vam_period))))//, MathMax(ma_long_period, rsi_period))))) return; double close_price = iClose(NULL, 0, 0); // Calcular Momentum double momentum = close_price - iClose(NULL, 0, momentum_period); // Calcular Volatilidad double volatility = iMA(NULL, 0, volatility_period, 0, MODE_SMA, PRICE_CLOSE); // Calcular VAM double vam =( momentum / (volatility * MathSqrt(momentum_period)))*10000; double atr = iATR(_Symbol,PERIOD_CURRENT,14)*_Point; double Bid = SymbolInfoDouble(_Symbol, SYMBOL_BID); double Ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK); double slPriceBuy = NormalizeDouble(Bid - slmul*atr,_Digits); double tpPriceBuy = NormalizeDouble(Ask + tpmul*atr,_Digits); double slPriceSell = NormalizeDouble(Ask + slmul*atr,_Digits); double tpPriceSell = NormalizeDouble(Bid - tpmul*atr,_Digits); // Señales if(vam > VAMTHRESH)// && ma_short > ma_long)// && rsi < 70 && ma_short > ma_long ) { // Comprar trade.Buy(lot_size,_Symbol, Ask, slPriceBuy, tpPriceBuy, " BUY EA "); } else if(vam < -VAMTHRESH)// && ma_short < ma_long)// rsi > 30 && ma_short < ma_long ) { // Vender trade.Sell(lot_size,_Symbol, Bid, slPriceSell, tpPriceSell, " SELL EA "); } }
Die Funktion iBars(NULL, 0) liefert die Gesamtzahl der Balken, die für das angegebene Symbol und den Zeitrahmen zugänglich sind.
Bars int: Die Gesamtzahl der Balken bzw. der zurückgegebene Wert wird in der Variablen bars gespeichert.
MathMax: Der Maximalwert der angegebenen Zahlen wird von dieser Funktion zurückgegeben. In diesem Fall wird die verschachtelte Methode verwendet, um das Maximum über mehrere Zeiträume hinweg zu ermitteln.
Die Variablen momentum_period, volatility_period, vam_period, ma_long_period und rsi_period, die zuvor festgelegt wurden, geben die Intervalle verschiedener Indikatoren oder Berechnungen an.
Wenn: Die Bedingung bestimmt, ob die Gesamtzahl der Balken geringer ist als die Summe der zugewiesenen Zeiten.
Wenn die „if“-Bedingung erfüllt ist (d.h. es sind nicht genügend Balken vorhanden), wird die Funktion sofort beendet und der Rest des Codes wird nicht ausgeführt.
VAM-Ergebnisse
Die Ergebnisse sehen wie folgt aus (nach schneller Optimierung, habe es nicht beendet):
Dies scheint für eine einfache Strategie und einen einfachen Indikator gut zu sein.
Mal sehen, was wir erreichen könnten, wenn wir ein Deep Learning-Modell dafür verwenden würden (aber heute werden wir etwas anderes verwenden), wir werden ein Deep Learning-Modell mit einigen Indikatoren erstellen, um zu sehen, was besser passt.
Deep Learning Modelle
Wir werden dieses Modell in ONNX exportieren, aber zunächst werden wir vergleichen, welches Modell besser ist.
Um all dies zu tun, werden wir Google Colab (damit wir nicht unsere PC-Ressourcen verbrauchen) mit seinem Python-Skript, das beigefügt ist, verwenden.
Da dies ein mql5-Anwendung ist, werde ich den Python-Code nicht erklären.
Es gibt zwei py-Skripte, das erste ist ein py-Skript mit allen Indikatoren verwendet, und das zweite ist das gleiche Skript, aber mit nur MACD-Indikator (weil im ersten Skript wir angenommen, MACD hat eine gute Trefferquote und R2, mit geringen Fehlern.
Die grafischen Ergebnisse des ersten Skripts lauten wie folgt:
Nachdem wir uns für den MACD entschieden hatten, bereiteten wir das Skript vor und passten die Daten für den ersten Januar 2024 an (für Backtests in mql5 ab dem 1.1.2024).
Die Ergebnisse des zweiten Skripts waren wie folgt (sehr ähnlich).
usw. ... (Sie können es selbst machen und die Ergebnisse mit colab überprüfen).
Das Python-Skript ist für Colab. Daher müssen Sie zunächst die erste Zelle ausführen, und wenn alle Bibliotheken installiert sind die zweite Zelle. Akzeptieren Sie sie, um sie die Modelle und Grafiken in Ihrem Laufwerk zu speichern, und warten Sie einfach, bis es fertig ist.
Die Daten werden von mlq5 abgerufen, da MetaTrader in Colab nicht installiert ist (die Werte sollten ähnlich sein).
Wie Sie in der zweiten Gruppe von Bildern sehen können, hat das MACD-Modell eine wirklich gute Trefferquote, weshalb wir es ausgewählt haben.
Bedingter LSTM
Eine erweiterte Version des herkömmlichen neuronalen Netzes mit langem Kurzzeitgedächtnis wird als bedingtes LSTM bezeichnet. Durch Hinzufügen weiterer kontextbezogener Daten oder Situationen zum Vorhersageprozess der LSTM-Architektur wird dieser verbessert. Da sich so viele Faktoren auf die Preisänderungen an den Finanzmärkten auswirken können, ist sie für die Finanzmarktprognose besonders interessant.Ein wirksames Instrument im Bereich der Aktien- oder Devisenprognose ist eine bedingte logistische Regressionsmaschine. Es ermöglicht dem Modell, zusätzlich zu den Preisdaten der Vergangenheit eine Vielzahl von Marktindikatoren und externen Variablen zu berücksichtigen. Dazu können Stimmungsdaten, allgemeinere Wirtschaftsindikatoren und technische Indikatoren wie RSI oder gleitende Durchschnitte gehören. Das Modell soll ein umfassenderes Bild der Marktdynamik vermitteln, indem es diese vielen Inputs integriert.
Kontextbezogenes Bewusstsein ist einer der Hauptvorteile der Verwendung von Conditional LSTM für Finanzprognosen. Die Finanzmärkte sind komplizierte Systeme, die von einer Vielzahl von Variablen beeinflusst werden. Da Conditional LSTM mehrere Indikatoren kombinieren kann, ist es möglicherweise in der Lage, komplexe Korrelationen zwischen zahlreichen Marktdynamiken aufzudecken. Durch seine Fähigkeit, sowohl statische Merkmale als auch Zeitreihendaten zu verwalten, eignet es sich gut für die Finanzmärkte, wo vergangene Trends und aktuelle Umstände gleichermaßen wichtig sind.
Darüber hinaus sind bedingte LSTMs genau wie herkömmliche LSTMs hervorragend in der Lage, langfristige Abhängigkeiten in Zeitreihendaten zu erfassen. Dies ist besonders auf den Finanzmärkten nützlich, wo sich langfristige Muster abzeichnen können. Das Modell kann Muster erkennen, die von einfacheren Modellen übersehen werden könnten, da es in der Lage ist, relevante Informationen über längere Sequenzen hinweg beizubehalten.
Dennoch gibt es gewisse Schwierigkeiten bei der Verwendung von Conditional LSTM für Finanzprognosen. Die größere Komplexität des Modells mag zwar Vorteile haben, bringt aber auch Herausforderungen mit sich. Eine Überanpassung wird immer wahrscheinlicher, je komplizierter das Training wird, insbesondere bei der Arbeit mit kleineren Datensätzen. Aus dieser Komplexität resultieren höhere Rechenkosten, was bei Echtzeit-Handelsanwendungen ein wichtiger Faktor sein kann.
Datenqualität und -relevanz werden mit Conditional LSTMs noch wichtiger. Das Modell erfordert nicht nur Preisdaten, sondern auch hochwertige, relevante Indikatordaten. In der schnelllebigen und manchmal undurchsichtigen Welt der Finanzmärkte kann es eine Herausforderung sein, konsistente und genaue Daten über all diese Dimensionen hinweg zu gewährleisten.
Bei der Bewertung des Potenzials von Conditional LSTMs muss auch die grundlegende Natur der Finanzmärkte berücksichtigt werden. Die Märkte werden durch unvorhersehbare Ereignisse und menschliches Verhalten beeinflusst, was die Wirksamkeit jedes noch so ausgefeilten Prognosemodells einschränken kann. Das Modell kann sich bei der Erkennung von Mustern in historischen Daten auszeichnen, hat aber Schwierigkeiten, wenn es mit noch nie dagewesenen Marktbedingungen oder großen wirtschaftlichen Schocks konfrontiert wird.
Ein weiteres Problem bei Conditional LSTMs ist, wie bei vielen Deep-Learning-Modellen, die Interpretierbarkeit. Auch wenn sie präzise Prognosen erstellen, kann es schwierig sein, die dahinter stehenden Überlegungen nachzuvollziehen. Der „Blackbox“-Aspekt könnte bei Finanzanwendungen, bei denen Erklärbarkeit und Offenheit häufig von entscheidender Bedeutung sind, Probleme verursachen.
Obwohl bedingte LSTMs faszinierende Möglichkeiten für indikatorbasierte Aktien- und Devisenprognosen bieten, ist es wichtig, sie mit Bedacht einzusetzen. Ihre Fähigkeit, komplizierte, vielschichtige Daten zu berücksichtigen, kann zu präziseren und differenzierteren Prognosen führen. Sie sollten jedoch aufgrund der Schwierigkeiten, die sich aus der zunehmenden Komplexität, den Datenanforderungen und der inhärenten Unvorhersehbarkeit der Finanzmärkte ergeben, als Bestandteil eines umfassenderen, sorgfältig durchdachten analytischen Ansatzes verwendet werden. ein gründliches Verständnis der Grenzen des Modells in praktischen Situationen und ein umfangreiches Backtesting. Die Anwendung solch fortschrittlicher Techniken im Bereich des Finanzhandels, bei dem viel auf dem Spiel steht, erfordert umfangreiche Backtests und das Wissen um die Grenzen des Modells in der Praxis.
Das Modell (wie im py-Skript) sieht wie folgt aus:
und seine Ein- und Ausgänge sollten wie folgt aussehen:
EA-Code
Der Hauptzweck dieses Expert Advisors (EA) ist die Automatisierung von Handelsentscheidungen auf der Grundlage einer Kombination aus technischen Indikatoren und Vorhersagen eines Deep-Learning-Modells (ONNX). Der EA verwendet den Indikator Volatility Adjusted Momentum (VAM) und den MACD (Moving Average Convergence Divergence) zusammen mit Preisprognosen, die von einem maschinellen Lernmodell erstellt werden. Er führt die Geschäfte in Abhängigkeit von der Kombination dieser Elemente aus.
Der EA beginnt mit der Definition verschiedener Eigenschaften und Bibliotheken. Die Klasse „CTrade“ ist für die Ausführung von Geschäften vorgesehen, während andere Header für statistische Funktionen und die Array-Verwaltung vorgesehen sind. Für die VAM-Berechnung und -Handelsausführung werden Eingabeparameter wie „momentum_period“, „volatility_period“ und „vam_period“ definiert, die zur Steuerung der Logik zur Berechnung von Momentum und Volatilität verwendet werden. Handelsparameter wie „Lotgröße“ und Multiplikatoren für Stop-Loss („slmul“) und Take-Profit („tpmul“) werden hier ebenfalls definiert, um dasVerhalten des EAs flexibel zu gestalten. Außerdem sind Konstanten enthalten, die die ONNX-Modellparameter wie „BATCH_SIZE“, „SEQUENCE_LENGTH“ und andere definieren, um zu verwalten, wie Daten an das Deep-Learning-Modell übergeben werden.
//+------------------------------------------------------------------+ //| VAM + DL(MACD) EA | //| Copyright 2024, Javier Santiago Gaston de Iriarte Cabrera | //| https://www.mql5.com/en/users/jsgaston/news | //+------------------------------------------------------------------+ #property copyright "Javier Santiago Gaston de Iriarte Cabrera" #property link "https://www.mql5.com/en/users/jsgaston/news" #property version "1.01" #include <Trade\Trade.mqh> #include <Math\Stat\Math.mqh> #include <Arrays\ArrayFloat.mqh> CTrade trade; // Inputs input int momentum_period = 13; input int volatility_period = 7; input int vam_period = 9; input double lot_size = 0.01; input int slippage = 3; input double VAMTHRESH = 9.0; input int slmul = 2; input int tpmul = 4; // ONNX model parameters #define BATCH_SIZE 1 #define SEQUENCE_LENGTH 30 #define INPUT_FEATURES 3 #define CONDITION_FEATURES 2 #define HIDDEN_DIM 128 #define NUM_LAYERS 2 float input_x[][SEQUENCE_LENGTH][INPUT_FEATURES]; float input_condition[][CONDITION_FEATURES]; float h0[][BATCH_SIZE][HIDDEN_DIM]; float c0[][BATCH_SIZE][HIDDEN_DIM]; #define PRICE_UP 0 #define PRICE_SAME 1 #define PRICE_DOWN 2 long ExtHandle = INVALID_HANDLE; int ExtPredictedClass = -1; datetime ExtNextBar = 0; datetime ExtNextDay = 0; float ExtMin = 0.0; float ExtMax = 1.0; // Initialize to 1.0 to prevent division by zero float predicted_last; #resource "/Files/stock_prediction_model_MACD.onnx" as uchar ExtModel[]
Die Initialisierungsfunktion „OnInit()“ ist von entscheidender Bedeutung, da sie das ONNX-Modell aus einer binären Ressource („stock_prediction_model_MACD.onnx“) lädt und die Eingabe- und Ausgabeformen des Modells einrichtet. Die Eingabe für das ONNX-Modell besteht aus historischen Kursdaten, MACD-Werten und initialisierten versteckten und Zellzuständen („h0“, „c0“) für die rekurrenten Schichten des Modells. Wenn das Modell erfolgreich geladen wurde, initialisiert die Funktion auch die minimalen und maximalen Preiswerte („ExtMin“ und „ExtMax“), die zur Normalisierung der Eingabedaten für das ONNX-Modell verwendet werden. Tritt beim Laden des Modells ein Fehler auf, wird „INIT_FAILED“ zurückgegeben, wodurch der Betrieb des EA effektiv gestoppt wird.
//+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { Print("BATCH_SIZE: ", BATCH_SIZE, ", CONDITION_FEATURES: ", CONDITION_FEATURES); ExtHandle = OnnxCreateFromBuffer(ExtModel,ONNX_DEFAULT); if(ExtHandle == INVALID_HANDLE) { Print("OnnxCreateFromBuffer error ", GetLastError()); return(INIT_FAILED); } // Set input shapes long input_shape[] = {BATCH_SIZE, SEQUENCE_LENGTH, INPUT_FEATURES}; if(!OnnxSetInputShape(ExtHandle, ONNX_DEFAULT, input_shape)) { Print("OnnxSetInputShape for input_x error ", GetLastError()); return(INIT_FAILED); } long condition_shape[] = {BATCH_SIZE,CONDITION_FEATURES}; if(!OnnxSetInputShape(ExtHandle, 1, condition_shape)) { Print("OnnxSetInputShape for input_condition error ", GetLastError()); return(INIT_FAILED); } long h0_shape[] = {NUM_LAYERS, BATCH_SIZE, HIDDEN_DIM}; if(!OnnxSetInputShape(ExtHandle, 2, h0_shape)) { Print("OnnxSetInputShape for h0 error ", GetLastError()); return(INIT_FAILED); } long c0_shape[] = {NUM_LAYERS, BATCH_SIZE, HIDDEN_DIM}; if(!OnnxSetInputShape(ExtHandle, 3, c0_shape)) { Print("OnnxSetInputShape for c0 error ", GetLastError()); return(INIT_FAILED); } const long output_shape[] = {1,1}; if(!OnnxSetOutputShape(ExtHandle,0,output_shape)) { Print("OnnxSetOutputShape error ",GetLastError()); return(INIT_FAILED); } // Initialize ExtMin and ExtMax GetMinMax(); Print("Initializing EA with VAM and ONNX integration"); return(INIT_SUCCEEDED); }
Die Funktion „OnTick()“ ist die Kernlogik, die bei jedem Preis-Tick ausgeführt wird. Zunächst wird geprüft, ob es sich um einen neuen Tag handelt, und die Mindest- und Höchstpreise werden mit „GetMinMax()“ entsprechend aktualisiert. Der nächste Block sorgt dafür, dass die Funktion nur dann fortgesetzt wird, wenn ein neuer Kursbalken verfügbar ist. Der EA aktualisiert dann die Variablen „ExtMin“ und „ExtMax“ auf die neuesten Kurswerte. Das Herzstück dieser Funktion ist die Kombination aus der VAM-Berechnung und der ONNX-Vorhersage. VAM wird berechnet, indem die Kursdifferenz (Momentum) durch das Produkt aus Volatilität und der Quadratwurzel der „Momentum-Periode“, skaliert mit 10.000, geteilt wird. Überschreitet der VAM den Schwellenwert („VAMTHRESH“), deutet dies auf einen starken Markttrend hin und signalisiert einen möglichen Handel.
Der EA kombiniert dann die Vorhersage- und VAM-Ergebnisse. Wenn VAM hoch ist (größer als „VAMTHRESH“) und das ONNX-Modell einen Preisanstieg vorhersagt, eröffnet der EA ein Kaufgeschäft mit einem berechneten Stop-Loss und Take-Profit auf Basis der Average True Range (ATR). Ähnlich verhält es sich, wenn VAM niedrig ist (unter negativem „VAMTHRESH“) und das ONNX-Modell einen Preisrückgang vorhersagt, eröffnet der EA ein Verkaufsgeschäft. Diese Geschäfte werden mit Hilfe der Klasse „CTrade“ ausgeführt, die mit den Handelsfunktionen der MetaTrader 5 Plattform interagiert.
Was das Risikomanagement betrifft, so werden die Stop-Loss- und Take-Profit-Niveaus dynamisch auf der Grundlage der ATR des Vermögenswerts berechnet. Dadurch wird sichergestellt, dass sich die Strategie an die Volatilität des Marktes anpasst und je nach den aktuellen Marktbedingungen einen flexibleren Ausstieg aus dem Handel ermöglicht.void OnTick() { // Check for new day and update ExtMin and ExtMax if(TimeCurrent() >= ExtNextDay) { GetMinMax(); ExtNextDay = TimeCurrent() - TimeCurrent() % PeriodSeconds(PERIOD_D1) + PeriodSeconds(PERIOD_D1); } // Check for new bar if(TimeCurrent() < ExtNextBar) return; ExtNextBar = TimeCurrent() - TimeCurrent() % PeriodSeconds() + PeriodSeconds(); // Update ExtMin and ExtMax double close = iClose(_Symbol, _Period, 0); if(ExtMin > close) ExtMin = (float)close; if(ExtMax < close) ExtMax = (float)close; int bars = iBars(_Symbol, PERIOD_CURRENT); if(bars < MathMax(momentum_period, MathMax(volatility_period, MathMax(vam_period, SEQUENCE_LENGTH)))) return; // Calculate VAM double momentum = close - iClose(_Symbol, PERIOD_CURRENT, momentum_period); double volatility = iStdDev(_Symbol, PERIOD_CURRENT, volatility_period, 0, MODE_SMA, PRICE_CLOSE); double vam = (momentum / (volatility * MathSqrt(momentum_period))) * 10000; Print("VAM ", vam); // Get ONNX prediction int result=GetPrediction(); // Trading logic combining VAM and ONNX prediction double atr = iATR(_Symbol, PERIOD_CURRENT, 14)*_Point; double Bid = SymbolInfoDouble(_Symbol, SYMBOL_BID); double Ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK); double slPriceBuy = NormalizeDouble(Bid - slmul * atr, _Digits); double tpPriceBuy = NormalizeDouble(Ask + tpmul * atr, _Digits); double slPriceSell = NormalizeDouble(Ask + slmul * atr, _Digits); double tpPriceSell = NormalizeDouble(Bid - tpmul * atr, _Digits); //Print(result); if(vam > VAMTHRESH && result == 0) { trade.Buy(lot_size, _Symbol, Ask, slPriceBuy, tpPriceBuy, "BUY VAM+ONNX"); } else if(vam < -VAMTHRESH && result == 2) { trade.Sell(lot_size, _Symbol, Bid, slPriceSell, tpPriceSell, "SELL VAM+ONNX"); } }
Die ONNX-Modellvorhersage wird durch den Aufruf von „GetPrediction()“ abgerufen. Die Eingaben für das Modell werden von der Funktion „PrepareInputs()“ vorbereitet, die die historischen Schlusskurse und MACD-Daten sammelt, sie anhand der Preisspanne („ExtMin“ und „ExtMax“) normalisiert und die vom Modell erwarteten Eingabefelder füllt. Es setzt die Daten für die Eingabepreissequenz („input_x“) und die MACD-basierten Bedingungen („input_condition“), während es die versteckten Zustände („h0“, „c0“) zurücksetzt. Sobald die Eingaben fertig sind, wird das Modell mit der Funktion „OnnxRun()“ ausgeführt, die den vorhergesagten Preis berechnet. Die Differenz zwischen dem vorhergesagten Preis und dem letzten vorhergesagten Preis wird verwendet, um zu bestimmen, ob das Modell erwartet, dass der Preis steigt, fällt oder gleich bleibt. Wenn die Änderung der Vorhersage zu gering ist, schlägt das Modell keine Bewegung vor (der Preis bleibt gleich).
void PrepareInputs() { ArrayResize(input_x, BATCH_SIZE); ArrayResize(input_condition, BATCH_SIZE); ArrayResize(h0, NUM_LAYERS); ArrayResize(c0, NUM_LAYERS); for(int i = 0; i < SEQUENCE_LENGTH; i++) { input_x[0][i][0] = (float)((iClose(_Symbol, PERIOD_CURRENT, i) - ExtMin) / (ExtMax - ExtMin)); double macd_main[], macd_signal[]; int macd_handle = iMACD(_Symbol, PERIOD_CURRENT, 12, 26, 9, PRICE_CLOSE); CopyBuffer(macd_handle, 0, i, 1, macd_main); CopyBuffer(macd_handle, 1, i, 1, macd_signal); input_x[0][i][1] = (float)((macd_main[0] - ExtMin) / (ExtMax - ExtMin)); input_x[0][i][2] = (float)((macd_signal[0] - ExtMin) / (ExtMax - ExtMin)); } double macd_main2[], macd_signal2[]; int macd_handle2 = iMACD(_Symbol, PERIOD_CURRENT, 12, 26, 9, PRICE_CLOSE); CopyBuffer(macd_handle2, 0, 0, 1, macd_main2); CopyBuffer(macd_handle2, 1, 0, 1, macd_signal2); input_condition[0][0] = (float)macd_main2[0]; input_condition[0][1] = (float)macd_signal2[0]; ArrayInitialize(h0, 0.0f); ArrayInitialize(c0, 0.0f); } //+------------------------------------------------------------------+ //| Get prediction from ONNX model | //+------------------------------------------------------------------+ int GetPrediction() { PrepareInputs(); float output_data[]; ArrayResize(output_data, 1); // Run the ONNX model if(!OnnxRun(ExtHandle, ONNX_NO_CONVERSION, input_x, input_condition, h0, c0, output_data)) { Print("OnnxRun error: ", GetLastError()); return ExtPredictedClass = -1; } float predicted=output_data[0]*(ExtMax-ExtMin)+ExtMin; Print("Predicted last ", predicted_last); Print("Predicted ",predicted); float last_close = (float)iClose(_Symbol, PERIOD_CURRENT, 0); Print("last close ",last_close); float delta = predicted_last - predicted; predicted_last=predicted; Print("Delta ",delta); if(MathAbs(delta) <= 0.00001) ExtPredictedClass = PRICE_SAME; else if(delta < 0) ExtPredictedClass = PRICE_UP; else ExtPredictedClass = PRICE_DOWN; Print(ExtPredictedClass); return ExtPredictedClass; }
Die Funktion „GetMinMax()“ ist für die Festlegung der Mindest- („ExtMin“) und Höchstwerte („ExtMax“) des Preises des letzten Datentages zuständig. Diese Werte werden verwendet, um die Eingaben zu normalisieren, bevor sie an das ONNX-Modell weitergeleitet werden, um sicherzustellen, dass das Modell Eingaben in einem einheitlichen Bereich erhält. Wenn der EA die erforderlichen Kursdaten nicht abrufen kann, wird er auf einen sicheren Bereich zurückgesetzt, um eine Division durch Null zu vermeiden.
void GetMinMax() { double close[]; int copied = CopyClose(_Symbol, PERIOD_D1, 0, SEQUENCE_LENGTH, close); if(copied > 0) { ExtMin = (float)MathMin(close); ExtMax = (float)MathMax(close); } else { Print("Failed to copy price data. Error: ", GetLastError()); ExtMin = 0; ExtMax = 1; // Prevent division by zero } }
Schließlich enthält der EA eine Deinitialisierungsfunktion „OnDeinit()“, die das ONNX-Modell-Handle freigibt, wenn der EA entfernt wird, um sicherzustellen, dass der Speicher ordnungsgemäß verwaltet wird und Ressourcenlecks vermieden werden.
void OnDeinit(const int reason) { if(ExtHandle != INVALID_HANDLE) { OnnxRelease(ExtHandle); ExtHandle = INVALID_HANDLE; } }
Zusammenfassend lässt sich sagen, dass dieser EA die technische Analyse (über VAM und MACD) mit den Vorhersagen des maschinellen Lernens eines ONNX-Modells verbindet, um informierte, automatisierte Handelsentscheidungen zu treffen. Die technische Analyse hilft bei der Erkennung von Trends, während das Modell des maschinellen Lernens die Preisentwicklung vorhersagt, was zu einer Hybridstrategie führt.
Ergebnisse
Nach der Optimierung
Schlussfolgerung
Dieser Artikel untersucht die Integration von Deep Learning, insbesondere von Conditional LSTM-Modellen, mit dem Volatility Adjusted Momentum (VAM)-Indikator zur Verbesserung automatisierter Handelssysteme. Durch die Kombination der Vorhersagefähigkeiten von LSTM und der volatilitätssensitiven Momentum-Analyse von VAM zielt die Strategie darauf ab, komplexe Marktdynamiken zu erfassen. Dieses auf MetaTrader 5 implementierte System generiert Handelssignale und passt das Risikomanagement dynamisch an.
Backtesting zeigt bessere Ergebnisse, wenn LSTM mit VAM kombiniert wird. Trotz Herausforderungen wie Überanpassung und Rechenaufwand deutet die Studie darauf hin, dass die Integration von Deep Learning mit technischer Analyse algorithmische Handelsstrategien erheblich verbessern kann.
Übersetzt aus dem Englischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/en/articles/15956





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