Discussione sull’articolo "Estensione della MQL5 Standard Library e riutilizzo del codice" - pagina 2

 
Tango_X:


Aiutatemi a capire come viene impostata la direzione di indicizzazione dell' array di buffer dell'indicatore, cioè la stessa di ArraySetAsSeries. La direzione predefinita è da presente a passato, ma io ho bisogno di renderla da passato a presente. È da ieri che sto lottando con questa domanda! Aiuto!

Non ne ha bisogno, poiché utilizza lo ZigZag standard.

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

Cercate il punto in cui è impostata la direzione in questo ZigZag , ma non è ancora chiaro perché ne abbiate bisogno: potete cambiare voi stessi la direzione di indicizzazione in qualsiasi momento - https://www.mql5.com/it/docs/series.

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

Non ne ha bisogno, perché utilizza lo ZigZag standard.

In questo ZigZag , cercate il punto in cui è impostata la direzione. Ma non è ancora chiaro perché ne abbiate bisogno: potete cambiare voi stessi la direzione dell'indicizzazione in qualsiasi momento - https://www.mql5.com/it/docs/series.


Grazie per le informazioni, le esamineremo!

 
Rashid Umarov:

Non ne ha bisogno, perché utilizza lo ZigZag standard.

In questo ZigZag cercate il punto in cui è impostata la direzione. Ma non è ancora chiaro perché ne abbiate bisogno: potete cambiare la direzione di indicizzazione da soli in qualsiasi momento - https://www.mql5.com/it/docs/series.


Mi dispiace, ma non è ancora chiaro come cambiare la direzione di indicizzazione, ad esempio, se non si ha accesso al sorgente Zigzag. La direzione di indicizzazione viene impostata da ArraySetAsSeries() - dove il parametro di input è un array per riferimento,

ma noi non abbiamo questo array, bensì solo un puntatore all'array del buffer dell'indicatore sotto forma di

//--- creare buffer
      ((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>


//--- parametri di ingresso
input ENUM_TIMEFRAMES   EAPeriod=PERIOD_CURRENT; //Periodo di programmazione
input string            CurrencyPair="EURUSD.m"; //Simbolo

//+------------------------------------------------------------------+
//| Classe CiZigZag.|
//| Scopo: classe di indicatori ZigZag. ||
//| Output della classe CIndicator.|
//+------------------------------------------------------------------+
class CiZigZag : public CIndicator
  {
protected:
   int               m_depth;
   int               m_deviation;
   int               m_backstep;

public:
                     CiZigZag(void);
                    ~CiZigZag(void);
   //--- metodi di accesso ai dati protetti
   int               Depth(void)          const { return(m_depth);      }
   int               Deviation(void)      const { return(m_deviation);  }
   int               Backstep(void)       const { return(m_backstep);   }
   //--- metodo di creazione
   bool              Create(const string symbol,const ENUM_TIMEFRAMES period,
                            const int depth,const int deviation_create,const int backstep);
   //--- metodi di accesso ai dati dell'indicatore
   double            ZigZag(const int index) const;
   double            High(const int index) const;
   double            Low(const int index) const;
   //--- metodo di identificazione
   virtual int       Type(void) const { return(IND_CUSTOM); }

protected:
   //--- metodi di personalizzazione
   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);
  };
//+------------------------------------------------------------------+
//| Costruttore|
//+------------------------------------------------------------------+
CiZigZag::CiZigZag(void) : m_depth(-1),
                         m_deviation(-1),
                         m_backstep(-1)
  {
  }
//+------------------------------------------------------------------+
//| Distruttore|
//+------------------------------------------------------------------+
CiZigZag::~CiZigZag(void)
  {
  }
//+------------------------------------------------------------------+
//|Creare l'indicatore "Zig Zag|
//+------------------------------------------------------------------+
bool CiZigZag::Create(const string symbol,const ENUM_TIMEFRAMES period,
                      const int depth,const int deviation_create,const int backstep)
  {
//--- controllare la cronologia
   if(!SetSymbolPeriod(symbol,period))
      return(false);
//--- creare
   m_handle=iCustom(symbol,period,"Examples\\ZigZag",depth,deviation_create,backstep);
//--- controllare il risultato
   if(m_handle==INVALID_HANDLE)
      return(false);
//--- indicatore creato con successo
   if(!Initialize(symbol,period,depth,deviation_create,backstep))
     {
      //--- errore di inizializzazione
      IndicatorRelease(m_handle);
      m_handle=INVALID_HANDLE;
      return(false);
     }
//--- ok
   return(true);
  }
//+------------------------------------------------------------------+
//| Inizializza l'indicatore con parametri universali |
//+------------------------------------------------------------------+
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));
  }
