English Русский 中文 Español 日本語 Português
preview
Die Wiederaufnahme einer alten Trendhandelsstrategie: Zwei Stochastik-Oszillatoren, ein MA und Fibonacci

Die Wiederaufnahme einer alten Trendhandelsstrategie: Zwei Stochastik-Oszillatoren, ein MA und Fibonacci

MetaTrader 5Handelssysteme | 4 August 2023, 09:03
444 0
Javier Santiago Gaston De Iriarte Cabrera
Javier Santiago Gaston De Iriarte Cabrera

Einleitung Die Details der Strategie

Die Strategie ist rein technisch und verwendet einige technische Indikatoren und Werkzeuge, um Signale und Ziele zu liefern. Die Komponenten der Strategie sind wie folgt:

  • Ein stochastischer Oszillator mit 14 Perioden.
  • Ein 5-Perioden-Stochastik-Oszillator.
  • Ein gleitender 200-Perioden-Durchschnitt.
  • Ein Werkzeug zur Fibonacci-Projektion (für die Festlegung von Zielen).

Der Stochastik-Oszillator ist ein beliebtes technisches Analyseinstrument, das von Händlern und Anlegern zur Messung der Dynamik und Stärke der Kursbewegungen eines Finanzinstruments verwendet wird. Es wurde von George C. Lane in den späten 1950er Jahren entwickelt. Er liegt zwischen 0 und 100, wobei Werte nahe der unteren Grenze als überverkaufte Niveaus (Aufwärtstrend) und Werte nahe der oberen Grenze als überkaufte Niveaus (Abwärtstrend) bezeichnet werden.

Der 5-Perioden-Stochastik-Oszillator ist für den täglichen Zeitrahmen
wie folgt definiert:

Stoch

Dabei sind Hoch und Tief die höchsten bzw. niedrigsten Kurse der letzten 5 Tage, während %D der gleitende N-Tage-Durchschnitt von %K ist (die letzten N Werte von %K). In der Regel handelt es sich dabei um einen einfachen gleitenden Durchschnitt, es kann aber auch ein exponentieller gleitender Durchschnitt sein, um eine weniger standardisierte Gewichtung für neuere Werte zu erhalten. Bei der Arbeit mit %D allein gibt es nur ein gültiges Signal - eine Divergenz zwischen %D und dem analysierten Wertpapier.

Ein gleitender Durchschnitt ist eine häufig verwendete statistische Berechnung, die zur Glättung von Kursdaten über einen bestimmten Zeitraum beiträgt. Sie ist in verschiedenen Bereichen weit verbreitet, darunter Finanzen, Wirtschaft und Signalverarbeitung. Im Zusammenhang mit den Finanzmärkten werden gleitende Durchschnitte häufig in der technischen Analyse eingesetzt, um Trends zu erkennen und Handelssignale zu generieren.

Ein gleitender Durchschnitt wird berechnet, indem man den Durchschnitt (Mittelwert) einer Reihe von Preisen über einen bestimmten Zeitraum hinweg nimmt und ihn aktualisiert, sobald neue Daten verfügbar sind. Mit jedem neuen Datenpunkt wird der älteste Datenpunkt gelöscht, sodass ein „gleitender“ Durchschnitt entsteht, der die jüngsten Preise widerspiegelt.


Umsetzung der Strategie

