English 日本語
preview
Automatisieren von Handelsstrategien in MQL5 (Teil 40): Fibonacci-Retracement-Handel mit nutzerdefinierten Levels

Automatisieren von Handelsstrategien in MQL5 (Teil 40): Fibonacci-Retracement-Handel mit nutzerdefinierten Levels

MetaTrader 5Handel |
17 4
Allan Munene Mutiiria
Allan Munene Mutiiria

Einführung

In unserem vorherigen Artikel (Teil 39) haben wir ein statistisches System der Rückkehr zum Mittelwert in MetaQuotes Language 5 (MQL5) entwickelt, das Preisdaten auf Momente wie Mittelwert, Varianz, Schiefe, Kurtosis und den Jarque-Bera Test analysiert, Reversionssignale auf der Basis von Konfidenzintervallen mit adaptiven Schwellenwerten und höherer Zeitrahmenbestätigung generiert, Handelsgeschäfte mit aktienbasiertem Sizing, Trailing Stops, Partial Closes und zeitbasierten Exits verwaltet und gleichzeitig ein On-Chart-Dashboard zur Echtzeitüberwachung bereitstellt. In Teil 40 entwickeln wir ein Fibonacci Retracement-Handelssystem mit nutzerdefinierten Levels.

Dieses System berechnet Retracement-Levels entweder anhand von Tageskerzenbereichen oder Lookback-Arrays, identifiziert Auf- oder Abwärts-Setups auf der Basis des Schlusskurses im Vergleich zum Eröffnungskurs, löst Einstiege beim Überschreiten bestimmter Levels wie 50% oder 61,8% mit maximalen Handelslimits aus, beinhaltet optionale Schließungen bei neuen Fib-Berechnungen, punktbasierte Trailing-Stops nach einem Gewinnschwellenwert und SL/TP-Puffer als Range-Prozentsätze. Wir werden die folgenden Themen behandeln:

  1. Die Fibonacci-Retracement-Strategie verstehen
  2. Implementation in MQL5
  3. Backtests
  4. Schlussfolgerung

Am Ende haben wir eine funktionierende MQL5-Strategie für den Handel mit Fibonacci-Retracements, die Sie anpassen können – los geht's!


Die Fibonacci-Retracement-Strategie verstehen

Die Fibonacci Rretracement-Strategy identifiziert potenzielle Unterstützungs- und Widerstandsniveaus, indem sie die aus der Fibonacci Sequenz abgeleiteten Schlüsselkennzahlen auf einen früheren Kursschwung anwendet, um Händlern zu helfen, Rücksetzer in Trendmärkten zu antizipieren, bei denen es wahrscheinlich ist, dass der Kurs sich umkehrt oder fortsetzt, nachdem er einen Teil der Bewegung zurückgegangen ist.

Bei einem Aufwärts-Setup, nach einem Aufwärtsschwung von einem Tief zu einem Hoch, fungieren Retracement-Levels wie 50% oder 61,8% als potenzielle Kaufzonen während Pullbacks, in Erwartung einer Rückkehr nach oben; bei einem Abwärts-Setup, nach einem Abwärtsschwung von einem Hoch zu einem Tief, dienen diese Levels als Verkaufszonen während Aufwärtskorrekturen, in Erwartung einer Wiederaufnahme des Abwärtstrends.

Wir verbessern die Einstiegsmöglichkeiten, indem wir die Überkreuzungen auf diesen Niveaus bestätigen, Puffer auf die Handelsniveaus anwenden, die auf der Swing-Range basieren, um das Risiko anzupassen, den Handel pro Niveau begrenzen, um ein übermäßiges Engagement zu vermeiden, und Trailing-Stops einbauen, um die Gewinne zu schützen, wenn sich der Preis günstig entwickelt, während wir optional die Positionen bei neuen Fib-Berechnungen für neue Setups schließen. Durch die Kombination dieser Elemente können wir Umkehrpunkte innerhalb von Trends anvisieren. Schauen Sie sich unten ein Beispiel für ein Abwärts-Retracement-Setup an, das wir haben könnten.

ABWÄRTS-RETRACEMENT-SETUP

Unser Plan ist es, Fib-Level mit Tageskerzen oder Lookback Arrays zu berechnen, die wir mit jeder Ihrer designierten Strategie wechseln können, bestimmen Auf- bzw. Abwärts-Richtung von schließen vs. öffnen, Trigger Einträge auf Kreuzungen von nutzerdefinierten Verhältnisse wie 50% oder 61.8%, oder jedes andere, das Sie wollen, dies sind die willkürlichen Niveaus, die wir für die bedeutendsten und häufigsten hielten; mit maximalen Handelslimits, SL/TP mit optionalen Range-basierten Puffern einstellen, Punkte-Trailing nach einer Gewinnschwelle aktivieren, auf neuen Fibs schließen, wenn gewählt, und mit farbigen Objekten und Info-Labels visualisieren, ein flexibles System für den Retracement-Handel aufbauen.


Implementation in MQL5

Um das Programm in MQL5 zu erstellen, öffnen wir den MetaEditor, gehen zum Navigator, suchen den Ordner Experts, klicken auf die Registerkarte „Neu“ und folgen den Anweisungen, um die Datei zu erstellen. Sobald das erstellt ist, müssen wir in der Programmierumgebung einige Eingabeparameter und globale Variablen deklarieren, die wir im gesamten Programm verwenden werden.

//+------------------------------------------------------------------+
//|                                 Fibonacci Retracement Ratios.mq5 |
//|                           Copyright 2025, Allan Munene Mutiiria. |
//|                                   https://t.me/Forex_Algo_Trader |
//+------------------------------------------------------------------+
#property copyright "Copyright 2025, Allan Munene Mutiiria."
#property link      "https://t.me/Forex_Algo_Trader"
#property version   "1.00"
#property strict

#include <Trade\Trade.mqh>                                        // For trade execution

//+------------------------------------------------------------------+
//| Enums                                                            |
//+------------------------------------------------------------------+
enum CloseOnNewEnum {                                             // Define enum for closing on new Fibonacci
   CloseOnNew_No  = 0,                                            // No
   CloseOnNew_Yes = 1                                             // Yes
};
enum TrailingTypeEnum {                                           // Define enum for trailing stop types
   Trailing_None   = 0,                                           // None
   Trailing_Points = 2                                            // By Points
};

