Indicador Volume de Compra e Venda

 
Olá pessoal,

eu estou tentando criar um indicador de volume que separe as agressões de compra e venda em um histograma com valores negativos (venda) e positivos (compra).

O problema é que ele retorna números gigantescos ou simplesmente não mostra valor algum.

//+---------------------------------------------------------------------------+
//|                                                            Aggression.mqh |
//|                                        Copyright © 2016, Evandro Teixeira |
//|                                            http://www.evandroteixeira.com |
//+---------------------------------------------------------------------------+
#property copyright                    "Copyright © 2016, Evandro Teixeira"
#property description                  "Buyers vs Sellers"
#property link                         "evandroteixeira.com"
#property version                      "1.0"

#property indicator_separate_window
#property indicator_buffers 2
#property indicator_plots   2

//---
#property indicator_type1                       DRAW_HISTOGRAM
#property indicator_style1                      STYLE_SOLID
#property indicator_width1                      2
#property indicator_label1                      "Buyers"

//---
#property indicator_type2                       DRAW_HISTOGRAM
#property indicator_style2                      STYLE_SOLID
#property indicator_width2                      2
#property indicator_label2                      "Sellers"

//---
double ExtBuyBuffer[],ExtSellBuffer[];

//---
#define     DATA_LIMIT 37

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int OnInit()
  {
      SetIndexBuffer(0,ExtBuyBuffer,INDICATOR_DATA);
      PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,DATA_LIMIT);
      PlotIndexSetInteger(0,PLOT_LINE_COLOR,clrCornflowerBlue);

      SetIndexBuffer(1,ExtSellBuffer,INDICATOR_DATA);
      PlotIndexSetInteger(1,PLOT_DRAW_BEGIN,DATA_LIMIT);
      PlotIndexSetInteger(1,PLOT_LINE_COLOR,clrViolet);

      IndicatorSetString(INDICATOR_SHORTNAME,"Aggression ");
      IndicatorSetInteger(INDICATOR_DIGITS,0);

      return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//| On DeInit                                                        |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
      //--
  }

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
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[])
  {
//--- requesting ticks
   MqlTick           tick_array[], tick;
   int copied        =  CopyTicks(Symbol(),tick_array,COPY_TICKS_TRADE);
   int count         =  ArraySize(tick_array);

   ArraySetAsSeries(tick_array,true);

   double currVolumeBUY, currVolumeSell;
//---
   for(int i=0; i<count; i++)
      {
         tick           = tick_array[i];
         bool buy       = tick.flags == 56;     //24
         bool sell      = tick.flags == 88;    //24

         //bool buy       = (tick.flags&TICK_FLAG_BUY)==TICK_FLAG_BUY;
         //bool sell      = (tick.flags&TICK_FLAG_SELL)==TICK_FLAG_SELL;
         //Print(buy);

         if(buy)
            {
               currVolumeBUY     = (double)tick.volume;
               //ExtBuyBuffer[i]   += currVolumeBUY;
               ExtBuyBuffer[i]   = currVolumeBUY;
            }

         if(sell)
            {
               currVolumeSell    = (double)tick.volume;
               //ExtSellBuffer[i] = volume[i]-ExtBuyBuffer[i];
               ExtSellBuffer[i]  -= currVolumeSell;
               //ExtSellBuffer[i]  = currVolumeSell-(currVolumeSell*2);
            }
         //ZeroMemory(tick);
      }
//----    
   return(rates_total);
  }
//+------------------------------------------------------------------+


Eu gostaria de saber se tem como atribuir essas agressões de compra e venda em um histograma e o que eu deixei passar em branco nesse código? 

Qualquer ajuda é bem-vinda.

Abraço,

Evandro Teixeira.
 

Evandro, boa tarde!

Ainda estou pegando o jeito no meta, mais ACHO que ExtBuyBuffer[i] o "i" representa o numero do candle, e o seu loop FOR count a quantidade de retorno de ticks que não são as mesmas, sera que isso não gera um erro no seu indicador?

 Atenciosamente,

Daniel 

 
Daniel Andrejczuk:

Evandro, boa tarde!

Ainda estou pegando o jeito no meta, mais ACHO que ExtBuyBuffer[i] o "i" representa o numero do candle, e o seu loop FOR count a quantidade de retorno de ticks que não são as mesmas, sera que isso não gera um erro no seu indicador?

 Atenciosamente,

Daniel 

Olá Daniel,

eu acho que não porque provavelmente apareceria no print o erro "array out of range". No print aparece todas as agressões do Times N Sales, ele só não adiciona os dados no histograma.

Abraço.
 

Oi Evandro, boa noite!

Veja, a situação que falei gera justamente esse erro ("array out of range"), junto com a mensagem de erro vem uma observação de numero de linha e coluna ("array out of range (10, 15)") que ACHO que deve ser a posição do i na array  ExtBuyBuffer[i].

Veja a situação hipotética: se no seu indicador tem 100 candles e 5000 ticks retornados.

ExtBuyBuffer[]-----esse array vai de 0 até 100 (qualquer valor acima de 100 gera erro array) ela guarda o valor do indicador no candle, como no caso da suposição,ate 100 por ter 100 candle. 

No seu loop "for(int i=0; i<count; i++)" count iria de 0 a 5000, a partir de 101 quando passar na variável ExtBuyBuffer[],  gerará o erro de array.

Sugiro dar mais uma verificada, o erro que vocÊ informou corrobora com meu palpite.

At,

Daniel 

 
Daniel Andrejczuk:

Oi Evandro, boa noite!

Veja, a situação que falei gera justamente esse erro ("array out of range"), junto com a mensagem de erro vem uma observação de numero de linha e coluna ("array out of range (10, 15)") que ACHO que deve ser a posição do i na array  ExtBuyBuffer[i].

Veja a situação hipotética: se no seu indicador tem 100 candles e 5000 ticks retornados.

ExtBuyBuffer[]-----esse array vai de 0 até 100 (qualquer valor acima de 100 gera erro array) ela guarda o valor do indicador no candle, como no caso da suposição,ate 100 por ter 100 candle. 

No seu loop "for(int i=0; i<count; i++)" count iria de 0 a 5000, a partir de 101 quando passar na variável ExtBuyBuffer[],  gerará o erro de array.

Sugiro dar mais uma verificada, o erro que vocÊ informou corrobora com meu palpite.

At,

Daniel 

Olá Daniel,

eu acho que você entendeu errado. Esse erro "array out of range" não esta acontecendo.

 
Opa, tranquilo!
 
Evandro Teixeira:
Olá pessoal,

eu estou tentando criar um indicador de volume que separe as agressões de compra e venda em um histograma com valores negativos (venda) e positivos (compra).

O problema é que ele retorna números gigantescos ou simplesmente não mostra valor algum.

//+---------------------------------------------------------------------------+
//|                                                            Aggression.mqh |
//|                                        Copyright © 2016, Evandro Teixeira |
//|                                            http://www.evandroteixeira.com |
//+---------------------------------------------------------------------------+
#property copyright                    "Copyright © 2016, Evandro Teixeira"
#property description                  "Buyers vs Sellers"
#property link                         "evandroteixeira.com"
#property version                      "1.0"

#property indicator_separate_window
#property indicator_buffers 2
#property indicator_plots   2

//---
#property indicator_type1                       DRAW_HISTOGRAM
#property indicator_style1                      STYLE_SOLID
#property indicator_width1                      2
#property indicator_label1                      "Buyers"

//---
#property indicator_type2                       DRAW_HISTOGRAM
#property indicator_style2                      STYLE_SOLID
#property indicator_width2                      2
#property indicator_label2                      "Sellers"

//---
double ExtBuyBuffer[],ExtSellBuffer[];

//---
#define     DATA_LIMIT 37

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int OnInit()
  {
      SetIndexBuffer(0,ExtBuyBuffer,INDICATOR_DATA);
      PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,DATA_LIMIT);
      PlotIndexSetInteger(0,PLOT_LINE_COLOR,clrCornflowerBlue);

      SetIndexBuffer(1,ExtSellBuffer,INDICATOR_DATA);
      PlotIndexSetInteger(1,PLOT_DRAW_BEGIN,DATA_LIMIT);
      PlotIndexSetInteger(1,PLOT_LINE_COLOR,clrViolet);

      IndicatorSetString(INDICATOR_SHORTNAME,"Aggression ");
      IndicatorSetInteger(INDICATOR_DIGITS,0);

      return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//| On DeInit                                                        |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
      //--
  }

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
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[])
  {
//--- requesting ticks
   MqlTick           tick_array[], tick;
   int copied        =  CopyTicks(Symbol(),tick_array,COPY_TICKS_TRADE);
   int count         =  ArraySize(tick_array);

   ArraySetAsSeries(tick_array,true);

   double currVolumeBUY, currVolumeSell;
//---
   for(int i=0; i<count; i++)
      {
         tick           = tick_array[i];
         bool buy       = tick.flags == 56;     //24
         bool sell      = tick.flags == 88;    //24

         //bool buy       = (tick.flags&TICK_FLAG_BUY)==TICK_FLAG_BUY;
         //bool sell      = (tick.flags&TICK_FLAG_SELL)==TICK_FLAG_SELL;
         //Print(buy);

         if(buy)
            {
               currVolumeBUY     = (double)tick.volume;
               //ExtBuyBuffer[i]   += currVolumeBUY;
               ExtBuyBuffer[i]   = currVolumeBUY;
            }

         if(sell)
            {
               currVolumeSell    = (double)tick.volume;
               //ExtSellBuffer[i] = volume[i]-ExtBuyBuffer[i];
               ExtSellBuffer[i]  -= currVolumeSell;
               //ExtSellBuffer[i]  = currVolumeSell-(currVolumeSell*2);
            }
         //ZeroMemory(tick);
      }
//----    
   return(rates_total);
  }
//+------------------------------------------------------------------+


Eu gostaria de saber se tem como atribuir essas agressões de compra e venda em um histograma e o que eu deixei passar em branco nesse código? 

