Livro de Ofertas no Gráfico

 

Olá,


Estou tentando fazer um Livro de Ofertas no Gráfico, semelhante ao Livro Visual do ProfitChart, conforme imagem abaixo.


LivroVisual


Eu já fiz um rascunho (código abaixo) e a maior dúvida é se esse histograma deve ser feito por um objeto do tipo OBJ_TREND ou de alguma outra maneira porque eu até estou conseguindo os dados do livro de ofertas mas não estou conseguindo plotá-los como um OBJ_TREND. Eu consigo por OBJ_HLINE mas, dessa forma, não é possível editar o comprimento da linha. Ou talvez seja de outro jeito e eu estou fazendo tudo errado. Agradeço qualquer ajuda para conseguir fazer esse indicador.


#property copyright ""
#property indicator_chart_window

int OnInit()
  {
   if(MarketBookAdd(_Symbol))
      return INIT_SUCCEEDED;   

   return INIT_FAILED;
  }

void OnDeinit(const int reason)
  {
   if(!MarketBookRelease(_Symbol))
      Print("Falha ao fechar o DOM");
  }
  
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[])
  {
  
  MqlBookInfo priceArray[];
  bool getBook=MarketBookGet(NULL,priceArray);
  
  if(getBook)
        {
         int size=ArraySize(priceArray); 
         for(int i=0;i<size;i++)
           {                    
            ObjectCreate(_Symbol,i,OBJ_TREND,0,-priceArray[i].volume,priceArray[i].price,0,priceArray[i].price);            
            ObjectSetInteger(_Symbol,i,OBJPROP_RAY,false);            
            ObjectSetInteger(_Symbol,i,OBJPROP_COLOR,C'0,0,0');
            ObjectSetInteger(_Symbol,i,OBJPROP_WIDTH,2);
            ObjectSetInteger(_Symbol,i,OBJPROP_TYPE,0);              
           }   
        }  
   
   return(rates_total);
  }
 
marcusmota:

Olá,


Estou tentando fazer um Livro de Ofertas no Gráfico, semelhante ao Livro Visual do ProfitChart, conforme imagem abaixo.



Eu já fiz um rascunho (código abaixo) e a maior dúvida é se esse histograma deve ser feito por um objeto do tipo OBJ_TREND ou de alguma outra maneira porque eu até estou conseguindo os dados do livro de ofertas mas não estou conseguindo plotá-los como um OBJ_TREND. Eu consigo por OBJ_HLINE mas, dessa forma, não é possível editar o comprimento da linha. Ou talvez seja de outro jeito e eu estou fazendo tudo errado. Agradeço qualquer ajuda para conseguir fazer esse indicador.

Olá amigo! Eu não sei nada ( ainda ) de programação, mas deixo meu incentivo e gratidão por estar fazendo algo excelente. Logo você vai conseguir e será muito bem sucedido. Deus te abençoe.

 

Pessoal, eu consegui fazer, mais ou menos, esse Livro Visual, conforme imagem e código abaixo. Mas ainda há um pequeno problema na determinação da largura desses retângulos. A minha ideia foi normalizar os volumes (entre o maior volume e o volume nulo) em uma quantidade fixa de pixels. Isso deu certo, mas há alguns momentos em que o comprimento desses retângulos fica oscilando bruscamente entre o valor correto e o valor máximo de pixels, sendo que o volume maior está em outros níveis (fiz a conferência do Livro de ofertas para ter a confirmação do caso). Acredito que o problema esteja na determinação do maior volume no array, e eu não devo ter feito da maneira mais adequada. Os volumes estão no bookArray[].volume e eu joguei esse array dentro de outro array (VolumeArray[]) para aí determinar o maior valor. Ao averiguar esse maior volume no script, parece que está tudo certo. Mas, em algumas ocasiões, esses retângulos continuam chacoalhando, rapidamente, pra lá e pra cá.


E outro pequeno problema, como vocês podem ver, é que eu devo estar escrevendo o código de maneira não adequada, pois eu faço tudo dentro do int OnCalculate, e acredito que essa não seja a melhor maneira, não é? Assim deve haver um maior uso de memória. Ainda não estou conseguindo escrever conforme a documentação, que declara as funções no espaço global. Mas isso vou melhorando com o tempo e gostaria de dicas de como otimizar esse código.



#property copyright "Marcus Mota"
#property indicator_chart_window
#property indicator_buffers 0
#property indicator_plots   0
#property strict

input int InpWidBook = 255; //Largura do Book Visual
input color InpClrBuy = C'17,134,225'; //Cor de Compra
input color InpClrSell = C'196,55,0'; //Cor de Venda

int OnInit()
  {
   if(MarketBookAdd(_Symbol))
      return INIT_SUCCEEDED;   

   return INIT_FAILED;
  }

