Untersuchung von Regressionsmodellen für kausale Inferenz und algorithmischen Handel
Einführung
Im Laufe mehrerer Artikel haben wir verschiedene Methoden zur Klassifizierung von Zeitreihen untersucht, aber wir sind nicht auf Regressionsmodelle eingegangen. Regressionsmodelle ermöglichen es uns im Gegensatz zur binären Klassifizierung, nicht die Wahrscheinlichkeit vorherzusagen, mit der eine Beobachtung zu einer bestimmten Klasse gehört, sondern kontinuierliche Werte, was die Möglichkeiten ihrer Anwendung zur Erstellung automatisierter Handelssysteme erweitert.
Die binäre Klassifizierung ist eine grundlegende Aufgabe des maschinellen Lernens, bei der das Ziel darin besteht, Eingabedaten in eine von zwei verschiedenen Kategorien oder Klassen zu klassifizieren. Im Kontext eines Forex-Handelsbots bedeutet dies normalerweise die Vorhersage eines „Kauf“- (dargestellt als 0) oder „Verkauf“-Signals (dargestellt als 1). Dieser Ansatz reduziert die komplexe Marktdynamik auf eine einfache Richtungsentscheidung.
Die bedeutendste inhärente Einschränkung der binären Klassifizierung für den quantitativen Handel ist ihre Unfähigkeit, das Ausmaß oder die Intensität einer vorhergesagten Kursbewegung zu quantifizieren. Ein binärer Klassifikator gibt nur an, ob sich der Kurs voraussichtlich nach oben oder unten bewegen wird, ohne Informationen darüber zu liefern, wie stark er sich voraussichtlich ändern wird. Dieser Mangel an Granularität schränkt die Entscheidungsfindung im Handel grundlegend ein.
Die Genauigkeit der Vorhersagen des Klassifikators allein berücksichtigt nicht das Ausmaß der Änderung und ist daher für den Handel nicht sehr nützlich. Dieser Aspekt ist entscheidend, da er verdeutlicht, dass eine hohe Richtungsgenauigkeit (z. B. die korrekte Vorhersage der Richtung in 70 % der Fälle) nicht automatisch zu profitablem Handel führt.
Wichtig ist die Beobachtung, dass eine hohe Richtungsgenauigkeit keine Rentabilität garantiert. Sie können zum Beispiel in 30 % der Fälle richtig liegen und profitabel sein, oder Sie können in 70 % der Fälle richtig liegen und unprofitabel sein. Dies zeigt, dass das Nettoergebnis einer Handelsstrategie durch die Höhe des Gewinns bei gewinnbringenden Trades im Vergleich zur Höhe des Verlusts bei verlustbringenden Trades bestimmt wird und nicht einfach durch den Prozentsatz der Gewinne.
Indem das binäre Klassifikationsmodell alle korrekten Richtungsprognosen unabhängig von der tatsächlichen Kursbewegung gleich behandelt, kann es nicht zwischen einer kleinen, unbedeutenden Kursbewegung und einer großen, hochprofitablen unterscheiden. Dies kann zu einem Szenario führen, in dem viele kleine gewinnbringende Trades durch wenige große verlustbringende Trades ausgeglichen werden oder umgekehrt, was trotz scheinbar hoher Genauigkeit zu einem insgesamt negativen PnL führt.
Das Fehlen einer Quantifizierung der Kursbewegung bedeutet, dass der Handelsbot keine Trades mit höheren erwarteten Gewinnen priorisieren oder Trades vermeiden kann, bei denen der potenzielle Verlust den potenziellen Gewinn deutlich überwiegt, selbst wenn die Richtung korrekt vorhergesagt wurde. Ohne Informationen über das Ausmaß arbeitet der Bot mit einem blinden Fleck bezüglich der tatsächlichen finanziellen Auswirkungen seiner Entscheidungen, was trotz eines hohen Prozentsatzes an richtungsbasierten Gewinnen zu suboptimalen oder sogar negativen kumulativen Renditen führt.
Änderung der Labeling-Funktion
Betrachten Sie das folgende Szenario: Es gibt eine finanzielle Zeitreihe, die auf Basis einer Reihe von Merkmalen vorhergesagt werden muss. Im Falle einer binären Klassifizierung kann die Richtung eines zukünftigen Trades (Kauf oder Verkauf) bestimmt werden, und diese Labels sind immer festgelegt. Wir können sie nicht anders labeln, um eine genauere Schätzung des Ausmaßes zukünftiger Kursabweichungen zu erhalten. Alle Trades gelten als gleichwertig, unabhängig davon, wie stark sich der Kurs tatsächlich geändert hat.
Stellen Sie sich nun vor, dass wir nicht nur die Richtung eines Handels vorhersagen können, sondern auch das Ausmaß der zukünftigen Änderung. Damit können wir unser Handelssystem feiner abstimmen, indem wir zusätzliche Filter erstellen, die dabei helfen, nur die vorhergesagten Kursschwankungen zu identifizieren, die für den Handel signifikant sind, und unbedeutende auszuschließen.
Um ein Regressionsmodell zu trainieren, ist es notwendig, Merkmale und Ziele für dessen Training vorzubereiten. Die Merkmale können vom Klassifikator und dem Regressor gemeinsam genutzt werden, während sich die Zielvariablen unterscheiden werden.
Schreiben wir eine einfache Funktion, die beispielhaft Labels für ein Regressionsmodell erzeugt.
@njit def calculate_labels_r(close_data, min_val, max_val): labels = [] for i in range(len(close_data) - max_val): rand = random.randint(min_val, max_val) labels.append(close_data[i + rand] - close_data[i]) return labels def get_labels_r(dataset, min = 1, max = 15) -> pd.DataFrame: # Extract closing prices from the dataset close_data = dataset['close'].values labels = calculate_labels_r(close_data, min, max) # Trim the dataset to match the length of calculated labels dataset = dataset.iloc[:len(labels)].copy() # Add the calculated labels as a new column dataset['labels'] = labels # Remove rows with NaN values (potentially introduced in 'calculate_labels') dataset = dataset.dropna() return dataset
Der Hauptunterschied zur Label-Erzeugung bei der binären Klassifizierung besteht darin, dass wir nun Kursänderungen bestimmen (Subtraktion des aktuellen Kurses vom zukünftigen Kurs), anstatt einfach die Richtung (Kauf oder Verkauf) zu bestimmen. Der Code wird durch Numba beschleunigt, sodass das Ziel-Labeling sehr schnell ist.
Die obige Funktion berücksichtigt nur die Differenz zwischen einem zufällig ausgewählten zukünftigen Kurs im Bereich {min_val; max_val} und dem aktuellen Kurs. Dies ist möglicherweise nicht ganz korrekt, da zwischenzeitliche Abweichungen, die signifikant sein könnten, nicht berücksichtigt werden. Ich schlage eine weitere Modifikation der Abweichungsberechnungsfunktion vor, die unten dargestellt ist.
@njit def calculate_labels_mean_r(close_data, min_val, max_val): labels = [] for i in range(len(close_data) - max_val): # Calculate the average price value in the window from min_val to max_val future_prices = close_data[i + min_val : i + max_val + 1] mean_future_price = np.mean(future_prices) # Calculate the difference between the average future value and the current price labels.append(mean_future_price - close_data[i]) return labels def get_labels_r(dataset, min = 1, max = 15) -> pd.DataFrame: # Extract closing prices from the dataset close_data = dataset['close'].values # Calculate buy/hold labels based on future price movements labels = calculate_labels_mean_r(close_data, min, max) # Trim the dataset to match the length of calculated labels dataset = dataset.iloc[:len(labels)].copy() # Add the calculated labels as a new column dataset['labels'] = labels # Remove rows with NaN values (potentially introduced in 'calculate_labels') dataset = dataset.dropna() return dataset
Nun berücksichtigt die Funktion alle Kursabweichungen im angegebenen Intervall und berechnet dafür den Durchschnitt der Kurse. Danach wird die Differenz zwischen dem Durchschnittswert der zukünftigen Kurse und dem aktuellen Kurs berechnet. Dementsprechend ruft die Funktion get_labels_r() nun die Labeling-Funktion calculate_labels_mean_r() auf und nicht mehr calculate_labels_r() wie zuvor. Wir können experimentieren, indem wir verschiedene Labeling-Funktionen aufrufen.
Hinzufügen eines Systems zur kausalen Inferenz
Für genauere Vorhersagen verwenden wir einen Algorithmus, der dem im Artikel über kausale Inferenz beschriebenen ähnelt. Der Hauptunterschied besteht in der Verwendung eines Regressors anstelle eines Klassifikators.
def meta_learners(data, models_number: int, iterations: int, depth: int): data = data.copy() data = data[(data.index < hyper_params['forward']) & (data.index > hyper_params['backward'])].copy() X = data[data.columns[1:-1]] y = data['labels'] data['meta_labels'] = 0 for i in range(models_number): X_train, X_val, y_train, y_val = train_test_split( X, y, train_size = 0.5, test_size = 0.5, shuffle = True) # fit debias model with train and validation subsets meta_m = CatBoostRegressor(iterations = iterations, depth = depth, verbose = False, use_best_model = True) meta_m.fit(X_train, y_train, eval_set = (X_val, y_val), plot = False) coreset = X.copy() coreset['labels'] = y coreset['labels_pred'] = meta_m.predict(X) data['meta_labels'] += abs(coreset['labels'] - coreset['labels_pred']) data['meta_labels'] = data['meta_labels'] / models_number return data
Die Funktion trainiert mehrere Regressoren auf zufälligen Teilmengen von Daten aus dem ursprünglichen Datensatz und vergleicht dann die tatsächlichen Zielwerte mit den vorhergesagten. Daher wird das Metamodell nicht 0 oder 1 (Trade eröffnen oder nicht) vorhersagen, sondern die Durchschnittswerte der Abweichungen der Prognosen von den tatsächlichen Werten. Auf diese Weise können wir Prognosen herausfiltern, die signifikant von den erwarteten Werten abweichen.
Training und Test trainierter Modelle
Zum Testen von Regressionsmodellen wurde der Tester modifiziert. Jetzt verfügt er über das Suffix ‚r‘. Es ist an der Zeit, mehrere Modelle zu trainieren. In diesem Artikel werde ich 10 Modelle trainieren und dasjenige auswählen, das sich aus meiner Sicht am besten eignet.
hyper_params = {
'symbol': 'EURUSD_H1',
'export_path': '/Users/dmitrievsky/drive_c/Program Files/MetaTrader 5/MQL5/Include/Trend following/',
'model_number': 0,
'markup': 0.00010,
'stop_loss': 0.00500,
'take_profit': 0.00200,
'periods': [i for i in range(5, 100, 30)],
'backward': datetime(2010, 1, 1),
'forward': datetime(2024, 1, 1),
}
models = []
for i in range(10):
print('Learn ' + str(i) + ' model')
data = get_labels_r(get_features(get_prices()), min=1, max=15)
dataset = meta_learners(data=data, models_number=5, iterations=15, depth=3)
models.append(fit_final_models(dataset, tol=3e-2))
Hier sollten wir auf den Parameter tol achten, der an die Funktion zum Training des endgültigen Modells übergeben wird. Da wir das Hauptmodell so robust wie möglich machen wollen, ist es nicht sinnvoll, es mit allen Beispielen zu trainieren. Wir werden es nur mit denjenigen Beispielen trainieren, deren Vorhersagen um weniger als den tol-Wert von den tatsächlichen Werten abweichen.
Da Abweichungen von Vorhersagen tatsächlich in Punkten gezählt werden, bedeutet tol=3e-2 eine maximale Differenz von 0.03 oder 300 vierstelligen Punkten. Es mag als Filter wie ein großer Unterschied erscheinen, aber es ist zu bedenken, dass dies eine Differenz in absoluten Werten ist, da Vorhersagen sowohl positiv als auch negativ sein können. Sie können mit diesem Parameter experimentieren. Nachfolgend finden Sie die Funktion selbst.
def fit_final_models(dataset, tol=1e-2) -> list: # features for model\meta models. We learn main model only on filtered labels X = dataset[dataset['meta_labels'] < tol] X, X_meta = X[X.columns[1:-2]], dataset[dataset.columns[1:-2]] # labels for model\meta models y = dataset[dataset['meta_labels'] < tol] y, y_meta = y[y.columns[-2]], dataset[dataset.columns[-1]] # fit main model with train and validation subsets model = RandomForestRegressor(n_estimators=50, max_depth=10) model.fit(X, y) # fit meta model with train and validation subsets meta_model = RandomForestRegressor(n_estimators=50, max_depth=10) meta_model.fit(X_meta, y_meta) data = get_features(get_prices()) R2 = test_model_r(data, [model, meta_model], hyper_params['stop_loss'], hyper_params['take_profit'], hyper_params['forward'], hyper_params['backward'], hyper_params['markup'], plt=False) if math.isnan(R2): R2 = -1.0 print('R2 is fixed to -1.0') print('R2: ' + str(R2)) result = [R2, model, meta_model] return result
Sortieren wir nun die Modelle und rufen die benutzerdefinierte Tester-Funktion auf:
models.sort(key=lambda x: x[0]) data = get_features(get_prices()) test_model_r(data, models[-1][1:], hyper_params['stop_loss'], hyper_params['take_profit'], hyper_params['forward'], hyper_params['backward'], hyper_params['markup'], plt=True)
Das Modell ist an die Trainingsdaten überfittet und schneidet bei neuen Daten schlecht ab:

Abb. 1. Testen des Modells mit grundlegendem Labeling
Wir werden genau die gleichen Manipulationen durchführen, aber wir verwenden die Trade-Labeling-Funktion calculate_labels_mean_r(), die zukünftige Durchschnittskurse berechnet.

Abb. 2. Testen des Modells mit gemitteltem Labeling
Die zweite Trade-Labeling-Funktion zeigt im Durchschnitt stabilere Ergebnisse bei neuen Daten. Dies liegt anscheinend daran, dass der Durchschnittswert zukünftiger Kurse berücksichtigt wird.
Der benutzerdefinierte Tester kann keine Schwellenwerte für das Hauptregressionsmodell festlegen, daher unterteilt er die Modellvorhersagen einfach in positive und negative, was bedeutet, dass die Signale immer noch recht grob sind. Aber wir werden dies direkt im Terminal des MetaTrader 5 beheben.
Exportieren von Modellen in das Terminal des MetaTrader 5
Jetzt müssen wir die Modelle im ONNX-Format in das Terminal exportieren und das Handelssystem konfigurieren. Die Exportfunktion sieht vertraut aus:
export_model_to_ONNX(model = models[-1], symbol = hyper_params['symbol'], periods = hyper_params['periods'], periods_meta = hyper_params['periods'], model_number = hyper_params['model_number'], export_path = hyper_params['export_path'])
Es ist anzumerken, dass ich CatBoost-Regressionsmodelle im ONNX-Format nicht mit dem Terminal verwenden konnte. Daher habe ich stattdessen Random Forest verwendet.
Die Dimension des Eingabetensors wird automatisch in Abhängigkeit von den Hyperparametern (Anzahl der Merkmale) angepasst, die vor Beginn des Trainings festgelegt werden. Anschließend werden die Modelle mithilfe der Funktion convert_sklearn() in das ONNX-Format konvertiert und in dem Verzeichnis auf der Festplatte gespeichert, das Sie in den Hyperparametern angegeben haben.
def export_model_to_ONNX(**kwargs): model = kwargs.get('model') symbol = kwargs.get('symbol') periods = kwargs.get('periods') periods_meta = kwargs.get('periods_meta') model_number = kwargs.get('model_number') export_path = kwargs.get('export_path') initial_type = [('float_input', FloatTensorType([None, len(hyper_params['periods'])]))] onnx_model = convert_sklearn(model[1], initial_types=initial_type) # save main model to ONNX with open(export_path +'catmodel ' + symbol + ' ' + str(model_number) +'.onnx', "wb") as f: f.write(onnx_model.SerializeToString()) onnx_model_meta = convert_sklearn(model[2], initial_types=initial_type) # save meta model to ONNX with open(export_path +'catmodel_m ' + symbol + ' ' + str(model_number) +'.onnx', "wb") as f: f.write(onnx_model_meta.SerializeToString()) code = '#include <Math\Stat\Math.mqh>' code += '\n' code += '#resource "catmodel '+ symbol + ' '+str(model_number)+'.onnx" as uchar ExtModel_' + symbol + '_' + str(model_number) + '[]' code += '\n' code += '#resource "catmodel_m '+ symbol + ' '+str(model_number)+'.onnx" as uchar ExtModel2_' + symbol + '_' + str(model_number) + '[]' code += '\n\n' code += 'int Periods' + symbol + '_' + str(model_number) + '[' + str(len(periods)) + \ '] = {' + ','.join(map(str, periods)) + '};' code += '\n' code += 'int Periods_m' + symbol + '_' + str(model_number) + '[' + str(len(periods_meta)) + \ '] = {' + ','.join(map(str, periods_meta)) + '};' code += '\n\n' # get features code += 'void fill_arays' + symbol + '_' + str(model_number) + '( double &features[]) {\n' code += ' double pr[], ret[];\n' code += ' ArrayResize(ret, 1);\n' code += ' for(int i=ArraySize(Periods'+ symbol + '_' + str(model_number) + ')-1; i>=0; i--) {\n' code += ' CopyClose(NULL,PERIOD_H1,1,Periods' + symbol + '_' + str(model_number) + '[i],pr);\n' code += ' ret[0] = MathStandardDeviation(pr);\n' code += ' ArrayInsert(features, ret, ArraySize(features), 0, WHOLE_ARRAY); }\n' code += ' ArraySetAsSeries(features, true);\n' code += '}\n\n' # get features code += 'void fill_arays_m' + symbol + '_' + str(model_number) + '( double &features[]) {\n' code += ' double pr[], ret[];\n' code += ' ArrayResize(ret, 1);\n' code += ' for(int i=ArraySize(Periods_m' + symbol + '_' + str(model_number) + ')-1; i>=0; i--) {\n' code += ' CopyClose(NULL,PERIOD_H1,1,Periods_m' + symbol + '_' + str(model_number) + '[i],pr);\n' code += ' ret[0] = MathStandardDeviation(pr);\n' code += ' ArrayInsert(features, ret, ArraySize(features), 0, WHOLE_ARRAY); }\n' code += ' ArraySetAsSeries(features, true);\n' code += '}\n\n' file = open(export_path + str(symbol) + ' ONNX include' + ' ' + str(model_number) + '.mqh', "w") file.write(code) file.close() print('The file ' + 'ONNX include' + '.mqh ' + 'has been written to disk')
Festlegen von Schwellenwerten im MetaTrader 5-Terminal
Da wir nun zwei Regressionsmodelle anstelle von zwei Klassifikatoren haben, können wir spezifische numerische Schwellenwerte festlegen.

Abb. 3. Konfiguration der Signalschwellenwerte im Terminal
- buy_threshold und sell_threshold sind für die Filterung der Signale des Hauptregressionsmodells verantwortlich. Wenn das Signal unter diesem Schwellenwert liegt, werden keine Trades eröffnet. Wenn beispielsweise die vorhergesagte Kursänderung weniger als 10 Pips beträgt, ist die Eröffnung eines solchen Trades nicht sehr sinnvoll, da dies den Spread und die Provision nicht deckt.
- Der meta_threshold filtert die Signale des Hauptmodells basierend auf der zuvor beschriebenen kausalen Inferenz. Es testet, wie stark die Prognose voraussichtlich von der tatsächlichen zukünftigen Änderung abweichen wird. Wenn die Differenz zu groß ist, werden die Trades ebenfalls nicht eröffnet.
Lassen Sie uns nun unser Modell im MetaTrader 5-Tester mit den vorgegebenen Schwellenwerten testen:

Abb. 4. Testen eines Modells mit vorgegebenen Schwellenwerten
Ich möchte Sie daran erinnern, dass der Forward-Zeitraum Anfang 2024 beginnt und das Modell diesen Forward-Zeitraum nun recht stabil handhabt. Dies unterstreicht die Bedeutung der korrekten Definition und Einstellung von Schwellenwerten. Sie können die Schwellenwerte selbst optimieren.
Die Vielfalt der Modelle kann groß sein, abhängig von der Art der Merkmale (in diesem Artikel werden beide Modelle mit Standardabweichungen trainiert) und von den Modellparametern selbst. Zum Beispiel wurde ein anderes Modell mit anderen Parametern trainiert, das auch ohne Anpassung der Schwellenwerte auf neuen Daten gut abschnitt.

Abb. 5. Training und Testen eines anderen Modells mit anderen Trainingsparametern
Nach der Anpassung der Schwellenwerte zeigte das Modell ab Anfang 2024 ein stetiges Wachstum.

Abb. 6. Testen des Modells im Terminal nach dem Festlegen der Schwellenwerte
Das Testen von Modellen auf Basis einer zweiten Trade-Labeling-Funktion und die Filterung nach Schwellenwerten liefern noch interessantere und genauere Ergebnisse:

Abb. 7. Testen des Modells auf Basis der durchschnittlichen Trade-Labeling-Funktion und tol = 1e-2
Wenn wir den Parameter tol beim Training von 1e-2 auf 1e-3 ändern, werden die Ergebnisse noch besser sein:

Abb. 8. Testen des Modells auf Basis der durchschnittlichen Trade-Labeling-Funktion und tol = 1e-3
Weitere Informationen
Um Modelle zu exportieren, müssen wir das Paket skl2onnx installieren und importieren:
from skl2onnx import convert_sklearn from skl2onnx.common.data_types import FloatTensorType
Der ONNX-Aufrufcode im Trading-Bot-Code wurde ebenfalls modifiziert, um neue Regressionsmodelle korrekt zu verarbeiten:
vectorf y_main(1), y_meta(1); OnnxRun(ExtHandle, ONNX_DEBUG_LOGS, f, y_main); OnnxRun(ExtHandle2, ONNX_DEBUG_LOGS, f_m, y_meta); float sig = y_main[0]; float meta_sig = y_meta[0];
Zusätzlich wurden neue Eingabeparameter zum Anpassen und Optimieren von Schwellenwerten hinzugefügt:
input double buy_threshold = 0.00001; input double sell_threshold = -0.00001; input double meta_threshold = 0.001;
Die ONNX-Modellnamen werden nun über #define-Direktiven referenziert, was die Einbindung von Modellen mit unterschiedlichen Namen erleichtert.
#define model ExtModel_EURUSD_H1_0 #define model_m ExtModel2_EURUSD_H1_0 #define periods PeriodsEURUSD_H1_0 #define periods_m Periods_mEURUSD_H1_0 #define fill_arrays fill_araysEURUSD_H1_0 #define fill_arrays_m fill_arays_mEURUSD_H1_0
Handelssignale werden generiert, wenn Bedingungen in Abhängigkeit von den Schwellenwerten ausgelöst werden:
if((Ask-Bid < max_spread*_Point) && MathAbs(meta_sig) < meta_threshold && AllowTrade(OrderMagic)) if(countOrders(OrderMagic) < max_orders && CheckMoneyForTrade(_Symbol, LotsOptimized(), ORDER_TYPE_BUY)) { double l = LotsOptimized(); if(sig > buy_threshold && Allow_Buy) { int res = -1; do { double stop = Bid - stoploss * _Point; double take = Ask + takeprofit * _Point; res = mytrade.PositionOpen(_Symbol, ORDER_TYPE_BUY, l, Ask, stop, take, bot_comment); Sleep(50); } while(res == -1); } else { if(sig < sell_threshold && Allow_Sell) { int res = -1; do { double stop = Ask + stoploss * _Point; double take = Bid - takeprofit * _Point; res = mytrade.PositionOpen(_Symbol, ORDER_TYPE_SELL, l, Bid, stop, take, bot_comment); Sleep(50); } while(res == -1); } } }
Der modifizierte Strategietester und die Modellexportfunktion wurden den entsprechenden Modulen hinzugefügt und dem Artikel beigefügt.
Schlussfolgerung
In diesem Artikel habe ich einen möglichen, aber nicht den einzigen Weg beschrieben, Handelssysteme auf der Grundlage von Regressionsmodellen aufzubauen. Dieser Ansatz ermöglicht eine feinere Abstimmung von auf maschinellem Lernen basierenden Bots. Er ermöglicht es auch, durch geeignete Schwellenwerte selbst klar unprofitable Modelle rentabler zu machen. Sie können beliebige Merkmale und/oder Handels-Labeling-Funktionen verwenden und diesen Algorithmus auch auf anderen Handelsinstrumenten und in anderen Zeitrahmen testen.
Das Archiv Python files.zip enthält die folgenden Dateien für die Entwicklung in der Python-Umgebung:
| Dateiname | Beschreibung |
|---|---|
| causal regression.py | Das Hauptskript für das Training von Modellen |
| labeling_lib.py | Aktualisiertes Modul zum Trade-Labeling |
| tester_lib.py | Aktualisierter benutzerdefinierter Strategietester basierend auf maschinellem Lernen |
| export_lib.py | Modul zum Exportieren von Modellen in das Terminal |
| EURUSD_H1.csv | Aus MetaTrader 5 exportierte Kursdaten |
Das Archiv MQL5 files.zip enthält Dateien für das MetaTrader 5-Terminal:
| Dateiname | Beschreibung |
|---|---|
| regression trader.ex5 | Der kompilierte Bot aus dem Artikel |
| regression trader.mq5 | Der Quellcode des Bots aus dem Artikel |
| Include//Trend following folder | Die ONNX-Modelle und die Header-Datei für die Verbindung mit dem Bot |
Übersetzt aus dem Russischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/ru/articles/18603
Warnung: Alle Rechte sind von MetaQuotes Ltd. vorbehalten. Kopieren oder Vervielfältigen untersagt.
Dieser Artikel wurde von einem Nutzer der Website verfasst und gibt dessen persönliche Meinung wieder. MetaQuotes Ltd übernimmt keine Verantwortung für die Richtigkeit der dargestellten Informationen oder für Folgen, die sich aus der Anwendung der beschriebenen Lösungen, Strategien oder Empfehlungen ergeben.
Die Übertragung der Trading-Signale in einem universalen Expert Advisor.
Neuronale Netze im Trading: Anomalieerkennung im Frequenzbereich (letzter Teil)
Eine alternative Log-datei mit der Verwendung der HTML und CSS
Analyse von Kurs-Zeit-Lücken in MQL5 (Teil II): Erstellung einer Heatmap der Liquiditätsverteilung über die Zeit
- Freie Handelsapplikationen
- Über 8.000 Signale zum Kopieren
- Wirtschaftsnachrichten für die Lage an den Finanzmärkte
Sie stimmen der Website-Richtlinie und den Nutzungsbedingungen zu.
Ich verwende „causal_regression_orig.py“, um die Header-Datei „ea“ zu erstellen, und kompiliere anschließend „ea“.
Das Ergebnis ist das unten abgebildete Bild „test_result“.
Es gibt so viel weniger Trades als in dem von dir geposteten Beispiel.
Was ist also der Unterschied zwischen diesen beiden?
Gibt es im Python-Tester viele Trades? Wenn ja, dann müssen die Schwellenwerte für die Eröffnung von Trades im MQL5-Programm neu eingestellt werden – vielleicht sind sie zu hoch.
Das ist das Ergebnis des Python-Testers; ich verwende denselben Code, den du in diesem Beitrag angehängt hast. Ich habe im Konfigurationsfenster des MT5-Testers nachgesehen: Die Schwellenwerte „buy_threshold“ und „sell_threshold“ sind beide auf 0,0001 bzw. -0,0001 eingestellt, genau wie in diesem Beitrag.
Ich habe den Code überprüft und konnte keinen Unterschied feststellen.
Dies ist das Ergebnis des Python-Testers. Ich verwende denselben Code, den Sie in diesem Beitrag angehängt haben. Ich habe im Konfigurationsfenster des MT5-Testers nachgesehen: Die Werte für „buy_threshold“ und „sell_threshold“ sind beide 0,0001 bzw. -0,0001, genau wie in den Einstellungen in diesem Beitrag.
Ich habe den Code überprüft und konnte keinen Unterschied feststellen.
Hallo Maxim, vielen Dank, dass du deine Erfahrungen mit uns teilst.
Eine Frage: Wie kann man sich vergewissern, dass der Expert Advisor nach der Berechnung des ONNX-Modells für den neuen Ticker und dem Ablegen der Datei im Ordner „Trend Following“ tatsächlich die trainierten Daten für den neuen Ticker verwendet? Bei anderen Tickers verhält sich der Expert Advisor identisch, selbst wenn man die ONNX_EURUSD-Datei löscht und eine andere einfügt. Muss man beim Wechsel des Tickers etwas am MQL5-Expert Advisor ändern?
Hallo Maxim, vielen Dank, dass du das mit uns teilst.
Eine Frage: Wie kann man sich nach der Berechnung des ONNX für einen neuen Ticker und dem Ablegen der Datei im Ordner „Trend Following“ vergewissern, dass der Expert Advisor nun tatsächlich die trainierten Daten für den neuen Ticker verwendet? Bei anderen Tickers verhält sich der Expert Advisor identisch, selbst wenn man die ONNX_EURUSD-Datei löscht und eine andere einfügt. Muss man beim Wechsel des Tickers etwas am MQL5-Expert Advisor ändern?
Hallo, im Code des Expert Advisors muss die .mqh-Datei mit dem neuen Ticker eingebunden werden
Das heißt, die markierte Datei muss durch eine andere Datei mit einem anderen Namen ersetzt werden, die vom Python-Skript generiert wurde.