Discussão do artigo "Estendendo a biblioteca padrão do MQL5 e reutilizando o código" - página 2

 
Tango_X:


Ajude-me a entender como a direção de indexação da matriz do buffer do indicador é definida aqui, ou seja, da mesma forma que ArraySetAsSeries. A direção padrão é do presente para o passado, mas preciso defini-la do passado para o presente. Estou me debatendo com essa questão desde ontem! Socorro!

Ele não precisa disso, pois usa o ZigZag padrão.

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

Procure o local onde a direção está definida nesse ZigZag , mas ainda não está claro por que você precisa dele - você mesmo pode alterar a direção da indexação a qualquer momento - https://www.mql5.com/pt/docs/series.

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

Ele não precisa disso, pois usa o ZigZag padrão

Nesse ZigZag , procure o local onde a direção está definida. Mas ainda não está claro por que você precisa dele - você mesmo pode alterar a direção da indexação a qualquer momento - https://www.mql5.com/pt/docs/series.


Obrigado pela informação, vamos dar uma olhada nisso!

 
Rashid Umarov:

Ele não precisa disso, pois usa o ZigZag padrão

Nesse ZigZag , procure o local onde a direção está definida. Mas ainda não está claro por que você precisa dele - você mesmo pode alterar a direção da indexação a qualquer momento - https://www.mql5.com/pt/docs/series.


Sinto muito, mas ainda não está claro como alterar a direção da indexação, por exemplo, se você não tiver acesso à fonte do ZigZag. A direção da indexação é definida por ArraySetAsSeries() - em que o parâmetro de entrada é uma matriz por referência,

mas não temos essa matriz, mas apenas um ponteiro para a matriz do buffer do indicador na forma de

//--- criar 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 agendamento
input string            CurrencyPair="EURUSD.m"; //Símbolo

//+------------------------------------------------------------------+
//| Classe CiZigZag.|
//| Finalidade: Classe do indicador ZigZag.
//| Saída da classe CIndicator.|
//+------------------------------------------------------------------+
class CiZigZag : public CIndicator
  {
protected:
   int               m_depth;
   int               m_deviation;
   int               m_backstep;

public:
                     CiZigZag(void);
                    ~CiZigZag(void);
   //--- métodos de acesso a dados 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 criação
   bool              Create(const string symbol,const ENUM_TIMEFRAMES period,
                            const int depth,const int deviation_create,const int backstep);
   //--- métodos de acesso aos dados do indicador
   double            ZigZag(const int index) const;
   double            High(const int index) const;
   double            Low(const int index) const;
   //--- método de identificação
   virtual int       Type(void) const { return(IND_CUSTOM); }

protected:
   //--- métodos de personalização
   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);
  };
//+------------------------------------------------------------------+
//| Construtor|
//+------------------------------------------------------------------+
CiZigZag::CiZigZag(void) : m_depth(-1),
                         m_deviation(-1),
                         m_backstep(-1)
  {
  }
//+------------------------------------------------------------------+
//| Destruidor|
//+------------------------------------------------------------------+
CiZigZag::~CiZigZag(void)
  {
  }
//+------------------------------------------------------------------+
//|| Criar o indicador "Zig Zag|
//+------------------------------------------------------------------+
bool CiZigZag::Create(const string symbol,const ENUM_TIMEFRAMES period,
                      const int depth,const int deviation_create,const int backstep)
  {
//--- verificar histórico
   if(!SetSymbolPeriod(symbol,period))
      return(false);
//--- criar
   m_handle=iCustom(symbol,period,"Examples\\ZigZag",depth,deviation_create,backstep);
//--- verifique o resultado
   if(m_handle==INVALID_HANDLE)
      return(false);
//--- indicador criado com sucesso
   if(!Initialize(symbol,period,depth,deviation_create,backstep))
     {
      //--- erro de inicialização
      IndicatorRelease(m_handle);
      m_handle=INVALID_HANDLE;
      return(false);
     }
//--- ok
   return(true);
  }
//+------------------------------------------------------------------+
//| Inicializar o indicador com parâmetros universais.
//+------------------------------------------------------------------+
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 o indicador com parâmetros especiais.
//+------------------------------------------------------------------+
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))
     {
      //--- linha de status de renderização
      m_name  ="ZigZag";
      m_status="("+symbol+","+PeriodDescription()+","+
               IntegerToString(depth)+","+IntegerToString(deviation_init)+","+
               IntegerToString(backstep)+") H="+IntegerToString(m_handle);
      //--- salvar configurações
      m_depth=depth;
      m_deviation=deviation_init;
      m_backstep=backstep;       
      //--- criar buffers
      ((CIndicatorBuffer*)At(0)).Name("ZIGZAG");
      ((CIndicatorBuffer*)At(1)).Name("HIGH");
      ((CIndicatorBuffer*)At(2)).Name("LOW");
      //--- ok
      return(true);
     }
//--- erro
   return(false);
  }
//+------------------------------------------------------------------+
//| Acesso ao buffer ZigZag do indicador "Zig Zag".
//+------------------------------------------------------------------+
double CiZigZag::ZigZag(const int index) const
  {
   CIndicatorBuffer *buffer=At(0);
//--- verificação
   if(buffer==NULL)
      return(EMPTY_VALUE);
//---
   return(buffer.At(index));
  }
