English Русский 中文 Español 日本語 Português
preview
Neuinterpretation klassischer Strategien in MQL5 (Teil II): FTSE100 und britische Staatsanleihen

Neuinterpretation klassischer Strategien in MQL5 (Teil II): FTSE100 und britische Staatsanleihen

MetaTrader 5Beispiele | 13 November 2024, 09:47
105 0
Gamuchirai Zororo Ndawana
Gamuchirai Zororo Ndawana

Für den modernen Anleger gibt es potenziell unendlich viele Möglichkeiten, KI in seine Handelsstrategien zu integrieren. Es ist sehr unwahrscheinlich, dass ein einzelner Anleger genügend Zeit hat, um jede Strategie sorgfältig zu analysieren, bevor er sich entscheidet, welcher er sein Kapital anvertraut. In dieser Artikelserie werden wir die breite Palette möglicher Anwendungen von KI im Handelsumfeld untersuchen. Unser Ziel ist es, Ihnen zu helfen, eine Strategie zu finden, die für Ihr spezielles Anlegerprofil geeignet ist.


Überblick über die Handelsstrategie

Der Financial Times Stock Exchange 100 (FTSE100) ist ein weltweit anerkannter Index, der die Performance der 100 größten an der London Stock Exchange (LSE) notierten Unternehmen abbildet. Der Index wurde 1984 mit einem Wert von 1000 Punkten geschaffen und notiert derzeit bei etwa 8000 Punkten. Die Unternehmen im Index werden proportional zu ihrer Marktkapitalisierung gewichtet, was bedeutet, dass größere Unternehmen einen größeren Einfluss auf den Markt haben als kleinere Unternehmen.

Alle Regierungen in den Industrieländern begeben Verbindlichkeiten in ihrer Landeswährung, und die britische Regierung bildet da keine Ausnahme. Die Gilt ist ein britischer Staatsschuldtitel, der ebenfalls an der LSE notiert ist. Gilts sind festverzinsliche Wertpapiere, die es in 2 verschiedenen Arten gibt. Der erste Typ ist die konventionelle Schuldverschreibung, die den Großteil der Schuldverkäufe ausmacht. Diese konventionelle Schuldverschreibung zahlt dem Inhaber der Schuldverschreibung bis zur Fälligkeit einen festen Kupon, bei Fälligkeit werden der letzte Kupon und das Kapital an den Anleger zurückgezahlt.

Seit ihrer Einführung ist die britische Regierung mit keiner einzigen Kupon- oder Kapitalzahlung an die Inhaber von Schuldverschreibungen in Verzug geraten. Durch den Kauf einer Schuldverschreibung leiht der Inhaber der britischen Regierung im Grunde Geld. Die Investition in Anleihen bietet dem versierten Anleger wesentliche Vorteile, darunter vorhersehbare Erträge und geringe Ausfallrisiken, um nur einige zu nennen. Die Kapitalrendite ist ein gängiger Maßstab, um zu beurteilen, wie rentabel eine Anlage war. Die Redewendung impliziert, dass es mehr wert ist, sein Geld zurückzubekommen, als einen Gewinn zu erzielen und dabei das Risiko einzugehen, sein Kapital zu verlieren.


Die zweite Art von Schuld ist die indexgebundene Schuldverschreibung. Diese besondere Schuldverschreibung hat keinen festen Kupon, sondern die Auszahlungen aus der Anleihe dürfen schwanken, um den Anleger für die gesamte Inflation zu entschädigen, die während des Haltens der Schuldverschreibung aufgelaufen ist. Diese indexgebundenen Anleihen sind aufgrund ihrer unvorhersehbaren Cashflow-Ströme nicht so beliebt wie die festverzinslichen Anleihen.

Es besteht ein umgekehrtes Verhältnis zwischen der Rendite einer Anleihe und der Nachfrage nach einer Anleihe. Wenn eine bestimmte Anleihe von den Anlegern stark nachgefragt wird, sinkt die Rendite der Anleihe, und wenn die Anleihe eine schlechte Performance aufweist, steigt die Rendite, um das Interesse der Anleger zu wecken. 

