Traduzir Indicador para EA, Implementar setup PVT.

 
Olá pessoal, é meu primeiro post aqui, o que me motivou foi passar a quarta madrugada seguida tentando traduzir um indicador de PVT para uma estratégia do EA. Quando o pvt cruza uma média pra cima ou pra baixo.

O indicador que eu baixei pra poder pegar a base do cálculo foi do Metaquotes mesmo: https://www.mql5.com/en/code/45

E o que eu queria fazer é conseguir transformar o código dele pra rodar dentro do EA. Porém encontrei algumas dificuldades como traduzir o  chamados rates_total e prev_calculated que já são embutidos na função OnCalculate da versão do indicador, porém não são quando o código é para EA,que usa outra função pra chamada (OnInit).

Outra dificuldade que tive foi de como faço para  tratar o PVT como Handle, porque a partir do momento que eu tiver um handle dele, eu consigo puxar o iMA e botar uma média móvel. 

Estou programando EAs faz 4 meses e o aprendizado aqui está sendo quase que literalmente na base da porrada, e é a primeira vez que peço ajuda aqui, porque acredito que me falta um detalhe simples que ainda não faz parte do meu conhecimento.

Abraço! 
 

Olá! 

Pra criar um EA com base nesse indicador, você vai precisar fazer exatamente o que você disse, criar o manipulador(handler) do indicador

e copiar o buffer referente ao dado do indicador que pretende usar. A partir daí é só criar a lógica operacional com base nos dados obtidos.


Deixo aqui a base disso:

//+------------------------------------------------------------------+
//|                                      Indicador_Personalizado.mq5 |
//|                                                  Henrique Araújo |
//+------------------------------------------------------------------+
#property copyright "Henrique Araújo"
#property link      "araujo_br@outlook.com.br"
#property version   "1.00"

int indicador_handle = INVALID_HANDLE;  //Manipulador do indicador
double indicador_buffer[];  //Váriavel que vai guardar os dados obtidos do buffer do indicador
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
   indicador_handle = iCustom(_Symbol,_Period,"nome_indicador.ex5"); 
   ArraySetAsSeries(indicador_buffer,true); //Inversão de array
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
   
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
   //Aqui copiamos os dados do buffer, vou tentar explicar abaixo qual a estrutura aqui
   //1. indicamos de qual manipulador queremos copiar os dados
   //2. indicamos de qual buffer queremos copiar os dados (nesse caso utilizei o buffer como '0' mas aqui seria o buffer referente ao dado do indicador que você quer utilizar)
   //3. a partir de qual posição você quer copiar os dados ? (aqui utilizei a posição '0' que seria o dado mais recente do buffer)
   //4. ´quantos dados você quer copiar ? (aqui eu copio do dado 0 até 5)
   //5. pra onde você vai jogar tudo isso ?  (e por fim jogamos esses dados pra dentro do nosso buffer, que vai ser utilizado em toda a lógica posteriormente)
   CopyBuffer(indicador_handle,0,0,5,indicador_buffer);
  }
//+------------------------------------------------------------------+


Abraço.

 
HENRIQUE ARAUJO DOS SANTOS:

....

Pessoal, precisa usar a função de copia ICustom.

existe formas de se calcular os dados de um indicador no EA, mas se ja esta pronto para que todo esse trabalho se é so copia-lo? 

Documentação sobre MQL5: Indicadores Técnicos / iCustom
Documentação sobre MQL5: Indicadores Técnicos / iCustom
  • www.mql5.com
[in] O nome do símbolo de segurança, os dados que devem ser usados para calcular o indicador. O valor NULL significa o símbolo atual. [in]  O nome do indicador personalizado, com o caminho relativo ao diretório raiz de indicadores (MQL5\Indicators\). Se um indicador está localizado em um subdiretório, por exemplo, em MQL5/Indicadores/ [in]...
 
HENRIQUE ARAUJO DOS SANTOS:

Olá! 

Pra criar um EA com base nesse indicador, você vai precisar fazer exatamente o que você disse, criar o manipulador(handler) do indicador

e copiar o buffer referente ao dado do indicador que pretende usar. A partir daí é só criar a lógica operacional com base nos dados obtidos.


Deixo aqui a base disso:


Abraço.

Oi Henrique! Então, essa parte eu fui capaz de fazer com alguns outros indicadores, o problema é que para o PVT não foi tão simples quanto criar um handle, e puxar uma função como iMA, iStoch, etc..

Por exemplo, o calculo dele para o indicador é esse:

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 &TickVolume[],
                const long &Volume[],
                const int &Spread[])
  {
//--- variables
   int pos;
//--- check for bars count
   if(rates_total<2)
      return(0);
//--- start calculation
   pos=prev_calculated-1;
//--- correct position, when it's first iteration
   if(pos<0)
     {
      pos=1;
      ExtPVTBuffer[0]=0.0;
     }
//--- main cycle
   if(InpVolumeType==VOLUME_TICK)
      CalculatePVT(pos,rates_total,Close,TickVolume);
   else
      CalculatePVT(pos,rates_total,Close,Volume);
//---- OnCalculate done. Return new prev_calculated.
   return(rates_total);
  }
//+------------------------------------------------------------------+
//| Calculate PVT by volume argument                                 |
//+------------------------------------------------------------------+
void CalculatePVT(int nPosition,
                  int nRatesCount,
                  const double &ClBuffer[],
                  const long &VolBuffer[])
  {
   if(nPosition<=0) nPosition=1;
//---
   for(int i=nPosition;i<nRatesCount && !IsStopped();i++)
     {
      //--- get some data
      double PrevClose=ClBuffer[i-1];
      //--- calculate PVT value
      if(PrevClose!=0)
         ExtPVTBuffer[i]=((ClBuffer[i]-PrevClose)/PrevClose)*VolBuffer[i]+ExtPVTBuffer[i-1];
      else ExtPVTBuffer[i]=ExtPVTBuffer[i-1];
     }

E estou tendo dificuldade em traduzir a chamada do Oncalculate, que tem as funções rates_total e prev_calculated. Porque no EA não podemos chamar essa função.

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 &TickVolume[],
                const long &Volume[],
                const int &Spread[])

Dai a ideia é procurar uma forma de traduzir esse codigo de forma que o EA rode, e vi que tem um workaround usando o iBars para o rates_total, que ai ele puxa a qtd de barras do periodo que estipular. mas foi o máximo que consegui desenvolver =(

 
Jonathan Pereira:

Pessoal, precisa usar a função de copia ICustom.

existe formas de se calcular os dados de um indicador no EA, mas se ja esta pronto para que todo esse trabalho se é so copia-lo? 

Honroso Jonathan! A ideia de implementar o indicador dentro do EA é porque li em um artigo que a função iCustom pode comprometer a velocidade do EA em até 60 vezes, e não queria comprometer a robustez do EA puxando a função.
Eu elaborei um pouco melhor na resposta acima pro nosso amigo Henrique, pra ver se podem me dar um help.


Obrigado mesmo assim! ICustom está como plano B =D

 
johnsilvabr:

Honroso Jonathan! A ideia de implementar o indicador dentro do EA é porque li em um artigo que a função iCustom pode comprometer a velocidade do EA em até 60 vezes.....

Vc deve notar que as funções em MQL5 são otimizadas a quase todas as atualizações, e os artigos que vi falando de velocidade são todos de meados de 2012 / 2014...


rates_total= o total de barras que tem no grafico;
prev_calculated = barras ja processadas;

 

as demais são dados que acompanham esse array de barras, se vc quer reescrever o indicador no EA deve ter isso em mente, deve calcular todas as barras ate o presente momento, e após isso ser capaz de processar uma nova barra.


Enfim, apenas por curiosidade, poderia postar o link do artigo que diz isso ?

 
Jonathan Pereira:

Vc deve notar que as funções em MQL5 são otimizadas a quase todas as atualizações, e os artigos que vi falando de velocidade são todos de meados de 2012 / 2014...


rates_total= o total de barras que tem no grafico;
prev_calculated = barras ja processadas;

 

as demais são dados que acompanham esse array de barras, se vc quer reescrever o indicador no EA deve ter isso em mente, deve calcular todas as barras ate o presente momento, e após isso ser capaz de processar uma nova barra.


Enfim, apenas por curiosidade, poderia postar o link do artigo que diz isso ?

Claro! Na verdade achei um artigo atualizado, que traz o que eu tinha lido de uns posts bem antigos e elabora melhor::

https://www.mql5.com/en/articles/4602

Olha que massa, se eu quiser puxar um handle do Icustom, demora 30x mais que rodar a função, maas se eu puxar só o resultado da função, ele consegue rodar bem rápido!

Bom, com meu plano 1 devidamente descartado, vou passar pro iCustom! Agora tenho um novo desafio: Pegar o codigo pronto que já tenho do PVT, e rodar uma banda de bollinger no menino. Alguma dica de por onde começar?

Vi que a estrutura da chamada OnCalculate é diferente do PVT pra o indicador das Bandas de bollinger:

//+------------------------------------------------------------------+
//| PVT iteration function                              |
//+------------------------------------------------------------------+
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 &TickVolume[],
                const long &Volume[],
                const int &Spread[])

E das BB

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const int begin,
                const double &price[])
  {
//--- variables
   int pos;
//--- indexes draw begin settings, when we've recieved previous begin
   if(ExtPlotBegin!=ExtBandsPeriod+begin)
     {
      ExtPlotBegin=ExtBandsPeriod+begin;
      PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,ExtPlotBegin);
      PlotIndexSetInteger(1,PLOT_DRAW_BEGIN,ExtPlotBegin);
      PlotIndexSetInteger(2,PLOT_DRAW_BEGIN,ExtPlotBegin);
     }

Alguma dica de como prosseguir?

 
Jonathan Pereira:

Pessoal, precisa usar a função de copia ICustom.

existe formas de se calcular os dados de um indicador no EA, mas se ja esta pronto para que todo esse trabalho se é so copia-lo? 

Tem razão, esqueci de escrever isso!! Acabei de corrigir.