
MQL5-Assistenten-Techniken, die Sie kennen sollten (Teil 40): Parabolic SAR
Einführung
Wir setzen diese Serie fort, die sich mit den verschiedenen Handels-Setups und Ideen befasst, die dank des MQL5-Assistenten schnell ausgenutzt und getestet werden können. In den letzten beiden Artikeln haben wir uns auf die grundlegenden Indikatoren und Oszillatoren konzentriert, wie sie in den Assistenten-Klassen der IDE enthalten sind. Dabei nutzten wir die verschiedenen Muster, die jeder der betrachteten Indikatoren liefern kann, testeten sie unabhängig und optimierten sie auch für Einstellungen, die eine Auswahl mehrerer Muster verwenden, sodass wir die Testergebnisse unabhängiger Musterläufe mit einer kollektiven oder optimierten Einstellung vergleichen konnten.
Wir halten uns in diesem Artikel an dieses Format, in dem wir Muster für Muster für den parabolic SAR durchgehen, bevor wir mit einem Testlauf abschließen, der mehrere Muster kombiniert, wie wir es in den letzten Artikeln getan haben. Der parabolische SAR wird fast unabhängig von jedem neuen Balken berechnet, da einige der Parameter, die in seine Formel eingehen, angepasst werden müssen, wie wir weiter unten sehen werden. Diese Eigenschaft macht ihn jedoch sehr empfindlich für Preisänderungen und Trends im Allgemeinen, was wiederum für seine Verwendung innerhalb einer eigenen Signalklasse spricht. In diesem Artikel werden wir 10 verschiedene Muster dieses Indikators untersuchen, indem wir jedes unabhängig voneinander testen und dann, wie in den letzten Artikeln, mit einem Testlauf abschließen, der eine Auswahl dieser Muster kombiniert.
Der am Ende dieses Artikels beigefügte Quellcode soll in einem MQL5-Assistenten verwendet werden, um einen Expert Advisor zusammenzustellen, der ihn verwendet. Für neue Leser gibt es hier und hier eine Anleitung, wie man das macht.
Definition des Parabolic-SAR
Die parabolische SAR ist ein Puffer von Werten, die durch die Extremwerte des aktuellen Trends in zunehmenden Beträgen (oder Schritten) bis zu einem voreingestellten Schwellenwert verschoben werden. Das klingt vielleicht etwas langatmig, aber es ist einfach eine sehr dynamische Methode, um den aktuellen Trend anzuzeigen und Punkte zu kartieren, an denen sich der gegebene Trend umkehren könnte. Die parabolische SAR-Formel ist sehr fließend; sie unterscheidet sich bei Aufwärts- und Abwärtstrends. Für einen Aufwärtstrend gilt:
wobei:
- SAR n+1 ist der SAR-Wert für den nächsten Balkens.
- SAR n ist der aktuelle SAR-Wert.
- EP (Extreme Point) ist der höchste Preis im aktuellen Trend.
- α ist der Beschleunigungsfaktor (AF), der in der Regel bei 0,02 beginnt und bei jedem Erreichen eines neuen EP um 0,02 erhöht wird, mit einem Höchstwert von 0,20 (dies kann in den Nutzereinstellungen variiert werden).
Es ist auch erwähnenswert, dass in einem Aufwärtstrend:
- EP ist der höchste Stand seit Beginn des Trends.
- Der SAR-Wert wird bei fortgesetztem Trend ansteigen und sich an die Kursbewegung anpassen.
Und für einen Abwärtstrend gilt:
wobei:
- EP ist der niedrigste Preis im aktuellen Abwärtstrend.
Ebenso erwähnenswert ist, dass in einem Abwärtstrend:
- EP ist der tiefste Stand seit Beginn des Trends.
- Der SAR-Wert vermindert sich mit der Zeit und folgt so dem Abwärtstrend.
Wenn also ein Trend fortschreitet, wird der SAR durch die Zu- oder Abnahmen (im Falle einer Abwärtsbewegung) tendenziell in Richtung der Kurse komprimiert, was wiederum eine Trendwende oder einen Trendwechsel näher rückt. Die Umsetzung in MQL5 erfolgt durch integrierte Indikatoren und Standardbibliotheksklassen, sodass wir uns in diesem Artikel nur auf diese beziehen. Betrachten wir nun die verschiedenen Muster, die der SAR zu bieten hat.
Die Crossover-Lücke der Umkehr
Unser erstes Muster, 0, ist die Crossover-Lücke, bei dem die Indikatorpunkte des SAR die Seiten wechseln, entweder, im Falle einer Aufwärtslücke, von über den Kurshöchstständen zu unter den Tiefstständen oder, im Falle einer Abwärtslücke, von unter den Tiefstständen zu über den Höchstständen. Oft ist die Größe der Lücke zwischen den parabolischen SAR-Punkten und dem nächstgelegenen Kurspunkt (der bei einer Aufwärtslücke das Tief und bei einer Abwärtslücke das Hoch ist) ein Hinweis auf die Stärke des Signals. Je größer dieser Abstand ist, desto stärker ist der neue Trend.
Allerdings sollten auch die makroökonomischen Bedingungen des Marktes berücksichtigt werden, da diese Crossover-Lücke recht häufig vorkommen können, insbesondere bei sehr volatilen Märkten, was zu vielen Fehlsignalen führen würde. Auf Märkten mit geringer Volatilität sollte man sich also eher auf dieses Signal verlassen. In den Fällen, in denen der SAR bei der Stop-Loss-Anpassung verwendet wird, wird der Stop-Loss an diesen Kreuzungspunkten nicht geschlossen, sondern einfach näher an den SAR verschoben, wobei das tatsächliche Schließen und Umkehren der Position von einem anderen Signal abhängt.
Um unser Muster 0 zu implementieren, verwenden wir in unserer nutzerdefinierten Signalklasse die folgende Funktion:
//+------------------------------------------------------------------+ //| Check for Pattern 0. | //+------------------------------------------------------------------+ bool CSignalSAR::IsPattern_0(ENUM_POSITION_TYPE T) { if(T == POSITION_TYPE_BUY && Base(StartIndex() + 1) > High(StartIndex() + 1) && Base(StartIndex()) < Low(StartIndex())) { return(true); } else if(T == POSITION_TYPE_SELL && Base(StartIndex() + 1) < Low(StartIndex() + 1) && Base(StartIndex()) > High(StartIndex())) { return(true); } return(false); }
Und Testläufe für einen mit einem Assistenten zusammengestellten Expert Advisor, der ausschließlich das Muster 0 verwendet, führen zu den folgenden Ergebnissen:
SAR-Kompressionszone
Unser nächstes Muster ist die Kompressionszone, die wohl eine Verfeinerung von Muster 0 ist. Der Hauptunterschied besteht, wie der Name schon sagt, darin, dass vor der Umkehrung des SAR-Indikators eine Preiskompression (d. h. ein vorheriger Trend mit geringer Volatilität) vorliegen muss. Wie bereits erwähnt, zeigt der SAR an, welcher Trend gerade vorherrscht (Aufwärts- oder Abwärtstrend). Wenn also ein früherer Trend nur eine geringe Dynamik aufweist, kann dies als Kompression interpretiert werden. Die Quantifizierung von „vernachlässigbar“ könnte bedeuten, dass wir einen weiteren Eingabeparameter hinzufügen müssen, um diesen Wert zu definieren; wir entscheiden uns jedoch dafür, dies über eine Kompressionsfunktion wie folgt umzusetzen:
bool Compression(ENUM_POSITION_TYPE T, double &Out) { Out = 0.0; int _i = StartIndex() + 1, _c = 0; double _last = Base(StartIndex() + 1); double _first = 0.0; if ( T == POSITION_TYPE_BUY && Base(StartIndex()) < Low(StartIndex()) && Base(_i) < Close(StartIndex()) && Base(_i) > High(_i) ) { while(Base(_i) > High(_i) && _c < __COMPRESSION_LIMIT) { _first = Base(_i); _i++; _c++; } if(_c > 0) { Out = fabs(_first - _last)/_c; return(true); } } else if ( T == POSITION_TYPE_SELL && Base(StartIndex()) > High(StartIndex()) && Base(_i) > Close(StartIndex()) && Base(_i) < Low(_i) ) { while(Base(_i) < Low(_i) && _c < __COMPRESSION_LIMIT) { _first = Base(_i); _i++; _c++; } if(_c > 0) { Out = fabs(_first - _last)/_c; return(true); } } return(false); }
Dies wiederum bedeutet, dass unsere Muster-0-Funktion wie folgt gehandhabt wird:
//+------------------------------------------------------------------+ //| Check for Pattern 1. | //+------------------------------------------------------------------+ bool CSignalSAR::IsPattern_1(ENUM_POSITION_TYPE T) { double _compression = 0.0; if(Compression(T, _compression)) { if(T == POSITION_TYPE_BUY && _compression < 0.02*fabs(Base(StartIndex())-Low(StartIndex()))) { return(true); } else if(T == POSITION_TYPE_SELL && _compression < 0.02*fabs(Base(StartIndex())-High(StartIndex()))) { return(true); } } return(false); }
Diese Funktion gibt an, um wie viel die Indikatorwerte im vorherigen Trend angepasst wurden. Was wir als unseren Schwellenwert für die Definition von vernachlässigbar als Eingabe verwenden, ist das, was wir bereits als Eingabe haben, und dies ist die SAR-Schritteingabe. Wenn also ein Bruchteil des anfänglichen SAR-Abstands zum Preis größer ist als die mittlere Veränderung der SAR-Werte im vorangegangenen Trend, dann liegt eine Kompression vor. Und da die Bedingungen für dieses Muster einfach eine Kompression und eine Umkehrung des Trends sind, würden wir eine Position in Übereinstimmung mit den Bedingungen des Musters 0 Trendumkehr eröffnen, die wir bereits oben mitgeteilt haben. Das Testen mit dem von unserem Assistenten zusammengestellten Expert Advisor, ausschließlich für das Muster 1, führt zu den folgenden Ergebnissen:
Wir testen mit dem Symbol EURJPY für das Jahr 2023, auf dem täglichen Zeitrahmen. Da es sich um ein Kompressionsmuster handelt, das wir strikt durch die Begrenzung des Gesamttrends definiert haben, indem wir den Anfangsschritt als unseren Anteil verwenden, werden nicht viele Trades platziert. Dies kann jedoch durch die Einführung eines weiteren Parameters angepasst werden, um dies abzumildern. Die für dieses Muster verwendete Eingabe für die Musterverwendung ist 2.
Erweiterte Trending SAR
Bei diesem Muster handelt es sich um ein Fortsetzungsmuster, das in Fällen aufgegriffen werden kann, in denen die anfängliche Trendwende gedämpft war, beispielsweise in Fällen, in denen die SAR-Umkehrlücke zu Beginn sehr gering war. Ein Aufwärtsmuster wird durch die wachsende Lücke zwischen den SAR-Punkten angezeigt, während der SAR-Indikator unter den Tiefstkursen bleibt, und ein Abwärtssignal wird im umgekehrten Szenario angezeigt, wenn die Lücken zwischen den Punkten ebenfalls größer werden, während der SAR-Indikator über den Höchstkursen bleibt. Man könnte dies als Nachzügler bezeichnen, aber es ist immer besser, es erst einmal auszuprobieren, bevor man solche Schlüsse zieht. Wir implementieren dies wie folgt in MQL5:
//+------------------------------------------------------------------+ //| Check for Pattern 2. | //+------------------------------------------------------------------+ bool CSignalSAR::IsPattern_2(ENUM_POSITION_TYPE T) { if(T == POSITION_TYPE_BUY && Base(StartIndex()) - Base(StartIndex() + 1) > Base(StartIndex() + 1) - Base(StartIndex() + 2) && Base(StartIndex() + 1) - Base(StartIndex() + 2) > Base(StartIndex() + 2) - Base(StartIndex() + 3) && Base(StartIndex() + 2) - Base(StartIndex() + 3) > Base(StartIndex() + 3) - Base(StartIndex() + 4) ) { return(true); } else if(T == POSITION_TYPE_SELL && Base(StartIndex() + 1) - Base(StartIndex()) > Base(StartIndex() + 2) - Base(StartIndex() + 1) && Base(StartIndex() + 2) - Base(StartIndex() + 1) > Base(StartIndex() + 3) - Base(StartIndex() + 2) && Base(StartIndex() + 3) - Base(StartIndex() + 2) > Base(StartIndex() + 4) - Base(StartIndex() + 3) ) { return(true); } return(false); }
Und um nur auf dieses Muster 2 zu testen, würde wir das Eingabeschema für Muster 4 verwenden. Testen wir nur dieses Muster mit den gleichen Einstellungen wie oben, erhalten wir folgende Ergebnisse:
SAR falsche Umkehr
Wie der Name schon sagt, handelt es sich bei diesem Muster um einen Wechsel zu einem neuen Trend, der fast sofort wieder in den vorherigen Trend zurückfällt. Dies wird oft durch ein- oder zweipunktige Trends auf dem SAR-Kurschart angezeigt, wobei der Trend, der diesen Punkten folgt, während er sich auf der gegenüberliegenden Seite befindet, anzeigt, worauf sich Händler konzentrieren sollten. Bei einem Aufwärtssignal würde also ein regelmäßiger Aufwärtstrend folgen, gefolgt von einem Umschwung, der sich dadurch auszeichnet, dass er nur 1-2 Kursbalken andauert, und dann eine Wiederaufnahme des Aufwärtstrends erfolgt, wobei das Signal die Wiederaufnahme des Trends ist. In ähnlicher Weise würde das Abwärtsmuster mit einem Abwärtstrend beginnen, der kurzzeitig über ein oder zwei Kursbalken nach oben umschlägt, bevor es wieder abwärts geht. Wir würden dieses Muster wie folgt programmieren:
//+------------------------------------------------------------------+ //| Check for Pattern 3. | //+------------------------------------------------------------------+ bool CSignalSAR::IsPattern_3(ENUM_POSITION_TYPE T) { if(T == POSITION_TYPE_BUY && Base(StartIndex()) < Low(StartIndex()) && Base(StartIndex() + 1) > High(StartIndex() + 1) && Base(StartIndex() + 2) < Low(StartIndex() + 2)) { return(true); } else if(T == POSITION_TYPE_SELL && Base(StartIndex()) > High(StartIndex()) && Base(StartIndex() + 1) < Low(StartIndex() + 1) && Base(StartIndex() + 2) > High(StartIndex() + 2)) { return(true); } return(false); }
Da dies unser viertes Muster ist, das wir als Muster 3 indizieren, bedeutet dies, dass wir Handelsgeschäfte platzieren müssen, bei denen wir uns ausschließlich auf seine Signale verlassen. Die Testläufe mit ähnlichen Einstellungen wie oben für dieses Muster wurden während des Testzeitraums durchgeführt, und es wurden keine Positionen platziert, sodass keine Ergebnisse mitgeteilt werden können. Nichtsdestotrotz sind die häufigsten Ursachen für diese falsche Umkehr die üblichen Verdächtigen: unruhige Märkte, geringe Volatilität oder Marktstörungen. Die Auswirkungen auf unbedarfte Händler können drastisch sein, weshalb sekundäre Indikatoren (wie der MACD), die Preisaktionsanalyse (für Unterstützung und Widerstand) oder die Volumenanalyse (wenn diese Informationen verfügbar sind) dabei helfen können. Damit sollte dieses Signal zuverlässiger sein als ein einzige Umkehr, wie z. B. das Muster 0.
Doppeltee SAR-Umkehr mit Trendfortsetzung
Dieses Muster ist unser Muster 3 plus 2 weitere Umkehrungen. Es führt zu einer Fortsetzung wie bei Muster 3, und ebenso wie man argumentieren kann, dass Muster 3 stärker ist als Muster 0, ist dieses Muster, 4, zuverlässiger oder stärker als Muster 3. Wir haben eine Code-Implementierung dafür bereitgestellt (siehe unten), führen jedoch keine Tests dafür durch und überlassen es dem Leser, dies weiter zu erforschen, was idealerweise einen Testzeitraum über das von uns in Betracht gezogene 1-Jahres-Fenster hinaus erfordern sollte. Da im Jahr 2023 für EURJPY auf Tagesbasis keine Handelsgeschäfte für Muster 3 platziert wurden, erwarten wir keine Signale und somit auch keine Handelsgeschäfte für Muster 4.
//+------------------------------------------------------------------+ //| Check for Pattern 4. | //+------------------------------------------------------------------+ bool CSignalSAR::IsPattern_4(ENUM_POSITION_TYPE T) { if(T == POSITION_TYPE_BUY && Base(StartIndex()) < Low(StartIndex()) && Base(StartIndex() + 1) > High(StartIndex() + 1) && Base(StartIndex() + 2) < Low(StartIndex() + 2) && Base(StartIndex() + 3) > High(StartIndex() + 4) && Base(StartIndex() + 4) < Low(StartIndex() + 5) ) { return(true); } else if(T == POSITION_TYPE_SELL && Base(StartIndex()) > High(StartIndex()) && Base(StartIndex() + 1) < Low(StartIndex() + 1) && Base(StartIndex() + 2) > High(StartIndex() + 2) && Base(StartIndex() + 3) < Low(StartIndex() + 4) && Base(StartIndex() + 4) > High(StartIndex() + 5) ) { return(true); } return(false); }
SAR-Divergenz mit gleitendem Durchschnitt
Muster 5 ist auf eine Divergenz zurückzuführen. Da die Divergenzen zwischen den Kursen und dem SAR recht häufig sind, dient der gleitende Durchschnittsindikator als Bestätigung. Für ein Aufwärtssignal würde der Kurs also in Richtung des SAR fallen, während der SAR ebenfalls steigt und der gleitende Durchschnitt unter oder gleich dem SAR liegt. Umgekehrt würde der Kurs, bei einem fallenden SAR, steigen, wobei der gleitende Durchschnitt immer noch über oder gleich dem SAR liegt. Die Anzahl der Schritte, die erforderlich sind, um einen Anstieg oder ein Absinken zu messen, kann nach eigenem Ermessen (oder durch Tests) bestimmt werden, für unsere Zwecke nehmen wir jedoch einfach drei an. Wir implementieren daher die Funktion, die diese Muster aufruft, wie folgt:
//+------------------------------------------------------------------+ //| Check for Pattern 5. | //+------------------------------------------------------------------+ bool CSignalSAR::IsPattern_5(ENUM_POSITION_TYPE T) { if(T == POSITION_TYPE_BUY && MA(StartIndex()) <= Base(StartIndex()) && Base(StartIndex()) > Base(StartIndex() + 1) && Base(StartIndex() + 1) > Base(StartIndex() + 2) && Close(StartIndex()) < Close(StartIndex() + 1) && Close(StartIndex() + 1) < Close(StartIndex() + 2) ) { return(true); } else if(T == POSITION_TYPE_SELL && MA(StartIndex()) >= Base(StartIndex()) && Base(StartIndex()) < Base(StartIndex() + 1) && Base(StartIndex() + 1) < Base(StartIndex() + 2) && Close(StartIndex()) > Close(StartIndex() + 1) && Close(StartIndex() + 1) > Close(StartIndex() + 2) ) { return(true); } return(false); }
Ein Test unseres Expert Advisors, bei dem ausschließlich dieses Muster verwendet wird, ergibt folgende Ergebnisse:
Es ist erwähnenswert, dass wir es hier mit drei Datenpuffern zu tun haben, nämlich mit den Kursen, dem gleitenden Durchschnitt und dem SAR. Die von uns gewählte Abweichung von diesen Werten liegt zwischen den Kursen und dem SAR, es können jedoch auch andere Abweichungen, z. B. zwischen dem gleitenden Durchschnitt und dem SAR, in Betracht gezogen werden. Diese Divergenz ist jedoch aufgrund der verzögernden Wirkung des gleitenden Durchschnitts zwangsläufig ein Nachzügler im Vergleich zu der Preis-SAR-Divergenz, die wir für diesen Artikel implementiert haben. Auf der anderen Seite ist sie auch weniger störend, da die Kursentwicklung kurzfristig viel Bewegung erzeugt, die langfristig oft nicht ins Gewicht fällt. Es könnte also durchaus von Nutzen sein, und der Leser ist eingeladen, auch diesen Weg zu erkunden. Die Eingabe für die Musterverwendung für dieses Muster ist 32.
Parabolische SAR-Kanalisierung
Das Muster von parabolischem SAR und Preiskanälen verbindet die Kursbewegung mit dem aktuellen SAR-Trend, um Signale zu erzeugen. Preiskanäle sind auf einem Preischart relativ leicht zu verstehen, aber der Versuch, diese Logik in Code umzusetzen, ist oft komplizierter, als man zunächst denkt. Es könnte also eine gute Idee sein, eine rudimentäre Funktion zu definieren, die die aktuelle Ober- und Untergrenze eines Preiskanals festlegt, dessen Bereich durch die Anzahl der zu betrachtenden Preisbalken in der Historie bestimmt wird. Wir nennen diese Funktion „Channel“ (Kanal) und ihre Logik, die sich in der Schnittstelle befindet, wird im Folgenden erläutert:
bool Channel(ENUM_POSITION_TYPE T) { vector _max,_max_i; vector _min,_min_i; _max.Init(2); _max.Fill(High(0)); _max_i.Init(2); _max_i.Fill(0.0); _min.Init(2); _min.Fill(Low(0)); _min_i.Init(2); _min_i.Fill(0.0); for(int i=0;i<m_ma_period;i++) { if(High(i) > _max[0]) { _max[0] = High(i); _max_i[0] = i; } if(Low(i) < _min[0]) { _min[0] = Low(i); _min_i[0] = i; } } double _slope = (Close(0) - Close(m_ma_period-1))/m_ma_period; double _upper_scale = fabs(_slope); double _lower_scale = fabs(_slope); for(int i=0;i<m_ma_period;i++) { if(i == _max_i[0]) { continue; } else { double _i_slope = (High(i) - _max[0])/(i - _max_i[0]); if((_i_slope > 0.0 && _slope > 0.0)||(_i_slope < 0.0 && _slope < 0.0)) { if(fabs(_i_slope-_slope) < _upper_scale) { _max[1] = High(i); _max_i[1] = i; } } } } for(int i=0;i<m_ma_period;i++) { if(i == _min_i[0]) { continue; } else { double _i_slope = (Low(i) - _min[0])/(i - _min_i[0]); if((_i_slope > 0.0 && _slope > 0.0)||(_i_slope < 0.0 && _slope < 0.0)) { if(fabs(_i_slope-_slope) < _lower_scale) { _min[1] = Low(i); _min_i[1] = i; } } } } vector _projections; _projections.Init(4); _projections[0] = _max[0] + (_max_i[0]*_slope); _projections[1] = _min[0] + (_min_i[0]*_slope); _projections[2] = _max[1] + (_max_i[1]*_slope); _projections[3] = _min[1] + (_min_i[1]*_slope); if(T == POSITION_TYPE_BUY && Close(0) < Close(m_ma_period) && Close(0) < _projections.Mean()) { return(true); } else if(T == POSITION_TYPE_SELL && Close(0) > Close(m_ma_period) && Close(0) > _projections.Mean()) { return(true); } return(false); }
Die primären Ergebnisse dieses Kanals sind: Zeigt der Kanal bei einer bestimmten Position eine mögliche Umkehrung an? Und um diese Frage zu beantworten, müssen wir zunächst feststellen, welche Preispunkte die obere und die untere Linie definieren. So einfach es ist, ein normales Kurschart zu erkennen, so leicht kann man sich im Code dazu verleiten lassen, sich auf Fraktale zu verlassen. Und obwohl dies funktionieren könnte, wenn der verwendete fraktale Indikator wirklich gut ist, habe ich festgestellt, dass die Konzentration auf die Gesamtneigung des gegebenen Rückblickzeitraums eine besser verallgemeinerbare Lösung bietet.
Um also unseren Kanal zu definieren, müssen wir uns zunächst ein Bild von der Steigung über den Rückblickzeitraum machen. Unser Rückblickszeitraum entspricht dem Zeitraum, den der Indikator für den gleitenden Durchschnitt verwendet, der in Muster 5 oben hervorgehoben wurde. Die Leser können ihre eigenen sekundären Parameter erstellen, um dies zu definieren, aber ich bin immer der Meinung, dass das Modell umso verallgemeinerbarer ist, je weniger Eingabeparameter es hat. Sobald wir also die Steigung haben, müssen wir die beiden Höchststände im definierten Rückblickszeitraum ermitteln, die am besten mit dieser Steigung übereinstimmen.
Normalerweise wird jedoch erwartet, dass der höchste Punkt im Rückblickzeitraum immer entlang dieser oberen Linie des Kanals liegt. Wenn wir also mit der Ermittlung dieses Maximalwerts beginnen, müssen wir anschließend alle anderen Höchstwerte durchgehen, bis wir auf einen zweiten, hohen Wert stoßen, dessen Steigung von unserem höchsten Punkt aus am ehesten mit der Steigung des Gesamttrends übereinstimmt. Hier ist der Gesamttrend natürlich die Veränderung des Schlusskurses über den gesamten Rückblickzeitraum.
Sobald wir diese beiden Punkte haben, würden wir dasselbe für die untere Begrenzung des Kanals tun, indem wir den niedrigsten Tiefpunkt und einen weiteren Tiefpunkt finden, der am besten mit der Neigung des Trends übereinstimmt, wenn er mit dem niedrigsten Punkt verbunden ist. Zwei Punktpaare definieren zwei Linien, und damit haben Sie einen Kanal, der ausschließlich auf der Rückblickperiode basiert. Bei der Betrachtung eines Preischarts wird man sicherlich nicht so mechanistisch vorgehen, da es unwahrscheinlich ist, dass ein fester Rückblick immer genügend Datenpunkte enthält, um dies zu definieren. Aus diesem Grund führt die einfache Verknüpfung dieser Punkte und der Versuch, sie zu extrapolieren, zwangsläufig zu einer Menge wilder oder zufälliger Kanäle. Ein fester Rückblick erfasst oft nicht alle für die Analyse wichtigen historischen Kurspunkte.
Deshalb definieren wir unseren Kanal so, dass er zwei und nicht nur eine obere und untere Begrenzungslinie hat. Jede dieser Linien würde durch die 4 Punkte verlaufen, die wir bereits oben definiert haben. Unser Aufwärtssignal mit Muster 6 besteht darin, dass sich der Kurs in der unteren Hälfte des Kanals befindet, wobei der parabolische SAR ebenfalls auf einen Aufwärtstrend hindeutet. Im umgekehrten Fall würde sich der Kurs in der oberen Hälfte des Kanals befinden, wobei der SAR einen Abwärtstrend anzeigt. Um festzustellen, in welcher Hälfte des Kanals sich unser aktueller Kurs befindet, nehmen wir einfach den Mittelwert aller vier projizierten Kurspunkte. Diese Projektionen sind einfach Verlängerungen der Linien, die durch unsere beiden Hoch- und Tiefpunkte bis zum aktuellen Index verlaufen, wobei die gleiche Steigung des Gesamttrends beibehalten wird. Wir implementieren dieses Muster wie folgt in MQL5:
//+------------------------------------------------------------------+ //| Check for Pattern 6. | //+------------------------------------------------------------------+ bool CSignalSAR::IsPattern_6(ENUM_POSITION_TYPE T) { if(T == POSITION_TYPE_BUY && Base(StartIndex()) < Low(StartIndex())) { return(Channel(T)); } else if(T == POSITION_TYPE_SELL && Base(StartIndex()) > High(StartIndex())) { return(Channel(T)); } return(false); }
Und das Testen mit den gleichen Einstellungen, die wir oben für EURJPY auf dem Tageskurs für 2023 verwenden, liefert uns folgende Ergebnisse:
Die Eingabe für die Musterverwendung für dieses Muster ist 64.
Schlussfolgerung
Wir haben uns 7 der 10 möglichen Muster des parabolischen SAR angesehen und belassen es vorerst dabei, damit dieser Beitrag nicht so langatmig wird. Die Muster, die wir im Folgeartikel betrachten werden, sind parabolische SAR- und Volumendivergenz, invertierter SAR auf einem höheren Zeitrahmen und SAR- und RSI-Überschneidung. Jedes der in diesem Artikel bereits behandelten Muster kann weiter genutzt und auf verschiedene Weise und in verschiedenen Formaten implementiert werden. Für diesen Artikel und die letzten beiden ähnlichen Artikel verlassen wir uns auf die eingebauten Mustermethoden der Signalklassendatei, von der unsere nutzerdefinierte Signalklasse erbt. In den letzten beiden Artikeln haben wir einen Parameter „m_patterns_used“ deklariert und verwendet, der doppelt und überflüssig war, weil unsere übergeordnete Klasse bereits den Parameter „m_patterns_usage“ hat. Letzteres minimiert unsere Kodierungsanforderungen und liefert, wenn es verwendet wird, auch präzisere Ergebnisse, da die tatsächliche Eingabekarte richtig verwendet wird.
Die Leser sollten dies nicht tun und den Code, der diesen beiden aktuellen Artikeln beigefügt ist, entsprechend ändern. Außerdem ist zu beachten, dass die Implementierung von Preiskanälen in Expert Advisors nicht sehr verbreitet ist, weshalb ich in einem unabhängigen Beitrag untersuchen könnte, wie dies auch eine Signalklasse sein könnte. Während das visuelle Lesen eines Preischarts mit einem Kanal einfach ist, weil die Definitionspunkte der oberen und unteren Grenze visuell leicht identifiziert werden können, ist dies im Code nicht dasselbe, sodass wir dies in einem zukünftigen Artikel ebenfalls berücksichtigen werden.
Schließlich machen wir in diesen Musterserien etwas, das einigen der integrierten Signale, die in der Standardbibliothek enthalten sind, gegen den Strich geht. Wir optimieren die idealen Schwellenwertbedingungen für jedes Muster. Dies widerspricht der Konvention, dass der Händler diese Schwellenwerte aufgrund seiner eigenen Erfahrungen und Beobachtungen beim Umgang mit den Indikatoren vorgibt. Unsere Testergebnisse scheinen zwar vielversprechend zu sein, weil wir mehrere Muster verwenden, aber man kann argumentieren, dass sie schwieriger zu verallgemeinern und daher kreuzvalidiert sind. Es könnte daher empfohlen werden, dass diese Schwellenwertgewichte vom Händlern im Voraus zugewiesen werden, falls mehrere Muster verwendet werden sollen. Wenn nur ein einziges Muster verwendet werden soll, was wir, wie in einem früheren Artikel, in dem die Input-Map-Werte für jedes einzelne Muster aufgeführt sind, erläutert wurde, durchaus in Betracht ziehen können, könnte eine Optimierung nur für diesen Schwellenwert vorgenommen werden.
Übersetzt aus dem Englischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/en/articles/15887





- Freie Handelsapplikationen
- Über 8.000 Signale zum Kopieren
- Wirtschaftsnachrichten für die Lage an den Finanzmärkte
Sie stimmen der Website-Richtlinie und den Nutzungsbedingungen zu.