//+------------------------------------------------------------------+
//| Acesso ao buffer High do indicador "Zig Zag".
//+------------------------------------------------------------------+
double CiZigZag::High(const int index) const
  {
   CIndicatorBuffer *buffer=At(1);
   //--- verificação
   if(buffer==NULL)
      return(EMPTY_VALUE);
//---
   return(buffer.At(index));
  }
//+------------------------------------------------------------------+
//| Acesso ao buffer baixo do indicador "Zig Zag".
//+------------------------------------------------------------------+
double CiZigZag::Low(const int index) const
  {
   CIndicatorBuffer *buffer=At(2);
//--- verificação
   if(buffer==NULL)
      return(EMPTY_VALUE);
//---
   return(buffer.At(index));
  }
//+------------------------------------------------------------------+



CiZigZag *Zig;
//+------------------------------------------------------------------+
//| Função de inicialização do indicador personalizado
//+------------------------------------------------------------------+
int OnInit()
  {
//--- mapeamento de buffers de indicadores
   Zig=new CiZigZag;
   Zig.Create(CurrencyPair,EAPeriod,12,5,3);
//---
   return(INIT_SUCCEEDED);
  }
void OnDeinit(const int reason)
  {
   delete(Zig);
  }  
//+------------------------------------------------------------------+
//| Função de iteração de indicador personalizado
//+------------------------------------------------------------------+
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_calculated para a próxima chamada
   return(rates_total);
  }
//+------------------------------------------------------------------+

Aqui está o código completo do indicador, em que a saída dos valores do indicador é do presente para o passado - e é necessário vice-versa

 
Tango_X:

Desculpe, mas ainda não está claro como alterar a direção da indexação, por exemplo, se não houver acesso ao Zigzag de origem. A direção da indexação é definida por ArraySetAsSeries(), em que o parâmetro de entrada é uma matriz por referência,

mas não temos essa matriz, mas apenas um ponteiro para a matriz do buffer do indicador na forma de

A classe base CIndicator tem um método GetData, que pode ser usado para obter dados do buffer do indicador.

Obtém dados do buffer do indicador por posição inicial e número

int GetData(
const intstart_pos, // posição
const intcount, // número
const int buffer_num, // número do buffer
double&buffer[]// matriz
) const



Depois disso, defina a direção de indexação desejada para sua matriz usando ArraySetAsSeries

 
Rashid Umarov:

A classe base CIndicator tem um método GetData que pode ser usado para obter dados do buffer do indicador.

Obtém dados do buffer do indicador por posição inicial e número de

int GetData(
const intstart_pos, // posição
const intcount, // número
const int buffer_num, // número do buffer
double&buffer[]// matriz
) const



Depois disso, defina a direção de indexação desejada para sua matriz.

Então, o resultado é acessar o buffer do indicador duas vezes, mas de maneiras diferentes? Afinal, aqui embaixo já temos acesso aos valores do buffer de indicador? Obtemos um array intermediário double &buffer[], entendi corretamente?

//+------------------------------------------------------------------+
//| Acesso ao buffer ZigZag do indicador "Zig Zag".
//+------------------------------------------------------------------+
double CiZigZag::ZigZag(const int index) const
  {
   CIndicatorBuffer *buffer=At(0);
//--- verificação
   if(buffer==NULL)
      return(EMPTY_VALUE);
//---
   return(buffer.At(index));
  }
 
Rashid Umarov:

A classe base CIndicator tem um método GetData que pode ser usado para obter dados do buffer do indicador.

Obtém dados do buffer do indicador por posição inicial e número de

int GetData(
const intstart_pos, // posição
const intcount, // número
const int buffer_num, // número do buffer
double&buffer[]// matriz
) const



Depois disso, defina a direção de indexação desejada para sua matriz usando ArraySetAsSeries

Eu o entendi corretamente?

CiZigZag *Zig;
double ArrZig[];
//+------------------------------------------------------------------+
//| Função de inicialização do indicador personalizado
//+------------------------------------------------------------------+
int OnInit()
  {
//--- mapeamento de buffers de 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);
  }
//+------------------------------------------------------------------+
//| Função de iteração de indicador personalizado
//+------------------------------------------------------------------+
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]);
     }
//--- valor de retorno de prev_calculated para a próxima chamada
   return(rates_total);
  }
//+------------------------------------------------------------------+
Você precisa copiar todo o histórico em cada tick?
 
Tango_X:

Estou entendendo corretamente???

Acontece que é necessário copiar todo o histórico em cada tique?

1. Você pode fazer isso na abertura de uma nova barra

2) Por que você precisa obter todos os valores do indicador todas as vezes e, ao mesmo tempo, cuidar da direção da indexação? Qual é a tarefa?

 

Por que agrupar um indicador simples em uma classe se ele for usado posteriormente em um gráfico ou por meio do iCustom?

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

OOP por OOP, tudo bem.

 
Rashid Umarov:

1. É possível abrir uma nova barra

2. por que você precisa obter todos os valores do indicador todas as vezes e, ao mesmo tempo, se preocupar com a direção da indexação? Qual é a tarefa?


O problema foi resolvido pelas condições do loop e agora tudo funciona como desejado.