English Русский Español 日本語
preview
MQL5-Assistent-Techniken, die Sie kennen sollten (Teil 38): Bollinger Bands

MQL5-Assistent-Techniken, die Sie kennen sollten (Teil 38): Bollinger Bands

MetaTrader 5Handelssysteme | 14 November 2024, 10:47
195 0
Stephen Njuki
Stephen Njuki

Einführung

Bollinger Bands sind ein beliebter technischer Indikator, der 1987 von John Bollinger entwickelt wurde und aus 3 Linien (oder Datenpuffern) besteht. Seine Hauptfunktion besteht darin, einen Weg zu finden, um die Marktvolatilität zu quantifizieren, indem übermäßig gekaufte und übermäßig verkaufte Preispunkte von gehandelten Wertpapieren identifiziert werden. Bollinger Bänder dehnen sich aufgrund der Marktvolatilität aus und ziehen sich zusammen, wobei sich die beiden äußeren Bänder bei steigender Volatilität weiter auseinanderziehen, während sich die beiden äußeren Bänder bei sinkender Volatilität enger zusammenziehen.

Händler nutzen diese Ausdehnungen und Kontraktionen, um Perioden von Preisausbrüchen bzw. Preiskonsolidierungen zu antizipieren. Die oberen und unteren Bollinger-Bänder dienen auch als dynamische Unterstützungs- und Widerstandsniveaus, da die Kurse dazu neigen, an diesen Niveaus abzuprallen, was potenzielle Anhaltspunkte für Umkehrungen oder Fortsetzungen bietet. Bollinger Bänder unterstützen häufig Mean-Reversion-Strategien, bei denen erwartet wird, dass die Kurse zum Mittelwert (dem mittleren Band) zurückkehren, nachdem sie entweder das obere oder das untere Band berührt haben. Überkaufte und überverkaufte Bedingungen werden auch festgestellt, wenn der Kurs über die äußeren Bänder hinausgeht, was auf potenzielle Umkehrpunkte hinweist. 

Wenn sich die Kurse durchgängig in der Nähe des oberen Bandes bewegen, deutet dies darauf hin, dass ein Aufwärtstrend bevorsteht, während eine überwiegend untere Bandposition häufig auf einen intakten Abwärtstrend hindeutet. Ausbrüche (oder Ausreißer) aus diesen Bändern können daher den Beginn eines neuen Trends oder einen Wendepunkt anzeigen. Schließlich kommt es zu einem Bollinger-Band-Squeeze, wenn das obere und das untere Band über einen bestimmten Zeitraum sehr nahe beieinander liegen, sodass die Volatilität gering ist und die Möglichkeit eines Ausbruchs unmittelbar bevorsteht.  Händler beobachten dies genau und nutzen oft die Richtung des Ausbruchs als Hinweis auf die Richtung. Die Formel für die 3 Datenpuffer ist einfach und kann durch die folgenden Gleichungen erfasst werden:

wobei:

  • MB ist der Puffer für die Bandmitte
  • SMA ist eine einfache gleitende Durchschnittsfunktion
  • P steht für die Historie der Schlusskurse
  • n ist der Zeitraum, über den der einfache gleitende Durchschnitt berechnet wird

wobei:

  • UB ist der Puffer des oberen Bandes
  • k ist ein abstimmbarer Faktor, dem häufig standardmäßig 2 zugewiesen wird
  • Sigma ist die Standardabweichung über den gemittelten Zeitraum.

wobei:

  • LB ist der Puffer des unteren Bandes

Dieser Artikel soll nicht nur die verschiedenen Signale aufzählen, die Bollinger Bands generieren können, sondern auch zeigen, wie sie in eine einzige individuelle Signalklassendatei integriert werden können. In der Regel sind diese Artikel so aufgebaut, dass zuerst die Wissenschaft hinter einer Idee und dann die Strategieprüfung und die Ergebnisse am Ende vorgestellt werden. In diesem Artikel werden wir jedoch, wie in einigen anderen zuvor, die Testergebnisse für jeden vorgestellten Signalaufbau zusammen mit dem Code des Signalaufbaus veröffentlichen. Das bedeutet, dass wir mehrere Testergebnisse im Laufe des Artikels vorstellen werden, anstatt sie am Ende zu präsentieren. Wir sehen bis zu 8 mögliche Bollinger-Band-Signale, die von Händlern ausgenutzt werden können.

Nutzerdefinierte Signalklassen sind nicht nur für die Entwicklung vielseitiger und robuster Signale von entscheidender Bedeutung, da sie die Kombination verschiedener Strategien ermöglichen, sondern der minimalistische Ansatz bei der Kodierung erlaubt es im Prinzip, Ideen in kurzer Zeit zu testen und zu validieren. Der am Ende dieses Artikels beigefügte Code soll im MQL5-Assistenten verwendet werden, um einen Expert Advisor zusammenzustellen, und neue Leser können eine Anleitung finden hier und hier wie dies zu tun ist. Sobald die Ideen einer Kreuzvalidierung unterzogen wurden, haben Händler die Möglichkeit, entweder den zusammengestellten Expert Advisor einzusetzen oder ihn mit Anpassungen für die Handelsausführung neu zu programmieren, wobei die Basisstrategie beibehalten wird.

Bevor wir die Signale durchgehen, könnte es lehrreich sein, wenn wir zeigen, wie wir die nutzerdefinierte Signalklasse vorbereiten, um all diese 8 Signalalternativen zu handhaben oder zu verarbeiten. Nachstehend finden Sie die Schnittstelle der nutzerdefinierten Signalklasse:

//+------------------------------------------------------------------+
//| Class CSignalBollingerBands.                                     |
//| Purpose: Class of generator of trade signals based on            |
//|          the 'BollingerBands' indicator.                         |
//| Is derived from the CExpertSignal class.                         |
//+------------------------------------------------------------------+
class CSignalBollingerBands : public CExpertSignal
{
protected:
   CiBands           m_bands;            // object-indicator

   ....

   //--- "weights" of market models (0-100)
   int               m_pattern_0;      // model 0 "Price Crossing the Upper Band or the Lower Band"
   int               m_pattern_1;      // model 1 "Price Bouncing Off Lower Band or Upper Band "
   int               m_pattern_2;      // model 2 "Price Squeeze Followed by a Breakout Above Upper Band or Below Lower Band "
   int               m_pattern_3;      // model 3 "Price Double Bottoms Near Lower Band or Double Top Near Upper Band "
   int               m_pattern_4;      // model 4 "Price Bounces Off the Middle Band from Above & Bounce Off from Below "
   int               m_pattern_5;      // model 5 "Volume Divergence at Lower Band or Upper Band "
   int               m_pattern_6;      // model 6 "Bands Widening After Downtrend or After Uptrend "
   int               m_pattern_7;      // model 7 "Bands Orientation and Angle Changes "
   uchar             m_patterns_used;  // bit-map integer for used pattens

public:
                     CSignalBollingerBands(void);
                    ~CSignalBollingerBands(void);
   
  ....

protected:
   
   ...


   //--- methods to check for patterns
   bool              IsPattern_0(ENUM_POSITION_TYPE T);
   bool              IsPattern_1(ENUM_POSITION_TYPE T);
   bool              IsPattern_2(ENUM_POSITION_TYPE T);
   bool              IsPattern_3(ENUM_POSITION_TYPE T);
   bool              IsPattern_4(ENUM_POSITION_TYPE T);
   bool              IsPattern_5(ENUM_POSITION_TYPE T);
   bool              IsPattern_6(ENUM_POSITION_TYPE T);
   bool              IsPattern_7(ENUM_POSITION_TYPE T);
};

Er folgt dem Standardansatz für die meisten nutzerdefinierten Signale, wobei die wichtigste Ergänzung für diesen Artikel die aufgelisteten Variablen „m_pattern_XX“ sind, die im Code hervorgehoben sind. Diese Variablen, die eine Gewichtung darstellen (ein Wert im Bereich von 0 - 100), sind in nutzerdefinierten Signalklassen, die über den Assistenten zusammengestellt werden, üblich. Schnelle Beispiele hierfür sind die Signalklasse für die Hüllkurven und die des des RSI. Beide Klassen verwenden diese Mustervariablen, die eine voreingestellte konstante Gewichtung aufweisen, die oft unter 100 liegt. Eine konstante Gewichtung ist an sich nicht problematisch, da jede Klasse im Prinzip dazu gedacht ist, mit anderen Signalklassen verwendet zu werden, sodass die jeweilige Gewichtung jeder Klasse für das Gesamtsignal des Expert Advisors optimiert oder angepasst wird.

Der Gedanke, sie zu optimieren, ist daher etwas seltsam, da die Gefahr einer Überanpassung für das getestete Symbol oder den gehandelten Titel sehr groß ist und die Verwendung dieser Muster oft voraussetzt, dass der Händler mit der relativen Bedeutung und Gewichtung der einzelnen Muster gut vertraut ist. Er braucht keinen Optimierer, der ihm das sagt. Falls mehrere Signalklassen verwendet werden, die alle ihre eigenen Muster haben, würde der Optimierungsbedarf in diesem Fall ins Unermessliche steigen. Deshalb ist es immer besser, sie als „wissensbasierte“ Konstanten zu haben und nicht als eine Gewichtung, die trainiert werden muss.

In diesem Artikel wollen wir uns jedoch mit der Möglichkeit befassen, diese Muster optimieren zu lassen. Dies geschieht in erster Linie aus dem Grund, dass diese Klasse ausschließlich mit dem Assistenten erstellt wird. Es wird nicht gegen ein anderes Signal gewichtet. Unser Gewichtungsparameter für dieses Signal wird daher bei 1,0 bleiben, wie bei den meisten Signalklassen, die wir in dieser Reihe getestet haben. Hinzu kommt, dass bei der Zuweisung konstanter Musterwerte in der Regel nur eines dieser Muster verwendet wird, während die anderen inaktiv sind. Dies bedeutet in der Regel, dass die Signalklasse zusammen mit anderen Signalen zusammengestellt wird, d. h. ihre Gewichtung wird optimiert, das ausgewählte Muster wird für die Zusammenarbeit mit anderen Signalen optimiert, während die anderen, nicht ausgewählten Muster inaktiv sind.

In diesem Artikel wollen wir alle Muster verwenden, wenn sie vorhanden sind. Die Muster sind gepaart, d.h. für Kauf- und Verkaufs-Bedingungen, und es ist unwahrscheinlich, dass zwei verschiedene Muster gleichzeitig angezeigt werden können (damit meinen wir, dass z.B. Muster 1 und Muster 2 gleichzeitig signalisiert werden könnten, nicht dass eine Kauf- und Verkaufs-Bedingung für ein einzelnes Muster gleichzeitig angezeigt werden könnte). Diese nutzerdefinierten Signalklassen haben Schwellenwerte für das Schließen und das Öffnen, sodass ein bestimmtes Muster je nach seinem optimierten Wert entweder einfach eine bereits offene Position schließen oder die Position schließen und eine Umkehrung eröffnen kann. Unser Expert Advisor wird daher diese Mustergewichte über ein kurzes Fenster für ein einzelnes Symbol optimieren und sehen, ob sich daraus etwas Interessantes ergibt.

Unsere nutzerdefinierte Signalklasse erbt von der Klasse „CExpertSignal“, die über die Funktion „PatternsUsage“ verfügt, die als Eingabe eine ganze Bitmaske für die in der nutzerdefinierten Signalklasse verwendeten Muster erhält. Da wir bis zu 8 Signalmuster verwenden können, reicht die Größe unserer Bitmap von 0 bis 2 hoch 8 minus eins, also bis 255. Dies bedeutet, dass wir nicht nur die individuellen Schwellenwerte der Muster bestimmen (wobei diese Schwellenwerte das Schließen und Öffnen von Positionen festlegen), sondern auch die Muster unter den 8 auswählen, die sich am besten für eine Strategie eignen, die die Bollinger-Bänder verwendet. Diese Auswahl für die Kombination von Mustern, die gleichzeitig verwendet werden sollen, wird im abschließenden Testerbericht am Ende dieses Artikels gezeigt (aufgrund der Länge des Artikels wird dieser auf den nächsten Artikel verschoben). Die nachstehenden Testergebnisse beziehen sich auf jedes der verfügbaren Muster, wenn der Expertenberater ein einziges Muster verwendet.

Beim Testen hat sich jedoch gezeigt, dass die Zuweisung der Anzahl der verwendeten Muster die Verwendung der Definitionsfunktion „IS_PATTERN_USAGE()“ nicht wie erwartet ermöglicht. Es scheint, dass die Standardzuweisung von -1 als Anzahl der verwendeten Muster, was bedeutet, dass alle Muster verwendet werden können, immer implementiert wird, unabhängig von den Eingaben, die wir machen. Um dies zu umgehen, verwenden wir unsere eigene bitweise Implementierung, die es ermöglicht, die eingegebene Hash-Map-Ganzzahl in 0s und 1s zu konvertieren, aus denen man lesen kann, welche Muster ausgewählt wurden. Die nachstehende Tabelle kann als Leitfaden für die 8 wichtigsten individuellen Musterkarten dienen, und wie wir sie in unserem Code interpretieren:

Eingabezuordnung 
(m_patterns_used)

implizierte Bits
byte-checker
100000001
0x01
200000010
0x02
400000100
0x04
800001000
0x08
1600010000
0x10
3200100000
0x20
6401000000
0x40
12810000000
0x80

Wie man sieht, impliziert jede der 8 aufgeführten Zuordnungen die Verwendung eines einzigen Musters. Dies wird am besten durch die implizierten Bits veranschaulicht, bei denen in einer Zeichenkette von 8 Zeichen alle bis auf eines Nullen sind. Der Eingabe kann ein beliebiger Wert von 0 bis 255 zugewiesen werden, weshalb es sich um ein Zeichen ohne Vorzeichen (Datentyp uchar) handelt.


Überschreiten des oberen Bandes oder des unteren Bandes

Unser erstes Signal ist also, wenn der Kurs entweder das obere oder das untere Band überquert. Wenn der Kurs das obere Band von oben durchquert, um darunter zu fallen, interpretieren wir dies als rückläufiges Signal. Umgekehrt, wenn der Kurs das untere Band von unten durchquert und darüber schließt, interpretieren wir dies möglicherweise als Aufwärtssignal. Wir implementieren diese Logik in einer Funktion, die auf das Muster 0 prüft, wie folgt:

//+------------------------------------------------------------------+
//| Check for Pattern 0.                                             |
//+------------------------------------------------------------------+
bool CSignalBollingerBands::IsPattern_0(ENUM_POSITION_TYPE T)
{  m_bands.Refresh(-1);
   m_close.Refresh(-1);
   if(T == POSITION_TYPE_BUY && Close(StartIndex() + 1) < Lower(StartIndex() + 1) && Close(StartIndex()) > Lower(StartIndex()))
   {  return(true);
   }
   else if(T == POSITION_TYPE_SELL && Close(StartIndex() + 1) > Upper(StartIndex() + 1) && Close(StartIndex()) < Upper(StartIndex()))
   {  return(true);
   }
   return(false);
}

Unser Code ist ziemlich einfach, was zum Teil dem Code der Standardbibliothek von MQL5 zu verdanken ist, in der die Codierung für den Bollinger Bands-Indikator auf ein Minimum reduziert ist, sodass eine Klasseninstanz für den Indikator wie diese deklariert wird:

//+------------------------------------------------------------------+
//| Class CSignalBollingerBands.                                     |
//| Purpose: Class of generator of trade signals based on            |
//|          the 'BollingerBands' indicator.                         |
//| Is derived from the CExpertSignal class.                         |
//+------------------------------------------------------------------+
class CSignalBollingerBands : public CExpertSignal
{
protected:
   CiBands           m_bands;            // object-indicator
   
  ...

  ...

};

Und es wird wie folgt initialisiert:

//+------------------------------------------------------------------+
//| Create indicators.                                               |
//+------------------------------------------------------------------+
bool CSignalBollingerBands::InitIndicators(CIndicators *indicators)
{
//--- check pointer
   if(indicators == NULL)
      return(false);
//--- initialization of indicators and timeseries of additional filters
   if(!CExpertSignal::InitIndicators(indicators))
      return(false);
//--- create and initialize MA indicator
   if(!InitMA(indicators))
      return(false);
//--- ok
   return(true);
}

Alles, was wir tun müssen, ist, sie zu aktualisieren, wie in der obigen Funktion angegeben. Wir machen uns keine Gedanken über die Anzahl der Puffer, da die Funktionen für das obere Band, das untere Band und das Hauptband (oder mittlere Band) in der Klasse integriert sind. Außerdem werden die Preise des Hauptsymbols Open, High, Low und Close in referenzierten Klassen initialisiert, sofern sie im Klassenkonstruktor wie folgt deklariert werden:

//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CSignalBollingerBands::CSignalBollingerBands(void) 
...

{
//--- initialization of protected data
   m_used_series = USE_SERIES_OPEN + USE_SERIES_HIGH + USE_SERIES_LOW + USE_SERIES_CLOSE;
   ...
}

Auch hier bleibt nur die Anforderung, den jeweiligen Preis-Handle bei jedem Balken zu aktualisieren, bevor der aktuelle Preis abgerufen wird. In unserem Fall verwenden wir den Schlusskurs, und das ist alles, was wir aktualisieren müssen. Wir führen Tests mit dem aus dem Assistenten zusammengesetzten Expert Advisor durch, bei denen wir die verwendete Eingabe-Bitmap des Musters auf 1 setzen, da wir nur das erste Muster verwenden. Die teilweise optimierten Testergebnisse, bei denen nur das Muster 0 verwendet wird, ergeben folgenden Bericht:

r0

c0

Die obigen Ergebnisse stammen aus USDCHF-Testläufen auf dem Tages-Zeitrahmen für das Jahr 2023. Da wir nur das Muster 0 verwenden, ist die Ganzzahl der Hashmap für die verwendeten Muster 1. Wir prüfen dieses Muster wie folgt in den langen und kurzen Bedingungen, die im Code am Ende dieses Artikels zusammen mit den Testergebnissen für alle Muster aufgeführt sind.


Preis prallt vom unteren oder oberen Band ab

Unser nächstes Signal ist das Abprallen der Kurse an einem der äußeren Bänder. Wenn der Kurs das obere Band berührt und dann wieder davon abweicht, wird dies als Abwärtssignal gewertet. Ist der Kurs dagegen bis zum unteren Bollinger-Band gefallen und hat sich dann erholt, wird dies als Aufwärtssignal gewertet. Diese Interpretation ergibt sich daraus, dass die oberen und unteren Bänder wichtige Umkehrzonen darstellen. Dies wiederum könnte mit der Psyche des Marktes zu erklären sein, wo Händler das Gefühl haben, dass eine Korrektur fällig ist, wenn ein Kurs übermäßig in eine bestimmte Richtung steigt. Zur Erinnerung: Bollinger Bänder verfolgen nicht nur Trends dank des Basislinien- (oder Mittel-) Puffers, sondern sie behalten auch die Volatilität im Auge. Nähert sich der Kurs also einem der äußeren Bänder oder weitet er sich aus, wird Volatilität impliziert.

Bestätigungsinstrumente, die alternative Indikatoren sein können, werden idealerweise zusammen mit den Bollinger Bändern verwendet. Um dies zu überprüfen, indem wir die äußeren Bänder in MQL5 abprallen lassen, verwenden wir die folgende Quelle:

//+------------------------------------------------------------------+
//| Check for Pattern 1.                                             |
//+------------------------------------------------------------------+
bool CSignalBollingerBands::IsPattern_1(ENUM_POSITION_TYPE T)
{  m_bands.Refresh(-1);
   m_close.Refresh(-1);
   if(T == POSITION_TYPE_BUY && Close(StartIndex() + 2) > Lower(StartIndex() + 2) && Close(StartIndex() + 1) <= Lower(StartIndex() + 1) && Close(StartIndex()) > Lower(StartIndex()))
   {  return(true);
   }
   else if(T == POSITION_TYPE_SELL && Close(StartIndex() + 2) < Upper(StartIndex() + 2) && Close(StartIndex() + 1) >= Upper(StartIndex() + 1) && Close(StartIndex()) < Upper(StartIndex()))
   {  return(true);
   }
   return(false);
}

Wir verwenden bis zu 8 Muster, und wie aus der oben geteilten Tabelle ersichtlich, ist die Eingabekarte (verwendete Mustereingabe) für das zweite Muster 2. Dadurch wird sichergestellt, dass wir bei der Prüfung auf Kauf- und Verkaufs-Bedingungen nur dieses Muster, das Abprallen von den oberen und unteren Bändern, verwenden. Wir führen Testläufe für das Paar USDCHF auf dem täglichen Zeitrahmen für das Jahr 2023 durch und erhalten die folgenden Ergebnisse:

r1

с1

Die Auswirkungen auf den Handel und die möglichen Strategien, die für dieses Setup entwickelt werden können, könnten die Verwendung von Limit-Stop-Orders beinhalten. Da man vor dem Berühren dieser extremen Bänder einen Hinweis darauf hat, auf welchem Kursniveau sich das obere oder untere Band befindet, kann diese Information zusammen mit einem geeigneten Stoppkurs, der ausgelöst wird, sobald die Umkehrung erreicht ist, zum Platzieren dieser Geschäfte verwendet werden.



Preisdruck, gefolgt von einem Ausbruch über das obere Band oder unter das untere Band

Bei unserem Mustertyp 2 handelt es sich um einen Preisdruck, gefolgt von einem Ausbruch. Die Definition eines Preis-Squeeze ist in der Regel eine längere Periode niedriger Volatilität, die bei den Bollinger Bändern durch eine Verengung zwischen dem oberen und unteren Band gekennzeichnet ist. Wie groß dieser Abstand sein muss, ist eine subjektive Angelegenheit. Für unsere Zwecke machen wir es uns etwas zu einfach, da wir einen Squeeze als gleichzeitige Schrumpfung in Richtung der Basis des Bollinger Bandes sowohl für das obere als auch für das untere Band interpretieren. Das heißt, wenn dieser Squeeze nur einen Balken lang ist, werden wir ihn nutzen. Unten sehen Sie die MQL5-Implementierung dieser Funktion.

//+------------------------------------------------------------------+
//| Check for Pattern 2.                                             |
//+------------------------------------------------------------------+
bool CSignalBollingerBands::IsPattern_2(ENUM_POSITION_TYPE T)
{  m_bands.Refresh(-1);
   m_close.Refresh(-1);
   if(Upper(StartIndex()) > Upper(StartIndex() + 1) && Upper(StartIndex() + 1) < Upper(StartIndex() + 2)  && Lower(StartIndex()) < Lower(StartIndex() + 1) && Lower(StartIndex() + 1) > Lower(StartIndex() + 2))
   {  if(T == POSITION_TYPE_BUY && Close(StartIndex()) >= Upper(StartIndex()))
      {  return(true);
      }
      else if(T == POSITION_TYPE_SELL && Close(StartIndex()) <= Lower(StartIndex()))
      {  return(true);
      }
   }
   return(false);
}

Nach unserem Code ist die Dauer des Squeeze genau ein Balken. Unser Code berücksichtigt nicht einmal, wie groß die Lücke zwischen der oberen und der unteren Bandbreite ist, obwohl dies ein weiterer wichtiger Faktor ist, der bei der Festlegung berücksichtigt werden könnte. Aus unserem obigen Quellcode geht hervor, dass jeder Einbruch im oberen Band, der gleichzeitig mit einem Anstieg im unteren Band auftritt, einen Squeeze darstellt. Wenn der Kurs nach diesem Squeeze auf dem oberen Band oder näher am oberen Band liegt, wird ein Aufwärtssignal angezeigt. Befindet sich der Kurs hingegen nach diesem Squeeze auf oder an dem unteren Band, werten wir das als Abwärtssignal. Testläufe nur mit diesem Muster ergeben folgende Ergebnisse:

r2

c2

Unsere obigen Ergebnisse aus einem kurzen Optimierungslauf über das Jahr 2023 auf dem täglichen Zeitrahmen für das Symbol USDCHF sind nicht kreuzvalidiert und können nur als Hinweis auf das Potenzial von Muster 2 dienen.


Doppeltes Tief in der Nähe des unteren Bandes oder doppeltes Hoch in der Nähe des oberen Bandes

Dieses Muster ist ebenfalls in unserer Liste enthalten und ähnelt offen gesagt ein wenig dem Muster 1 (dem zweiten Muster oben). Der Hauptunterschied besteht darin, dass wir hier mehr als einen Abprall von den äußeren Bändern haben, im Gegensatz zu dem Solo-Abprall, den wir bei Muster 1 hatten. Dieses Muster, das als Muster 3 bezeichnet wird, kann also als Muster 1 mit einer Bestätigung angesehen werden. Aus diesem Grund gibt es nicht viele Handelsmöglichkeiten, die sich allein auf dieses Muster stützen. Die Implementierung in MQL5 sieht wie folgt aus:

//+------------------------------------------------------------------+
//| Check for Pattern 3.                                             |
//+------------------------------------------------------------------+
bool CSignalBollingerBands::IsPattern_3(ENUM_POSITION_TYPE T)
{  m_bands.Refresh(-1);
   m_close.Refresh(-1);
   m_high.Refresh(-1);
   m_low.Refresh(-1);
   if
   (
      T == POSITION_TYPE_BUY &&
      Close(StartIndex() + 4) < Close(StartIndex() + 3) &&
      Close(StartIndex() + 3) > Close(StartIndex() + 2) &&
      Close(StartIndex() + 2) < Close(StartIndex() + 1) &&
      Close(StartIndex() + 1) > Close(StartIndex()) &&
      Close(m_close.MinIndex(StartIndex(), 5)) - Upper(StartIndex()) >= -1.0 * Range(StartIndex())
   )
   {  return(true);
   }
   else if
   (
      T == POSITION_TYPE_SELL &&
      Close(StartIndex() + 4) > Close(StartIndex() + 3) &&
      Close(StartIndex() + 3) < Close(StartIndex() + 2) &&
      Close(StartIndex() + 2) > Close(StartIndex() + 1) &&
      Close(StartIndex() + 1) < Close(StartIndex()) &&
      Lower(StartIndex()) - Close(m_close.MaxIndex(StartIndex(), 5)) >= -1.0 * Range(StartIndex())
   )
   {  return(true);
   }
   return(false);
}

Die Eingabe-Zuordnung, die uns darauf beschränkt, nur mit diesem Muster zu handeln, ist die Bitmap 4. Wie aus unserer obigen Referenztabelle ersichtlich, zeigt ein Blick auf die implizierten Bits, dass beim Zählen von rechts nach links alles Null ist, außer dem vierten Zeichen, das unser Muster 3 darstellt. Testläufe mit ähnlichen Einstellungen wie oben, USDCHF, täglicher Zeitrahmen, 2023, liefern uns folgende Ergebnisse:

r3

c3

Wie deutlich zu erkennen ist, werden nicht viele Trades platziert, da doppelte Extremas auf einem der oberen oder unteren Bänder nicht häufig vorkommt. Das bedeutet vielleicht, dass dieses Muster unabhängig von einem anderen Indikator verwendet werden kann, im Gegensatz zu einigen der Muster, die wir gerade oben gesehen haben.


