English Русский 中文 Español 日本語 Português
preview
Entwicklung eines Roboters in Python und MQL5 (Teil 2): Auswahl, Erstellung und Training von Modellen, Python Custom Tester

Entwicklung eines Roboters in Python und MQL5 (Teil 2): Auswahl, Erstellung und Training von Modellen, Python Custom Tester

MetaTrader 5Tester | 1 November 2024, 09:56
279 0
Yevgeniy Koshtenko
Yevgeniy Koshtenko

Kurze Zusammenfassung des vorherigen Artikels

Im vorangegangenen Artikel haben wir ein wenig über maschinelles Lernen gesprochen, eine Datenerweiterung durchgeführt, Merkmale für das zukünftige Modell entwickelt und die besten davon ausgewählt. Jetzt ist es an der Zeit, ein funktionierendes, maschinelles Lernmodell zu erstellen, das aus unseren Merkmalen lernt und (hoffentlich erfolgreich) handelt. Um das Modell zu evaluieren, werden wir einen nutzerdefinierten Python-Tester schreiben, der uns hilft, die Leistung des Modells und die Schönheit der Testgraphen zu bewerten. Um schönere Testgraphen und eine größere Modellstabilität zu erreichen, werden wir außerdem eine Reihe klassischer Funktionen des maschinellen Lernens entwickeln.

Unser oberstes Ziel ist es, ein funktionierendes und maximal profitables Modell für die Preisprognose und den Handel zu entwickeln. Der gesamte Code wird in Python geschrieben sein, mit Einbindung der MQL5-Bibliothek. 


Python-Version und erforderliche Module

Ich habe bei meiner Arbeit Python in der Version 3.10.10 verwendet.

Der unten angefügte Code enthält mehrere Funktionen für die Datenvorverarbeitung, die Merkmalsextraktion und das Training eines maschinellen Lernmodells. Dazu gehören insbesondere:

  • Die Funktion zum Clustern von Merkmalen unter Verwendung des Gaussian Mixture Model (GMM) aus der Bibliothek sklearn
  • Die Funktion zur Merkmalsextraktion mittels rekursiver Merkmaleliminierung mit Kreuzvalidierung (RFECV) aus der sklearn-Bibliothek
  • Die Funktion für das Training des XGBoost-Klassifikators

Um den Code auszuführen, müssen Sie die folgenden Python-Module installieren:

  • pandas
  • numpy
  • sklearn
  • xgboost
  • matplotlib
  • seaborn
  • MetaTrader 5
  • tqdm

Sie können sie mit „pip“ - dem Python-Paketinstallationsprogramm - installieren. Hier ist ein Beispielbefehl zur Installation aller erforderlichen Module:

pip install pandas numpy sklearn xgboost matplotlib seaborn tqdm MetaTrader5

Los geht's!


Klassifizierung oder Regression?

Dies ist eine der ewigen Fragen bei der Datenprognose. Die Klassifizierung eignet sich besser für binäre Probleme, bei denen eine klare Ja-Nein-Antwort erforderlich ist. Es gibt auch eine Mehrklassen-Klassifizierung. Wir werden dies in künftigen Artikeln der Reihe erörtern, da es die Modelle erheblich stärken kann.

Die Regression eignet sich für eine spezifische Vorhersage eines bestimmten zukünftigen Wertes einer kontinuierlichen Reihe, einschließlich einer Preisreihe. Auf der einen Seite kann dies sehr viel bequemer sein, aber auf der anderen Seite ist die Kennzeichnung von Daten für die Regression, genau wie die Kennzeichnung selbst, ein schwieriges Thema, da wir kaum etwas anderes tun können, als den zukünftigen Preis des Vermögenswertes zu nehmen. 

Mir persönlich gefällt die Klassifizierung besser, weil sie die Arbeit mit der Datenkennzeichnung vereinfacht. Viele Dinge können in Ja-Nein-Bedingungen getrieben werden, während die Multi-Klassen-Klassifizierung auf ganze komplexe manuelle Handelssysteme wie Smart Money angewendet werden kann. Sie haben den Code für die Datenbeschriftung bereits im vorigen Artikel dieser Reihe gesehen, und er ist eindeutig für die binäre Klassifizierung geeignet. Aus diesem Grund werden wir diese besondere Modellstruktur wählen.

Es bleibt die Entscheidung über das Modell selbst.


Auswahl eines Klassifikationsmodells

Wir müssen ein geeignetes Klassifizierungsmodell für unsere Daten mit den ausgewählten Merkmalen auswählen. Die Wahl hängt von der Anzahl der Merkmale, der Datentypen und der Anzahl der Klassen ab.

Beliebte Modelle sind die logistische Regression für die binäre Klassifizierung, der Zufallsforst für hohe Dimensionen und Nichtlinearitäten sowie neuronale Netze für komplexe Probleme. Die Auswahl ist riesig. Nachdem ich viele Dinge ausprobiert habe, bin ich zu dem Schluss gekommen, dass unter den heutigen Bedingungen das Boosten und darauf basierende Modelle am effektivsten sind. 

Ich habe mich für das hochmoderne XGBoost-Modell entschieden - Boosting über Entscheidungsbäume mit Regularisierung, Parallelität und vielen Einstellungen. XGBoost gewinnt aufgrund seiner hohen Genauigkeit häufig Wettbewerbe in der Datenwissenschaft. Dies wurde zum Hauptkriterium für die Wahl eines Modells. 


Generierung des Klassifikationsmodellcodes

Der Code verwendet das hochmoderne XGBoost-Modell - Gradient Boosting über Entscheidungsbäume. Eine Besonderheit von XGBoost ist die Verwendung von zweiten Ableitungen für die Optimierung, was die Effizienz und Genauigkeit im Vergleich zu anderen Modellen erhöht. 

Die Funktion train_xgboost_classifier erhält die Daten und die Anzahl der Boosting-Runden. Es teilt die Daten in X-Features und y-Labels auf, erstellt das XGBClassifier-Modell mit Hyperparameter-Tuning und trainiert es mit der fit()-Methode.

Die Daten werden in Training/Test aufgeteilt, das Modell wird mit Hilfe der Funktion auf den Trainingsdaten trainiert. Das Modell wird an den verbleibenden Daten getestet, und die Genauigkeit der Vorhersagen wird berechnet.

Die Hauptvorteile von XGBoost sind die Kombination mehrerer Modelle zu einem hochpräzisen Modell unter Verwendung von Gradient Boosting und die Optimierung für zweite Ableitungen zur Steigerung der Effizienz.

Außerdem müssen wir die OpenMP-Laufzeitbibliothek installieren, um sie zu verwenden. Für Windows müssen Sie die Microsoft Visual C++ Redistributable herunterladen, die zu Ihrer Python-Version passt.

Kommen wir nun zum Code selbst. Zu Beginn des Codes importieren wir die xgboost-Bibliothek auf folgende Weise:

import xgboost as xgb

Der Rest des Codes:

import xgboost as xgb

def train_xgboost_classifier(data, num_boost_rounds=500):
    # Check if data is not empty
    if data.empty:
        raise ValueError("Data should not be empty")
    
    # Check if all required columns are present in the data
    required_columns = ['label', 'labels']
    if not all(column in data.columns for column in required_columns):
        raise ValueError(f"Data is missing required columns: {required_columns}")
    
    # Remove the 'label' column as it is not a feature
    X = data.drop(['label', 'labels'], axis=1)
    y = data['labels']
    
    # Check if all features have numeric data type
    if not all(pd.api.types.is_numeric_dtype(X[column]) for column in X.columns):
        raise ValueError("All features should have numeric data type")
    
    # Create an XGBoostClassifier model
    clf = xgb.XGBClassifier(objective='binary:logistic', max_depth=10, learning_rate=0.3, n_estimators=num_boost_rounds, random_state=1)
    
    # Train the model on the data
    clf.fit(X, y)
    
    # Return the trained model
    return clf

labeled_data_engineered = feature_engineering(labeled_data_clustered, n_features_to_select=20)

# Get all data
raw_data = labeled_data_engineered

# Test the model on all data
train_data = raw_data[raw_data.index <= FORWARD]

# Test the model on all data
test_data = raw_data[raw_data.index >= FORWARD]

# Train the XGBoost model on the filtered data
xgb_clf = train_xgboost_classifier(train_data, num_boost_rounds=100)

# Test the model on all data
test_data = raw_data[raw_data.index >= FORWARD]
X_test = test_data.drop(['label', 'labels'], axis=1)
y_test = test_data['labels']
predicted_labels = xgb_clf.predict(X_test)

# Calculate prediction accuracy
accuracy = (predicted_labels == y_test).mean()
print(f"Prediction accuracy: {accuracy:.2f}")

Trainieren wir das Modell und sehen wir, dass die Genauigkeit bei 52 % liegt.

Unsere Klassifizierungsgenauigkeit liegt jetzt bei 53 % der gewinnbringenden Kennzeichnungen. Bitte beachten Sie, dass wir hier von Prognosesituationen sprechen, wenn der Kurs sich um mehr als den Take-Profit (200 Pips) verändert hat und den Stop (100 Pips) nicht mit dem Heck berührt hat. In der Praxis werden wir einen Gewinnfaktor von etwa drei haben, was für einen profitablen Handel völlig ausreichend ist. Der nächste Schritt ist das Schreiben eines nutzerdefinierten Testers in Python, um die Rentabilität der Modelle in USD (nicht in Punkten) zu analysieren. Es ist wichtig zu verstehen, ob das Modell unter Berücksichtigung des Aufschlags Geld einbringt oder ob es die Mittel aufzehrt.


Implementierung von der Funktion des nutzerdefinierten Tester in Python

def test_model(model, X_test, y_test, markup, initial_balance=10000.0, point_cost=0.00001):
    balance = initial_balance
    trades = 0
    profits = []

    # Test the model on the test data
    predicted_labels = model.predict(X_test)
    for i in range(len(predicted_labels) - 48):
        if predicted_labels[i] == 1:
            # Open a long position
            entry_price = X_test.iloc[i]['close']
            exit_price = X_test.iloc[i+48]['close']
            if exit_price > entry_price + markup:
                # Close the long position with profit
                profit = (exit_price - entry_price - markup) / point_cost
                balance += profit
                trades += 1
                profits.append(profit)
            else:
                # Close the long position with loss
                loss = (entry_price - exit_price + markup) / point_cost
                balance -= loss
                trades += 1
                profits.append(-loss)
        elif predicted_labels[i] == 0:
            # Open a short position
            entry_price = X_test.iloc[i]['close']
            exit_price = X_test.iloc[i+48]['close']
            if exit_price < entry_price - markup:
                # Close the short position with profit
                profit = (entry_price - exit_price - markup) / point_cost
                balance += profit
                trades += 1
                profits.append(profit)
            else:
                # Close the short position with loss
                loss = (exit_price - entry_price + markup) / point_cost
                balance -= loss
                trades += 1
                profits.append(-loss)

    # Calculate the cumulative profit or loss
    total_profit = balance - initial_balance

    # Plot the balance change over the number of trades
    plt.plot(range(trades), [balance + sum(profits[:i]) for i in range(trades)])
    plt.title('Balance Change')
    plt.xlabel('Trades')
    plt.ylabel('Balance ($)')
    plt.xticks(range(0, len(X_test), int(len(X_test)/10)), X_test.index[::int(len(X_test)/10)].strftime('%Y-%m-%d'))  # Add dates to the x-axis
    plt.axvline(FORWARD, color='r', linestyle='--')  # Add a vertical line for the FORWARD date
    plt.show()

    # Print the results
    print(f"Cumulative profit or loss: {total_profit:.2f} $")
    print(f"Number of trades: {trades}")

# Get test data
test_data = raw_data[raw_data.index >= FORWARD]
X_test = test_data.drop(['label', 'labels'], axis=1)
y_test = test_data['labels']

# Test the model with markup and target labels
initial_balance = 10000.0
markup = 0.00001
test_model(xgb_clf, X_test, y_test, markup, initial_balance)

Der Code erstellt eine Funktion zum Testen des maschinellen Lernmodells anhand von Testdaten und zur Analyse seiner Rentabilität unter Berücksichtigung des Aufschlags (dies sollte Verluste bei Spreads und verschiedene Arten von Provisionen einschließen). Swaps werden nicht berücksichtigt, da sie dynamisch sind und von den Leitzinsen abhängen. Sie können berücksichtigt werden, indem man einfach ein paar Pips zum Aufschlag hinzufügt.

Die Funktion empfängt ein Modell, Testdaten, einen Aufschlag und einen Anfangssaldo. Der Handel wird anhand der Modellvorhersagen simuliert: Kaufen bei 1, Verkaufen bei 0. Wenn der Gewinn den Aufschlag übersteigt, wird die Position geschlossen und der Gewinn dem Saldo hinzugefügt.

Handel und Gewinn/Verlust jeder Position werden gespeichert. Die Saldenkurve wird erstellt. Der kumulierte Gesamtgewinn/-verlust wird berechnet.

Am Ende erhalten wir Testdaten und entfernen überflüssige Spalten. Das trainierte Modell xgb_clf wird mit dem gegebenen Aufschlag und Anfangssaldo getestet. Testen wir es!


Der Tester arbeitet insgesamt erfolgreich, und wir sehen eine sehr schöne Saldenkurve. Dies ist ein nutzerdefinierter Tester zur Analyse des Gewinns eines Handelsmodells für maschinelles Lernen unter Berücksichtigung von Markup und Labels.


Implementierung der Kreuzvalidierung in das Modell

Um eine zuverlässigere Bewertung der Qualität eines maschinellen Lernmodells zu erhalten, müssen wir eine Kreuzvalidierung durchführen. Die Kreuzvalidierung ermöglicht die Bewertung eines Modells anhand mehrerer Datenuntergruppen, wodurch eine Überanpassung vermieden und eine objektivere Bewertung ermöglicht wird.

In unserem Fall verwenden wir eine 5-fache Kreuzvalidierung, um das XGBoost-Modell zu bewerten. Dazu verwenden wir die Funktion cross_val_score aus der Sklearn-Bibliothek.

Ändern wir den Code der Funktion train_xgboost_classifier wie folgt:

def train_xgboost_classifier(data, num_boost_rounds=500):
    # Check that data is not empty
    if data.empty:
        raise ValueError("Data should not be empty")

    # Check that all required columns are present in the data
    required_columns = ['label', 'labels']
    if not all(column in data.columns for column in required_columns):
        raise ValueError(f"Data is missing required columns: {required_columns}")

    # Drop the 'label' column since it is not a feature
    X = data.drop(['label', 'labels'], axis=1)
    y = data['labels']

    # Check that all features have numeric data type
    if not all(pd.api.types.is_numeric_dtype(X[column]) for column in X.columns):
        raise ValueError("All features should have numeric data type")

    # Create XGBoostClassifier model
    clf = xgb.XGBClassifier(objective='binary:logistic', max_depth=10, learning_rate=0.3, n_estimators=num_boost_rounds, random_state=1)

    # Train the model on the data using cross-validation
    scores = cross_val_score(clf, X, y, cv=5)

    # Calculate the mean accuracy of the predictions
    accuracy = scores.mean()

    print(f"Mean prediction accuracy on cross-validation: {accuracy:.2f}")

    # Train the model on the data without cross-validation
    clf.fit(X, y)

    # Return the trained model
    return clf

labeled_data_engineered = feature_engineering(labeled_data_clustered, n_features_to_select=20)

# Get all data
raw_data = labeled_data_engineered

# Train data
train_data = raw_data[raw_data.index <= FORWARD]

# Train the XGBoost model on the filtered data
xgb_clf = train_xgboost_classifier(train_data, num_boost_rounds=100)

# Test data
test_data = raw_data[raw_data.index >= FORWARD]
X_test = test_data.drop(['label', 'labels'], axis=1)
y_test = test_data['labels']
predicted_labels = xgb_clf.predict(X_test)

