English Русский 中文 Español 日本語 Português 한국어 Français Italiano Türkçe
preview
Ein Beispiel für die Zusammenstellung von ONNX-Modellen in MQL5

Ein Beispiel für die Zusammenstellung von ONNX-Modellen in MQL5

MetaTrader 5Maschinelles Lernen | 24 April 2023, 11:25
272 0
MetaQuotes
MetaQuotes

Einführung

Für einen stabilen Handel ist es in der Regel empfehlenswert, sowohl die gehandelten Instrumente als auch die Handelsstrategien zu diversifizieren. Das Gleiche gilt für Modelle des maschinellen Lernens: Es ist leichter, mehrere einfachere Modelle zu erstellen als ein komplexes. Es kann jedoch schwierig sein, diese Modelle zu einem ONNX-Modell zusammenzufügen.

Es ist jedoch möglich, mehrere trainierte ONNX-Modelle in einem MQL5-Programm zu kombinieren. In diesem Artikel betrachten wir eines aus so einem Ensemble, den sogenannten Abstimmungsklassifikator. Wir werden Ihnen zeigen, wie einfach es ist, ein solches Ensemble zu realisieren.


Modelle für das Projekt

Für unser Beispiel verwenden wir zwei einfache Modelle: ein Regressionsmodell zur Preisvorhersage und ein Klassifikationsmodell zur Vorhersage von Preisbewegungen. Der Hauptunterschied zwischen den Modellen besteht darin, dass die Regression das Ausmaß vorhersagt, während die Klassifikation die Klasse vorhersagt.

Das erste Modell ist die Regression.

Es wird mit den Daten des EURUSD D1 von 2003 bis Ende 2022 trainiert. Das Training wird mit einer Serie von 10 OHLC-Preisen durchgeführt. Um die Trainierbarkeit des Modells zu verbessern, normalisieren wir die Preise und teilen den Durchschnittspreis der Reihe durch die Standardabweichung der Reihe. So legen wir eine Reihe in einen bestimmten Bereich mit einem Mittelwert von 0 und einer Streuung von 1, was die Konvergenz beim Training verbessert.

Infolgedessen sollte das Modell den Schlusskurs für den nächsten Tag vorhersagen.

Das Modell ist sehr einfach. Sie wird hier nur zu Demonstrationszwecken bereitgestellt.

# Copyright 2023, MetaQuotes Ltd.
# https://www.mql5.com

from datetime import datetime
import MetaTrader5 as mt5
import tensorflow as tf
import numpy as np
import pandas as pd
import tf2onnx
from sklearn.model_selection import train_test_split
from tqdm import tqdm
from sys import argv

if not mt5.initialize():
    print("initialize() failed, error code =",mt5.last_error())
    quit()

# we will save generated onnx-file near the our script
data_path=argv[0]
last_index=data_path.rfind("\\")+1
data_path=data_path[0:last_index]
print("data path to save onnx model",data_path)

# input parameters
inp_model_name = "model.eurusd.D1.10.onnx"
inp_history_size = 10
inp_start_date = datetime(2003, 1, 1, 0)
inp_end_date = datetime(2023, 1, 1, 0)

# get data from client terminal
eurusd_rates = mt5.copy_rates_range("EURUSD", mt5.TIMEFRAME_D1, inp_start_date, inp_end_date)
df = pd.DataFrame(eurusd_rates)


#
# collect dataset subroutine
#
def collect_dataset(df: pd.DataFrame, history_size: int):
    """
    Collect dataset for the following regression problem:
    - input: history_size consecutive H1 bars;
    - output: close price for the next bar.

    :param df: D1 bars for a range of dates
    :param history_size: how many bars should be considered for making a prediction
    :return: features and labels
    """
    n = len(df)
    xs = []
    ys = []
    for i in tqdm(range(n - history_size)):
        w = df.iloc[i: i + history_size + 1]

        x = w[['open', 'high', 'low', 'close']].iloc[:-1].values
        y = w.iloc[-1]['close']
        xs.append(x)
        ys.append(y)

    X = np.array(xs)
    y = np.array(ys)
    return X, y
###