Abprallen des mittleren Bandes von oben und Abprallen von unten

Unser nächstes und fünftes Muster ist das Muster 4, bei dem es sich um Fortsetzungsmuster inmitten eines Trends handelt. Wenn sich der Kurs also in eine bestimmte Richtung bewegt, macht er häufig einige Pausen. Während dieser Unterbrechungen gibt es mehr Schwankungen als eindeutige Trends, aber oft (aber nicht immer) kann der Preis vor der Wiederaufnahme eines Trends den Widerstand (wenn der Trend abwärts gerichtet ist) oder die Unterstützung (wenn der Trend aufwärts gerichtet ist) testen. Das Testen dieser Niveaus kann durch den Basispuffer des Bollinger Bandes markiert werden, da dieser, wie auch das obere und untere Band, dazu neigt, als dynamisches Unterstützungs-/Widerstandsniveau zu fungieren.

Dieses Muster interpretieren wir als Aufwärtsmuster, wenn der Kurs die Basis (mittlerer Puffer) von oben testet und dann von ihr nach oben abprallt, und als Abwärtsmuster, wenn das Gleiche umgekehrt geschieht. Ein Abpraller von unten. Die Umsetzung in MQL5 sieht folgendermaßen aus:

//+------------------------------------------------------------------+
//| Check for Pattern 4.                                             |
//+------------------------------------------------------------------+
bool CSignalBollingerBands::IsPattern_4(ENUM_POSITION_TYPE T)
{  m_bands.Refresh(-1);
   m_close.Refresh(-1);
   if(T == POSITION_TYPE_BUY && Close(StartIndex() + 2) > Base(StartIndex() + 2) && Close(StartIndex() + 1) <= Base(StartIndex() + 1) && Close(StartIndex()) > Base(StartIndex()))
   {  return(true);
   }
   else if(T == POSITION_TYPE_SELL && Close(StartIndex() + 2) < Base(StartIndex() + 2) && Close(StartIndex() + 1) >= Base(StartIndex() + 1) && Close(StartIndex()) < Base(StartIndex()))
   {  return(true);
   }
   return(false);
}

Tests mit ähnlichen Umgebungseinstellungen wie oben führen zu folgenden Ergebnissen:

r4

c4

Unser Bollinger-Band-Indikator verwendet für alle Testläufe in diesem Artikel dieselben Einstellungen, d. h. die Periodenlänge des Indikators ist 20 und die Abweichung (deviation) beträgt 2.


Volumen-Divergenz am unteren oder oberen Band

Als Nächstes folgt unser sechstes Muster, das auf Divergenzen zwischen Volumen und Volatilität abzielt. Viele Händler, vor allem auf dieser Plattform, handeln mit Devisenpaaren, für die nur selten verlässliche Volumendaten vorliegen, da es schwierig ist, diese Informationen über mehrere Broker hinweg zu integrieren. Daher verwenden wir bei der Verfolgung oder Messung des Volumens bei der Umsetzung dieses Konzepts den wohl nächstbesten Proxy. Preisspanne. Die Argumente dafür sind, dass, wenn viele Käufer auf ein bestimmtes Paar bieten, sich dieses Paar zwangsläufig stark in Richtung des Gebots bewegt. Dies ist natürlich nicht ganz richtig, da eine ebenso große Anzahl von Verkaufs-Kontrakten am anderen Ende dieser Aktion die Preisbewegung hemmen könnte, und dennoch würde sich das Gesamtvolumen nicht in der resultierenden Preisspanne des Balkens widerspiegeln.

Es ist also einfach ein Kompromiss. Wir interpretieren als Aufwärtssignal, wenn die Preisspanne in 3 aufeinanderfolgenden Kursbalken systematisch abnimmt, während der Schlusskurs gleichzeitig am oder unter dem unteren Band der Bollinger Bänder liegt. In ähnlicher Weise haben wir ein Verkaufssignal, wenn es einen Rückgang in der Preisspanne von 3 Balken gibt und der Schlusskurs an oder über dem oberen Bandpuffer liegt. Der Grund dafür könnte in der Erschöpfung früherer Trends liegen, wobei der Rückgang des „Volumens“ am äußersten Ende einer Preisspanne entweder auf eine Umkehr oder zumindest auf einen Rückschlag hinweist. Dies wird in MQL5 wie folgt umgesetzt:

//+------------------------------------------------------------------+
//| Check for Pattern 5.                                             |
//+------------------------------------------------------------------+
bool CSignalBollingerBands::IsPattern_5(ENUM_POSITION_TYPE T)
{  m_bands.Refresh(-1);
   m_close.Refresh(-1);
   m_high.Refresh(-1);
   m_low.Refresh(-1);
   if(Range(StartIndex()) < Range(StartIndex() + 1) && Range(StartIndex() + 1) < Range(StartIndex() + 2))
   {  if(T == POSITION_TYPE_BUY && fabs(m_close.GetData(StartIndex()) - Lower(StartIndex())) < fabs(m_close.GetData(StartIndex()) - Base(StartIndex())))
      {  return(true);
      }
      else if(T == POSITION_TYPE_SELL && fabs(m_close.GetData(StartIndex()) - Upper(StartIndex())) < fabs(m_close.GetData(StartIndex()) - Base(StartIndex())))
      {  return(true);
      }
   }
   return(false);
}

Die Testläufe nur mit diesem Muster und mit ähnlichen Einstellungen für die Laufumgebung wie bei den vorherigen Tests führen zu folgenden Ergebnissen:

r5

c5


Schlussfolgerung

Ich hatte vor, alle 8 Muster des Bollinger-Band-Indikators zu behandeln, wie im beigefügten Code angegeben, aber dieser Artikel hat sich als etwas zu langatmig herausgestellt. Daher werde ich den Rest bald in einem Folgeartikel behandeln.

Abschließend haben wir jedoch 5 von mindestens 8 Signalmustern untersucht, die man beim Handel mit den Bollinger-Bändern verwenden kann. Dieser Indikator erfasst nicht nur den allgemeinen Trend des Preises, sondern auch die Volatilität dank seiner beiden äußeren Bandpuffer. Wenn diese Informationen mit der Marktpsychologie kombiniert werden, wie wir gesehen haben, kann aus diesem einen Indikator eine Reihe von Signalen generiert werden. Während jedes dieser Muster einzeln verwendet werden kann, wie wir es in diesem Artikel getan haben, weil er gekürzt werden musste, kann der Eingabeparameter der verwendeten Muster tatsächlich die Mehrfachauswahl von Mustern ermöglichen, sodass sie kombiniert und optimiert werden können, um ein dynamischeres Setup zu erstellen, das besser zu verschiedenen Arten von Märkten passt.

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

Beigefügte Dateien |
SignalWZ_38.mqh (21.4 KB)
wz_38.mq5 (8.67 KB)
Beispiel für CNA (Causality Network Analysis), SMOC (Stochastic Model Optimal Control) und Nash Game Theory mit Deep Learning Beispiel für CNA (Causality Network Analysis), SMOC (Stochastic Model Optimal Control) und Nash Game Theory mit Deep Learning
Wir werden Deep Learning zu den drei Beispielen hinzufügen, die in früheren Artikeln veröffentlicht wurden, und die Ergebnisse mit den vorherigen vergleichen. Das Ziel ist es, zu lernen, wie man DL zu anderen EAs hinzufügt.
Erstellen eines integrierten MQL5-Telegram-Expertenberaters (Teil 6): Responsive Inline-Schaltflächen hinzufügen Erstellen eines integrierten MQL5-Telegram-Expertenberaters (Teil 6): Responsive Inline-Schaltflächen hinzufügen
In diesem Artikel integrieren wir interaktive Inline-Buttons in einen MQL5 Expert Advisor, die eine Echtzeitsteuerung über Telegram ermöglichen. Jeder Tastendruck löst bestimmte Aktionen aus und sendet Antworten an den Nutzer zurück. Außerdem modularisieren wir Funktionen zur effizienten Handhabung von Telegram-Nachrichten und Callback-Abfragen.
Wie man die automatische Optimierung in MQL5 Expert Advisors implementiert Wie man die automatische Optimierung in MQL5 Expert Advisors implementiert
Schritt für Schritt Anleitung zur automatischen Optimierung in MQL5 für Expert Advisors. Wir werden eine robuste Optimierungslogik, bewährte Verfahren für die Parameterauswahl und die Rekonstruktion von Strategien mit Backtesting behandeln. Darüber hinaus werden übergeordnete Methoden wie die Walk-Forward-Optimierung erörtert, um Ihren Handelsansatz zu verbessern.
Einführung in Connexus (Teil 1): Wie verwendet man die WebRequest-Funktion? Einführung in Connexus (Teil 1): Wie verwendet man die WebRequest-Funktion?
Dieser Artikel ist der Beginn einer Reihe von Entwicklungen für eine Bibliothek namens „Connexus“, die HTTP-Anfragen mit MQL5 erleichtern soll. Das Ziel dieses Projekts ist es, dem Endnutzer diese Möglichkeit zu bieten und zu zeigen, wie man diese Hilfsbibliothek verwendet. Ich wollte sie so einfach wie möglich gestalten, um das Studium zu erleichtern und die Möglichkeit für künftige Entwicklungen zu schaffen.