English Русский 中文 Español 日本語 Português 한국어 Français Italiano Türkçe
Anlegen eines mehrwährungsfähigen Indikators unter Verwendung zahlreicher Indikatorzwischenspeicher

Anlegen eines mehrwährungsfähigen Indikators unter Verwendung zahlreicher Indikatorzwischenspeicher

MetaTrader 5Indikatoren | 8 März 2016, 09:44
717 0
Alexey Klenov
Alexey Klenov

Einleitung

Es begann alles damit, als ich in dem Artikel Theoretische Grundlagen zum Aufbau von Cluster Indikatoren für Devisenhandel zum ersten Mal etwas von Clusterindikatoren gehört habe. Das hat mich damals sehr interessiert und so habe ich beschlossen, etwas Ähnliches in Sachen Kursanalyse für mehrere Währungen zu programmieren. Zunächst habe ich unter der Code-Bezeichnung MultiCurrencyIndex eine eigene Variante des Indikators umgesetzt, in dem auf der Grundlage der berechneten Werte der Währungsindices die Berechnung der klassischen Indikatoren (RSI, MACD, CCI) erfolgt ist. 

Und jetzt werde ich Ihnen schildern, wie ich diesen Indikator auf die neue Plattform MetaTrader 5 in Verbindung mit MQL5 übertragen habe, außer dass ich statt des CCI den Stochastischen Oszillator (Stochastik-Indikator) berechnen werde, da dieser (meiner Ansicht nach) zukunftsträchtiger ist.

Beginnen wir mit einigen Begriffsbestimmungen:

Der US Dollar Index  - Ein anhand der mir freundlicherweise von Neutron zur Verfügung gestellten Formel berechneter Wert der Art „double“.

Formel zur Berechnung des USD-Index,

mit USD/YYY = alle unmittelbaren Quotierungen der Art USD/CHF; XXX/USD = alle gegenläufigen wie EUR/USD.

Die übrigen Währungsindices werden aus den Schlusswerten (Close) der Währungspaare berechnet, die USD beinhalten.

Die Hauptlinien - zwei unmittelbar zum aktuellen Diagramm gehörende die Rechendaten abbildende Linien. In dem EURUSD-Diagramm sind es beispielsweise die Linien für die Währungen EUR und USD.

Hilfslinien - die übrigen berechneten Indikatorlinien, die nicht zu dem aktuellen Diagramm gehören. Für dasselbe EURUSD-Diagramm sind das zum Beispiel die Linien für die Währungen GBP, CHF, JPY, CAD, AUD und NZD.

Close - der Wert des Schlusskurses des Balkens des aktuellen Zeitraums (der Art „double“) für das benötigte Währungspaar.

Also, fangen wir an.

Die Aufgabenstellung

Zunächst brauchen wir eine Aufgabenstellung.

  1. Synchronisierung der Diagramme der aktivierten Währungspaare des aktuellen Zeitraums.
  2. Zugriff auf die Schlusskurse (Close) von sieben Währungspaaren: EURUSD, GBPUSD, USDCHF, USDJPY, USDCAD, AUDUSD und NZDUSD sowie deren Zwischenspeicherung in den für Hilfsberechnungen vorgesehenen Indikatorpuffern.
  3. Berechnung des US Dollar Index auf dem aktuellen Balken auf der Grundlage der in Punkt (2) gewonnenen Daten.
  4. Berechnung der übrigen Währungsindices in Kenntnis des US Dollar Index für den aktuellen Balken.
  5. Durchführung der genannten Berechnungen (Punkt 3 und 4) in der für die gewählte Verlaufslänge erforderlichen Häufigkeit.
  6. Berechnung der folgenden Werte für jeden der gewählten Währungsindices je nach Art des Indikators:
    • Relativer Stärke Indikator (Relative Strength Index, RSI);
    • Indikator für das Zusammen-/Auseinanderlaufen des gleitenden Durchschnitts (Moving Average Convergence / Divergence, MACD);
    • Stochastik (Stochastik Oszillator);
    • diese Aufstellung kann fortlaufend erweitert werden.

Dafür benötigen wir:

31 Indikatorpuffer:

  • 0 - 7 jeweils einschließlich - Zwischenspeicher zur Abbildung der Ergebnislinien;
  • 8 - 14 einschließlich - Zwischenspeicher für die Hauptwährungspaare, die USD beinhalten;
  • 15 - 22 einschließlich - Zwischenspeicher für die Währungsindices;
  • 23 - 30 einschließlich - Zwischenspeicher für die Zwischenergebnisse des Stochastik Oszillators der Art „close/close“ ohne Glättung.

Zur Auswahl der Indikatorart führen wir den geeigneten Aufzählungstyp enum ein:

enum Indicator_Type
  {
   Use_RSI_on_indexes             = 1, // RSI of the index  
   Use_MACD_on_indexes            = 2, // MACD from the index  
   Use_Stochastic_Main_on_indexes = 3  // Stochastic on the index
  };
Als Nächstes geben wir mithilfe des Eingabebefehls „input“ im Einstellungen-Fenster eine Aufstellung der Indikatoren zur Auswahl durch den Anwender aus. 
input Indicator_Type ind_type=Use_RSI_on_indexes;  // type of the indicator from the index

Es besteht die Möglichkeit, unter der Registerkarte „Inputs“ eine anwenderfreundlichere Art zur Wiedergabe der Bezeichnungen der Eingangsparameter einzustellen. Dazu wird der Zeilenkommentar verwendet, der in derselben Zeile hinter der Beschreibung des Eingangsparameters stehen muss. So können den Eingangsparametern für den Anwender verständlichere Bezeichnungen zur Seite gestellt werden.

Dieselben Regeln gelten für den Aufzählungsbefehl enum. Das heißt, wenn der mnemonischen Bezeichnung wie in unserem Beispiel ein Kommentar zur Seite gestellt wird, wird anstelle der mnemonischen Bezeichnung der Inhalt dieses Kommentars verwendet. Das verleiht zusätzliche Flexibilität beim Schreiben von Programmen mit verständlichen Beschreibungen der Eingangsparameter.

Die Entwickler haben versucht, geeignete Mittel bereitzustellen, damit der Endanwender eines MQL5-Programms die „menschliche“ Bezeichnung der Parameter angezeigt bekommt und nicht, was im Programmcode geschrieben steht. Ausführlichere Angaben können hier nachgelesen werden.

Abbildung 1. Auswahl der Art des Indikators

Abbildung 1. Auswahl der Art des Indikators

Wir stellen dem Anwender eine Auswahl der erforderlichen Währungen zur Abbildung des Indikators sowie deren Farben zur Verfügung:

input bool USD=true;
input bool EUR=true;
input bool GBP=true;
input bool JPY=true;
input bool CHF=true;
input bool CAD=true;
input bool AUD=true;
input bool NZD=true;

input color Color_USD = Green;            // USD line color
input color Color_EUR = DarkBlue;         // EUR line color
input color Color_GBP = Red;             // GBP line color
input color Color_CHF = Chocolate;        // CHF line color
input color Color_JPY = Maroon;           // JPY line color
input color Color_AUD = DarkOrange;       // AUD line color
input color Color_CAD = Purple;          // CAD line color
input color Color_NZD = Teal;            // NZD line color

Abbildung 2. Auswahl der Farbe für die Indikatorlinien

Abbildung 2. Auswahl der Farbe für die Indikatorlinien

Einige weitere einstellbare Parameter:

input string rem000        =  ""; // depending on the type of the indicator
input string rem0000       =  ""; // requires a value :
input int rsi_period       =   9; // period RSI
input int MACD_fast        =   5; // period MACD_fast
input int MACD_slow        =  34; // period MACD_slow
input int stoch_period_k   =   8; // period Stochastic %K
input int stoch_period_sma =   5; // period of smoothing for Stochastics %K
input int shiftbars        = 500; // number of bars for calculating the indicator

Abbildung 3. Indikatorparameter

Abbildung 3. Indikatorparameter

Die Beschränkung auf 500 Balken zur Berechnung des Indikators ist künstlich, reicht jedoch zur Wiedergabe des Grundgedankens der Indexberechnungen aus. Dabei ist zu bedenken, dass jeder Indikatorpuffer Speicherplatz benötigt, und dass der Speicherplatz auf dem Rechner möglicherweise nicht ausreicht, wenn dieser Variablen (in Millionen Balken) zu viel Platz eingeräumt wird.

Indikatorpuffer:

double  EURUSD[], // quotes
        GBPUSD[],
        USDCHF[],
        USDJPY[],
        AUDUSD[],
        USDCAD[],
        NZDUSD[];   
               
double    USDx[], // indexes
          EURx[],
          GBPx[],
          JPYx[],
          CHFx[],
          CADx[],
          AUDx[],
          NZDx[];
                         
double USDplot[], // results of currency lines
       EURplot[],
       GBPplot[],
       JPYplot[],
       CHFplot[],
       CADplot[],
       AUDplot[],
       NZDplot[]; 

double USDStoch[], // buffers of intermediate data schotastics by the close/close type without smoothing
       EURStoch[],
       GBPStoch[],
       JPYStoch[],
       CHFStoch[],
       CADStoch[],
       AUDStoch[],
       NZDStoch[];
Darüber hinaus benötigen wir einige globale (auf der Ebene des Indikators) Variablen:
int              i,ii;
int           y_pos=0; // Y coordinate variable for the informatory objects  
datetime   arrTime[7]; // Array with the last known time of a zero valued bar (needed for synchronization)  
int        bars_tf[7]; // To check the number of available bars in different currency pairs  
int        countVal=0; // Number of executable Rates  
int           index=0;
datetime  tmp_time[1]; // Intermediate array for the time of the bar 

Damit sind wir bei der recht umfangreichen Funktion OnInit angelangt, in der wir die Indikatorpuffer ihren Zwecken entsprechend verteilen.

Da die anfänglichen Berechnungen den US Dollar Index durchlaufen, wird für USD die Möglichkeit eingerichtet, die Abbildung dieser Währung in den Indikatorpuffern lediglich auszuschalten.

So sieht das aus:

if(USD)
  {
   countVal++;
   SetIndexBuffer(0,USDplot,INDICATOR_DATA);               // array for rendering
   PlotIndexSetString(0,PLOT_LABEL,"USDplot");              // name of the indicator line (when selected with a mouse)
   PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,shiftbars);       // from which we begin rendering
   PlotIndexSetInteger(0,PLOT_DRAW_TYPE,DRAW_LINE);         // drawing style (line)
   PlotIndexSetInteger(0,PLOT_LINE_COLOR,Color_USD);       // color of line rendering
   if(StringFind(Symbol(),"USD",0)!=-1)
     {PlotIndexSetInteger(0,PLOT_LINE_WIDTH,wid_main);}    // if the symbol name contains USD 
                                                       // then draw a line of appropriate width 
   else
     {PlotIndexSetInteger(0,PLOT_LINE_STYLE,style_slave);}
   ArraySetAsSeries(USDplot,true);                       // indexation of array as a timeseries   
   ArrayInitialize(USDplot,EMPTY_VALUE);                  // zero values 
   f_draw("USD",Color_USD);                            // rendering in the indicator information window 
  }
SetIndexBuffer(15,USDx,INDICATOR_CALCULATIONS);            // array of dollar index for calculations
                                                      // (is not displayed in the indicator as a line) 
ArraySetAsSeries(USDx,true);                            // indexation of an array as a time series
ArrayInitialize(USDx,EMPTY_VALUE);                       // zero values

if(ind_type==Use_Stochastic_Main_on_indexes)
  {
   SetIndexBuffer(23,USDstoch,INDICATOR_CALCULATIONS);     // if the destination of the indicator as a Use_Stochastic_Main_on_indexes,
                                                           // then this intermediate array is needed
   ArraySetAsSeries(USDstoch,true);                        // indexation of array as a time series
   ArrayInitialize(USDstoch,EMPTY_VALUE);                  // zero values
  }
Für die Währung EUR sieht der Code in der Funktion OnInit folgendermaßen aus:
if(USD)
  {
   countVal++;
   SetIndexBuffer(0,USDplot,INDICATOR_DATA);              // array for rendering
   PlotIndexSetString(0,PLOT_LABEL,"USDplot");             // name of the indicator line (when selected with a mouse)
   PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,shiftbars);       // from which we begin rendering
   PlotIndexSetInteger(0,PLOT_DRAW_TYPE,DRAW_LINE);         // drawing style (line)
   PlotIndexSetInteger(0,PLOT_LINE_COLOR,Color_USD);       // color of line rendering
   if(StringFind(Symbol(),"USD",0)!=-1)
     {PlotIndexSetInteger(0,PLOT_LINE_WIDTH,wid_main);}    // if the symbol name contains USD 
                                                       // then draw a line of appropriate width 
   else
     {PlotIndexSetInteger(0,PLOT_LINE_STYLE,style_slave);}
   ArraySetAsSeries(USDplot,true);                       // indexation of array as a timeseries
   ArrayInitialize(USDplot,EMPTY_VALUE);                  // zero values 
   f_draw("USD",Color_USD);                             // rendering in the indicator information window 
  }
SetIndexBuffer(15,USDx,INDICATOR_CALCULATIONS);             // array of dollar index for calculations
                                                       // (is not displayed in the indicator as a line) 
ArraySetAsSeries(USDx,true);                             // indexation of an array as a time series
ArrayInitialize(USDx,EMPTY_VALUE);                        // zero values

if(ind_type==Use_Stochastic_Main_on_indexes)
  {
   SetIndexBuffer(23,USDstoch,INDICATOR_CALCULATIONS);      // if the destination of the indicator as a Use_Stochastic_Main_on_indexes,
                                                       // then this intermediate array is needed
   ArraySetAsSeries(USDstoch,true);                      // indexation of array as a time series
   ArrayInitialize(USDstoch,EMPTY_VALUE);                 // zero values
  }

if(EUR)
  {
   countVal++;
   SetIndexBuffer(1,EURplot,INDICATOR_DATA);              // array for rendering
   PlotIndexSetString(1,PLOT_LABEL,"EURplot");             // name of the indicator line (when pointed to with a mouse)
   PlotIndexSetInteger(1,PLOT_DRAW_BEGIN,shiftbars);       // which we begin rendering from
   PlotIndexSetInteger(1,PLOT_DRAW_TYPE,DRAW_LINE);         // drawing style (lines)
   PlotIndexSetInteger(1,PLOT_LINE_COLOR,Color_EUR);       // the color of rendering lines
   if(StringFind(Symbol(),"EUR",0)!=-1)
     {PlotIndexSetInteger(1,PLOT_LINE_WIDTH,wid_main);}    // if the symbol name contains EUR
                                                       // then we draw a line of the appropriate width 
   else
     {PlotIndexSetInteger(1,PLOT_LINE_STYLE,style_slave);}  // if the symbol name does NOT contain EUR,
                                                       // then we draw a line of an appropriate style (on the crosses)
   ArraySetAsSeries(EURplot,true);                       // indexation of the array as a time series
   ArrayInitialize(EURplot,EMPTY_VALUE);                  // zero values
   SetIndexBuffer(8,EURUSD,INDICATOR_CALCULATIONS);        // data of Close currency pair EURUSD
   ArraySetAsSeries(EURUSD,true);                        // indexation of the array as a time series
   ArrayInitialize(EURUSD,EMPTY_VALUE);                   // zero values
   SetIndexBuffer(16,EURx,INDICATOR_CALCULATIONS);         // array of the EURO index for calculations
                                                      // (not displayed on the indicator as a line) 
   ArraySetAsSeries(EURx,true);
   ArrayInitialize(EURx,EMPTY_VALUE);
   if(ind_type==Use_Stochastic_Main_on_indexes)
     {
      SetIndexBuffer(24,EURstoch,INDICATOR_CALCULATIONS);   // if the indicator destination as a Use_Stochastic_Main_on_indexes,
                                                       // then this intermediate array is needed
      ArraySetAsSeries(EURstoch,true);                   // indexation of the array as a time series
      ArrayInitialize(EURstoch,EMPTY_VALUE);              // zero values
     }
   f_draw("EUR",Color_EUR);                            // rendering in the indicator information window
  }
Ganz ähnlich wie bei dem EUR sieht der Code bei anderen Währungen aus, etwa bei GBP, JPY, CHF, CAD, AUD und NZD, wobei die Kennziffern der Zwischenspeicher entsprechend verschoben werden. Den Programmcode zu diesen Währungen finden Sie in der Datei mit dem Indikator im Anhang zu diesem Beitrag.

Damit ist die Bereitstellung des Indikators abgeschlossen.

Jetzt benötigen wir einige benutzerdefinierte Funktionen:

  • Zur Berechnung des RSI anhand des benutzerdefinierten Zwischenspeichers
  • Zur Berechnung des MACD
  • Zur Berechnung des SMA anhand des benutzerdefinierten Zwischenspeichers
  • Zur Berechnung des Stochastik Oszillators der Art „close/close“ ohne Glättung
  • Zur Abbildung der Objekte (informativ)
  • Für den Kommentar in der unteren rechten Ecke des Indikators (bezüglich des Indikatorzustands)
  • Zur Bereitstellung der Währungspaare der aktivierten Zeiträume

Ich werde jeden von ihnen kurz vorstellen:

  • Berechnung des RSI anhand des benutzerdefinierten Zwischenspeichers

Eingangsparameter:

double f_RSI(double &buf_in[], int period,int shift),

mit buf_in[] für ein Datenfeld (Array) der Art „double“ (wie Zeitreihen), period für den Zeitraum des Indikators RSI; und shift als der Balken des Index, für den wir den Indikator berechnen. Es wird ein Wert der Art „double“ ausgegeben.

  • Berechnung des MACD

Eingangsparameter:

double f_MACD(double &buf_in[], int period_fast,int period_slow,int shift),

mit buf_in[] für ein Datenfeld (Array) der Art „double“ (wie Zeitreihen); period_fast für den Zeitraum des schnell gleitenden Durchschnitts (fast МА); period_slow entsprechend für den Zeitraum des langsam gleitenden Durchschnitts (slow МА); und shift als der Balken des Index, für den wir den Indikator berechnen. Es wird ein Wert der Art „double“ ausgegeben.

  • Berechnung des SMA

Eingangsparameter:

double SimpleMA(const int position,const int period,const double &price[]),

mit position als der Balken des Index, für den wir den Indikator berechnen; period für den Zeitraum des Indikators SMA; und price[] für ein Datenfeld (Array) vom Typ „double“ (wie Zeitreihen). Es wird ein Wert der Art „double“ ausgegeben.

  • Zur Berechnung des Stochastik Oszillators der Art „close/close“ ohne Glättung

Eingangsparameter:

double f_Stoch(double &price[], int period_k, int shift),

mit price[] für ein Datenfeld der Art „double“ (wie Zeitreihen); period_fast für den Zeitraum der %K-Linie des Indikators; und shift als der Balken des Index, für den wir den Indikator berechnen. Es wird ein Wert der Art „double“ ausgegeben.

  • Abbildung der Objekte

Eingangsparameter:

int f_draw(string name, color _color)

mit name für Objektbezeichnung und _color für Objektfarbe. Die Funktion dient lediglich zur Information. In der oberen rechten Ecke des Indikatorfensters beginnend gibt sie die Bezeichnungen der aktivierten Währungen aus. Die Farbe des Währungstextes entspricht derjenigen der Linie des zu ihr gehörenden Indikators.

  • Kommentar in der unteren rechten Ecke des Indikators

Eingangsparameter:

int f_comment(string text)

text = in der unteren rechten Ecke des Indikators zu platzierender Text. Eine Art Fortschrittsleiste bezüglich der Arbeit des Indikators.

Und zu guter Letzt die abschließende und gleichzeitig eine der wichtigsten Funktionen, nämlich:

  • Die Bereitstellung der Währungspaare der aktivierten Zeiträume

Ohne Eingangsparameter.

In MetaTrader 5 wird der Kursverlauf in Form der Minutendaten des Zeitraums (Timeframe, TF) zu jedem Kürzel gespeichert. Deshalb werden beim Start der Anwendung auf dem Ausgabegerät (Terminal) vor Beginn der Arbeit mit dem Programm zunächst alle erforderlichen (aktivierten) Diagramme auf der Grundlage eben dieser Minutendaten des Zeitraums erstellt. Diese Erstellung findet auch bei einem Wechsel des Zeitraums des aktuellen Diagramms statt, oder bei dem Versuch, aus dem Code des MQL5-Programms auf das Diagramm für diesen Zeitraum zuzugreifen.

Deshalb:

  • muss beim ersten Aufruf der Anwendung auf dem Ausgabegerät (Terminal) eine Zeit lang gewartet werden, solange die erforderlichen Zeiträume der aktivierten Währungspaare angelegt werden (das geschieht möglicherweise im Hintergrund, sodass der Anwender es nicht sieht).
  • müssen die Nullbalken bei allen aktivierten Währungen zur exakten Wiedergabe des Indikators synchronisiert werden. Das heißt, wenn es auf dem aktuellen Balken zu einer Kursänderung (Tick) kommt, durch die ein neuer Balken eröffnet wird (zum Beispiel ein Stundenbalken), muss gewartet werden, bis dieselben Kursänderungen bei den anderen Währungspaaren eintreten, die darauf ihrerseits jeweils einen neuen Balken eröffnen (eine neue Stunde). Erst danach wird mit der Berechnung des Indikators für den neuen Balken begonnen.

Der erste Teil dieser Aufgabe wird mithilfe der im Lieferumfang enthaltenen Funktion Balken (Bars) umgesetzt, die die Anzahl der Balken im Verlauf für den dem Kürzel entsprechenden Zeitraum ausgibt. Es genügt, die unten vorgestellte Variante dieser Funktion zu verwenden.

int  Bars(
   string          symbol_name,   // symbol name
   ENUM_TIMEFRAMES   timeframe    // period
   );

In einem eigens dazu deklarierten Datenfeld wird die Anzahl der verfügbaren Balken für alle Währungspaare erfasst. Wir prüfen jeden Wert auf die erforderliche Mindestanzahl an Kursverlaufsdaten (die Variable „Anzahl der Balken zur Berechnung des Indikators“ in den Indikatoreinstellungen). Liegt die Anzahl der verfügbaren Balken in Kursverlauf irgendeines Instrumentes unter dem Wert dieser Variablen, müssen wir davon ausgehen, dass die Erstellung nicht erfolgreich war, und fragen die Anzahl der verfügbaren Daten erneut ab. Sobald die Menge der verfügbaren Verlaufsdaten zu allen Währungspaaren größer ist, als vom Anwender verlangt, gilt dieser Teil der Bereitstellung als erfolgreich ausgeführt.

Der zweite Teil der Synchronisierungsaufgabe wird mithilfe der Funktion CopyTime ausgeführt.

 Wir kopieren die Eröffnungszeit des Nullbalkens jedes aktivierten Instruments (Kürzels) in ein eigens für diese Zwecke bestimmtes Datenfeld. Wenn alle Elemente dieses Datenfeldes identisch und ungleich Null sind, ist davon auszugehen, dass unser Nullbalken synchronisiert ist, die Berechnung kann also beginnen. Ausführlichere Informationen dazu bietet der Programmcode des angehängten Indikators.

Damit beenden wir die Beschreibung der Zusatzfunktionen und gehen über zur Umsetzung der Funktion OnCalculate. Da es sich um einen mehrwährungsfähigen Indikator handelt, wird eine zweite Variante für den Aufruf dieser Funktion benötigt.

int OnCalculate(const int     rates_total, // size of incoming time series
                const int prev_calculated, // processing of bars on the previous request
                const datetime&    time[], // Time
                const double&      open[], // Open
                const double&      high[], // High
                const double&       low[], // Low
                const double&     close[], // Close
                const long& tick_volume[], // Tick Volume
                const long&      volume[], // Real Volume
                const int&       spread[]  // Spread
   );

Wir bestimmen die Anzahl der für die Berechnung erforderlichen Balken:

   int limit=shiftbars;

   if(prev_calculated>0)
     {limit=1;}
   else
     {limit=shiftbars;}

Wir synchronisieren die Diagramme der Währungspaare:

   init_tf();

Des Weiteren kopieren wir mithilfe der Funktion CopyClose die Schlussdaten aller benötigten Währungspaare in die eigens dafür angemeldeten Indikatorpuffer. (Ausführlicheres zum Zugriff auf die Daten anderer Zeiträume des aktuellen und/oder eines anderen Instrumentes (Kürzels) kann in der Hilfe nachgelesen werden)

Wenn die Funktion die Daten aus irgendeinem Grund nicht kopiert und die Antwort -1 ausgegeben hat, erscheint im Kommentar eine Fehlermeldung zu dem Währungspaar und wir warten auf das Eintreten einer neuen Kursänderung bei dem aktuellen Kürzel.

   if (EUR){copied=CopyClose("EURUSD",PERIOD_CURRENT,0,shiftbars,EURUSD); if (copied==-1){f_comment("Wait...EURUSD");return(0);}}
   if (GBP){copied=CopyClose("GBPUSD",PERIOD_CURRENT,0,shiftbars,GBPUSD); if (copied==-1){f_comment("Wait...GBPUSD");return(0);}}
   if (CHF){copied=CopyClose("USDCHF",PERIOD_CURRENT,0,shiftbars,USDCHF); if (copied==-1){f_comment("Wait...USDCHF");return(0);}}
   if (JPY){copied=CopyClose("USDJPY",PERIOD_CURRENT,0,shiftbars,USDJPY); if (copied==-1){f_comment("Wait...USDJPY");return(0);}}
   if (AUD){copied=CopyClose("AUDUSD",PERIOD_CURRENT,0,shiftbars,AUDUSD); if (copied==-1){f_comment("Wait...AUDUSD");return(0);}}
   if (CAD){copied=CopyClose("USDCAD",PERIOD_CURRENT,0,shiftbars,USDCAD); if (copied==-1){f_comment("Wait...USDCAD");return(0);}}
   if (NZD){copied=CopyClose("NZDUSD",PERIOD_CURRENT,0,shiftbars,NZDUSD); if (copied==-1){f_comment("Wait...NZDUSD");return(0);}}  

Weiterhin nehmen wir in dem Zyklus (von 0 bis zur Obergrenze) vor:

  • Die Berechnung des US Dollar Index;
  • Die Berechnung der Indices anderer Währungen auf der Grundlage der Schlussdaten (Close) und des US Dollar Index für den aktuellen Balken.
for (i=limit-1;i>=0;i--)
   {
      //calculation of USD index
      USDx[i]=1.0;
      if (EUR){USDx[i]+=EURUSD[i];}         
      if (GBP){USDx[i]+=GBPUSD[i];}
      if (CHF){USDx[i]+=1/USDCHF[i];}
      if (JPY){USDx[i]+=1/USDJPY[i];}
      if (CAD){USDx[i]+=1/USDCAD[i];}
      if (AUD){USDx[i]+=AUDUSD[i];}
      if (NZD){USDx[i]+=NZDUSD[i];}
      USDx[i]=1/USDx[i];
      //calculation of other currency values
      if (EUR){EURx[i]=EURUSD[i]*USDx[i];}
      if (GBP){GBPx[i]=GBPUSD[i]*USDx[i];}
      if (CHF){CHFx[i]=USDx[i]/USDCHF[i];}
      if (JPY){JPYx[i]=USDx[i]/USDJPY[i];}
      if (CAD){CADx[i]=USDx[i]/USDCAD[i];}
      if (AUD){AUDx[i]=AUDUSD[i]*USDx[i];}
      if (NZD){NZDx[i]=NZDUSD[i]*USDx[i];}
   }

Die Daten speichern wir in den entsprechenden Indikatorpuffern. Wir prüfen, welche Art Indikator von dem Anwender bei der Bereitstellung gewählt wurde, und nehmen auf dieser Grundlage die entsprechenden Berechnungen vor.

Wenn die Anzeige des RSI nach Indices gewünscht wurde, ist der folgende Code auszuführen:

if (ind_type==Use_RSI_on_indexes)
   {
      if (limit>1){ii=limit - rsi_period - 1;}
      else{ii=limit - 1;}
      for(i=ii;i>=0;i--)
         {
            if (USD){USDplot[i]=f_RSI(USDx,rsi_period,i);}
            if (EUR){EURplot[i]=f_RSI(EURx,rsi_period,i);}
            if (GBP){GBPplot[i]=f_RSI(GBPx,rsi_period,i);}
            if (CHF){CHFplot[i]=f_RSI(CHFx,rsi_period,i);}
            if (JPY){JPYplot[i]=f_RSI(JPYx,rsi_period,i);}
            if (CAD){CADplot[i]=f_RSI(CADx,rsi_period,i);}
            if (AUD){AUDplot[i]=f_RSI(AUDx,rsi_period,i);}
            if (NZD){NZDplot[i]=f_RSI(NZDx,rsi_period,i);}                  
         }
   }  

Soll der MACD nach Indices angezeigt werden, folgt (richtig, bisher wurde er nur auf der Grundlage des SimpleMA umgesetzt, die Umsetzung auf der Grundlage des EMA erfolgt später):

if (ind_type==Use_MACD_on_indexes)
   {
      if (limit>1){ii=limit - MACD_slow - 1;}
      else{ii=limit - 1;}
      for(i=ii;i>=0;i--)
         {
           if (USD){USDplot[i]=f_MACD(USDx,MACD_fast,MACD_slow,i);}
           if (EUR){EURplot[i]=f_MACD(EURx,MACD_fast,MACD_slow,i);}
           if (GBP){GBPplot[i]=f_MACD(GBPx,MACD_fast,MACD_slow,i);}
           if (CHF){CHFplot[i]=f_MACD(CHFx,MACD_fast,MACD_slow,i);}
           if (JPY){JPYplot[i]=f_MACD(JPYx,MACD_fast,MACD_slow,i);}
           if (CAD){CADplot[i]=f_MACD(CADx,MACD_fast,MACD_slow,i);}
           if (AUD){AUDplot[i]=f_MACD(AUDx,MACD_fast,MACD_slow,i);}
           if (NZD){NZDplot[i]=f_MACD(NZDx,MACD_fast,MACD_slow,i);}                  
         }
   } 

Im Fall des Stochastik Oszillators muss zunächst die %K-Linie berechnet und anschließend mithilfe der Methode SimpleMA geglättet werden. Die geglättete Ergebnislinie wird in dem Diagramm abgebildet.

if (ind_type==Use_Stochastic_Main_on_indexes)
   {
      if (limit>1){ii=limit - stoch_period_k - 1;}
      else{ii=limit - 1;}
      for(i=ii;i>=0;i--)
         {
           if (USD){USDstoch[i]=f_Stoch(USDx,rsi_period,i);}
           if (EUR){EURstoch[i]=f_stoch(EURx,stoch_period_k,i);}
           if (GBP){GBPstoch[i]=f_stoch(GBPx,stoch_period_k,i);}
           if (CHF){CHFstoch[i]=f_stoch(CHFx,stoch_period_k,i);}
           if (JPY){JPYstoch[i]=f_stoch(JPYx,stoch_period_k,i);}
           if (CAD){CADstoch[i]=f_stoch(CADx,stoch_period_k,i);}
           if (AUD){AUDstoch[i]=f_stoch(AUDx,stoch_period_k,i);}
           if (NZD){NZDstoch[i]=f_stoch(NZDx,stoch_period_k,i);}                  
         }
      if (limit>1){ii=limit - stoch_period_sma - 1;}
      else{ii=limit - 1;}
      for(i=ii;i>=0;i--)
         {
            if (USD){USDplot[i]=SimpleMA(i,stoch_period_sma,USDstoch);}
            if (EUR){EURplot[i]=SimpleMA(i,stoch_period_sma,EURstoch);}
            if (GBP){GBPplot[i]=SimpleMA(i,stoch_period_sma,GBPstoch);}
            if (CHF){CHFplot[i]=SimpleMA(i,stoch_period_sma,CHFstoch);}
            if (JPY){JPYplot[i]=SimpleMA(i,stoch_period_sma,JPYstoch);}
            if (CAD){CADplot[i]=SimpleMA(i,stoch_period_sma,CADstoch);}
            if (AUD){AUDplot[i]=SimpleMA(i,stoch_period_sma,AUDstoch);}
            if (NZD){NZDplot[i]=SimpleMA(i,stoch_period_sma,NZDstoch);}                  
          }                     
   }       

Damit sind die Indikatorberechnungen abgeschlossen. Die Abbildungen 4 -6 zeigen Beispiele unterschiedlicher Arten von Indikatoren.

Abbildung 4. RSI nach Indices

Abbildung 4. RSI nach Indices

Abbildung 5. MACD nach Währungsindices

Abbildung 5. MACD nach Währungsindices

Abbildung 6. Stochastik Oszillator nach Währungsindices

Abbildung 6. Stochastik Oszillator nach Währungsindices

Fazit

Bei der Umsetzung des Indikators MultiCurrencyIndex habe ich die unbegrenzte Anzahl an Indikatorpuffern in MQL5 ausgenutzt, was den Programmcode erheblich vereinfacht hat. Dieser Beitrag zeigt ein Beispiel für diesen Ansatz. Für zuverlässige Indikatoranzeigen wurde der Algorithmus zur Synchronisierung der unterschiedlichen Instrumente in Bezug auf den Nullbalken dargestellt. Ebenso wurde einer der möglichen Algorithmen für den Zugriff auf die Daten anderer Instrumente bezüglich des Kürzels, an das der Indikator angehängt ist, vorgeführt.

Da das Ziel des Beitrags war, die Möglichkeit der Arbeit mit einer immensen Anzahl von Indikatorpuffern vorzuführen, sind die vorgestellten Funktionen zur Berechnung von Indikatoren anhand benutzerdefinierter Datenfelder nicht die optimalsten, um die Leser nicht zu überfrachten, reichen jedoch zur Ausführung der erforderlichen Berechnungen aus.

Es spricht vieles „für“ und „gegen“ die Cluster-Analyse des Devisenmarktes. Auf diesem Ansatz beruhende Handelssysteme sind frei verfügbar und werden in unterschiedlichen Foren diskutiert, darunter auch in der MQL4.Community. Deshalb werden die Grundsätze des Handels mithilfe dieses Indikators in dem hier vorliegenden Artikel nicht behandelt.

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

Beigefügte Dateien |
Virtual Order Manager zum Verwalten von Ordern innerhalb der positionszentrischen Umgebung von MetaTrader 5 Virtual Order Manager zum Verwalten von Ordern innerhalb der positionszentrischen Umgebung von MetaTrader 5
Diese Klassenbibliothek kann einem Expert Advisor in MetaTrader 5 hinzugefügt werden, damit dieser orderzentrisch geschrieben werden kann, weitestgehend ähnlich zu MetaTrader 4, im Vergleich zum positionsbasierten Ansatz von MetaTrader 5. Dies geschieht durch die Verwaltung von virtuellen Ordern im MetaTrader 5 Client Terminal und die Aufrechterhaltung eines Schutzstopps des Brokers für jede Position, um vor Katastrophenfällen zu schützen.
Übersetzung von MQL4 in MQL5 Übersetzung von MQL4 in MQL5
Dieser Beitrag bietet eine Kurzanleitung zu den Funktionen der Programmiersprache MQL4 und hilft bei der Umstellung Ihrer Programme von MQL4 auf MQL5. Für jede MQL4-Funktion (mit Ausnahme der Handelsfunktionen) werden die entsprechende Beschreibung und die Bereitstellung in MQL5 vorgestellt, was den Zeitaufwand für den Wechsel erheblich verkürzt. Der Einfachheit halber wurden die MQL4-Funktionen ähnlich wie in der MQL4-Hilfe in Gruppen aufgeteilt.
Ein Beispiel für ein Handelssystem auf der Grundlage des Indikators Heiken-Ashi Ein Beispiel für ein Handelssystem auf der Grundlage des Indikators Heiken-Ashi
In diesem Beitrag betrachten wir die Verwendung eines Heikin-Ashi-Indikators im Handel. Basierend auf diesem Indikator wird ein einfaches Handelssystem betrachtet und ein Expert Advisor in MQL5 geschrieben. Handelstätigkeiten werden auf Basis der Klassen der Standard-Klassenbibliothek implementiert. Die auf der Historie basierenden und mithilfe des in MetaTrader 5 eingebauten Strategietesters erhaltenen Testergebnisse der geprüften Handelsstrategie werden in diesem Beitrag bereitgestellt.
MetaTrader 5: Handelsprognosen und Umsatzzahlen per E-Mail in Blogs, sozialen Netzen und auf thematischen Webseiten veröffentlichen MetaTrader 5: Handelsprognosen und Umsatzzahlen per E-Mail in Blogs, sozialen Netzen und auf thematischen Webseiten veröffentlichen
Dieser Beitrag zielt darauf ab, gebrauchsfertige Lösungen für die Veröffentlichung von Prognosen mittels MetaTrader 5. Er behandelt eine Reihe von Gedanken: von der Verwendung thematischer Webseiten zur Veröffentlichung von MetaTrader-Meldungen über die Erstellung einer eigenen Webseite ohne Erfahrung in Sachen Webprogrammierung bis hin zur abschließenden Einbindung in den Mikrobloggingdienst eines sozialen Netzes, die zahlreichen Leserinnen und Lesern ermöglicht, die Prognosen zu lesen und zu verfolgen. Alle hier vorgestellten Lösungen sind hundertprozentig kostenlos und können von allen eingerichtet werden, die über E-Mail- und FTP-Grundkenntnisse verfügen. Dem Einsatz derselben Verfahren für berufsmäßige Webhosting- und gewerbliche Handelsprognosedienste steht nichts entgegen.