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

 
SeriousRacoon:
Видимо, OnChartEvent прилетает раньше, чем OnInit.
Не, раньше код был отдельно в методе draw(). То же самое было (его первоначально вызывал OnInit() )... Его я планировал запускать при инициализации, а потом при изменении графика. Позже убрал методы и все кинул в ChartEvent
 
Yevhenii Levchenko:

Тут у Вас все смешалось: кони, люди )) Гистограмма отображается по соседним буферам. Поэтому High и Low должны быть рядом. Аналогично буфера Open и Close. 

На самом деле все очень просто:

//+------------------------------------------------------------------+
//|                                                       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  clrBlack
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
//--- plot LowBuffer
#property indicator_label2  "LowBuffer"
#property indicator_type2   DRAW_HISTOGRAM
#property indicator_color2  clrBlack
#property indicator_style2  STYLE_SOLID
#property indicator_width2  1
//--- plot OpenBuffer
#property indicator_label3  "OpenBuffer"
#property indicator_type3   DRAW_HISTOGRAM
#property indicator_color3  clrGreen
#property indicator_style3  STYLE_SOLID
#property indicator_width3  5
//--- plot CloseBuffer
#property indicator_label4  "CloseBuffer"
#property indicator_type4   DRAW_HISTOGRAM
#property indicator_color4  clrRed
#property indicator_style4  STYLE_SOLID
#property indicator_width4  5
//--- input parameters

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

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,LowBuffer);
   SetIndexBuffer(2,OpenBuffer);
   SetIndexBuffer(3,CloseBuffer);

//---
   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[])
{
   int nLimit = rates_total - prev_calculated; 
   if (prev_calculated > 0)
      nLimit++;

   for(int i = 0; i < nLimit; i++)
   {
      HighBuffer[i+StartDrawing]=High[i];
      LowBuffer[i+StartDrawing]=Low[i];
      OpenBuffer[i+StartDrawing] = Open[i];
      CloseBuffer[i+StartDrawing] = Close[i];
   }
   
   return(rates_total);
}
//+------------------------------------------------------------------+

Получаем:


 
Ihor Herasko:

Тут у Вас все смешалось: кони, люди )) Гистограмма отображается по соседним буферам. Поэтому High и Low должны быть рядом. Аналогично буфера Open и Close. 

На самом деле все очень просто:

Получаем:

Блин, круто! Спасибо огромное, Игорь!

Оно даже с ChartEvent работает корректно
 
Out of range выкидывало снова... По какой причине непонятно. Добавил просто булевскую переменную, чтобы пропустить первый цикл и все стало работать тип-топ:
        bool limit=false;

        if (limit){
            for (int i=0; i<BarsInChart; i++){
              Comment ("i+StartDrawing is: ", StartDrawing+i, " Bars in chart: ", BarsInChart);
                HighBuffer[i+StartDrawing]=High[i];
                LowBuffer[i+StartDrawing]=Low[i];
                OpenBuffer[i+StartDrawing] = Open[i];
                CloseBuffer[i+StartDrawing] = Close[i];
              
            }
         }
         limit=true;
 
Yevhenii Levchenko:
По какой причине непонятно. 
 for (int i=0; i<BarsInChart - StartDrawing; i++)
 
Ihor Herasko:

Не, это не подходит... Выкидывает оут оф рейндж. Нужно пропускать цикл первый. Хрен его знает зачем, но это решает проблему. Все остальное, что пробовал, не робит . Хотя должны быть и другие варианты

 
Yevhenii Levchenko:
мне для мт4 нужно :)

еле нашел, вот инструкция чтобы понять логику как работает DRAW_HISTOGRAM

https://www.mql5.com/ru/forum/111497/page651#comment_3073303

 
Igor Makanu:

еле нашел, вот инструкция чтобы понять логику как работает DRAW_HISTOGRAM

https://www.mql5.com/ru/forum/111497/page651#comment_3073303

Спасибо! :)
 
Yevhenii Levchenko:
Out of range выкидывало снова... По какой причине непонятно. Добавил просто булевскую переменную, чтобы пропустить первый цикл и все стало работать тип-топ:

Чего-то зачем-то навычисляли с индексами. Попробуйте так (сам не пробовал, каюсь):

for (int i = FirstVisibleBar; i >= fmax(0, FirstVisibleBar - BarsInChart); i--)
{
        if (Open[i] <= Close[i])
        {
                HighBuffer[i]       = High[i];
                BodyBuffer[i]       = Close[i];
                LowBuffer[i]        = Open[i];
                BackgroundBuffer[i] = Low[i];
        }
        else
        if (Open[i] > Close[i])
        {
                HighBuffer[i]       = High[i];
                BodyBuffer[i]       = Open[i];
                LowBuffer[i]        = Close[i];
                BackgroundBuffer[i] = Low[i];
        }
}
 
SeriousRacoon:

Чего-то зачем-то навычисляли с индексами. Попробуйте так (сам не пробовал, каюсь):

Та уже есть готовое решение, Ihor Herasko уже показал как нужно. А Igor Makanu показал принципы построения. Но все равно спасибо :)