English
preview
Datenwissenschaft und maschinelles Lernen (Teil 24): Zeitreihenprognose im Forex mit regulären AI-Modellen

Datenwissenschaft und maschinelles Lernen (Teil 24): Zeitreihenprognose im Forex mit regulären AI-Modellen

MetaTrader 5Handel | 30 Juli 2024, 10:07
20 0
Omega J Msigwa
Omega J Msigwa

Inhalt


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.

  1. Zeit

     Hierbei handelt es sich um eine unabhängige Variable, die die spezifischen Zeitpunkte angibt, zu denen die Datenpunkte beobachtet wurden.

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

mql5 zeitreihenprognose bild

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, 

Zeitreihenprognose ML-Modelle

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:

Zeitreihenprognosedatensatz


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:

Testdarstellung LightGBM

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:

Bedeutung des Zeitreihen-OHLC-Merkmals

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:

Merkmalswichtigkeit von Zeitreihendaten mit SHARP

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: 

  1. 7DAY_STDDEV
  2. DAYOFMONTH
  3. DAYOFWEEK
  4. DAYOFYEAR
  5. MONTH
  6. DIFF_LAG1_OPEN
  7. DIFF_LAG1_HIGH
  8. DIFF_LAG1_LOW
  9. 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.

Stationär vs. nicht stationär

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.

LightGBM Zeitreihenprognose stationäres Ziel

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

Konfusionsmatrix lightGBM


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.

Tester-Einstellungen

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.

Metatrader 5 Strategie-Tester-Bericht

Auch die Salden-/Kapitalkurve war beeindruckend.

Metatrader 5-Tester-Grafik



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:



Übersetzt aus dem Englischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/en/articles/15013

Beigefügte Dateien |
Attachments.zip (317.52 KB)
Aufbau des Kerzenmodells Trend-Constraint (Teil 5): Nachrichtensystem (Teil II) Aufbau des Kerzenmodells Trend-Constraint (Teil 5): Nachrichtensystem (Teil II)
Heute besprechen wir eine funktionierende Telegram-Integration für MetaTrader 5 Indikator-Benachrichtigungen, die die Leistungsfähigkeit von MQL5 in Zusammenarbeit mit Python und der Telegram Bot API nutzt. Wir werden alles im Detail erklären, damit niemand etwas verpasst. Am Ende dieses Projekts werden Sie wertvolle Erkenntnisse gewonnen haben, die Sie in Ihren Projekten anwenden können.
Integrieren Sie Ihr eigenes LLM in EA (Teil 4): Trainieren Sie Ihr eigenes LLM mit GPU Integrieren Sie Ihr eigenes LLM in EA (Teil 4): Trainieren Sie Ihr eigenes LLM mit GPU
Angesichts der rasanten Entwicklung der künstlichen Intelligenz sind Sprachmodelle (language models, LLMs) heute ein wichtiger Bestandteil der künstlichen Intelligenz, sodass wir darüber nachdenken sollten, wie wir leistungsstarke LLMs in unseren algorithmischen Handel integrieren können. Für die meisten Menschen ist es schwierig, diese leistungsstarken Modelle auf ihre Bedürfnisse abzustimmen, sie lokal einzusetzen und sie dann auf den algorithmischen Handel anzuwenden. In dieser Artikelserie werden wir Schritt für Schritt vorgehen, um dieses Ziel zu erreichen.
Erstellung von Zeitreihenvorhersagen mit neuronalen LSTM-Netzen: Normalisierung des Preises und Tokenisierung der Zeit Erstellung von Zeitreihenvorhersagen mit neuronalen LSTM-Netzen: Normalisierung des Preises und Tokenisierung der Zeit
In diesem Artikel wird eine einfache Strategie zur Normalisierung der Marktdaten anhand der täglichen Spanne und zum Training eines neuronalen Netzes zur Verbesserung der Marktprognosen beschrieben. Die entwickelten Modelle können in Verbindung mit einem bestehenden technischen Analysesystem oder auf eigenständiger Basis verwendet werden, um die allgemeine Marktrichtung vorherzusagen. Der in diesem Artikel skizzierte Rahmen kann von jedem technischen Analysten weiter verfeinert werden, um Modelle zu entwickeln, die sowohl für manuelle als auch für automatisierte Handelsstrategien geeignet sind.
Aufbau des Kerzenmodells Trend-Constraint (Teil 5): Nachrichtensystem (Teil I) Aufbau des Kerzenmodells Trend-Constraint (Teil 5): Nachrichtensystem (Teil I)
Wir werden den Hauptcode von MQL5 in bestimmte Codeschnipsel aufteilen, um die Integration von Telegram und WhatsApp für den Empfang von Signalnachrichten von dem Trend Constraint-Indikator zu veranschaulichen, den wir in dieser Artikelserie erstellen. Dies wird sowohl Anfängern als auch erfahrenen Entwicklern helfen, das Konzept leicht zu verstehen. Zunächst werden wir die Einrichtung von MetaTrader 5 für Nachrichten und deren Bedeutung für den Nutzer behandeln. Dies wird den Entwicklern helfen, im Voraus Notizen zu machen, die sie dann in ihren Systemen anwenden können.