English Русский 中文 Español 日本語 Português
preview
Integration von MQL5 in Datenverarbeitungspakete (Teil 2): Maschinelles Lernen und prädiktive Analytik

Integration von MQL5 in Datenverarbeitungspakete (Teil 2): Maschinelles Lernen und prädiktive Analytik

MetaTrader 5Handelssysteme | 18 Oktober 2024, 10:39
148 0
Hlomohang John Borotho
Hlomohang John Borotho

Einführung

In diesem Artikel konzentrieren wir uns speziell auf Machine Learning (ML) und Predictive Analytics (maschinelles Lernen und prognostische Analytik). Datenverarbeitungspakete eröffnen neue Möglichkeiten für quantitative Händler und Finanzanalysten. Durch die Einbettung von maschinellen Lernfähigkeiten in MQL5 können Händler ihre Handelsstrategien von traditionellen regelbasierten Systemen zu hochentwickelten, datengesteuerten Modellen weiterentwickeln, die sich kontinuierlich an die sich verändernden Marktbedingungen anpassen.

Dabei werden die leistungsstarken Python-Bibliotheken für Datenverarbeitung und maschinelles Lernen wie scikit-learn in Verbindung mit MQL5 eingesetzt. Diese Integration ermöglicht es Händlern, Vorhersagemodelle anhand historischer Daten zu trainieren, ihre Effektivität mit Backtesting-Techniken zu testen und diese Modelle dann für Handelsentscheidungen in Echtzeit einzusetzen. Die Flexibilität bei der Kombination dieser Tools ermöglicht die Entwicklung von Strategien, die über die typischen technischen Indikatoren hinausgehen und prädiktive Analysen und Mustererkennung beinhalten, die die Handelsergebnisse erheblich verbessern können.


Sammeln der historischen Daten

Um zu beginnen, benötigen wir historische Daten aus MetaTrader 5, die im .csv-Format gespeichert werden. Wir starten also einfach die MetaTrader-Plattform und navigieren oben in das MetaTrader 5-Fenster/Panel zu > Extras und dann > Optionen und wir werden zu den Charts-Optionen (Diagramme) gelangen. Sie müssen dann die Anzahl der Balken im Diagramm auswählen, die Sie herunterladen möchten. Am besten wählen Sie die Option „Unlimited“, da wir mit dem Datum arbeiten und nicht wissen, wie viele Balken in einem bestimmten Zeitraum vorhanden sind.

Navigieren > Extras > Optionen

Danach müssen Sie nun die eigentlichen Daten herunterladen. Dazu müssen Sie zu > Ansicht und dann zu > Symbole navigieren. Auf der Registerkarte Spezifikationen navigieren Sie einfach zu > Balken oder Ticks, je nachdem, welche Art von Daten Sie herunterladen möchten. Fahren Sie fort und geben Sie das Anfangs- und Enddatum der historischen Daten ein, die Sie herunterladen möchten. Klicken Sie anschließend auf die Schaltfläche "Anfragen", um die Daten herunterzuladen und im .csv-Format zu speichern.

Herunterzuladende Balken

Nach all diesen Schritten haben Sie erfolgreich historische Daten von Ihrer MetaTrader-Handelsplattform heruntergeladen. Nun müssen Sie die Jupyter-Lab-Umgebung für die Analyse herunterladen und einrichten. Um Jupyter Lab herunterzuladen und einzurichten, besuchen Sie die offizielle Website und folgen Sie den einfachen Schritten, um es herunterzuladen. Je nach Art des Betriebssystems, das Sie verwenden, haben Sie verschiedene Möglichkeiten, ob Sie mit pip, conda oder brew installieren möchten.


MetaTrader 5 Historische Daten auf Jupyter Lab verarbeiten

Um Ihre MetaTrader 5 historischen Daten erfolgreich in Jupyter Lab zu laden, müssen Sie den Ordner kennen, den Sie zum Herunterladen der Daten ausgewählt hatten, und dann in Jupyter Lab einfach zu diesem Ordner navigieren.um loszulegen, müssen Sie die Daten laden und die Spaltennamen überprüfen. Wir müssen die Spaltennamen überprüfen, damit wir die Spalten richtig behandeln und Fehler vermeiden, die bei der Verwendung eines falschen Spaltennamens auftreten könnten.

python code:

import pandas as pd

# assign variable to the historical data
file_path = '/home/int_junkie/Documents/ML/predi/XAUUSD.m_H1_201510010000_202408052300.csv'

data = pd.read_csv(file_path, delimiter='\t')

# Display the first few rows and column names
print(data.head())
print(data.columns)

Ausgabe:

Historische Datenausgabe

Wir arbeiten mit MetaTrader 5 historischen Daten aus dem Jahr 2015 bis 2024, das sind etwa 9 Jahre historischer Daten. Diese Art von Daten hilft, breite Marktzyklen zu erfassen. Der Datensatz wird wahrscheinlich verschiedene Marktphasen erfassen, was ein besseres Verständnis und eine bessere Modellierung dieser Zyklen ermöglichen wird. Längere Datensätze verringern die Wahrscheinlichkeit einer Überanpassung, da sie ein umfassenderes Spektrum von Szenarien bieten.

Ein Modell, das auf einem breiteren Datensatz trainiert wurde, ist eher in der Lage, auf unbekannte Daten zu verallgemeinern, insbesondere wenn es sich um einen Datensatz mit einem kleineren Zeitrahmen wie 1H handelt. Dies ist besonders wichtig bei der Analyse von Zeitreihen, wo eine größere Anzahl von Beobachtungen die Zuverlässigkeit der Ergebnisse erhöht. So können Sie beispielsweise säkulare Trends (langfristige Marktrichtungen) oder wiederkehrende saisonale Effekte erkennen, die für Prognosen relevant sind.

Liniendiagramm aus historischen Daten

data.plot.line(y = "<CLOSE>", x = "<DATE>", use_index = True)

Ausgabe:

Preis-Chart

Wir verwenden den obigen Code bei der Visualisierung von Zeitreihendaten, z. B. von Finanzwerten im Zeitverlauf. Wenn der Index Ihres Datenrahmens bereits Datumsangaben enthält, können Sie auf die Angabe von 'x=“<DATE>“' verzichten und einfach 'use_index=True' verwenden.

del data["<VOL>"]
del data["<SPREAD>"]

Dann löschen wir die angegebenen Spalten aus unseren historischen Daten. Wir verwenden die Pandas-Bibliothek, um diese Spalten zu löschen.

data.head()

Ausgabe:

DataFrame

Aus der obigen Ausgabe geht hervor, dass die angegebenen Spalten tatsächlich gelöscht wurden.

# We add a colunm for tommorows price
data["<NexH>"] = data["<CLOSE>"].shift(-1)

1. 'data[“<NexH>“]':

  • Dadurch wird dem Daten-Frame „data“ eine neue Spalte mit der Bezeichnung „<NexH>“ (NEXT HOUR) hinzugefügt. Der Wert in dieser Spalte stellt die Schlusskurse für die nächste Stunde im Verhältnis zu jeder Zeile dar.

2. 'data[“<CLOSE>“].shift(-1)':

  • data[“<CLOSE>“]' bezieht sich auf die bestehende Spalte im Data-Frame, die die Schlusskurse für jeden Zeitpunkt enthält.
  • Die Methode '.shift(-1)' verschiebt die Datumszeit in der Spalte „<CLOSE>“ um eine Zeile nach oben (weil das Argument '-1' ist), wodurch jeder Wert effektiv in die vorherige Zeile verschoben wird.
  • Dies hat zur Folge, dass der Wert, der ursprünglich einem bestimmten Datum entsprach, nun in der Zeile mit dem vorherigen Datum erscheint.

Ausgabe:

Spalte der nächsten Stunde

data["<TRGT>"] = (data["<NexH>"] > data["<CLOSE>"]).astype(int)