Wenn sich die Aktienmärkte schlecht entwickeln, ziehen die Anleger in der Regel ihre Gelder aus dem risikoreichen Aktienmarkt ab und investieren sie lieber in sicherere Wertpapiere wie Staatsanleihen. Umgekehrt neigen die Anleger, wenn sie wieder Vertrauen in den Aktienmarkt gewinnen, dazu, ihre Mittel aus den sicheren Staatsanleihen abzuziehen und in den Aktienmarkt zu investieren. Der Hauptgrund für dieses Verhalten liegt in der Spanne der erwarteten Erträge. Der Aktienmarkt garantiert im Durchschnitt höhere Renditen als der Rentenmarkt und ist daher attraktiver. Der Aktienmarkt birgt jedoch ein größeres intrinsisches Risiko, sodass die Anleger sehr empfindlich auf Anzeichen von Schwäche reagieren. 



Überblick über die Methodik

Wir haben einen KI-gesteuerten Expert Advisor entwickelt, der seine eigenen Handelsregeln für die beiden Märkte lernt. Als Anleger sind wir in der Regel voreingenommen gegenüber Strategien, die uns gefallen. Wenn wir jedoch einen algorithmischen Lernansatz wählen, können wir sicher sein, dass unser Programm alle Entscheidungen auf der Grundlage der von uns gesammelten Daten trifft.

Finanzielle Zeitreihendaten sind notorisch verrauscht. Es ist bekannt, dass bei verrauschten Datensätzen einfachere Modelle genauso gut funktionieren können wie neuronale Netze. Daher haben wir ein lineares Regressionsmodell von Grund auf in MQL5 implementiert und dabei die Matrix- und Vektor-API verwendet. Wir haben unsere Eingabedaten standardisiert und skaliert, bevor wir unser Modell angepasst haben, da unsere Eingabedaten in unterschiedlichen Maßstäben vorliegen, das Gilts- und das UK100-Symbol haben unterschiedliche Maßstäbe. Wir haben die Pseudo-Inverse-Lösung zur Berechnung unserer Modellparameter verwendet.

Außerdem haben wir unser KI-Modell mit Hilfe der technischen Analyse gesteuert, sodass unser System nur dann in einen Handel einsteigt, wenn auch unsere technischen Indikatoren zu demselben Ergebnis führen. Schließlich haben wir auch unser KI-System eingesetzt, das uns hilft, potenzielle Umkehrungen zu erkennen und zu entscheiden, wann wir unsere Positionen schließen sollten. In unseren früheren Artikeln, als wir unsere linearen Modelle von Grund auf neu entwickelt haben, bemerkte einer der Nutzer, dass der Output des Modells außerhalb des akzeptablen Bereichs lag. In diesem Artikel haben wir versucht, dieses Problem zu lösen, indem wir eine Spalte für unseren Modellabstand (intercept) eingefügt und unsere Daten standardisiert und skaliert haben.


Implementation in MQL5

Für den Anfang haben wir zunächst ein Skript in MQL5 erstellt, um eine Vorstellung davon zu bekommen, wie alle Teile unseres Expert Advisors zusammenpassen werden. Zunächst müssen wir die Eingaben für unsere Anwendung definieren. Wir müssen festlegen, wie viele Daten wir abrufen und wie weit wir in die Zukunft schauen wollen. Je mehr Daten Sie abrufen, desto rechenintensiver wird die Anwendung letztendlich sein. Deshalb versuchen wir hier einen Ausgleich zu schaffen, indem wir dem Endnutzer erlauben, so viele Daten abzurufen, wie er glaubt, mit seinen Ressourcen bewältigen zu können. Außerdem sollten wir nicht vergessen, dass sich die Marktbewegungen ändern. Daher kann es sein, dass sich die Leistung nicht verbessert, wenn alle verfügbaren Daten abgerufen werden.

In letzter Zeit werden Marktkurse algorithmisch angeboten, im Gegensatz zum früheren System des offenen Ausrufs. Das Studium von Marktkursen, die auf einem Marktverhalten beruhen, das wir wahrscheinlich nie wieder erleben werden, ist vielleicht nicht sinnvoll. Daher beschränken wir uns auf die jüngsten Daten.