//+------------------------------------------------------------------+
//| Inizializza l'indicatore con parametri speciali |
//+------------------------------------------------------------------+
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))
     {
      //--- linea di stato del rendering
      m_name  ="ZigZag";
      m_status="("+symbol+","+PeriodDescription()+","+
               IntegerToString(depth)+","+IntegerToString(deviation_init)+","+
               IntegerToString(backstep)+") H="+IntegerToString(m_handle);
      //--- salvare le impostazioni
      m_depth=depth;
      m_deviation=deviation_init;
      m_backstep=backstep;       
      //--- creare buffer
      ((CIndicatorBuffer*)At(0)).Name("ZIGZAG");
      ((CIndicatorBuffer*)At(1)).Name("HIGH");
      ((CIndicatorBuffer*)At(2)).Name("LOW");
      //--- ok
      return(true);
     }
//--- errore
   return(false);
  }
//+------------------------------------------------------------------+
//| Accesso al buffer ZigZag dell'indicatore "Zig Zag" |
//+------------------------------------------------------------------+
double CiZigZag::ZigZag(const int index) const
  {
   CIndicatorBuffer *buffer=At(0);
//--- controllo
   if(buffer==NULL)
      return(EMPTY_VALUE);
//---
   return(buffer.At(index));
  }
//+------------------------------------------------------------------+
//| Accesso al buffer High dell'indicatore "Zig Zag".
//+------------------------------------------------------------------+
double CiZigZag::High(const int index) const
  {
   CIndicatorBuffer *buffer=At(1);
   //--- controllo
   if(buffer==NULL)
      return(EMPTY_VALUE);
//---
   return(buffer.At(index));
  }
//+------------------------------------------------------------------+
//| Accesso al buffer Low dell'indicatore "Zig Zag".
//+------------------------------------------------------------------+
double CiZigZag::Low(const int index) const
  {
   CIndicatorBuffer *buffer=At(2);
//--- controllo
   if(buffer==NULL)
      return(EMPTY_VALUE);
//---
   return(buffer.At(index));
  }
//+------------------------------------------------------------------+



CiZigZag *Zig;
//+------------------------------------------------------------------+
//| Funzione di inizializzazione dell'indicatore personalizzata |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- mappatura dei buffer degli indicatori
   Zig=new CiZigZag;
   Zig.Create(CurrencyPair,EAPeriod,12,5,3);
//---
   return(INIT_SUCCEEDED);
  }
void OnDeinit(const int reason)
  {
   delete(Zig);
  }  
//+------------------------------------------------------------------+
//| Funzione di iterazione dell'indicatore personalizzata |
//+------------------------------------------------------------------+
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]);  
      }
//--- restituisce il valore di prev_calculated per la chiamata successiva
   return(rates_total);
  }
//+------------------------------------------------------------------+

Ecco il codice completo dell'indicatore, dove l'output dei valori dell'indicatore è dal presente al passato - ed è necessario viceversa

 
Tango_X:

Scusate, ma non è ancora chiaro come cambiare la direzione dell'indicizzazione, ad esempio, se non si ha accesso allo Zigzag di origine. La direzione dell'indicizzazione viene impostata da ArraySetAsSeries(), dove il parametro di ingresso è un array per riferimento,