data

Wir verwenden dann den obigen Code, um eine neue Spalte im Daten-Frame „data“ zu erstellen, die Binärwerte (0 oder 1) enthält, die angeben, ob der Höchstkurs der nächsten Periode („NexH“) größer als der aktuelle Schlusskurs („<CLOSE>“) ist.

1. 'data[“<TRGT>“]':

  • Dies ist die neue Spalte mit der Bezeichnung „<TRGT>“ (TARGET) im Daten-Frame „data“. In dieser Spalte werden die binären Zielwerte (0 oder 1) auf der Grundlage einer Bedingung gespeichert.

2. '(data["<NexH>"] > data["<CLOSE>"])':

  • Dieser Ausdruck vergleicht für jede Zeile den Wert in der Spalte ''<NexH>'' (Höchstkurs der nächsten Periode) mit dem Wert in der Spalte ''<CLOSE>'' (aktueller Schlusskurs).
  • Es handelt sich um eine boolesche Reihe, bei der jeder Wert entweder 'True' (wenn der nächste Höchststand größer ist als der aktuelle Schlussstand) oder 'False' (wenn nicht) ist.

3. „.astype(int)“:

  • Diese Funktion wandelt die booleschen Werte ('True' oder 'False') in Ganzzahlen ('1' bzw. '0') um.
  • 'True' wird zu „1“, und 'False' wird zu '0'.

Ausgabe:

Ziel

from sklearn.ensemble import RandomForestClassifier

model = RandomForestClassifier(n_estimators = 50, min_samples_split = 50, random_state = 1)

train = data.iloc[:-50]
test = data.iloc[-50:]

predictors = ["<CLOSE>","<TICKVOL>", "<OPEN>", "<HIGH>", "<LOW>"]
model.fit(train[predictors], train["<TRGT>"])

Ausgabe:

Random Forest

1. Importieren des Random Forest Classifiers:

  • Der „Random-Forest-Classifier“ ist ein maschinelles Lernmodell, das mehrere Entscheidungsbäume erstellt und deren Ergebnisse zusammenführt, um die Vorhersagegenauigkeit zu verbessern und die Überanpassung zu kontrollieren.

2. Modell-Initialisierung:

  • Der „estimator“ (Schätzer) gibt die Anzahl der Entscheidungsbäume im „forest“ (Wald) an. In diesem Fall wird das Modell 50 Bäume bauen.
  • „min-sample-split“ legt die Mindestanzahl der Stichproben fest, die für die Aufteilung eines internen Knotens erforderlich sind. Ein höherer Wert verringert die Überanpassung, indem er sicherstellt, dass die Aufteilung nur dann erfolgt, wenn genügend Daten vorhanden sind.
  • „random-state“ legt die Zufallsauswahl fest, um die Reproduzierbarkeit der Ergebnisse zu gewährleisten. Die Verwendung desselben Seeds (z. B. 1) führt bei jeder Ausführung des Codes zu denselben Ergebnissen.

3. Aufteilung der Daten in Trainings- und Testgruppen:

  • „data.iloc[:-50]“ wählt alle Zeilen außer den letzten 50 als Trainingsdaten aus.
  • „data.iloc[-50:]“ wählt die letzten 50 Zeilen als Testdaten aus
  • Diese Aufteilung wird üblicherweise bei Zeitreihendaten verwendet, bei denen das Modell anhand historischer Daten trainiert und anhand der jüngsten Daten getestet wird, um die Leistung bei zukünftigen Vorhersagen zu bewerten.

4. Festlegen der Prädiktorvariablen:

  • Die Liste „predictors“ enthält die Spaltennamen, die die vom Modell für die Vorhersagen verwendeten Merkmale darstellen. Dazu gehören (''“<CLOSE>“, '“<TICKVOL>“', '“<OPEN>“', '“<HIGH>“', und '“<LOW>“').