//+------------------------------------------------------------------+
//|                                                  UK100 Gilts.mq5 |
//|                                        Gamuchirai Zororo Ndawana |
//|                          https://www.mql5.com/en/gamuchiraindawa |
//+------------------------------------------------------------------+
#property copyright "Gamuchirai Zororo Ndawana"
#property link      "https://www.mql5.com/en/gamuchiraindawa"
#property version   "1.00"
#property script_show_inputs

//+------------------------------------------------------------------+
//| Inputs                                                           |
//+------------------------------------------------------------------+
input int fetch = 20;                  //How much data should we fetch?
input int look_ahead = 20;             //How far into the future should we forecast?

Jetzt können wir damit beginnen, das Herzstück unseres Skripts zu definieren. Zuerst werden wir Variablen definieren, die wir im gesamten Skript benötigen.

//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//--- Global variables we will need inside our expert advisor
   matrix coefficients = matrix::Zeros(1,9);
   vector mean_values = vector::Zeros(8);
   vector std_values = vector::Zeros(8);
   vector intercept = vector::Ones(fetch);
   matrix input_matrix = matrix::Zeros(9,fetch);
   matrix gilts_data,uk100_data,target;

Beachten Sie, dass die Eingabedaten um eine vorausschauende Anzahl von Schritten, „look_ahead“, verzögert werden und die Zieldaten vor den Eingabedaten abgerufen werden.

//--- First we will fetch the market data
   gilts_data.CopyRates("UKGB_Z4",PERIOD_CURRENT,COPY_RATES_OHLC,1+look_ahead,fetch);
   uk100_data.CopyRates("UK100",PERIOD_CURRENT,COPY_RATES_OHLC,1+look_ahead,fetch);
   target.CopyRates("UK100",PERIOD_CURRENT,COPY_RATES_CLOSE,1,fetch);

Wir müssen nun eine Eingabematrix erstellen. Die erste Spalte in unserer Eingabematrix ist die Zahl eins, die so oft wiederholt wird, wie die Eingabe abgerufen wird. Dies liegt daran, dass dieser Eintrag von Einsen einfach mit unserer Berechnung des Bias-Terms in unserem linearen Modell multipliziert werden soll. Von dort aus füllen wir die Daten zu den britischen Staatsanleihen und dem FTSE 100 aus.

//--- Fill in the input matrix
   input_matrix.Row(intercept,0);
   input_matrix.Row(gilts_data.Row(0),1);
   input_matrix.Row(gilts_data.Row(1),2);
   input_matrix.Row(gilts_data.Row(2),3);
   input_matrix.Row(gilts_data.Row(3),4);
   input_matrix.Row(uk100_data.Row(0),5);
   input_matrix.Row(uk100_data.Row(1),6);
   input_matrix.Row(uk100_data.Row(2),7);
   input_matrix.Row(uk100_data.Row(3),8);

Wir sehen uns die abgerufenen Daten an, um sicherzustellen, dass die Daten die richtige Größe haben und dass die Matrizen für die vorzunehmenden Manipulationen geeignet sind. Beachten Sie, dass unsere Berechnungen fehlschlagen und Fehler bei der Ausführung zurückgeben, wenn unsere Matrizen nicht die richtige Größe haben.

//--- Display the data fetched
   Print("Input matrix: ");
   Print("Rows: ",input_matrix.Rows()," Columns: ",input_matrix.Cols());
   Print(input_matrix);

   Print("Target: ");
   Print("Rows: ",target.Rows()," Columns: ",target.Cols());
   Print(target);

   Print("UK100: ");
   Print("Rows: ",uk100_data.Rows()," Columns: ",uk100_data.Cols());
   Print(uk100_data);

   Print("GILTS: ");
   Print("Rows: ",gilts_data.Rows()," Columns: ",gilts_data.Cols());
   Print(gilts_data);

Um unsere Eingabedaten zu skalieren und zu normalisieren, müssen wir den Mittelwert und die Standardabweichung für jede Spalte, die wir bearbeiten, berechnen. Als ich zum ersten Mal maschinelles Lernen lernte, war ich mir nicht sicher, wann eine Skalierung und Standardisierung der Daten erforderlich war. Im Laufe der Zeit habe ich jedoch die Faustregel gelernt, dass eine Skalierung erforderlich ist, wenn die Eingaben in unterschiedlichen Maßstäben erfolgen. So bewegen sich beispielsweise die Marktdaten unserer Gilts im 100er-Bereich, die Marktdaten unseres FTSE100 jedoch im 8000er-Bereich, weshalb hier eine Skalierung erforderlich ist. Beachten Sie, dass es nie notwendig ist, das Ziel zu skalieren.

//--- Calculate the scaling values
   mean_values = input_matrix.Mean(1);
   std_values = input_matrix.Std(1);
   Print("Mean values: ");
   Print(mean_values);

   Print("Std values: ");
   Print(std_values);

Um unsere Eingabedaten zu normalisieren, subtrahieren wir zunächst den Spaltenmittelwert und dividieren dann durch die Standardabweichung. Dieser Vorverarbeitungsschritt hilft unserem Modell, effektiv zu lernen, und er ist von entscheidender Bedeutung, wenn die Modelleingaben auf verschiedenen Skalen liegen, wie in unserem Fall.

//--- Normalizing and scaling our input data
   for(int i = 0; i < 8; i++)
     {
      //--- Extract the vector
      vector temp = input_matrix.Row(i + 1);
      //--- Scale the data
      temp = ((temp - mean_values[i+1]) / std_values[i+1]);
      //--- Write the data back
      input_matrix.Row(temp,i+1);
     }

//--- Finished normalizing the data
   Print("Finished normalizing the data.");
   Print(input_matrix);

Berechnen wir nun unsere Modellparameter, also die Koeffizienten unseres linearen Modells. Wir können dies tun, indem wir eine Matrixmultiplikation der Zieldaten und der Pseudo-Inverse der Eingabedaten durchführen. Dies liefert uns eine 1xn-Matrix mit einem Koeffizientenwert für jede Spalte in unserer Matrix. Das Vorzeichen jedes Koeffizientenwerts gibt die Steigung an, d. h. ob das Ziel mit zunehmender Eingangsvariable steigt oder sinkt.

//--- Now we can calculate our coefficient values
   coefficients = target.MatMul(input_matrix.PInv());

   Print("Coefficient values");
   Print(coefficients);

Um eine Vorhersage aus unserem Modell zu erhalten, müssen wir zunächst die aktuellen Eingabedatenwerte abrufen, sie skalieren und dann die lineare Regressionsformel anwenden, um die Vorhersage unseres Modells zu erhalten.

//--- Now we can obtain a forecast from our model
   gilts_data.CopyRates("UKGB_Z4",PERIOD_CURRENT,COPY_RATES_OHLC,0,1);
   uk100_data.CopyRates("UK100",PERIOD_CURRENT,COPY_RATES_OHLC,0,1);

//--- Scale our inputs
   gilts_data[0,0] = ((gilts_data[0,0] - mean_values[1]) / std_values[1]);
   gilts_data[1,0] = ((gilts_data[1,0] - mean_values[2]) / std_values[2]);
   gilts_data[2,0] = ((gilts_data[2,0] - mean_values[3]) / std_values[3]);
   gilts_data[3,0] = ((gilts_data[3,0] - mean_values[4]) / std_values[4]);
   uk100_data[0,0] = ((uk100_data[0,0] - mean_values[5]) / std_values[5]);
   uk100_data[1,0] = ((uk100_data[1,0] - mean_values[6]) / std_values[6]);
   uk100_data[2,0] = ((uk100_data[2,0] - mean_values[7]) / std_values[7]);
   uk100_data[3,0] = ((uk100_data[3,0] - mean_values[8]) / std_values[8]);

   Print("Normalized inputs: ");
   Print(gilts_data);
   Print(uk100_data);

   double forecast = (
                        (1 * coefficients[0,0]) +
                        (gilts_data[0,0] * coefficients[0,1]) +
                        (gilts_data[1,0] * coefficients[0,2]) +
                        (gilts_data[2,0] * coefficients[0,3]) +
                        (gilts_data[3,0] * coefficients[0,4]) +
                        (uk100_data[0,0] * coefficients[0,5]) +
                        (gilts_data[1,0] * coefficients[0,6]) +
                        (gilts_data[2,0] * coefficients[0,7]) +
                        (gilts_data[3,0] * coefficients[0,8])
                     );

//--- Give our predictions
   Comment("Model forecast: ",forecast);

Unser Skript

Abb. 1: Unser Skript