void OnDeinit(const int reason)
  {
   ObjectsDeleteAll(0,0,OBJ_LABEL);
   ObjectsDeleteAll(0,0,OBJ_RECTANGLE_LABEL);
  }
  
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[])
  { 
  
  //Variáveis necessárias aos cálculos
  double TickSize = SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_SIZE); 
  double MaximumPrice = ChartGetDouble(0,CHART_PRICE_MAX);
  long ChartWidth = ChartGetInteger(0,CHART_WIDTH_IN_PIXELS,0);
  double BidPrice, AskPrice, MinimunChange;       
  
  MqlTick LastPrice;     
  SymbolInfoTick(Symbol(),LastPrice);  
  BidPrice = LastPrice.bid;  
  AskPrice = LastPrice.ask;
  MinimunChange = MaximumPrice+TickSize;    
  
  //Variação de 1 Tick em Pixels, para a altura do OBJ_RECTANGLE_LABEL
  int PixelX, PixelY, PixelYMax, PixelXMax, PixelYMaxPlus, PixelXMaxPlus;  
  int MaximumPriceToPixel = ChartTimePriceToXY(0,0,TimeCurrent(),MaximumPrice,PixelXMax,PixelYMax);  
  int MaximumPricePlusToPixel = ChartTimePriceToXY(0,0,TimeCurrent(),MinimunChange,PixelXMaxPlus,PixelYMaxPlus);
  int PixelTick = MathAbs(PixelYMaxPlus-PixelYMax);    
   
  //Eventos do Book 
  MqlBookInfo bookArray[];
 
  bool getBook=MarketBookGet(_Symbol,bookArray);    
    
  if(getBook)
        {
         int size=ArraySize(bookArray);
         double VolumeArray[]; 
         ArrayResize(VolumeArray,size,0);          
         for(int i=0;i<size;i++)
           {                      
            double Pixel = ChartTimePriceToXY(0,0,TimeCurrent(),bookArray[i].price,PixelX,PixelY);            
                     
            VolumeArray[i]=(int)bookArray[i].volume;            
            double MaxBookVolume=VolumeArray[ArrayMaximum(VolumeArray,0,WHOLE_ARRAY)];                                        
                                         
            //Book Visual
            ObjectCreate(0,(string)i+"Rectangle",OBJ_RECTANGLE_LABEL,0,0,0);            
            ObjectSetInteger(0,(string)i+"Rectangle",OBJPROP_BORDER_TYPE,BORDER_SUNKEN);            
            ObjectSetInteger(0,(string)i+"Rectangle",OBJPROP_XSIZE,(int)(-(bookArray[i].volume/MaxBookVolume)*InpWidBook));
            ObjectSetInteger(0,(string)i+"Rectangle",OBJPROP_YSIZE,PixelTick);
            ObjectSetInteger(0,(string)i+"Rectangle",OBJPROP_XDISTANCE,ChartWidth);
            ObjectSetInteger(0,(string)i+"Rectangle",OBJPROP_YDISTANCE,PixelY);            
               if(bookArray[i].price > BidPrice) {
            ObjectSetInteger(0,(string)i+"Rectangle",OBJPROP_BGCOLOR,InpClrSell); }
               else if(bookArray[i].price < AskPrice){
            ObjectSetInteger(0,(string)i+"Rectangle",OBJPROP_BGCOLOR,InpClrBuy); }                                                        
           }              
        }  
   
   return(rates_total);
  }
 
Olá Marcus, eu acho que esse tutorial pode ajudar você de alguma, especialmente na parte "3.4. Exibindo o volume do histograma no Depth of Market".


Abraço!
MQL5 Cookbook: Implementando seu próprio Depth of Market (Book de Ofertas)
MQL5 Cookbook: Implementando seu próprio Depth of Market (Book de Ofertas)
  • 2016.03.07
  • Vasiliy Sokolov
  • www.mql5.com
A linguagem MQL5 está em constante evolução e oferece mais oportunidades para operações com a troca de informações a cada ano. Um desses tipos de dados de troca são informações sobre Depth of Market. É uma tabela especial que mostra os níveis de preços e volumes de ordens limitadas. O terminal MetaTrader 5 tem uma versão do Depth Mercado para a...
 
marcusmota:

Pessoal, eu consegui fazer, mais ou menos, esse Livro Visual, conforme imagem e código abaixo. Mas ainda há um pequeno problema na determinação da largura desses retângulos. A minha ideia foi normalizar os volumes (entre o maior volume e o volume nulo) em uma quantidade fixa de pixels. Isso deu certo, mas há alguns momentos em que o comprimento desses retângulos fica oscilando bruscamente entre o valor correto e o valor máximo de pixels, sendo que o volume maior está em outros níveis (fiz a conferência do Livro de ofertas para ter a confirmação do caso). Acredito que o problema esteja na determinação do maior volume no array, e eu não devo ter feito da maneira mais adequada. Os volumes estão no bookArray[].volume e eu joguei esse array dentro de outro array (VolumeArray[]) para aí determinar o maior valor. Ao averiguar esse maior volume no script, parece que está tudo certo. Mas, em algumas ocasiões, esses retângulos continuam chacoalhando, rapidamente, pra lá e pra cá.


E outro pequeno problema, como vocês podem ver, é que eu devo estar escrevendo o código de maneira não adequada, pois eu faço tudo dentro do int OnCalculate, e acredito que essa não seja a melhor maneira, não é? Assim deve haver um maior uso de memória. Ainda não estou conseguindo escrever conforme a documentação, que declara as funções no espaço global. Mas isso vou melhorando com o tempo e gostaria de dicas de como otimizar esse código.



Ola!


Espero que tenha evoluído com sucesso, promete ser um belo indicador ainda mais se for compartilhar conosco.


A propósito, como vc inseriu o nome do ativo + tempo gráfico no background?


Abs.

 
Japa Trader Br:

Ola!


Espero que tenha evoluído com sucesso, promete ser um belo indicador ainda mais se for compartilhar conosco.


A propósito, como vc inseriu o nome do ativo + tempo gráfico no background?


Abs.

Fala Japa. Não sei se foi dessa forma que ele fez. Mas é possível fazer um indicador ou script que plota um ObjectLabel com o texto sendo o "nome do ativo, timeframe". E alinhá-lo ao centro.

 
Samuel Manoel De Souza:

Fala Japa. Não sei se foi dessa forma que ele fez. Mas é possível fazer um indicador ou script que plota um ObjectLabel com o texto sendo o "nome do ativo, timeframe". E alinhá-lo ao centro.

Blz, foi o que pensei...e consegui fazer. heheh

 
Japa Trader Br:

Ola!


Espero que tenha evoluído com sucesso, promete ser um belo indicador ainda mais se for compartilhar conosco.


A propósito, como vc inseriu o nome do ativo + tempo gráfico no background?


Abs.

Japa, fiz essa marca d'água exatamente como o Samuel comentou. Coloquei aí o código abaixo. Quanto ao indicador do book no gráfico, usando ele ao longo do dia a dia eu modifiquei um pouco a ideia dele. Agora crio linhas horizontais somente nos preços que possuem uma quantidade maior ou igual a de interesse (tipo um filtro). E nos preços onde os lotes são muitos altos (filtro superior) há um label mostrando o número. São as necessidades que vamos vendo ao longo do dia a dia e adaptando, né. Se tiver interesse só dizer aí.


//+------------------------------------------------------------------+
//|                                                     MARCA D'AGUA |
//|                                                      Marcus Mota |
//+------------------------------------------------------------------+
#property copyright "Marcus Mota"
#property indicator_chart_window
#property indicator_buffers 0
#property indicator_plots   0
#property strict

//--- inputs
input string   inputFonte="Tahoma";    //Fonte
input ushort   inputTamanho=100;       //Tamanho
input color    inputCor=clrGray;       //Cor
input double   inputAlpha=0.2;         //Transparência

//--- variáveis
long Altura,Comprimento;
//+------------------------------------------------------------------+
//| Inicialização                                                    |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- possíveis erros
   if(inputTamanho<=0
      || inputAlpha<0
      || inputAlpha>1)
     {
      printf("Erro nos parâmetros de entrada!");
      return INIT_FAILED;
     }

   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Deletar a marca d'água                                           |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   ObjectDelete(0,"Marca D'Água");
  }
//+------------------------------------------------------------------+
//| Criação da marca d'água                                          |
//+------------------------------------------------------------------+
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[])
  {
//--- dimensões do gráfico
   Altura=ChartGetInteger(0,CHART_HEIGHT_IN_PIXELS,0);
   Comprimento=ChartGetInteger(0,CHART_WIDTH_IN_PIXELS,0);

//--- criação da marca d'água
   ObjectCreate(0,"Marca D'Água",OBJ_LABEL,0,0,0);
   ObjectSetInteger(0,"Marca D'Água",OBJPROP_COLOR,0,CorDaMarcaDAgua());
   ObjectSetInteger(0,"Marca D'Água",OBJPROP_FONTSIZE,inputTamanho);
   ObjectSetString(0,"Marca D'Água",OBJPROP_FONT,inputFonte);
   ObjectSetInteger(0,"Marca D'Água",OBJPROP_BACK,true);
   ObjectSetString(0,"Marca D'Água",OBJPROP_TEXT,Symbol()+", "+Periodo());
   ObjectSetInteger(0,"Marca D'Água",OBJPROP_ANCHOR,ANCHOR_CENTER);
   ObjectSetInteger(0,"Marca D'Água",OBJPROP_XDISTANCE,(Comprimento/2));
   ObjectSetInteger(0,"Marca D'Água",OBJPROP_YDISTANCE,(Altura/2));

   return(rates_total);
  }