Der Code bereitet einen Random-Forest-Klassifikator vor, um das zukünftige Marktverhalten auf der Grundlage vergangener Daten vorherzusagen. Das Modell wird anhand von Merkmalen wie Schlusskurs, Tick-Volumen und anderen trainiert. Nach der Aufteilung der Daten in einen Trainings- und einen Testsatz wird das Modell an die Trainingsdaten angepasst und lernt aus den historischen Mustern, um zukünftige Vorhersagen zu treffen.

Messung der Genauigkeit des Modells

from sklearn.metrics import precision_score

prcsn = model.predict(test[predictors])

Wir importieren die Funktion „precision-score“ aus dem Modul „sklearn.metrics“. Die Genauigkeit ist eine Metrik zur Bewertung von Klassifizierungsmodellen, die besonders nützlich ist, wenn die Klassen unausgewogen sind. Sie misst, wie viele der vorhergesagten positiven Ergebnisse tatsächlich positiv sind. Hohe Präzision bedeutet niedrige Positivraten.

Präzisionsgleichung

prcsn = pd.Series(prcsn, index = test.index)

Anschließend werden die Vorhersagen („prcsn“) in eine Pandas-‚Serie‘ umgewandelt, wobei der Index aus dem Testdatensatz erhalten bleibt.

precision_score(test["<TRGT>"], prcsn)

Die Genauigkeit der Vorhersagen des Modells erhalten wir, indem wir die tatsächlichen Zielwerte in der Testmenge mit den vorhergesagten Werten vergleichen.

Ausgabe:

Vorhersage-Ergebnis

cmbnd = pd.concat([test["<TRGT>"], prcsn], axis = 1)

cmbnd.plot()

Wir fassen die tatsächlichen Zielwerte und die vom Modell vorhergesagten Werte zur einfacheren Analyse in einem einzigen Datenrahmen zusammen.

Ausgabe:

Geplant vs. Tatsächlich

def predors(train, test, predictors, model):
    model.fit(train[predictors], train["<TRGT>"])
    prcsn = model.predict(test[predictors])
    prcsn = pd.Series(prcsn, index = test.index, name = "Predictions")
    cmbnd = pd.concat([test["<TRGT>"], prcsn], axis = 1)
    return cmbnd

Diese Funktion nimmt einen Trainings- und einen Testdatensatz, eine Liste von Prädiktorvariablen und ein maschinelles Lernmodell auf. Die Funktion trainiert das Modell anhand der Trainingsdaten, macht Vorhersagen anhand der Testdaten und gibt einen Datenrahmen zurück, der sowohl die tatsächlichen Zielwerte als auch die vorhergesagten Werte nebeneinander enthält.

def backtestor(data, model, predictors, start = 2500, step = 250):
    all_predictions = []

    for i in range(start, data.shape[0], step):
        train = data.iloc[0:i].copy()
        test = data.iloc[i:(i + step)].copy()
        predictions = predors(train, test, predictors, model)
        all_predictions.append(predictions)
    return pd.concat(all_predictions)

Diese Funktion führt einen Rolling-Back-Test für einen Zeitreihendatensatz unter Verwendung eines maschinellen Lernmodells durch. Beim Backtest wird die Leistung des Modells bewertet, indem die Vorhersagen so simuliert werden, als ob sie in einer realen Handelsumgebung gemacht würden, in der die Daten im Laufe der Zeit nach und nach aufgedeckt werden.

predictions = backtestor(data, model, predictors)

Führt die Funktion „backtestor“ unter Verwendung des angegebenen Datensatzes (“data“), des Modells für maschinelles Lernen (“model“) und der Prädiktorvariablen (“predictors“) aus. Es wird ein rollierender Backtest durchgeführt, und die daraus resultierenden Vorhersagen werden in der Variablen „predicitions“ gespeichert.

predictions["Predictions"].value_counts()

Wir zählen die Anzahl der Vorkommen jedes einzelnen Wertes in der Spalte „Predictions“ des Vorhersage-Datenrahmens.

Ausgabe:

Vorhersagen

precision_score(predictions["<TRGT>"], predictions["Predictions"])

Berechnet die Genauigkeit der Vorhersage des Modells. Die Präzision ist eine Metrik, die die Genauigkeit positiver Vorhersagen misst.

Ausgabe:

P_Wertung

Präzision Eq

predictions["<TRGT>"].value_counts() / predictions.shape[0]

Berechnet den Anteil der einzelnen Werte in der Spalte „<TRGT>“ im Verhältnis zur Gesamtzahl der Vorhersagen.

Ausgabe:

Anteil

horizons = [2, 5, 55, 125, 750]
new_predictors = []

# Ensure only numeric columns are used for rolling calculations
numeric_columns = data.select_dtypes(include=[float, int]).columns

for i in horizons:
    # Calculate rolling averages for numeric columns only
    rolling_averages = data[numeric_columns].rolling(i).mean()
    
    # Generate the ratio column
    ratio_column = f"Close_Ratio_{i}"
    data[ratio_column] = data["<CLOSE>"] / rolling_averages["<CLOSE>"]
    
    # Generate the trend column
    trend_column = f"Trend_{i}"
    data[trend_column] = data["<TRGT>"].shift(1).rolling(i).sum()
    
    new_predictors += [ratio_column, trend_column]
data

Erzeugt neue Merkmale auf der Grundlage von gleitenden Durchschnittswerten und Trends über verschiedene Zeithorizonte. Die zusätzlichen Prädiktoren tragen dazu bei, die Leistung des Modells zu verbessern, indem sie ihm mehr Informationen über den Markt in unterschiedlichen Zeiträumen liefern.

Ausgabe:

Neue Prädiktorspalten

data = data.dropna()

Jede Zeile im Data-Frame mit fehlenden Werten wird gelöscht.

def predict(train, test, predictors, model):
    model.fit(train[predictors], train["<TRGT>"])
    prcsn = model.predict_proba(test[predictors])[:1]
    prcsn[prcsn >= .6] = 1
    prcsn[prcsn < .6] = 0
    prcsn = pd.Series(prcsn, index = test.index, name = "Predictions")
    cmbnd = pd.concat([test["<TRGT>"], prcsn], axis = 1)
    return cmbnd

Das Modell wird anhand des Trainingsdatensatzes unter Verwendung der ausgewählten Prädiktoren und Zielvariablen trainiert. Für Schwellenwerte und Vorhersagen wird ein nutzerdefinierter Schwellenwert von 0,6 verwendet. Wenn die Wahrscheinlichkeit für Klasse1 0,6 oder höher ist, sagt das Modell „1“ voraus. Andernfalls wird „0“ vorhergesagt. Diese Anpassung ermöglicht es dem Modell, konservativer zu sein und ein höheres Vertrauen zu verlangen, bevor es einen Handel signalisiert.

predictions = backtestor(data, model, new_predictors)
predictions["Predictions"].value_counts()
precision_score(predictions["<TRGT>"], predictions["Predictions"])

Ausgabe:

2. Präzisionsergebnis

Unser Genauigkeitswert ist leicht gestiegen, 0,52, wenn wir aufrunden.


Trainieren Sie das Modell und exportieren Sie es nach ONNX

import pandas as pd
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
import onnx
import skl2onnx
from skl2onnx import convert_sklearn
from skl2onnx.common.data_types import FloatTensorType

# Load and preprocess your data (example)
# Replace this with your actual data loading process
#data = pd.read_csv('your_data.csv')  # Replace with your actual data source
#data = data.dropna()

# Define predictors and target
predictors = ["<CLOSE>", "<TICKVOL>", "<OPEN>", "<HIGH>", "<LOW>"]
target = "<TRGT>"

# Split data into train and test sets
train, test = train_test_split(data, test_size=0.2, shuffle=False)

# Define and train the model
model = RandomForestClassifier(n_estimators=50, min_samples_split=50, random_state=1)
model.fit(train[predictors], train[target])

# Export the trained model to ONNX format
initial_type = [('float_input', FloatTensorType([None, len(predictors)]))]
onnx_model = convert_sklearn(model, initial_types=initial_type)

# Save the ONNX model to a file
with open("random_forest_model.onnx", "wb") as f:
    f.write(onnx_model.SerializeToString())

Wir trainieren unser Modell, und es wird konvertiert und exportiert und im ONNX-Format mit „skl2onnx“ gespeichert. Wir kopieren unser gespeichertes Modell in den MQL5-Ordner „Dateien“, wo wir darauf zugreifen können.

Gespeichertes Modell



Alles zusammen auf MQL5

Laden des Modells bei Oninit().

#include <Trade/Trade.mqh>
#define   ModelName          "RandomForestClassifier"
#define   ONNXFilename       "random_forest_model.onnx"

// Single ONNX model resource
#resource "\\Files\\random_forest_model.onnx" as const uchar ExtModelDouble[];

input double lotsize = 0.1;     // Trade lot size
input double stoploss = 20;     // Stop loss in points
input double takeprofit = 50;   // Take profit in points

// Trading functions
CTrade m_trade;

Die Includes und globalen Variablen im globalen Bereich. Wir geben auch an, dass das ONNX-Modell in MQL5 als binäre Ressource eingebettet ist. #resource wird verwendet, um externe Dateien einzubinden.

//+------------------------------------------------------------------+
//| Run classification using double values                           |
//+------------------------------------------------------------------+
bool RunModel(long model, vector &input_vector, vector &output_vector)
{
    ulong batch_size = input_vector.Size() / 5; // Assuming 5 input features
    if (batch_size == 0)
        return (false);

    output_vector.Resize((int)batch_size);

    // Prepare input tensor
    double input_data[];
    ArrayResize(input_data, input_vector.Size());

    for (int k = 0; k < input_vector.Size(); k++)
        input_data[k] = input_vector[k];

    // Set input shape
    ulong input_shape[] = {batch_size, 5}; // 5 input features for each prediction
    OnnxSetInputShape(model, 0, input_shape);

    // Prepare output tensor
    double output_data[];
    ArrayResize(output_data, (int)batch_size);

    // Set output shape (binary classification)
    ulong output_shape[] = {batch_size, 2}; // Output shape for probability (0 or 1)
    OnnxSetOutputShape(model, 0, output_shape);

    // Run the model
    bool res = OnnxRun(model, ONNX_DEBUG_LOGS, input_data, output_data);

    if (res)
    {
        // Copy output to vector (only keeping the class with highest probability)
        for (int k = 0; k < batch_size; k++)
            output_vector[k] = (output_data[2 * k] < output_data[2 * k + 1]) ? 1.0 : 0.0;
    }

    return (res);
}

Diese Funktion „RunModel“ ist ein ONNX-Modell, das wir trainiert haben, um binäre Klassifizierungen durchzuführen. Die Funktion bestimmt die vorhergesagte Klasse (0 oder 1) auf der Grundlage, welche Klasse die höhere Wahrscheinlichkeit hat, und speichert die Ergebnisse in einem Ausgabevektor.

//+------------------------------------------------------------------+
//| Generate input data for prediction                               |
//+------------------------------------------------------------------+
vector input_data()
{
    vector input_vector;
    MqlRates rates[];

    // Get the last 5 bars of data
    if (CopyRates(Symbol(), PERIOD_H1, 5, 1, rates) > 0)
    {
        input_vector.Resize(5 * 5); // 5 input features for each bar

        for (int i = 0; i < 5; i++)
        {
            input_vector[i * 5] = rates[i].open;
            input_vector[i * 5 + 1] = rates[i].high;
            input_vector[i * 5 + 2] = rates[i].low;
            input_vector[i * 5 + 3] = rates[i].close;
            input_vector[i * 5 + 4] = rates[i].tick_volume;
        }
    }

    return (input_vector);
}