Unsere Skripteingaben.

Abb. 2: Unsere Skripteingaben

Unser Prognosemodell

Abb. 3: Die Prognose unseres Modells


Aufbau unseres Expertenberaters in MQL5

Nachdem wir nun so weit gekommen sind, können wir mit dem Aufbau unseres Expert Advisors beginnen. Um mit dem Aufbau unserer Anwendung zu beginnen, werden wir zunächst die Handelsbibliothek importieren, damit wir unsere Positionen verwalten können.

//+------------------------------------------------------------------+
//|                                                  UK100 Gilts.mq5 |
//|                                        Gamuchirai Zororo Ndawana |
//|                          https://www.mql5.com/en/gamuchiraindawa |
//+------------------------------------------------------------------+
#property copyright "Gamuchirai Zororo Ndawana"
#property link      "https://www.mql5.com/en/gamuchiraindawa"
#property version   "1.00"

//+------------------------------------------------------------------+
//|Libraries we need                                                 |
//+------------------------------------------------------------------+
#include <Trade/Trade.mqh>             //Trade class
CTrade Trade;                          //Initialize the class

Dann werden wir die Eingaben für unsere Anwendung festlegen, sodass der Endnutzer entscheiden kann, wie viele Daten er abrufen und wie weit er in die Zukunft schauen möchte.

//+------------------------------------------------------------------+
//| Inputs                                                           |
//+------------------------------------------------------------------+
input int fetch = 20;                  //How much data should we fetch?
input int look_ahead = 20;             //How far into the future should we forecast?

Wir brauchen auch globale Variablen, die im gesamten Programm verwendet werden.

//+------------------------------------------------------------------+
//| Global vairables                                                 |
//+------------------------------------------------------------------+
matrix coefficients = matrix::Zeros(1,9);
vector mean_values = vector::Zeros(8);
vector std_values = vector::Zeros(8);
vector intercept = vector::Ones(fetch);
matrix input_matrix = matrix::Zeros(9,fetch);
matrix gilts_data,uk100_data,target;
double willr_buffer[],rsi_buffer[];
int willr_handler,rsi_handler;
double forecast,bid,ask;
int model_forecast = 0;
int state = 0;

Definieren wir eine Funktion, die unsere Trainingsdaten abruft und die Skalierungswerte ermittelt, die wir zur Standardisierung und Skalierung unserer Daten benötigen. Beachten Sie, dass wir Matrizen anstelle von Arrays verwenden, weil wir die speziellen Matrix- und Vektorfunktionen der MQL5-API nutzen wollen.

//+------------------------------------------------------------------+
//| Let us fetch our training data                                   |
//+------------------------------------------------------------------+
void fetch_training_data(void)
  {
//--- First we will fetch the market data
   gilts_data.CopyRates("UKGB_Z4",PERIOD_CURRENT,COPY_RATES_OHLC,1+look_ahead,fetch);
   uk100_data.CopyRates("UK100",PERIOD_CURRENT,COPY_RATES_OHLC,1+look_ahead,fetch);
   target.CopyRates("UK100",PERIOD_CURRENT,COPY_RATES_CLOSE,1,fetch);

//--- Fill in the input matrix
   input_matrix.Row(intercept,0);
   input_matrix.Row(gilts_data.Row(0),1);
   input_matrix.Row(gilts_data.Row(1),2);
   input_matrix.Row(gilts_data.Row(2),3);
   input_matrix.Row(gilts_data.Row(3),4);
   input_matrix.Row(uk100_data.Row(0),5);
   input_matrix.Row(uk100_data.Row(1),6);
   input_matrix.Row(uk100_data.Row(2),7);
   input_matrix.Row(uk100_data.Row(3),8);

//--- Display the data fetched
   Print("Input matrix: ");
   Print("Rows: ",input_matrix.Rows()," Columns: ",input_matrix.Cols());
   Print(input_matrix);

   Print("Target: ");
   Print("Rows: ",target.Rows()," Columns: ",target.Cols());
   Print(target);

   Print("UK100: ");
   Print("Rows: ",uk100_data.Rows()," Columns: ",uk100_data.Cols());
   Print(uk100_data);

   Print("GILTS: ");
   Print("Rows: ",gilts_data.Rows()," Columns: ",gilts_data.Cols());
   Print(gilts_data);

//--- Calculate the scaling values
   mean_values = input_matrix.Mean(1);
   std_values = input_matrix.Std(1);

   Print("Mean values: ");
   Print(mean_values);

   Print("Std values: ");
   Print(std_values);
  }