//+------------------------------------------------------------------+
//| Cor da marca d'água, com cálculo da transparência                |
//+------------------------------------------------------------------+
color CorDaMarcaDAgua()
  {
//--- processo de transparência 
   color ChartBackColorGet=(color)ChartGetInteger(0,CHART_COLOR_BACKGROUND,0);
   uchar blueBack=(uchar)MathFloor(ChartBackColorGet/65536);
   uchar greenBack=(uchar)MathFloor((ChartBackColorGet-(blueBack*65536))/256);
   uchar redBack=(uchar)(ChartBackColorGet -(blueBack*65536) -(greenBack*256));
   uchar blueObject=(uchar)MathFloor(inputCor/65536);
   uchar greenObject=(uchar)MathFloor((inputCor-(blueObject*65536))/256);
   uchar redObject=(uchar)(inputCor -(blueObject*65536) -(greenObject*256));

   uchar redAlpha=(uchar)(redBack*(1-inputAlpha)+redObject*inputAlpha);
   uchar greenAlpha=(uchar)(greenBack*(1-inputAlpha)+greenObject*inputAlpha);
   uchar blueAlpha = (uchar)(blueBack*(1 - inputAlpha) + blueObject*inputAlpha);
   string ClrAlpha = (string)redAlpha+", "+(string)greenAlpha+", "+(string)blueAlpha;

   return (color)ClrAlpha;
  }
//+------------------------------------------------------------------+
//| Período na marca d'água                                          |
//+------------------------------------------------------------------+
string Periodo()
  {
   string Periodo;
   int timeframe=Period();
   switch(timeframe)
     {
      case PERIOD_M1  : Periodo="M1";   break;
      case PERIOD_M2  : Periodo="M2";   break;
      case PERIOD_M3  : Periodo="M3";   break;
      case PERIOD_M4  : Periodo="M4";   break;
      case PERIOD_M5  : Periodo="M5";   break;
      case PERIOD_M6  : Periodo="M6";   break;
      case PERIOD_M10 : Periodo="M10";  break;
      case PERIOD_M12 : Periodo="M12";  break;
      case PERIOD_M15 : Periodo="M15";  break;
      case PERIOD_M20 : Periodo="M20";  break;
      case PERIOD_M30 : Periodo="M30";  break;
      case PERIOD_H1  : Periodo="H1";   break;
      case PERIOD_H2  : Periodo="H2";   break;
      case PERIOD_H3  : Periodo="H3";   break;
      case PERIOD_H4  : Periodo="H4";   break;
      case PERIOD_H6  : Periodo="H6";   break;
      case PERIOD_H8  : Periodo="H8";   break;
      case PERIOD_H12 : Periodo="H12";  break;
      case PERIOD_D1  : Periodo="D1";   break;
      case PERIOD_W1  : Periodo="W1";   break;
      case PERIOD_MN1 : Periodo="MN1";  break;
     }

   return(Periodo);
  }
//+------------------------------------------------------------------+
 
Eu não entendo de programação, mas gostei muito do indicador!...conseguiu resolver a questão da oscilação do comprimento dos retângulos de volumes?
 
marcusmota:

Japa, fiz essa marca d'água exatamente como o Samuel comentou. Coloquei aí o código abaixo. Quanto ao indicador do book no gráfico, usando ele ao longo do dia a dia eu modifiquei um pouco a ideia dele. Agora crio linhas horizontais somente nos preços que possuem uma quantidade maior ou igual a de interesse (tipo um filtro). E nos preços onde os lotes são muitos altos (filtro superior) há um label mostrando o número. São as necessidades que vamos vendo ao longo do dia a dia e adaptando, né. Se tiver interesse só dizer aí.


Olá fera!

No fim consegui fazer e compartilhei com o pessoal semana aqui:

Fiz 95% igual ao seu. 
Porém ao usar tempos gráficos de dia/semanal/etc ele estava retornado o período em número mesmo usando o switch. 

Darei uma revisada 100% comparando com o seu. 
Posso colocar seu nome nos créditos do indicador? Pois você foi minha inspiração. 

Em relação ao book visual, poderia compartilhar o compilado final? E se me pertimitir, testar e fazer sugestões. 


Abs! 
 
[REMOVIDO PELO MODERADOR]
Razão: