[РЕШЕНО] Прошу помощи в написании индикатора

 

Здравствуйте все!

Пишу первый свой индикатор, но не могу толку дать :(

Смысл индикатора: сравнивать последнюю закрытую свечу с предыдущими (в количестве не более, чем задано в настройках) по open и close

и выводить количество предыдущих свечей, которые перекрываются ценой открытия или закрытия последней свечи.

То есть, число гистограммы будет показывать, что вот эта свеча вышла из диапазона предыдущих n штук.

Вот, например, закрытие свечей больше, чем закрытия и открытия предыдущих 20 свечей, 

или закрытие меньше, чем закрытие и открытие предыдущих 7 свечей.

Сейчас гистограмма показывает равные значения для всех свечей :(

Вот, что я начудил (осторожно! дикий треш которого я не понимаю ;) :

// Описание, которое видно на первой вкладке окна свойств индикатора
#property description "Фильтр флета"
#property description "хер его знает как он работает"

#property indicator_separate_window // в отдельном окне
#property indicator_buffers 1
#property indicator_plots   1

// Рисуем гистограмму
#property indicator_type1   DRAW_HISTOGRAM
#property indicator_color1  clrDarkSlateGray
#property indicator_style1  STYLE_SOLID
#property indicator_label1  "Flat_Filter"
#property indicator_width1  1

// Входящие переменные
input int      Bars_Count=20; // Бары для расчёта флета

// Буфер индикатора
double         FlatBuffer[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,FlatBuffer,INDICATOR_DATA);
   PlotIndexSetInteger(0,PLOT_LINE_STYLE,STYLE_SOLID); 
   PlotIndexSetInteger(0,PLOT_LINE_WIDTH,3);
   ArraySetAsSeries(FlatBuffer,true);
//---
   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[])
{
//---
ArraySetAsSeries(open,true);
ArraySetAsSeries(close,true);

int i;
for(i=rates_total-1;i>=0;i--)
{
double Open=open[i], Close=close[i];

int BarCountF=1;
for(BarCountF=1; BarCountF<Bars_Count && !IsStopped(); BarCountF++)
   {
   int MiO=ArrayMinimum(open,i,BarCountF); // находим индекс с мин-open
   double MinO=open[MiO];             // запрашиваем цену из массива по индексу
   int MiC=ArrayMinimum(close,i,BarCountF); // находим индекс с мин-close
   double MinC=close[MiC];             // запрашиваем цену из массива по индексу
   double kMin;
   if(MinO<=MinC) // Если открытие свечи меньше закрытия
      {kMin=MinO;} // запоминаем цену открытия
      else         // в противном случае
      {kMin=MinC;} // запоминаем цену закрытия

   int MaO=ArrayMaximum(open,i,BarCountF); // находим индекс с макс-open
   double MaxO=open[MaO];             // запрашиваем цену из массива по индексу
   int MaC=ArrayMaximum(close,i,BarCountF); // находим индекс с макс-close
   double MaxC=close[MaC];             // запрашиваем цену из массива по индексу
   double kMax;
   if(MaxO>MaxC)
      {kMax=MaxO;}
      else
      {kMax=MaxC;}   
   
   if(Open<kMin || Open>kMax || Close<kMin || Close>kMax)
      {break;}
   }
   
    FlatBuffer[i]=BarCountF;
}

//--- return value of prev_calculated for next call
   return(rates_total);
}
 

Пройдись в отладчике, посмотри, как вычисляется значение BarCountF для каждого бара. (Именно это значение записывается в буффер индикатора)

Судя по всему - оно у тебя всегда одно и то же, похоже, максимальное - то есть, не происходит выхода по break из внутреннего цикла подсчета. Погляди - почему.


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

 

Так?:

//+------------------------------------------------------------------+
//|                                                  Flat Filter.mq5 |
// Описание, которое видно на первой вкладке окна свойств индикатора
#property description "Фильтр флета"
#property description "хер его знает как он работает"

#property indicator_separate_window // в отдельном окне
#property indicator_buffers 1
#property indicator_plots   1

// Рисуем гистограмму
#property indicator_type1   DRAW_HISTOGRAM
#property indicator_color1  clrDarkSlateGray
#property indicator_style1  STYLE_SOLID
#property indicator_label1  "Flat_Filter"
#property indicator_width1  1

// Входящие переменные
input int      Bars_Count=20; // Бары для расчёта флета

                              // Буфер индикатора
double         FlatBuffer[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,FlatBuffer,INDICATOR_DATA);
   PlotIndexSetInteger(0,PLOT_LINE_STYLE,STYLE_SOLID);
   PlotIndexSetInteger(0,PLOT_LINE_WIDTH,3);
   ArraySetAsSeries(FlatBuffer,true);
//---
   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[])
  {
//---
   ArraySetAsSeries(open,true);
   ArraySetAsSeries(close,true);

   int i;
   int limit=MathMin(rates_total-prev_calculated,rates_total-Bars_Count);
   for(i=limit;i>=0;i--)
     {
      double Open=open[i],Close=close[i];
      int BarCountF=1;
      FlatBuffer[i]=BarCountF;
      
      for(BarCountF=Bars_Count-1; BarCountF>0 && !IsStopped(); BarCountF--)
        {
         int MiO=ArrayMinimum(open,i+1,BarCountF); // находим индекс с мин-open
         double MinO=open[MiO];             // запрашиваем цену из массива по индексу
         int MiC=ArrayMinimum(close,i+1,BarCountF); // находим индекс с мин-close
         double MinC=close[MiC];             // запрашиваем цену из массива по индексу
         double kMin=MathMin(MinO,MinC);

         int MaO=ArrayMaximum(open,i+1,BarCountF); // находим индекс с макс-open
         double MaxO=open[MaO];             // запрашиваем цену из массива по индексу
         int MaC=ArrayMaximum(close,i+1,BarCountF); // находим индекс с макс-close
         double MaxC=close[MaC];             // запрашиваем цену из массива по индексу
         double kMax=MathMax(MaxC,MaxO);
         
         if(Open<kMin || Open>kMax || Close<kMin || Close>kMax)
           {
            FlatBuffer[i]=BarCountF;
            break;
           }
        }
     }

//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+


 
Sergey Chalyshev:

Так?:



О-о-о! Сергей, дорогой Вы мой человек!

Огромное спасибо! :) То, что надо!

Пойду-ка я вчитаюсь в Ваш правильный код и помедитирую над своими ошибками ;)

 
George Merts:

И... если это твой первый индикатор - то он неоправданно сложен. ... С другой стороны - с этим индикатором ты получишь больше опыта


:) А простые неинтересно - их и без меня много ;)

 

А если вот этот блок

if(Open<kMin || Open>kMax || Close<kMin || Close>kMax)
           {
            FlatBuffer[i]=BarCountF;
            break;
           }

поменять на

if(Open<kMin || Close<kMin){FlatBuffer[i]=(-1)*BarCountF;break;}
if(Open>kMax || Close>kMax){FlatBuffer[i]=BarCountF;break;}

то гистограмма будет показывать в какую сторону произошёл пробой - вверх или вниз :)