//+------------------------------------------------------------------+

Da wir nun unsere Skalierungswerte haben, müssen wir eine Funktion definieren, die unsere Eingabedaten tatsächlich skaliert und standardisiert.

//+------------------------------------------------------------------+
//| Let us scale and standardize the training data                   |
//+------------------------------------------------------------------+
void scale_training_data(void)
  {
//--- Normalizing and scaling our input data
   for(int i = 0; i < 8; i++)
     {
      //--- Extract the vector
      vector temp = input_matrix.Row(i + 1);
      //--- Scale the data
      temp = ((temp - mean_values[i+1]) / std_values[i+1]);
      //--- Write the data back
      input_matrix.Row(temp,i+1);
     }

//--- Finished normalizing the data
   Print("Finished normalizing the data.");
   Print(input_matrix);
  }

Nachdem unsere Trainingsdaten skaliert und standardisiert wurden, können wir unsere Modellparameter berechnen.

//+------------------------------------------------------------------+
//| Calculate coefficient values                                     |
//+------------------------------------------------------------------+
void calculate_coefficient_values(void)
  {
//--- Now we can calculate our coefficient values
   coefficients = target.MatMul(input_matrix.PInv());

   Print("Coefficient values");
   Print(coefficients);
  }

Wir brauchen auch eine Funktion, die für das Abrufen einer Vorhersage aus unserem Modell verantwortlich ist. Unser Verfahren ist einfach: Wir holen zunächst die Marktdaten ein, skalieren die Daten und wenden dann die lineare Regressionsformel an, um eine Vorhersage zu erhalten.

//+------------------------------------------------------------------+
//| Fetch a forecast from our model                                  |
//+------------------------------------------------------------------+
void fetch_forecast(void)
  {
//--- Now we can obtain a forecast from our model
   gilts_data.CopyRates("UKGB_Z4",PERIOD_CURRENT,COPY_RATES_OHLC,0,1);
   uk100_data.CopyRates("UK100",PERIOD_CURRENT,COPY_RATES_OHLC,0,1);

//--- Scale our inputs
   gilts_data[0,0] = ((gilts_data[0,0] - mean_values[1]) / std_values[1]);
   gilts_data[1,0] = ((gilts_data[1,0] - mean_values[2]) / std_values[2]);
   gilts_data[2,0] = ((gilts_data[2,0] - mean_values[3]) / std_values[3]);
   gilts_data[3,0] = ((gilts_data[3,0] - mean_values[4]) / std_values[4]);
   uk100_data[0,0] = ((uk100_data[0,0] - mean_values[5]) / std_values[5]);
   uk100_data[1,0] = ((uk100_data[1,0] - mean_values[6]) / std_values[6]);
   uk100_data[2,0] = ((uk100_data[2,0] - mean_values[7]) / std_values[7]);
   uk100_data[3,0] = ((uk100_data[3,0] - mean_values[8]) / std_values[8]);

   Print("Normalized inputs: ");
   Print(gilts_data);
   Print(uk100_data);

//--- Calculate the model's prediction
   forecast = (
                 (1 * coefficients[0,0]) +
                 (gilts_data[0,0] * coefficients[0,1]) +
                 (gilts_data[1,0] * coefficients[0,2]) +
                 (gilts_data[2,0] * coefficients[0,3]) +
                 (gilts_data[3,0] * coefficients[0,4]) +
                 (uk100_data[0,0] * coefficients[0,5]) +
                 (gilts_data[1,0] * coefficients[0,6]) +
                 (gilts_data[2,0] * coefficients[0,7]) +
                 (gilts_data[3,0] * coefficients[0,8])
              );

//--- Store the model's prediction
   if(forecast < iClose("UK100",PERIOD_CURRENT,0))
     {
      model_forecast = -1;
     }

   if(forecast > iClose("UK100",PERIOD_CURRENT,0))
     {
      model_forecast = 1;
     }

//--- Give the user feedback
   Comment("Model forecast: ",forecast);
  }