# get prices
X, y = collect_dataset(df, history_size=inp_history_size)

# normalize prices
m = X.mean(axis=1, keepdims=True)
s = X.std(axis=1, keepdims=True)
X_norm = (X - m) / s
y_norm = (y - m[:, 0, 3]) / s[:, 0, 3]

# split data to train and test sets
X_train, X_test, y_train, y_test = train_test_split(X_norm, y_norm, test_size=0.2, random_state=0)

# define model
model = tf.keras.Sequential([
    tf.keras.layers.LSTM(64, input_shape=(inp_history_size, 4)),
    tf.keras.layers.BatchNormalization(),
    tf.keras.layers.Dropout(0.1),
    tf.keras.layers.Dense(32, activation='relu'),
    tf.keras.layers.BatchNormalization(),
    tf.keras.layers.Dropout(0.1),
    tf.keras.layers.Dense(32, activation='relu'),
    tf.keras.layers.Dense(1)
])

model.compile(optimizer='adam', loss='mse', metrics=['mae'])

# model training for 50 epochs
lr_reduction = tf.keras.callbacks.ReduceLROnPlateau(monitor='val_loss', factor=0.1, patience=3, min_lr=0.000001)
history = model.fit(X_train, y_train, epochs=50, verbose=2, validation_split=0.15, callbacks=[lr_reduction])

# model evaluation
test_loss, test_mae = model.evaluate(X_test, y_test)
print(f"test_loss={test_loss:.3f}")
print(f"test_mae={test_mae:.3f}")

# save model to onnx
output_path = data_path+inp_model_name
onnx_model = tf2onnx.convert.from_keras(model, output_path=output_path)
print(f"saved model to {output_path}")

# finish
mt5.shutdown()
Es wird davon ausgegangen, dass unser Regressionsmodell ausgeführt wird und der sich daraus ergebende vorhergesagte Preis in die folgenden Klassen umgewandelt werden sollte: Preis geht nach unten, Preis ändert sich nicht, Preis geht nach oben. Dies ist erforderlich, um den Wahlklassifikator zu organisieren.

Das zweite Modell ist das Klassifizierungsmodell.

Es wird auf EURUSD D1 von 2010 bis Ende 2022 trainiert. Das Training wird mit einer Serie von 63 Schlusskursen durchgeführt. Bei der Ausgabe muss eine von drei Klassen definiert werden: Der Preis wird sinken, der Preis wird innerhalb von 10 Punkten bleiben oder der Preis wird steigen. Wegen der zweiten Klasse mussten wir das Modell mit Daten aus dem Jahr 2010 trainieren. Davor, im Jahr 2009, wechselten die Märkte von vierstelliger zu fünfstelliger Genauigkeit. So wurden aus einem alten Punkt zehn neue Punkte.

Wie im vorherigen Modell ist der Preis normalisiert. Die Normalisierung ist dieselbe: Wir teilen die Abweichung vom Durchschnittspreis in der Reihe durch die Standardabweichung in der Reihe. Die Idee dieses Modells wurde in dem Artikel „Finanzielle Zeitreihenprognose mit MLP in Keras“ (auf Russisch) beschrieben. Auch dieses Modell ist nur für Demonstrationszwecke gedacht.

# Copyright 2023, MetaQuotes Ltd.
# https://www.mql5.com
#
# Classification model
# 0,0,1 - predict price down
# 0,1,0 - predict price same
# 1,0,0 - predict price up
#

from datetime import datetime
import MetaTrader5 as mt5
import tensorflow as tf
import numpy as np
import pandas as pd
import tf2onnx
from sklearn.model_selection import train_test_split
from tqdm import tqdm
from keras.models import Sequential
from keras.layers import Dense, Activation,Dropout, BatchNormalization, LeakyReLU
from keras.optimizers import SGD
from keras import regularizers
from sys import argv

# initialize MetaTrader 5 client terminal
if not mt5.initialize():
    print("initialize() failed, error code =",mt5.last_error())
    quit()

# we will save the generated onnx-file near the our script
data_path=argv[0]
last_index=data_path.rfind("\\")+1
data_path=data_path[0:last_index]
print("data path to save onnx model",data_path)

