English Русский 中文 Español 日本語 Português
Universeller Trend mit grafischem Interface

Universeller Trend mit grafischem Interface

MetaTrader 5Beispiele | 5 Mai 2017, 12:56
1 298 0
Dmitry Fedoseev
Dmitry Fedoseev
Universeller Trend mit grafischem Interface

Inhalt

Einführung

Zwei frühere Artikel beschreiben wie man einen universellen Oszillator mit einem grafischen Interface erstellt, und wie man auf dieser Basis einen universellen Kanal entwickelt.  

Ein universeller Trendindikator kann auch auf Basis des universellen Oszillators erstellt werden. Um aber Wiederholungen zu vermeiden, verwenden wir einen etwas anderen Weg. Einige finden vielleicht Gefallen an diesem, neuen Weg.

Für den universellen Oszillator und den universellen Kanal wurden alle Elemente als Klassen über automatische Pointer erstellt, und die Sichtbarkeit und Positionierung durch weitere Klassen gehandhabt. Jetzt erstellen wir ein universelles, mehrteiliges Bedienelement nach den Prinzipien, wie sie in der Serie "Benutzerdefinierte grafische Bedienelemente" (Artikel 1, Artikel 2, Artikel 3) beschrieben werden. Es werden jedoch nur die Methoden entwickelt, die für diesen Artikel benötigt werden. 

Indikatortypen

Wir werden uns nicht nur auf die Indikatoren beschränken, die traditionell als Trendindikatoren erachtet werden. Jeder Indikator, der auf der Preisrichtung beruht (gleitende Durchschnitte, der RSI und andere) kann für die Bestimmung sowohl der Positionseröffnung wie der Trendrichtung verwendet werden. Ist der Preis zum Beispiel über dem gleitenden Durchschnitt, können wir einen Aufwärtstrend annehmen und umgekehrt (Fig. 1).


Fig. 1. Preis und gleitender Durchschnitt zur Trendbestimmung. Blaue Aufwärtspfeile deuten auf Kaufgelegenheiten
(der Preis ist über dem MA), rote Abwärtspfeile auf Verkaufsgelegenheiten (der Preis ist unter dem MA).

Die Steigung eines MA kann auf ähnliche Weise verwendet werden: steigend — Aufwärtstrend, fallend — Abwärtstrend (Fig. 2).

 
Fig. 2. Die Steigung als Trendindikator. Blaue Aufwärtspfeile deuten auf Kaufgelegenheiten
(der MA steigt), rote Abwärtspfeile
auf Verkaufsgelegenheiten (der MA fällt)

Wurde eine Bar ermittelt, die den MA kreuzt (Der Schlusskurs einer Bar ist unter dem MA, der der nächsten über ihm), entsteht so durch den gleitende Durchschnitt eine Eröffungsgelegenheit. In diesem Fall existiert das Handelssignal für die Dauer der Bar (Fig. 3). 

 
Fig. 3. Der gleitenden Durchschnitt zur Bestimmung der Positionseröffnung. Blaue Aufwärtspfeile zeigen Kaufgelegenheiten
(der Preis einer Bar ist unter dem MA, der der nächsten darüber), rote Abwärtspfeile
zeigen
Verkaufsgelegenheiten 
(der Preis der einen Bar ist über dem MA, der der nächsten darunter)

Die Steigung des MA kann ähnlich genutzt werden: Bars mit einer Umkehr der Steigung sind Einstiegspunkte (Fig. 4). 

 
Fig. 4. Die Steigung eines gleitenden Durchschnitts zur Bestimmung der Positionseröffnung. Blaue Aufwärtspfeile zeigen Kaufgelegenheiten
(lokales Minimum des MA), rote Abwärtspfeile ´zeigen Verkaufsgelegenheiten (lokales Maximum des MA)

In diesem Artikel befassen wir uns mit den Möglichkeiten, einen Trend zu bestimmen (siehe Fig. 1 und Fig. 2). Das Ermitteln von Einstigsgelegenheiten sind hier nur zum besseren Verständnis und der Vollständigkeit halber aufgeführt.   

Auch Oszillatoren werden zum Bestimmen von Einstiegspunkten verwendet, meistens durch das Kreuzen bestimmter Level, z.B. RSI (Fig. 5). Es gibt mindesten zwei Möglichkeiten, den Stochastik Oszillator für Einstiegspunkte zu verwenden: Das Kreuzen eines Levels oder das Kreuzen der Hauptlinie mit einer Signallinie.  

 
Fig. 5. Einstiegspunkte auf Basis des RSI Indikators. Blaue Pfeile zeigen Kaufsignale (Kreuzen des Levels von
70 aufwärts), rote Pfeile zeigen Verkaufssignale (Kreuzen des Levels von 30 nach unten)

Fragen wir uns, wie Oszillatoren einen Trend identifizieren können. Die Antwort ist für die Stochastik eindeutig: Auf Basis der Lage von Haupt- und Signallinie, und zwar ist die Hauptlinie über der Signallinie, kann man kaufen, ist sie darunter — verkaufen (Fig. 6).


Fig. 6. Die Lage von Haupt- und Signallinie des Stochastik Oszillators zur Trendbestimmung. Die blauen Pfeile zeigen
einen Aufwärtstrend (Hauptlinie über der Signallinie), rote Pfeile einen Abwärtstrend (Hauptlinie unter der Signallinie)

Ähnlich die Verwendung von Level: Ist der Oszillator über einem bestimmten Level, kaufen, ist sie darunter — verkaufen (Fig. 7).

 
Fig. 7. Die Verwendung des RSI-Oszillators mittels Levels zur Trendbestimmung. Blaue Pfeile zeigen den Aufwärtstrend 
(RSI über 60), rote Pfeile einen Abwärtstrend (RSI unter 40)
 

Trendanzeige

Finden wir den bequemsten Weg, einen Trend anzuzeigen. Die allererste Idee ist einfach eine Linie zu zeichnen, deren Farbe mit dem Trend wechselt. Betrachten wir die Trendbestimmung durch RSI und die Level von 60 und 40. Ist die Linie des RSI über 60, können wir kaufen, ist sie unter 40, verkaufen (Fig. 7). Im Falle, dass der der RSI zwischen 40 und 60 ist, können wir weder kaufen noch verkaufen. Vertauschen wir nun beide Level: Der Level für Kaufen ist nun 40 (wir können kaufen, wenn die Werte größer 40 sind), und der Verkaufslevel ist nun 60 (verkaufen, wenn unter 60). In diesem Fall könnten wir, wenn die Werte zwischen 40 und 60 liegen, sowohl kaufen wie verkaufen (Fig. 8).

 
Fig. 8. Trendbestimmung mittels des RSI-Oszillators. Der Kauflevel steht auf 40, der für Verkauf auf 60.
Jetzt gibt es eine Zone, in der ge- und verkauft werden kann (es existieren blaue und rote Pfeile).

Daraus folgt, dass der Trend in zwei unabhängigen Datengruppen angezeigt werden müssten. Wir verwenden zwei Indikatorpuffer: einer ist etwas nach oben geschoben worden, der andere etwas nach unten (so können beide Puffer zugleich angezeigt werden). Da die Puffer nicht ständig Daten anzeigen, ist es besser Icons oder eine Histogramm zu verwenden. Wählen wir zunächst die Icons. In diesem Fall können wir, zusätzlich zu den unterschiedlichen Farben für die Puffer, verschiedene Icons verwenden. Fig. 9 zeigt wie der Indikator jetzt aussieht.

 
Fig. 9. Ein bequemer Weg, einen Trend anzuzeigen

Diese Methode zur Trenddarstellung erhöht die Anzahl der darstellbaren Indikatoren. So können zum Beispiel Indikatoren angezeigt werden, die nicht von der Trendrichtung abhängen, sondern nur in bestimmtem Zeitspannen das Handeln erlauben oder verbieten. So können wir zum Beispiel den ATRoder STD verwenden. Sind ihre Werte über einem jeweiligen Schwellwert, werden beide Pfeile (auf- und abwärts) angezeigt. So wird der universelle Indikator noch universeller.   

Verwendete Indikatoren

Bevor wir aber mit dem Erstellen des universellen Trendindikators beginnen, definieren wir die Liste der Indikatoren für die Bestimmung des Trends. Damit ergeben sich auch die die externen Parameter (Werte und Typen der Variablen). Natürlich können nicht alle Möglichkeiten durch einen Indikator erfasst werden — es wären einfach zu viele. Selbst ein gleitender Durchschnitt kann auf zwei Arten verwendet werden. Mehr noch, es könnten zwei gleitenden Durchschnitte verwendet werden. Es muss daher eine einfache Möglichkeit angeboten werden, die Daten der Initialisierung anzupassen.

Einige Indikatoren verwenden identische Optionen, obwohl das auf den ersten Blick nicht immer so aussieht. Wenn Sie zum Beispiel zur Trendbestimmung zwei MAs verwenden (schnell und langsam), wird eine Trendbestimmung auf Basis von MA und Preis überflüssig. Setzen wir die Periodenlänge des schnellen MA auf 1, dann entspricht der MA dem Preis. Daher sollte jeder Indikator individuell behandelt werden. Darüber hinaus ist es notwendig, jede Variante von jedem Indikator zu berücksichtigen.

iAC (Accelerator Oscillator)

Der Indikator hat keine eigenen Parameter, er ist identisch mit dem OsMA mit bestimmten Parametern, wir werden ihn daher übergehen.  

iAD (Accumulation/Distribution)

Ein sehr spezifischer Indikator. Die Breite der Indikatorwerte ist nicht festgelegt, seine Linie ist nicht kontinuierlich und er eignet sich ohne zusätzliche Maßnahmen (z.B. Glättung) nicht zur Trendbestimmung. Er wird nicht verwendet. 

iADX (Average Directional Index)

Variante 1. Die Lage der Linien von PDI und MDI. PDI über MDI — Abwärtstrend, PDI unter MDI — Abwärtstrend.

Parameter

  1. int adx_period. 

Variante 2. Ist Richtungsunabhängig. Die Linie des ADX relativ zur Lage einen bestimmten Levels. ADX über dem Level — Kauf und Verkauf ist erlaubt. Zusätzlich zu den Parametern des Indikators, benötigen wir einen weiteren zur Angabe des Levels. 

 Parameter:

  1. int adx_period — Periodenlänge;
  2. double level — Wert des Levels. 

iADXWilder (Average Directional Index by Welles Wilder)

Ähnlich dem ADX.

iAlligator (Alligator)

Der Indikator besteht aus drei gleitenden Durchschnitten mit unterschiedlichen Periodenlängen und Versatz. Es gibt viele Möglichkeiten, diesem Indikator zu verwenden. Wir verwenden allerdings nur eine.

Variante 1. Die schnelle Linie (Lippen) ist über der mittleren (Zähne), die mittlere über der langsamen (Kinn) — Aufwärtstrend, liegen die Linien in einer umgekehrten Reihenfolge vor, — Abwärtstrend.   

Parameter

    1. int jaw_period — Periodenlänge der Linie des Kinns; 
    2. int jaw_shift — Versatz der Linie des Kinns; 
    3. int teeth_period — Periodenlänge der Linie der Zähne;
    4. int teeth_shift — Versatz der Linie der Zähne; 
    5. int lips_period — Periodenlänge der Linie der Lippen; 
    6. int lips_shift — Versatz der Linie der Lippen;
    7. ENUM_MA_METHOD ma_method — Typ der Glättung; 
    8. ENUM_APPLIED_PRICE applied_price — Preistyp.

iAMA (Adaptive Moving Average)

Der Indikator ist ein gleitender Durchschnitt. Wir werden zwei Varianten der Anwendung für alle MAs.

Variante 1. Steigung der Linie. Zusätzlich zu den Standardparametern der Indikatoren, benötigen wir einen weiteren Parameter, der einen zweiten Bezugspunkt des Indikators zur Bestimmung der Steigung festlegt. 

Parameter

    1. int ama_period — AMA Periodenlänge; 
    2. int fast_ma_period — Periodenlänge des schnellen, gleitenden Durchschnitts;
    3. int slow_ma_period — Periodenlänge des langsamen, gleitenden Durchschnitts; 
    4. int ama_shift — horizontaler Versatz des Indikators; 
    5. ENUM_APPLIED_PRICE  applied_price — Preistyp;
    6. int shift2 — Abstand des Punktes zur Bestimmung der Steigung.

Variante 2. Zwei Linien: schnell und langsam. Ist die erste Linie über der langsamen — Aufwärtstrend, die schnell unter der langsamen — Abwärtstrend. Zwei identische Sätze von Parametern werden benötigt. 

Parameter

    1. int ama_period1 — AMA Periodenlänge; 
    2. int fast_ma_period1 — Periodenlänge des schnellen, gleitenden Durchschnitts;
    3. int slow_ma_period1 — Periodenlänge des langsamen, gleitenden Durchschnitts; 
    4. int ama_shift1 — horizontaler Versatz des Indikators; 
    5. ENUM_APPLIED_PRICE  applied_price1 — Preistyp;
    6. int ama_period2 — AMA Periodenlänge; 
    7. int fast_ma_period2 — Periodenlänge des schnellen, gleitenden Durchschnitts;
    8. int slow_ma_period2 — Periodenlänge des langsamen, gleitenden Durchschnitts; 
    9. int ama_shift2 — horizontaler Versatz des Indikators; 
    10. ENUM_APPLIED_PRICE  applied_price2 — Preistyp.
Hinweis: Variablen der schnellen Linie enden mit 1, die der langsamen mit 2.


Der Indikator hat keine Parameter, er ist identisch mit dem MACD-Indikator mit bestimmten Parametern, er wird nicht verwendet.   

iATR (Average True Range)

Dieser Indikator hängt nicht von einer Richtung ab, wir verwenden eine Variante.

Variante 1: Richtungsunabhängig. Die Lage der Linie des ATR relativ zu einem Level. ATR über dem Level — kaufen und verkaufen sind erlaubt. Zusätzlich zu den Parametern des Indikators, benötigen wir einen weiteren zur Angabe des Levels. 

 Parameter:

  1. int ma_period — Periodenlänge;
  2. double level — Wert des Levels.  

iBearsPower (Bears Power) und iBullsPower (Bulls Power)

Die Indikatoren BearsPower und BullsPower sind nicht symmetrisch, d.h. sie müssen beide verwendet werden: einer für die Kaufsignale, der andere für die zum Verkaufen. Wir verwenden BullsPower für den Aufwärtstrend und BearsPower für den Abwärtstrend. Wir verwenden zwei Varianten: die relative Lage des Indikators zu einem Level und die Steigung.

Variante 1. Ist BullsPower über dem Level — ist Kaufen erlaubt, ist BearsPower unter demselben Level — ist Verkaufen erlaubt. Zusätzlich zu den Standardparametern benötigen wir den Wert des Levels.

Parameter:

    1. int ma_period — Periodenlänge;
    2. double level — Wert des Levels.   

Variante 2. Die Richtung des Indikators. Für diese Variante benötigen wir einen weiteren Parameter, der einen zweiten Bezugspunkt des Indikators zur Bestimmung der Steigung festlegt.

Parameter:

    1. int ma_period — Periodenlänge;
    2. int shift2 — Abstand des zweiten Punktes.   

iBands (Bollinger Bands)

Dieser bildet einen Kanal.

Variante 1. Kreuzt der Preis die obere Linie nach oben, beginnt ein Aufwärtstrend; kreuzt der Preis die Mittellinie nach unten ist der Aufwärtstrend beendet. Der Indikator funktioniert ähnlich in die andere Richtung mit der unteren Linie und dem Abwärtstrend.  

Parameter:

    1. int bands_period — Periodenlänge der Mittellinie;
    2. int bands_shift — horizontaler Versatz des Indikators; 
    3. double — Zahl der Standardabweichungen; 
    4. ENUM_APPLIED_PRICE  applied_price — Preistyp.

iCCI (Commodity Channel Index)

Der Indikator ist ein Oszillator in einem eigenen Fenster. Die Linie des Indikators ist stark unterbrochen, selbst bei längeren Periodenlängen, wir verwenden ihn daher ohne seine Steigung.

Variante 1. Position relativ zum Level. Ist der Indikatorwert über dem Level — Aufwärtstrend, ist er kleiner als der negative Werte des Levels — Abwärtstrend. 

Parameter:

    1. int ma_period — Glättungslänge; 
    2. ENUM_APPLIED_PRICE  applied_price — Preistyp oder handle;  
    3. double level — Wert des Levels.   

iChaikin (Chaikin Oscillator)

Der Indikator ist ähnlich dem CCI.

Variante 1. Position relativ zum Level. Ist der Indikatorwert über dem Level — Aufwärtstrend, ist er kleiner als der negative Werte des Levels — Abwärtstrend. 

Parameter:

    1. int fast_ma_period — schnelle Periodenlänge;  
    2. int ow_ma_period — langsame Periodenlänge; 
    3. ENUM_MA_METHOD ma_method — Typ der Glättung; 
    4. ENUM_APPLIED_VOLUME  applied_volume — verwendetes Volumen; 
    5. double level — Wert des Levels. 

iDEMA (Double Exponential Moving Average)

Der Indikator ist ein gleitender Durchschnitt und wird ähnlich dem oben beschriebenen AMA verwendet.

Variante 1. Steigung der Linie. 

Parameter

    1. int ma_period — Glättungslänge;
    2. ENUM_APPLIED_PRICE  applied_price — Preistyp;
    3. int ma_shift — horizontaler Versatz des Indikators; 
    4. int shift2 — Abstand des Punktes zur Bestimmung der Steigung.

Variante 2. Zwei Linien: schnell und langsam.

Parameter

    1. int ma_period1 — Glättungslänge;
    2. ENUM_APPLIED_PRICE  applied_price1 — Preistyp;
    3. int ma_shift1 — horizontaler Versatz des Indikators; 
    4. int ma_period2 — Glättungslänge;
    5. ENUM_APPLIED_PRICE  applied_price2 — Preistyp;
    6. int ma_shift2 — horizontaler Versatz des Indikators.
Hinweis: Variablen der schnellen Linie enden mit 1, die der langsamen mit 2. 

iDeMarker (DeMarker)

Der Indikator ist ein Oszillator in einem eigenen Fenster mit einem Bereich zwischen 0 und 1. Der Neutralwert des Indikators liegt bei 0,5. Die Linie des Indikators ist sehr unruhig, so dass dessen Steigung nicht verwendbar ist.

Variante 1. Position relativ zum Level. Das Verkaufslevel wird über die Parameter gesetzt, das Kauflevel wird dazu symmetrisch zum Wert von 0,5 berechnet. 

Parameter:

  1. int ma_period — Glättungslänge;
  2. double level — Verkaufslevel.

iEnvelopes (Envelopes)

Der Indikator bildet einen Kanal ähnlich den Bollinger Bänder, nur ist seine Verwendung einfacher.

Variante 1. Ist der Preis höher als die Obergrenze des Kanals, ist Kaufen erlaubt. Ist er unter der Untergrenze, ist Verkaufen erlaubt.  

Parameter:

  1. int ma_period — Periodenlänge der Mittellinie;
  2. int ma_shift — horizontaler Versatz des Indikators; 
  3. ENUM_MA_METHOD ma_method — Typ der Glättung;
  4. ENUM_APPLIED_PRICE applied_price — Preistyp; 
  5. double deviation — Abweichung der Kanalgrenzen von der Mittellinie.  

iForce (Force Index)

Der Indikator ist ein Oszillator in einem eigenen Fenster mit einem Bereich um 0. Der Indikator ist ähnlich dem CCI.

Variante 1. Position relativ zum Level. 

Parameter: 

  1. int ma_period — Glättungslänge; 
  2. ENUM_MA_METHOD ma_method — Typ der Glättung; 
  3. ENUM_APPLIED_VOLUME applied_volume — Volumenstyp für die Berechnung;
  4. double level — Wert des Levels.    

iFractals (Fractals)

Der Indikator hat keine Parameter.

Variante 1. Verwendung erfolgt auf Grund des letzten Fraktals. War das letzte Fraktal ein Maximum, ist Verkaufen erlaubt. Ist es ein Minimum — Kaufen ist erlaubt.  

iFrAMA (Fractal Adaptive Moving Average)

Der Indikator ist ein gleitender Durchschnitt. Seine Verwendung ist ähnlich der des AMA. 

Variante 1. Steigung der Linie. 

Parameter

  1. int ma_period — Glättungslänge; 
  2. int ma_shift — horizontaler Versatz des Indikators; 
  3. ENUM_APPLIED_PRICE  applied_price — Preistyp;
  4. int shift2 — Abstand des Punktes zur Bestimmung der Steigung.

Variante 2. Zwei Linien: schnell und langsam.

Parameter

    1. int ma_period1 — Glättungslänge; 
    2. int ma_shift1 — horizontaler Versatz des Indikators; 
    3. ENUM_APPLIED_PRICE  applied_price1 — Preistyp;
    4. int ma_period2 — Glättungslänge; 
    5. int ma_shift2 — horizontaler Versatz des Indikators; 
    6. ENUM_APPLIED_PRICE  applied_price2 — Preistyp.
Hinweis: Variablen der schnellen Linie enden mit 1, die der langsamen mit 2. 

iGator (Gator Oscillator)

Der Indikator berechnet sich auf Basis des Alligator-Indikators. Die Information dieses Indikators kann auch über den Alligator erhalten werden, wir werden ihn daher nicht einbeziehen. 

iIchimoku (Ichimoku Kinko Hyo)

Die folgenden Linien des Indikators könnten interessant sein: Tenkan Kijun und die Wolke. In der Wolke können wir zwei Linie mit wechselnden Positionen definieren (mal ist die eine oben, mal die andere). Es gibt zwei Varianten des Indikators.

Variante 1. Die Position der Linien von Tenkan und Kijun. Ist die Linie des Tenkan (rot) über der Linie des Kijun (blau), haben wir einen Aufwärtstrend. Ist der Tenkan unter dem Kijun — gibt es einen Abwärtstrend.

Parameter: 

    1. int tenkan_sen — Periodenlänge der Tenkan-sen-Linie; 
    2. int kijun_sen — Periodenlänge der Kijun-sen-Linie; 
    3. int senkou_span_b — Periodenlänge des Senkou Span B.  

Variante 2. Auf Basis der Richtung der Wolke. Die Wolke wird duch zwei Linie definiert: SpanA und SpanB. Ist SpanA über SpanB — Aufwärtstrend, anders herum — Abwärtstrend.

Parameter: 

    1. int tenkan_sen — Periodenlänge der Tenkan-sen-Linie; 
    2. int kijun_sen — Periodenlänge der Kijun-sen-Linie; 
    3. int senkou_span_b — Periodenlänge des Senkou Span B.  

Wir werden diesen Indikator nicht verwenden, da er sehr spezifisch ist. 

iMomentum (Momentum)

Der Indikator ist ein Oszillator in einem eigenen Fenster. Die Linie des Indikators ist sehr unruhig, so dass dessen Steigung nicht verwendbar ist. Es wird aber die Version mit Level verwendet.

Variante 1. Level. Neutraler Level: 100. Zusätzlich zu den Standardparametern benötigen wir den Wert eines Verkaufslevels. Der Kauflevel berechnet sich symmetrisch zum neutralen Level von 100.

Parameter:

    1. int mom_period — Glättungslänge; 
    2. ENUM_APPLIED_PRICE applied_price — Preistyp oder handle;
    3. double level — Verkaufslevel.  

iMFI (Money Flow Index)

Der Indikator ist ein Oszillator in einem eigenen Fenster mit einem Bereich zwischen 0 und 100. Neutraler Level: 50. Die Linie des Indikators ist sehr unruhig, so dass dessen Steigung nicht verwendbar ist.

Variante 1. Mit Level. Zusätzlich zu den Standardparametern benötigen wir den Wert eines Verkaufslevels. Der Kauflevel berechnet sich symmetrisch zum neutralen Level von 50. Ist die Indikatorlinie über dem Kauflevel — Aufwärtstrend, ist sie unter dem Verkaufslevel — Abwärtstrend. 

Parameter: 

    1. int ma_period — Glättungslänge;
    2. ENUM_APPLIED_VOLUME applied_volume — Volumenstyp für die Berechnung;
    3. double level — Verkaufslevel.  

iMA (Moving Average)

Das ist eine einfacher, gleitender Durchschnitt.

Variante 1. Steigung der Linie.

Parameter

    1. int ma_period — Glättungslänge; 
    2. int ma_shift — horizontaler Versatz des Indikators; 
    3. ENUM_MA_METHOD ma_method — Typ der Glättung; 
    4. ENUM_APPLIED_PRICE applied_price — Preistyp;
    5. int shift2 — Abstand des Punktes zur Bestimmung der Steigung.

Variante 2. Zwei Linien: schnell und langsam.

Parameter

  1. int ma_period1 — Glättungslänge; 
  2. int ma_shift1 — horizontaler Versatz des Indikators; 
  3. ENUM_MA_METHOD ma_method1 — Typ der Glättung; 
  4. ENUM_APPLIED_PRICE applied_price1 — Preistyp;
  5. int ma_period2 — Glättungslänge; 
  6. int ma_shift2 — horizontaler Versatz des Indikators; 
  7. ENUM_MA_METHOD ma_method2 — Typ der Glättung; 
  8. ENUM_APPLIED_PRICE applied_price2 — Preistyp.
Hinweis: Variablen der schnellen Linie enden mit 1, die der langsamen mit 2. 


iOsMA (Moving Average of Oscillator (MACD histogram)

Der OsMA Oszillator ist ein Histogramm in einem eigenen Fenster. Zwei Varianten sind möglich: Auf Basis von Level und Richtung.

Variante 1. Mit Level. Ist das Histogramm über dem Level, ist Kaufen erlaubt, ist es unter dem negativen Wert dieses Levels — ist Verkaufen erlaubt.

Parameter: 

  1. int fast_ema_period — Periodenlänge des schnellen, gleitenden Durchschnitts; 
  2. int slow_ema_period — Periodenlänge des langsamen, gleitenden Durchschnitts; 
  3. int signal_period — Glättungslänge der Signallinie;
  4. ENUM_APPLIED_PRICE  applied_price — Preistyp oder handle; 
  5. double level — Wert des Levels.

Variante 2. Auf Basis der Richtung. Ist die Richtung des Histogramms aufwärts, ist Kaufen erlaubt; ist sie abwärts — ist Verkaufen erlaubt. Wir benötigen einen weiteren Parameter, der einen zweiten Bezugspunkt des Indikators zur Bestimmung der Steigung festlegt.  

Parameter:

  1. int fast_ema_period — Periodenlänge des schnellen, gleitenden Durchschnitts; 
  2. int slow_ema_period — Periodenlänge des langsamen, gleitenden Durchschnitts; 
  3. int signal_period — Glättungslänge der Signallinie;
  4. ENUM_APPLIED_PRICE  applied_price — Preistyp oder handle; 
  5. int shift2 — Abstand des zweiten Punktes zur Bestimmung der Richtung. 

iMACD (Moving Averages Convergence-Divergence)

Das Histogramm des MACD wird mit der Signallinie im eigenen Fester gezeichnet. Es gibt drei Wege diesen Indikator zu verwenden: Auf Basis des Verhältnisses des Histogramms zum Level, die Richtung des Histogramms und dessenb Position relativ zur Signallinie. Das Letzte ist jedoch ein Sonderfall der Wertung des OsMA gegen den Level (wenn dessen Level 0 beträgt), und er wird daher nicht verwendet.  

Variante 1. Mit Level. Ist das Histogramm über dem Level, ist Kaufen erlaubt, ist es unter dem negativen Wert dieses Levels — ist Verkaufen erlaubt.

Parameter: 

  1. int fast_ema_period — Periodenlänge des schnellen, gleitenden Durchschnitts; 
  2. int slow_ema_period — Periodenlänge des langsamen, gleitenden Durchschnitts; 
  3. int signal_period — Glättungslänge der Signallinie;
  4. ENUM_APPLIED_PRICE  applied_price — Preistyp oder handle; 
  5. double level — Wert des Levels.

Variante 2. Auf Basis der Richtung. Bewegt sich das Histogramm aufwärts — Kaufen; wenn abwärts — Verkaufen. Wir benötigen einen weiteren Parameter, der einen zweiten Bezugspunkt des Indikators zur Bestimmung der Steigung festlegt.  

Parameter:

  1. int fast_ema_period — Periodenlänge des schnellen, gleitenden Durchschnitts; 
  2. int slow_ema_period — Periodenlänge des langsamen, gleitenden Durchschnitts; 
  3. int signal_period — Glättungslänge der Signallinie;
  4. ENUM_APPLIED_PRICE  applied_price — Preistyp oder handle; 
  5. int shift2 — Abstand des zweiten Punktes zur Bestimmung der Richtung. 

iOBV (On Balance Volume)

So wie der AD hat dieser Indikator keinen bestimmten Wertebereich und ist sehr unruhig. Er wird nicht verwendet. 

iSAR (Parabolic Stop And Reverse System)

Der Indikator wird auf dem Chart in Form von Punktelinien gezeichnet. Abhängig vom der Richtung der Preisbewegung liegt die Linie darüber oder darunter.

Variante 1. Position relativ zum Preis. Preis ist über dem Indikator — Aufwärtstrend, Preis liegt unter dem Indikator — Abwärtstrend. 

Parameter:

  1. double step — Schrittweite der Preisänderungen — Beschleunigungsfaktor;
  2. Doppel-Maximum — maximale Schrittweite. 

iRSI (Relative Strength Index)

Ein Oszillator im eigenen Fenster. Eine Anwendungsvariante ähnlich zum MFI.

Variante 1. Mit Level.

Parameter: 

  1. int ma_period — Glättungslänge; 
  2. ENUM_APPLIED_PRICE  price — Preistyp;
  3. double level — Verkaufslevel.  

iRVI (Relative Vigor Index)

Ein Oszillator im eigenen Fenster mit einer Signallinie. Die Werte schwanken um Null.

Variante 1. Mit Level. Über dem Level — kaufen, unter den Negativen des Levels — verkaufen.

Parameter:

    1. int ma_period — Glättungslänge;
    2. double level — Wert des Levels.  

Variante 2. Die Haupt- und Signallinie.

Parameter:

    1. int ma_period — Glättungslänge.  

iStdDev (Standard Deviation)

Dieser Indikator hängt nicht von einer Richtung ab. Ähnlich den ATR.

Variante 1. Mit Level. 

Parameter: 

    1. int ma_period — Glättungslänge; 
    2. int ma_shift — horizontaler Versatz des Indikators; 
    3. ENUM_MA_METHOD ma_method — Typ der Glättung; 
    4. ENUM_APPLIED_PRICE applied_price — Preistyp;
    5. double level — Wert des Levels.  

iStochastic (Stochastic Oscillator)

Ein Oszillator im eigenen Fenster mit Haupt- und Signallinie. 

Variante 1. Die Steigung der Hauptlinie. 

Parameter:

  1. int Kperiod — K-Periodenlänge;
  2. int Dperiod — D-Periodenlänge;
  3. int slowing — abschließende Glättungslänge; 
  4. ENUM_MA_METHOD ma_method — Typ der Glättung; 
  5. ENUM_STO_PRICE price_field — Preistyp;
  6. int shift2 — Abstand des zweiten Punktes zur Bestimmung der Richtung der Steigung. 

Variante 2. Mit Level. Die Indikatorwerte variieren im Bereich von 0 bis +100, der neutrale Level liegt bei 50. Ein zusätzlicher Parameter wird für den Verkaufslevel benötigt, der Kauflevel wird errechnet. 

Parameter:

  1. int Kperiod — K-Periodenlänge;
  2. int Dperiod — D-Periodenlänge;
  3. int slowing — abschließende Glättungslänge; 
  4. ENUM_MA_METHOD ma_method — Typ der Glättung; 
  5. ENUM_STO_PRICE price_field — Preistyp;
  6. double level — Wert des Levels.

Variante 3. Die Position von Haupt- und Signallinie.

Parameter:

  1. int Kperiod — K-Periodenlänge;
  2. int Dperiod — D-Periodenlänge;
  3. int slowing — abschließende Glättungslänge; 
  4. ENUM_MA_METHOD ma_method — Typ der Glättung; 
  5. ENUM_STO_PRICE price_field — Preistyp.

iTEMA (Triple Exponential Moving Average)

Ein weiterer gleitenden Durchschnitt.

Variante 1. Steigung der Linie.

Parameter

  1. int ma_period — Glättungslänge; 
  2. int ma_shift — horizontaler Versatz des Indikators; 
  3. ENUM_APPLIED_PRICE applied_price — Preistyp;
  4. int shift2 — Abstand des Punktes zur Bestimmung der Steigung.

Variante 2. Zwei Linien: schnell und langsam.

Parameter

  1. int ma_period1 — Glättungslänge; 
  2. int ma_shift1 — horizontaler Versatz des Indikators; 
  3. ENUM_APPLIED_PRICE applied_price1 — Preistyp;
  4. int ma_period2 — Glättungslänge; 
  5. int ma_shift2 — horizontaler Versatz des Indikators; 
  6. ENUM_APPLIED_PRICE applied_price2 — Preistyp.
Anmerkung. Die Variablen für die schnelle Linie endend mit 1, die der langsamen mit 2. 

iTriX (Triple Exponential Moving Averages Oscillator)

Ein Oszillator im eigenen Fenster. Eine Variante — Steigung der Linie. Wir versuchen eine zweite Variante mit zwei Linien: schnell und langsam 

Variante 1. Steigung der Linie.

Parameter

  1. int ma_period — Glättungslänge; 
  2. int ma_shift — horizontaler Versatz des Indikators; 
  3. ENUM_APPLIED_PRICE applied_price — Preistyp;
  4. int shift2 — Abstand des Punktes zur Bestimmung der Steigung.
Hinweis: Die iTriX-Funktion hat keinen Parameter ma_shift, dennoch kann der Indikator verschoben werden. Das Verschieben geschieht nicht über einen Versatz-Parameter (er ist für alle Indikatoren auf 0 gesetzt), sondern durch die Berechnung des Index der Bar.

Variante 2. Zwei Linien: schnell und langsam.

Parameter

  1. int ma_period1 — Glättungslänge; 
  2. int ma_shift1 — horizontaler Versatz des Indikators; 
  3. ENUM_APPLIED_PRICE applied_price1 — Preistyp;
  4. int ma_period2 — Glättungslänge; 
  5. int ma_shift2 — horizontaler Versatz des Indikators; 
  6. ENUM_APPLIED_PRICE applied_price2 — Preistyp.
Anmerkung. Die Variablen für die schnelle Linie endend mit 1, die der langsamen mit 2. 

iWPR (Williams' Percent Range)

Der Indikator ist identisch mit der Linie der Stochastik mit einer Verzögerung (slowing) von 1, nur in umgekehrter Darstellung. Er wird nicht verwendet.

iVIDyA (Variable Index Dynamic Average)

Ein weiterer gleitenden Durchschnitt.

Variante 1. Steigung der Linie.

Parameter

  1. int cmo_period — CMO period 
  2. ema_period — Glättungslänge 
  3. ma_shift — horizontaler Versatz des Indikators 
  4. ENUM_APPLIED_PRICE applied_price  — Preistyp
  5. int shift2 — Abstand des Punktes zur Bestimmung der Steigung.
Variante 2. Zwei Linien: schnell und langsam.

Parameter

  1. int ma_period1 — Glättungslänge; 
  2. int ma_shift1 — horizontaler Versatz des Indikators; 
  3. ENUM_APPLIED_PRICE applied_price1 — Preistyp;
  4. int ma_period2 — Glättungslänge; 
  5. int ma_shift2 — horizontaler Versatz des Indikators; 
  6. ENUM_APPLIED_PRICE applied_price2 — Preistyp.
Hinweis: Variablen der schnellen Linie enden mit 1, die der langsamen mit 2. 

iVolumes (Volumes)

Die Werte des Indikators hängen nicht von seiner Richtung ab. Der Indikator kann ähnlich wie ATR oder STD verwendet werden.

Variante 1. Level. Sind die Werte des Indikators über dem Level, sind Kaufen und Verkaufen erlaubt. 

Parameter:

  1. ENUM_APPLIED_VOLUME  applied_volume — Volumenstyp;
  2. double level — Wert des Levels.  

Wir haben die Indikatoren mit ihren verwendeten Varianten definiert. Schreiben wir als nächsten eine Enumeration all dessen. Im Verzeichnis "Includes" erstellen wir das Verzeichnis "UniTrend" und erstellen dort die Datei UniTrendDefines.mqh mit folgender Enumeration: 

enum EType{    Type_ADX_PDIMDI,          // Positionen der Linien von PDI und MDI des Indikators ADX    Type_ADX_Level,           // Position der Linien des ADX relativ zu Level    Type_ADXW_PDIMDI,         // Positionen der Linien von PDI und MDI des Indikators Wilders ADX    Type_ADXW_Level,          // Postione der Linie des ADX relativ zum Level von Wilders ADX    Type_Alligator,           // Alligator    Type_AMA_Dir,             // Richtung des АМА          Type_AMA_2MA,             // zwei АМАs    Type_ATR_Level,           // ATR    Type_BuBe_Level,          // Bulls/Bears Power mit Level    Type_BuBe_Dir,            // Richtung von Bulls/Bears Power    Type_Bands,               // Bollinger Bänder    Type_CCI_Level,           // CCI, und mit Level    Type_Chaikin_Level,       // Chaikin Oszillator und mit Level    Type_DEMA_Dir,            // Richtung des DEMA        Type_DEMA_2MA,            // zwei DEMAs        Type_DeMarker_Level,      // DeMarker und mit Level    Type_Envelopes,           // Envelope    Type_Force_Level,         // Force Oszillator und mit Level    Type_Fractals,            // Fraktale    Type_FrAMA_Dir,           // Richtung des FrAMA        Type_FrAMA_2MA,           // zwei FrAMAs    Type_Ichimoku_TK,         // Ichimoku: Tenkan und Kijun    Type_Ichimoku_SASB,       // Ichimoku: Wolke          Type_Momentum_Level,      // Momentum und mit Level    Type_MFI_Level,           // MFI und mit Level    Type_MA_Dir,              // Richtung des MA          Type_MA_2MA,              // zwei MAs    Type_OsMA_Dir,            // Richtung des OsMA    Type_OsMA_Level,          // OsMA und mit Level    Type_MACD_Dir,            // Richtung des MACD    Type_MACD_Level,          // MACD und mit Level    Type_SAR,                 // SAR    Type_RSI_Level,           // RSI und mit Level    Type_RVI_Level,           // RVI und mit Level    Type_RVI_MS,              // Haupt- und Signallinie des RVI    Type_STD_Level,           // standard deviation und mit Level    Type_Sto_Dir,             // Richtung der Stochastik    Type_Sto_Level,           // Stochastik und mit Level    Type_Sto_MS,              // Haupt- und Signallinie der Stochastik            Type_TEMA_Dir,            // Richtung des TEMA    Type_TEMA_2MA,            // zwei TEMAs    Type_TriX_Dir,            // Richtung des TriX    Type_TriX_2MA,            // zwei TriXs    Type_VIDyA_Dir,           // Richtung des VIDyA    Type_VIDyA_2MA,           // zwei VIDyAs    Type_Volumes              // Volumen       

};

Externe Parameter

Durch die Analyse de oben beschrieben Indikatoren erkennen wir die benötigten, externen Parameter. Alle benötigten Parameter mit ihren Typen befinden sich in Tabelle 1. Alle Variablen beginnen zunächst mit "f_" (für schnell oder engl. "fast"). In den Varianten mit einem schnellen und einem langsamen gleitenden Durchschnitt erhält die zweite Gruppe der Parameter den Präfix "s_" (für "langsam" oder eng. "slow").

Tabelle 1. Externe Parameter mit ihren Typen  

Typ Name
int  f_period1
int  f_shift1
int  f_period2
int  f_shift2
int  f_period3
int  f_shift3
ENUM_MA_METHOD  f_method
ENUM_APPLIED_PRICE  f_price
ENUM_APPLIED_VOLUME   f_volume
ENUM_STO_PRICE  f_sto_price
double  f_level
int  f_dot2shift
double  f_step 
double  f_maximum 
int  s_period1
int  s_shift1
int  s_period2
int  s_shift2
int  s_period3
int 
s_shift3
ENUM_MA_METHOD  s_method
ENUM_APPLIED_PRICE  s_price
int mult 
int  level_digits 
int  sar_step_digits 
int  sar_maximum_digits 

Zusätzlich zu den angegebenen Parameter aus den Beschreibungen der Indikatoren, gibt es weitere Parameter am Ende der Tabelle:

  • mult — Ein Multiplikator der Parameter in Points, abhängig von der Anzahl der Dezimalstellen der Kurse. Die Werte einiger Indikatoren, wie MACD und OsMA, zeigen sich als Preise und da ist es bequemer, sie in Points festzulegen. Die Werte der Parameter müssen dann in Abhängigkeit der Dezimalstellen der Preise angepasst werden.
  • level_digits — Die Anzahl der Dezimalstellen der Level-Parameter. Im grafischen Interface wird der Werte der Level mittels dem Bedienelement CSpinBox festgelegt (ein Eingabefeld mit "+" und "-"-Tasten), es wäre daher nahe liegend, die verschiedenen, minimalen Änderungen der verschiedenen Indikatoren auch so festzulegen (der Betrag, um den sich der Wert durch das Drücken von "+" oder "-" ändert).
  • sar_step_digits — die Anzahl der Dezimalstellen der Parameter von Schrittweiten des Indikators SAR.
  • sar_maximum_digits — Anzahl der Dezimalstellen des Maximalwertes des Indikators SAR.
Jetzt ist es schwierig, die geeigneten Werte der Parameter level_digits, sar_step_digitssar_maximum_digits zu bestimmen, wir werden deshalb Konstanten der Datei UniTrendDefines.mqh hinzufügen, deren Werte leicht zu korrigieren sind:
#define ADX_LEVEL_DIGITS         0 // für den ADX-Indikator
#define ADXW_LEVEL_DIGITS        0 // für den ADX Wilder-Indikator
#define ATR_LEVEL_DIGITS         1 // für den ATR-Indikator
#define BUBE_LEVELS_DIGITS       1 // für den Bulls/Bears-Power-Indikator
#define CCI_LEVEL_DIGITS         0 // für den CCI-Indikator
#define CHAIKIN_LEVEL_DIGITS     0 // für den Chaikin-Oszillator
#define DEMARKER_LEVEL_DIGITS    2 // für den Demarker-Indikator 
#define FORCE_LEVEL_DIGITS       3 // für den Force-Indikator
#define MOMENTUM_LEVEL_DIGITS    2 // für den Momentum-Indikator 
#define MFI_LEVEL_DIGITS         0 // für den MFI-Indikator
#define OSMA_LEVBEL_DIGITS       2 // für den OsMA-Indikator
#define MACD_LEVEL_DIGITS        2 // für den MACD-Indikator
#define RSI_LEVEL_DIGITS         0 // für den RSI-Indikator
#define RVI_LEVEL_DIGITS         2 // für den RVI-Indikator
#define STD_LEVEL_DIGITS         1 // für den STD-Indikator
#define STO_LEVEL_DIGITS         0 // für den Stochastic-Indikator
#define BANDS_LEVEL_DIGITS       1 // für die Bollinger Bänder
#define ENVELOPES_LEVEL_DIGITS   2 // für den Envelopes-Indikator
#define SAR_STEP_DIGITS          3 // für den SAR-Indikator (Parameter der Schrittweite)
      #define SAR_MAXIMUM_DIGITS       2 // für den SAR-Indikator (Parameter für das Maximum)

Für ATR, Bulls/Bears, OsMA, MACD, STD werden die Werte der Level in Points angegeben. 

Erstellen wir folgende Struktur aus der Tabelle 1:

struct SExtParams{
   int                 f_period1;
   int                 f_shift1;
   int                 f_period2;
   int                 f_shift2;
   int                 f_period3;
   int                 f_shift3;
   long                f_method;
   long                f_price;
   long                f_volume;
   long                f_sto_price;
   double              f_level;
   int                 f_dot2shift;
   double              f_step;  
   double              f_maximum;  
   int                 s_period1;
   int                 s_shift1;
   int                 s_period2;
   int                 s_shift2;
   int                 s_period3;
   int                 s_shift3;
   long                s_method;
   long                s_price;
   int                 mult;
   int                 level_digits;
   int                 sar_step_digits;
   int                 sar_maximum_digits;      
            };

Die Kombinierbarkeit von Parametern in einer Struktur erlaubt uns, sie vom Rest des Codes zu trennen. Das erleichtert spätere Revisionen des Indikators, wenn die bestehenden Trendindikatoren nicht ausreichen und weitere hinzugefügt werden sollen. Darüber hinaus erleichtert das erheblich die Übergabe der Parameter an Funktionen und Klassenmethoden.

Da der Indikator dieses Artikels den Trend als eine Reihe von Zeichen (gleich für alle Indikatoren) darstellt, können wir sehr leicht eine Benachrichtigung über den Beginn eines neuen Trends ergänzen. Der eine oder andere bevorzugt vielleicht, erst von einem vollständig, gebildeten Trend (Anzeige auf einer vollständigen Bar) benachrichtigt zu werden, andere wieder wollen sofort über einen neuen Trend (auf der aktuellen Bar) informiert werden. Daher schreiben wir eine weitere Enumeration für die Art der Benachrichtigung:

enum EAlerts{
   Alerts_off=0, // keine Benachrichtigung
   Alerts_Bar0=1, // Benachrichtigung während der aktuellen Bar
   Alerts_Bar1=2 // Benachrichtigung nach der letzten geschlossenen Bar
            };  

Erstellen eines Indikators

Das Erstellen der Klassen für den universelle Indikator ist detailliert in den Artikeln "Der universell Oszillator mit dem graphischen Interface" und "Universeller Kanal mit grafischem Interface" beschrieben. betrachte wir die besonderen Merkmale ihrer Erzeugung bezüglich dieses Artikels.

Alle bereits erwähnten Methoden für Bestimmung des Trends sind in zwei Gruppen organisiert: mit einem oder zwei Indikatoren. In der ersten Gruppe muss nach dem Laden des Indikators ein Handle geprüft werden, in der zweiten zwei Handles. Das bedeutet die Basisklasse bekommt zwei Kindklassen, jeweils mit einer unterschiedlichen Überprüfung der Handles. Im Gegenzug haben diese Kindklassen wiederum ihre eigenen Kindklassen zur Trendbestimmung.

Die Basisklasse:

class CUniTrend{
   protected:
  
      int m_handle1;
      int m_handle2;
      
      string m_name;
      string m_help;
      
      int m_ci;
      
      double m_b1[1];
      double m_b2[1];      
      double m_b3[1];    
      double m_b4[1];
            
      int m_shift;
      int m_shift1;    
      int m_shift2;
      int m_shift3;
      
      int m_dot2shift;
      
      double m_level;      
      
   public:
  
      void CUniTrend(){
         m_handle1=INVALID_HANDLE;
         m_handle2=INVALID_HANDLE;
      }
      
      void ~CUniTrend(){
         if(m_handle1!=INVALID_HANDLE){
            IndicatorRelease(m_handle1);
         }
         if(m_handle2!=INVALID_HANDLE){
            IndicatorRelease(m_handle2);
         }        
      }
  
      virtual int Calculate( const int rates_total,
                     const int prev_calculated,
                     double & upBuffer[],
                     double & dnBuffer[]
      ){
         return(rates_total);
      }
      
      virtual bool Calculated(){
         return(false);
      }
      
      virtual bool CheckHandles(){
         return(true);
      }      
      
      string Name(){
         return(m_name);
      }    
      string Help(){
         return(m_help);
      }
            };

Der "protected" Bereich beinhaltet die Deklaration verschiedener Hilfsvariablen, die nützlich in den Kindklassen werden. Die Variable für die Handles der Indikatoren werden im Konstruktor initialisiert und werden vom Destruktor wieder freigegeben. Die weiteren Methoden sind virtuell.

Die Kindklasse einer Variante mit einem Indikator:

class CUniTrend1:public CUniTrend{
   public:
      bool Calculated(){
         if(BarsCalculated(m_handle1)>0){
            return(true);
         }  
         else{
            return(false);
         }    
      }
      
      bool CheckHandles(){
         return(m_handle1!=INVALID_HANDLE);
      }
            };

Die Klasse hat zwei Methoden: CheckHandle() — sie erlaubt zu prüfen, ob der Indikator geladen werden kann, und Calculated() — sie stell fest, ob der Indikator vollständig berechnet worden ist, und, ob die Inhalte der Puffer, die den Trend zeigen, aktualisiert werden können.

Eine Kindklasse mit der Variante für zwei Indikatoren:

class CUniTrend2:public CUniTrend{
   public:
      bool Calculated(){
         if(BarsCalculated(m_handle1)>0 && BarsCalculated(m_handle2)>0){
            return(true);
         }  
         else{
            return(false);
         }    
      }      
      
      bool CheckHandles(){
         return(m_handle1!=INVALID_HANDLE && m_handle2!=INVALID_HANDLE);
      }
            };

Alle Klassen mit unterschiedlichen Varianten zur Trendbestimmung, sind Kindklassen von entweder CUniTrend1 oder CUniTrend2. Betrachten wir die folgende Kindklasse:

class CUniTrend_ADX_PDIMDI:public CUniTrend1{
   private:  
   public:
  
      void CUniTrend_ADX_PDIMDI( bool use_default,
                                 bool keep_previous,
                                 SExtParams & par){
        
         // Einstellen der Standardparameter
        
         if(use_default){
            if(keep_previous){
               if(par.f_period1==PARAMETER_EMPTY)par.f_period1=14;
            }
            else{
               par.f_period1=14;
            }      
         }          
         // Landen des Indikators
         m_handle1=iADX(Symbol(),Period(),par.f_period1);
         // Bilden des Namens des Indikators mit Hinweis über die Parameter
         m_name=StringFormat( "iADX_PDIMDI(%i)",
                              par.f_period1
                            );
  
         m_help=StringFormat( "adx_period - f_period1(%i)",
                              par.f_period1
                            );
      }
      
      int Calculate( const int rates_total,
                     const int prev_calculated,
                     double & upBuffer[],
                     double & dnBuffer[]
      ){
         int start;
        
         if(prev_calculated==0){
            start=1;
         }
         else{
            start=prev_calculated-1;
         }
      
         for(int i=start;i<rates_total;i++){
        
            upBuffer[i]=EMPTY_VALUE;        
            dnBuffer[i]=EMPTY_VALUE;
        
            m_ci=rates_total-i-1;
            
            if(CopyBuffer(m_handle1,PLUSDI_LINE,m_ci,1,m_b1)==-1){
               return(0);
            }
            
            if(CopyBuffer(m_handle1,MINUSDI_LINE,m_ci,1,m_b2)==-1){
               return(0);
            }
            
            if(m_b1[0]>m_b2[0]){
               upBuffer[i]=1;
            }
            else if(m_b1[0]<m_b2[0]){
               dnBuffer[i]=-1;            
            }
            
         }      
      
         return(rates_total);
      }
            };

Die wichtigsten Punkte im Konstruktor der Klasse sind kommentiert, und die Methode Calculate() ist analog zur Standardfunktion OnCalculate() der Indikatoren. Der Code dieser Methode in Anlehnung an den Code der Indikatoren geschrieben.

In der dem Artikel beigefügten Datei befinden sich all Indikatorklassen in Include/UniTrend/UniTrendIndicators.mqh.

Jetzt, da wir alle Klassen vorbereitet haben, können einen einfachen Indikator zur Trendbestimmung erstellen, genau so, wie wir das bereits in den Artikeln über den universellen Oszillator und universellen Kanal gemacht haben. Ein fertiger Indikator ohne grafisches Interface ist in der beigefügten Datei Indicators/iUniTrend.mq5 vorhanden.

Erstellen eines grafischen Interfaces

Alle Klassen des grafischen Interfaces befinden sich in den Dateien UniTrendForm.mqh und UniTrendControl.mqh. Die Formklasse befindet sich in der Datei UniTrendForm.mqh file, und die Datei UniTrendControl.mqh beinhaltet die Klassen des universellen Bedienelementes zur Eingabe der Indikatorparameter. Es ist nicht notwendig auf die Formklasse detailliert einzugehen, da sie bereits in den erwähnten Artikeln über den universellen Oszillator und den universellen Kanal beschrieben wurde. Außerdem wurde sie im Artikel "Benutzerdefinierte grafische Bedienelemente. Teil 3. Formen" erläutert. Wenden wir uns dem Erstellen des universellen Bedienelementes zu.

Die Basis des universellen Bedienelementes ist die Basisklasse CUniTrendControl. Der "public" Teil der Klasse enthält nur virtuelle Methoden, der "protected" Teil einige Hilfsmethoden zum Bearbeiten von Auswahllisten: Methoden zum Eintragen der Einstellungen der Varianten in die Liste und Methoden zur Auswahl aus der Liste. Hier ist der kommentierte Code der Basisklasse:

class CUniTrendControl{
   protected:
      
      /* Funktion zur Berechnung der kleinsten Wertänderung
         durch die Anzahl der Dezimalstellen des Parameters des Levels
      */
      double SolveChange(int d){
         return(NormalizeDouble(1.0/pow(10,d),d));  
      }
      
      // Ausfüllen der Liste der Varianten aus ENUM_MA_METHOD
      void AddVariantsMethod(CComBox & cb){
         for(int i=0;i<ArraySize(e_method);i++){
            cb.AddItem(EnumToString((ENUM_MA_METHOD)e_method[i]));
         }
      }
      
      // Ausfüllen der Liste der Varianten aus ENUM_APPLIED_PRICE
      void AddVariantsPrice(CComBox & cb){
         for(int i=0;i<ArraySize(e_price);i++){
            cb.AddItem(EnumToString((ENUM_APPLIED_PRICE)e_price[i]));
         }
      }      
      
      // Ausfüllen der Liste der Varianten aus ENUM_APPLIED_VOLUME
      void AddVariantsVolume(CComBox & cb){
         for(int i=0;i<ArraySize(e_volume);i++){
            cb.AddItem(EnumToString((ENUM_APPLIED_VOLUME)e_volume[i]));
         }
      }  
      
      // Ausfüllen der Liste der Varianten aus ENUM_STO_PRICE     
      void AddVariantsStoPrice(CComBox & cb){
         for(int i=0;i<ArraySize(e_sto_price);i++){
            cb.AddItem(EnumToString((ENUM_STO_PRICE)e_sto_price[i]));
         }
      }      
      
      // Rückgabe des Index der ENUM_MA_METHOD  
      int MethodIndex(long val){
         for(int i=ArraySize(e_method)-1;i>=0;i--){
            if(e_method[i]==val){
               return(i);
            }
         }
         return(-1);
      }
      
      // Rückgabe des Index aus ENUM_APPLIED_PRICE
      int PriceIndex(long val){
         for(int i=ArraySize(e_price)-1;i>=0;i--){
            if(e_price[i]==val){
               return(i);
            }
         }
         return(-1);
      }  
      
      // Rückgabe des Index aus ENUM_APPLIED_VOLUME   
      int VolumeIndex(long val){
         for(int i=ArraySize(e_volume)-1;i>=0;i--){
            if(e_volume[i]==val){
               return(i);
            }
         }
         return(-1);
      }  
      
      // Rückgabe des Index aus ENUM_STO_PRICE     
      int StoPriceIndex(long val){
         for(int i=ArraySize(e_sto_price)-1;i>=0;i--){
            if(e_sto_price[i]==val){
               return(i);
            }
         }
         return(-1);
      }      
      
   public:
      
      // Initialisierung des Bedienelementes
      virtual void Init(SExtParams & par){}
      
      // Festlegen der Werte
      virtual void SetValues(SExtParams & par){}      
      
      // Rückgabe der Werte
      virtual void GetValues(SExtParams & par){}
      
      // Anzeigen des Bedienelementes
      virtual void Show(int x,int y){}      
      
      // Ausblenden des Bedienelementes
      virtual void Hide(){}      
      
      // Anzahl der Bedienelemente zur Berechnung der Fensterhöhe
      virtual int ControlsCount(){
         return(0);
      }
      
      // Handhabung von Ereignissen
      virtual int Event(int id,long lparam,double dparam,string sparam){
         return(0);
      }
      
};
    

Batrachten wir jetzt eine Kindklasse zur Trendbestimmung auf Basis von ADX mit Level (zwei Bedienelemente):

class CUniTrendControl_ADX_Level: public CUniTrendControl{
   private:
  
      // Pointer auf die einfachen Bedienelemente
      CSpinInputBox m_f_period1;
      CSpinInputBox m_f_level;
  
   public:
  
      // Initialisierung des Bedienelementes
      void Init(SExtParams & par){
         m_f_period1.Init("f_period1",SPIN_BOX_WIDTH,1," adx_period");
         m_f_period1.SetMinValue(1);
         m_f_period1.SetReadOnly(false);
         m_f_level.Init("f_level",COMBO_BOX_WIDTH,this.SolveChange(par.level_digits)," level");
         m_f_level.SetMinValue(0);
         m_f_level.SetReadOnly(false);
      }
  
      // Festlegen der Werte
      void SetValues(SExtParams & par){        
         m_f_period1.SetValue(par.f_period1);
         m_f_level.SetValue(par.f_level);
      }
  
      // Rückgabe der Werte
      void GetValues(SExtParams & par){
         par.f_period1=(int)m_f_period1.Value();
         par.f_level=m_f_level.Value();
      }    
  
      // Anzeigen des Bedienelementes
      void Show(int x,int y){
         m_f_period1.Show(x,y);
         y+=20;
         m_f_level.Show(x,y);
      }      
  
      // Ausblenden des Bedienelementes
      void Hide(){
         m_f_period1.Hide();
         m_f_level.Hide();
      }
  
      // Anzahl der Bedienelemente zur Berechnung der Fensterhöhe
      int ControlsCount(){
         return(2);
      }
  
      // Ausführen der Ereignisse der Bedienelemente
      int Event(int id,long lparam,double dparam,string sparam){
         int e1=m_f_period1.Event(id,lparam,dparam,sparam);
         int e2=m_f_level.Event(id,lparam,dparam,sparam);
         if(e1!=0 || e2!=0){
            return(1);
         }
         return(0);
      }
};
    

Eine Variable des Typs SExtParam wird den Methoden SetValues() und GetValues() übergeben, die Struktur umfasst die benötigten Variablen, die von den Kindklassen verwendet werden. Wir müssen die Minimaländerung des Bedienelementes der Level festlegen; das kann währen der Initialisierung des Bedienelementes geschehen, es wird daher auch eine Struktur mit den Parametern der Methode init() übergeben. Im Allgemeinen korrespondiert das Erstellen einer Kindklasse mit allen Prinzipien für das Erstellen eines Bedienelementes im Artikel "Benutzerdefinierte grafische Bedienelemente. Teil 1: Erstellen eines einfachen Bedienelements", außer, dass hier nicht alle, sondern nur die notwendigen Methoden erstellt wurden. 

Zusammenführen von GUI und Indikator

Dieses Stadium der Indikatorerstellung ist sehr ähnlich dem korrespondierenden Stadium der Erstellung des universellen Trendindikators und der des universellen Kanals. Betrachten wir die Unterschiede.

Früher, als der Indikator mit Standardwerten lief (UseDefault=true), wurden alle Parameter mit -1 initialisiert. Jetzt reicht das nicht mehr aus, da die Werte der Level manchmal negative sein können. Die Initialisierung wird daher jetzt mit dem Wert PARAMETER_EMPTY durchgeführt, der in der Datei UniTrendDefines.mqh deklariert ist. Die Konstante erhält den Wert INT_MAX (ein Wert, der die Grenzen der realen Werte der Level weit überschreitet).

Ein weiterer, kleiner Unterschied betrifft die Funktion OnTimer(). Die Methode Calculated() wird aufgerufen, um zu prüfen, ob der Indikator berechnet wurde, da einige Varianten für den Trend nur einen Indikator überprüfen müssen, andere aber zwei. Das lässt sich nur innerhalb der Indikatorklassen ermitteln.

Im Ergebnis erhalten einen weiteren, universellen und bequemen Indikator (Fig. 10).

Fig. 10. Ein universeller Trendindikator mit grafischem Interface
Fig. 10. Ein universeller Trendindikator mit grafischem Interface

Hinweis: Zusätzlich zur Anzeige des Namens der aus der Liste gewählten Variante, wird auch der verwendete Indikatortyp im Fenster des Indikators angezeigt, oben links in der Ecke. Neben dem Typ werden auch die Werte aller Parameter (in Klammern) angezeigt. Sind die Werte der Level in Points angegeben, wird angezeigt, wie die Points in reale Werte umzurechnen sind(Fig. 11).

 
Fig. 11. Darstellung von Parametern in Points

Der dargestellte Indikator ist Teil des Attachments unten, sein Dateiname ist Indicators/iUniTrendGUI.mq5.  

Schlussfolgerung 

Insgesamt umfasst der Indikator 46 verschiedene Möglichkeiten zur Trendbestimmung. Das grafische Interface, das einen schnellen Wechsel der Parameter der Indikator und ihres Typs erlaubt, ermöglicht eine komfortable Analyse der Historie. Durch die Möglichkeit von Benachrichtigungen ist er geeignet für einen praktischen Einsatz.

Es ist ein neuer Weg, ein grafisches Interface zu erstellen, der Vor- aber auch Nachteile hat. Der Nachteil ist die große Menge an Code und daher eine Menge Arbeit. Anders als die Klassen, die die Sichtbarkeit von Bedienelemente handhabt (wie beim universellen Oszillator und dem universellen Kanal), wurde hier ein vollständiges Bedienelement für fast jede Variante zur Trendbestimmung erstellt. Aber eine klare Trennung und die Unabhängigkeit des Codes der kombinierten Bedienelementes konnte die Entwicklung stark vereinfachen, und das vereinfacht weitere Entwicklungen, falls das notwendig werden sollte.

Anlagen

Dem Artikel beigefügt ist das Archiv mit allen benötigten Dateien. Die Dateien liegen bereits an den korrekten Verzeichnissen. Sie sollten in den gleichen Verzeichnissen des Terminals kopiert werden. 

Übersetzt aus dem Russischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/ru/articles/3018

Beigefügte Dateien |
files.zip (32.11 KB)
Das Handelssystem DiNapoli Das Handelssystem DiNapoli
Im Artikel wird gründlich das Handelssystem unter Verwendung der Ebene Fibonatschtschi betrachtet, die Joe DiNapoli entwickelt und beschrieben hat. Es werden die Hauptbegriffe und das Wesen des Systems erklärt, es wird die Illustration auf dem Beispiel des unkomplizierten Indikators gegeben.
Das Handeln nach Donchians Kanälen Das Handeln nach Donchians Kanälen
Im Artikel werden einige Strategien aufgrund des Kanals Donchians unter Verwendung verschiedener Indikatorfilter getestet und entwickelt. Es wird die Forschung und die vergleichende Analyse ihrer Arbeit durchgeführt.
Grafische Interfaces X: Algorithmus für den Zeilenumbruch im mehrzeiligen Textfeld (build 12) Grafische Interfaces X: Algorithmus für den Zeilenumbruch im mehrzeiligen Textfeld (build 12)
Wir fahren fort mit der Entwicklung eines mehrzeiligen Textfeldes. Diesmal ist es unsere Aufgabe einen Algorithmus für den Fall, dass der Text die Breite des Textfeldes überschreitet, zu entwickeln oder, umgekehrt, einen Zeilenumbruch zu entfernen, wenn die möglich ist.
Grafisches Interface X: Sortieren, Neuerstellen der Tabelle und Steuerelemente der Zellen (build 11) Grafisches Interface X: Sortieren, Neuerstellen der Tabelle und Steuerelemente der Zellen (build 11)
Wir fahren fort neue Elemente der Tabellendarstellung hinzuzufügen: Datensortierung, Handhabung der Zahl der Spalten und Zeilen, Setzen des Zelltyps, um dort auch Steuerelemente eintragen zu können.