Discussão do artigo "Distribuições estatísticas em forma de histogramas sem buffers de indicador e matrizes"

 

Novo artigo Distribuições estatísticas em forma de histogramas sem buffers de indicador e matrizes foi publicado:

O artigo considera a possibilidade de criar histogramas, distribuições estatísticas das características do mercado usando memória gráfica, ou seja, sem o uso de buffers de indicador e matrizes. Aqui você tem à sua disposição não só exemplos detalhados de como construir esses histogramas, mas também pode conhecer a funcionalidade "oculta" dos objetos gráficos da linguagem MQL5.

Neste artigo, vamos nos concentrar nos histogramas verticais de séries de variação: os valores de preço das características estudadas estarão localizados no eixo vertical em ordem crescente, enquanto a frequência, no eixo horizontal (Fig. 1). Os dados de preços, que entram ao terminal, são agrupados e alocados na barra atual e podem ser exibidos com respeito ao eixo da esquerda, direita ou em ambos os lados simultaneamente.

Fig. 1. Gráfico de colunas vertical de distribuição de preços Bid e Ask. 

Fig. 1. Gráfico de colunas vertical de distribuição de preços Bid e Ask.

Autor: Sergey Pavlov

 
A encadernação não atrapalha?
 

Uma grande ajuda para trabalhar no mercado seria a criação de um indicador na forma de um histograma na janela principal com dados da pilha sobre o número de ordens, mas em dinâmica....