# input parameters
inp_model_name = "model.eurusd.D1.63.onnx"
inp_history_size = 63
inp_start_date = datetime(2010, 1, 1, 0)
inp_end_date = datetime(2023, 1, 1, 0)

# get data from the client terminal
eurusd_rates = mt5.copy_rates_range("EURUSD", mt5.TIMEFRAME_D1, inp_start_date, inp_end_date)
df = pd.DataFrame(eurusd_rates)


#
# collect dataset subroutine
#
def collect_dataset(df: pd.DataFrame, history_size: int):
    """
    Collect dataset for the following regression problem:
    - input: history_size consecutive H1 bars;
    - output: close price for the next bar.

    :param df: H1 bars for a range of dates
    :param history_size: how many bars should be considered for making a prediction
    :return: features and labels
    """
    n = len(df)
    xs = []
    ys = []
    for i in tqdm(range(n - history_size)):
        w = df.iloc[i: i + history_size + 1]
        x = w[['close']].iloc[:-1].values

        delta = x[-1] - w.iloc[-1]['close']
        if np.abs(delta)<=0.0001:
           y = 0, 1, 0
        else:
           if delta<0:
              y = 1, 0, 0
           else:
              y = 0, 0, 1

        xs.append(x)
        ys.append(y)

    X = np.array(xs)
    Y = np.array(ys)
    return X, Y
###


# get prices
X, Y = collect_dataset(df, history_size=inp_history_size)

# normalize prices
m = X.mean(axis=1, keepdims=True)
s = X.std(axis=1, keepdims=True)
X_norm = (X - m) / s

# split data to train and test sets
X_train, X_test, Y_train, Y_test = train_test_split(X_norm, Y, test_size=0.1, random_state=0)

# define model
model = Sequential()
model.add(Dense(64, input_dim=inp_history_size, activity_regularizer=regularizers.l2(0.01)))
model.add(BatchNormalization())
model.add(LeakyReLU())
model.add(Dropout(0.3))
model.add(Dense(16, activity_regularizer=regularizers.l2(0.01)))
model.add(BatchNormalization())
model.add(LeakyReLU())
model.add(Dense(3))
model.add(Activation('softmax'))

opt = SGD(learning_rate=0.01, momentum=0.9)
model.compile(optimizer=opt, loss='categorical_crossentropy', metrics=['accuracy'])

# model training for 300 epochs
lr_reduction = tf.keras.callbacks.ReduceLROnPlateau(monitor='val_loss', factor=0.9, patience=5, min_lr=0.00001)
history = model.fit(X_train, Y_train, epochs=300, validation_data=(X_test, Y_test), shuffle = True, batch_size=128, verbose=2, callbacks=[lr_reduction])

# model evaluation
test_loss, test_accuracy = model.evaluate(X_test, Y_test)
print(f"test_loss={test_loss:.3f}")
print(f"test_accuracy={test_accuracy:.3f}")

# save model to onnx
output_path = data_path+inp_model_name
onnx_model = tf2onnx.convert.from_keras(model, output_path=output_path)
print(f"saved model to {output_path}")

# finish
mt5.shutdown()
Die Modelle wurden mit Daten bis Ende 2022 trainiert, sodass noch genügend Zeit blieb, um ihre Funktionsweise im Strategietester zu demonstrieren.


Ein Ensemble von ONNX-Modellen im MQL5 Expert Advisor

Nachfolgend finden Sie einen einfachen Expert Advisor, der die Möglichkeiten von Modell-Ensembles demonstriert. Die Hauptprinzipien der Verwendung von ONNX-Modellen in MQL5 wurden im zweiten Teil des vorherigen Artikels beschrieben.

Forward-Deklarationen und Definitionen

#include <Trade\Trade.mqh>

input double InpLots = 1.0;              // Lots amount to open position

#resource "Python/model.eurusd.D1.10.onnx" as uchar ExtModel1[]
#resource "Python/model.eurusd.D1.63.onnx" as uchar ExtModel2[]

#define SAMPLE_SIZE1 10
#define SAMPLE_SIZE2 63

long     ExtHandle1=INVALID_HANDLE;
long     ExtHandle2=INVALID_HANDLE;
int      ExtPredictedClass1=-1;
int      ExtPredictedClass2=-1;
int      ExtPredictedClass=-1;
datetime ExtNextBar=0;
CTrade   ExtTrade;

//--- price movement prediction
#define PRICE_UP   0
#define PRICE_SAME 1
#define PRICE_DOWN 2

OnInit-Funktion

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   if(_Symbol!="EURUSD" || _Period!=PERIOD_D1)
     {
      Print("model must work with EURUSD,D1");
      return(INIT_FAILED);
     }

//--- create first model from static buffer
   ExtHandle1=OnnxCreateFromBuffer(ExtModel1,ONNX_DEFAULT);
   if(ExtHandle1==INVALID_HANDLE)
     {
      Print("First model OnnxCreateFromBuffer error ",GetLastError());
      return(INIT_FAILED);
     }
//--- since not all sizes defined in the input tensor we must set them explicitly
//--- first index - batch size, second index - series size, third index - number of series (OHLC)
   const long input_shape1[] = {1,SAMPLE_SIZE1,4};
   if(!OnnxSetInputShape(ExtHandle1,0,input_shape1))
     {
      Print("First model OnnxSetInputShape error ",GetLastError());
      return(INIT_FAILED);
     }
   
//--- since not all sizes defined in the output tensor we must set them explicitly
//--- first index - batch size, must match the batch size of the input tensor
//--- second index - number of predicted prices (we only predict Close)
   const long output_shape1[] = {1,1};
   if(!OnnxSetOutputShape(ExtHandle1,0,output_shape1))
     {
      Print("First model OnnxSetOutputShape error ",GetLastError());
      return(INIT_FAILED);
     }

//--- create second model from static buffer
   ExtHandle2=OnnxCreateFromBuffer(ExtModel2,ONNX_DEFAULT);
   if(ExtHandle2==INVALID_HANDLE)
     {
      Print("Second model OnnxCreateFromBuffer error ",GetLastError());
      return(INIT_FAILED);
     }
  
//--- since not all sizes defined in the input tensor we must set them explicitly
//--- first index - batch size, second index - series size
   const long input_shape2[] = {1,SAMPLE_SIZE2};
   if(!OnnxSetInputShape(ExtHandle2,0,input_shape2))
     {
      Print("Second model OnnxSetInputShape error ",GetLastError());
      return(INIT_FAILED);
     }

//--- since not all sizes defined in the output tensor we must set them explicitly
//--- first index - batch size, must match the batch size of the input tensor
//--- second index - number of classes (up, same or down)
   const long output_shape2[] = {1,3};
   if(!OnnxSetOutputShape(ExtHandle2,0,output_shape2))
     {
      Print("Second model OnnxSetOutputShape error ",GetLastError());
      return(INIT_FAILED);
     }
//--- ok
   return(INIT_SUCCEEDED);
  }

Wir werden es nur mit EURUSD, D1 ausführen. Das liegt daran, dass wir die Daten der aktuellen Symbolperiode verwenden, während die Modelle mit Tagespreisen trainiert werden.

Die Modelle sind im Expert Advisor als Ressourcen enthalten.

Es ist wichtig, die Formen der Eingangs- und Ausgangsdaten explizit zu definieren.

Die Funktion OnTick

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//--- check new bar
   if(TimeCurrent()<ExtNextBar)
      return;
//--- set next bar time
   ExtNextBar=TimeCurrent();
   ExtNextBar-=ExtNextBar%PeriodSeconds();
   ExtNextBar+=PeriodSeconds();

//--- predict price movement
   Predict();
//--- check trading according to prediction
   if(ExtPredictedClass>=0)
      if(PositionSelect(_Symbol))
         CheckForClose();
      else
         CheckForOpen();
  }

Alle Handelsoperationen werden nur zu Beginn des Tages durchgeführt.

Funktion der Vorhersage

//+------------------------------------------------------------------+
//| Voting classification                                            |
//+------------------------------------------------------------------+
void Predict(void)
  {
//--- evaluate first model
   ExtPredictedClass1=PredictPrice(ExtHandle1,SAMPLE_SIZE1);
//--- evaluate second model
   ExtPredictedClass2=PredictPriceMovement(ExtHandle2,SAMPLE_SIZE2);
//--- vote
   if(ExtPredictedClass1==ExtPredictedClass2)
      ExtPredictedClass=ExtPredictedClass1;
   else
      ExtPredictedClass=-1;
  }

Eine Klasse gilt als ausgewählt, wenn beide Modelle für die gleiche Klasse gestimmt haben. Dies ist eine Mehrheitsentscheidung. Und da es nur zwei Modelle im Ensemble gibt, bedeutet die Mehrheitsentscheidung „einstimmig“.

Vorhersage des Tagesschlusskurses aus 10 vorherigen OHLC-Kursen

//+------------------------------------------------------------------+
//| Predict next price (first model)                                 |
//+------------------------------------------------------------------+
int PredictPrice(const long handle,const int sample_size)
  {
   static matrixf input_data(sample_size,4);    // matrix for prepared input data
   static vectorf output_data(1);               // vector to get result
   static matrix  mm(sample_size,4);            // matrix of horizontal vectors Mean
   static matrix  ms(sample_size,4);            // matrix of horizontal vectors Std
   static matrix  x_norm(sample_size,4);        // matrix for prices normalize

//--- prepare input data
   matrix rates;
//--- request last bars
   if(!rates.CopyRates(_Symbol,_Period,COPY_RATES_OHLC,1,sample_size))
      return(-1);
//--- get series Mean
   vector m=rates.Mean(1);
//--- get series Std
   vector s=rates.Std(1);
//--- prepare matrices for prices normalization
   for(int i=0; i<sample_size; i++)
     {
      mm.Row(m,i);
      ms.Row(s,i);
     }
//--- the input of the model must be a set of vertical OHLC vectors
   x_norm=rates.Transpose();
//--- normalize prices
   x_norm-=mm;
   x_norm/=ms;

//--- run the inference
   input_data.Assign(x_norm);
   if(!OnnxRun(handle,ONNX_NO_CONVERSION,input_data,output_data))
      return(-1);
//--- denormalize the price from the output value
   double predicted=output_data[0]*s[3]+m[3];
//--- classify predicted price movement
   int    predicted_class=-1;
   double delta=rates[3][sample_size-1]-predicted;
   if(fabs(delta)<=0.0001)
      predicted_class=PRICE_SAME;
   else
     {
      if(delta<0)
         predicted_class=PRICE_UP;
      else
         predicted_class=PRICE_DOWN;

     }

   return(predicted_class);
  }

Die Eingabedaten sollten nach denselben Regeln aufbereitet werden wie beim Training des Modells. Nach der Ausführung des Modells wird der resultierende Wert wieder in den Preis umgerechnet. Die Klasse wird auf der Grundlage der Differenz zwischen dem letzten Schlusskurs in der Serie und dem resultierenden Kurs berechnet.

Die Vorhersage der Kursentwicklung basiert auf einer Reihe von 63 täglichen Schlusskursen:

//+------------------------------------------------------------------+
//| Predict price movement (second model)                            |
//+------------------------------------------------------------------+
int PredictPriceMovement(const long handle,const int sample_size)
  {
   static vectorf input_data(sample_size);    // vector for prepared input data
   static vectorf output_data(3);             // vector to get result

//--- request last bars
   if(!input_data.CopyRates(_Symbol,_Period,COPY_RATES_CLOSE,1,sample_size))
      return(-1);
//--- get series Mean
   float m=input_data.Mean();
//--- get series Std
   float s=input_data.Std();
//--- normalize prices
   input_data-=m;
   input_data/=s;

//--- run the inference
   if(!OnnxRun(handle,ONNX_NO_CONVERSION,input_data,output_data))
      return(-1);
//--- evaluate prediction
   return(int(output_data.ArgMax()));
  }

Die Preise werden nach den gleichen Regeln wie im ersten Modell normalisiert. Dieses Mal ist der Code jedoch kompakter, da die Eingabe ein Vektor und keine Matrix ist. Die Klasse wird durch den Maximalwert der drei Wahrscheinlichkeiten ausgewählt.

Die Handelsstrategie ist einfach. Die Handelsgeschäfte werden zu Beginn eines jeden Tages durchgeführt. Wenn die Vorhersage lautet „der Preis wird steigen“, dann kaufen wir; wenn sie lautet „der Preis wird fallen“, dann verkaufen wir.

//+------------------------------------------------------------------+
//| Check for open position conditions                               |
//+------------------------------------------------------------------+
void CheckForOpen(void)
  {
   ENUM_ORDER_TYPE signal=WRONG_VALUE;
//--- check signals
   if(ExtPredictedClass==PRICE_DOWN)
      signal=ORDER_TYPE_SELL;    // sell condition
   else
     {
      if(ExtPredictedClass==PRICE_UP)
         signal=ORDER_TYPE_BUY;  // buy condition
     }

//--- open position if possible according to signal
   if(signal!=WRONG_VALUE && TerminalInfoInteger(TERMINAL_TRADE_ALLOWED))
      ExtTrade.PositionOpen(_Symbol,signal,InpLots,
                            SymbolInfoDouble(_Symbol,signal==ORDER_TYPE_SELL ? SYMBOL_BID:SYMBOL_ASK),
                            0,0);
  }
//+------------------------------------------------------------------+
//| Check for close position conditions                              |
//+------------------------------------------------------------------+
void CheckForClose(void)
  {
   bool bsignal=false;
//--- position already selected before
   long type=PositionGetInteger(POSITION_TYPE);
//--- check signals
   if(type==POSITION_TYPE_BUY && ExtPredictedClass==PRICE_DOWN)
      bsignal=true;
   if(type==POSITION_TYPE_SELL && ExtPredictedClass==PRICE_UP)
      bsignal=true;

//--- close position if possible
   if(bsignal && TerminalInfoInteger(TERMINAL_TRADE_ALLOWED))
     {
      ExtTrade.PositionClose(_Symbol,3);
      //--- open opposite
      CheckForOpen();
     }
  }


Wir haben unser Modell mit den Daten bis Anfang 2023 trainiert. Legen wir also das Prüfintervall vom Jahresanfang an fest.

Test-Einstellungen

Hier ist das Testergebnis auf der Grundlage der Daten seit Anfang des Jahres.

Testergebnisse des Expert Advisors


Es wäre interessant, die Testergebnisse für jedes einzelne Modell zu kennen.

Dazu müssen wir den EA-Quellcode wie folgt ändern:

enum EnModels
  {
   USE_FIRST_MODEL,    // Use first model only
   USE_SECOND_MODEL,   // Use second model only
   USE_BOTH_MODELS     // Use both models
  };
input EnModels InpModels = USE_BOTH_MODELS;  // Models using
input double   InpLots   = 1.0;              // Lots amount to open position

...

//+------------------------------------------------------------------+
//| Voting classification                                            |
//+------------------------------------------------------------------+
void Predict(void)
  {
//--- evaluate first model
   if(InpModels==USE_BOTH_MODELS || InpModels==USE_FIRST_MODEL)
      ExtPredictedClass1=PredictPrice(ExtHandle1,SAMPLE_SIZE1);
//--- evaluate second model
   if(InpModels==USE_BOTH_MODELS || InpModels==USE_SECOND_MODEL)
      ExtPredictedClass2=PredictPriceMovement(ExtHandle2,SAMPLE_SIZE2);

//--- check predictions
   switch(InpModels)
     {
      case USE_FIRST_MODEL :
         ExtPredictedClass=ExtPredictedClass1;
         break;
      case USE_SECOND_MODEL :
         ExtPredictedClass=ExtPredictedClass2;
         break;
      case USE_BOTH_MODELS :
         if(ExtPredictedClass1==ExtPredictedClass2)
            ExtPredictedClass=ExtPredictedClass1;
         else
            ExtPredictedClass=-1;
     }
  }

Aktivieren Sie den Parameter „Use first model only“ (‚Nur das erste Modell verwenden‘).

Expert Advisor-Einstellungen zur Verwendung nur des ersten Modells

Die Ergebnisse des ersten Modelltests

Erste Modelltestergebnisse


Nun wollen wir das zweite Modell testen. Hier sind die Ergebnisse des zweiten Modelltests.

Zweite Modelltest-Ergebnisse

Das zweite Modell erwies sich als viel stärker als das erste. Die Ergebnisse bestätigen die Theorie, dass schwache Modelle zusammengesetzt werden müssen. In diesem Artikel ging es jedoch nicht um die Theorie des Bildens von Ensemble, sondern um die praktische Anwendung.

Wichtiger Hinweis: Bitte beachten Sie, dass die in diesem Artikel verwendeten Modelle nur zur Demonstration der Arbeit mit ONNX-Modellen in der Sprache MQL5 dienen. Der Expert Advisor ist nicht für den Handel auf realen Konten vorgesehen.



Schlussfolgerung

Wir haben ein sehr einfaches, aber anschauliches Beispiel für ein Ensemble aus zwei ONNX-Modellen vorgestellt. Die Anzahl der gleichzeitig verwendeten Modelle ist begrenzt und kann 256 Modelle nicht überschreiten. Aber auch die Verwendung von mehr als zwei Modellen erfordert einen anderen Ansatz bei der Programmierung von Expert Advisors, nämlich die objektorientierte Programmierung.

Aber das ist ein Thema für einen anderen Artikel.

Übersetzt aus dem Russischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/ru/articles/12433

Beigefügte Dateien |
MQL5.zip (105.08 KB)
Algorithmen zur Optimierung mit Populationen: Harmonie-Suche (HS) Algorithmen zur Optimierung mit Populationen: Harmonie-Suche (HS)
In diesem Artikel werde ich den leistungsstärksten Optimierungsalgorithmus untersuchen und testen - die Harmonie-Suche (HS), inspiriert durch den Prozess der Suche nach der perfekten Klangharmonie. Welcher Algorithmus ist nun der führende in unserer Bewertung?
Backpropagation von Neuronalen Netze mit MQL5-Matrizen Backpropagation von Neuronalen Netze mit MQL5-Matrizen
Der Artikel beschreibt die Theorie und Praxis der Anwendung des Backpropagation-Algorithmus in MQL5 unter Verwendung von Matrizen. Es bietet vorgefertigte Klassen zusammen mit Beispielen von Skripten, Indikatoren und Expert Advisors.
Datenwissenschaft und maschinelles Lernen (Teil 11): Naïve Bayes, Wahrscheinlichkeitsrechnung im Handel Datenwissenschaft und maschinelles Lernen (Teil 11): Naïve Bayes, Wahrscheinlichkeitsrechnung im Handel
Der Handel mit Wahrscheinlichkeiten ist wie ein Drahtseilakt - er erfordert Präzision, Ausgewogenheit und ein ausgeprägtes Risikobewusstsein. In der Welt des Handels ist die Wahrscheinlichkeit alles. Das ist der Unterschied zwischen Erfolg und Misserfolg, Gewinn und Verlust. Indem sie sich die Macht der Wahrscheinlichkeit zunutze machen, können Händler fundierte Entscheidungen treffen, Risiken effektiv verwalten und ihre finanziellen Ziele erreichen. Ob Sie nun ein erfahrener Anleger oder ein Anfänger sind, das Verständnis der Wahrscheinlichkeit ist der Schlüssel zur Entfaltung Ihres Handelspotenzials. In diesem Artikel werden wir die aufregende Welt des Handels mit Wahrscheinlichkeiten erkunden und Ihnen zeigen, wie Sie Ihr Handelsspiel auf die nächste Stufe heben können.
Wie man ONNX-Modelle in MQL5 verwendet Wie man ONNX-Modelle in MQL5 verwendet
ONNX (Open Neural Network Exchange) ist ein offenes Format, das zur Darstellung von Modellen des maschinellen Lernens entwickelt wurde. In diesem Artikel wird untersucht, wie ein CNN-LSTM-Modell zur Vorhersage von Finanzzeitreihen erstellt werden kann. Wir werden auch zeigen, wie man das erstellte ONNX-Modell in einem MQL5 Expert Advisor verwendet.