//+------------------------------------------------------------------+
//| Input Parameters                                                 |
//+------------------------------------------------------------------+
input bool   UseDailyApproach     = true;                         // Use daily candle (true) or array (false)
input string fibLevelsStr         = "50,61.8";                    // Comma-separated Fib levels for entry (e.g., 50,61.8)
input int    maxTradesPerLevel    = 1;                            // Max trades per level per Fib period (0=unlimited)
input CloseOnNewEnum CloseOnNewFib = CloseOnNew_No;               // Close trades on new Fib calc
input TrailingTypeEnum TrailingType = Trailing_None;              // Trailing Stop Type
input double Trailing_Stop_Pips   = 30.0;                         // Trailing Stop in Pips (for Points type)
input double Min_Profit_To_Trail_Pips = 50.0;                     // Min Profit to Start Trailing in Pips
input int    LookbackSize         = 100;                          // Number of candles for array approach
input double LotSize              = 0.1;                          // Trade lot size
input int    MagicNumber          = 12345;                        // Magic number for trades
input bool   IncludeCurrentBar    = false;                        // Include current bar in array calcs for updates
input double SlBufferPercent      = 0.0;                          // SL buffer percent of range (0=no buffer)
input double TpBufferPercent      = 0.0;                          // TP buffer percent of range (0=no buffer)

Wir beginnen mit der Einbindung der Bibliothek „Trade“ mit „#include <Trade\Trade.mqh>“, um die Funktionen zur Auftragsausführung und Positionsverwaltung zu aktivieren. Wir definieren zwei Enumerationen für Nutzeroptionen: „CloseOnNewEnum“ mit den Werten „CloseOnNew_No“, um Handelsgeschäfte bei neuen Fib-Berechnungen nicht zu schließen, und „CloseOnNew_Yes“, um dies zu tun, und „TrailingTypeEnum“ mit „Trailing_None“, um das Trailing zu deaktivieren, oder „Trailing_Points“ für eine punktbasierte Anpassung.

Als Nächstes richten wir die Eingabeparameter für die Anpassung ein. „UseDailyApproach“ ist standardmäßig true für Bereiche der Tageskerzen oder false für array-basierte Lookbacks, „fibLevelsStr“ als „50,61.8“ erlaubt kommagetrennte Retracement-Levels für Eingaben, „maxTradesPerLevel“ bei 1 begrenzt Handelsgeschäfte pro Level pro Periode (0 für unbegrenzt), „CloseOnNewFib“ verwendet das Enum, um Schließungen bei Recalcs zu entscheiden, und „TrailingType“ wählt den Trailing-Modus.

Für Trailing-Details legt „Trailing_Stop_Pips“ mit 30,0 den Abstand fest, „Min_Profit_To_Trail_Pips“ mit 50,0 die Gewinnschwelle für den Start. „LookbackSize“ mit 100 definiert Kerzen für den Array-Modus, „LotSize“ mit 0.1 für die Positionsgröße, „MagicNumber“ als 12345, um Handelsgeschäfte zu identifizieren, „IncludeCurrentBar“ als false, um optional den sich bildenden Balken in die Berechnungen einzubeziehen, und „SlBufferPercent“ sowie „TpBufferPercent“ beide auf 0,0 für bereichsbasierte Anpassungen an Stops und Gewinne (höhere Werte fügen Puffer hinzu). Wenn wir kompilieren, erhalten wir diesen Satz von Eingaben.

ANPASSUNG DER EINGÄNGE

Mit den Eingaben können wir nun einige globale Variablen erstellen, die wir im gesamten Programm verwenden werden.

//+------------------------------------------------------------------+
//| Global Variables                                                 |
//+------------------------------------------------------------------+
CTrade obj_Trade;                                                 //--- Trade object
int    barsTotal;                                                 //--- For daily approach
#define FIB_OBJ "Fibonacci Retracement"                           //--- Define Fibonacci object name
// Persistent variables for both approaches
static double storedEntryLvls[];                                  //--- Array of entry levels
static int    storedTradesCount[];                                //--- Trades count per level
static double storedSl = 0.0;                                     //--- Stored stop loss
static double storedTp = 0.0;                                     //--- Stored take profit
static string storedInfo = "";                                    //--- Stored information string
static bool   storedIsBullish = false;                            //--- Stored bullish flag
static double fibLevels[];                                        //--- Parsed Fibonacci levels (original order)
static string lastShownInfo = "";                                 //--- To detect changes and avoid unnecessary updates
// For array approach
static bool   fibCalculated = false;                              //--- Fibonacci calculated flag
static double currentHigh = 0.0;                                  //--- Current high
static double currentLow = 0.0;                                   //--- Current low
static string fibName = "Fib_Array";                              //--- Fibonacci name for array

Als Nächstes deklarieren wir globale Variablen, beginnend mit „obj_Trade“ als Instanz von CTrade für die Bearbeitung von Aufträgen, „barsTotal“, um die täglichen Balken im täglichen Ansatz zu verfolgen, und definieren „FIB_OBJ“ als „Fibonacci Retracement“ für den Namen des Haupt-Fib-Objekts. Für die Persistenz über tägliche und Array-Methoden hinweg verwenden wir statische Arrays wie „storedEntryLvls[]“, um berechnete Einstiegspreise zu speichern, „storedTradesCount[]“ für die Anzahl der Handelsgeschäfte pro Ebene, die auf 0 initialisierten Doppelwerte „storedSl“ und „storedTp“.0 für Stop-Loss und Take-Profit, „storedInfo“ als leere Zeichenkette für den Anzeigetext, „storedIsBullish“ als false, um die Richtung zu kennzeichnen, „fibLevels[]“ für geparste Ratios und „lastShownInfo“ als leer, um Infoänderungen zu erkennen und Redraws zu minimieren.

Speziell für den Array-Ansatz beginnt der statische Wert „fibCalculated“ mit „false“, um anzuzeigen, ob Levels gesetzt sind, „currentHigh“ und „currentLow“ mit 0,0, um die Extremwerte für Überschreitungsprüfungen zu speichern, und „fibName“ als „Fib_Array“ für den Objektidentifikator. Damit sind wir bereit, mit der Implementierungslogik zu beginnen. Wir beginnen mit OnInit, um die Logik zu initialisieren.

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit() {
   obj_Trade.SetExpertMagicNumber(MagicNumber);                   //--- Set magic number for trade object
   // Force initial calculation for daily approach
   barsTotal = 0;                                                 //--- Ensure first tick updates
   // Parse fibLevelsStr into fibLevels array (from MQL5 docs: StringSplit)
   string tempLevels[];                                           //--- Temporary levels array
   ushort commaSep = StringGetCharacter(",", 0);                  //--- Get comma separator
   int numLevels = StringSplit(fibLevelsStr, commaSep, tempLevels); //--- Split string into levels
   ArrayResize(fibLevels, numLevels);                             //--- Resize fibLevels array
   for (int i = 0; i < numLevels; i++) {                          //--- Iterate through levels
      fibLevels[i] = StringToDouble(tempLevels[i]);               //--- Convert to double
   }
   ArrayResize(storedEntryLvls, numLevels);                       //--- Resize storedEntryLvls
   ArrayResize(storedTradesCount, numLevels);                     //--- Resize storedTradesCount
   // Clean up old labels
   ObjectsDeleteAll(0, "InfoLabel_", -1, OBJ_LABEL);              //--- Delete all info labels
   lastShownInfo = "";                                            //--- Reset last shown info
   // Clean up old Fib object for array
   ObjectDelete(0, fibName);                                      //--- Delete Fibonacci object
   fibCalculated = false;                                         //--- Reset calculated flag
   return(INIT_SUCCEEDED);                                        //--- Return success
}

In OnInit konfigurieren wir das Handelsobjekt, indem wir „obj_Trade.SetExpertMagicNumber“ mit „MagicNumber“ aufrufen, um unsere Aufträge zu identifizieren. Für den täglichen Ansatz setzen wir „barsTotal“ auf 0, um eine erste Aktualisierung beim ersten Tick zu gewährleisten. Wir parsen „fibLevelsStr“ in das Array „fibLevels“, indem wir die Zeichenkette mit StringSplit und StringGetCharacter als Trennzeichen an Kommas aufteilen, temporäre Zeichenketten in „tempLevels“ speichern, die Größe von „fibLevels“ an die Anzahl anpassen und jede Zeichenkette in einer Schleife mit StringToDouble in ein Double konvertieren. Anschließend wird die Größe von „storedEntryLvls“ und „storedTradesCount“ an die Anzahl der zu verfolgenden Ebenen angepasst.

Um aufzuräumen, löschen wir alle Info-Labels mit ObjectsDeleteAll unter Angabe des Präfixes „InfoLabel_“ und des Typs OBJ_LABEL, setzen „lastShownInfo“ auf leer, entfernen alle alten Fib-Objekte namens „fibName“ mit ObjectDelete und setzen „fibCalculated“ auf false. Schließlich geben wir INIT_SUCCEEDED zurück, um die erfolgreiche Einrichtung anzuzeigen. Wir können nun zur Ereignisbehandlung der Ticks übergehen und unsere erste Logik definieren, um alles auf den Weg zu bringen. Wir werden den Ansatz der täglichen Signale verwenden.

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick() {
   if (UseDailyApproach) {                                        //--- Check daily approach
      // Daily approach logic remains the same
      int bars = iBars(_Symbol, PERIOD_D1);                       //--- Get daily bars
      if (barsTotal != bars && TimeCurrent() > StringToTime("00:05")) { //--- Check new bar
         barsTotal = bars;                                        //--- Update bars total
         ObjectDelete(0, FIB_OBJ);                                //--- Delete Fib object
         double openPrice = iOpen(_Symbol, PERIOD_D1, 1);         //--- Get open price
         double closePrice = iClose(_Symbol, PERIOD_D1, 1);       //--- Get close price
         double high = iHigh(_Symbol, PERIOD_D1, 1);              //--- Get high
         double low = iLow(_Symbol, PERIOD_D1, 1);                //--- Get low
         datetime startingTime = iTime(_Symbol, PERIOD_D1, 1);    //--- Get start time
         datetime endingTime = iTime(_Symbol, PERIOD_D1, 0) - 1;  //--- Get end time
         double range = high - low;                               //--- Calc range
         storedIsBullish = (closePrice > openPrice);              //--- Set bullish flag
         string levelsList = "";                                  //--- Init levels list
         for (int i = 0; i < ArraySize(fibLevels); i++) {         //--- Iterate levels
            storedTradesCount[i] = 0;                             //--- Reset count
            if (storedIsBullish) {                                //--- Check bullish
               storedEntryLvls[i] = NormalizeDouble(high - range * fibLevels[i] / 100, _Digits); //--- Calc entry
            } else {                                              //--- Handle bearish
               storedEntryLvls[i] = NormalizeDouble(low + range * fibLevels[i] / 100, _Digits); //--- Calc entry
            }
            levelsList += DoubleToString(fibLevels[i], 1) + ": " + DoubleToString(storedEntryLvls[i], _Digits) + "\n"; //--- Add to list
         }
         if (storedIsBullish) {                                   //--- Check bullish
            // Bullish: Fibo from low to high for correct 0% at high, 100% at low, green
            ObjectCreate(0, FIB_OBJ, OBJ_FIBO, 0, startingTime, low, endingTime, high); //--- Create Fib
            ObjectSetInteger(0, FIB_OBJ, OBJPROP_COLOR, clrGreen); //--- Set color
            for (int i = 0; i < ObjectGetInteger(0, FIB_OBJ, OBJPROP_LEVELS); i++) { //--- Iterate levels
               ObjectSetInteger(0, FIB_OBJ, OBJPROP_LEVELCOLOR, i, clrGreen); //--- Set level color
            }
            storedSl = NormalizeDouble(low - range * (SlBufferPercent / 100), _Digits); //--- Calc SL
            storedTp = NormalizeDouble(high + range * (TpBufferPercent / 100), _Digits); //--- Calc TP
            storedInfo = "Daily Approach - Bullish\n" +           //--- Set info
                         "Open: " + DoubleToString(openPrice, _Digits) + "\n" +
                         "Close: " + DoubleToString(closePrice, _Digits) + "\n" +
                         "Buy Entries:\n" + levelsList +
                         "SL: " + DoubleToString(storedSl, _Digits) + "\n" +
                         "TP: " + DoubleToString(storedTp, _Digits);
            Print("New daily bar: Bullish Fibonacci levels calculated. Entries: ", levelsList); //--- Log
         } else {                                                 //--- Handle bearish
            // Bearish: Fibo from high to low for correct 0% at low, 100% at high, red
            ObjectCreate(0, FIB_OBJ, OBJ_FIBO, 0, startingTime, high, endingTime, low); //--- Create Fib
            ObjectSetInteger(0, FIB_OBJ, OBJPROP_COLOR, clrRed);  //--- Set color
            for (int i = 0; i < ObjectGetInteger(0, FIB_OBJ, OBJPROP_LEVELS); i++) { //--- Iterate levels
               ObjectSetInteger(0, FIB_OBJ, OBJPROP_LEVELCOLOR, i, clrRed); //--- Set level color
            }
            storedSl = NormalizeDouble(high + range * (SlBufferPercent / 100), _Digits); //--- Calc SL
            storedTp = NormalizeDouble(low - range * (TpBufferPercent / 100), _Digits); //--- Calc TP
            storedInfo = "Daily Approach - Bearish\n" +           //--- Set info
                         "Open: " + DoubleToString(openPrice, _Digits) + "\n" +
                         "Close: " + DoubleToString(closePrice, _Digits) + "\n" +
                         "Sell Entries:\n" + levelsList +
                         "SL: " + DoubleToString(storedSl, _Digits) + "\n" +
                         "TP: " + DoubleToString(storedTp, _Digits);
            Print("New daily bar: Bearish Fibonacci levels calculated. Entries: ", levelsList); //--- Log
         }
      }
   }
   // Redraw chart objects
   ChartRedraw();                                                 //--- Redraw chart
}

In OnTick wird, wenn „UseDailyApproach“ aktiviert ist, die Anzahl der Tagesbalken mithilfe von iBars mit _Symbol und dem Makro PERIOD_D1 abgerufen. Wenn sich ein neuer Tagesbalken bildet und die aktuelle Zeit über 00:05 über TimeCurrent und StringToTime, aktualisieren wir „barsTotal“, entfernen ein eventuell vorhandenes Fib-Objekt mit „ObjectDelete“ auf „FIB_OBJ“ und holen den vorherigen Tagesbalken aus iOpen, Close über „iClose“, High mit iHigh, Low mit „iLow“, zusammen mit den Start- und Endzeiten, die durch Subtraktion von 1 Sekunde für eine korrekte Darstellung angepasst werden. Wir berechnen den Bereich als Hoch minus Tief, setzen „storedIsBullish“ auf true, wenn der Schlusskurs größer ist als der Eröffnungskurs, führen eine Schleife durch die „fibLevels“-Größe von ArraySize, um „storedTradesCount[i]“ auf Null zurückzusetzen, berechnen normalisierte Einstiegsniveaus mit „NormalizeDouble“ (subtrahieren den Bereich mal den Prozentsatz des Niveaus vom Hoch für aufwärts, addieren zum Tiefkurs für abwärts) und erstellen eine „levelsList“-String für die Anzeige.

Für Aufwärtsfälle erstellen wir ein Fib-Objekt mit dem Namen „FIB_OBJ“ als OBJ_FIBO, das vom Tiefpunkt zu Beginn bis zum Hochpunkt am Ende verankert ist, setzen seine Farbe mit ObjectSetInteger auf OBJPROP_COLOR auf grün und führen eine Schleife über die Anzahl der Levels aus „ObjectGetInteger“ mit „OBJPROP_LEVELS“ durch über „OBJPROP_LEVELCOLOR“ grün einfärben; „storedSl“ unterhalb von „low“ um den Pufferprozentsatz des Bereichs berechnen, „storedTp“ oberhalb von „high“ in ähnlicher Weise, „storedInfo“ mit Ansatztyp, Open/Close, Liste der Einträge und Handelsstufen formatieren und die Berechnung protokollieren. Für abwärts, spiegeln wir den Prozess: Anker Fib von hoch zu niedrig, verwenden rote Farben, setzen SL über hoch und TP unter niedrig, aktualisieren Informationen entsprechend, und loggen das. Abschließend aktualisieren wir das Bildmaterial mit der Funktion ChartRedraw. Es ist immer eine gute Programmierpraxis, den Code bei jedem Meilenstein zu kompilieren und zu testen, um sicherzustellen, dass alles in Ordnung ist. Beim Kompilieren erhalten wir folgendes Ergebnis.

BESTÄTIGTE FIBONACCI-RETRACEMENT-NIVEAUS

Aus dem Bild können wir ersehen, dass wir den Bereich berechnen, die Richtung bestimmen und das entsprechende Fibonacci-Objekt zeichnen. Wir müssen nun die entsprechenden Positionen verfolgen und eröffnen, sobald wir auf die angegebenen Niveaus zurückgehen. Hier ist die Logik, mit der wir das erreicht haben.

//+------------------------------------------------------------------+
//| Display info using labels without flicker                        |
//+------------------------------------------------------------------+
void ShowLabels(string info) {
   if (info == lastShownInfo) return;                             //--- Skip if no change
   lastShownInfo = info;                                          //--- Update last info
   // Split info into lines
   string lines[];                                                //--- Lines array
   ushort nlSep = StringGetCharacter("\n", 0);                    //--- Get newline sep
   int numLines = StringSplit(info, nlSep, lines);                //--- Split into lines
   int y = 10;                                                    //--- Starting Y
   for (int i = 0; i < numLines; i++) {                           //--- Iterate lines
      string name = "InfoLabel_" + IntegerToString(i);            //--- Label name
      if (ObjectFind(0, name) < 0) {                              //--- Check exists
         ObjectCreate(0, name, OBJ_LABEL, 0, 0, 0);               //--- Create label
         ObjectSetInteger(0, name, OBJPROP_CORNER, CORNER_LEFT_UPPER); //--- Set corner
         ObjectSetInteger(0, name, OBJPROP_XDISTANCE, 10);        //--- Set X distance
         ObjectSetInteger(0, name, OBJPROP_FONTSIZE, 8);          //--- Set font size
      }
      ObjectSetInteger(0, name, OBJPROP_YDISTANCE, y);            //--- Set Y distance
      ObjectSetString(0, name, OBJPROP_TEXT, lines[i]);           //--- Set text
      y += 15;                                                    //--- Increment Y
   }
   // Delete extra labels if numLines decreased
   for (int i = numLines; ; i++) {                                //--- Iterate extras
      string name = "InfoLabel_" + IntegerToString(i);            //--- Label name
      if (ObjectFind(0, name) < 0) break;                         //--- Break if none
      ObjectDelete(0, name);                                      //--- Delete label
   }
}

// Display info every tick using labels (but only update if changed)
ShowLabels(storedInfo);                                           //--- Show labels
// Entry logic: Checked every tick using stored levels (no existing position)
if (PositionsTotal() == 0) {                                      //--- Check no positions
   double close1 = iClose(_Symbol, _Period, 1);                   //--- Get close 1
   double close2 = iClose(_Symbol, _Period, 2);                   //--- Get close 2
   for (int i = 0; i < ArraySize(storedEntryLvls); i++) {         //--- Iterate levels
      // Only enter on levels 0 < fib <=100 (retracements), ignore 0/100/extensions for entry
      if (fibLevels[i] <= 0 || fibLevels[i] > 100.0) continue;    //--- Skip invalid
      if ((maxTradesPerLevel == 0 || storedTradesCount[i] < maxTradesPerLevel) && //--- Check count
          ((storedIsBullish && close1 > storedEntryLvls[i] && close2 <= storedEntryLvls[i]) || //--- Buy cross
           (!storedIsBullish && close1 < storedEntryLvls[i] && close2 >= storedEntryLvls[i]))) { //--- Sell cross
         string levelStr = DoubleToString(fibLevels[i], 1);       //--- Level string
         ulong ticket = 0;                                        //--- Init ticket
         if (storedIsBullish) {                                   //--- Check buy
            Print("Buy signal triggered at ", close1, " crossing level ", levelStr, " (", storedEntryLvls[i], ")"); //--- Log
            obj_Trade.Buy(LotSize, _Symbol, 0, storedSl, storedTp, "Fibo Buy at " + levelStr); //--- Open buy
            ticket = obj_Trade.ResultDeal();                      //--- Get deal
         } else {                                                 //--- Handle sell
            Print("Sell signal triggered at ", close1, " crossing level ", levelStr, " (", storedEntryLvls[i], ")"); //--- Log
            obj_Trade.Sell(LotSize, _Symbol, 0, storedSl, storedTp, "Fibo Sell at " + levelStr); //--- Open sell
            ticket = obj_Trade.ResultDeal();                      //--- Get deal
         }
         storedTradesCount[i]++;                                  //--- Increment count
         break;                                                   //--- Break loop
      }
   }
}

Zunächst definieren wir die Funktion „ShowLabels“, um Strategie-Informationen auf dem Chart mit Hilfe von Etiketten ohne unnötige Redraws anzuzeigen. Dabei wird eine Zeichenkette „info“ genommen und frühzeitig zurückgegeben, wenn sie mit „lastShownInfo“ übereinstimmt, um ein Flackern zu vermeiden, andernfalls wird „lastShownInfo“ aktualisiert. Wir teilen „info“ in das Array „lines“ über StringSplit on newline von StringGetCharacter auf, dann durchlaufen wir eine Schleife durch „numLines“, um Etiketten mit dem Namen „InfoLabel_“ plus Index mit ObjectFind zu erstellen oder zu aktualisieren, um das Vorhandensein zu prüfen; wenn neu, verwenden wir ObjectCreate als OBJ_LABEL mit linker oberer Ecke, X-Abstand 10 und Schriftgröße 8. Wir stellen den Y-Abstand schrittweise ein, beginnend mit 10, indem wir jedes Mal 15 hinzufügen, und den Text zu „lines[i]“ mit „ObjectSetString“ auf „OBJPROP_TEXT“. Um Extras zu bereinigen, wenn die Anzahl der Zeilen abnimmt, wird eine Schleife von „numLines“ aufwärts gebildet, in der alle verbleibenden Beschriftungen mit ObjectDelete gelöscht werden, bis mit der Funktion „ObjectFind“ keine mehr gefunden werden.

Dann rufen wir in der Tick-Funktion direkt unter der zuvor definierten Logik die Funktion mit „storedInfo“ bei jedem Tick auf, um die Anzeige nur bei Änderungen zu aktualisieren. Für die Einstiegslogik, wenn keine Positionen aus PositionsTotal gleich Null vorhanden sind, holen wir vorherige Schließungen mit iClose bei den Verschiebungen 1 und 2, dann Schleife über „storedEntryLvls“ Größe von „ArraySize“, Überspringen Ebenen außerhalb 0 bis 100 für echte Retracements. Wenn Handelsgeschäfte erlaubt sind (unbegrenzt oder unter „maxTradesPerLevel“) und eine Kreuzung auftritt – Close1 über Level und Close2 bei oder unter für Käufe, oder Close1 unter und Close2 bei oder über für Verkäufe – formatieren wir „levelStr“ mit DoubleToString auf eine Dezimalstelle gerundet, initialisieren ein Ticket, protokollieren das Signal, eröffnen einen Kauf oder Verkauf über „obj_Trade.Buy“ oder „Sell“ mit „LotSize“, Symbol, Marktpreis 0, „storedSl“, „storedTp“ und Kommentar einschließlich Level, erfassen das Geschäftsergebnis, erhöhen „storedTradesCount[i]“ und brechen ab, um mehrere Einträge pro Tick zu vermeiden. Nach dem Kompilieren erhalten wir folgendes Ergebnis:

BESTÄTIGTE ERÖFFNUNG

Nachdem wir nun den Einstieg in die Logik des täglichen Ansatzes bestätigen können, wollen wir uns dem anderen Ansatz zuwenden. Wir haben uns für dieses Projekt für zwei Logiken entschieden, um Ihnen zu zeigen, wie Sie diese umstellen oder an die von Ihnen gewünschten Handelsansätze anpassen können. Da dieser Array-Ansatz dynamisch ist, um mehr Signale zu geben, wollen wir die Analyse nur einmal durchführen, und so lange der Preis zwischen dem vorherigen Setup liegt, warten wir. Wir analysieren nur, wenn das vorherige Setup durchbrochen wurde, d. h. wenn der Kurs aus dem Bereich zwischen 0 und 100 herauskommt. Beachten Sie, dass es über 100 weitere Stufen gibt. Wir brauchen also eine Funktion, die den Bruch signalisiert.

//+------------------------------------------------------------------+
//| Check if price breaches the current Fib extremes                 |
//+------------------------------------------------------------------+
bool IsBreach() {
   if (!fibCalculated) return false;                              //--- Return false if not calculated
   double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);            //--- Get bid price
   if (storedIsBullish) {                                         //--- Check bullish
      // For bullish, 0% is high, 100% is low
      return (bid > currentHigh || bid < currentLow);             //--- Check breach
   } else {                                                       //--- Handle bearish
      // For bearish, 0% is low, 100% is high
      return (bid > currentLow || bid < currentHigh);             //--- Check breach
   }
}

Hier implementieren wir die Funktion „IsBreach“, um zu erkennen, ob der aktuelle Geldkurs aus SymbolInfoDouble mit SYMBOL_BID über die gespeicherten Fib-Extreme hinausgebrochen ist, und geben frühzeitig false zurück, wenn „fibCalculated“ nicht true ist. Bei Aufwärts-Setups, bei denen 0% auf dem Hoch und 100% auf dem Tief liegen, wird geprüft, ob das Gebot über „currentHigh“ oder unter „currentLow“ liegt; bei Abwärts-Setups mit umgekehrten Ankern wird geprüft, ob das Gebot über „currentLow“ oder unter „currentHigh“ liegt, wobei bei „true“ Wiederholungen im Array-Modus ausgelöst werden. Gut. Wir können nun unseren Array-Ansatz einbeziehen, der mit dem täglichen Ansatz identisch ist.

else {                                                          //--- Array approach
   // Array approach: Calculate only when not calculated or breached
   if (!fibCalculated || IsBreach()) {                          //--- Check recalc
      if (fibCalculated) {                                      //--- Check calculated
         // Invalidate and forget previous
         ObjectDelete(0, fibName);                              //--- Delete Fib
         fibCalculated = false;                                 //--- Reset flag
      }
      int startShift = IncludeCurrentBar ? 0 : 1;               //--- Set start shift
      int copyCount = IncludeCurrentBar ? LookbackSize : LookbackSize; //--- Set copy count
      double high[], low[];                                     //--- High and low arrays
      ArraySetAsSeries(high, true);                             //--- Set as series
      ArraySetAsSeries(low, true);                              //--- Set as series
      if (CopyHigh(_Symbol, _Period, startShift, copyCount, high) <= 0) return; //--- Copy high
      if (CopyLow(_Symbol, _Period, startShift, copyCount, low) <= 0) return; //--- Copy low
      int highestCandle = ArrayMaximum(high, 0, copyCount);     //--- Get highest
      int lowestCandle = ArrayMinimum(low, 0, copyCount);       //--- Get lowest
      MqlRates pArray[];                                        //--- Rates array
      ArraySetAsSeries(pArray, true);                           //--- Set as series
      int pData = CopyRates(_Symbol, _Period, startShift, copyCount, pArray); //--- Copy rates
      if (pData <= 0) return;                                   //--- Check data
      double highVal = pArray[highestCandle].high;              //--- Get high val
      double lowVal = pArray[lowestCandle].low;                 //--- Get low val
      double range = highVal - lowVal;                          //--- Calc range
      int oldestShift = IncludeCurrentBar ? (LookbackSize - 1) : LookbackSize; //--- Oldest shift
      double openCandle = iOpen(_Symbol, _Period, oldestShift); //--- Get open
      double closeCandle = iClose(_Symbol, _Period, IncludeCurrentBar ? 0 : 1); //--- Get close
      storedIsBullish = (closeCandle > openCandle);             //--- Set bullish
      string levelsList = "";                                   //--- Init list
      for (int i = 0; i < ArraySize(fibLevels); i++) {          //--- Iterate levels
         storedTradesCount[i] = 0;                              //--- Reset count
         if (storedIsBullish) {                                 //--- Check bullish
            storedEntryLvls[i] = NormalizeDouble(highVal - range * fibLevels[i] / 100, _Digits); //--- Calc entry
         } else {                                               //--- Handle bearish
            storedEntryLvls[i] = NormalizeDouble(lowVal + range * fibLevels[i] / 100, _Digits); //--- Calc entry
         }
         levelsList += DoubleToString(fibLevels[i], 1) + ": " + DoubleToString(storedEntryLvls[i], _Digits) + "\n"; //--- Add to list
      }
      if (storedIsBullish) {                                    //--- Check bullish
         // Bullish: Anchor from low to high
         datetime time1 = pArray[lowestCandle].time;            //--- Time1
         double price1 = lowVal;                                //--- Price1
         datetime time2 = pArray[highestCandle].time;           //--- Time2
         double price2 = highVal;                               //--- Price2
         ObjectCreate(0, fibName, OBJ_FIBO, 0, time1, price1, time2, price2); //--- Create Fib
         ObjectSetInteger(0, fibName, OBJPROP_COLOR, clrGreen); //--- Set color
         for (int i = 0; i < ObjectGetInteger(0, fibName, OBJPROP_LEVELS); i++) { //--- Iterate levels
            ObjectSetInteger(0, fibName, OBJPROP_LEVELCOLOR, i, clrGreen); //--- Set level color
         }
         storedSl = NormalizeDouble(lowVal - range * (SlBufferPercent / 100), _Digits); //--- Calc SL
         storedTp = NormalizeDouble(highVal + range * (TpBufferPercent / 100), _Digits); //--- Calc TP
         storedInfo = "Array Approach - Bullish\n" +            //--- Set info
                      "Array Open: " + DoubleToString(openCandle, _Digits) + "\n" +
                      "Array Close: " + DoubleToString(closeCandle, _Digits) + "\n" +
                      "Buy Entries:\n" + levelsList +
                      "SL: " + DoubleToString(storedSl, _Digits) + "\n" +
                      "TP: " + DoubleToString(storedTp, _Digits);
      } else {                                                  //--- Handle bearish
         // Bearish: Anchor from high to low
         datetime time1 = pArray[highestCandle].time;           //--- Time1
         double price1 = highVal;                               //--- Price1
         datetime time2 = pArray[lowestCandle].time;            //--- Time2
         double price2 = lowVal;                                //--- Price2
         ObjectCreate(0, fibName, OBJ_FIBO, 0, time1, price1, time2, price2); //--- Create Fib
         ObjectSetInteger(0, fibName, OBJPROP_COLOR, clrRed);   //--- Set color
         for (int i = 0; i < ObjectGetInteger(0, fibName, OBJPROP_LEVELS); i++) { //--- Iterate levels
            ObjectSetInteger(0, fibName, OBJPROP_LEVELCOLOR, i, clrRed); //--- Set level color
         }
         storedSl = NormalizeDouble(highVal + range * (SlBufferPercent / 100), _Digits); //--- Calc SL
         storedTp = NormalizeDouble(lowVal - range * (TpBufferPercent / 100), _Digits); //--- Calc TP
         storedInfo = "Array Approach - Bearish\n" +            //--- Set info
                      "Array Open: " + DoubleToString(openCandle, _Digits) + "\n" +
                      "Array Close: " + DoubleToString(closeCandle, _Digits) + "\n" +
                      "Sell Entries:\n" + levelsList +
                      "SL: " + DoubleToString(storedSl, _Digits) + "\n" +
                      "TP: " + DoubleToString(storedTp, _Digits);
      }
      currentHigh = storedIsBullish ? highVal : lowVal;         //--- Set current high
      currentLow = storedIsBullish ? lowVal : highVal;          //--- Set current low
      fibCalculated = true;                                     //--- Set calculated
   }
   // Display info using labels (but only update if changed)
   ShowLabels(storedInfo);                                        //--- Show labels
   // Entry logic: Checked every tick using stored levels (no existing position)
   if (PositionsTotal() == 0) {                                   //--- Check no positions
      double close1 = iClose(_Symbol, _Period, 1);                //--- Get close 1
      double close2 = iClose(_Symbol, _Period, 2);                //--- Get close 2
      for (int i = 0; i < ArraySize(storedEntryLvls); i++) {      //--- Iterate levels
         if (fibLevels[i] <= 0 || fibLevels[i] > 100.0) continue; //--- Skip invalid
         if ((maxTradesPerLevel == 0 || storedTradesCount[i] < maxTradesPerLevel) && //--- Check count
             ((storedIsBullish && close1 > storedEntryLvls[i] && close2 <= storedEntryLvls[i]) || //--- Buy cross
              (!storedIsBullish && close1 < storedEntryLvls[i] && close2 >= storedEntryLvls[i]))) { //--- Sell cross
            string levelStr = DoubleToString(fibLevels[i], 1);     //--- Level string
            ulong ticket = 0;                                      //--- Init ticket
            if (storedIsBullish) {                                 //--- Check buy
               Print("Buy signal triggered (Array) at ", close1, " crossing level ", levelStr, " (", storedEntryLvls[i], ")"); //--- Log
               obj_Trade.Buy(LotSize, _Symbol, 0, storedSl, storedTp, "Fibo Buy Array at " + levelStr); //--- Open buy
               ticket = obj_Trade.ResultDeal();                        //--- Get deal
            } else {                                               //--- Handle sell
               Print("Sell signal triggered (Array) at ", close1, " crossing level ", levelStr, " (", storedEntryLvls[i], ")"); //--- Log
               obj_Trade.Sell(LotSize, _Symbol, 0, storedSl, storedTp, "Fibo Sell Array at " + levelStr); //--- Open sell
               ticket = obj_Trade.ResultDeal();                        //--- Get deal
            }
            storedTradesCount[i]++;                                //--- Increment count
            break;                                                 //--- Break loop
         }
      }
   }
}

Wir verwenden den Array-Ansatz für den nicht-täglichen Modus. Die Fib-Levels werden nur dann neu berechnet, wenn dies noch nicht geschehen ist oder wenn „IsBreach“ einen Preisdurchbruch feststellt. Falls bereits gesetzt, löschen wir das alte Fib-Objekt mit ObjectDelete auf „fibName“ und setzen „fibCalculated“ auf false zurück. Die Startverschiebung und die Anzahl der Kopien hängen von „IncludeCurrentBar“ ab: bei „true“ wird 0 und ein vollständiger Rückblick verwendet, bei „false“ wird 1 und nur abgeschlossene Takte verwendet. High und Low Arrays werden mit ArraySetAsSeries als Serie gesetzt und mit den Funktionen CopyHigh und CopyLow gefüllt. Wenn dies nicht gelingt, kehren wir vorzeitig zurück. Dann werden die höchste und die niedrigste Kerze mit ArrayMaximum und ArrayMinimum von Index 0 bis Count ermittelt.

Um genaue Werte und Zeiten zu erhalten, kopieren wir die Raten in „pArray“ mit CopyRates, und wenn die Daten nicht ausreichen, extrahieren wir „highVal“ aus dem Hoch der Kerze und „lowVal“ aus dem Tief der Kerze und berechnen die Spanne als deren Differenz. Für die Richtung wird mit iOpen die älteste Schicht geöffnet und mit iClose die jüngste Schicht geschlossen, wobei „storedIsBullish“ gesetzt wird, wenn close größer als open ist. Schleife durch die „fibLevels“-Größe von ArraySize, um die Zählungen zurückzusetzen, normalisierte Einträge zu berechnen (subtrahiere Bereichsprozent von „highVal“ für aufwärts, addiere zu „lowVal“ für abwärts), und stelle „levelsList“ für Info zusammen. Für die Zeichnung und den Handel verwenden wir einen ähnlichen Ansatz wie für den täglichen Modus. Nach dem Kompilieren erhalten wir folgendes Ergebnis:

BESTÄTIGUNG DER LOGIK DES ARRAY-ANSATZES

Wir können sehen, dass wir den Array-Ansatz verwenden und Positionen einleiten. Jetzt geht es darum, die Positionen zu verwalten, indem wir sie schließen, wenn wir neue Signale erhalten, und die Positionen, die sich zu unseren Gunsten entwickeln, nachziehen.

//+------------------------------------------------------------------+
//| Close all positions with matching magic and symbol               |
//+------------------------------------------------------------------+
void CloseAllPositions() {
   for (int i = PositionsTotal() - 1; i >= 0; i--) {              //--- Iterate positions reverse
      if (PositionGetTicket(i) > 0 && PositionGetInteger(POSITION_MAGIC) == MagicNumber && PositionGetString(POSITION_SYMBOL) == _Symbol) { //--- Check position
         obj_Trade.PositionClose(PositionGetTicket(i));                //--- Close position
      }
   }
}

//+------------------------------------------------------------------+
//| Apply Points Trailing Stop (from reference)                      |
//+------------------------------------------------------------------+
void ApplyPointsTrailing() {
   double point = _Point;                                         //--- Get point value
   for (int i = PositionsTotal() - 1; i >= 0; i--) {              //--- Iterate positions reverse
      if (PositionGetTicket(i) > 0) {                             //--- Check valid ticket
         if (PositionGetString(POSITION_SYMBOL) == _Symbol && PositionGetInteger(POSITION_MAGIC) == MagicNumber) { //--- Check symbol and magic
            double sl = PositionGetDouble(POSITION_SL);              //--- Get SL
            double tp = PositionGetDouble(POSITION_TP);              //--- Get TP
            double openPrice = PositionGetDouble(POSITION_PRICE_OPEN); //--- Get open price
            ulong ticket = PositionGetInteger(POSITION_TICKET);      //--- Get ticket
            if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) { //--- Check buy
               double newSL = NormalizeDouble(SymbolInfoDouble(_Symbol, SYMBOL_BID) - Trailing_Stop_Pips * point, _Digits); //--- Calc new SL
               if (newSL > sl && SymbolInfoDouble(_Symbol, SYMBOL_BID) - openPrice > Min_Profit_To_Trail_Pips * point) { //--- Check conditions
                  obj_Trade.PositionModify(ticket, newSL, tp);           //--- Modify position
               }
            } else if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL) { //--- Check sell
               double newSL = NormalizeDouble(SymbolInfoDouble(_Symbol, SYMBOL_ASK) + Trailing_Stop_Pips * point, _Digits); //--- Calc new SL
               if (newSL < sl && openPrice - SymbolInfoDouble(_Symbol, SYMBOL_ASK) > Min_Profit_To_Trail_Pips * point) { //--- Check conditions
                  obj_Trade.PositionModify(ticket, newSL, tp);           //--- Modify position
               }
            }
         }
      }
   }
}

Dies sind die Funktionen, die wir benötigen, um die Verwaltungslogik zu erreichen. Wir müssen sie nur bei Bedarf entsprechend aufrufen.

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick() {
   // Points trailing can run anytime
   if (TrailingType == Trailing_Points && PositionsTotal() > 0) { //--- Check trailing
      ApplyPointsTrailing();                                      //--- Apply trailing
   }
   //--- call where necessary
         if (CloseOnNewFib == CloseOnNew_Yes) {                   //--- Check close on new
            CloseAllPositions();                                  //--- Close positions
         }
}

Wir rufen die Funktionen in der Tick-Funktion auf, wo es nötig ist. Nun müssen die Objekte, die wir beim Beenden des Charts erstellt haben, wie folgt gelöscht werden.

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason) {
   ObjectsDeleteAll(0, "InfoLabel_", -1, OBJ_LABEL);              //--- Delete all info labels
   ObjectDelete(0, FIB_OBJ);                                      //--- Delete daily Fibonacci
   ObjectDelete(0, fibName);                                      //--- Delete array Fibonacci
}

In der Funktion OnDeinit werden alle Info-Labels mit der Funktion ObjectsDeleteAll unter Angabe des Präfixes „InfoLabel_“ und des Typs OBJ_LABEL aus allen Unterfenstern entfernt. Anschließend wird das tägliche Fib-Objekt über „ObjectDelete“ auf „FIB_OBJ“ und das Array auf „fibName“ gelöscht, um das Bildmaterial zu löschen. Nach dem Kompilieren erhalten wir folgendes Ergebnis:

KOMPILIERTES GIF

Wir können sehen, dass wir die Positionen standardmäßig verwalten, indem wir bei Bedarf Trailing-Stops anwenden und so unsere Ziele erreichen. Bleiben nur noch die Backtests des Programms, und das wird im nächsten Abschnitt behandelt.


Backtests

Nach einem gründlichen Backtest erhalten wir folgende Ergebnisse.

Backtest-Grafik:

GRAPH

Bericht des Backtest:

BERICHT


Schlussfolgerung

Zusammenfassend haben wir ein Retracement-Handelssystem in MQL5 entwickelt, das Niveaus anhand von Tageskerzen oder Lookback-Arrays berechnet, Auf- oder Abwärts-Setups anhand des Schlusskurses im Vergleich zum Eröffnungskurs identifiziert, Käufe oder Verkäufe bei der Überschreitung von nutzerdefinierten Quoten mit Handelslimits pro Niveau ausführt, optionale Schließungen bei Recalcs, punktbasierte Trailing-Stops nach einer Gewinnschwelle und Einstiegsniveaus mit Range-Puffern anwendet, ergänzt durch visuelle Darstellungen auf dem Chart und Informationsetiketten.

Haftungsausschluss: Dieser Artikel ist nur für Bildungszwecke gedacht. Der Handel ist mit erheblichen finanziellen Risiken verbunden, und die Volatilität der Märkte kann zu Verlusten führen. Gründliche Backtests und sorgfältiges Risikomanagement sind entscheidend, bevor Sie dieses Programm auf den Live-Märkten einsetzen.

Mit dieser Fibonacci-Retracement-Strategie sind Sie für den effektiven Handel mit Pullback-Gelegenheiten gerüstet und bereit für die weitere Optimierung Ihrer Handelsreise. Viel Spaß beim Handeln!

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

Beigefügte Dateien |
Letzte Kommentare | Zur Diskussion im Händlerforum (4)
Israr Hussain Shah
Israr Hussain Shah | 17 Nov. 2025 in 15:47
wow diese so gut ich bin mit diesem ist meine Handelsstrategie perfekt danke für diese
Allan Munene Mutiiria
Allan Munene Mutiiria | 18 Nov. 2025 in 06:04
Israr Hussain Shah Handelsstrategie perfekt danke für diese
Vielen Dank für das freundliche Feedback. Willkommen.
Lesley Malabi Barasa
Lesley Malabi Barasa | 19 Nov. 2025 in 07:12
Das ist so erstaunlich, nur um das, was ich auf dem Campus gelernt habe, auf meine Handelsstrategien anzuwenden. Können wir auch eine über Geometrische Brownsche Bewegung und Kalkül machen?
Allan Munene Mutiiria
Allan Munene Mutiiria | 19 Nov. 2025 in 07:29
Lesley Malabi Barasa Handelsstrategien anzuwenden. Können wir auch einen über Geometrische Brownsche Bewegung und Kalkül machen?
Danke für das freundliche Feedback. Sicherlich.
Entwicklung des Price Action Analysis Toolkit (Teil 50): Entwicklung der RVGI, CCI und SMA Confluence Engine in MQL5 Entwicklung des Price Action Analysis Toolkit (Teil 50): Entwicklung der RVGI, CCI und SMA Confluence Engine in MQL5
Vielen Händlern fällt es schwer, echte Umkehrungen zu erkennen. Dieser Artikel stellt einen EA vor, der RVGI, CCI (±100) und einen SMA-Trendfilter kombiniert, um ein einziges klares Umkehrsignal zu erzeugen. Der EA enthält ein On-Chart-Panel, konfigurierbare Warnungen und die vollständige Quelldatei zum sofortigen Herunterladen und Testen.
Klassische Strategien neu interpretieren (Teil 13): Unsere Kreuz-Strategie in neue Dimensionen führen (Teil 2) Klassische Strategien neu interpretieren (Teil 13): Unsere Kreuz-Strategie in neue Dimensionen führen (Teil 2)
Nehmen Sie an unserer Diskussion teil, in der wir nach weiteren Verbesserungen für unsere Strategie des Kreuzens von gleitenden Durchschnitten suchen, um die Verzögerung in unserer Handelsstrategie durch den Einsatz unserer Kompetenzen im Bereich Data Science auf ein zuverlässigeres Niveau zu reduzieren. Es ist eine gut untersuchte Tatsache, dass die Projektion Ihrer Daten in höhere Dimensionen manchmal die Leistung Ihrer Machine-Learning-Modelle verbessern kann. Wir zeigen Ihnen, was dies für Sie als Händler konkret bedeutet, und veranschaulichen, wie Sie dieses leistungsstarke Prinzip mit Ihrem MetaTrader 5-Terminal für sich nutzen können.
Entwicklung einer Handelsstrategie: Die Triple-Sinus-Mittelwertumkehrmethode Entwicklung einer Handelsstrategie: Die Triple-Sinus-Mittelwertumkehrmethode
In diesem Artikel wird die Methode der Triple Sine Mean Reversion vorgestellt, eine Handelsstrategie, die auf einem neuen mathematischen Indikator basiert – dem Triple Sine Oscillator (TSO). Der TSO ist von der kubischen Sinusfunktion abgeleitet, die zwischen -1 und +1 oszilliert und sich daher zur Erkennung überkaufter und überverkaufter Marktbedingungen eignet. Insgesamt zeigt die Studie, wie mathematische Funktionen in praktische Handelsinstrumente umgewandelt werden können.
Markets Positioning Codex in MQL5 (Teil 2):  Bitweises Lernen, mit Multi-Patterns für Nvidia Markets Positioning Codex in MQL5 (Teil 2): Bitweises Lernen, mit Multi-Patterns für Nvidia
Wir setzen unsere neue Serie zur Marktpositionierung fort, in der wir bestimmte Vermögenswerte mit spezifischen Handelsrichtungen in überschaubaren Testfenstern untersuchen. Wir begannen mit der Betrachtung der Aktie von Nvidia Corp. im letzten Artikel, in dem wir 5 Signalmuster aus der komplementären Paarung von RSI und DeMarker-Oszillator behandelten. In diesem Artikel befassen wir uns mit den verbleibenden 5 Mustern und gehen auch auf die Optionen mit mehreren Mustern ein, die nicht nur ungebundene Kombinationen aller zehn Muster, sondern auch spezielle Kombinationen von nur einem Paar umfassen.