Как корректно отрисовать свечу с помощью гистограмм?

 

Салют!

Строю индикатор, который должен отображать дополнительные котировки на текущем графике. Есть 4 буфера для отрисовки дополнительных свеч (все свечи одним цветом):

- для хая (толщина 1);

- для тела (толщина 2);

- для лоу (толщина 1);

- фоновый (по цвету фона графика, толщина 2);

Строю через код:

void draw(){
  for (int i=0; i<BarsInChart; i++){
    Comment ("i+StartDrawing is: ", StartDrawing, " Bars in chart: ", BarsInChart);
      if (Open[i]<=Close[i]){
         HighBuffer[i+StartDrawing]=High[i];
         BodyBuffer[i+StartDrawing]=Close[i];
         LowBuffer[i+StartDrawing]=Open[i];
         BackgroundBuffer[i+StartDrawing]=Low[i];
      }else  if(Open[i]>Close[i]){
         HighBuffer[i+StartDrawing]=High[i];
         BodyBuffer[i+StartDrawing]=Open[i];
         LowBuffer[i+StartDrawing]=Close[i];
         BackgroundBuffer[i+StartDrawing]=Low[i];
      }
   }
 
}


Но строит как-то не корректно (не все отрисовывает):



Общую структуру цены , конечно, передает. Но это не то пальто - нужно чтобы отображалось полноценно. Но "тело" что-то не хочет строить. Да и другие элементы , скорее всего, не все...

Пробовал строить по алгоритму, описанному в чудесном монологеForex Trader - не получилось, отображение дополнительных котировок еще хуже стает. Пробовал менять толщину буферов на хай, лоу и тела. На хай и на лоу работает, меняют толщину. А тело как не строилось, так и не строится...

Собственно, как я понимаю, на скрине только хай и лоу буферы отображаются (а может быть и они не все). Подскажите, как это решить можно?

 
для МТ5 использовать DRAW_CANDLES или DRAW_COLOR_CANDLES
 
Taras Slobodyanik:
для МТ5 использовать DRAW_CANDLES или DRAW_COLOR_CANDLES
мне для мт4 нужно :)
 
Yevhenii Levchenko:
мне для мт4 нужно :)

Толщину для буферов, отображающих тело свечи, сделайте больше, чем толщина буферов, отображающих тени. Вроде Вы так и пишете, но непонятно, что там за фоновый буфер? Нужно всего 4 буфера: 2 - соединяют между собой High и Low, еще 2 - соединяют между собой Open и Close.

Второй вариант (более функциональный и быстрый, но чуть сложнее) - рисовать на холсте.

 
Ihor Herasko:

Толщину для буферов, отображающих тело свечи, сделайте больше, чем толщина буферов, отображающих тени. 

Второй вариант (более функциональный и быстрый, но чуть сложнее) - рисовать на холсте.

Так и сделал - толщина для тела больше, чем для теней. Делал и супер толстым тело и другим цветом - отображало какие-то небольшие кусочки. Но не полноценно.

Canvas может и не вкурю сходу... Думал проще через гистрограмму :)

Сам алгоритм постройки, в примере выше, верный?
 
Yevhenii Levchenko:
мне для мт4 нужно :)

тогда смотрите код Heiken Ashi, там всё уже готово.

 
Попробовал запустить с OnInit() метод с указанным выше кодом... Инициализация неудачна, пишет:

2019.08.14 18:49:19.570 Candles EURUSD,H1: array out of range in 'Candles.mq4' (137,20)

Это в этой строке(перед "[" ):

HighBuffer[i+StartDrawing]=High[i];

Хотя значение i=0 так же StartDrawing=0;

При этом сам индикатор не выкидывает. Если открыть окно настроек индикатора и нажать "ОК", то индикатор рисует криво как на скрине. Скорее всего он в определенные буфферы не может войти? Может ли такое быть? Если да, в чем может быть причина?

 
Yevhenii Levchenko:
Попробовал запустить с OnInit() метод с указанным выше кодом... Инициализация неудачна, пишет:

Это в этой строке(перед "[" ):

Хотя значение i=0 так же StartDrawing=0;

При этом сам индикатор не выкидывает. Если открыть окно настроек индикатора и нажать "ОК", то индикатор рисует криво как на скрине. Скорее всего он в определенные буфферы не может войти? Может ли такое быть? Если да, в чем может быть причина?

Покажите весь код.

 
Ihor Herasko:

Покажите весь код.

//+------------------------------------------------------------------+
//|                                                       Candle.mq4 |
//|                                               Yevhenii Levchenko |
//|                          https://www.mql5.com/ru/users/levchenko |
//+------------------------------------------------------------------+
#property copyright "Yevhenii Levchenko"
#property link      "https://www.mql5.com/ru/users/levchenko"
#property version   "1.00"
#property strict
#property indicator_chart_window
#property indicator_buffers 4
#property indicator_plots   4
//--- plot HighBuffer
#property indicator_label1  "HighBuffer"
#property indicator_type1   DRAW_HISTOGRAM
#property indicator_color1  clrDarkSlateGray
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
//--- plot BodyBuffer
#property indicator_label2  "BodyBuffer"
#property indicator_type2   DRAW_HISTOGRAM
#property indicator_color2  clrDarkSlateGray
#property indicator_style2  STYLE_SOLID
#property indicator_width2  2
//--- plot LowBuffer
#property indicator_label3  "LowBuffer"
#property indicator_type3   DRAW_HISTOGRAM
#property indicator_color3  clrDarkSlateGray
#property indicator_style3  STYLE_SOLID
#property indicator_width3  1
//--- plot BackgroundBuffer
#property indicator_label4  "BackgroundBuffer"
#property indicator_type4   DRAW_HISTOGRAM
#property indicator_color4  clrWhite
#property indicator_style4  STYLE_SOLID
#property indicator_width4  2
//--- input parameters

input color    CandleColor=clrDarkSlateGray;
input color    BackgroundColor=clrWhite;
input bool     Inverse=false;
//--- indicator buffers
double         HighBuffer[];
double         BodyBuffer[];
double         LowBuffer[];
double         BackgroundBuffer[];

int BarsInChart=0;
int FirstVisibleBar=0;
int StartDrawing=0;
int controller=0;

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,HighBuffer);
   SetIndexBuffer(1,BodyBuffer);
   SetIndexBuffer(2,LowBuffer);
   SetIndexBuffer(3,BackgroundBuffer);
   
//---
   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[])
  {

   return(rates_total);
  }
//+------------------------------------------------------------------+
//| ChartEvent function                                              |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
  {
      if (id==CHARTEVENT_CHART_CHANGE){
        int scale=(int) ChartGetInteger(0,CHART_SCALE,0);
        // Comment("Scale is: ", scale);
      
        
         BarsInChart = WindowBarsPerChart();
         FirstVisibleBar = WindowFirstVisibleBar();
         StartDrawing = FirstVisibleBar-BarsInChart+1;
         
         if (StartDrawing<0){ 
         BarsInChart+=StartDrawing;
         StartDrawing=0;
         }
         
         for (int i=0; i<BarsInChart; i++){
           Comment ("i+StartDrawing is: ", StartDrawing+i, " Bars in chart: ", BarsInChart);
           ResetLastError();
            if (Open[i]<=Close[i]){
               HighBuffer[i+StartDrawing]=High[i];
               BodyBuffer[i+StartDrawing]=Close[i];
               LowBuffer[i+StartDrawing]=Open[i];
               BackgroundBuffer[i+StartDrawing]=Low[i];
            }else  if(Open[i]>Close[i]){
               HighBuffer[i+StartDrawing]=High[i];
               BodyBuffer[i+StartDrawing]=Open[i];
               LowBuffer[i+StartDrawing]=Close[i];
               BackgroundBuffer[i+StartDrawing]=Low[i];
            }else{}
           
         }
         
      }
   
  }
//+------------------------------------------------------------------+

 
Видимо, OnChartEvent прилетает раньше, чем OnInit.
 
Ihor Herasko:

 Вроде Вы так и пишете, но непонятно, что там за фоновый буфер? Нужно всего 4 буфера: 2 - соединяют между собой High и Low, еще 2 - соединяют между собой Open и Close.

Только сейчас увидел дополнение...

Фоновый буфер нужен чтобы закрасить низ гистограммы. Как я понимаю каждый буфер строит гистограмму от самого основания до указанного значение буфера. То есть получается, что свеча , по идее, строится слоями. Сначала хай, потом тело, потом лоу. Фоновый закрашивает все, что ниже свечи. По идее. Но оно почему-то совсем не хочет строить эти чертовы гистограммы. Даже одну... Так что не могу точно сказать, выполняет ли свою роль фоновый буфер...