Die Handelsregeln der Strategie lauten wie folgt:

  • Ein Kaufsignal wird generiert, wenn beide Stochastik-Oszillatoren gleichzeitig das überverkaufte Niveau erreichen, abprallen und dann wieder auf dieses Niveau zurückkehren (ungefähr zur gleichen Zeit). Der gesamte Prozess muss durchgeführt werden, solange der Markt über dem gleitenden 200-Perioden-Durchschnitt liegt. Das erste Ziel wird mit Hilfe der Fibonacci-Projektion festgelegt, die vom Tiefpunkt des ersten Tiefpunkts der stochastischen Oszillatoren und dem Tiefpunkt des zweiten Tiefpunkts ausgeht. Das erste Ziel ist also die 61,8%-Projektion und das zweite Ziel die 100,0%-Projektion.
  • Ein Verkaufssignal wird generiert, wenn beide Stochastik-Oszillatoren gleichzeitig das überkaufte Niveau erreichen, abprallen und dann wieder auf dieses Niveau zurückkehren (ungefähr zur gleichen Zeit). Der gesamte Prozess muss durchgeführt werden, während der Markt unter dem gleitenden 200-Perioden-Durchschnitt liegt. Das erste Ziel wird mit Hilfe der Fibonacci-Projektion festgelegt, die vom Höchststand des ersten Zeitpunkts, an dem die stochastischen Oszillatoren ihren Höchststand erreichten, und vom Höchststand des zweiten Zeitpunkts, an dem sie ihren Höchststand erreichten, ausgeht. Das erste Ziel ist also die 61,8%-Projektion und das zweite Ziel die 100,0%-Projektion.

(Ich habe die Strategie dahingehend geändert, dass die Stopp-Levels in jedem Fibonacci-Level liegen)

Die folgende Abbildung zeigt ein rückläufiges Signal:

abwärts


Letztendlich können die Ergebnisse von Markt zu Markt variieren und die aktuellen Ergebnisse sind möglicherweise nicht stabil. Strategien funktionieren in bestimmten Zeiträumen, können aber in anderen unterdurchschnittlich abschneiden.

Der Stopp der Strategie liegt entweder bei der Hälfte des Ziels, sodass ein Risiko-Ertrags-Verhältnis von 2,0 erreicht wird, oder wenn der Markt die gleitende Durchschnittslinie durchbricht.

Im Finanzwesen ist das Fibonacci-Retracement eine Methode der technischen Analyse zur Bestimmung von Unterstützungs- und Widerstandsniveaus. Sie ist nach der Fibonacci-Zahlenfolge benannt, deren Verhältnisse Kursniveaus vorgeben, bis zu denen die Märkte dazu neigen, einen Teil einer Bewegung zurückzugehen, bevor ein Trend in die ursprüngliche Richtung weitergeht.

Eine Fibonacci-Retracement-Prognose wird erstellt, indem man zwei Extrempunkte auf einem Diagramm nimmt und den vertikalen Abstand durch Fibonacci-Verhältnisse teilt. 0 % wird als Beginn des Retracements angesehen, während 100 % eine vollständige Umkehr zum ursprünglichen Kurs vor der Bewegung bedeutet. Für diese Kursniveaus werden im Chart (nicht in diesem EA) horizontale Linien eingezeichnet, die als Unterstützungs- und Widerstandsniveaus dienen.

Übliche Werte sind 23,6%, 38,2%, 50% und 61,8%.


Ergebnisse

Obwohl dies eine profitable Strategie ist, variiert sie von Markt zu Markt und die aktuellen Ergebnisse sind möglicherweise nicht stabil. Strategien funktionieren in bestimmten Zeiträumen, können aber in anderen unterdurchschnittlich abschneiden. Bitte testen Sie die Strategie, bevor Sie sie verwenden, und ändern Sie die Werte, um die beste Erleichterung zu erzielen, wie z. B. Schichttage oder Zeiträume.

Damit können wir alle Daten überschreiben 

   int Highest = iHighest(Symbol(),my_timeframe,MODE_CLOSE,shift,1);
   double High0=iHigh(Symbol(),my_timeframe,0);


   int Lowest = iLowest(Symbol(),my_timeframe,MODE_CLOSE,shift,1);
   double Low0=iLow(Symbol(),my_timeframe,0);

Zu Testzwecken werden wir jedoch einen kleineren Verschiebungswert (z. B. 300) verwenden.

Dies sind die Ergebnisse für Verschub (shift) = 300, die Zeitrahmen = 30 Minuten und den Zeitraum von 2013 bis 2023 (20. Juni) sowie ein Risiko von 2 %.

Grafik

Daten

In der Finanzwelt misst die Sharpe-Ratio (auch Sharpe-Index oder Reward-to-Variability-Ratio genannt) die Wertentwicklung einer Anlage, z. B. eines Wertpapiers oder Portfolios, im Vergleich zu einem risikofreien Vermögenswert, nachdem sie um das Risiko bereinigt wurde. Sie ist definiert als die Differenz zwischen den Renditen der Anlage und der risikofreien Rendite, geteilt durch die Standardabweichung der Anlagerenditen. Er stellt den zusätzlichen Ertrag dar, den ein Anleger pro Einheit Risikoerhöhung erhält.

Sharpe



Code

OnInit deklarieren wir die zu verwendenden technischen Elemente, die Handles:

void OnInit()
  {
   Stochastic_handle1 = iStochastic(_Symbol, PERIOD_CURRENT, Signal_0_Stoch_PeriodK, Signal_0_Stoch_PeriodD, Signal_0_Stoch_PeriodSlow, MODE_SMA, STO_LOWHIGH);
   Stochastic_handle2 = iStochastic(_Symbol, PERIOD_CURRENT, Signal_1_Stoch_PeriodK, Signal_1_Stoch_PeriodD, Signal_1_Stoch_PeriodSlow, MODE_SMA, STO_LOWHIGH);

//--- create handle of the indicator iMA
   handle_iMA=iMA(_Symbol,PERIOD_CURRENT,Inp_MA_ma_period,Inp_MA_ma_shift,
                  Inp_MA_ma_method,Inp_MA_applied_price);


//Test

   Alert("Expert Advisor has been launched");

  }

Dieser Code erstellt ein Handle für einen Stochastik-Indikator. Der Handle heißt Stochastic_handle1. Die Funktion iStochastic() wird zur Erstellung des Handles verwendet. Die Parameter, die an die Funktion übergeben werden, sind das Symbol, die aktuelle Periode, die Periode für die %K-Linie, die Periode für die %D-Linie, die Periode für die langsame Linie, der Modus für die langsame Linie und der Typ der Stochastik (niedrig/hoch).

Dieser Code wird verwendet, um den gleitenden Durchschnitt (MA) des aktuellen Symbols mit den angegebenen Parametern zu berechnen. Die Variable handle_iMA speichert das Ergebnis der MA-Berechnung. Die für die Berechnung verwendeten Parameter sind das Symbol, die aktuelle Periode, die MA-Periode, die MA-Verschiebung, die MA-Methode und der angewandte Preis. Das Symbol ist das Währungspaar oder das Wertpapier, für das der MA berechnet wird. Die aktuelle Zeitrahmen ist der des Charts, für den der MA berechnet wird. Die MA-Periode ist die Anzahl der Balken, die zur Berechnung des MA verwendet werden. Die MA-Verschiebung ist die Anzahl der Balken, um die die MA-Berechnung verschoben wird. Die MA-Methode ist die Art der MA-Berechnung, z. B. einfach, exponentiell, geglättet oder linear gewichtet. Der angewandte Preis ist der Preistyp, der in der MA-Berechnung verwendet wird, wie z. B. Close, Open, High, Low, Median, Typical oder Weighted.

Wir müssen all diese Parameter, die außerhalb und vor OnInit deklariert werden, eingeben.


Bei OnTick werden wir dies verwenden, um die Werte der einzelnen Ticks zu erhalten

   MqlTick tick;
   SymbolInfoTick(_Symbol,tick);

Dieser Code wird verwendet, um die Tick-Daten für ein bestimmtes Symbol abzurufen. Die erste Zeile deklariert eine MqlTick-Variable namens tick. Die zweite Zeile ruft die Funktion SymbolInfoTick() auf, die zwei Parameter benötigt, den Symbolnamen und die Tick-Variable. Die Funktion ruft die Tick-Daten für das angegebene Symbol ab und speichert sie in der Tick-Variable.


Um die Fibonacci-Retracement-Levels zu simulieren, werden wir dies verwenden:

int Highest = iHighest(Symbol(),my_timeframe,MODE_CLOSE,shift,1);
   double High0=iHigh(Symbol(),my_timeframe,0);


   int Lowest = iLowest(Symbol(),my_timeframe,MODE_CLOSE,shift,1);
   double Low0=iLow(Symbol(),my_timeframe,0);



   double highestValue = iHigh(Symbol(),my_timeframe,Highest);


   double lowestValue = iLow(Symbol(),my_timeframe,Lowest);
// Obtener el valor más alto y más bajo de la barra actual
   double currentHigh = High0;
   double currentLow = Low0;

// Obtener el valor más alto y más bajo de la barra anterior
   double previousHigh = highestValue;
   double previousLow = lowestValue;


   double level0s = currentHigh;
   double level1s = currentHigh - (currentHigh - previousLow) * 0.236;
   double level2s = currentHigh - (currentHigh - previousLow) * 0.382;
   double level3s = currentHigh - (currentHigh - previousLow) * 0.618;
   double level4s = previousLow;

   double level0b = currentLow;
   double level1b = currentLow + (-currentLow + previousHigh) * 0.236;
   double level2b = currentLow + (-currentLow + previousHigh) * 0.382;
   double level3b = currentLow + (-currentLow + previousHigh) * 0.618;
   double level4b = previousHigh;

Dieser Code in der Sprache MQL5 wird verwendet, um die höchsten und niedrigsten Werte eines bestimmten Symbols und einer Periode zu bestimmen. Die ersten beiden Codezeilen weisen den höchsten Wert des Symbols und der Periode der Variablen Highest und den höchsten Wert des Symbols und der Periode beim gegebenen Shift=0 der Variablen High0 (aktuelle Kerze) zu. Die nächsten beiden Codezeilen weisen den niedrigsten Wert des Symbols und der Periode der Variablen Lowest und den niedrigsten Wert des Symbols und der Periode bei der angegebenen Verschiebung=0 der Variablen Low0 zu.


Wir verwenden eine Verschiebung, um auszuwählen, wie viele Balken wir zurückblicken wollen.

Für MA werden wir dies verwenden:

//---
   double array_ma[];
   ArraySetAsSeries(array_ma,true);
   int start_pos=0,count=3;
   if(!iGetArray(handle_iMA,0,start_pos,count,array_ma))
      return;

Dieser Code wird verwendet, um ein Array von gleitenden Durchschnitten aus einem Handle abzurufen. In der ersten Zeile wird ein Array mit der Bezeichnung array_ma deklariert, das zur Speicherung der gleitenden Durchschnitte verwendet wird. In der zweiten Zeile wird das Array als Serie festgelegt. In der dritten und vierten Zeile werden zwei Integer-Variablen, start_pos und count, deklariert, die zur Angabe der Startposition und der Anzahl der aus dem Handle abzurufenden Elemente verwendet werden. Die fünfte Zeile verwendet die Funktion iGetArray, um die gleitenden Durchschnitte aus dem Handle abzurufen und im array_ma zu speichern. Die Funktion gibt false zurück, wenn der Aufruf fehlschlägt.

Damit (außerhalb von OnInit)

bool iGetArray(const int handle,const int buffer,const int start_pos,
               const int count,double &arr_buffer[])
  {
   bool result=true;
   if(!ArrayIsDynamic(arr_buffer))
     {
      //if(InpPrintLog)
      PrintFormat("ERROR! EA: %s, FUNCTION: %s, this a no dynamic array!",__FILE__,__FUNCTION__);
      return(false);
     }
   ArrayFree(arr_buffer);
//--- reset error code
   ResetLastError();
//--- fill a part of the iBands array with values from the indicator buffer
   int copied=CopyBuffer(handle,buffer,start_pos,count,arr_buffer);
   if(copied!=count)
     {
      //--- if the copying fails, tell the error code
      //if(InpPrintLog)
      PrintFormat("ERROR! EA: %s, FUNCTION: %s, amount to copy: %d, copied: %d, error code %d",
                  __FILE__,__FUNCTION__,count,copied,GetLastError());
      //--- quit with zero result - it means that the indicator is considered as not calculated
      return(false);
     }
   return(result);
  }

Dieser Code wird verwendet, um einen Teil eines Indikatorpuffers in ein Array zu kopieren. Er nimmt fünf Parameter entgegen: ein Handle, einen Puffer, eine Startposition, eine Anzahl und einen Array-Puffer. Es wird zunächst geprüft, ob der Array-Puffer dynamisch ist, und wenn nicht, wird eine Fehlermeldung ausgegeben. Anschließend wird der Fehlercode zurückgesetzt und der Puffer in den Array-Puffer kopiert. Wenn die kopierte Menge nicht mit der Anzahl übereinstimmt, wird eine Fehlermeldung ausgegeben und false zurückgegeben. Andernfalls gibt sie true zurück.


Das gibt Fehler aus, und, um die Ergebnisse in einem Diagramm darzustellen, werden wir dies verwenden:

   string text="";
   for(int i=0; i<count; i++)
      text=text+IntegerToString(i)+": "+DoubleToString(array_ma[i],Digits()+1)+"\n";
//---
   Comment(text);

Dieser Code wird verwendet, um die Werte eines Arrays vom Typ double in der Sprache MQL5 auszudrucken. Der Code beginnt damit, dass eine String-Variable namens „text“ deklariert und ihr eine leere Zeichenkette zugewiesen wird. Dann wird eine for-Schleife verwendet, um das Array zu durchlaufen, wobei die Variable „i“ als Schleifenzähler verwendet wird. Bei jeder Iteration wird der Wert von „i“ mit der Funktion IntegerToString() in eine Zeichenkette umgewandelt, und der Wert des Arrays bei diesem Index wird mit der Funktion DoubleToString() in eine Zeichenkette umgewandelt. Die Funktion Digits() wird verwendet, um die Anzahl der Dezimalstellen zu bestimmen, die bei der Umwandlung des Double-Wertes in eine Zeichenkette verwendet werden sollen. Die umgewandelten Werte werden dann an die Zeichenkette „text“ angehängt, wobei nach jedem Wert ein neues Zeilenzeichen hinzugefügt wird. Schließlich wird die Funktion Comment() verwendet, um die Variable „text“ auszudrucken.


Wir werden dasselbe mit den beiden Stochastiks tun.

Wir werden Bedingungen festlegen, damit nicht mehr als ein Auftrag gleichzeitig geöffnet wird, und zwar wie folgt:

   int total = PositionsTotal();

   if(total==0)
{
...code
}

   if(total>0)
{
...code
}

Um einen Auftrag zu senden, werden wir dies verwenden:

if(!trade.Buy(get_lot(tick.bid),_Symbol,tick.bid,newStopLossLevelb1,newTakeProfitLevelb2))
                 {
                  //--- failure message
                  Print("Buy() method failed. Return code=",trade.ResultRetcode(),
                        ". Code description: ",trade.ResultRetcodeDescription());
                 }
               else
                 {
                  Print("Buy() method executed successfully. Return code=",trade.ResultRetcode(),
                        " (",trade.ResultRetcodeDescription(),")");
                 }

Dabei werden wir tick.bid und folglich den SL und TP verwenden. Der TP ist das höchste Hoch der Verschubperiode, und der SL ist das Tief der aktuellen Kerze.

Um eine Position zu schließen, wenn der Preis den MA kreuzt, verwenden wir dies:

if(rates[1].close >array_ma22[0])
           {

            trade.PositionClose(_Symbol,5);
            Print("cerro");
            return;
           }
         else
            return;

        }

Um den TP und SL zu ändern, werden wir dies verwenden:

            //--- setting the operation parameters
            request.action  =TRADE_ACTION_SLTP; // type of trade operation
            request.position=position_ticket;   // ticket of the position
            request.symbol=position_symbol;     // symbol
            request.sl      =newStopLossLevelss;                  // Stop Loss of the position
            request.tp      =newTakeProfitLevelss;               // Take Profit of the position
            request.magic=Expert_MagicNumber;         // MagicNumber of the position
            //--- output information about the modification
            PrintFormat("Modify #%I64d %s %s",position_ticket,position_symbol,EnumToString(type));
            //--- send the request
            if(!OrderSend(request,result))
               PrintFormat("OrderSend error %d",GetLastError());  // if unable to send the request, output the error code
            //--- information about the operation
            PrintFormat("retcode=%u  deal=%I64u  order=%I64u",result.retcode,result.deal,result.order);

Denken Sie daran, das Freeze- und das Stopp-Level zu berücksichtigen. Beachten Sie auch, dass Sie sowohl TP als auch SL ändern müssen, da sonst ein Fehler angezeigt wird.

Ich habe zu allen Fibonacci-Levels StopLoss-Levels hinzugefügt, daher können die Ergebnisse vom ursprünglichen Start abweichen. Nach der Lektüre dieses Codes können Sie den Code modifizieren und diese Ebenen ändern.


Schlussfolgerung

Diese Strategie kann in bestimmten Zeiträumen gewinnbringend sein, aber auch unter anderen Umständen eine unterdurchschnittliche Entwicklung zeigen. Während der Krise 2008-2014 und der Covid-Krise 2020 war die Strategie schlecht. Sie sollten dies berücksichtigen, wenn Sie diese Strategie verwenden. 

Diese Strategie funktioniert sowohl in Krisenzeiten als auch in Trendphasen.

Es ergibt sich ein Sharpe-Verhältnis von etwa 4, was bedeutet, dass die Strategie zumindest robust ist und die Finanzierung zur Bewertung der risikobereinigten Wertentwicklung als sehr gut und nahezu hervorragend angesehen wird.

Diese Strategie kann als Ergänzung zu anderen Strategien verwendet werden.

Sie können diese Strategie nach Belieben abändern, und ich glaube, dass Sie damit bessere Ergebnisse erzielen können.

Zur Erinnerung, Ziel dieses Artikels ist es, das Verständnis für die Strategie zu fördern. Diese Strategie ist nicht für den Einsatz, wenn Sie es verwenden, seine auf eigene Gefahr.

Ich empfehle Ihnen, diesen Bot über mehrere Zeitrahmen und über andere Symbole zu testen

Die Verwendung anderer Zeiträume wird wahrscheinlich zu anderen Ergebnissen führen.

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

Beigefügte Dateien |
2Stoch_1MA.mq5 (77.39 KB)
Kann Heiken-Ashi in Kombination mit gleitenden Durchschnitten gute Signale liefern? Kann Heiken-Ashi in Kombination mit gleitenden Durchschnitten gute Signale liefern?
Kombinationen von Strategien können bessere Chancen bieten. Wir können Indikatoren oder Muster miteinander kombinieren, oder noch besser, Indikatoren mit Mustern, sodass wir einen zusätzlichen Bestätigungsfaktor erhalten. Gleitende Durchschnitte helfen uns, den Trend zu bestätigen und zu verfolgen. Sie sind die bekanntesten technischen Indikatoren, und das liegt an ihrer Einfachheit und ihrer erwiesenen Fähigkeit, einen Mehrwert für Analysen zu schaffen.
Zyklusanalyse mit dem Goertzel-Algorithmus Zyklusanalyse mit dem Goertzel-Algorithmus
In diesem Artikel stellen wir Code-Utilities vor, die den Goertzel-Algorithmus in Mql5 implementieren, und untersuchen zwei Möglichkeiten, wie die Technik bei der Analyse von Kursen für die Entwicklung möglicher Strategien eingesetzt werden kann.
Verstehen von Funktionen in MQL5 mit Anwendungen Verstehen von Funktionen in MQL5 mit Anwendungen
Funktionen sind in jeder Programmiersprache von entscheidender Bedeutung. Sie helfen Entwicklern, das DRY-Konzept anzuwenden, was bedeutet, sich nicht zu wiederholen, und bieten viele weitere Vorteile. In diesem Artikel finden Sie viele weitere Informationen über Funktionen und wie wir unsere eigenen Funktionen in MQL5 mit einfachen Anwendungen erstellen können, die in jedem System, das Sie haben, verwendet oder aufgerufen werden können, um Ihr Handelssystem zu bereichern, ohne die Dinge zu komplizieren.
Prognose mit ARIMA-Modellen in MQL5 Prognose mit ARIMA-Modellen in MQL5
In diesem Artikel setzen wir die Entwicklung der CArima-Klasse zur Erstellung von ARIMA-Modellen fort, indem wir intuitive Methoden hinzufügen, die Vorhersagen ermöglichen.