(um exemplo é o indicador #Xaser-info

[Excluído]  
Lembrei-me dessa maneira de exibir os indicadores da VSA. Clara e eficaz
 

Sergey, isso é muito interessante e eu gostaria de falar sobre o assunto.

Primeiro, não sei como obter o código da postagem de notícias. Acabei salvando o código e copiando e colando-o do arquivo salvo. Não tenho certeza do que é um arquivo .mht.

De qualquer forma, colei a função DrawHistogram(), mas quando tentei compilá-la, havia variáveis indefinidas, por exemplo, color_R_active. Você poderia me ajudar a defini-las?

Obrigado.

Chuck Stangor

 
cstangor:

Sergey, isso é muito interessante e eu gostaria de falar sobre o assunto.

Primeiro, não sei como obter o código da postagem de notícias. Acabei salvando o código e copiando e colando-o do arquivo salvo. Não tenho certeza do que é um arquivo .mht.

De qualquer forma, colei a função DrawHistogram(), mas quando tentei compilá-la, havia variáveis indefinidas, por exemplo, color_R_active. Você poderia me ajudar a defini-las?

Obrigado.

Chuck Stangor

Mostrar o código completo.

 
Sergey Pavlov:

Mostrar o código completo.

//+------------------------------------------------------------------+
//|draw_histogram.mqh
//| Copyright 2016, MetaQuotes Software Corp. |
//| https://www.mql5.com
//+------------------------------------------------------------------+
#property copyright "Copyright 2016, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
//+------------------------------------------------------------------+
//| define|
//+------------------------------------------------------------------+
// #define MacrosHello "Olá, mundo!"
// #define MacrosYear 2010
//+------------------------------------------------------------------+
//| Importações de DLL|
//+------------------------------------------------------------------+
// #importar "user32.dll"
// int SendMessageA(int hWnd,int Msg,int wParam,int lParam);
// #importar "my_expert.dll"
// int ExpertRecalculate(int wParam,int lParam);
// #import
//+------------------------------------------------------------------+
//| Importações EX5|
//+------------------------------------------------------------------+
// #importar "stdlib.ex5"
// string ErrorDescription(int error_code);
// #import
//+------------------------------------------------------------------+

void DrawHistogram(bool draw,     // desenhar um histograma para a esquerda ou para a direita
                   string h_name, // prefixo exclusivo para o nome do objeto
                   double price,  // preço (parâmetro analisado)
                   datetime time, // vincular um histograma à barra atual
                   int span,      // capacidade de dígitos do parâmetro analisado
                   int swin=0)    // janela do histograma
  {
   double y=NormalizeDouble(price,span);
   string pfx=DoubleToString(y,span);
// se draw=true, desenha o histograma à direita
   if(draw)
     {
      string name="+ "+h_name+pfx;                   // nome do objeto: prefixo+preço
      ObjectCreate(0,name,OBJ_TREND,swin,time,y);    // criar o objeto
      ObjectSetInteger(0,name,OBJPROP_COLOR,color_R_active); // definir a cor do objeto
      ObjSet;                                                // macro de encurtamento de código
      if(StringFind(ObjectGetString(0,name,OBJPROP_TEXT),"*",0)<0)
        {// se o preço resultante entrou na amostra pela primeira vez
         ObjectSetString(0,name,OBJPROP_TEXT,"*1");          // a frequência de preço é 1
         ObjectSetInteger(0,name,OBJPROP_TIME,1,time+hsize); // definir a coordenada de tempo
        }
      else
        {// se o preço resultante entrou na amostra não pela primeira vez
         string str=ObjectGetString(0,name,OBJPROP_TEXT);    // obter o valor da propriedade
         string strint=StringSubstr(str,1);                  // destacar a substring
         long n=StringToInteger(strint);                     // obter uma frequência para cálculos adicionais
         n++;                                                // aumentar o valor em 1
         ObjectSetString(0,name,OBJPROP_TEXT,"*"+(string)n); // gravar um novo valor na propriedade
         ObjectSetInteger(0,name,OBJPROP_TIME,1,time+hsize*n);//definir a coordenada de tempo
        }
     }
// se draw=false, escreva o histograma à esquerda
   if(!draw)
     {
      string name="- "+h_name+pfx;
      ObjectCreate(0,name,OBJ_TREND,swin,time,y);
      ObjectSetInteger(0,name,OBJPROP_COLOR,color_L_active);
      ObjSet;
      if(StringFind(ObjectGetString(0,name,OBJPROP_TEXT),"*",0)<0)
        {
         ObjectSetString(0,name,OBJPROP_TEXT,"*1");
         ObjectSetInteger(0,name,OBJPROP_TIME,1,time-hsize);
        }
      else
        {
         string str=ObjectGetString(0,name,OBJPROP_TEXT);
         string strint=StringSubstr(str,1);
         long n=StringToInteger(strint);
         n++;
         ObjectSetString(0,name,OBJPROP_TEXT,"*"+(string)n);
         ObjectSetInteger(0,name,OBJPROP_TIME,1,time-hsize*n);
        }
     }
  ChartRedraw();
}
 
//+------------------------------------------------------------------+
//|draw_histogram.mqh
//| Copyright 2016, MetaQuotes Software Corp. |
//| https://www.mql5.com
//+------------------------------------------------------------------+
#property copyright "Copyright 2016, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
//--- Макросы
#define   R        43    // значения префикса (+) для гистограмм справа
#define   L        45    // значения префикса (-) для гистограмм слева
#define   WIDTH    2     // толщина линий
#define   ObjSet1  ObjectSetInteger(0,name,OBJPROP_WIDTH,WIDTH)
#define   ObjSet2  ObjectSetDouble(0,name,OBJPROP_PRICE,0,y)
#define   ObjSet3  ObjectSetInteger(0,name,OBJPROP_TIME,0,time)
#define   ObjSet4  ObjectSetDouble(0,name,OBJPROP_PRICE,1,y)
#define   ObjSet5  ObjectSetInteger(0,name,OBJPROP_BACK,true)
#define   ObjSet   ObjSet1;ObjSet2;ObjSet3;ObjSet4;ObjSet5
//---
int      hsize=10;                     // масштаб гистограммы
color    color_R_active=clrRed;        // цвет активных линий справа
color    color_R_passive=clrLightCoral;// цвет пассивных линий справа
color    color_L_active=clrBlue;       // цвет активных линий слева
color    color_L_passive=clrSkyBlue;   // цвет пассивных линий слева

void DrawHistogram(bool draw,     // desenhar um histograma para a esquerda ou para a direita
                   string h_name, // prefixo exclusivo para o nome do objeto
                   double price,  // preço (parâmetro analisado)
                   datetime time, // vincular um histograma à barra atual
                   int span,      // capacidade de dígitos do parâmetro analisado
                   int swin=0)    // janela do histograma
  {
   double y=NormalizeDouble(price,span);
   string pfx=DoubleToString(y,span);
// se draw=true, desenha o histograma à direita
   if(draw)
     {
      string name="+ "+h_name+pfx;                   // nome do objeto: prefixo+preço
      ObjectCreate(0,name,OBJ_TREND,swin,time,y);    // criar o objeto
      ObjectSetInteger(0,name,OBJPROP_COLOR,color_R_active); // definir a cor do objeto
      ObjSet;                                                // macro de encurtamento de código
      if(StringFind(ObjectGetString(0,name,OBJPROP_TEXT),"*",0)<0)
        {// se o preço resultante entrou na amostra pela primeira vez
         ObjectSetString(0,name,OBJPROP_TEXT,"*1");          // a frequência de preço é 1
         ObjectSetInteger(0,name,OBJPROP_TIME,1,time+hsize); // definir a coordenada de tempo
        }
      else
        {// se o preço resultante entrou na amostra não pela primeira vez
         string str=ObjectGetString(0,name,OBJPROP_TEXT);    // obter o valor da propriedade
         string strint=StringSubstr(str,1);                  // destacar a substring
         long n=StringToInteger(strint);                     // obter uma frequência para cálculos adicionais
         n++;                                                // aumentar o valor em 1
         ObjectSetString(0,name,OBJPROP_TEXT,"*"+(string)n); // gravar um novo valor na propriedade
         ObjectSetInteger(0,name,OBJPROP_TIME,1,time+hsize*n);//definir a coordenada de tempo
        }
     }
// se draw=false, escreva o histograma à esquerda
   if(!draw)
     {
      string name="- "+h_name+pfx;
      ObjectCreate(0,name,OBJ_TREND,swin,time,y);
      ObjectSetInteger(0,name,OBJPROP_COLOR,color_L_active);
      ObjSet;
      if(StringFind(ObjectGetString(0,name,OBJPROP_TEXT),"*",0)<0)
        {
         ObjectSetString(0,name,OBJPROP_TEXT,"*1");
         ObjectSetInteger(0,name,OBJPROP_TIME,1,time-hsize);
        }
      else
        {
         string str=ObjectGetString(0,name,OBJPROP_TEXT);
         string strint=StringSubstr(str,1);
         long n=StringToInteger(strint);
         n++;
         ObjectSetString(0,name,OBJPROP_TEXT,"*"+(string)n);
         ObjectSetInteger(0,name,OBJPROP_TIME,1,time-hsize*n);
        }
     }
  ChartRedraw();
}
 
Sergey Pavlov:
//+------------------------------------------------------------------+
//|draw_histogram.mqh
//| Copyright 2016, MetaQuotes Software Corp. |
//| https://www.mql5.com
//+------------------------------------------------------------------+
#property copyright "Copyright 2016, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
//--- Макросы
#define   R        43    // значения префикса (+) для гистограмм справа
#define   L        45    // значения префикса (-) для гистограмм слева
#define   WIDTH    2     // толщина линий
#define   ObjSet1  ObjectSetInteger(0,name,OBJPROP_WIDTH,WIDTH)
#define   ObjSet2  ObjectSetDouble(0,name,OBJPROP_PRICE,0,y)
#define   ObjSet3  ObjectSetInteger(0,name,OBJPROP_TIME,0,time)
#define   ObjSet4  ObjectSetDouble(0,name,OBJPROP_PRICE,1,y)
#define   ObjSet5  ObjectSetInteger(0,name,OBJPROP_BACK,true)
#define   ObjSet   ObjSet1;ObjSet2;ObjSet3;ObjSet4;ObjSet5
//---
int      hsize=10;                     // масштаб гистограммы
color    color_R_active=clrRed;        // цвет активных линий справа
color    color_R_passive=clrLightCoral;// цвет пассивных линий справа
color    color_L_active=clrBlue;       // цвет активных линий слева
color    color_L_passive=clrSkyBlue;   // цвет пассивных линий слева

void DrawHistogram(bool draw,     // desenhar um histograma para a esquerda ou para a direita
                   string h_name, // prefixo exclusivo para o nome do objeto
                   double price,  // preço (parâmetro analisado)
                   datetime time, // vincular um histograma à barra atual
                   int span,      // capacidade de dígitos do parâmetro analisado
                   int swin=0)    // janela do histograma
  {
   double y=NormalizeDouble(price,span);
   string pfx=DoubleToString(y,span);
// se draw=true, desenha o histograma à direita
   if(draw)
     {
      string name="+ "+h_name+pfx;                   // nome do objeto: prefixo+preço
      ObjectCreate(0,name,OBJ_TREND,swin,time,y);    // criar o objeto
      ObjectSetInteger(0,name,OBJPROP_COLOR,color_R_active); // definir a cor do objeto
      ObjSet;                                                // macro de encurtamento de código
      if(StringFind(ObjectGetString(0,name,OBJPROP_TEXT),"*",0)<0)
        {// se o preço resultante entrou na amostra pela primeira vez
         ObjectSetString(0,name,OBJPROP_TEXT,"*1");          // a frequência de preço é 1
         ObjectSetInteger(0,name,OBJPROP_TIME,1,time+hsize); // definir a coordenada de tempo
        }
      else
        {// se o preço resultante entrou na amostra não pela primeira vez
         string str=ObjectGetString(0,name,OBJPROP_TEXT);    // obter o valor da propriedade
         string strint=StringSubstr(str,1);                  // destacar a substring
         long n=StringToInteger(strint);                     // obter uma frequência para cálculos adicionais
         n++;                                                // aumentar o valor em 1
         ObjectSetString(0,name,OBJPROP_TEXT,"*"+(string)n); // gravar um novo valor na propriedade
         ObjectSetInteger(0,name,OBJPROP_TIME,1,time+hsize*n);//definir a coordenada de tempo
        }
     }
// se draw=false, escreva o histograma à esquerda
   if(!draw)
     {
      string name="- "+h_name+pfx;
      ObjectCreate(0,name,OBJ_TREND,swin,time,y);
      ObjectSetInteger(0,name,OBJPROP_COLOR,color_L_active);
      ObjSet;
      if(StringFind(ObjectGetString(0,name,OBJPROP_TEXT),"*",0)<0)
        {
         ObjectSetString(0,name,OBJPROP_TEXT,"*1");
         ObjectSetInteger(0,name,OBJPROP_TIME,1,time-hsize);
        }
      else
        {
         string str=ObjectGetString(0,name,OBJPROP_TEXT);
         string strint=StringSubstr(str,1);
         long n=StringToInteger(strint);
         n++;
         ObjectSetString(0,name,OBJPROP_TEXT,"*"+(string)n);
         ObjectSetInteger(0,name,OBJPROP_TIME,1,time-hsize*n);
        }
     }
  ChartRedraw();
}
Obrigado!
 

Sr. Sergey,

Estou tentando plotar o volume de compra e venda de tick em vez de bid e ask para ter um volume no preço como indicador, é possível? você tem algum código com volume de compra/venda de tick que possa postar?

Muito obrigado!


Exemplo de dados que quero plotar, ele plota um histograma horizontal do volume de ticks de compra/venda em uma janela separada:

#property indicator_separate_window
#property indicator_buffers 2
#property indicator_plots   2
//
#property indicator_label1  "SELL Tick"
#property indicator_type1   DRAW_HISTOGRAM
#property indicator_color1  clrTomato
#property indicator_style1  STYLE_SOLID
//
#property indicator_label2  "BUY Tick"
#property indicator_type2   DRAW_HISTOGRAM
#property indicator_color2  clrSpringGreen
#property indicator_style2  STYLE_SOLID
#property indicator_width2  5

//--- buffers de indicadores
double         ExtBuyBuffer[];
double         ExtSellBuffer[];

int OnInit()
  {
//--- mapeamento de buffers de indicadores
   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);
  }



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]+=NormalizeDouble(last_tick.volume,2); 
         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]+=NormalizeDouble(last_tick.volume,2); 
         int shift=rates_total-1-ticks;
         ticks++;
         ExtSellBuffer[rates_total-1]=last_tick.volume;
         PlotIndexSetInteger(1,PLOT_SHIFT,shift);
     }

//
//--- valor de retorno de prev_calculated para a próxima chamada

   return(rates_total);
 }