English Русский 中文 Español 日本語 Português
Übertragen eines Indikator Code in einen Expert Advisor Code. Allgemeine Strukturelle Regelungen von Expert Advisor und Anzeigefunktionen

Übertragen eines Indikator Code in einen Expert Advisor Code. Allgemeine Strukturelle Regelungen von Expert Advisor und Anzeigefunktionen

MetaTrader 4Beispiele | 28 Januar 2016, 13:03
3 388 0
Nikolay Kositsin
Nikolay Kositsin

Einführung

In dem vorherigen Artikel (Transferring an Indicator Code into an Expert Advisor Code. Indicator Structure) haben wir die allgemeine Struktur eines Indikators analysiert, den Code, der gedacht ist für die Übertragung in einen Expert Advisor Code und beschrieben die Grundgedanken einer vorläufigen Einstellung eines Indikator Codes. Lassen Sie uns nun versuchen den erhaltenen Code in eine benutzerdefinierte Funktion zu verändern, weil das vielleicht die einfachste Art der Darstellung eines Indikators in einem Expert Advisor ist. Eine benutzerdefinierte Funktion kann als mqh-Datei dargestellt werden und ihre Deklaration im Expert Advisor, mit Verwendung der Anweisung #include, erfordert sehr wenig Platz. Das Aufrufen dieser Funktion ist nicht viel schwieriger als das Aufrufen eines spezifischen Indikators. Was wichtiger ist, solche benutzerdefinierten Funktionen können eher universell sein, für ihre weitere Verwendung in jedem Expert Advisor.

Bevor wir anfangen eine solche Funktion zu schreiben, lassen Sie uns analysieren wie diese Funktion mit dem anderen Teil des Expert Advisor interagieren wird, unabhängig von der inneren Struktur der Funktion.


Struktur eines EA mit Benutzerdefiniertem Indikator Aufruf

Lassen Sie uns zunächst den schematischen Aufbau eines EA untersuchen, der Daten von benutzerdefinierten Indikatoren erhält. In diesem EA sind wir vor allem nur an dem Teil interessiert, der Daten von einem benutzerdefinierten Indikator erhält. Bis jetzt werden wir nicht über die Art sprechen, wie der EA diese Daten verarbeitet, diese in Handelssignale überträgt und die Struktur eines ausführenden Teils des EA. Lassen Sie uns als benutzerdefinierten Indikator in diesem EA denjenigen analysieren, der im vorherigen Artikel besprochen wurde. Hier ist ein Beispiel einer Expert Advisor Struktur:

//+------------------------------------------------------------------+
//|                                               ExpertIndPlan0.mqh |
//|                      Copyright © 2007, MetaQuotes Software Corp. |
//|                                       https://www.metaquotes.net/ |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2007, MetaQuotes Software Corp."
#property link      "https://www.metaquotes.net/"
//---- EA input parameters
extern int period10 = 15;
extern int period11 = 15;
extern int period12 = 15;
//---- EA input parameters
extern int period20 = 15;
extern int period21 = 15;
extern int period22 = 15;
//---- Declaring buffers for indicator values
double Ind_Buffer1[6];
double Ind_Buffer2[6];
//+------------------------------------------------------------------+
//| Custom Expert initialization function                            |
//+------------------------------------------------------------------+
int init()
  {
// Here is the code of EA initialization
//---- initialization end
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom Expert iteration function                                 |
//+------------------------------------------------------------------+
int start()
  {
//---- Checking whether the bars number is enough for further calculation
   if(iBars(Symbol(), 0) < period10 + period11 + period12 + 10)
       return(0);
   if(iBars(Symbol(), 0) < period20 + period21 + period22 + 10)
       return(0);
//---- getting indicator values for further calculation
   for(int bar = 5; bar >= 1; bar--)
     {
       Ind_Buffer1[bar] = iCustom("IndicatorPlan", Symbol(), 0, period10, 
                                  period11, period12, 0, bar);
       Ind_Buffer2[bar] = iCustom("IndicatorPlan", Symbol(), 0, period20, 
                                  period21, period22, 0, bar);
     }
// Here is the EA code, forming trade signals 
// based on the values of indicator buffer cells 
//----
// here is the EA executive part code, 
// requesting for placing an order 
//----
   return(0);
  }
//+------------------------------------------------------------------+

In diesem Schema nehmen wir bei jedem Tick von einem Nullpuffer des benutzerdefinierten Indikators IndicatorPlan.mq4 gezählte Werte in zwei Aufrufen und platzieren sie in gemeinsamen Arrays Ind_buffer1[] und Ind_Buffer2[]. Das Schema des Aufrufens eines Indikators wurde mit der Überlegung gemacht, dass wir für weitere Berechnungen nur die fünf letzten Indikatorwerte benötigen, mit Ausnahme des Null-Wertes.


Struktur eines EA mit Benutzerdefiniertem Funktionsaufruf

Während wir eine universelle Anzeigefunktion entwickeln, geeignet für jeden Expert Advisor, sollte sie die erhaltenen Werte an Indikator-Analoga senden, die Indikatorwerte für alle Balken des Charts speichern werden. Natürlich, wir könnten eine Anzeigefunktion entwickeln, die komplett analog wäre zum Aufruf eines Indikators, aber eine solche Funktion zu schreiben würde zu viel Zeit in Anspruch nehmen und der Code wird sehr lang.

Wir können es einfacher machen. Diese Funktion sollte als Eingabe die Parameter eines benutzerdefinierten Indikators und Puffer empfangen, und sie sollte den gleichen Puffer mit einer Anzeigemodus-Emulation zurückgeben, wobei Zellen mit berechneten Indikatorwerten gefüllt werden. Es kann in unserer Funktion einfach gemacht werden durch Deklarieren einer durch Verweis verknüpften externen Variable, entsprechend einem Anzeigepuffer. In der MQL4 Sprache wird es wie dieses aussehen: double& InputBuffer. Die Anzeigefunktion sollte als eine logische deklariert sein, 'true' zurückgeben, wenn eine Berechnung erfolgreich war, und 'false', wenn eine Berechnung erfolglos war aufgrund des Fehlens der richtigen Anzahl an Balken im Chart. Nach diesen Erklärungen sollte die Anzeigefunktion, aufgebaut nach dem Indikatorschema, besprochen im vorherigen Artikel, die folgende Form haben:

bool Get_IndSeries(int Number,string symbol, int timeframe, 
                   bool NullBarRecount, int period0, int period1, 
                   int period2, double& InputBuffer0[],
                   double& InputBuffer1[], double& InputBuffer2[])

Die Anzeigefunktion hat eine zusätzliche externe variable Zahl, die den Wert von dieser Anzeigefunktion Aufrufnummer übernimmt.

Es ist natürlich, dass, mit Ausnahme des Anzeigepuffer InputBuffer0, die externen Variablen auch Puffer enthalten für Zwischenberechnungen, InputBuffer1 und InputBuffer2, weil es sehr problematisch ist, diese Puffer innerhalb der Funktion unterzubringen. Es ist besser den Anzeigemodus dieser Puffer-Operation innerhalb der Funktion zu emulieren. Es wird keine Probleme verursachen. Lassen Sie uns nun auf die Bedeutung der externen Variable NullBarRecout eingehen. Tatsächlich benötigt die Mehrheit der EAs keine Berechnungen auf der Null-Bar, und während wir den Code für eine universelle Anzeigefunktion schreiben, wird es die Indikatorwerte natürlich auf der Null-Bar berechnen, was die Ausführungszeit erheblich erhöhen kann. Durch die Angabe externer Parameter der Funktion NullBarRecount als 'false', verbieten wir der Funktion Berechnungen auf der Null-Bar, wenn es nicht notwendig ist.

Jetzt können wir das Schema einer EA-Struktur für den Aufruf von Indikatoren in einer Variante mit Aufruffunktionen darstellen:

//+------------------------------------------------------------------+
//|                                               ExpertIndPlan1.mqh |
//|                      Copyright © 2007, MetaQuotes Software Corp. |
//|                                       https://www.metaquotes.net/ |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2007, MetaQuotes Software Corp."
#property link      "https://www.metaquotes.net/"
//---- EA input parameters
extern int period10 = 15;
extern int period11 = 15;
extern int period12 = 15;
//---- EA input parameters
extern int period20 = 15;
extern int period21 = 15;
extern int period22 = 15;
//---- Indicator buffers declaration
double Ind_Buffer10[], Ind_Buffer11[], Ind_Buffer12[];
double Ind_Buffer20[], Ind_Buffer21[], Ind_Buffer22[];
//+------------------------------------------------------------------+
//| Get_IndSeries() function                                         |
//+------------------------------------------------------------------+
//---- Declaration of the function Get_IndSeries()
bool Get_IndSeries(int Number,string symbol, int timeframe, 
                   bool NullBarRecount, int period0, int period1, 
                   int period2, double& InputBuffer0[], 
                   double& InputBuffer1[], double& InputBuffer2[]) 
  {
    //---- 
    // Here is the code of the function GetIdicator()
    //----
    return(true);
  }
//+------------------------------------------------------------------+
//| Custom Expert initialization function                            |
//+------------------------------------------------------------------+
int init()
  {
//----
// Here is the code of the EA initialization
//---- initialization end
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom Expert iteration function                                 |
//+------------------------------------------------------------------+
int start()
  {
//---- Checking whether the bars number is enough for further calculation
   if(iBars(Symbol(), 0) < period10 + period11 + period12 + 10)
      return(0);
   if(iBars(Symbol(), 0) < period20 + period21 + period22 + 10)
      return(0);
//---- getting indicator values for further calculation
   if(!Get_IndSeries(0,Symbol(), 0, false, period10, period11, period12,
      Ind_Buffer10, Ind_Buffer11, Ind_Buffer12))
       return(0);
   if(!Get_IndSeries(1, Symbol(), 0, false, period20, period21, period22, 
      Ind_Buffer20, Ind_Buffer21,Ind_Buffer22))
       return(0);  
//----
// Here is the EA code, forming trade signals 
// based on the values of indicator buffer cells 
//----
// here is the EA executive part code, 
// requesting for placing an order
//----
 
   return(0);
  }
//+------------------------------------------------------------------+


Allgemeines Schema der Umwandlung eines Indikator-Code in eine Benutzerdefinierte Funktion

Nach diesen Vorarbeiten können wir weitergehen zum Aufbau eines Allgemeinen Schemas einer inneren Struktur einer Anzeigefunktion. Lassen Sie uns als Basis das letzte Anzeigeschema des vorherigen Artikels nehmen. Es sollte keine Schwierigkeiten geben:

1. Nehmen Sie nur die Inhalte der Funktion int start(),

2. Hinzufügen der Deklaration der Funktion Get_IndSeries():

bool Get_IndSeries(string symbol, int timeframe, bool NullBarRecount,
                   int period0, int period1, int period2, 
                   double& InputBuffer0, double& InputBuffer1, 
                   double& InputBuffer2)

3. Ändern Sie die Namen der Anzeigepuffer innerhalb des codes (Ind_buffer) entsprechend in Puffernamen (InputBuffer) der externen Variablen der Funktion Get_IndSeries(),

4. Hinzufügen der Deklaration der Variable LastCountBar,

5. Prüfen Sie Wahrheit der Variable NullBarRecount:

if(!NullBarRecount)
    LastCountBar = 1;

6. In allen Zyklen der Anzeigeberechnung ändern Sie Zero in LastCountBar,

7. Machen Sie Änderungen ganz am Anfang des Codes, bei der Prüfung, ob die Anzahl der Balken ausreichend für weitere Berechnungen ist: return(0) in return(false),

8. Am Ende des Codes ändern Sie return(0) in return(true);

Die Anzeigefunktion ist fertig:

//+------------------------------------------------------------------+
//|                                                Get_IndSeries.mqh |
//|                      Copyright © 2007, MetaQuotes Software Corp. |
//|                                        https://www.metaquotes.net/ |
//+------------------------------------------------------------------+ 
bool Get_IndSeries(int Number, string symbol,int timeframe, 
                   bool NullBarRecount, int period0, int period1, 
                   int period2, double& InputBuffer0[], 
                   double& InputBuffer1[], double& InputBuffer2[])  
  {
//---- getting the number of all bars of a chart
   int IBARS = iBars(symbol, timeframe);
//---- Checking whether the bars number is enough for further calculation
   if(IBARS < period0 + period1 + period2)
      return(false);
//---- EMULATION OF INDICATOR BUFFERS
   if(ArraySize(InputBuffer0) < IBARS)
     {
       ArraySetAsSeries(InputBuffer0, false);
       ArraySetAsSeries(InputBuffer1, false);
       ArraySetAsSeries(InputBuffer2, false);
       //----  
       ArrayResize(InputBuffer0, IBARS); 
       ArrayResize(InputBuffer1, IBARS); 
       ArrayResize(InputBuffer2, IBARS); 
       //----
       ArraySetAsSeries(InputBuffer0, true);
       ArraySetAsSeries(InputBuffer1, true);
       ArraySetAsSeries(InputBuffer2, true); 
     } 
//----+ introducing static memory variables
   static int IndCounted[];
//----+ changing the size of static variables
   if(ArraySize(IndCounted) < Number + 1)
       ArrayResize(IndCounted, Number + 1); 
//----+ introducing an integer variable
   int LastCountBar;
//----+ Checking if the recalculation of the zero bar is allowed
   if(!NullBarRecount)
       LastCountBar = 1;
   else 
       LastCountBar = 0;
//----+ Inserting a variable with a floating point
   double Resalt0, Resalt1, Resalt2;
//----+ Inserting integer variables and getting already calculated bars
   int limit, MaxBar, bar, counted_bars = IndCounted[Number];
//----+ Remembering the number of all bars of a chart (we do not count the zero bar!)
   IndCounted[Number] = IBARS - 1;
//---- defining the number of the oldest bar, 
// starting from which new bars will be recalculated
   limit = IBARS - counted_bars - 1; 
//---- defining the number of the oldest bar, 
// starting from which new bars will be recalculated
   MaxBar = IBARS - 1 - (period0 + period1 + period2); 
//---- initialization of zero 
   if(limit > MaxBar)
     {
       limit = MaxBar;
       for(bar = IBARS - 1; bar >= 0; bar--)
         {
           InputBuffer0[bar] = 0.0;
           InputBuffer1[bar] = 0.0;
           InputBuffer2[bar] = 0.0;
         }
     }
//----+ THE FIRST CYCLE OF INDICATOR CALCULATION 
   for(bar = limit; bar >= LastCountBar; bar--)
     {
       // Here code of the variable Resalt1 calculation  
       // based on the external variable period1
       InputBuffer1[bar] = Resalt1;
     }
//----+ THE SECOND CYCLE OF INDICATOR CALCULATION 
   for(bar = limit; bar >= LastCountBar; bar--)
     {
       // Here code of the variable Resalt2 calculation 
       // based on the values of the buffer Ind_Buffer1[] 
       // and external variable period2
       InputBuffer2[bar] = Resalt2;
     }
//----+ THE MAIN CYCLE OF INDICATOR CALCULATION 
   for(bar = limit; bar >= LastCountBar; bar--)
     {
       // Here code of the variable Resalt0 calculation 
       // based on the values of the buffer Ind_Buffer2[] 
       // and external variable period0
       InputBuffer0[bar] = Resalt0;
     }
   return(true);
  }
//+------------------------------------------------------------------+

Ich denke, wenn ein Leser MQL4 sehr gut verwendet, wird er nach dem Lesen der oben beschriebenen Vorgänge keine Schwierigkeiten haben, beim Schreiben von Anzeigefunktionen nach dem angegebenen Schema.


Beispiel des Schreibens einer Benutzerspezifischen Anzeigefunktion

Lassen Sie uns nun eine Anzeigefunktion schreiben. Dazu nehmen wir einen möglichst einfachen Indikator:

//+------------------------------------------------------------------+
//|                                                         RAVI.mq4 |
//|                      Copyright © 2005, MetaQuotes Software Corp. |
//|                                       https://www.metaquotes.net/ |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2005, MetaQuotes Software Corp."
#property link      "https://www.metaquotes.net/"
//---- drawing the indicator in a separate window
#property indicator_separate_window 
//---- number of indicator buffers
#property indicator_buffers 1 
//---- indicator color
#property indicator_color1 Red 
//---- INPUT PARAMETERS OF THE INDICATOR 
extern int Period1 = 7; 
extern int Period2 = 65; 
extern int MA_Metod = 0;
extern int PRICE = 0;
//---- indicator buffers
double ExtBuffer[]; 
//+------------------------------------------------------------------+ 
//| RAVI initialization function                                     | 
//+------------------------------------------------------------------+ 
int init() 
  { 
//---- indicator drawing style
   SetIndexStyle(0, DRAW_LINE); 
//---- indicator buffers 
   SetIndexBuffer(0,ExtBuffer); 
//---- indicator name and labels for subwindows 
   IndicatorShortName("RAVI (" + Period1+ ", " + Period2 + ")"); 
   SetIndexLabel(0, "RAVI"); 
//---- initialization end
   return(0); 
  } 
//+------------------------------------------------------------------+ 
//| RAVI iteration function                                          | 
//+------------------------------------------------------------------+ 
int start() 
  {
   int MinBars = MathMax(Period1, Period2); 
//---- checking whether the bars number is enough for further calculation
   if(Bars < MinBars)
       return(0);
//----+ Introducing variables with a floating point 
   double MA1, MA2, result; 
//----+ Introducing integer variables and getting already calculated bars
   int MaxBar, bar, limit, counted_bars = IndicatorCounted();
//---- checking for possible errors
   if(counted_bars < 0)
       return(-1);
//---- the last calculated bar should be recalculated 
   if(counted_bars > 0)
       counted_bars--;
//---- defining the number of the oldest bar, 
// starting from which all bars will be recalculated 
   MaxBar = Bars - 1 - MinBars;
//---- defining the number of the oldest bar, 
// starting from which new bars will be recalculated 
   limit = Bars - counted_bars - 1; 
//---- zero initialization
   if(limit > MaxBar)
     {
       for(int ii = Bars - 1; ii >= MaxBar; ii--)
           ExtBuffer[ii] = 0.0;
       limit = MaxBar;
     }
//---- main cycle 
   for(bar = 0; bar <= limit; bar++) 
     { 
       MA1 = iMA(NULL, 0, Period1, 0, MA_Metod, PRICE,bar); 
       MA2 = iMA(NULL, 0, Period2, 0, MA_Metod, PRICE,bar); 
       //---- 
       result = ((MA1 - MA2) / MA2)*100; 
       ExtBuffer[bar] = result; 
     }  
//---- 
   return(0); 
  } 
//+------------------------------------------------------------------+


Algorithmus festlegen

1. Alle unnötigen Elemente des Indikator-Codes loswerden,

2. Schreiben Sie den Code für die Anzeigepuffer-Emulation für einen einzelnen Puffer ExtBuffer[],

3. Ersetzen Sie die Funktion IndicatorCounted() für die Variable IndCounted,

4. Initialisieren Sie die Variable IndCounted durch die Menge der Chart-Balken minus eins,

5. Ädern Sie vorgegebene variable Balken in den Aufruf der Zeitreihen iBars (Symbol, Zeitrahmen),

6. Löschen Sie die nicht benötigte Überprüfung für counted_bars:

//---- checking possible errors
if(counted_bars < 0)
    return(-1);
//---- the last calculated bar must be recalculated 
if(counted_bars > 0) 
    counted_bars--;

7. Belassen Sie nur die Inhalte der Funktion int start(),

8. Hinzufügen der Deklaration der Funktion Get_RAVISeries():

bool Get_RAVISeries(int Number, string symbol,int timeframe, 
                    bool NullBarRecount, int Period1, 
                    int Period2, int MA_Metod, int  PRICE, 
                    double& InputBuffer[])

9. Ersetzen Sie die Anzeigepuffer-Namen innerhalb des Codes (ExtBuffer) entsprechend für Puffer-Namen (InputPuffer) vo externen Variablen der Funktion Get_RAVISeries(),

10. Hinzufügen der Deklaration der Variable LastCountBar,

11. Ändern Sie die statische Variable IndCount in ein Array IndCounted[Number] und fügen Sie einen Code hinzu zum Ändern der Größe von Variablen, abhängig von der Anzahl an Aufrufen der Funktion Get_RAVISeries. mqh:

//----+ changing the size of static variables
   if(ArraySize(IndCounted) < Number + 1)
     {
       ArrayResize(IndCounted, Number + 1); 
     }

12. Prüfen Sie die Wahrheit der Variable NullBarRecount:

if(!NullBarRecount)
    LastCountBar = 1;

13. In allen Anzeigeberechnungszyklen ändern Sie Null in LastCountBar:

for(bar = limit; bar >= LastCountBar; bar--)

14. Machen Sie eine Änderung am Anfang des Codes, wo geprüft wird ob die Anzahl der Balken ausreichend ist: return(0) in return(false),

15. Am Ende ersetzen Sie return(0) mit return(true).

Nach allen Änderungen des Codes erhalten wir die Anzeigefunktion Get_RAVISeries():

//+------------------------------------------------------------------+
//|                                               Get_RAVISeries.mqh |
//|                      Copyright © 2007, MetaQuotes Software Corp. |
//|                                       https://www.metaquotes.net/ |
//+------------------------------------------------------------------+
bool Get_RAVISeries(int Number, string symbol,int timeframe, 
                    bool NullBarRecount, int Period1, int Period2, 
                    int MA_Metod, int  PRICE, double& InputBuffer[])    
  {
//---- getting the number of all bars of a chart
   int IBARS = iBars(symbol, timeframe);  
//---- Checking whether the bars number is enough for further calculation
   if(IBARS < MathMax(Period1, Period2))
       return(false);
//---- EMULATION OF INDICATOR BUFFERS
   if(ArraySize(InputBuffer) < IBARS)
     {
       ArraySetAsSeries(InputBuffer, false);
       //----  
       ArrayResize(InputBuffer, IBARS); 
       //----
       ArraySetAsSeries(InputBuffer, true);
     } 
//----+  inserting static variables of memory
   static int IndCounted[]; 
//----+ changing the size of static variables
   if(ArraySize(IndCounted) < Number + 1)
     {
       ArrayResize(IndCounted, Number + 1); 
     }
 //----+ Introducing an integer variable
   int LastCountBar;
//----+ Checking whether the recalculation of the zero bar is allowed
   if(!NullBarRecount)
       LastCountBar = 1;
//----+ Introducing floating point variables 
   double MA1,MA2,result; 
//----+ Introducing integer variables and getting alreadu calculated bars
   int MaxBar, bar, limit, counted_bars = IndCounted[Number];
//----+ Remembering the amount of all chart bars
   IndCounted[Number] = IBARS - 1;
//---- determining the number of the oldest bar, 
// starting from which new bars will be recalculated
   limit = IBARS - counted_bars - 1; 
   // Print(IBARS - counted_bars); 
//---- determining the number of the oldest bar, 
// starting from which all bars will be recalculated
   MaxBar = IBARS - 1 - MathMax(Period1, Period2); 
//---- zero initialization 
   if(limit > MaxBar)
     {
       limit = MaxBar;
       for(bar = IBARS - 1; bar >= 0; bar--)
         {
           InputBuffer[bar] = 0.0;
         }
     } 
//----+ THE FIRST CYCLE OF INDICATOR CALCULATION 
   for(bar = limit; bar >= LastCountBar; bar--)
     { 
       MA1 = iMA(symbol, timeframe, Period1, 0, MA_Metod, PRICE, bar); 
       MA2 = iMA(symbol, timeframe, Period2, 0, MA_Metod, PRICE, bar); 
       //---- 
       result = ((MA1 - MA2) / MA2)*100; 
       InputBuffer[bar] = result; 
     } 
//----+  
   return(true);
  }
//+------------------------------------------------------------------+

Sicher, all dies ist großartig! Kompetent, nicht zu einfach. Aber eine Frage kommt auf - wird diese Anzeigefunktion das gleiche berechnen wie ein benutzerdefinierter Indikator?


Testen der Benutzerdefinierten Anzeigefunktion auf Rechengenauigkeit

Wir müssen prüfen, ob die Funktions-Berechnungsergebnisse gleich sind, wie die der Berechnung eines benutzerdefinierten Indikators. Zu diesem Zweck ist der beste Expert Advisor derjenige, der nicht tradet und nur Werte erhält von dem benutzerdefinierten Indikator RAVI.mq4 und der benutzerdefinierten Funktion Get_RAVISeries(), die Unterschiede findet und danach den Anzeigewert, den Wert der benutzerdefinierten Anzeige und die Differenz zwischen ihnen in eine Protokolldatei sendet. Alles was wir tun müssen, ist den Inhalt der Protokolldatei zu analysieren, um die endgültige Aussage zu machen über die Übereinstimmung der benutzerdefinierten Funktion mit dem Indikator RAVI.mq4:

//+------------------------------------------------------------------+
//|                                           Get_RAVISeriesTest.mq4 |
//|                      Copyright © 2007, MetaQuotes Software Corp. |
//|                                       https://www.metaquotes.net/ |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2007, MetaQuotes Software Corp."
#property link      "https://www.metaquotes.net/"
//---- INPUT EA PARAMETERS
extern bool NullBarRecount = true;
//---- indicator buffers
double RAVI_Buffer0[];
double RAVI_Buffer1[];
double RAVI_Buffer2[];
//+------------------------------------------------------------------+
//| Get_RAVISeries() function                                        |
//+------------------------------------------------------------------+
#include <Get_RAVISeries.mqh>
//+------------------------------------------------------------------+
//| Custom Expert initialization function                            |
//+------------------------------------------------------------------+
int init()
  {
//---- initialization end
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom Expert iteration function                                 |
//+------------------------------------------------------------------+
int start()
  {
//---- 
   double Ind_Velue, Resalt;
//---- 
   if(!Get_RAVISeries(0, Symbol(), 0, NullBarRecount, 10, 20, 1, 0,
      RAVI_Buffer0))
       return(0);  
   if(!Get_RAVISeries(1, Symbol(), 240, NullBarRecount, 25, 66, 2, 1,
      RAVI_Buffer1))
       return(0);
   if(!Get_RAVISeries(2, Symbol(), 1440, NullBarRecount, 30, 70, 3, 3,
      RAVI_Buffer2))
       return(0);
//---- getting indicator values for the test 0
   Ind_Velue = iCustom(NULL, 0, "RAVI", 10, 20, 1, 0, 0, 2); 
   Resalt = RAVI_Buffer0[2] - Ind_Velue; 
   Print("  " + Ind_Velue + "    " + RAVI_Buffer0[2] + "    " + Resalt+"");
//---- getting indicator values for the test 1
   Ind_Velue = iCustom(NULL, 240, "RAVI", 25, 66, 2, 1, 0, 2);
   Resalt = RAVI_Buffer1[2] - Ind_Velue; 
   Print("  " + Ind_Velue + "    " + RAVI_Buffer1[2] + "    " + Resalt+"" );
//---- getting indicator values for the test 2
   Ind_Velue = iCustom(NULL, 1440, "RAVI", 30, 70, 3, 3, 0, 2);
   Resalt = RAVI_Buffer2[2] - Ind_Velue; 
   Print("  " + Ind_Velue + "    " + RAVI_Buffer2[2] + "    " + Resalt + "");
//----
   return(0);
  }
//+------------------------------------------------------------------+

In einem Strategietester starten Sie den Expert Advisor Get_RAVISeriesTest. Selbstverständlich muss die kompilierte Datei RAVI.mq4 bereits in dem Ordner expert\indicators sein, und die Dateio GetRAVIseries.mqh in dem Ordner \expert \indicators des MetaTrader Client Terminals. Im Strategietester-Journal und in einer Protokolldatei sehen wir zwei Spalten mit Anzeigewerten und ihr Analogon in der Form einer Funktion. Die dritte Spalte zeigt die Differenz dieser Werte. Alle Werte der letzten Spalte sind gleich Null. Es bedeutet, die Werte sind in beiden Fällen identisch. Wir können feststellen, dass die Aufgabe des Schreibens einer benutzerdefinierten Anzeigefunktion erfolgreich gelöst ist!


Fazit

Es gelang uns also die Aufgabe der Übertragung eines Indikator-Codes aus einem benutzerdefinierten Indikator in einen Expert Advisor Code, durch das Herstellen eines Analogon des Indikators als universelle benutzerdefinierte Funktion, die in jeder mqh-Datei platziert werden und in dem Code von jedem Expert Advisor verwendet werden kann, analog zu einem benutzerdefinierten Indikator.

In dem Nächsten Artikel zu diesem Thema, analysieren wir ein schwierigeres Beispiel des Schreibens von Funktionen dieser Art und die Implementierung eines einfachen Expert Advisor, basieren auf einer solchen Funktion.

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

Beigefügte Dateien |
ExpertIndPlan0.mqh (2.27 KB)
ExpertIndPlan1.mqh (2.89 KB)
RAVI.mq4 (2.93 KB)
Terminal Service Client. Wie man einen Pocket PC zu Big Brothers Freund macht Terminal Service Client. Wie man einen Pocket PC zu Big Brothers Freund macht
Der Artikel beschreibt die Art und Weise der Verbindung eines Remote-PCs mit installiertem MT4-Client Terminal über einen PDA.
Schnelleinstieg oder Kurzanleitung für Anfänger Schnelleinstieg oder Kurzanleitung für Anfänger
Liebe Leser, in diesem Artikel möchte ich Ihnen vermitteln und zeigen, wie man sich möglichst schnell und einfach die Grundlagen der Erstellung automatischer Handelssysteme, wie die Arbeit mit Indikatoren u. a., erschließt. Der Beitrag richtet sich an Neueinsteiger, in ihm kommen weder komplizierte noch schwer zu verstehende Beispiele zur Anwendung.
Ein Expert Advisor auf Bestellung gemacht. Handbuch für einen Trader Ein Expert Advisor auf Bestellung gemacht. Handbuch für einen Trader
Nicht alle Trader sind Programmierer. Und nicht alle Programmierer sind wirklich gut. Also, was sollte getan werden, wenn Sie Ihr System automatisieren müssen und keine Zeit und Lust haben MQL4 zu studieren?
Auftragsstrategien. Ein universelles automatisches Handelssystem Auftragsstrategien. Ein universelles automatisches Handelssystem
In diesem Beitrag dreht sich alles um Strategien, in denen bedingte Aufträge (Pending Orders) intensiv genutzt werden, um eine Metasprache, die geschaffen werden kann, um diese Strategien in Formelsprache zu beschreiben, und um die Verwendung eines universellen automatischen Handelssystems, dessen Arbeitsweise auf diesen Beschreibungen beruht.