ma non abbiamo questo array, bensì solo un puntatore all'array del buffer dell'indicatore sotto forma di

La classe base CIndicator dispone di un metodo GetData, che può essere utilizzato per ottenere i dati dal buffer dell'indicatore.

Ottiene i dati dal buffer dell'indicatore in base alla posizione iniziale e al numero

int GetData(
const intstart_pos, // posizione
const intcount, // numero
const int buffer_num, // numero del buffer
double&buffer[]// array
) const



Successivamente, impostare la direzione di indicizzazione desiderata per l'array utilizzando ArraySetAsSeries

 
Rashid Umarov:

La classe base CIndicator dispone di un metodo GetData che può essere utilizzato per ottenere i dati dal buffer dell'indicatore.

Ottiene i dati dal buffer dell'indicatore in base alla posizione di partenza e al numero di

int GetData(
const intstart_pos, // posizione
const intcount, // numero
const int buffer_num, // numero del buffer
double&buffer[]// array
) const



Dopo di che, impostare la direzione di indicizzazione desiderata per l'array.

Quindi risulta che si accede al buffer dell'indicatore due volte, ma in modi diversi? Dopo tutto, qui sotto abbiamo già accesso ai valori del buffer indicatore? Otteniamo un array intermedio double &buffer[] Ho capito bene?

//+------------------------------------------------------------------+
//| Accesso al buffer ZigZag dell'indicatore "Zig Zag" |
//+------------------------------------------------------------------+
double CiZigZag::ZigZag(const int index) const
  {
   CIndicatorBuffer *buffer=At(0);
//--- controllo
   if(buffer==NULL)
      return(EMPTY_VALUE);
//---
   return(buffer.At(index));
  }
 
Rashid Umarov:

La classe base CIndicator dispone di un metodo GetData che può essere utilizzato per ottenere i dati dal buffer dell'indicatore.

Ottiene i dati dal buffer dell'indicatore in base alla posizione di partenza e al numero di

int GetData(
const intstart_pos, // posizione
const intcount, // numero
const int buffer_num, // numero del buffer
double&buffer[]// array
) const



Dopodiché, impostate la direzione di indicizzazione desiderata per il vostro array utilizzando ArraySetAsSeries

Ho capito bene?

CiZigZag *Zig;
double ArrZig[];
//+------------------------------------------------------------------+
//| Funzione di inizializzazione dell'indicatore personalizzata |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- mappatura dei buffer degli indicatori
   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);
  }
//+------------------------------------------------------------------+
//| Funzione di iterazione dell'indicatore personalizzata |
//+------------------------------------------------------------------+
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++)
     {

      //se (Zig.ZigZag(i)!=0) Print(Zig.ZigZag(i)," ",time[i]); 
      if(ArrZig[i]!=0) Print(ArrZig[i]," ",time[i]);
     }
//--- restituisce il valore di prev_calculated per la chiamata successiva
   return(rates_total);
  }
//+------------------------------------------------------------------+
Risulta che è necessario copiare l'intera cronologia a ogni tick?
 
Tango_X:

Ho capito bene?

Risulta che è necessario copiare l'intera cronologia ad ogni spunta?

1. Si può fare all'apertura di una nuova barra.

2. Perché è necessario ottenere tutti i valori degli indicatori ogni volta e allo stesso tempo occuparsi della direzione dell'indicizzazione? Qual è il compito?

 

Perché racchiudere un semplice indicatore in una classe se poi viene utilizzato in un grafico o tramite iCustom?

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

OOP per amore dell'OOP, ok.

 
Rashid Umarov:

1. È possibile aprire una nuova barra

2. Perché è necessario ottenere ogni volta tutti i valori degli indicatori e allo stesso tempo preoccuparsi della direzione di indicizzazione? Qual è il compito?


Il problema è stato risolto dalle condizioni del ciclo, ora tutto funziona come desiderato. grazie!