Schließlich benötigen wir auch eine Funktion, die aktuelle Marktdaten und Daten zu technischen Indikatoren abruft.

//+------------------------------------------------------------------+
//| This function will fetch current market data                     |
//+------------------------------------------------------------------+
void update_market_data(void)
  {
//--- Market prices
   bid = SymbolInfoDouble("UK100",SYMBOL_BID);
   ask = SymbolInfoDouble("UK100",SYMBOL_ASK);

//--- Technical indicators
   CopyBuffer(rsi_handler,0,0,1,rsi_buffer);
   CopyBuffer(willr_handler,0,0,1,willr_buffer);
  }

Außerdem benötigen wir 2 Funktionen, die die Vorhersage unseres KI-Modells anhand der Messwerte unserer technischen Indikatoren validieren. Wir möchten nur dann in Setups mit hoher Wahrscheinlichkeit einsteigen, wenn sowohl unsere technische als auch unsere quantitative Analyse in die gleiche Richtung weisen.

//+------------------------------------------------------------------+
//| This function will check if we have oppurtunities to buy         |
//+------------------------------------------------------------------+
void check_bullish_sentiment(void)
  {
   if((willr_buffer[0] > -20) && (rsi_buffer[0] > 70))
     {
      Trade.Buy(0.2,"UK100",ask,ask-5,ask+5,"UK100 Gilts AI");
      state = 1;
     }
  }

//+------------------------------------------------------------------+
//| This function will check if we have oppurtunities to sell        |
//+------------------------------------------------------------------+
void check_bearish_sentiment(void)
  {
   if((willr_buffer[0] < -80) && (rsi_buffer[0] <370))
     {
      Trade.Sell(0.2,"UK100",ask,ask-5,ask+5,"UK100 Gilts AI");
      state = -1;
     }
  }

Darüber hinaus können wir nun mit der Definition des Initialisierungsverfahrens für unseren Expert Advisor beginnen. Zunächst müssen wir die Trainingsdaten abrufen, von dort aus müssen wir unsere Trainingsdaten skalieren und standardisieren, danach werden wir unsere Koeffizientenwerte berechnen, und schließlich werden wir unsere technischen Indikatoren einrichten und validieren, dass unsere technischen Indikatoren gültig sind.

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- Fetch the training data
   fetch_training_data();

//--- Scale the training data
   scale_training_data();

//--- Calculate the coefficients
   calculate_coefficient_values();

//--- Setup the indicators
   rsi_handler = iRSI("UK100",PERIOD_CURRENT,20,PRICE_CLOSE);
   willr_handler = iWPR("UK100",PERIOD_CURRENT,30);

//--- Validate the technical indicators
   if((rsi_handler == INVALID_HANDLE) || (willr_handler == INVALID_HANDLE))
     {
      Comment("Failed to load indicators. ",GetLastError());
      return(INIT_FAILED);
     }

//--- Everything went well
   return(INIT_SUCCEEDED);
  }

Wenn unser Expert Advisor aus dem Chart entfernt wird, werden die nicht mehr benötigten Ressourcen freigegeben. Wir werden die Indikatoren, die wir in unserer technischen Analyse verwendet haben, abkoppeln und darüber hinaus auch unseren Expert Advisor aus dem Chart entfernen.

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//--- Free up the resoruces we don't need
   IndicatorRelease(willr_handler);
   IndicatorRelease(rsi_handler);
   ExpertRemove();
  }

Wenn wir schließlich aktualisierte Preise erhalten, aktualisieren wir zunächst unsere Marktdaten und holen dann eine Prognose von unserem KI-Modell ab. Wenn wir keine offenen Positionen haben, prüfen wir, ob unsere technischen Indikatoren mit unserem KI-Modell übereinstimmen, bevor wir unsere Positionen eröffnen. Andernfalls, wenn wir bereits offene Positionen haben, prüfen wir, ob unser KI-Modell eine Umkehrung gegen unsere offene Position vorhersagt. Wenn unser Modell eine Umkehr erwartet, werden wir unsere offenen Positionen schließen.

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//--- Fetch updated market data
   update_market_data();

//--- Fetch a forecast from our model
   fetch_forecast();

