![Datenwissenschaft und maschinelles Lernen (Teil 24): Zeitreihenprognose im Forex mit regulären AI-Modellen](https://c.mql5.com/2/81/Data_Science_and_Machine_Learning_Part_24_600x314.jpg)
Datenwissenschaft und maschinelles Lernen (Teil 24): Zeitreihenprognose im Forex mit regulären AI-Modellen
Inhalt
- Was ist eine Zeitreihenprognose?
- Warum und wo wird die Zeitreihenprognose eingesetzt?
- Ein Vergleich zwischen klassischen und modernen, auf Zeitreihen basierenden ML-Modellen
- Merkmalstechnik für Zeitreihenprognosen
- Training des Modells LightGBM-Regressor
- Erweiterter Dickey-Fuller-Test
- Warum ist Stationarität wichtig?
- Vorhersage einer stationären Zielvariablen
- Aufbau des LightGBM-Klassifikatormodells
- Speichern des LightGBM-Klassifikatormodells in ONNX
- Alles in einen Handelsroboter verpacken
- Testen des Modells mit dem Strategietester
- Vorteile der Verwendung klassischer und moderner ML-Modelle für die Zeitreihenprognose
- Schlussfolgerung
Was ist Zeitreihenprognose?
Bei der Zeitreihenprognose werden vergangene Daten verwendet, um zukünftige Werte in einer Folge von Datenpunkten vorherzusagen. Diese Abfolge ist in der Regel nach der Zeit geordnet, daher der Name Zeitreihe.
Kernvariablen in Zeitreihendaten
Wir können in unseren Daten so viele Merkmalsvariablen haben, wie wir wollen, aber alle Daten für Zeitreihenanalysen oder Prognosen müssen diese beiden Variablen enthalten.
- Zeit
Hierbei handelt es sich um eine unabhängige Variable, die die spezifischen Zeitpunkte angibt, zu denen die Datenpunkte beobachtet wurden. - Zielvariable
Dies ist der Wert, den Sie versuchen, auf der Grundlage früherer Beobachtungen und möglicherweise anderer Faktoren vorherzusagen. (z. B. täglicher Börsenschlusskurs, stündliche Temperatur, Website-Traffic pro Minute).
Ziel der Zeitreihenprognose ist es, historische Muster und Trends in den Daten zu nutzen, um fundierte Vorhersagen über zukünftige Werte zu treffen.
Dieser Artikel setzt voraus, dass Sie ein grundlegendes Verständnis von ONNX, Zeitreihenprognose und Light Gradient Boosting Machine (LightGBM) haben. Bitte lesen Sie diese Artikel, wenn Sie sie noch nicht gelesen haben, um sich Klarheit zu verschaffen.
Warum und wo wird die Zeitreihenprognose eingesetzt?
Die Zeitreihenanalyse und -prognose kann in den folgenden Szenarien eingesetzt werden:
- Vorhersage zukünftiger Werte
- Verstehen des/der vergangenen Verhaltens/Verhaltensweisen
- Planung für die Zukunft, die von der Vergangenheit abhängig sein könnte
- Bewertung der aktuellen Leistungen
Klassische und moderne Modelle des maschinellen Lernens im Vergleich zu zeitreihenbasierten Modellen
Im Gegensatz zu klassischen Modellen des maschinellen Lernens wie der linearen Regression, der Support Vector Machine (SVM), den neuronalen Netzen (NN) und anderen, die wir in früheren Artikeln besprochen haben — die darauf abzielen, Beziehungen zwischen Merkmalsvariablen zu ermitteln und auf der Grundlage dieser erlernten Beziehungen zukünftige Vorhersagen zu treffen — prognostizieren Zeitreihenmodelle zukünftige Werte auf der Grundlage zuvor beobachteter Werte.
Dieser Unterschied im Ansatz bedeutet, dass Zeitreihenmodelle speziell für den Umgang mit zeitlichen Abhängigkeiten und Mustern, die sequenziellen Daten innewohnen, konzipiert sind. Zeitreihenprognosemodelle wie ARIMA, SARIMA, Exponential Smoothing, RNN, LSTM und GRU nutzen historische Daten zur Vorhersage zukünftiger Punkte in der Reihe, wobei Trends, Saisonalität und andere zeitliche Strukturen erfasst werden.
Das nachstehende Flussdiagramm veranschaulicht verschiedene Modelle des maschinellen Lernens, die für Zeitreihenprognosen verwendet werden,
Da die Zeitreihenmodelle in der Lage sind, zeitliche Abhängigkeiten in den Daten zu erfassen, können sie eine realistische Lösung bieten, wenn es darum geht, Vorhersagen für den Devisenmarkt zu treffen, da wir alle wissen, dass das, was derzeit auf dem Markt passiert, auf einige Faktoren zurückzuführen sein könnte, die gerade erst kurz zuvor oder in der Vergangenheit passiert sind. So können beispielsweise Nachrichten, die vor 5 Minuten zum EURUSD veröffentlicht wurden, einer der Faktoren für eine starke Kursänderung zum aktuellen Zeitpunkt sein. Um dies besser zu verstehen, sollten wir uns die Vorteile der Zeitreihenprognose im Vergleich zur traditionellen Prognose mit Hilfe von Modellen des maschinellen Lernens ansehen.
Aspekt | Zeitreihenprognose | Traditionelle und moderne ML-Prognosen |
---|---|---|
Zeitliche Abhängigkeiten | Sie sind in der Lage, zeitliche Muster zu erfassen, da sie die Reihenfolge der Datenpunkte und die Abhängigkeiten im Zeitverlauf berücksichtigen. | Traditionelle ML-Modelle behandeln Datenpunkte als unabhängig und ignorieren dabei zeitliche Abhängigkeiten in den Daten. |
Umgang mit Trends und Saisonalität | Zeitreihenmodelle wie ARIMA und einige andere haben integrierte Komponenten zur Behandlung von Trends und Saisonalität | Erfordert manuelle Extraktion und Entwicklung von Merkmalen zur Erfassung von Trends und Saisonalität. |
Autokorrelation | Modelle wie ARIMA und LSTMs können die Autokorrelation in den Daten berücksichtigen. | Sie gehen davon aus, dass jedes Merkmal unabhängig ist, sodass sie Autokorrelation nicht berücksichtigen können, sofern sie nicht explizit in den Merkmalen modelliert ist. |
Komplexität der Modelle | Zeitreihenmodelle sind für sequenzielle Daten konzipiert und eignen sich daher besser für solche Aufgaben. | Herkömmliche Modelle erfordern möglicherweise ein Feature-Engineering, um sequentielle Daten angemessen zu behandeln. Dies erhöht die Komplexität des Prozesses |
Zeitliche Hierarchien | Kann natürlich auf hierarchische Zeitreihenprognosen erweitert werden (z. B. monatlich, wöchentlich). | Herkömmliche Modelle können ohne zusätzliche technische Hilfsmittel Probleme mit der Vorhersage auf mehreren zeitlichen Skalen haben. |
Prognoseleistung | Ergibt oft eine bessere Vorhersageleistung bei zeitabhängigen Aufgaben, da die Reihenfolge berücksichtigt wird. | Kann bei zeitabhängigen Aufgaben unterdurchschnittlich abschneiden. |
Rechnerische Effizienz | Zeitreihenmodelle können inkrementell und effizient mit neuen Daten aktualisiert werden. | Herkömmliche Modelle müssen möglicherweise komplett neu trainiert werden, was bei neuen Daten rechenintensiver ist. |
Interpretierbare Trends und Saisonalität | Modelle wie ARIMA liefern interpretierbare Komponenten für Trend und Saisonalität. | Erfordert zusätzliche Schritte zur Interpretation von Trends und saisonalen Schwankungen anhand von konstruierten Merkmalen. |
Klassische und moderne maschinelle Lernmodelle wie LightGBM, XGBoost, CatBoost usw. sind zwar standardmäßig nicht gut für Zeitreihenprognosen geeignet. Sie können dennoch für Zeitreihenvorhersagen verwendet werden, wenn die richtigen Informationen vorliegen. Der Schlüssel dazu liegt im Feature Engineering.
Merkmalstechniken für Zeitreihenprognosen
Bei der Zeitreihenprognose geht es darum, neue Merkmale zu erstellen und bestehende Merkmale so aufzubereiten, dass sie wichtige Informationen/Komponenten für Zeitreihen enthalten, wie z. B.: Trend, Saisonalität, zyklische Muster, Stationarität, Autokorrelation und partielle Autokorrelation, usw.
Es gibt viele Aspekte, die Sie berücksichtigen können, wenn Sie neue Merkmale für ein Zeitreihenproblem erstellen; im Folgenden sind einige davon aufgeführt:
01: Verzögert auftretende Merkmale
In den Daten für das klassische maschinelle Lernen sammeln wir oft Daten wie OPEN, HIGH, LOW, CLOSE und einige andere Daten zum aktuellen Balken. Diese enthält die aktuellen Informationen zu jedem einzelnen Balken und bietet keine Informationen darüber, was vor diesem bestimmten Balken geschah.
Indem wir verzögerte Merkmale in unsere Daten einführen, stellen wir sicher, dass wir zeitliche Abhängigkeiten von früheren Bars erfassen, die definitiv etwas mit dem aktuellen Barrenpreis zu tun haben.
MQL5
//--- getting Open, high, low and close prices ohlc_struct OHLC; OHLC.AddCopyRates(Symbol(), timeframe, start_bar, bars); time_vector.CopyRates(Symbol(), timeframe, COPY_RATES_TIME, start_bar, bars); //--- Getting the lagged values of Open, High, low and close prices ohlc_struct lag_1; lag_1.AddCopyRates(Symbol(), timeframe, start_bar+1, bars); ohlc_struct lag_2; lag_2.AddCopyRates(Symbol(), timeframe, start_bar+2, bars); ohlc_struct lag_3; lag_3.AddCopyRates(Symbol(), timeframe, start_bar+3, bars);
Im obigen Beispiel sind es nur drei Verzögerungen. Da wir diese Daten täglich sammeln, erhalten wir die Informationen der drei vorhergehenden Tage für 1000 Balken.
Durch das Kopieren der MqlRates in Vektoren, die bei start_bar+1 beginnen, erhalten wir den vorherigen Balken als beim Kopieren der Kurse ab start_bar. Dies kann manchmal verwirrend sein. Bitte besuchen Sie https://www.mql5.com/en/docs/series
MQL5
input int bars = 1000; input ENUM_TIMEFRAMES timeframe = PERIOD_D1; input uint start_bar = 2; //StartBar|Must be >= 1 struct ohlc_struct { vector open; vector high; vector low; vector close; matrix MATRIX; //this stores all the vectors all-together void AddCopyRates(string symbol, ENUM_TIMEFRAMES tf, ulong start, ulong size) { open.CopyRates(symbol, tf, COPY_RATES_OPEN, start, size); high.CopyRates(symbol, tf, COPY_RATES_HIGH, start, size); low.CopyRates(symbol, tf, COPY_RATES_LOW, start, size); close.CopyRates(symbol, tf, COPY_RATES_CLOSE, start, size); this.MATRIX.Resize(open.Size(), 4); //we resize it to match one of the vector since all vectors are of the same size this.MATRIX.Col(open, 0); this.MATRIX.Col(high, 1); this.MATRIX.Col(low, 2); this.MATRIX.Col(close, 3); } };
02: Rollierende Statistik
Rollierende Statistiken wie Mittelwert, Standardabweichungen und andere Statistiken dieser Art helfen, die jüngsten Trends und die Volatilität innerhalb eines Zeitfensters zusammenzufassen. Hier kommen einige Indikatoren ins Spiel, wie z. B. der gleitende Durchschnitt für einen bestimmten Zeitraum, die Standardabweichung für eine bestimmte Zeit usw.
int ma_handle = iMA(Symbol(),timeframe,30,0,MODE_SMA,PRICE_WEIGHTED); //The Moving averaege for 30 days int stddev = iStdDev(Symbol(), timeframe, 7,0,MODE_SMA,PRICE_WEIGHTED); //The standard deviation for 7 days vector SMA_BUFF, STDDEV_BUFF; SMA_BUFF.CopyIndicatorBuffer(ma_handle,0,start_bar, bars); STDDEV_BUFF.CopyIndicatorBuffer(stddev, 0, start_bar, bars);
Diese rollierenden Statistiken vermitteln ein umfassenderes Bild von den Marktveränderungen und erfassen möglicherweise langfristige Schwankungen, die in den verzögerten Merkmalen nicht erkennbar sind.
03: Datum-Zeit-Funktionen
Wie bereits erwähnt, verfügen Zeitreihendaten über eine Zeitvariable, aber nur eine Datum-Zeit-Variable zu haben, ist nicht sehr hilfreich, wir müssen ihre Merkmale extrahieren.
Wie wir wissen, weist der Devisenmarkt einige Muster auf oder verhält sich zu bestimmten Zeiten auf eine bestimmte Weise. Ein Beispiel: Freitags wird in der Regel nicht viel gehandelt, und der Markt ist volatil, wenn es an diesem Tag ein neues Ereignis gibt. Auch können sich die Handelsaktivitäten in einigen Monaten zum Besseren oder Schlechteren verändern, das gleiche gilt für einige Jahre. Zum Beispiel in Wahljahren in einigen Ländern wie den US-Wahlen.
Durch die Einführung von Datum-Zeit-Merkmalen erfassen wir explizit saisonale Muster, sodass unser Modell die Vorhersagen auf der Grundlage der Jahreszeit, eines bestimmten Tages oder Monats usw. anpassen kann.
Lassen Sie uns Datum-Zeit-Merkmale in MQL5 sammeln:
vector time_vector; //we want to add time vector time_vector.CopyRates(Symbol(), timeframe, COPY_RATES_TIME, start_bar, bars); //copy the time in seconds ulong size = time_vector.Size(); vector DAY(size), DAYOFWEEK(size), DAYOFYEAR(size), MONTH(size); MqlDateTime time_struct; string time = ""; for (ulong i=0; i<size; i++) { time = (string)datetime(time_vector[i]); //converting the data from seconds to date then to string TimeToStruct((datetime)StringToTime(time), time_struct); //convering the string time to date then assigning them to a structure DAY[i] = time_struct.day; DAYOFWEEK[i] = time_struct.day_of_week; DAYOFYEAR[i] = time_struct.day_of_year; MONTH[i] = time_struct.mon; }
04: Differenzierung
Durch die Differenzierung der Reihen mit saisonalen Verzögerungen werden saisonale Muster aus den Daten entfernt, um Stationarität zu erreichen, was für einige Modelle oft eine Voraussetzung ist.
Versuchen wir eine Differenzierung mit Lag1 von den aktuellen Preisen.
MQL5
vector diff_lag_1_open = OHLC.open - lag_1.open; vector diff_lag_1_high = OHLC.high - lag_1.high; vector diff_lag_1_low = OHLC.low - lag_1.low; vector diff_lag_1_close = OHLC.close - lag_1.close;
Sie können so viele „lags“ differenzieren, wie Sie wollen, Sie sind nicht auf „lag 1“ beschränkt.
Bis zu diesem Punkt haben wir 26 unabhängige Variablen/Merkmale, was für unsere unabhängigen Variablen ausreichend ist. Da wir versuchen, ein Regressionsproblem zu lösen, wollen wir die Schlusskurse als endgültige Zielvariable verwenden.
vector TARGET_CLOSE; TARGET_CLOSE.CopyRates(Symbol(), timeframe, COPY_RATES_CLOSE, start_bar-1, bars); //one bar forward
Fühlen Sie sich frei, weitere Funktionen für Ihr Problem zu erstellen, indem Sie andere Aspekte berücksichtigen, die wir unten nicht berücksichtigt haben.
05: Externe Variablen (exogene Faktoren)
- Wetterdaten: Versuchen Sie herauszufinden, ob es hilft
- Wirtschaftsindikatoren: für Finanzprognosen, einschließlich BIP, Arbeitslosenquoten usw.
06: Fourier- und Wavelet-Transformationen
Verwendung von Fourier- oder Wavelet-Transformationen zur Extraktion zyklischer Muster und Trends im Frequenzbereich.
07: Ziel-Kodierung
Sie können Merkmale erstellen, die auf aggregierten Statistiken (Mittelwert, Median) der Zielvariablen über verschiedene Zeiträume basieren.
Der endgültige Datensatz hat 27 Spalten:
Training des Regressormodells LightGBM
Da wir nun alle benötigten Daten haben, wollen wir uns nun der Python-Seite zuwenden.
Wir können damit beginnen, die Daten in Trainings- und Testproben aufzuteilen.
Python
X = df.drop(columns=["TARGET_CLOSE"]) Y = df["TARGET_CLOSE"] train_size = 0.7 #configure train size train_size = round(train_size*df.shape[0]) x_train = X.iloc[:train_size,:] x_test = X.iloc[train_size:, :] y_train = Y.iloc[:train_size] y_test = Y.iloc[train_size:] print(f"x_train_size{x_train.shape}\nx_test_size{x_test.shape}\n\ny_train{y_train.shape}\ny_test{y_test.shape}")Ergebnisse
x_train_size(700, 26) x_test_size(300, 26) y_train(700,) y_test(300,)
Wir wollen das Modell an die Trainingsdaten anpassen.
model = lgb.LGBMRegressor(**params) model.fit(x_train, y_train)
Testen wir das trainierte Modell und zeichnen wir die Vorhersagen und r2_score.
Python
from sklearn.metrics import r2_score test_pred = model.predict(x_test) accuracy = r2_score(y_test, test_pred) #showing actual test values and predictions plt.figure(figsize=(8, 6)) plt.plot(y_test, label='Actual Values') plt.plot(test_pred, label='Predicted Values') plt.xlabel('Index') plt.ylabel('Values') plt.title('Actual vs. Predicted Values') plt.legend(loc="lower center") # Add R-squared (accuracy) score in a corner plt.text(0.05, 0.95, f"LightGBM (Accuracy): {accuracy:.4f}", ha='left', va='top', transform=plt.gca().transAxes, fontsize=10, bbox=dict(boxstyle='round', facecolor='white', alpha=0.7)) plt.grid(True) plt.savefig("LighGBM Test plot") plt.show()
Ergebnis:
Das Modell hat eine Genauigkeit von 84 % bei der Vorhersage der Schlusskurse unter Verwendung aller Daten, die ihm zur Verfügung standen. Obwohl dies eine gute Genauigkeit zu sein scheint, müssen wir unsere Variablen für weitere Analysen und Modellverbesserungen untersuchen.
Unter Verwendung der in LightGBM integrierten Darstellung der Wichtigkeit von Merkmalen ergibt sich die folgende Darstellung.
Python
# Plot feature importance using Gain lgb.plot_importance(model, importance_type="gain", figsize=(8,6), title="LightGBM Feature Importance (Gain)") plt.tight_layout() plt.savefig("LighGBM feature importance(Gain)") plt.show()
Das Ergebnis:
Merkmalsbedeutung: bezieht sich auf Techniken, die den relativen Beitrag jedes Merkmals (Variable) in einem Datensatz zu den Vorhersagen des Modells bewerten. Sie hilft uns zu verstehen, welche Merkmale den größten Einfluss auf die Vorhersagen des Modells haben.
Es ist wichtig zu wissen, dass baumbasierte Methoden wie LightGBM und XGBoost die Wichtigkeit von Merkmalen anders berechnen als nicht baumbasierte Modelle. Sie berücksichtigen, wie oft ein Merkmal für Splitting-Entscheidungen in den Bäumen verwendet wird und wie sich diese Splits auf die endgültige Vorhersage auswirken.
Alternativ können Sie auch SHAP verwenden, um die Wichtigkeit von Merkmalen zu prüfen.
Python:
explainer = shap.TreeExplainer(model) shap_values = explainer(x_train) shap.summary_plot(shap_values, x_train, max_display=len(x_train.columns), show=False) # Show all features # Adjust layout and set figure size plt.subplots_adjust(left=0.12, bottom=0.1, right=0.9, top=0.9) plt.gcf().set_size_inches(6, 8) plt.tight_layout() plt.savefig("SHAP_Feature_Importance_Summary_Plot.png") plt.show()
Das Ergebnis:
Aus der Merkmalswichtigkeit geht hervor, dass die Variablen zur Erfassung saisonaler Muster wie DAYOFWEEK, MONTH, DAYOFMONTH und DAYOFYEAR zu den Variablen mit dem geringsten Beitrag zu den Vorhersagen des Modells gehören.
Seltsamerweise sind diese nach dem Augmented Dickey Fuller Test. alle stationär.
Augmented Dickey-Fuller (ADF) Test
Dies ist ein statistischer Test, der verwendet wird, um festzustellen, ob ein Zeitreihendatensatz stationär ist oder nicht. Stationarität ist eine entscheidende Eigenschaft für viele Methoden der Zeitreihenprognose und -analyse.
Eine stationäre Variable oder ein stationärer Datensatz bezieht sich auf eine Reihe, bei der die statistischen Eigenschaften (Mittelwert, Varianz, Autokorrelation) im Laufe der Zeit konstant bleiben. Zum Beispiel auf dem Aktienmarkt. Der Mittelwert der OHLC-Werte kann im Laufe der Zeit drastisch ansteigen oder abfallen, sodass diese Werte größtenteils nicht stationär sind, während ihre Renditen, wie z. B. der Mittelwert oder die Varianz der Differenz zwischen Hoch und Tief, im Laufe der Zeit stationär sind.
Ich habe diesen Test mit dem gesamten Datensatz durchgeführt, den wir haben.
from statsmodels.tsa.stattools import adfuller def adf_test(series, signif=0.05): """ Performs the ADF test on a pandas Series and interprets the results. Args: series: The pandas Series containing the time series data. signif: Significance level for the test (default: 0.05). Returns: A dictionary containing the test statistic, p-value, used lags, critical values, and interpretation of stationarity. """ dftest = adfuller(series, autolag='AIC') adf_stat = dftest[0] # Access test statistic pvalue = dftest[1] # Access p-value usedlag = dftest[2] # Access used lags critical_values = dftest[4] # Access critical values interpretation = 'Stationary' if pvalue < signif else 'Non-Stationary' result = {'Statistic': adf_stat, 'p-value': pvalue, 'Used Lags': usedlag, 'Critical Values': critical_values, 'Interpretation': interpretation} return result
for col in df.columns: adf_results = adf_test(df[col], signif=0.05) print(f"ADF Results for column {col}:\n {adf_results}")
Von den 27 Variablen wurden nur 9 Variablen als stationär erkannt. Diese Variablen sind:
- 7DAY_STDDEV
- DAYOFMONTH
- DAYOFWEEK
- DAYOFYEAR
- MONTH
- DIFF_LAG1_OPEN
- DIFF_LAG1_HIGH
- DIFF_LAG1_LOW
- DIFF_LAG1_CLOSE
Um herauszufinden, ob die Variablen stationär sind oder nicht, können Sie sich einfach das Verteilungsdiagramm ansehen. Bei gut um den Mittelwert verteilten Daten handelt es sich höchstwahrscheinlich um stationäre Daten.
Warum ist Stationarität wichtig?
Viele statistische Methoden, die in der Zeitreihenanalyse und -prognose eingesetzt werden, gehen von Stationarität aus. Wenn eine Zeitreihe nicht stationär ist, können diese Methoden irreführende oder ungenaue Ergebnisse liefern.
Stellen Sie sich vor, Sie versuchen, zukünftige Aktienkurse zu prognostizieren, wenn die Kurse ständig nach oben tendieren. Das Zeitreihenmodell wäre nicht in der Lage, den zugrunde liegenden Trend zu erfassen.
Klassische oder sogar so genannte moderne maschinelle Lernmodelle wie das von uns verwendete LightGBM sind in der Lage, nichtlineare Beziehungen zwischen den Merkmalen zu verarbeiten, wodurch sie weniger von der in den Daten vorhandenen Stationarität beeinflusst werden. Die Bedeutung der Merkmale für dieses Modell hat deutlich gezeigt, dass die wichtigsten Merkmale für unser Modell nicht-stationäre OHLC-Variablen sind.
Das bedeutet jedoch nicht, dass Variablen wie der Wochentag keinen Einfluss auf das Modell haben. Die Bedeutung von Funktionen ist nur ein Teil des Ganzen. Meiner Meinung nach ist Fachwissen weiterhin erforderlich.
Es besteht keine Notwendigkeit, diese Variable fallen zu lassen, weil sie niedriger eingestuft ist, da ich davon überzeugt bin, dass sie den EURUSD beeinflusst.
Vorhersage einer stationären Zielvariablen
Eine stationäre Zielvariable verbessert die Leistung vieler Modelle des maschinellen Lernens, wenn es um Zeitreihenprognosen geht, da stationäre Daten eine Konstante (Mittelwert, Varianz, Autokorrelation) über die Zeit aufweisen. Wie Sie wissen, ist die Vorhersage, wohin sich der Markt in der nächsten Kerze bewegen wird, schwierig, aber die Vorhersage der Anzahl der Pips oder Punkte für die nächste Bewegung ist nicht sehr schwierig.
Wenn wir vorhersagen können, wie viele Punkte der nächste Balken generieren wird, können wir dies nutzen, um Handelsziele festzulegen (Stop-Loss und Take-Profit).
Um dies zu erreichen, müssen wir eine Differenzierung erster Ordnung finden, indem wir den vorherigen Schlusskurs vom nächsten Schlusskurs subtrahieren.
Python
Y = df["TARGET_CLOSE"] - df["CLOSE"] # first order differencing
Durch Differenzierung der nächstgelegenen Preise mit den vorherigen erhalten wir eine stationäre Variable.
adf_results = adf_test(Y,signif=0.05)
print(f"ADF Results:\n {adf_results}")
Ergebnisse:
ADF Results: {'Statistic': -23.37891429248752, 'p-value': 0.0, 'Used Lags': 1, 'Critical Values': {'1%': -3.4369193380671, '5%': -2.864440383452517, '10%': -2.56831430323573}, 'Interpretation': 'Stationary'}
Nach der Anpassung des Regressor-Modells an die neue stationäre Zielvariable und der Bewertung seiner Leistung anhand des Testdatensatzes ergab sich folgendes Bild.
Das Modell hatte eine schlechte Leistung, wenn die Zielvariable stationär war. Wie immer beim maschinellen Lernen kann es viele Faktoren geben, die zu diesem Ergebnis führen, aber für den Moment werden wir zu dem Schluss kommen, dass LightGBM bei stationären Zielvariablen nicht gut funktioniert. Wir bleiben bei dem Regressionsmodell, das für die Vorhersage der Zielschlusswerte erstellt wurde.
Dieses Regressionsmodell, das kontinuierliche Schlusskurse vorhersagt, ist nicht so nützlich wie ein Modell, das die Handelssignale wie Kauf oder Verkauf vorhersagt; um dies zu erreichen, müssen wir ein weiteres Modell zur Vorhersage der Handelssignale erstellen.
Aufbau eines Klassifizierungsmodell LightGBM
Um ein Klassifizierungsmodell zu erstellen, müssen wir die Zielvariable als binäre Zielvariable vorbereiten, wobei 1 für ein Kaufsignal und 0 für ein Verkaufssignal steht.
Python
Y = [] target_open = df["TARGET_OPEN"] target_close = df["TARGET_CLOSE"] for i in range(len(target_open)): if target_close[i] > target_open[i]: # if the candle closed above where it opened thats a buy signal Y.append(1) else: #otherwise it is a sell signal Y.append(0) # split Y into irrespective training and testing samples y_train = Y[:train_size] y_test = Y[train_size:]
Ich habe das LightGBM-Modell in einer Pipeline mit der Technik StandardScaler trainiert.
Python
from sklearn.pipeline import Pipeline from sklearn.preprocessing import StandardScaler params = { 'boosting_type': 'gbdt', # Gradient Boosting Decision Tree 'objective': 'binary', # For binary classification (use 'regression' for regression tasks) 'metric': ['auc','binary_logloss'], # Evaluation metric 'num_leaves': 25, # Number of leaves in one tree 'n_estimators' : 100, # number of trees 'max_depth': 5, 'learning_rate': 0.05, # Learning rate 'feature_fraction': 0.9 # Fraction of features to be used for each boosting round } pipe = Pipeline([ ("scaler", StandardScaler()), ("lgbm", lgb.LGBMClassifier(**params)) ]) # Fit the pipeline to the training data pipe.fit(x_train, y_train)
Die Testergebnisse waren mit einer Gesamtgenauigkeit von 53 % nicht sonderlich überraschend.
Klassifizierungsbericht:
Classification Report precision recall f1-score support 0 0.49 0.79 0.61 139 1 0.62 0.30 0.40 161 accuracy 0.53 300 macro avg 0.56 0.54 0.51 300 weighted avg 0.56 0.53 0.50 300
Konfusionsmatrix
Speichern des LightGBM-Klassifikatormodells in ONNX
Wie bereits zuvor ist das Speichern des LightGBM-Modells im ONNX-Format unkompliziert und erfordert nur wenige Codezeilen.
import onnxmltools from onnxmltools.convert import convert_lightgbm import onnxmltools.convert.common.data_types from skl2onnx.common.data_types import FloatTensorType from skl2onnx import convert_sklearn, update_registered_converter from skl2onnx.common.shape_calculator import ( calculate_linear_classifier_output_shapes, ) # noqa from onnxmltools.convert.lightgbm.operator_converters.LightGbm import ( convert_lightgbm, ) # noqa # registering onnx converter update_registered_converter( lgb.LGBMClassifier, "GBMClassifier", calculate_linear_classifier_output_shapes, convert_lightgbm, options={"nocl": [False], "zipmap": [True, False, "columns"]}, ) # Final LightGBM conversion to ONNX model_onnx = convert_sklearn( pipe, "pipeline_lightgbm", [("input", FloatTensorType([None, x_train.shape[1]]))], target_opset={"": 12, "ai.onnx.ml": 2}, ) # And save. with open("lightgbm.Timeseries Forecasting.D1.onnx", "wb") as f: f.write(model_onnx.SerializeToString())
Packen wir alles in einen Handelsroboter
Da wir nun ein maschinelles Lernmodell in ONNX gespeichert haben, können wir es direkt in einen Expert Advisor einbinden und den LightGBM-Klassifikator für Zeitreihenvorhersagen in MetaTrader 5 verwenden.
MQL5
#resource "\\Files\\lightgbm.Timeseries Forecasting.D1.onnx" as uchar lightgbm_onnx[] //load the saved onnx file #include <MALE5\LightGBM\LightGBM.mqh> CLightGBM lgb;
Mit der im vorherigen Artikel erstellten LightGBM-Klasse konnte ich das Modell initialisieren und für Vorhersagen verwenden.
int OnInit() { //--- if (!lgb.Init(lightgbm_onnx)) //Initialize the LightGBM model return INIT_FAILED; //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- if (NewBar()) //Trade at the opening of a new candle { vector input_vector = input_data(); long signal = lgb.predict_bin(input_vector); //--- MqlTick ticks; SymbolInfoTick(Symbol(), ticks); if (signal==1) //if the signal is bullish { if (!PosExists(POSITION_TYPE_BUY)) //There are no buy positions { if (!m_trade.Buy(lotsize, Symbol(), ticks.ask, ticks.bid-stoploss*Point(), ticks.ask+takeprofit*Point())) //Open a buy trade printf("Failed to open a buy position err=%d",GetLastError()); } } else if (signal==0) //Bearish signal { if (!PosExists(POSITION_TYPE_SELL)) //There are no Sell positions if (!m_trade.Sell(lotsize, Symbol(), ticks.bid, ticks.ask+stoploss*Point(), ticks.bid-takeprofit*Point())) //open a sell trade printf("Failed to open a sell position err=%d",GetLastError()); } else //There was an error return; } }
Die Funktion input_data() ist für das Sammeln von Daten zuständig, ähnlich der Art und Weise, wie die Daten im Skript gesammelt und in einer CSV-Datei gespeichert wurden Feature engineering Timeseries forecasting.mq5.
Testen des Modells mit dem Strategietester.
Schließlich können wir das Modell in der Handelsumgebung testen. Da die Daten von einem täglichen Zeitrahmen gesammelt wurden, könnte es eine gute Idee sein, sie auf einem niedrigeren Zeitrahmen zu testen, um Fehler „Markt geschlossen“ zu vermeiden, da wir für den Handel Signal bei der Eröffnung eines neuen bar suchen. Wir können auch die Modellierungsart auf offene Preise einstellen, um schneller zu testen.
Der EA traf in ca. 5 % der Fälle die richtigen Vorhersagen, wenn man den Stop-Loss und den Take-Profit auf 500 bzw. 700 Punkte setzt.
Auch die Salden-/Kapitalkurve war beeindruckend.
Vorteile der Verwendung klassischer und moderner ML-Modelle für die Zeitreihenprognose
Die Verwendung von maschinellen Lernmodellen, die nicht auf Zeitreihen basieren, für Zeitreihenprognosen hat mehrere Vorteile. Im Folgenden sind einige der wichtigsten Vorteile aufgeführt:
1. Flexibilität bei der Entwicklung von Merkmalen
Klassische maschinelle Lernmodelle ermöglichen umfangreiche Merkmalestechniken, das zur Einbeziehung verschiedener externer Variablen und abgeleiteter Merkmale genutzt werden kann. Sie können Ihren menschlichen Intellekt einsetzen, um alle Daten, die Sie für nützlich halten, manuell zu analysieren und einzubeziehen, einschließlich komplexer Merkmale wie Verzögerungen und rollierende Statistiken, wie wir es in diesem Beitrag getan haben.
2. Umgang mit Nicht-Stationarität
Anstatt die Reihen durch Differenzierung stationär zu machen, können Sie Trend und Saisonalität direkt als Merkmale einbeziehen, und das Modell wird die Muster ohne Probleme lernen.
3. Keine Annahmen über die Datenverteilung
Viele klassische Zeitreihenmodelle (wie ARIMA) gehen davon aus, dass die Daten einer bestimmten statistischen Verteilung folgen. Klassische und moderne ML-Modelle sind dagegen flexibler, was die Datenverteilung angeht.
Modelle wie Entscheidungsbäume, Random Forests und Gradient Boosting (einschließlich LightGBM) gehen nicht von einer bestimmten Verteilung der Daten aus.
4. Skalierbarkeit
Klassische ML-Modelle können große Datensätze effizienter verarbeiten und sind oft einfacher zu skalieren.
5. Komplexe Wechselwirkungen
Klassische ML-Modelle können komplexe, nicht-lineare Beziehungen zwischen Merkmalen und der Zielvariablen erfassen.
6. Robustheit gegenüber fehlenden Daten
Modelle des maschinellen Lernens verfügen oft über bessere Mechanismen für den Umgang mit fehlenden Daten als traditionelle Zeitreihenmodelle.
7. Ensemble-Methoden
Sie können problemlos Ensemble-Methoden wie Bagging, Boosting und Stacking verwenden, um die Modellleistung zu verbessern, indem Sie mehrere Modelle kombinieren, um die Vorhersageleistung und Robustheit zu verbessern.
8. Nutzerfreundlichkeit und Integration
Klassische ML-Modelle sind oft nutzerfreundlicher und verfügen über umfangreiche Bibliotheken und Tools für die Implementierung, Visualisierung und Auswertung.
Bibliotheken wie Scikit-learn, LightGBM und XGBoost bieten umfassende Tools für die Erstellung, Abstimmung und Bewertung dieser Modelle.
Die Quintessenz
Sowohl klassische als auch moderne Modelle des maschinellen Lernens können problemlos für die Zeitreihenanalyse und -prognose verwendet werden und können Zeitreihenmodelle mit den richtigen Informationen, der richtigen Abstimmung und den in diesem Artikel beschriebenen Verfahren übertreffen. Ich habe mich für LightGBM als Beispiel entschieden, aber jedes klassische oder moderne maschinelle Lernmodell wie SVM, lineare Regression, Naïve Bayes, XGBoost usw. kann angewendet werden.
Peace out.
Verfolgen Sie die Entwicklung von Modellen für maschinelles Lernen und vieles mehr in dieser Artikelserie auf diesem GitHub repo.
Tabelle der Anhänge
Dateiname | Dateityp | Beschreibung und Verwendung |
---|---|---|
LightGBM timeseries forecasting.mq5 | Expert Advisor | Handelsroboter zum Laden des ONNX-Modells und Testen der endgültigen Handelsstrategie in MetaTrader 5. |
lightgbm.Timeseries Forecasting.D1.onnx | ONNX | LightGBM-Modell im ONNX-Format. |
LightGBM.mqh | einzubinden (Bibliothek) | Besteht aus dem Code zum Laden des ONNX-Modellformats und zum Einsatz in der nativen Sprache MQL5. |
Feature engineering Timeseries forecasting.mq5 | ein Skript | Dies ist ein Skript, in dem alle Daten gesammelt und für die Zeitreihenanalyse und -prognose aufbereitet werden. |
forex-timeseries-forecasting-lightgbm.ipynb | Python-Skript (Jupyter Notebook) | Der gesamte Python-Code, der in diesem Artikel besprochen wird, ist in diesem Notebook zu finden. |
Quellen und Referenzen:
- Zeitreihengespräch: Stationarität (https://youtu.be/oY-j2Wof51c)
- Kishan Manani - Merkmalstechnik für Zeitreihenprognosen | PyData London 2022 (https://www.youtube.com/watch?v=9QtL7m3YS9I)
- Aktienmarktvorhersage durch Deep Learning-Techniken: Ein Überblick (https://arxiv.org/abs/2212.12717)
- Herausforderungen bei der Zeitreihenprognose (https://www.youtube.com/watch?v=rcdDl8qf0ZA)
- Stationarität und Differenzbildung (https://otexts.com/fpp2/stationarity.html)
- Ziel/Mittelwert-Kodierung für kategorische Attribute | Python (https://www.youtube.com/watch?v=nd7vc4MZQz4)
Übersetzt aus dem Englischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/en/articles/15013
![Aufbau des Kerzenmodells Trend-Constraint (Teil 5): Nachrichtensystem (Teil II)](https://c.mql5.com/2/82/Building_A_Candlestick_Trend_Constraint_Model_Part_5__NEXT_LOGO_2.png)
![Integrieren Sie Ihr eigenes LLM in EA (Teil 4): Trainieren Sie Ihr eigenes LLM mit GPU](https://c.mql5.com/2/82/Integrate_Your_Own_LLM_into_EA_Part_4____LOGO.png)
![Erstellung von Zeitreihenvorhersagen mit neuronalen LSTM-Netzen: Normalisierung des Preises und Tokenisierung der Zeit](https://c.mql5.com/2/82/Creating_Time_Series_Predictions_using_LSTM_Neural_Networks___LOGO.png)
![Aufbau des Kerzenmodells Trend-Constraint (Teil 5): Nachrichtensystem (Teil I)](https://c.mql5.com/2/81/Building_A_Candlestick_Trend_Constraint_Model_Part_5___LOGO.png)
![MQL5 - Sprache von Handelsstrategien, eingebaut ins Kundenterminal MetaTrader 5](https://c.mql5.com/i/registerlandings/logo-2.png)
- 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.