English 日本語
preview
Integration des AI-Modells in eine bereits bestehende MQL5-Handelsstrategie

Integration des AI-Modells in eine bereits bestehende MQL5-Handelsstrategie

MetaTrader 5Handel |
118 1
Hlomohang John Borotho
Hlomohang John Borotho

Einführung

In diesem Artikel werden wir das AI-Modell in eine bereits bestehende MQL5-Handelsstrategie integrieren. Wir werden Order Block in Verbindung mit Fibonacci aus dem vorherigen Artikel verwenden. Viele bestehende MQL5-Handelsstrategien beruhen auf festen Indikatoren, starren Schwellenwerten oder vordefinierten Mustern, die möglicherweise nicht über verschiedene Marktzyklen hinweg effektiv sind. Diesen Strategien fehlt die Fähigkeit, aus vergangenen Daten zu lernen, komplexe Muster zu erkennen oder ihre Entscheidungen dynamisch an veränderte Bedingungen anzupassen.

Die Integration eines KI-Modells in eine MQL5-Handelsstrategie kann dazu beitragen, bestehende Herausforderungen zu überwinden, indem maschinenlernbasierte Anpassungs- und Entscheidungsfindungsfähigkeiten integriert werden. Mithilfe von Techniken wie Long Short Term Memory (LSTM) oder prädiktiver Analytik kann KI umfangreiche historische und Echtzeit-Datensätze analysieren, um intelligentere Handelsaktionen zu entwickeln. Im Gegensatz zu starren, vordefinierten Strategien passen sich KI-gestützte Systeme dynamisch an und verfeinern ihre Ansätze, indem sie aus den sich verändernden Marktbedingungen lernen. Dies führt zu einem schärferen Timing für den Handel, einer effektiveren Risikominderung und einer höheren Rentabilität im Laufe der Zeit.


Erste Schritte

Der erste Schritt besteht darin, den vorhandenen MQL5-Code in Python zu konvertieren. Da wir künstliche Intelligenz in die Handelsstrategie integrieren, ist eine Python-basierte Version der ursprünglichen MQL5-Logik unerlässlich. Diese Umstellung stellt sicher, dass wir nahtlos KI-gesteuerte Erweiterungen einbauen können, ohne die Kernfunktionalität der Strategie zu beeinträchtigen. Die Python-Version des Codes sollte das Verhalten des MQL5-Skripts genau nachbilden, einschließlich der Handelsausführungslogik, der Indikatorberechnungen, der Auftragsverwaltung und aller Risikomanagementregeln. Dadurch wird gewährleistet, dass das KI-Modell mit einem System interagiert, das sich identisch zu dem auf dem MetaTrader 5 ausgeführten System verhält, was eine genaue Prüfung und Optimierung vor der vollständigen Integration ermöglicht. Sobald dieser Schritt abgeschlossen ist, können wir mit der Einbettung von Machine-Learning-Modellen fortfahren, die KI auf Marktdaten trainieren und schließlich ein intelligentes, adaptives Handelssystem schaffen, das die Entscheidungsfindung und die Leistung verbessert.

MQL5-Code:

#include <Trade/Trade.mqh>
#include <Arrays\ArrayObj.mqh>
CTrade trade;

#define BullOB clrLime
#define BearOB clrRed

//+------------------------------------------------------------------+
//|                           Global vars                            |
//+------------------------------------------------------------------+
double Lots = 0.01;
int takeProfit = 170;
int length = 100;
input double stopLoss = 350;
input double Mgtn = 0.85;

bool isBullishOB = false; 
bool isBearishOB = false;

input int Time1Hstrt = 3;
input int Time1Hend = 4;

class COrderBlock : public CObject {
public:
   int direction;
   datetime time;
   double high;
   double low;
   bool traded;

   string rectName;  
   string tradeRectName; 

   COrderBlock(int dir, datetime t, double h, double l) {
      direction = dir;
      time = t;
      high = h;
      low = l;
      traded = false;
      rectName = "";
      tradeRectName = "";
      
   }

   void draw(datetime tmS, datetime tmE, color clr) {
      rectName = "OB REC" + TimeToString(time);
      ObjectCreate(0, rectName, OBJ_RECTANGLE, 0, time, low, tmS, high);
      ObjectSetInteger(0, rectName, OBJPROP_FILL, true);
      ObjectSetInteger(0, rectName, OBJPROP_COLOR, clr);

      tradeRectName = "OB trade" + TimeToString(time);
      ObjectCreate(0, tradeRectName, OBJ_RECTANGLE, 0, tmS, high, tmE, low);
      ObjectSetInteger(0, tradeRectName, OBJPROP_FILL, true);
      ObjectSetInteger(0, tradeRectName, OBJPROP_COLOR, clr);
   }
   
   void removeDrawings() {
      if (ObjectFind(0, rectName) != -1) {
         ObjectDelete(0, rectName); // Delete the main rectangle
      }
      if (ObjectFind(0, tradeRectName) != -1) {
         ObjectDelete(0, tradeRectName); // Delete the trade rectangle
      }
   }
};
// Pointer to CArrayObj

// Declare the dynamic array to hold order blocks
CArrayObj *orderBlocks; 
color OBClr;
datetime T1;
datetime T2;

int OnInit() {
   orderBlocks = new CArrayObj(); // Allocate memory for the array
   return(INIT_SUCCEEDED);
}

void OnDeinit(const int reason) {
   ObjectsDeleteAll(0, "OB");
   
   // Clear and free the order blocks
   if (orderBlocks != NULL) {
      orderBlocks.Clear(); // This will delete objects inside
      delete orderBlocks; // Free the array memory
      orderBlocks = NULL;
   }
}

void OnTick() {
   if (isNewBar()) {
      static int prevDay = 0;
      
      MqlDateTime structTime;
      TimeCurrent(structTime);
      structTime.min = 0;
      structTime.sec = 0;
      
      structTime.hour = Time1Hstrt;
      datetime timestrt = StructToTime(structTime);
      
      structTime.hour = Time1Hend;
      datetime timend = StructToTime(structTime);
      
      getOrderB();
      double Bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
      double Ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);

      for (int i = orderBlocks.Total() - 1; i >= 0; i--) {
         COrderBlock *OB = (COrderBlock *)orderBlocks.At(i);

         if (CheckPointer(OB) != POINTER_INVALID && !OB.traded) {
         
            if(OB.direction > 0 && Ask < OB.high){
               double entry = Ask;
               double tp = getHigh(iHighest(_Symbol, PERIOD_CURRENT, MODE_HIGH, iBarShift(_Symbol, PERIOD_CURRENT, OB.time)));
               double sl = NormalizeDouble(OB.low - Mgtn, _Digits);
   
               T2 = getTime(0);
               OB.draw(T1, T2, BullOB);
               trade.Buy(Lots, _Symbol, entry, sl, tp, "OB buy");
               OB.traded = true;
               //OB.removeDrawings();
               orderBlocks.Delete(i); // Delete from array
               delete OB; // Free memory
               
               
            }
         }
         if(CheckPointer(OB) != POINTER_INVALID && !OB.traded){
            if (OB.direction < 0 && Bid > OB.low) {
                  double entry = Bid;
                  double tp = getLow(iLowest(_Symbol, PERIOD_CURRENT, MODE_LOW, iBarShift(_Symbol, PERIOD_CURRENT, OB.time)));
                  double sl = NormalizeDouble(OB.high + Mgtn, _Digits);
      
                  T2 = getTime(0);
                  OB.draw(T1, T2, BearOB);
                  trade.Sell(Lots, _Symbol, entry, sl, tp, "OB sell");
                  OB.traded = true;
                  //OB.removeDrawings();
                  orderBlocks.Delete(i); // Delete from array
                  delete OB; // Free memory
                  

            }
         }
      }
   }
}

void getOrderB(){

   static int prevDay = 0;
   
   MqlDateTime structTime;
   TimeCurrent(structTime);
   structTime.min = 0;
   structTime.sec = 0;
   
   structTime.hour = Time1Hstrt;
   datetime timestrt = StructToTime(structTime);
   
   structTime.hour = Time1Hend;
   datetime timend = StructToTime(structTime);
   
   int visibleBars = (int)ChartGetInteger(0,CHART_VISIBLE_BARS);
         
   for(int i = 1; i <= visibleBars; i++){
      if(getOpen(i) < getClose(i)){ // index is i since the loop starts from i which is = 1 "for(int i = 1)..."
         if(getOpen(i + 2) < getClose(i + 2)){
            if(getOpen(i + 3) > getClose(i + 3) && getOpen(i + 3) < getClose(i + 2)){
               Print("Bullish Order Block confirmed at: ", TimeToString(getTime(i + 2), TIME_DATE||TIME_MINUTES));
               //isBullishOB = true;
               //OB = new COrderBlock();
               int direction = 1;
               datetime time = getTime(i + 3);
               double high = getHigh(i + 3);
               double low = getLow(i + 3);
               isBullishOB = true;
               
               OBClr = isBullishOB ? BullOB : BearOB;
               
               // specify strt time
               T1 = time;
               // reset BULLOB flag
               isBullishOB = false;
               // crucial
               COrderBlock *newOB = new COrderBlock(direction, time, high, low);
               orderBlocks.Add(newOB);
               break;
               
               //delete newOB;
            }
         }
      }
      if(getOpen(i) > getClose(i)){
         if(getOpen(i + 2) > getClose(i + 2)){
            if(getOpen(i + 3) < getClose(i + 3) && getOpen(i + 3) < getClose(i + 2)){
               Print("Bearish Order Block confirmed at: ", TimeToString(getTime(i + 2), TIME_DATE||TIME_MINUTES));
               //isBearishOB = true;
               //OB = new COrderBlock();
               int direction = -1;
               datetime time = getTime(i + 3);
               double high = getHigh(i + 3);
               double low = getLow(i + 3);
               isBearishOB = true;
               
               OBClr = isBearishOB ? BearOB : BullOB;
               
               T1 = time;
               
               // reset the BEAROB flag
               isBearishOB = false;
               // crusssial
               COrderBlock *newOB = new COrderBlock(direction, time, high, low);
               orderBlocks.Add(newOB);
               break;
               
               //delete newOB;
            }
         }
      }
    }
      
}

double getHigh(int index) {
    return iHigh(_Symbol, _Period, index);
}

double getLow(int index) {
    return iLow(_Symbol, _Period, index);
}

double getOpen(int index){
   return iOpen(_Symbol, _Period, index);
}

double getClose(int index){
   return iClose(_Symbol, _Period, index);
}

datetime getTime(int index) {
    return iTime(_Symbol, _Period, index);
}

bool isNewBar() {
   // Memorize the time of opening of the last bar in the static variable
   static datetime last_time = 0;
   
   // Get current time
   datetime lastbar_time = (datetime)SeriesInfoInteger(Symbol(), Period(), SERIES_LASTBAR_DATE);

   // First call
   if (last_time == 0) {
      last_time = lastbar_time;
      return false;
   }

   // If the time differs (new bar)
   if (last_time != lastbar_time) {
      last_time = lastbar_time;
      return true;
   }

   // If no new bar, return false
   return false;
}

void deler(){
   static int prevDay = 0;
   
   MqlDateTime structTime;
   TimeCurrent(structTime);
   structTime.min = 0;
   structTime.sec = 0;
   
   structTime.hour = Time1Hstrt;
   datetime timestrt = StructToTime(structTime);
   
   structTime.hour = Time1Hend;
   datetime timend = StructToTime(structTime);

}

In unserem vorherigen Artikel haben wir die Kernfunktionalität und das Design dieses Codes besprochen. Er implementiert eine algorithmische Handelsstrategie, die sich auf die Identifizierung und den Handel mit „Orderblöcken“ konzentriert - spezifische Kerzenmuster, von denen angenommen wird, dass sie potenzielle Marktumkehrungen signalisieren. Als Expert Advisor (EA) kombiniert er die Analyse von Preisbewegungen mit automatischer Handelsausführung. Der Code nutzt die objektorientierte Programmierung durch die Klasse „OrderBlock“, um wichtige Musterdaten (Zeitstempel, Preisgrenzen, Richtung) zu speichern und visuelle Chart-Anmerkungen zu verwalten. Ein dynamisches Array „CArrayObj“ verfolgt aktive Auftragsblöcke und sorgt für eine effiziente Speicherverwaltung und Echtzeitüberwachung von Mustern über mehrere Chart-Instanzen hinweg.

Die Funktion „getOrderB()“ dient der Mustererkennung, indem sie historische Kerzen auf bestimmte Auf- und Abwärts-Sequenzen untersucht. Aufwärts-Orderblöcke werden erkannt, wenn drei aufeinanderfolgende Aufwärts-Kerzen einer Abwärts-Kerze folgen, während Abwärts-Muster drei Abwärts-Kerzen nach einer Aufwärts-Kerze erfordern. Erkannte Muster werden als „COrderBlock“-Objekte mit Richtungsflags (1 für aufwärts, -1 für abwärts) instanziiert und im Array gespeichert. Der Code enthält vom Nutzer konfigurierbare Zeitfilter („Time1Hstrt“, „Time1Hend“), um sich auf bestimmte Handelssitzungen zu konzentrieren und die Relevanz der Muster zu erhöhen.

Bei jedem neuen Balken (erkannt über „isNewBar()“) verarbeitet der EA aktive Orderblöcke in der Funktion „OnTick()“. Bei Aufwärtsmustern geht er Kaufpositionen ein, wenn der Kurs über das Hoch des Orderblocks ausbricht, und setzt den Stop-Loss unter das Tief des Musters abzüglich einer Marge („Mtgn“). Abwärtsgerichtete Handelsgeschäfte werden bei Durchbrüchen unter die Tiefststände des Musters mit Stopps über den Höchstständen des Musters ausgelöst. Der EA verwendet „CTrade“ für die Auftragsverwaltung und berechnet Take-Profit-Levels auf der Grundlage der jüngsten Höchst- und Tiefststände. Ausgeführte Handelsgeschäfte entfernen automatisch ihre zugehörigen Orderblöcke und Chartzeichnungen, um doppelte Signale zu vermeiden.

Das System verfügt über mehrere Sicherheitsvorkehrungen: Die Stop-Loss-Abstände werden an die Anforderungen der Dezimalstellen des Brokers angepasst, die Positionsgröße bleibt auf „Lots“ festgelegt und visuelle Indikatoren (farbige Rechtecke) sorgen für Transparenz bei der Strategievalidierung. Die Nutzer können wichtige Parameter wie den Stop-Loss-Abstand (StopLoss), die Gewinnspanne (Mtgn) und das Timing der Sitzung über Eingabevariablen anpassen. Der Code sorgt für ein Gleichgewicht zwischen Automatisierung und diskretionären Elementen - während die Mustererkennung algorithmisch erfolgt, werden bei der Handelsausführung maklerspezifische Beschränkungen wie Mindeststoppabstände und Spread-Überlegungen berücksichtigt.

Python-Version:

Bevor wir loslegen, benötigen wir wie immer historische Marktdaten. Diese Daten dienen als Grundlage für das Training unseres KI-Modells und die Validierung der Genauigkeit unserer Strategie. Ich gehe davon aus, dass Sie inzwischen mit der Beschaffung von historischen Daten vertraut sind. Wenn Sie jedoch unsicher sind oder eine Auffrischung benötigen, lesen Sie bitte den ersten Teil meines Leitfadens zur Integration von MQL5 mit Datenverarbeitungspaketen. Im Folgenden laden wir einfach die historischen Daten.

import pandas as pd

# Load historical data
file_path = '/home/int_junkie/Documents/DataVisuals/AI inside MQL5/XAUUSD_H1.csv'
data = pd.read_csv(file_path)

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

Bei der Strukturierung der Python-Version des Codes stellen wir sicher, dass er für die effektive Verarbeitung historischer Marktdaten ausgelegt ist, die als Grundlage für das Training unseres KI-Modells dienen. Der erste Schritt besteht darin, eine Datenpipeline zu erstellen, die es dem Skript ermöglicht, historische Kursdaten aufzunehmen, vorzuverarbeiten und zu organisieren, einschließlich wichtiger Merkmale wie Eröffnungs-, Höchst-, Tiefst- und Schlusskurse, Volumen und relevante technische Indikatoren. Dieses strukturierte Format ermöglicht es dem KI-Modell, aussagekräftige Muster aus dem vergangenen Marktverhalten zu lernen.

Zusätzlich integrieren wir Funktionen zum Trainieren eines LSTM-Modells (Long Short-Term Memory), einer speziellen Art von rekurrenten neuronalen Netzen (RNN), die für ihre Fähigkeit bekannt sind, sequentielle Daten zu analysieren und langfristige Abhängigkeiten zu erfassen. Der Trainingsprozess ist auf die bestehende Kauf- und Verkaufslogik der ursprünglichen MQL5-Strategie abgestimmt, um sicherzustellen, dass das Modell lernt, Handelsentscheidungen auf der Grundlage historischer Kursbewegungen zu treffen. Durch die Zuordnung vergangener Daten zu den entsprechenden Kauf- und Verkaufssignalen verfeinert das LSTM-Modell schrittweise seine Vorhersagefähigkeiten, sodass es potenzielle Marktbewegungen besser vorhersagen kann. Dieser strukturierte Ansatz ermöglicht es uns, die Lücke zwischen dem traditionellen regelbasierten Handel und der KI-gestützten Entscheidungsfindung zu schließen und damit letztlich die Anpassungsfähigkeit und Genauigkeit des Handelssystems zu verbessern.

import pandas as pd
import numpy as np
from datetime import datetime
from keras.models import Sequential
from keras.layers import LSTM, Dense
import tensorflow as tf

# Constants
LOTS = 0.01
TAKE_PROFIT = 170
STOP_LOSS = 350
MGTN = 0.85
TIME1_HSTRT = 3
TIME1_HEND = 4

# Helper functions
def get_high(data, index):
    return data.iloc[index]['<HIGH>']

def get_low(data, index):
    return data.iloc[index]['<LOW>']

def get_open(data, index):
    return data.iloc[index]['<OPEN>']

def get_close(data, index):
    return data.iloc[index]['<CLOSE>']

def get_time(data, index):
    return data.iloc[index]['DATETIME']  # Combined datetime column

def is_new_bar(current_time, last_time):
    return current_time != last_time

class OrderBlock:
    def __init__(self, direction, time, high, low):
        self.direction = direction
        self.time = time
        self.high = high
        self.low = low
        self.traded = False

def get_order_blocks(data):
    order_blocks = []
    visible_bars = len(data)

    for i in range(1, visible_bars - 3):  # Adjusted to avoid index errors
        if get_open(data, i) < get_close(data, i):  # Bullish condition
            if get_open(data, i + 2) < get_close(data, i + 2):
                if get_open(data, i + 3) > get_close(data, i + 3) and get_open(data, i + 3) < get_close(data, i + 2):
                    print(f"Bullish Order Block confirmed at: {get_time(data, i + 2)}")
                    direction = 1
                    time = get_time(data, i + 3)
                    high = get_high(data, i + 3)
                    low = get_low(data, i + 3)
                    order_blocks.append(OrderBlock(direction, time, high, low))
                    break

        if get_open(data, i) > get_close(data, i):  # Bearish condition
            if get_open(data, i + 2) > get_close(data, i + 2):
                if get_open(data, i + 3) < get_close(data, i + 3) and get_open(data, i + 3) < get_close(data, i + 2):
                    print(f"Bearish Order Block confirmed at: {get_time(data, i + 2)}")
                    direction = -1
                    time = get_time(data, i + 3)
                    high = get_high(data, i + 3)
                    low = get_low(data, i + 3)
                    order_blocks.append(OrderBlock(direction, time, high, low))
                    break

    return order_blocks

def simulate_trading(data, order_blocks):
    trades = []
    last_time = None

    for i, row in data.iterrows():
        current_time = row['DATETIME']
        if is_new_bar(current_time, last_time):
            last_time = current_time

            bid = row['<CLOSE>']  # Assuming bid price is close price
            ask = row['<CLOSE>']  # Assuming ask price is close price

            for ob in order_blocks:
                if not ob.traded:
                    if ob.direction > 0 and ask < ob.high:  # Buy condition
                        entry = ask
                        tp = data.iloc[:i]['<HIGH>'].max()  # Take profit as highest high
                        sl = ob.low - MGTN  # Stop loss
                        trades.append({
                            'time': current_time,
                            'direction': 'buy',
                            'entry': entry,
                            'tp': tp,
                            'sl': sl
                        })
                        ob.traded = True

                    if ob.direction < 0 and bid > ob.low:  # Sell condition
                        entry = bid
                        tp = data.iloc[:i]['<LOW>'].min()  # Take profit as lowest low
                        sl = ob.high + MGTN  # Stop loss
                        trades.append({
                            'time': current_time,
                            'direction': 'sell',
                            'entry': entry,
                            'tp': tp,
                            'sl': sl
                        })
                        ob.traded = True

    return trades

Hier implementiert der Code eine Handelsstrategie, die auf der Erkennung von Orderblöcken und der Handelssimulation anhand historischer Marktdaten basiert. Zunächst werden wichtige Bibliotheken importiert, darunter Pandas für die Datenmanipulation, NumPy für numerische Operationen und Keras/TensorFlow für eine mögliche KI-Integration. Das Skript definiert wichtige Handelsparameter wie Losgröße (LOTS), Take Profit (TAKE_PROFIT), Stop Loss (STOP_LOSS) und einen Risikomanagementfaktor (MGTN). Die Hilfsfunktionen extrahieren wichtige Kurspunkte (Eröffnungs-, Höchst-, Tiefst- und Schlusskurs) und Zeitstempelwerte aus dem Datensatz und gewährleisten so einen strukturierten Zugriff auf historische Daten. Die Klasse OrderBlock wird eingeführt, um Informationen über erkannte Aufwärts- oder Abwärts-Orderblöcke zu speichern. Dies sind kritische Bereiche im Price-Action-Handel, in denen Institutionen möglicherweise bedeutende Aufträge platziert haben.

Die Funktion get_order_blocks durchsucht die historischen Kursdaten, um potenzielle Orderblöcke auf der Grundlage einer Reihe von Aufwärts- oder Abwärtsbewegungen zu erkennen. Es identifiziert Muster, bei denen eine Preisverschiebung auftritt, und speichert die Zeit, den Höchst- und den Tiefstwert der erkannten Orderblöcke. Sobald die Orderblöcke identifiziert sind, führt die Funktion simulate_trading simulierte Abschlüsse aus. Sie durchläuft die historischen Daten und prüft, ob neue Balken (Kerzen) erscheinen und ob die Preisbedingungen den Kriterien für Kauf oder Verkauf auf der Grundlage der erkannten Orderblöcke entsprechen. Wenn eine Kauf- oder Verkaufsbedingung erfüllt ist, erfasst die Funktion einen Handel, wobei ein Einstiegskurs, ein Take-Profit und ein Stop-Loss dynamisch auf der Grundlage früherer Höchst-/Tiefstwerte festgelegt werden. Dieses Setup ermöglicht Backtests der Strategie, indem es analysiert, wie sich die Handelsgeschäfte in der Vergangenheit entwickelt hätten, und legt damit den Grundstein für die Integration von KI zur weiteren Optimierung der Handelsausführung.

# Columns: ['<DATE>', '<TIME>', '<OPEN>', '<HIGH>', '<LOW>', '<CLOSE>']
data = pd.read_csv('/home/int_junkie/Documents/DataVisuals/AI inside MQL5/XAUUSD_H1.csv', delimiter='\t')

# Combine DATE and TIME into a single DATETIME column
data['DATETIME'] = pd.to_datetime(data['<DATE>'] + ' ' + data['<TIME>'])

# Drop the original DATE and TIME columns
data.drop(columns=['<DATE>', '<TIME>'], inplace=True)

# Step 1: Detect order blocks
order_blocks = get_order_blocks(data)

# Step 2: Simulate trading based on order blocks
trades = simulate_trading(data, order_blocks)

Nach der Zusammenführung werden die ursprünglichen Datums- und Zeitspalten entfernt, damit der Datensatz sauber bleibt. Als Nächstes ruft das Skript „get_order_blocks(data)“ auf, das die Kursdaten nach potenziellen Aufwärts- und Abwärts-Orderblöcken durchsucht, d. h. nach Schlüsselbereichen, in denen möglicherweise bedeutende Kursumkehrungen oder institutionelle Aufträge erteilt wurden. Sobald die Orderblöcke erkannt sind, führt „simulate_trading(data, order_blocks)“ einen Backtest durch, indem es prüft, ob die Marktbedingungen einen dieser Orderblöcke auslösen, und simulierte Kauf- oder Verkaufstransaktionen auf der Grundlage von vordefinierten Einstiegs-, Gewinnmitnahme- und Stop-Loss-Regeln ausführt. Grundsätzlich bewerten wir die Effektivität der Handelsstrategie anhand von Preisaktionsdaten aus der Vergangenheit.

# Features: Historical OHLC data
# Labels: Buy (1), Sell (-1), Hold (0)
labels = []
for i, row in data.iterrows():
    label = 0  # Hold by default
    for trade in trades:
        if trade['time'] == row['DATETIME']:
            label = 1 if trade['direction'] == 'buy' else -1
    labels.append(label)

data['label'] = labels

# Step 4: Train LSTM model (example using Keras)
from keras.models import Sequential
from keras.layers import LSTM, Dense

# Prepare data for LSTM
def create_sequences(data, seq_length):
    X, y = [], []
    for i in range(len(data) - seq_length):
        X.append(data.iloc[i:i + seq_length][['<OPEN>', '<HIGH>', '<LOW>', '<CLOSE>']].values)
        y.append(data.iloc[i + seq_length]['label'])
    return np.array(X), np.array(y)

seq_length = 50  # Sequence length for LSTM
X, y = create_sequences(data, seq_length)

# Build LSTM model
model = Sequential()
model.add(LSTM(50, input_shape=(seq_length, 4)))  # 4 features: open, high, low, close
model.add(Dense(1, activation='tanh'))  # Output: -1 (sell), 0 (hold), 1 (buy)
model.compile(optimizer='adam', loss='mse')

# Train the model
model.fit(X, y, epochs=20, batch_size=32)

# Save the model
model.save('lstm_trading_model.h5')


Ausgabe:


Dieses Codesegment trainiert ein LSTM-Modell zur Vorhersage von Handelsentscheidungen anhand historischer Kursdaten. Der Datensatz ist mit drei möglichen Signalen gekennzeichnet: 1 (kaufen), -1 (verkaufen), oder 0 (halten). Kennzeichnungen werden durch Iteration durch historische Zeitstempel zugewiesen - wenn ein Handel zu einem bestimmten Zeitpunkt stattfand, spiegelt die Kennzeichnung seine Richtung wider; andernfalls wird sie standardmäßig auf 0 (keine Aktion) gesetzt. Dies schafft einen Rahmen für überwachtes Lernen, in dem das Modell lernt, Sequenzen vergangener Marktdaten mit nachfolgenden Handelsaktionen zu verknüpfen.

Für das LSTM-Training werden die Daten in 50-Schritt-Folgen von OHLC-Werten (Open, High, Low, Close) umstrukturiert. Jede Sequenz dient als Eingabe für die Vorhersage des Labels im nächsten Zeitschritt. Die Modellarchitektur umfasst:

  • Eine LSTM-Schicht (50 Einheiten) zur Analyse der zeitlichen Muster in der 4-Merkmale-Eingabe (OHLC).
  • Eine dichte Ausgabeschicht mit einer tanh-Aktivierung zur Erstellung von Vorhersagen zwischen -1 und 1.

Das Modell wird 20 Epochen lang mit dem Adam-Optimierer und dem Verlust des mittleren quadratischen Fehlers (MSE) trainiert. Nach dem Training wird es als „lstm_trading_model.h5“ gespeichert und kann in Handelsstrategien eingesetzt werden, um Echtzeitsignale zu erzeugen.


Einsatz des Modells

Nachdem Ihr LSTM-Modell nun als .h5-Datei serialisiert ist, geht es in der nächsten Phase darum, es innerhalb des MQL5-Ökosystems zu operationalisieren. Dies erfordert die Schaffung einer Interoperabilitätsschicht zwischen dem Python-Framework für maschinelles Lernen und der nativen Handelsinfrastruktur von MQL5, da die direkte Integration von Python nicht unterstützt wird. Eine Standardlösung besteht darin, einen Python-basierten Microservice (mit leichtgewichtigen Frameworks wie Flask oder FastAPI) zu implementieren, um das trainierte Modell zu hosten. Dieser Server fungiert als Vorhersage-Endpunkt: Er nimmt formatierte Marktdaten von MQL5 auf, führt LSTM-basierte Schlussfolgerungen aus und liefert Handelssignale in Echtzeit. Auf der MQL5-Seite nutzt Ihr Expert Advisor die „WebRequest()“-API, um sequenzielle Preisdaten an diesen Endpunkt zu übertragen und die JSON-Antworten zu parsen, wodurch Rohprognosen in ausführbare Aktionen umgewandelt werden.

Nach erfolgreicher Umsetzung dieser Brücke verlagert sich der Schwerpunkt auf die Integration der Live-Strategie. Der Expert Advisor überträgt kuratierte Datenpakete (z. B. 50-bar-OHLC-Sequenzen) in konfigurierbaren Intervallen selbstständig an den Inferenzserver. Der Python-Dienst verarbeitet diese Eingaben vor, führt Tensor-Operationen durch die LSTM-Architektur aus und liefert probabilistische Handelsanweisungen (Kaufen/Verkaufen/Halten) mit Vertrauensmetriken. Diese Signale werden dann in die Entscheidungspipeline des EA eingespeist, wo sie mit vordefinierten Risikoparametern - dynamische Stop-Loss-Schwellenwerte, Gewinnzielquoten und Positionsgrößenalgorithmen - kombiniert werden, um verwaltete Handelsgeschäfte auszuführen. Um operationelle Risiken zu minimieren, sollten wir eine schrittweise Einführung durchführen: Wir validieren das System in einer Sandbox-Demo-Umgebung, überwachen kontinuierlich die Latenzzeit und die Modellabweichung und integrieren Notfallprotokolle (z. B. Rückgriff auf auf technischen Indikatoren basierende Strategien), um die Funktionalität bei Serverausfällen oder Vorhersageanomalien aufrecht zu erhalten.


Schlussfolgerung

In diesem Projekt haben wir eine bestehende MQL5-Handelsstrategie durch die Integration eines KI-gestützten Entscheidungsfindungsprozesses unter Verwendung eines neuronalen Netzwerks mit Long Short-Term Memory (LSTM) verbessert. Wir begannen damit, die Kernlogik der MQL5-Strategie in Python zu übersetzen und ihr Verhalten anhand historischer OHLC-Daten nachzubilden. Anschließend identifizierten wir wichtige Handelssignale, wie z. B. Orderblöcke, und simulierten Handelsgeschäften, um markierte Daten für das Training des KI-Modells zu generieren. Anschließend trainierten wir das LSTM-Modell auf Sequenzen historischer Kursdaten, um vorherzusagen, ob die nächste Marktbewegung ein Kauf, ein Verkauf oder ein Halten sein sollte. Schließlich wurde das Modell als „.h5“-Datei gespeichert und konnte für den Live- oder halbautomatischen Handel eingesetzt werden.

Die Integration von KI in eine herkömmliche regelbasierte Strategie bringt den Händlern große Vorteile. Im Gegensatz zu einer statischen Logik, die festen Bedingungen folgt, kann das LSTM-Modell komplexes Preisverhalten erlernen und sich im Laufe der Zeit an die sich verändernde Marktdynamik anpassen. Dies macht die Strategie flexibler, potenziell genauer und weniger anfällig für falsche Signale, auf die starre Systeme hereinfallen könnten. Händler profitieren von einem System, das das Beste aus beiden Welten vereint: die Struktur und Zuverlässigkeit technischer Regeln mit der Anpassungsfähigkeit und Lernfähigkeit des maschinellen Lernens.

Dieser hybride Ansatz verbessert Ein- und Ausstiegsentscheidungen und öffnet die Tür für ein intelligenteres, datengesteuertes Risikomanagement im Echtzeithandel. Die Integration von KI in eine traditionelle regelbasierte Strategie bringt Händlern große Vorteile. Im Gegensatz zu einer statischen Logik, die festen Bedingungen folgt, kann das LSTM-Modell komplexes Preisverhalten erlernen und sich im Laufe der Zeit an die sich verändernde Marktdynamik anpassen. Dies macht die Strategie flexibler, potenziell genauer und weniger anfällig für falsche Signale, auf die starre Systeme hereinfallen könnten. Händler profitieren von einem System, das das Beste aus beiden Welten vereint: die Struktur und Zuverlässigkeit technischer Regeln mit der Anpassungsfähigkeit und Lernfähigkeit des maschinellen Lernens. Dieser hybride Ansatz verbessert nicht nur Ein- und Ausstiegsentscheidungen, sondern öffnet auch die Tür für ein intelligenteres, datengesteuertes Risikomanagement im Echtzeithandel.

Dateiname
Beschreibung
FIB_OB.mq5 Datei mit der ursprünglichen MQL5-Strategie
FIB_OB to AI.ipynb
Datei, die das Notebook enthält, um die Strategielogik zu konvertieren, das Modell zu trainieren und es zu speichern
XAUUSD_H1.csv
Datei mit historischen XAUUSD-Kursdaten


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

Beigefügte Dateien |
Letzte Kommentare | Zur Diskussion im Händlerforum (1)
malky3200
malky3200 | 28 Apr. 2025 in 10:25
Frage.... Gibt es einen Grund, warum Sie die Epoche auf 20 eingestellt haben?
Ist es möglich, die KI auf einer laufenden Basis lernen zu lassen?
Erstellen eines Handelsadministrator-Panels in MQL5 (Teil X): Externe, ressourcenbasierte Schnittstelle Erstellen eines Handelsadministrator-Panels in MQL5 (Teil X): Externe, ressourcenbasierte Schnittstelle
Heute machen wir uns die Möglichkeiten von MQL5 zunutze, um externe Ressourcen - wie Bilder im BMP-Format - zu nutzen und eine einzigartig gestaltete Nutzeroberfläche für das Trading Administrator Panel zu erstellen. Die hier gezeigte Strategie ist besonders nützlich, wenn mehrere Ressourcen, einschließlich Bilder, Töne und mehr, für eine rationelle Verteilung zusammengefasst werden. Nehmen Sie an dieser Diskussion teil und erfahren Sie, wie diese Funktionen implementiert werden, um eine moderne und visuell ansprechende Oberfläche für unser New_Admin_Panel EA zu schaffen.
Automatisieren von Handelsstrategien in MQL5 (Teil 15): Price Action Harmonic Cypher Pattern mit Visualisierung Automatisieren von Handelsstrategien in MQL5 (Teil 15): Price Action Harmonic Cypher Pattern mit Visualisierung
In diesem Artikel befassen wir uns mit der Automatisierung des harmonischen Cypher-Musters in MQL5 und erläutern seine Erkennung und Visualisierung auf MetaTrader 5-Charts. Wir implementieren einen Expert Advisor, der Umkehrpunkte identifiziert, Fibonacci-basierte Muster validiert und Handelsgeschäfte mit klaren grafischen Kommentaren ausführt. Der Artikel schließt mit einer Anleitung zu den Backtests und zur Optimierung des Programms für einen effektiven Handel.
Automatisieren von Handelsstrategien in MQL5 (Teil 16): Midnight Range Breakout mit der Preisaktion Break of Structure (BoS) Automatisieren von Handelsstrategien in MQL5 (Teil 16): Midnight Range Breakout mit der Preisaktion Break of Structure (BoS)
In diesem Artikel automatisieren wir die Midnight Range Breakout mit Break of Structure Strategie in MQL5, indem wir den Code für die Breakout-Erkennung und die Handelsausführung detailliert beschreiben. Wir definieren präzise Risikoparameter für Einstieg, Stopp und Gewinn. Backtests und Optimierung sind für den praktischen Handel enthalten.
Vom Neuling zum Experten: Programmieren von Kerzen Vom Neuling zum Experten: Programmieren von Kerzen
In diesem Artikel machen wir den ersten Schritt in die MQL5-Programmierung, auch für absolute Anfänger. Wir zeigen Ihnen, wie Sie bekannte Kerzenmuster in einen voll funktionsfähigen nutzerdefinierten Indikator verwandeln können. Kerzenmuster sind wertvoll, da sie reale Kursbewegungen widerspiegeln und Marktverschiebungen signalisieren. Anstatt die Charts manuell zu scannen - ein Ansatz, der fehleranfällig und ineffizient ist - werden wir besprechen, wie Sie den Prozess mit einem Indikator automatisieren können, der Muster für Sie identifiziert und kennzeichnet. Auf dem Weg dorthin werden wir uns mit Schlüsselkonzepten wie Indexierung, Zeitreihen, Average True Range (für Genauigkeit bei schwankender Marktvolatilität) und der Entwicklung einer nutzerdefinierten, wiederverwendbaren Bibliothek von Kerzen-Mustern für den Einsatz in zukünftigen Projekten beschäftigen.