//--- Check for a position we can open
   if(PositionsTotal() == 0)
     {
      if(model_forecast == 1)
        {
         check_bullish_sentiment();
        }

      else
         if(model_forecast == -1)
           {
            check_bearish_sentiment();
           }
     }

//--- Check for a reversal
   else
      if(PositionsTotal() > 0)
        {
         if(model_forecast != state)
           {
            Alert("Reversal detected by our AI system! Closing all positions now.");
            Trade.PositionClose("UK100");
           }
        }
  }
//+------------------------------------------------------------------+

Unser System in Aktion

Abb. 4: Unser AI-System in Aktion


Schlussfolgerung

In unserem heutigen Artikel haben wir gezeigt, wie Sie einen KI-geführten Expert Advisor in MQL5 erstellen können. Der größte Vorteil unseres Ansatzes besteht darin, dass wir den Zeitrahmen wechseln können, ohne unsere Anwendung neu kalibrieren zu müssen, während wir bei der Implementierung unserer Lösung mit ONNX mindestens 1 ONNX-Modell für jeden Zeitrahmen benötigen würden, den wir handeln möchten. Unsere aktuelle Lösung ist selbstoptimierend und kann unter vielen verschiedenen Bedingungen eingesetzt werden. 

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

Beigefügte Dateien |
UK100_Gilts.mq5 (10.13 KB)
Selbstoptimierender Expert Advisor mit MQL5 und Python (Teil III): Den Boom-1000-Algorithmus knacken Selbstoptimierender Expert Advisor mit MQL5 und Python (Teil III): Den Boom-1000-Algorithmus knacken
In dieser Artikelserie erörtern wir, wie wir Expert Advisors entwickeln können, die sich selbständig an dynamische Marktbedingungen anpassen. Im heutigen Artikel werden wir versuchen, ein tiefes neuronales Netz auf die synthetischen Märkte von Derivativen abzustimmen.
Erstellen eines integrierten MQL5-Telegram Expert Advisors (Teil 5): Senden von Befehlen von Telegram an MQL5 und Empfangen von Antworten in Echtzeit Erstellen eines integrierten MQL5-Telegram Expert Advisors (Teil 5): Senden von Befehlen von Telegram an MQL5 und Empfangen von Antworten in Echtzeit
In diesem Artikel erstellen wir mehrere Klassen, um die Echtzeitkommunikation zwischen MQL5 und Telegram zu erleichtern. Wir konzentrieren uns darauf, Befehle von Telegram abzurufen, sie zu entschlüsseln und zu interpretieren und entsprechende Antworten zurückzusenden. Am Ende stellen wir sicher, dass diese Interaktionen effektiv getestet werden und in der Handelsumgebung funktionieren.
Einführung in Connexus (Teil 1): Wie verwendet man die WebRequest-Funktion? Einführung in Connexus (Teil 1): Wie verwendet man die WebRequest-Funktion?
Dieser Artikel ist der Beginn einer Reihe von Entwicklungen für eine Bibliothek namens „Connexus“, die HTTP-Anfragen mit MQL5 erleichtern soll. Das Ziel dieses Projekts ist es, dem Endnutzer diese Möglichkeit zu bieten und zu zeigen, wie man diese Hilfsbibliothek verwendet. Ich wollte sie so einfach wie möglich gestalten, um das Studium zu erleichtern und die Möglichkeit für künftige Entwicklungen zu schaffen.
MQL5-Assistenten-Techniken, die Sie kennen sollten (Teil 37): Gaußsche Prozessregression mit linearen und Matérn-Kernel MQL5-Assistenten-Techniken, die Sie kennen sollten (Teil 37): Gaußsche Prozessregression mit linearen und Matérn-Kernel
Lineare Kernel sind die einfachste Matrix ihrer Art, die beim maschinellen Lernen für lineare Regression und Support Vector Machines verwendet wird. Der Matérn-Kernel hingegen ist eine vielseitigere Version der Radialbasisfunktion, die wir in einem früheren Artikel besprochen haben, und er eignet sich für die Abbildung von Funktionen, die nicht so glatt sind, wie es die RBF annehmen würde. Wir erstellen eine nutzerdefinierte Signalklasse, die beide Kernel für die Vorhersage von Long- und Short-Bedingungen verwendet.