English Русский 日本語
preview
Optimierung und Optimierung des Roh-Codes zur Verbesserung der Backtest-Ergebnisse

Optimierung und Optimierung des Roh-Codes zur Verbesserung der Backtest-Ergebnisse

MetaTrader 5Beispiele |
16 0
Hlomohang John Borotho
Hlomohang John Borotho

Einführung

Das Streben nach zuverlässigen Backtest-Ergebnissen im algorithmischen Handel hängt nicht nur von einer robusten Strategielogik ab, sondern auch von der Effizienz und Präzision des zugrunde liegenden Codes. Die Optimierungen und Anpassungen des Roh-Codes sind entscheidend, um sicherzustellen, dass Expert Advisors (EAs) wie vorgesehen funktionieren, den Rechenaufwand minimieren und gleichzeitig die Ausführungsgenauigkeit maximieren. Schlecht optimierter Code kann die Backtest-Ergebnisse durch verzögerte Auftragsausführung, falsche Signalerkennung oder Ressourcenerschöpfung verzerren - Probleme, die das wahre Potenzial einer Strategie verschleiern.

Während des Strategieentwicklungsprozesses werden wir mehrere wichtige Schritte unternehmen, um sicherzustellen, dass der EA sowohl funktional als auch technisch solide ist. Wir beginnen mit dem Hinzufügen von nutzerdefinierten Hilfsfunktionen und wiederverwendbaren Logikblöcken, um Vorgänge zu rationalisieren und sich wiederholenden Code zu vermeiden. Dann werden wir gut strukturierte Variablen und Konstanten einführen, die die Lesbarkeit des Codes verbessern und die Anpassung der Parameter vereinfachen. Diese grundlegenden Optimierungen helfen bei der Pflege des Codes und verbessern die Gesamtausführungszeit bei schweren Backtest-Lasten oder Multi-Symbol-Tests.

Ein weiterer wichtiger Bereich, in dem Verbesserungen vorgenommen werden, ist die effizientere Nutzung von technischen Indikatoren. Anstatt die Indikatoren bei jedem Tick oder Balken blind zu berechnen, werden wir eine intelligentere Aktualisierungslogik implementieren, um Last und Verzögerung zu reduzieren. Wir werden auch mit verschiedenen Indikatorenkombinationen experimentieren, um eine bessere Entscheidungsfindung in der Logik des EAs zu unterstützen. Durch die Kombination von struktureller Code-Verfeinerung, leistungsfähigen Funktionen und Indikator-Optimierung können wir sowohl die Qualität als auch die Geschwindigkeit von Backtests drastisch verbessern und so einer durchgängig profitablen und einsetzbaren Strategie näher kommen.



Entwicklung einer Strategie

Die Entwicklung unserer algorithmischen Handelsstrategie beginnt mit einem strukturierten, methodischen Ansatz zur Mustererkennung und Signalvalidierung. Die Strategie basiert auf einem Kerzen-basierten Rahmen, der entwickelt wurde, um Umkehrszenarien mit hoher Wahrscheinlichkeit zu identifizieren. Bei Kaufpositionen erkennt die Logik systematisch drei aufeinanderfolgende Aufwärtskerzen, gefolgt von einer oder zwei korrigierenden Abwärtskerzen, die in einer bestätigenden Aufwärtskerze bei Index 1 (dem zuletzt geschlossenen Balken) gipfeln.

Umgekehrt werden Verkaufspositionen durch ein umgekehrtes Muster ausgelöst: drei aufeinanderfolgende Abwärtskerzen, gefolgt von einer oder zwei Aufwärts-Retracement-Kerzen und abgeschlossen durch eine bestätigende Abwärtskerze bei Index 1. Diese Konfiguration stellt sicher, dass die Signale nur bei der Bildung eines neuen Balkens validiert werden, sodass sich die Ausführung an der bestätigten Preisbewegung und nicht an den Schwankungen innerhalb des Balkens orientiert.

Um diese Logik in die Tat umzusetzen, wird die Architektur der Strategie dem modularen Code-Design und der Recheneffizienz Priorität einräumen. Zunächst werden Hilfsfunktionen implementiert, um sich wiederholende Aufgaben zu abstrahieren, wie z. B. die Klassifizierung von Kerzen (Auf-/Abwärts-Bestimmung) und die Sequenzvalidierung (Überprüfung aufeinanderfolgender Kerzenmuster). Diese Funktionen nutzen die nativen Preisdatenzugriffsmethoden von MQL5, einschließlich „iOpen()“ und „iClose()“, und minimieren gleichzeitig redundante Berechnungen durch statisches Variablen-Caching.

Zweitens stellt ein ereignisgesteuertes Ausführungsmodell sicher, dass der Expert Advisor (EA) nur dann Signale verarbeitet, wenn sich ein neuer Balken bildet, wie durch Zeitstempelvergleiche bei Index 1 ermittelt. Dieser Ansatz reduziert unnötigen Rechenaufwand und verhindert falsche Auslöser bei der Entwicklung von Balken.

Die letzte Phase der Entwicklung wird sich auf die Leistungsoptimierung und Robustheitstests konzentrieren. Technische Indikatoren, wie z. B. Volumenfilter oder volatilitätsangepasste Stop-Loss-Levels, werden integriert, um die Präzision des Ein- und Ausstiegs zu verfeinern. Darüber hinaus werden historische Pufferarrays für die Speicherung von Kerzen-Mustern vorab zugewiesen, wodurch der Overhead bei der Speicherzuweisung während der Laufzeit reduziert wird. Durch die Kombination dieser Elemente - modulares Codedesign, ereignisgesteuerte Ausführung und strategische Integration von Indikatoren - erreicht die EA ein Gleichgewicht zwischen Reaktionsfähigkeit und Ressourceneffizienz.

Code:

//+------------------------------------------------------------------+
//|                           Includes                               |
//+------------------------------------------------------------------+
#include <Trade/Trade.mqh>
MqlTick CTick, PTick;
CTrade trade;

enum InLot{
   Lot_fixed,
   Lot_dynamic,
};

//+------------------------------------------------------------------+
//|                           Inputs                                 |
//+------------------------------------------------------------------+
input group "--------------General Inputs--------------"
input int RSI_Period = 14;
input int    TakeProfit   = 100;     // TP in points
input ulong  MagicNumber  = 888888;  // EA identifier
input int    MaxBarsCheck = 8;       // Historical bars to analyze
input InLot Lot_mode = Lot_fixed;
input double  In_Lot = 0.01;
input bool TrailYourStop = true;
input int trailingStop = 50;
//input int StopLoss = 234;

//+------------------------------------------------------------------+
//|                      Global Variables                            |
//+------------------------------------------------------------------+
int rsiHandle, macdHanlde;
datetime lastBarTime;

double pointMultiplier;
double StopLoss     = 150;

bool bullish_pattern_met = false;
bool bearish_pattern_met = false;

double first_bullish_low = 0.0;
double first_bearish_high = 0.0;

ENUM_TIMEFRAMES TimeFrame = PERIOD_CURRENT;

Die Architektur des Expert Advisors integriert wichtige Bibliotheken und Datenstrukturen, um nahtlose Handelsfunktionen zu ermöglichen. Die Einbindung der Bibliothek <Trade/Trade.mqh> ermöglicht den Zugriff auf die Klasse CTrade und vereinfacht die Auftragsverwaltung, wie z. B. das Öffnen, Ändern und Schließen von Positionen. Zwei MqlTick-Strukturen - „CTick“ und „PTick“ - werden eingesetzt, um Preisdaten in Echtzeit zu verfolgen und so die Präzision des Ausführungszeitpunkts und die Analyse der Marktbedingungen zu gewährleisten. Eine Enumeration (InLot) definiert die Positionsgrößen-Methode des EA und bietet sowohl feste (Lot_fixed) als auch dynamische (Lot_dynamic) Modi, wobei letztere für potenzielle risikoangepasste Lot-Berechnungen in zukünftigen Iterationen reserviert sind.

Die Nutzeranpassung wird durch eine spezielle Eingabeschnittstelle erleichtert, die Parameteranpassungen ohne Änderung des Kerncodes ermöglicht. Zu den kritischen Einstellungen gehört RSI_Periode (Standard: 14), die die Empfindlichkeit der Indikatoren bestimmt, die wir später bei der Entwicklung verwenden werden, sowie die Werte „TakeProfit“ und „TrailingStop“ (in Punkten) zur Festlegung der Risiko-Rendite-Schwellenwerte. Der Parameter „MagicNumber“ stellt die Integrität der Handelsidentifikation sicher, während „MaxBarsCheck“ die Tiefe der historischen Daten für die Musteranalyse bestimmt. Die Flexibilität der Positionsgröße wird durch Lot_mode und In_Lot erreicht, und die Trailing-Stop-Funktionen (TrailYourStop, trailingStop) automatisieren die Gewinnsicherung bei günstigem Handelsverlauf.

Intern werden komplexe Arbeitsabläufe über globale Variablen verwaltet. Indikator-Handles (rsiHandle, macdHandle) speichern und referenzieren Indikator-Instanzen während der Laufzeit, während „lastBarTime“ die zeitliche Synchronisation durch Aufzeichnung des Zeitstempels der zuletzt analysierten Kerze erleichtert. Boolesche Flags (bullish_pattern_met, bearish_pattern_met) und Swing-Level-Marker (first_bullish_low, first_bearish_high) überwachen dynamisch die Marktbedingungen, und TimeFrame legt die operative Periodizität des EA fest, wobei für die unmittelbare Verwendbarkeit standardmäßig der Zeitrahmen des aktiven Charts verwendet wird.

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit(){

   // Create RSI and MACD indicator handles
   rsiHandle = iRSI(_Symbol, TimeFrame, RSI_Period, PRICE_CLOSE);
   macdHanlde = iMACD(_Symbol, TimeFrame, 12, 26, 9, PRICE_CLOSE);

   return(INIT_SUCCEEDED);
}

Die Funktion „Oninit()“ initialisiert RSI- und MACD-Indikatoren korrekt, indem sie die richtigen Einstellungen für ihre Perioden und Preistypen zuweist. Diese Indikatoren werden im Speicher für die zukünftige Verwendung bei der Optimierung von Handelssignalen vorbereitet. Ein erfolgreiches Setup gibt INIT_SUCCEEDED zurück, um zu bestätigen, dass der EA betriebsbereit ist.

void OnTick(){

   if(!NewBarTrigger()) return;
   ThreeBar();
}
//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
//| Detects new bar formation                                        |
//+------------------------------------------------------------------+
bool NewBarTrigger(){

   datetime currentTime = iTime(_Symbol, PERIOD_CURRENT, 0);
   if(currentTime != lastBarTime){
      lastBarTime = currentTime;
      return true;
   }
   return false;
}

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

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

//+------------------------------------------------------------------+
//| Execute trade with risk parameters                               |
//+------------------------------------------------------------------+
void ExecuteTrade(ENUM_ORDER_TYPE tradeType)
{
   double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
   double price = (tradeType == ORDER_TYPE_BUY) ? SymbolInfoDouble(_Symbol, SYMBOL_ASK) :                                                  SymbolInfoDouble(_Symbol, SYMBOL_BID);

   // Convert StopLoss and TakeProfit from pips to actual price distances
   double sl_distance = StopLoss * point;
   double tp_distance = TakeProfit * point;
   
   double sl = (tradeType == ORDER_TYPE_BUY) ? price - sl_distance :
                                               price + sl_distance;   
   double tp = (tradeType == ORDER_TYPE_BUY) ? price + tp_distance :
                                               price - tp_distance;
   trade.PositionOpen(_Symbol, tradeType, In_Lot, price, sl, tp, NULL);
}

Die Funktion „OnTick()“ dient als Herzschlag unseres EA und wird bei jedem eingehenden Markttick ausgeführt. Um eine übermäßige Verarbeitung und unnötige Berechnungen zu vermeiden, wird zunächst mit „NewBarTrigger()“ geprüft, ob ein neuer Balken vorliegt. Wenn sich ein neuer Balken gebildet hat, rufen wir die Funktion „ThreeBar()“ auf, die unsere Handelslogik und die Routine zur Mustererkennung enthält.

Die Funktion „NewBarTrigger()“ ist für die Erkennung des Beginns einer neuen Kerze verantwortlich. Dies geschieht durch den Vergleich der Öffnungszeit der aktuellen Kerze mit der in „lastBarTime“ zuvor gespeicherten Zeit. Wenn ein neuer Zeitstempel erkannt wird, wird „lastBarTime“ aktualisiert und true zurückgegeben, sodass „OnTick()“ fortgesetzt werden kann. Dadurch wird sichergestellt, dass Handelsentscheidungen nur einmal pro Balken getroffen werden, was für unsere Strategie, die auf der Bestätigungen des Schließens des Balkens beruht, entscheidend ist. Die Hilfsfunktionen „getHigh()“ und „getLow()“ sind einfache Hilfsaufrufe, die den Höchst- und Tiefstpreis eines bestimmten Balkenindex im aktuellen Chart zurückgeben.

Die Funktion „ExecuteTrade()“ sorgt für die Platzierung von Handelsgeschäften mit den richtigen Risikoparametern. Zunächst wird der aktuelle Marktpreis je nach Handelsart (Kauf oder Verkauf) ermittelt, dann werden Stop Loss und Take Profit in tatsächlichen Preiseinheiten berechnet, indem die nutzerdefinierten Pip/Point-Werte unter Verwendung des Wertes von „Point“ des Symbols umgerechnet werden. Diese berechneten Werte werden dann an die Methode „PositionOpen()“ der Klasse „CTrade“ weitergegeben, um sicherzustellen, dass jeder Handel mit genauen und konsistenten Risikokontrollen ausgeführt wird.

//+------------------------------------------------------------------+
//| Candle pattern detection Function                                |
//+------------------------------------------------------------------+
void ThreeBar() {
   // Settings
   string symbol = Symbol();              // Current symbol
   ENUM_TIMEFRAMES timeframe = PERIOD_M5; // Timeframe (e.g., 1-hour)

   // Pattern detection variables
   int min_bullish_count = 3;
   int min_bearish_count = 3;
   int check_candles = 6;  // Check the last 6 candles for patterns

   bool bullish_pattern = false;
   bool bearish_pattern = false;
   static bool bullish_pattern_detected = false;
   static bool bearish_pattern_detected = false;

   // Loop through recent candles to search for patterns
   for (int i = check_candles; i >= min_bullish_count; i--) {
      
      // Reset pattern flags for each loop iteration
      bullish_pattern = false;
      bearish_pattern = false;

      // 1. Check for Bullish Trend Pattern
      int bullish_count = 0;
      int bearish_count = 0;

      // Count initial bullish candles
      for (int j = i; j >= i - min_bullish_count + 1; j--) {
         if (iClose(symbol, timeframe, j) > iOpen(symbol, timeframe, j)){
            bullish_count++;
            first_bullish_low = getLow(5);
         }
         else
            break;
      }

      // Check for 1 or 2 bearish candles followed by a bullish candle
      if (bullish_count >= min_bullish_count) {
         for (int j = i - bullish_count; j >= i - bullish_count - 1; j--) {
            if (iClose(symbol, timeframe, j) < iOpen(symbol, timeframe, j))
               bearish_count++;
            else
               break;
         }
         if ((bearish_count == 1 || bearish_count == 2) &&
             iClose(symbol, timeframe, i - bullish_count - bearish_count) > iOpen(symbol, timeframe, i - bullish_count - bearish_count)) {
            bullish_pattern = true;
         }
      }

      // 2. Check for Bearish Trend Pattern
      int bearish_candles_count = 0;
      int bullish_candles_count = 0;

      // Count initial bearish candles
      for (int j = i; j >= i - min_bearish_count + 1; j--) {
         if (iClose(symbol, timeframe, j) < iOpen(symbol, timeframe, j)){
            bearish_candles_count++;
            first_bearish_high = getHigh(5);
         }
         else
            break;
      }

      // Check for 1 or 2 bullish candles followed by a bearish candle
      if (bearish_candles_count >= min_bearish_count) {
         for (int j = i - bearish_candles_count; j >= i - bearish_candles_count - 1; j--) {
            if (iClose(symbol, timeframe, j) > iOpen(symbol, timeframe, j))
               bullish_candles_count++;
            else
               break;
         }
         if ((bullish_candles_count == 1 || bullish_candles_count == 2) &&
             iClose(symbol, timeframe, i - bearish_candles_count - bullish_candles_count) < iOpen(symbol, timeframe, i - bearish_candles_count - bullish_candles_count)) {
            bearish_pattern = true;
         }
      }

      // Print result and call functions only once for each pattern
      if (bullish_pattern && !bullish_pattern_detected) {
         Print("Bullish pattern conditions are met");
         ExecuteTrade(ORDER_TYPE_BUY); // Call to buyer function
         bullish_pattern_detected = true;
      } else if (!bullish_pattern) {
         bullish_pattern_detected = false; // Reset when conditions no longer met
      }

      if (bearish_pattern && !bearish_pattern_detected) {
         Print("Bearish pattern conditions are met");
         ExecuteTrade(ORDER_TYPE_SELL); // Call to seller function
         bearish_pattern_detected = true;
      } else if (!bearish_pattern) {
         bearish_pattern_detected = false; // Reset when conditions no longer met
      }   
   }
}

Die Funktion „ThreeBar()“ ist das Herzstück der Mustererkennungslogik unseres Expert Advisors. Er analysiert die jüngsten Kerzen-Formationen auf dem M5-Zeitrahmen oder einem beliebigen Zeitrahmen, den Sie in den Expert Advisor laden, um potenzielle steigende oder fallende Trendumkehr-Setups zu erkennen. Die Logik beginnt mit dem Scannen der letzten sechs Kerzen, um Muster zu erkennen, bei denen auf eine Serie von mindestens drei aufeinanderfolgenden Auf- oder Abwärtskerzen ein kurzer Rücksetzer (eine oder zwei entgegengesetzte Kerzen) und dann eine Bestätigungskerze in der ursprünglichen Trendrichtung folgt. Wird eine solche Struktur erkannt, wird das Vorhandensein eines gültigen Musters angezeigt.

Während jeder Scan-Schleife werden wichtige Kurspunkte wie der Tiefststand eines Aufwärtsschwungs oder der Höchststand eines Abwärtsschwungs für eine mögliche spätere Verwendung, z. B. als Strukturbruch oder Handelsfilter, erfasst.

Gegenwärtig eröffnet der EA zwei Positionen, wenn wir eine Abwärtskerze nach der Aufwärtskerze haben, und eröffnet ein weiteres Handelsgeschäft, nachdem die Kerze geschlossen wurde, aber er eröffnet eine Position, wenn wir zwei Abwärtskerzen gefolgt von einer Aufwärtskerze haben. Das Gleiche gilt für die Verkaufssignale. Um dieses Problem zu lösen, müssen wir „break“ hinzufügen, das die Schleife sofort stoppt, sobald ein Muster einen Handel ausgelöst hat. Dies verhindert, dass der EA weiter in frühere Kerzen hineinläuft und dasselbe Muster in einer anderen Position wiederfindet, insbesondere wenn die Struktur Rücksetzer von sowohl einem als auch zwei Balken zulässt.

// Print result and call functions only once for each pattern
if (bullish_pattern && !bullish_pattern_detected) {
   Print("Bullish pattern conditions are met");
   ExecuteTrade(ORDER_TYPE_BUY);
   bullish_pattern_detected = true;
   break; // prevent further detection in this run
} else if (!bullish_pattern) {
   bullish_pattern_detected = false;
}
      
if (bearish_pattern && !bearish_pattern_detected) {
   Print("Bearish pattern conditions are met");
   ExecuteTrade(ORDER_TYPE_SELL);
   bearish_pattern_detected = true;
   break; // prevent further detection in this run
} else if (!bearish_pattern) {
   bearish_pattern_detected = false;
}

Einbindung von Indikatorfiltern:

// Indicator buffers
double rsi_value[1];    // Use array for buffer storage
double macd_main[1];    
double macd_signal[1];
   
// Get indicator values - with error checking
if (CopyBuffer(rsiHandle, 0, 0, 1, rsi_value) <= 0) {
    Print("RSI CopyBuffer error: ", GetLastError());
    return;
}
   
if (CopyBuffer(macdHandle, 0, 0, 1, macd_main) <= 0) { 
    Print("MACD Main Line error: ", GetLastError());
    return;
}
   
if (CopyBuffer(macdHandle, 1, 0, 1, macd_signal) <= 0) { 
    Print("MACD Signal Line error: ", GetLastError());
    return;
}

Bevor wir die Indikatorfilter in die Handelslogik einbeziehen, müssen wir die RSI- und MACD-Indikatorwerte mit „CopyBuffer()“ abrufen und überprüfen. Dadurch wird sichergestellt, dass der EA die neuesten Messwerte von den Indikator-Handles erhält. Im obigen Code werden Arrays verwendet, um einen einzelnen Wert aus jedem Indikatorpuffer zu speichern, und nach jeder Pufferkopie wird eine Fehlerbehandlung durchgeführt, um etwaige Probleme wie fehlgeschlagene Handle-Zugriffe oder fehlende Daten abzufangen.

Wenn ein Puffer keine Daten abrufen kann, wird die Funktion vorzeitig beendet und der entsprechende Fehler protokolliert, sodass der EA keine Handelsentscheidungen auf der Grundlage ungültiger oder fehlender Indikatoreingaben treffen kann.

// Filter + Trade Logic
if (bullish_pattern && !bullish_pattern_detected &&
    rsi_value[0] > 50 && macd_main[0] > macd_signal[0])  
{
    Print("Bullish pattern confirmed with RSI(", rsi_value[0], ") and MACD(", 
          macd_main[0], "/", macd_signal[0], ")");
    ExecuteTrade(ORDER_TYPE_BUY);
    bullish_pattern_detected = true;
    break;
 }
else if (!bullish_pattern)
    bullish_pattern_detected = false;
      
if (bearish_pattern && !bearish_pattern_detected &&
    rsi_value[0] < 50 && macd_main[0] < macd_signal[0])  
{
    Print("Bearish pattern confirmed with RSI(", rsi_value[0], ") and MACD(", 
          macd_main[0], "/", macd_signal[0], ")");
    ExecuteTrade(ORDER_TYPE_SELL);
    bearish_pattern_detected = true;
    break;
}
else if (!bearish_pattern)
    bearish_pattern_detected = false;

Das Muster aus drei Kerzen allein führt oft zu schlechten Backtest-Ergebnissen, da es den allgemeinen Markttrend nicht berücksichtigt, was häufig zu falschen Signalen führt. Um die Leistung zu verbessern, führen wir eine Trendbestätigung ein, indem wir RSI- und MACD-Indikatoren direkt in den Handelsentscheidungsblock einbeziehen.

Damit ein Aufwärtssignal gültig ist, muss der RSI über 50 liegen - was auf ein Aufwärtsmomentum hindeutet - und die MACD-Hauptlinie muss über der Signallinie liegen - was auf eine Bestätigung des Aufwärtstrends hindeutet. Für rückläufige Signale muss der RSI unter 50 liegen, und die MACD-Hauptlinie muss unterhalb der Signallinie liegen. Diese Filterlogik erhöht die Handelsgenauigkeit, indem sie den Einstieg mit der allgemeinen Marktdynamik in Einklang bringt.

Durch die Einbindung dieser Filter stellen wir sicher, dass durch das Drei-Kerzen-Muster ausgelöste Handelsgeschäfte nur dann ausgeführt werden, wenn sie durch technische Indikatoren unterstützt werden, die die vorherrschende Marktrichtung widerspiegeln. Dieser doppelte Bestätigungsansatz reduziert die Häufigkeit von Handelsgeschäften während unruhiger oder seitwärts gerichteter Märkte und erhöht die Wahrscheinlichkeit, in Handelsgeschäfte einzusteigen, hinter denen ein Momentum steht.

Letztendlich verbessert diese Verfeinerung die Entscheidungsfähigkeit des EA, was zu konsistenteren und günstigeren Backtest-Ergebnissen führt und gleichzeitig dazu beiträgt, „Whipsaws“ zu vermeiden, die durch das alleinige Verlassen auf die Kerzen-Struktur verursacht werden.



Backtest-Ergebnisse für (XAU/USD)

Die Backtests wurde anhand historischer Preisdaten für XAUUSD (Gold/US-Dollar) auf dem 1-Stunden-Zeitrahmen über ein 4-monatiges Testfenster (26. November 2021 - 17. März 2022) bewertet. Zu den wichtigsten Parametern gehören:

  • Zeitraum des RSI: 14
  • Risikomanagement: 500 Punkte Take Profit (TP), 150 Punkte Stop Loss (SL), feste Losgröße
  • Analyse Konfiguration: 8-Balken historischer Rückblickszeitraum

Marktkontext

Während des Testzeitraums wurde Gold zu einem Durchschnittspreis von 1.841,59 $ gehandelt, wobei die Volatilitätsextreme von 1.752,95 $ (Tiefstkurs) bis 2.070,48 $ (Höchstkurs) reichten. Dieser Aufwärtstrend spiegelt eine starke Tendenz nach oben wider, die besonders Anfang 2022 deutlich wurde, als die Preise um etwa 18 % anstiegen und den Höchststand vom März erreichten. Der ausgeprägte Aufwärtstrend in diesem Zeitraum steht im Einklang mit den makroökonomischen Faktoren.



Schlussfolgerung

Bei diesem Optimierungsprozess haben wir die Grenzen des alleinigen Verlassens auf ein Muster aus drei Kerzen für Handelseinstiege durch die Einbeziehung wichtiger technischer Indikatoren - RSI und MACD - beseitigt. Wir begannen mit der Sicherstellung eines robusten Datenabrufs durch Indikator-Handles und Pufferkopien mit Fehlerprüfungen. Wir haben diese Indikatoren dann als Bestätigungsfilter in der Handelsausführungslogik eingesetzt, um den Handel auf den vorherrschenden Markttrend abzustimmen. Dadurch werden die Handelsqualität und die Konsistenz der Backtests erheblich verbessert, da Signale mit geringer Wahrscheinlichkeit während einer Schwankung oder eines Gegentrends herausgefiltert werden.

Zusammenfassend lässt sich sagen, dass die Kombination von rohen Preisaktionsmustern mit momentumbasierten Indikatoren wie RSI und MACD ein kontextbewussteres Handelssystem schafft. Dieser mehrschichtige Ansatz verbessert die Fähigkeit des Expert Advisors, zwischen hochwertigen und minderwertigen Handels-Setups zu unterscheiden. Durch die Forderung nach einem Zusammenspiel von Kerzen-Mustern und breiteren Trendsignalen wird der EA disziplinierter und reagiert weniger auf kurzfristige Störungen, was letztlich zu einer verbesserten Leistung und Robustheit sowohl beim Backtesting als auch beim Live-Handel führt.

Weitere Verbesserung und Forschung:

Bereich
 Anregung
Vorteile
Dynamischer Stop-Loss oder Take-Profit
SL/TP auf Basis der ATR oder der jüngsten Volatilität anpassen
Macht das Risikomanagement anpassungsfähig an die Marktbedingungen
Trendfilter-Erweiterung
Einbeziehung von gleitenden Durchschnitten (z. B. 200 EMA) zur Bestimmung des langfristigen Trends
Verbessert die Genauigkeit der Einflugrichtung
Kontrolle der Handelsfrequenz
Fügen Sie eine Abkühlungszeit zwischen den Handelsgeschäften oder eine Höchstgrenze für Geschäfte pro Tag hinzu
Verringert den übermäßigen Handel und die Häufung von Handelsgeschäften
Multi-Timeframe-Analyse
Bestätigen Sie RSI- und MACD-Trends auf höheren Zeitskalen (z. B. H1, H4)
Verbessert die Zuverlässigkeit des Signals durch Angleichung über Zeitrahmen hinweg
Nachrichtenfilterung
Integration eines Wirtschaftskalenders oder der Erkennung von Nachrichtenzeiten
Vermeidung von Handelsgeschäften bei Ereignissen mit hoher Auswirkung

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

Beigefügte Dateien |
Die Grenzen des maschinellen Lernens überwinden (Teil 1): Mangel an interoperablen Metriken Die Grenzen des maschinellen Lernens überwinden (Teil 1): Mangel an interoperablen Metriken
Es gibt eine mächtige und allgegenwärtige Kraft, die die kollektiven Bemühungen unserer Gemeinschaft, verlässliche Handelsstrategien zu entwickeln, die KI in irgendeiner Form einsetzen, leise untergräbt. In diesem Artikel wird festgestellt, dass ein Teil der Probleme, mit denen wir konfrontiert sind, auf das blinde Festhalten an „Best Practices“ zurückzuführen ist. Indem wir dem Leser einfache marktbasierte Beweise aus der realen Welt vorlegen, werden wir ihm erklären, warum wir von einem solchen Verhalten absehen und stattdessen bereichsgebundene „Best Practices“ anwenden müssen, wenn unsere Gemeinschaft eine Chance haben soll, das latente Potenzial der KI zu nutzen.
Von der Grundstufe bis zur Mittelstufe: Template und Typename (I) Von der Grundstufe bis zur Mittelstufe: Template und Typename (I)
In diesem Artikel beginnen wir mit der Betrachtung eines der Konzepte, das viele Anfänger vermeiden. Das hängt damit zusammen, dass Templates kein einfaches Thema sind, da viele das Grundprinzip, das den Templates zugrunde liegt, nicht verstehen: die Überladung von Funktionen und Prozeduren.
Eine alternative Log-datei mit der Verwendung der HTML und CSS Eine alternative Log-datei mit der Verwendung der HTML und CSS
In diesem Artikel werden wir eine sehr einfache, aber leistungsfähige Bibliothek zur Erstellung der HTML-Dateien schreiben, dabei lernen wir auch, wie man eine ihre Darstellung einstellen kann (nach seinem Geschmack) und sehen wir, wie man es leicht in seinem Expert Advisor oder Skript hinzufügen oder verwenden kann.
Von der Grundstufe bis zur Mittelstufe: Überladen Von der Grundstufe bis zur Mittelstufe: Überladen
Vielleicht wird dieser Artikel für Programmieranfänger am verwirrendsten sein. In der Tat werde ich hier zeigen, dass nicht immer alle Funktionen und Prozeduren im selben Code eindeutige Namen haben. Ja, wir können problemlos Funktionen und Prozeduren mit demselben Namen verwenden - und das nennt man Überladen.