Diskussion zum Artikel "Erweiterung der MQL5-Standardbibliothek und Wiederverwendung von Code" - Seite 2

 
Tango_X:


Helfen Sie mir zu verstehen, wie die Indizierung Richtung der Indikator-Puffer-Array hier festgelegt ist, d.h. das gleiche wie ArraySetAsSeries. Die Standardrichtung ist von der Gegenwart zur Vergangenheit, aber ich muss es von der Vergangenheit zur Gegenwart machen. Ich kämpfe seit gestern mit dieser Frage! Hilfe!

Es ist nicht notwendig, da es den Standard ZigZag verwendet.

//--- erstellen
   m_handle=iCustom(symbol,period,"zigzag",depth,deviation_create,backstep);

Suchen Sie die Stelle, an der die Richtung in diesem ZigZag festgelegt ist, aber es ist immer noch unklar, warum Sie es brauchen - Sie können die Indizierungsrichtung jederzeit selbst ändern - https://www.mql5.com/de/docs/series.

Документация по MQL5: Доступ к таймсериям и индикаторам
Документация по MQL5: Доступ к таймсериям и индикаторам
  • www.mql5.com
Доступ к таймсериям и индикаторам - справочник по языку алгоритмического/автоматического трейдинга для MetaTrader 5
 
Rashid Umarov:

Das ist nicht nötig, denn es verwendet den Standard-ZigZag

Suchen Sie in diesem ZigZag nach der Stelle, an der die Richtung festgelegt ist. Aber es ist immer noch unklar, warum Sie es brauchen - Sie können die Richtung der Indizierung jederzeit selbst ändern - https://www.mql5.com/de/docs/series.


Vielen Dank für die Information, wir werden uns das ansehen!

 
Rashid Umarov:

Es braucht sie nicht, da es den Standard-ZigZag verwendet

In diesem ZigZag suchen Sie nach der Stelle, an der die Richtung eingestellt ist. Aber es ist immer noch nicht klar, warum Sie es brauchen - Sie können die Indizierungsrichtung jederzeit selbst ändern - https://www.mql5.com/de/docs/series.


Es tut mir leid, aber es ist immer noch nicht klar, wie man die Indizierungsrichtung ändern kann, zum Beispiel, wenn man keinen Zugriff auf die Zigzag-Quelle hat. Die Indizierungsrichtung wird mit ArraySetAsSeries() gesetzt - wobei der Eingabeparameter ein Array per Referenz ist,

aber wir haben dieses Array nicht, sondern nur einen Zeiger auf das Indikatorpuffer-Array in Form von

//--- Puffer erstellen
      ((CIndicatorBuffer*)At(0)).Name("ZIGZAG");
      ((CIndicatorBuffer*)At(1)).Name("HIGH");
      ((CIndicatorBuffer*)At(2)).Name("LOW");
 
//+------------------------------------------------------------------+
//|OOO_ZIGZAG.mq5 |
//| Copyright 2017, MetaQuotes Software Corp. | |
//|https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2017, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property indicator_chart_window
#include <..\Include\Indicators\Indicator.mqh>


//--- Eingabeparameter
input ENUM_TIMEFRAMES   EAPeriod=PERIOD_CURRENT; //Zeitraum einplanen
input string            CurrencyPair="EURUSD.m"; //Symbol

//+------------------------------------------------------------------+
//| Klasse CiZigZag.|
//| Zweck: ZigZag-Indikator Klasse.
//| Ausgabe der Klasse CIndicator.|
//+------------------------------------------------------------------+
class CiZigZag : public CIndicator
  {
protected:
   int               m_depth;
   int               m_deviation;
   int               m_backstep;

public:
                     CiZigZag(void);
                    ~CiZigZag(void);
   //--- Methoden des Zugriffs auf geschützte Daten
   int               Depth(void)          const { return(m_depth);      }
   int               Deviation(void)      const { return(m_deviation);  }
   int               Backstep(void)       const { return(m_backstep);   }
   //--- Erstellungsmethode
   bool              Create(const string symbol,const ENUM_TIMEFRAMES period,
                            const int depth,const int deviation_create,const int backstep);
   //--- Methoden für den Zugriff auf Indikatordaten
   double            ZigZag(const int index) const;
   double            High(const int index) const;
   double            Low(const int index) const;
   //--- Identifizierungsverfahren
   virtual int       Type(void) const { return(IND_CUSTOM); }

protected:
   //--- Anpassungsmethoden
   virtual bool      Initialize(const string symbol,const ENUM_TIMEFRAMES period,const int num_params,const MqlParam &params[]);
   bool              Initialize(const string symbol,const ENUM_TIMEFRAMES period,
                                const int depth,const int deviation_init,const int backstep);
  };
//+------------------------------------------------------------------+
//| Konstruktor|
//+------------------------------------------------------------------+
CiZigZag::CiZigZag(void) : m_depth(-1),
                         m_deviation(-1),
                         m_backstep(-1)
  {
  }
//+------------------------------------------------------------------+
//| Destruktor|
//+------------------------------------------------------------------+
CiZigZag::~CiZigZag(void)
  {
  }
//+------------------------------------------------------------------+
//|| Erstellen Sie den "Zig Zag"-Indikator|
//+------------------------------------------------------------------+
bool CiZigZag::Create(const string symbol,const ENUM_TIMEFRAMES period,
                      const int depth,const int deviation_create,const int backstep)
  {
//--- Verlauf prüfen
   if(!SetSymbolPeriod(symbol,period))
      return(false);
//--- erstellen
   m_handle=iCustom(symbol,period,"Examples\\ZigZag",depth,deviation_create,backstep);
//--- Prüfung des Ergebnisses
   if(m_handle==INVALID_HANDLE)
      return(false);
//--- Indikator erfolgreich erstellt
   if(!Initialize(symbol,period,depth,deviation_create,backstep))
     {
      //--- Initialisierungsfehler
      IndicatorRelease(m_handle);
      m_handle=INVALID_HANDLE;
      return(false);
     }
//--- ok
   return(true);
  }
//+------------------------------------------------------------------+
//| Initialisieren des Indikators mit universellen Parametern |
//+------------------------------------------------------------------+
bool CiZigZag::Initialize(const string symbol,const ENUM_TIMEFRAMES period,const int num_params,const MqlParam &params[])
  {
   return(Initialize(symbol,period,(int)params[0].integer_value,(int)params[1].integer_value,(int)params[2].integer_value));
  }
//+------------------------------------------------------------------+
//| Initialisieren des Indikators mit speziellen Parametern |
//+------------------------------------------------------------------+
bool CiZigZag::Initialize(const string symbol,const ENUM_TIMEFRAMES period,
                        const int depth,const int deviation_init,const int backstep)
  {
   if(CreateBuffers(symbol,period,3))
     {
      //--- Rendering-Statuszeile
      m_name  ="ZigZag";
      m_status="("+symbol+","+PeriodDescription()+","+
               IntegerToString(depth)+","+IntegerToString(deviation_init)+","+
               IntegerToString(backstep)+") H="+IntegerToString(m_handle);
      //--- Einstellungen speichern
      m_depth=depth;
      m_deviation=deviation_init;
      m_backstep=backstep;       
      //--- Puffer erstellen
      ((CIndicatorBuffer*)At(0)).Name("ZIGZAG");
      ((CIndicatorBuffer*)At(1)).Name("HIGH");
      ((CIndicatorBuffer*)At(2)).Name("LOW");
      //--- ok
      return(true);
     }
//--- Fehler
   return(false);
  }
//+------------------------------------------------------------------+
//| Zugriff auf den Zickzack-Puffer des "Zickzack"-Indikators |
//+------------------------------------------------------------------+
double CiZigZag::ZigZag(const int index) const
  {
   CIndicatorBuffer *buffer=At(0);
//--- prüfen
   if(buffer==NULL)
      return(EMPTY_VALUE);
//---
   return(buffer.At(index));
  }
//+------------------------------------------------------------------+
Zugriff auf den High-Puffer des "Zig Zag"-Indikators //|
//+------------------------------------------------------------------+
double CiZigZag::High(const int index) const
  {
   CIndicatorBuffer *buffer=At(1);
   //--- prüfen
   if(buffer==NULL)
      return(EMPTY_VALUE);
//---
   return(buffer.At(index));
  }
//+------------------------------------------------------------------+
//| Zugriff auf den Low-Puffer des "Zig Zag"-Indikators |
//+------------------------------------------------------------------+
double CiZigZag::Low(const int index) const
  {
   CIndicatorBuffer *buffer=At(2);
//--- prüfen
   if(buffer==NULL)
      return(EMPTY_VALUE);
//---
   return(buffer.At(index));
  }
//+------------------------------------------------------------------+



CiZigZag *Zig;
//+------------------------------------------------------------------+
//| Benutzerdefinierte Initialisierungsfunktion für Indikatoren |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- Zuordnung von Indikatorpuffern
   Zig=new CiZigZag;
   Zig.Create(CurrencyPair,EAPeriod,12,5,3);
//---
   return(INIT_SUCCEEDED);
  }
void OnDeinit(const int reason)
  {
   delete(Zig);
  }  
//+------------------------------------------------------------------+
//| Benutzerdefinierte Indikator-Iterationsfunktion |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
//---
   int limit;
   if(prev_calculated==0)limit=0;
   else
     limit=prev_calculated-1; 
     
   for(int i=limit;i<rates_total && !IsStopped();i++)
      {
       Zig.Refresh();
       if (Zig.ZigZag(i)!=0) Print(Zig.ZigZag(i)," ",time[i]);  
      }
//--- Rückgabe des Wertes von prev_calculated für den nächsten Aufruf
   return(rates_total);
  }
//+------------------------------------------------------------------+

Hier ist der vollständige Code des Indikators, wobei die Ausgabe der Indikatorwerte von der Gegenwart in die Vergangenheit erfolgt - und umgekehrt

 
Tango_X:

Sorry, aber immer noch nicht klar, wie man die Richtung der Indizierung zu ändern, zum Beispiel, wenn es keinen Zugriff auf die Quelle Zigzag ist. Die Indizierungsrichtung wird durch ArraySetAsSeries() festgelegt - wobei der Eingabeparameter ein Array per Referenz ist,

aber wir haben dieses Array nicht, sondern nur einen Zeiger auf das Indikatorpuffer-Array in Form von

Die Basisklasse CIndicator verfügt über eine GetData-Methode, mit der Daten aus dem Indikatorpuffer geholt werden können.

Holt Daten aus dem Indikatorpuffer nach Startposition und Nummer

int GetData(
const intstart_pos, // Position
const intcount, // Anzahl
const int buffer_num, // Puffernummer
double&buffer[]// Array
) const



Danach legen Sie die gewünschte Indizierungsrichtung für Ihr Array mit ArraySetAsSeries fest

 
Rashid Umarov:

Die Basisklasse CIndicator verfügt über eine GetData-Methode, die verwendet werden kann, um Daten aus dem Indikatorpuffer abzurufen.

Holt Daten aus dem Indikatorpuffer nach Startposition und Anzahl der

int GetData(
const intstart_pos, // Position
const intcount, // Anzahl
const int buffer_num, // Puffernummer
double&buffer[]// Array
) const



Danach legen Sie die gewünschte Indizierungsrichtung für Ihr Array fest.

Es stellt sich also heraus, dass man zweimal auf den Indikatorpuffer zugreifen muss, aber auf unterschiedliche Weise? Immerhin haben wir hier unten bereits Zugriff auf die Werte des Indikatorpuffers? Wir erhalten ein Zwischen-Array double &buffer[] Ich verstehe Sie richtig?

//+------------------------------------------------------------------+
//| Zugriff auf den Zickzack-Puffer des "Zickzack"-Indikators |
//+------------------------------------------------------------------+
double CiZigZag::ZigZag(const int index) const
  {
   CIndicatorBuffer *buffer=At(0);
//--- prüfen
   if(buffer==NULL)
      return(EMPTY_VALUE);
//---
   return(buffer.At(index));
  }
 
Rashid Umarov:

Die Basisklasse CIndicator verfügt über eine GetData-Methode, die verwendet werden kann, um Daten aus dem Indikatorpuffer abzurufen.

Holt Daten aus dem Indikatorpuffer nach Startposition und Anzahl der

int GetData(
const intstart_pos, // Position
const intcount, // Anzahl
const int buffer_num, // Puffernummer
double&buffer[]// Array
) const



Danach setzen Sie die gewünschte Indizierungsrichtung für Ihr Array mit ArraySetAsSeries

Habe ich Sie richtig verstanden?

CiZigZag *Zig;
double ArrZig[];
//+------------------------------------------------------------------+
//| Benutzerdefinierte Initialisierungsfunktion für Indikatoren |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- Zuordnung von Indikatorpuffern
   Zig=new CiZigZag;
   Zig.Create(CurrencyPair,EAPeriod,12,5,3);

   SetIndexBuffer(0,ArrZig,INDICATOR_CALCULATIONS);
   ArraySetAsSeries(ArrZig,false);

//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//||
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   delete(Zig);
  }
//+------------------------------------------------------------------+
//| Benutzerdefinierte Indikator-Iterationsfunktion |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
//---
   int limit;
   if(prev_calculated==0) limit=0;
   else
      limit=prev_calculated-1;

   Zig.Refresh();
   Zig.GetData(0,rates_total-1,0,ArrZig);

   for(int i=limit;i<rates_total-1 && !IsStopped();i++)
     {

      //if (Zig.ZigZag(i)!=0) Print(Zig.ZigZag(i)," ",time[i]); 
      if(ArrZig[i]!=0) Print(ArrZig[i]," ",time[i]);
     }
//--- Rückgabewert von prev_calculated für den nächsten Aufruf
   return(rates_total);
  }
//+------------------------------------------------------------------+
Es stellt sich heraus, dass Sie den gesamten Verlauf bei jedem Tick kopieren müssen?
 
Tango_X:

Verstehe ich Sie richtig???

Es stellt sich heraus, dass es notwendig ist, den gesamten Verlauf bei jedem Tick zu kopieren?

1. Sie können dies bei der Eröffnung eines neuen Balkens tun.

2. warum müssen Sie jedes Mal alle Indikatorwerte abrufen und sich gleichzeitig um die Indizierungsrichtung kümmern? Was ist überhaupt die Aufgabe?

 

Warum sollte man einen einfachen Indikator in eine Klasse verpacken, wenn er später entweder in einem Diagramm oder über iCustom verwendet wird?

Второе решение лучше, потому что является объектно-ориентированным

OOP um der OOP willen, okay.

 
Rashid Umarov:

1. Es ist möglich, einen neuen Balken zu öffnen.

2. warum müssen Sie jedes Mal alle Indikatorwerte abrufen und sich gleichzeitig um die Indizierungsrichtung kümmern? Was ist überhaupt die Aufgabe?


Das Problem wurde durch die Schleifenbedingungen gelöst, jetzt funktioniert alles wie gewünscht. danke!