Как сделать несколько гистограмм на один бар?

Авторизуйтесь или зарегистрируйтесь, чтобы добавить комментарий
Sergey Savinkin
2099
Sergey Savinkin  

Подскажите, как можно на 1 баре разместить несколько гистограмм для разных буферов рядом друг с другом или накопительно? Примеры на рисунке.


Andrei Fandeev
35935
Andrei Fandeev  
Sergey Savinkin:

Ну верхний вариант понятно как - делаем дополнительные 2 буфера.
Сначала выводим буфер сумм трёх первичных буферов, потом буфер двух первичных, потом один из первичных.

Второй вариант не знаю вообще ли возможен (я про 4ку). В МТ5 возможно есть какие-то танцы с бубнами

Всяко линии в таких случаях нагляднее гисты будут

Sergey Savinkin
2099
Sergey Savinkin  
Andrei Fandeev:

Ну верхний вариант понятно как - делаем дополнительные 2 буфера.
Сначала выводим буфер сумм трёх первичных буферов, потом буфер двух первичных, потом один из первичных.

Второй вариант не знаю вообще ли возможен (я про 4ку). В МТ5 возможно есть какие-то танцы с бубнами

Всяко линии в таких случаях нагляднее гисты будут

Спасибо, я про МТ5. Про разные буферы в одном индикаторном окне я не подумал. Это вариант. Попробую.

Artyom Trishkin
Модератор
52406
Artyom Trishkin  
Sergey Savinkin:

Спасибо, я про МТ5. Про разные буферы в одном индикаторном окне я не подумал. Это вариант. Попробую.

Самый длинный столбец должен иметь наименьший индекс буфера, самый короткий - наибольший индекс. В общем - бутерброд...

Sergey Savinkin
2099
Sergey Savinkin  
Artyom Trishkin:

Самый длинный столбец должен иметь наименьший индекс буфера, самый короткий - наибольший индекс. В общем - бутерброд...

Спасибо, так и сделаю.

Nikolai Semko
6531
Nikolai Semko  

Вариант через канвас в первом приближении (реализовано только для макс. увеличения)

Даже собственные буферы для гистограмы по сути не нужны

#property indicator_chart_window
#include <Canvas\iCanvas.mqh> // https://www.mql5.com/ru/code/22164

#property indicator_buffers 3
#property indicator_plots   3
//--- plot Ma1
#property indicator_label1  "Ma1"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrRed
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
//--- plot Ma2
#property indicator_label2  "Ma2"
#property indicator_type2   DRAW_LINE
#property indicator_color2  clrBlue
#property indicator_style2  STYLE_SOLID
#property indicator_width2  1
//--- plot Ma3
#property indicator_label3  "Ma3"
#property indicator_type3   DRAW_LINE
#property indicator_color3  clrGreen
#property indicator_style3  STYLE_SOLID
#property indicator_width3  1
//--- indicator buffers
double         Ma1Buffer[];
double         Ma2Buffer[];
double         Ma3Buffer[];

int MaHandle1,MaHandle2,MaHandle3,RT=0;
////////////////////////////////////////////////////////////////////////////////
int OnInit()
  {
//--- indicator buffers mapping
   ChartSetInteger(0,CHART_SCALE,0,5);
   SetIndexBuffer(0,Ma1Buffer,INDICATOR_DATA);
   SetIndexBuffer(1,Ma2Buffer,INDICATOR_DATA);
   SetIndexBuffer(2,Ma3Buffer,INDICATOR_DATA);
   MaHandle1=iMA(NULL,0,10,0,MODE_SMA,PRICE_CLOSE);
   MaHandle2=iMA(NULL,0,20,0,MODE_SMA,PRICE_CLOSE);
   MaHandle3=iMA(NULL,0,30,0,MODE_SMA,PRICE_CLOSE);
   ChartSetInteger(0,CHART_CROSSHAIR_TOOL,0,true);

   return(INIT_SUCCEEDED);
  }
void OnDeinit(const int reason) {if (reason<2) ChartRedraw(); }
////////////////////////////////////////////////////////////////////////////////
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 to_copy;
   if(prev_calculated>rates_total || prev_calculated<=0) to_copy=rates_total;
   else
     {
      to_copy=rates_total-prev_calculated;
      to_copy++;
     }
   if(CopyBuffer(MaHandle1,0,0,to_copy,Ma1Buffer)<=0) Print("Error CopyBuffer1 - ",GetLastError());
   if(CopyBuffer(MaHandle2,0,0,to_copy,Ma2Buffer)<=0) Print("Error CopyBuffer2 - ",GetLastError());
   if(CopyBuffer(MaHandle3,0,0,to_copy,Ma3Buffer)<=0) Print("Error CopyBuffer3 - ",GetLastError());
   if(rates_total==prev_calculated && W.Right_bar<1)
     {
      Canvas.FillRectangle((int)Canvas.X(0.0)-11,W.Height-1,(int)Canvas.X(0.0)+11, 0,0);
      Canvas.FillRectangle((int)Canvas.X(0.0)-11,W.Height-1,(int)Canvas.X(0.0)-5, W.Height-Round(fabs(close[RT-1]-Ma1Buffer[RT-1])/W.dy_pix),0xA0FF0000);
      Canvas.FillRectangle((int)Canvas.X(0.0)- 3,W.Height-1,(int)Canvas.X(0.0)+3, W.Height-Round(fabs(close[RT-1]-Ma2Buffer[RT-1])/W.dy_pix),0xA00000FF);
      Canvas.FillRectangle((int)Canvas.X(0.0)+ 5,W.Height-1,(int)Canvas.X(0.0)+11,W.Height-Round(fabs(close[RT-1]-Ma3Buffer[RT-1])/W.dy_pix),0xA000FF00);
      Canvas.Update();
     }
   RT=rates_total;
   return(rates_total);
  }
////////////////////////////////////////////////////////////////////////////////
void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
  {
   if(id==CHARTEVENT_CHART_CHANGE)
     {
      Canvas.Erase(0);
      for(int i=W.Left_bar;i>=W.Right_bar; i--)
        {
         double curPrice=iClose(NULL,0,i);
         Canvas.FillRectangle((int)Canvas.X((double)i)-11,W.Height-1,(int)Canvas.X((double)i)-5, W.Height-Round(fabs(curPrice-Ma1Buffer[RT-1-i])/W.dy_pix),0xA0FF0000);
         Canvas.FillRectangle((int)Canvas.X((double)i)- 3,W.Height-1,(int)Canvas.X((double)i)+3, W.Height-Round(fabs(curPrice-Ma2Buffer[RT-1-i])/W.dy_pix),0xA00000FF);
         Canvas.FillRectangle((int)Canvas.X((double)i)+ 5,W.Height-1,(int)Canvas.X((double)i)+11,W.Height-Round(fabs(curPrice-Ma3Buffer[RT-1-i])/W.dy_pix),0xA000FF00);
        }
      Canvas.Update();
     }
  }

желтым маркером выделено то, что непосредственно относится к рисованию трехцветной гистограммы

Artyom Trishkin
Модератор
52406
Artyom Trishkin  
Nikolai Semko:

Вариант через канвас в первом приближении (реализовано только для макс. увеличения)

Даже собственные буферы для гистограмы по сути не нужны

желтым маркером выделено то, что непосредственно относится к рисованию трехцветной гистограммы

А без рисуемых МА? И чтобы в окне данных были значения каждого столбца гистограммы, а не просто трёх скользящих?

Nikolai Semko
6531
Nikolai Semko  
Artyom Trishkin:

А без рисуемых МА? И чтобы в окне данных были значения каждого столбца гистограммы, а не просто трёх скользящих?

Так я машки взял просто с потолка для примера, как основа для расчета. Я же не знаю какие значения нужны в гистограммы выводить. 
Если машки не рисовать, то будет еще проще и короче.

Alexey Viktorov
25773
Alexey Viktorov  
Artyom Trishkin:

А без рисуемых МА? И чтобы в окне данных были значения каждого столбца гистограммы, а не просто трёх скользящих?

Nikolai Semko:

Так я машки взял просто с потолка для примера. Я же не знаю какие значения нужны в гистограммы выводить. 
Если машки не рисовать, то будет еще проще и короче.

Не проще, не короче не будет. Чтобы в окне данных были значения нужны индикаторные буферы. И не важно чем и как их заполнять. ИМХО.

Nikolai Semko
6531
Nikolai Semko  
Alexey Viktorov:

Не проще, не короче не будет. Чтобы в окне данных были значения нужны индикаторные буферы. И не важно чем и как их заполнять. ИМХО.

Заполнять буферы можете чем угодно. Здесь речь об отображении. 
Канвас нужен для реализации того, что физически не возможно стандартными индикаторными примочками реализовать.

Nikolai Semko
6531
Nikolai Semko  
Artyom Trishkin:

А без рисуемых МА? И чтобы в окне данных были значения каждого столбца гистограммы, а не просто трёх скользящих?

Вы это имели ввиду?

#property indicator_chart_window
#include <Canvas\iCanvas.mqh> // https://www.mql5.com/ru/code/22164

#property indicator_buffers 3

//--- indicator buffers
double         Ma1Buffer[];
double         Ma2Buffer[];
double         Ma3Buffer[];

int MaHandle1,MaHandle2,MaHandle3,RT=0;
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   ChartSetInteger(0,CHART_SCALE,0,5);
   SetIndexBuffer(0,Ma1Buffer,INDICATOR_CALCULATIONS);
   SetIndexBuffer(1,Ma2Buffer,INDICATOR_CALCULATIONS);
   SetIndexBuffer(2,Ma3Buffer,INDICATOR_CALCULATIONS);
   MaHandle1=iMA(NULL,0,10,0,MODE_SMA,PRICE_CLOSE);
   MaHandle2=iMA(NULL,0,20,0,MODE_SMA,PRICE_CLOSE);
   MaHandle3=iMA(NULL,0,30,0,MODE_SMA,PRICE_CLOSE);
   ChartSetInteger(0,CHART_CROSSHAIR_TOOL,0,true);
//  GetWindowProperties(W);

//---
   return(INIT_SUCCEEDED);
  }
void OnDeinit(const int reason) {if (reason<2) ChartRedraw(); }
//+------------------------------------------------------------------+
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 to_copy;
   if(prev_calculated>rates_total || prev_calculated<=0) to_copy=rates_total;
   else
     {
      to_copy=rates_total-prev_calculated;
      to_copy++;
     }
   if(CopyBuffer(MaHandle1,0,0,to_copy,Ma1Buffer)<=0) Print("Error CopyBuffer1 - ",GetLastError());
   if(CopyBuffer(MaHandle2,0,0,to_copy,Ma2Buffer)<=0) Print("Error CopyBuffer2 - ",GetLastError());
   if(CopyBuffer(MaHandle3,0,0,to_copy,Ma3Buffer)<=0) Print("Error CopyBuffer3 - ",GetLastError());
   if(rates_total==prev_calculated && W.Right_bar<1)
     {
      Canvas.FillRectangle((int)Canvas.X(0.0)-11,W.Height-1,(int)Canvas.X(0.0)+11, 0,0);
      Canvas.FillRectangle((int)Canvas.X(0.0)-11,W.Height-1,(int)Canvas.X(0.0)-5, W.Height-Round(fabs(Ma1Buffer[RT-1]-W.Y_min)/(5*W.dy_pix)),0xA0FF0000);
      Canvas.FillRectangle((int)Canvas.X(0.0)- 3,W.Height-1,(int)Canvas.X(0.0)+3, W.Height-Round(fabs(Ma2Buffer[RT-1]-W.Y_min)/(5*W.dy_pix)),0xA00000FF);
      Canvas.FillRectangle((int)Canvas.X(0.0)+ 5,W.Height-1,(int)Canvas.X(0.0)+11,W.Height-Round(fabs(Ma3Buffer[RT-1]-W.Y_min)/(5*W.dy_pix)),0xA000FF00);
      Canvas.Update();
     }
   RT=rates_total;
   return(rates_total);
  }
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
  {
   if(id==CHARTEVENT_CHART_CHANGE)
     {
      Canvas.Erase(0);
      for(int i=W.Left_bar;i>=W.Right_bar; i--)
        {
         Canvas.FillRectangle((int)Canvas.X((double)i)-11,W.Height-1,(int)Canvas.X((double)i)-5, W.Height-Round(fabs(Ma1Buffer[RT-1-i]-W.Y_min)/(5*W.dy_pix)),0xA0FF0000);
         Canvas.FillRectangle((int)Canvas.X((double)i)- 3,W.Height-1,(int)Canvas.X((double)i)+3, W.Height-Round(fabs(Ma2Buffer[RT-1-i]-W.Y_min)/(5*W.dy_pix)),0xA00000FF);
         Canvas.FillRectangle((int)Canvas.X((double)i)+ 5,W.Height-1,(int)Canvas.X((double)i)+11,W.Height-Round(fabs(Ma3Buffer[RT-1-i]-W.Y_min)/(5*W.dy_pix)),0xA000FF00);
        }
      Canvas.Update();
     }
  }
//+------------------------------------------------------------------+
12
Авторизуйтесь или зарегистрируйтесь, чтобы добавить комментарий