//+------------------------------------------------------------------+
//| Check if there is a new bar                                      |
//+------------------------------------------------------------------+
bool NewBar()
{
    static datetime last_time = 0;
    datetime current_time = iTime(Symbol(), Period(), 0);

    if (current_time != last_time)
    {
        last_time = current_time;
        return (true);
    }
    return (false);
}

//+------------------------------------------------------------------+
//| Check if a position of a certain type exists                     |
//+------------------------------------------------------------------+
bool PosExists(int type)
{
    for (int i = PositionsTotal() - 1; i >= 0; i--)
    {
        if (PositionGetInteger(POSITION_TYPE) == type && PositionGetString(POSITION_SYMBOL) == Symbol())
            return (true);
    }
    return (false);
}

//+------------------------------------------------------------------+
//| Script program initialization                                    |
//+------------------------------------------------------------------+
int OnInit()
{
    Print("Initializing ONNX model...");

    // Initialize the ONNX model
    long model = OnnxCreateFromBuffer(ExtModelDouble, ONNX_DEFAULT);
    if (model == INVALID_HANDLE)
    {
        Print("Error loading ONNX model: ", GetLastError());
        return INIT_FAILED;
    }

    // Store the model handle for further use
    GlobalVariableSet("model_handle", model);
    return (INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
{
    if (NewBar()) // Trade at the opening of a new candle
    {
        vector input_vector = input_data();
        vector output_vector;

        // Retrieve the model handle
        long model = GlobalVariableGet("model_handle");
        if (model == INVALID_HANDLE)
        {
            Print("Invalid model handle.");
            return;
        }

        bool prediction_success = RunModel(model, input_vector, output_vector);
        if (!prediction_success || output_vector.Size() == 0)
        {
            Print("Prediction failed.");
            return;
        }

        long signal = output_vector[0]; // The predicted class (0 or 1)

        MqlTick ticks;
        if (!SymbolInfoTick(Symbol(), ticks))
            return;

        if (signal == 1) // Bullish signal
        {
            if (!PosExists(POSITION_TYPE_BUY)) // No buy positions exist
            {
                if (!m_trade.Buy(lotsize, Symbol(), ticks.ask, ticks.bid - stoploss * Point(), ticks.ask + takeprofit * Point())) // Open a buy trade
                    Print("Failed to open a buy position, error = ", GetLastError());
            }
        }
        else if (signal == 0) // Bearish signal
        {
            if (!PosExists(POSITION_TYPE_SELL)) // No sell positions exist
            {
                if (!m_trade.Sell(lotsize, Symbol(), ticks.bid, ticks.ask + stoploss * Point(), ticks.bid - takeprofit * Point())) // Open a sell trade
                    Print("Failed to open a sell position, error = ", GetLastError());
            }
        }
    }
}

//+------------------------------------------------------------------+
//| Script program deinitialization                                  |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
    // Release the ONNX model
    long model = GlobalVariableGet("model_handle");
    if (model != INVALID_HANDLE)
    {
        OnnxRelease(model);
    }
}
Während der Initialisierung wird das Modell geladen und sein Handle zur späteren Verwendung gespeichert. In der Funktion „OnTick()“ führt das Skript das Modell aus, wenn ein neuer Balken erkannt wird. Wir verwenden die Vorhersage des Modells (0 für auf- und 1 für abwärts) und führen die Trades entsprechend aus. Kaufgeschäfte werden getätigt, wenn das Modell einen Aufwärtstrend vorhersagt, während Verkaufstransaktionen bei einem Abwärtstrend getätigt werden.



Schlussfolgerung

Zusammenfassend lässt sich sagen, dass wir ein Datenverarbeitungspaket (Jupyter Lab) verwendet haben, um historische Daten zu verarbeiten, und das Modell mithilfe von maschinellem Lernen entwickelt und trainiert haben, um Vorhersagen treffen zu können. Wir haben die entscheidenden Schritte untersucht, die für eine nahtlose Integration und einen reibungslosen Betrieb erforderlich sind. Anschließend konzentrierten wir uns auf das Laden und die Handhabung des Modells innerhalb von MQL5, indem wir es als Ressource einbetteten und sicherstellten, dass das Modell ordnungsgemäß initialisiert und während der Laufzeit verfügbar ist.

Abschließend haben wir ein ONNX-Modell in eine MQL5-Handelsumgebung integriert, um die Entscheidungsfindung durch maschinelles Lernen zu verbessern. Der Prozess begann mit dem Laden des Modells in die MQL5-Umgebung. Wir haben dann den Expert Advisor so konfiguriert, dass er relevante Marktdaten sammelt, sie in Merkmalsvektoren vorverarbeitet und in das Modell für Vorhersagen einspeist. Die Logik wurde entwickelt, um auf der Grundlage der Ergebnisse des Modells Handelsgeschäfte auszuführen. Positionen werden nur eröffnet, wenn ein neuer Balken erkannt wird und keine kollidierenden Geschäfte aktiv sind. Darüber hinaus sorgt das System für Positionsprüfungen, Fehlermanagement und Ressourcendeallokation, um eine robuste und effiziente Handelslösung zu gewährleisten. Diese Implementierung zeigt eine nahtlose Mischung aus Finanzanalyse und KI-gesteuerten Erkenntnissen und ermöglicht automatisierte Handelsstrategien, die sich in Echtzeit an die Marktbedingungen anpassen.


Referenzen

Ein Modell erstellen


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

Nachrichtenhandel leicht gemacht (Teil 3): Ausführen des Handels Nachrichtenhandel leicht gemacht (Teil 3): Ausführen des Handels
In diesem Artikel wird unser Nachrichtenhandelsexperte mit der Eröffnung von Handelsgeschäften auf der Grundlage des in unserer Datenbank gespeicherten Wirtschaftskalenders beginnen. Außerdem werden wir die Expertengrafiken verbessern, um mehr relevante Informationen über bevorstehende Wirtschaftsereignisse anzuzeigen.
MQL5-Integration: Python MQL5-Integration: Python
Python ist eine bekannte und beliebte Programmiersprache mit vielen Funktionen, insbesondere in den Bereichen Finanzen, Datenwissenschaft, künstliche Intelligenz und maschinelles Lernen. Python ist ein leistungsfähiges Werkzeug, das auch beim Handel nützlich sein kann. MQL5 ermöglicht es uns, diese leistungsstarke Sprache als Integration zu nutzen, um unsere Ziele effektiv zu erreichen. In diesem Artikel erfahren Sie, wie Sie Python in MQL5 integrieren und verwenden können, nachdem Sie einige grundlegende Informationen über Python gelernt haben.
Klassische Strategien neu interpretieren (Teil IV): SP500 und US-Staatsanleihen Klassische Strategien neu interpretieren (Teil IV): SP500 und US-Staatsanleihen
In dieser Artikelserie analysieren wir klassische Handelsstrategien mit modernen Algorithmen, um festzustellen, ob wir die Strategie mithilfe von KI verbessern können. Im heutigen Artikel greifen wir einen klassischen Ansatz für den Handel mit dem SP500 auf, indem wir seine Beziehung zu den US-Staatsanleihen nutzen.
Aufbau des Kerzenmodells Trend-Constraint (Teil 8): Entwicklung eines Expert Advisors (I) Aufbau des Kerzenmodells Trend-Constraint (Teil 8): Entwicklung eines Expert Advisors (I)
In dieser Diskussion werden wir unseren ersten Expert Advisor in MQL5 erstellen, der auf dem Indikator basiert, den wir im vorherigen Artikel erstellt haben. Wir werden alle Funktionen abdecken, die erforderlich sind, um den Prozess zu automatisieren, einschließlich des Risikomanagements. Dies wird den Nutzern in hohem Maße zugute kommen, wenn sie von der manuellen Ausführung von Geschäften zu automatisierten Systemen übergehen.