Qualquer ajuda é bem-vinda.

Abraço,

Evandro Teixeira.

Na documentação da função Copyticks: https://www.mql5.com/en/docs/series/copyticks

"If the from and count parameters are not specified, all available recent ticks (but not more than 2000) will be written to ticks_array[]. The flags parameter allows specifying the type of required ticks."


Ou seja, se não especificar o from nem o count, o indicador vai ler os 2000 ticks mais recentes, e o valor do tick_array será 2000.

Documentation on MQL5: Timeseries and Indicators Access / CopyTicks
Documentation on MQL5: Timeseries and Indicators Access / CopyTicks
  • www.mql5.com
Timeseries and Indicators Access / CopyTicks - Reference on algorithmic/automated trading language for MetaTrader 5
 
cat0l0n:

Na documentação da função Copyticks: https://www.mql5.com/en/docs/series/copyticks

"If the from and count parameters are not specified, all available recent ticks (but not more than 2000) will be written to ticks_array[]. The flags parameter allows specifying the type of required ticks."


Ou seja, se não especificar o from nem o count, o indicador vai ler os 2000 ticks mais recentes, e o valor do tick_array será 2000.

Sim, eu já tinha visto isso. A dificuldade esta em colocar os ticks na tela, parecido com o volume porem separados em comprados e vendidos. Usando o indicador de volume ou qualquer outro de acumulação como base, parece bem simples mas quando eu tento aplicar o mesmo conceito nesse indicador o máximo que eu consigo é colocar tick por tick.

 

//+---------------------------------------------------------------------------+
//|                                                            Aggression.mqh |
//|                                        Copyright © 2016, Evandro Teixeira |
//|                                            http://www.evandroteixeira.com |
//+---------------------------------------------------------------------------+
#property copyright                    "Copyright © 2016, Evandro Teixeira"
#property description                  "Buyers vs Sellers"
#property link                         "evandroteixeira.com"
#property version                      "1.0"

#property indicator_separate_window
#property indicator_buffers 2
#property indicator_plots   2

#property indicator_label1  "Buyer"
#property indicator_type1   DRAW_HISTOGRAM
#property indicator_color1  White
#property indicator_style1  STYLE_SOLID
#property indicator_width1  3

#property indicator_label2  "Seller"
#property indicator_type2   DRAW_HISTOGRAM
#property indicator_color2  FireBrick
#property indicator_style2  STYLE_SOLID
#property indicator_width2  3

//--- indicator buffers
double         ExtBuyBuffer[];
double         ExtSellBuffer[];
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                         |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
  }
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,ExtBuyBuffer,INDICATOR_DATA);
   SetIndexBuffer(1,ExtSellBuffer,INDICATOR_DATA);
   PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0);
   PlotIndexSetDouble(1,PLOT_EMPTY_VALUE,0);
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator 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 &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
   static int ticks=0;
//---
   if(ticks==0)
     {
      ArrayInitialize(ExtSellBuffer,0);
      ArrayInitialize(ExtBuyBuffer,0);
     }
//---
   MqlTick last_tick;
   if(SymbolInfoTick(Symbol(),last_tick) && last_tick.flags == 56)
     {
         ExtBuyBuffer[ticks]+=last_tick.volume;
         int shift=rates_total-1-ticks;
         ticks++;
         ExtBuyBuffer[rates_total-1]+=last_tick.volume;
         PlotIndexSetInteger(0,PLOT_SHIFT,shift);
     }
   if(SymbolInfoTick(Symbol(),last_tick) && last_tick.flags == 88)
     {
         ExtSellBuffer[ticks]-=last_tick.volume;
         int shift=rates_total-1-ticks;
         ticks++;
         ExtSellBuffer[rates_total-1]-=last_tick.volume;
         PlotIndexSetInteger(1,PLOT_SHIFT,shift);
     }

//--- return value of prev_calculated for next call
   return(rates_total);
  }
//-----------------------------------------++
 

Eu retirei a variável int shift e o PlotIndexSetInteger e aparentemente resolveu o problema.

Abraço! 

 
Evandro Teixeira:

Eu retirei a variável int shift e o PlotIndexSetInteger e aparentemente resolveu o problema.

Abraço! 

Acho que teria mais um problema. Não tenho certeza se a função OnCalculate consegue processar todos os ticks. Na documentação, está escrito que OnTick pode deixar de processar algum tick se ainda estiver processando um tick anterior, mas não há nada muito claro a respeito de OnCalculate. Acho que vale a pena fazer um check para ver se o total de ticks processados no indicador é igual ao valor do tick_volume, que guarda a quantidade de ticks por candle.
 

Ola cat0l0n ! 

OnTick se usa em um EA e processa somente o tickt da vez (nos EA  o evento OnCalculate não é acionado).

OnCalculate se usa em um indicador e deve trabalhar pela função de pesquisa de dados tipo copyrate (nos indicadores  o evento OnTick não é acionado). 

Pequenas sutilezas,  perdi muito tempo por ninguém me ter dito isso antes, talvez ajude essa informação.

Atenciosamente,

Daniel 

Razão: