Discusión sobre el artículo "Ampliación de la librería estándar de MQL5 y la reutilización del código" - página 2

 
Tango_X:


Ayúdame a entender cómo se establece aquí la dirección de indexación de la matriz del búfer del indicador, es decir, lo mismo que ArraySetAsSeries. La dirección por defecto es de presente a pasado, pero necesito que sea de pasado a presente. Llevo desde ayer con esta duda, ¡ayuda!

No lo necesita, ya que utiliza el ZigZag estándar.

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

Busca el lugar donde se establece la dirección en este ZigZag , pero todavía no está claro por qué lo necesitas - puedes cambiar la dirección de indexación tú mismo en cualquier momento - https://www.mql5.com/es/docs/series.

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

No lo necesita, ya que utiliza el ZigZag estándar

En este ZigZag , busque el lugar donde se establece la dirección. Pero todavía no está claro por qué lo necesita - usted mismo puede cambiar la dirección de indexación en cualquier momento - https://www.mql5.com/es/docs/series.


Gracias por la información, ¡lo investigaremos!

 
Rashid Umarov:

No lo necesita, ya que utiliza el ZigZag estándar

En este ZigZag buscar el lugar donde se establece la dirección. Pero todavía no está claro por qué lo necesita - usted puede cambiar la dirección de indexación a ti mismo en cualquier momento - https://www.mql5.com/es/docs/series.


Lo siento, pero todavía no está claro cómo cambiar la dirección de indexación, por ejemplo, si usted no tiene acceso a la fuente Zigzag. La dirección de indexación se establece por ArraySetAsSeries() - donde el parámetro de entrada es un array por referencia,

pero no tenemos este array, sino sólo un puntero al array del buffer indicador en forma de

//--- crear buffers
      ((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>


//--- parámetros de entrada
input ENUM_TIMEFRAMES   EAPeriod=PERIOD_CURRENT; //Período de programación
input string            CurrencyPair="EURUSD.m"; //Símbolo

//+------------------------------------------------------------------+
//| Clase CiZigZag.|
//| Propósito: Clase de indicador ZigZag. |||
//| Salida de la clase CIndicator.|
//+------------------------------------------------------------------+
class CiZigZag : public CIndicator
  {
protected:
   int               m_depth;
   int               m_deviation;
   int               m_backstep;

public:
                     CiZigZag(void);
                    ~CiZigZag(void);
   //--- métodos de acceso a los datos protegidos
   int               Depth(void)          const { return(m_depth);      }
   int               Deviation(void)      const { return(m_deviation);  }
   int               Backstep(void)       const { return(m_backstep);   }
   //--- método de creación
   bool              Create(const string symbol,const ENUM_TIMEFRAMES period,
                            const int depth,const int deviation_create,const int backstep);
   //--- métodos de acceso a los datos de los indicadores
   double            ZigZag(const int index) const;
   double            High(const int index) const;
   double            Low(const int index) const;
   //--- método de identificación
   virtual int       Type(void) const { return(IND_CUSTOM); }

protected:
   //--- métodos de personalización
   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);
  };
//+------------------------------------------------------------------+
//| Constructor|
//+------------------------------------------------------------------+
CiZigZag::CiZigZag(void) : m_depth(-1),
                         m_deviation(-1),
                         m_backstep(-1)
  {
  }
//+------------------------------------------------------------------+
//| Destructor|
//+------------------------------------------------------------------+
CiZigZag::~CiZigZag(void)
  {
  }
//+------------------------------------------------------------------+
//|| Crear el indicador "Zig Zag|
//+------------------------------------------------------------------+
bool CiZigZag::Create(const string symbol,const ENUM_TIMEFRAMES period,
                      const int depth,const int deviation_create,const int backstep)
  {
//--- comprobar historial
   if(!SetSymbolPeriod(symbol,period))
      return(false);
//--- crear
   m_handle=iCustom(symbol,period,"Examples\\ZigZag",depth,deviation_create,backstep);
//--- comprueba el resultado
   if(m_handle==INVALID_HANDLE)
      return(false);
//--- indicador creado con éxito
   if(!Initialize(symbol,period,depth,deviation_create,backstep))
     {
      //--- error de inicialización
      IndicatorRelease(m_handle);
      m_handle=INVALID_HANDLE;
      return(false);
     }
//--- ok
   return(true);
  }
//+------------------------------------------------------------------+
//| Inicializar el indicador con parámetros universales.
//+------------------------------------------------------------------+
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));
  }
//+------------------------------------------------------------------+
//| Inicializar el indicador con parámetros especiales ||.
//+------------------------------------------------------------------+
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))
     {
      //--- renderización de la línea de estado
      m_name  ="ZigZag";
      m_status="("+symbol+","+PeriodDescription()+","+
               IntegerToString(depth)+","+IntegerToString(deviation_init)+","+
               IntegerToString(backstep)+") H="+IntegerToString(m_handle);
      //--- guardar configuración
      m_depth=depth;
      m_deviation=deviation_init;
      m_backstep=backstep;       
      //--- crear buffers
      ((CIndicatorBuffer*)At(0)).Name("ZIGZAG");
      ((CIndicatorBuffer*)At(1)).Name("HIGH");
      ((CIndicatorBuffer*)At(2)).Name("LOW");
      //--- ok
      return(true);
     }
//--- error
   return(false);
  }
//+------------------------------------------------------------------+
//| Acceso al buffer ZigZag del indicador "Zig Zag" | //| Acceso al buffer ZigZag del indicador "Zig Zag
//+------------------------------------------------------------------+
double CiZigZag::ZigZag(const int index) const
  {
   CIndicatorBuffer *buffer=At(0);
//--- comprobar
   if(buffer==NULL)
      return(EMPTY_VALUE);
//---
   return(buffer.At(index));
  }
//+------------------------------------------------------------------+
//| Acceso al buffer High del indicador "Zig Zag" ||
//+------------------------------------------------------------------+
double CiZigZag::High(const int index) const
  {
   CIndicatorBuffer *buffer=At(1);
   //--- comprobar
   if(buffer==NULL)
      return(EMPTY_VALUE);
//---
   return(buffer.At(index));
  }
//+------------------------------------------------------------------+
//| Acceso al buffer Low del indicador "Zig Zag" ||
//+------------------------------------------------------------------+
double CiZigZag::Low(const int index) const
  {
   CIndicatorBuffer *buffer=At(2);
//--- comprobar
   if(buffer==NULL)
      return(EMPTY_VALUE);
//---
   return(buffer.At(index));
  }
//+------------------------------------------------------------------+



CiZigZag *Zig;
//+------------------------------------------------------------------+
//| Función de inicialización del indicador personalizada |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- asignación de búferes indicadores
   Zig=new CiZigZag;
   Zig.Create(CurrencyPair,EAPeriod,12,5,3);
//---
   return(INIT_SUCCEEDED);
  }
void OnDeinit(const int reason)
  {
   delete(Zig);
  }  
//+------------------------------------------------------------------+
//| Función de iteración del indicador personalizada |
//+------------------------------------------------------------------+
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]);  
      }
//--- valor de retorno de prev_calculado para la siguiente llamada
   return(rates_total);
  }
//+------------------------------------------------------------------+

Aquí está el código completo del indicador, donde la salida de los valores del indicador es del presente al pasado - y es necesario viceversa

 
Tango_X:

Lo siento, pero todavía no está claro cómo cambiar la dirección de indexación, por ejemplo, si no hay acceso a la fuente Zigzag. La dirección de indexación se establece por ArraySetAsSeries() - donde el parámetro de entrada es una matriz por referencia,

pero no tenemos este array, sino sólo un puntero al array del buffer del indicador en forma de

La clase base CIndicator tiene un método GetData, que se puede utilizar para obtener datos del buffer del indicador.

Obtiene los datos del buffer del indicador por posición inicial y número

int GetData(
constint start_pos, // posición
const intcount, // número
const int buffer_num, // número del buffer
double&buffer[]// matriz
) const



Después de eso, establece la dirección de indexación deseada para tu array utilizando ArraySetAsSeries

 
Rashid Umarov:

La clase base CIndicator tiene un método GetData que se puede utilizar para obtener datos del búfer del indicador.

Obtiene datos del búfer del indicador por posición de inicio y número de

int GetData(
constint start_pos, // posición
const intcount, // número
const int buffer_num, // número de búfer
double&buffer[]// matriz
) const



Después de eso, establece la dirección de indexación deseada para tu array.

¿Así que resulta que hay que acceder al buffer indicador dos veces, pero de formas distintas? Después de todo, aquí abajo ya tenemos acceso a los valores del buffer indicador? Obtenemos un array intermedio double &buffer[] ¿he entendido bien?

//+------------------------------------------------------------------+
//| Acceso al buffer ZigZag del indicador "Zig Zag" | //| Acceso al buffer ZigZag del indicador "Zig Zag
//+------------------------------------------------------------------+
double CiZigZag::ZigZag(const int index) const
  {
   CIndicatorBuffer *buffer=At(0);
//--- comprobar
   if(buffer==NULL)
      return(EMPTY_VALUE);
//---
   return(buffer.At(index));
  }
 
Rashid Umarov:

La clase base CIndicator tiene un método GetData que se puede utilizar para obtener datos del búfer del indicador.

Obtiene datos del búfer del indicador por posición de inicio y número de

int GetData(
constint start_pos, // posición
const intcount, // número
const int buffer_num, // número de búfer
double&buffer[]// matriz
) const



Después de eso, establece la dirección de indexación deseada para tu array usando ArraySetAsSeries

¿Te he entendido bien?

CiZigZag *Zig;
double ArrZig[];
//+------------------------------------------------------------------+
//| Función de inicialización del indicador personalizada |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- asignación de búferes indicadores
   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);
  }
//+------------------------------------------------------------------+
//| Función de iteración del indicador personalizada |
//+------------------------------------------------------------------+
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]);
     }
//--- valor de retorno de prev_calculado para la siguiente llamada
   return(rates_total);
  }
//+------------------------------------------------------------------+
Resulta que necesitas copiar todo el histórico en cada tick?
 
Tango_X:

¿he entendido bien?

¿Resulta que es necesario copiar todo el historial en cada tick?

1. Puede hacerlo en la apertura de una nueva barra

2. ¿Por qué es necesario obtener todos los valores de los indicadores cada vez, y al mismo tiempo cuidar de la dirección de indexación? ¿Cuál es la tarea en absoluto?

 

¿Por qué envolver un simple indicador en una clase si se utiliza más tarde en un gráfico o a través de iCustom?

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

OOP por el bien de OOP, de acuerdo.

 
Rashid Umarov:

1. Es posible abrir una nueva barra

2. ¿Por qué es necesario obtener todos los valores de los indicadores cada vez, y al mismo tiempo preocuparse por la dirección de indexación? ¿Cuál es la tarea en absoluto?


¡El problema fue resuelto por las condiciones de bucle, ahora todo funciona como se desea. gracias!