# Calculate the accuracy of the predictions
accuracy = (predicted_labels == y_test).mean()
print(f"Accuracy: {accuracy:.2f}")

Beim Training des Modells führt die Funktion train_xgboost_classifier eine 5-fache Kreuzvalidierung durch und gibt die durchschnittliche Vorhersagegenauigkeit aus. Die Schulung umfasst weiterhin die Probe bis zum FORWARD-Datum.

Die Kreuzvalidierung wird nur zur Bewertung des Modells verwendet, nicht zum Training. Das Training wird mit allen Daten bis zum FORWARD-Datum ohne Kreuzvalidierung durchgeführt.

Die Kreuzvalidierung ermöglicht eine zuverlässigere und objektivere Bewertung der Modellqualität, was theoretisch die Robustheit des Modells gegenüber neuen Preisdaten erhöhen wird. Oder nicht? Schauen wir uns an, wie der Tester funktioniert.


Das Testen von XGBoost mit Kreuzvalidierung auf Daten von 1990-2024 ergab eine Genauigkeit von 56 % für den Test nach 2010. Das Modell erwies sich beim ersten Versuch als sehr robust gegenüber neuen Daten. Auch die Genauigkeit hat sich deutlich verbessert, was eine gute Nachricht ist.


Optimierung von Modellhyperparametern auf einem Raster

Die Optimierung der Hyperparameter ist ein wichtiger Schritt bei der Erstellung eines maschinellen Lernmodells, um dessen Genauigkeit und Leistung zu maximieren. Es ist ähnlich wie bei der Optimierung von MQL5 EAs, man muss sich nur vorstellen, dass es anstelle eines EAs ein maschinelles Lernmodell gibt. Mit der Rastersuche finden wir die Parameter, die am besten funktionieren.

Schauen wir uns die rasterbasierte XGBoost-Hyperparameteroptimierung mit Scikit-learn an.

Wir werden GridSearchCV aus Scikit-learn verwenden, um das Modell über alle Hyperparametersätze des Rasters hinweg kreuzvalidieren zu können. Der Satz mit der höchsten durchschnittlichen Genauigkeit bei der Kreuzvalidierung wird ausgewählt.

Optimierungscode:

from sklearn.model_selection import GridSearchCV

# Define the grid of hyperparameters
param_grid = {
    'max_depth': [3, 5, 7, 10],
    'learning_rate': [0.1, 0.3, 0.5],
    'n_estimators': [100, 500, 1000]
}

# Create XGBoost model
clf = xgb.XGBClassifier(objective='binary:logistic', random_state=1)

# Perform grid search to find the best hyperparameters
grid_search = GridSearchCV(clf, param_grid, cv=5, scoring='accuracy')
grid_search.fit(X_train, y_train)

# Print the best hyperparameters
print("Best hyperparameters:", grid_search.best_params_)

# Print the mean accuracy of the predictions on cross-validation for the best hyperparameters
print("Mean prediction accuracy on cross-validation:", grid_search.best_score_)

Hier definieren wir ein Raster von Hyperparametern param_grid, erstellen das XGBoost clf-Modell und suchen mit der Methode GridSearchCV nach optimalen Hyperparametern über dem Raster. Anschließend werden die besten Hyperparameter grid_search.best_params_ und die durchschnittliche Vorhersagegenauigkeit der Kreuzvalidierung grid_search.best_score_ ausgegeben.

Beachten Sie, dass wir in diesem Code die Kreuzvalidierung zur Optimierung der Hyperparameter verwenden. Dies ermöglicht uns eine zuverlässigere und objektivere Bewertung der Modellqualität.

Nachdem wir diesen Code ausgeführt haben, erhalten wir die besten Hyperparameter für unser XGBoost-Modell und die durchschnittliche Vorhersagegenauigkeit bei der Kreuzvalidierung. Anschließend können wir das Modell mit den besten Hyperparametern auf allen Daten trainieren und es auf neuen Daten testen.

Daher ist die Optimierung der Modellhyperparameter über ein Raster eine wichtige Aufgabe bei der Erstellung von Modellen für maschinelles Lernen. Mit der GridSearchCV-Methode aus der Scikit-Learn-Bibliothek können wir diesen Prozess automatisieren und die besten Hyperparameter für ein gegebenes Modell und die Daten finden.

def train_xgboost_classifier(data, num_boost_rounds=1000):
    # Check that data is not empty
    if data.empty:
        raise ValueError("Data should not be empty")

    # Check that all required columns are present in the data
    required_columns = ['label', 'labels']
    if not all(column in data.columns for column in required_columns):
        raise ValueError(f"Data is missing required columns: {required_columns}")

    # Drop the 'label' column since it is not a feature
    X = data.drop(['label', 'labels'], axis=1)
    y = data['labels']

    # Check that all features have numeric data type
    if not all(pd.api.types.is_numeric_dtype(X[column]) for column in X.columns):
        raise ValueError("All features should have numeric data type")

    # Create XGBoostClassifier model
    clf = xgb.XGBClassifier(objective='binary:logistic', random_state=1)

    # Define hyperparameters for grid search
    param_grid = {
        'max_depth': [3, 5, 7, 10],
        'learning_rate': [0.05, 0.1, 0.2, 0.3, 0.5],
        'n_estimators': [50, 100, 600, 1200, 2000]
    }

    # Train the model on the data using cross-validation and grid search
    grid_search = GridSearchCV(clf, param_grid, cv=5, scoring='accuracy')
    grid_search.fit(X, y)

    # Calculate the mean accuracy of the predictions
    accuracy = grid_search.best_score_

    print(f"Mean prediction accuracy on cross-validation: {accuracy:.2f}")

    # Return the trained model with the best hyperparameters
    return grid_search.best_estimator_


Model ensembling

Es ist an der Zeit, unser Modell noch cooler und besser zu machen! Modell-Ensembling ist ein leistungsfähiger Ansatz beim maschinellen Lernen, der mehrere Modelle kombiniert, um die Vorhersagegenauigkeit zu verbessern. Beliebte Methoden sind Bagging (Erstellung von Modellen auf der Grundlage verschiedener Teilstichproben von Daten) und Boosting (sequentielles Training von Modellen, um die Fehler der vorherigen Modelle zu korrigieren).

In unserer Aufgabe verwenden wir das XGBoost-Ensemble mit Bagging und Boosting. Wir erstellen mehrere XGBoosts, die auf verschiedenen Teilstichproben trainiert wurden, und kombinieren ihre Vorhersagen. Außerdem optimieren wir die Hyperparameter der einzelnen Modelle mit GridSearchCV.

Vorteile des Ensembling: höhere Genauigkeit, geringere Varianz, verbesserte Gesamtmodellqualität.

Die endgültige Modell-Trainingsfunktion verwendet Kreuzvalidierung, Ensembling und Grid-Bagging-Hyperparameterauswahl.

def train_xgboost_classifier(data, num_boost_rounds=1000):
    # Check that data is not empty
    if data.empty:
        raise ValueError("Data should not be empty")

    # Check that all required columns are present in the data
    required_columns = ['label', 'labels']
    if not all(column in data.columns for column in required_columns):
        raise ValueError(f"Missing required columns in data: {required_columns}")

    # Remove the 'label' column as it is not a feature
    X = data.drop(['label', 'labels'], axis=1)
    y = data['labels']

    # Check that all features have numeric data type
    if not all(pd.api.types.is_numeric_dtype(X[column]) for column in X.columns):
        raise ValueError("All features should have numeric data type")

    # Create XGBoostClassifier model
    clf = xgb.XGBClassifier(objective='binary:logistic', random_state=1)

    # Define hyperparameters for grid search
    param_grid = {
        'max_depth': [3, 7, 12],
        'learning_rate': [0.1, 0.3, 0.5],
        'n_estimators': [100, 600, 1200]
    }

    # Train the model on the data using cross-validation and hyperparameter tuning
    grid_search = GridSearchCV(clf, param_grid, cv=5, scoring='accuracy')
    grid_search.fit(X, y)

    # Calculate the mean accuracy of the predictions
    accuracy = grid_search.best_score_

    print(f"Mean accuracy on cross-validation: {accuracy:.2f}")

    # Return the trained model
    return grid_search.best_estimator_

labeled_data_engineered = feature_engineering(labeled_data_clustered, n_features_to_select=20)

# Get all data
raw_data = labeled_data_engineered

# Train data
train_data = raw_data[raw_data.index <= FORWARD]

# Test data
test_data = raw_data[raw_data.index <= EXAMWARD]

# Train the XGBoost model on the filtered data
xgb_clf = train_xgboost_classifier(train_data, num_boost_rounds=100)

# Test the model on all data
test_data = raw_data[raw_data.index >= FORWARD]
X_test = test_data.drop(['label', 'labels'], axis=1)
y_test = test_data['labels']
predicted_labels = xgb_clf.predict(X_test)

# Calculate the accuracy of the predictions
accuracy = (predicted_labels == y_test).mean()
print(f"Prediction accuracy: {accuracy:.2f}")

Wir implementieren das Modell-Ensemble durch Bagging, führen den Test durch und erhalten das folgende Testergebnis:


Die Genauigkeit bei der Klassifizierung von Geschäften mit einem Risiko-Ertrags-Verhältnis von 1:8 stieg auf 73 %. Mit anderen Worten: Ensembling und Rastersuche haben die Klassifizierungsgenauigkeit im Vergleich zur vorherigen Version des Codes enorm verbessert. Ich halte dies für ein mehr als ausgezeichnetes Ergebnis, und aus den vorangegangenen Charts zur Leistung des Modells im vorderen Teil kann man deutlich erkennen, wie sehr es sich im Laufe der Codeentwicklung verbessert hat.   

 

Umsetzung der Untersuchungsstichprobe und Prüfung der Robustheit des Modells

Jetzt verwende ich für den Test Daten nach dem EXAMWARD-Datum. Auf diese Weise kann ich die Leistung des Modells mit völlig neuen Daten testen, die nicht zum Trainieren und Testen des Modells verwendet wurden. Auf diese Weise kann ich objektiv beurteilen, wie sich das Modell unter realen Bedingungen verhält.

Ein wichtiger Schritt bei der Validierung eines Modells für maschinelles Lernen ist das Testen an einer Prüfungsprobe. Dadurch wird sichergestellt, dass das Modell auch bei neuen Daten gut funktioniert und einen Eindruck von seiner Leistung in der Praxis vermittelt. Hier müssen wir den Stichprobenumfang richtig bestimmen und sicherstellen, dass er repräsentativ ist.

In meinem Fall verwende ich Post-EXAMWARD-Daten, um das Modell an völlig unbekannten Daten außerhalb von Train und Test zu testen. Auf diese Weise erhalte ich eine objektive Bewertung der Effizienz des Modells und der Bereitschaft für den tatsächlichen Einsatz.

Ich habe das Training mit Daten aus den Jahren 2000-2010 durchgeführt, den Test mit Daten aus den Jahren 2010-2019, die Prüfung mit Daten aus 2019. Die Prüfung simuliert den Handel in einer unbekannten Zukunft.


Insgesamt sieht alles gut aus. Die Genauigkeit bei der Prüfung ist auf 60 % gesunken, aber das Wichtigste ist, dass das Modell rentabel und recht robust ist und keine starken Drawdowns aufweist. Erfreulich ist, dass das Modell das Konzept von Risiko und Gewinn erlernt - es sagt Situationen mit geringem Risiko und hohem Gewinnpotenzial voraus (wir verwenden ein Verhältnis von 1:8).


Schlussfolgerung

Dies ist der zweite Artikel in der Serie über die Erstellung eines Handelsroboters in Python. Derzeit ist es uns gelungen, die Probleme der Arbeit mit Daten, der Arbeit mit Merkmalen, der Auswahl und sogar der Erzeugung von Merkmalen sowie das Problem der Auswahl und des Trainings eines Modells zu lösen. Wir haben auch einen nutzerdefinierten Tester implementiert, der das Modell testet, und es scheint, dass alles ziemlich gut funktioniert. Übrigens habe ich auch andere Funktionen ausprobiert, einschließlich der einfachsten, und versucht, die Daten zu vereinfachen - ohne Erfolg. Modelle mit diesen Merkmalen leeren das Konto im Tester. Dies bestätigt einmal mehr, dass Merkmale und Daten nicht weniger wichtig sind als das Modell selbst. Wir können ein gutes Modell erstellen und verschiedene Verbesserungen und Methoden anwenden, aber wenn die Merkmale unbrauchbar sind, dann wird es auch schamlos unsere Kaution für unbekannte Daten aufbrauchen. Im Gegenteil, mit einer guten Ausstattung können Sie selbst mit einem mittelmäßigen Modell ein stabiles Ergebnis erzielen. 


Weitere Entwicklungen

Für die Zukunft plane ich, eine eigene Version des Online-Handels im MetaTrader 5-Terminal zu erstellen, um direkt über Python zu handeln und den Komfort zu erhöhen. Schließlich war mein ursprünglicher Anreiz, eine Version speziell für Python zu erstellen, die Probleme bei der Übertragung von Funktionen auf MQL5. Es ist immer noch viel schneller und bequemer für mich, Merkmale, ihre Auswahl, Datenbeschriftung und Datenerweiterung in Python zu handhaben.

Ich glaube, dass die MQL5-Bibliothek für Python zu Unrecht unterschätzt wird. Es ist klar, dass nur wenige Menschen sie nutzen. Es ist eine leistungsstarke Lösung, mit der man wirklich schöne Modelle erstellen kann, die sowohl das Auge als auch den Geldbeutel erfreuen!

Ich würde auch gerne eine Version implementieren, die aus den historischen Daten der Markttiefe einer echten Börse - CME oder MOEX - lernt. Auch dies ist ein vielversprechendes Unterfangen.

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

Beigefügte Dateien |
Entwicklung eines Wiedergabesystems (Teil 47): Chart Trade Projekt (VI) Entwicklung eines Wiedergabesystems (Teil 47): Chart Trade Projekt (VI)
Schließlich beginnt unser Indikator Chart Trade mit dem EA zu interagieren, sodass die Informationen interaktiv übertragen werden können. Daher werden wir in diesem Artikel den Indikator verbessern, sodass er funktional genug ist, um zusammen mit jedem EA verwendet zu werden. Dadurch können wir auf den Indikator Chart Trade zugreifen und mit ihm arbeiten, als ob er tatsächlich mit einem EA verbunden wäre. Aber wir werden es auf eine viel interessantere Weise tun als bisher.
Klassische Strategien neu interpretieren (Teil VIII): Währungsmärkte und Edelmetalle zum USDCAD Klassische Strategien neu interpretieren (Teil VIII): Währungsmärkte und Edelmetalle zum USDCAD
In dieser Artikelserie nehmen wir bekannte Handelsstrategien unter die Lupe, um zu sehen, ob wir sie mithilfe von KI verbessern können. Testen Sie mit uns in der heutigen Diskussion, ob es eine zuverlässige Beziehung zwischen Edelmetallen und Währungen gibt.
Entwicklung eines Replay Systems (Teil 48): Das Konzept eines Dienstes verstehen Entwicklung eines Replay Systems (Teil 48): Das Konzept eines Dienstes verstehen
Wie wäre es, etwas Neues zu lernen? In diesem Artikel erfahren Sie, wie Sie Skripte in Dienste umwandeln können und warum dies sinnvoll ist.
MQL5-Assistenten-Techniken, die Sie kennen sollten (Teil 36): Q-Learning mit Markov-Ketten MQL5-Assistenten-Techniken, die Sie kennen sollten (Teil 36): Q-Learning mit Markov-Ketten
Reinforcement Learning ist neben dem überwachten und dem unüberwachten Lernen eine der drei Hauptrichtungen des maschinellen Lernens. Es geht also um die optimale Steuerung oder das Erlernen der besten langfristigen Strategie, die der Zielfunktion am besten entspricht. Vor diesem Hintergrund untersuchen wir die mögliche Rolle, die ein MLP für den Lernprozess eines von einem Assistenten zusammengestellten Expertenberaters spielt.