Вопросы начинающего - Индикатор Fractals

 

Приветствую уважаемые члены сообщества! )

  Совсем недавно начал изучать программирование на MQL5. Чтобы хоть немного подготовиться к решению вопросов и задач, прочитал для начала справку от корки до корки. Так же прочитал практически все статьи по MQL5. Кстати, лучшие статьи на мой взгляд, как раз таки для начинающих, где действительно всё подробно и понятно написано, опубликовал Samuel. Вот кому учебник бы взяться писать. Но это моё субъективное мнение. Многое конечно после статей прояснилось, но изучение чего-либо это, как лабиринт - выходы есть, но тупики в процессе поиска этих выходов неизбежны. Прежде, чем приступить к созданию чего-либо, решил для начала поковырять и изменить вид уже существующих индикаторов, для практики. Взял самый наипростейший индикатор - Fractals.  И попробовал с ним сделать наипростейшую модификацию. Всего то:

 1. Вместо 5 свечей в построении фрактала участвуют 3.

 2. Рисует не стрелки, а линии, чтобы получился вот такой вид:

В другом торговом терминале 

И вот мой первый тупик в этом лабиринте! ))) В МТ5 у меня выходит вот так:

В МТ5 

Подскажите, пожалуйста, что я делаю не так и, если не сложно, прокомментируйте буквально каждую строку кода, я так лучше усваиваю предмет.

На данный момент код такой:

//+------------------------------------------------------------------+
//|                                                      fract 3.mq5 |
//|                        Copyright 2010, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2010, MetaQuotes Software Corp."
#property link      "http://www.mql5.com"
#property version   "1.00"
#property indicator_chart_window
#property indicator_buffers 2
#property indicator_plots   2
//--- plot fr_up
#property indicator_label1  "fr_up"
#property indicator_type1   DRAW_LINE
#property indicator_color1  RoyalBlue
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
//--- plot fr_dw
#property indicator_label2  "fr_dw"
#property indicator_type2   DRAW_LINE
#property indicator_color2  OrangeRed
#property indicator_style2  STYLE_SOLID
#property indicator_width2  1
//--- indicator buffers
double         fr_upBuffer[];
double         fr_dwBuffer[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
void OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,fr_upBuffer,INDICATOR_DATA);
   SetIndexBuffer(1,fr_dwBuffer,INDICATOR_DATA);
//---
   PlotIndexSetInteger(0,PLOT_LINE_STYLE,STYLE_SOLID);
   PlotIndexSetInteger(1,PLOT_LINE_STYLE,STYLE_SOLID);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate (const int rates_total,      // размер входных таймсерий
                 const int prev_calculated,  // обработано баров на предыдущем вызове
                 const datetime& time[],     // Time
                 const double& open[],       // Open
                 const double& High[],       // High
                 const double& Low[],        // Low
                 const double& close[],      // Close
                 const long& tick_volume[],  // Tick Volume
                 const long& volume[],       // Real Volume
                 const int& spread[]         // Spread
   )

  {
   int i,limit;
//---
   if(rates_total < 3)
      return(0);
//---
   if(prev_calculated < 5)
     {
      limit=2; 
      //--- clean up arrays
      ArrayInitialize(fr_upBuffer,STYLE_SOLID);
      ArrayInitialize(fr_dwBuffer,STYLE_SOLID);
     }
   else limit = rates_total-3;

   for(i = limit;i < rates_total-3;i++)
     {
      //---- Верхний фрактал
      if(High[i] > High[i+1] && High[i] >= High[i-1])
         fr_upBuffer[i] = High[i];
      else fr_upBuffer[i] = STYLE_SOLID;

      //---- Нижний фрактал
      if(Low[i] < Low[i+1] && Low[i] <= Low[i-1])
         fr_dwBuffer[i] = Low[i];
      else fr_dwBuffer[i] = STYLE_SOLID;
     }

   return(rates_total);
  }

P.S. В справку не посылайте, она у меня всегда открыта.))) 

 

Нашёл, где допустил основную ошибку.)) 

 

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate (const int rates_total,      // размер входных таймсерий
                 const int prev_calculated,  // обработано баров на предыдущем вызове
                 const datetime& time[],     // Time
                 const double& open[],       // Open
                 const double& High[],       // High
                 const double& Low[],        // Low
                 const double& close[],      // Close
                 const long& tick_volume[],  // Tick Volume
                 const long& volume[],       // Real Volume
                 const int& spread[])        // Spread

  {
   int i,limit;
   
   if(rates_total < 5)
      return(0);

   if(prev_calculated < 7)
     {
      limit = 2;
      
      ArrayInitialize(fr_upBuffer,STYLE_SOLID);
      ArrayInitialize(fr_dwBuffer,STYLE_SOLID);
     }
   else limit=rates_total-5;
   
   for(i=limit;i<rates_total-3;i++)
      {
//---- Верхний фрактал
      if (High[i] > High[i+1] && High[i] >= High[i-1])
         fr_upBuffer[i] = High[i];
         
      else fr_upBuffer[i] = fr_upBuffer[i-1];

//---- Нижний фрактал
      if (Low[i] < Low[i+1] && Low[i] <= Low[i-1])
         fr_dwBuffer[i] = Low[i];
         
      else fr_dwBuffer[i] = fr_dwBuffer[i-1];
      }
   return(rates_total);
  }

 Получилась такая картинка:

Как то он только странно обрывается в конце. Как это можно исправить?

 И какую роль играет вот эта часть кода?

 

if(rates_total < 3)
      return(0);

   if(prev_calculated < 7)
     {
      limit = 2;
      //--- clean up arrays
      ArrayInitialize(fr_upBuffer,STYLE_SOLID);
      ArrayInitialize(fr_dwBuffer,STYLE_SOLID);
     }
   else limit = rates_total - 3;
 

Значения индикатора не пересчитывались на каждом баре и, чтобы это исправить, я добавил вот такую часть кода:

   int i;
   int limit;
   static datetime   Old_Time;           // статическая переменная
   datetime          New_Time[1];        // массив
   bool              IsNewBar = false;   // подтверждение нового бара

   int copied = CopyTime(_Symbol,_Period,0,1,New_Time);    // копируем время текущего бара в массив New_Time[0]

   if(copied > 0)               // если копирование прошло успешно и
     {
      if(Old_Time!=New_Time[0]) // если время предыдущего бара не равно времени текущего бара, то...
        {
         IsNewBar=true; 
         Old_Time=New_Time[0];
        }
     }
   else
     {
      Alert("Ошибка копирования времени, номер ошибки: ",GetLastError());
      ResetLastError();
      return(1);
     }

   if(IsNewBar == false)
     {
      return(1);
     }

Также я забыл об одном важном моменте - индексация массивов:

 

   ArraySetAsSeries(High,true);
   ArraySetAsSeries(Low,true);
   ArraySetAsSeries(fr_upBuffer,true);
   ArraySetAsSeries(fr_dwBuffer,true);

 Но теперь у меня вообще ничего не отображается на графике. Вот теперь я в конкретном тупике и метод тыка уже не помогает.))) Подскажите, пожалуйста, что я делаю не правильно. Файл с тем, что на данный момент сделал прилагаю:

 

Файлы:
 
tol64:

Значения индикатора не пересчитывались на каждом баре и, чтобы это исправить, я добавил вот такую часть кода:

Также я забыл об одном важном моменте - индексация массивов:

 

 Но теперь у меня вообще ничего не отображается на графике. Вот теперь я в конкретном тупике и метод тыка уже не помогает.))) Подскажите, пожалуйста, что я делаю не правильно. Файл с тем, что на данный момент сделал прилагаю:

 

небольшой совет, в индикаторах динамические массивы автоматически индексируются как тайм серии так что нет необходимости ее делать.

когда я писал подобный индикатор для мт4 у меня тоже проблемка была как у вас в конце линии уходили вниз, решил это таким способом. может поможет (код для мт4) , под мт5 еще его не пробовал переписывать

#property indicator_chart_window
#property indicator_buffers 2
#property indicator_color1 Blue
#property indicator_color2 Red

double UpperBuffer[];
double LowerBuffer[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
  {
   SetIndexStyle(0,DRAW_LINE);
   SetIndexStyle(1,DRAW_LINE);
   SetIndexBuffer(0,UpperBuffer);
   SetIndexBuffer(1,LowerBuffer);
   SetIndexDrawBegin(0,0);
   SetIndexDrawBegin(1,0);
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
  {
//----
   
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
  {
   //int    limit;
   int    counted_bars=IndicatorCounted();
   //---- last counted bar will be recounted
   //if(counted_bars>0) counted_bars--;
   //limit=counted_bars;
//----
   for(int i=0; i<counted_bars; i++)
     { 
      UpperBuffer[i] = Fractal(i,counted_bars,MODE_UPPER);
      LowerBuffer[i] = Fractal(i,counted_bars,MODE_LOWER);
     }

//----
   return(0);
  }
//+------------------------------------------------------------------+
double Fractal(int ind,int bar,int mode)
{
 
 for(int k=ind; k<=bar;k++)
 {
  double val=iFractals(NULL, 0, mode, k);
 
  if (val>0)
  {
   return(val);
  } 
 }
 
}


 

в мкл5 все массивы индексируются как массивы...

 
CoreWinTT:

в мкл5 все массивы индексируются как массивы...

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

#property indicator_chart_window
#property indicator_buffers 4
#property indicator_plots   3
#property indicator_type1   DRAW_LINE
#property indicator_type2   DRAW_LINE
#property indicator_type3   DRAW_LINE
#property indicator_color1  DodgerBlue
#property indicator_color2  DodgerBlue
#property indicator_color3  Blue
#property indicator_style3  STYLE_DOT
//--- input parameters
input int ADX_period=14; // Period
//---- buffers
double ExtHighBuffer[];
double ExtLowBuffer[];
double ExtMiddBuffer[];
double adxBuffer[];
//--- handles for ADX
int h_adx;
//--- bars minimum for calculation
#define DATA_LIMIT 60
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,ExtHighBuffer,INDICATOR_DATA);
   SetIndexBuffer(1,ExtLowBuffer,INDICATOR_DATA);
   SetIndexBuffer(2,ExtMiddBuffer,INDICATOR_DATA);
   SetIndexBuffer(3,adxBuffer,INDICATOR_CALCULATIONS);
//--- sets first bar from what index will be drawn
   PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,DATA_LIMIT);
   PlotIndexSetInteger(1,PLOT_DRAW_BEGIN,DATA_LIMIT);
   PlotIndexSetInteger(3,PLOT_DRAW_BEGIN,DATA_LIMIT);
//--- get handles
   h_adx=iADX(Symbol(),0,ADX_period);
//--- initialization done
   return(0);
  }
//+------------------------------------------------------------------+
//| 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[])
  {

   if(rates_total<DATA_LIMIT)
      return(0);

   int calculated=BarsCalculated(h_adx);
   if(calculated<rates_total)
     {
      return(0);
     }

   int to_copy;
   if(prev_calculated>rates_total || prev_calculated<0) to_copy=rates_total;
   else
     {
      to_copy=rates_total-prev_calculated;
      if(prev_calculated>0) to_copy++;
     }

   if(CopyBuffer(h_adx,0,0,to_copy,adxBuffer)<=0)
     {
      return(0);
     }

   int i,limit;
   if(prev_calculated<=DATA_LIMIT)
      limit=DATA_LIMIT;
   else limit=prev_calculated-1;

   for(i=limit;i<rates_total;i++)
     {
      int InpChannelPeriod=(int)floor(150/adxBuffer[i]);
      ExtHighBuffer[i]=Highest(high,InpChannelPeriod,i);
      ExtLowBuffer[i]=Lowest(low,InpChannelPeriod,i);
      ExtMiddBuffer[i]=(ExtHighBuffer[i]+ExtLowBuffer[i])/2.0;;
     }

   return(rates_total);
  }
//+------------------------------------------------------------------+
//| get highest value for range                                      |
//+------------------------------------------------------------------+
double Highest(const double &array[],int range,int fromIndex)
  {
   double res;
   int i;
//---
   res=array[fromIndex];
   for(i=fromIndex;i>fromIndex-range && i>=0;i--)
     {
      if(res<array[i]) res=array[i];
     }
//---
   return(res);
  }
//+------------------------------------------------------------------+
//| get lowest value for range                                       |
//+------------------------------------------------------------------+
double Lowest(const double &array[],int range,int fromIndex)
  {
   double res;
   int i;
//---
   res=array[fromIndex];
   for(i=fromIndex;i>fromIndex-range && i>=0;i--)
     {
      if(res>array[i]) res=array[i];
     }
//---
   return(res);
  }
//+------------------------------------------------------------------+
Документация по MQL5: Основы языка / Переменные
Документация по MQL5: Основы языка / Переменные
  • www.mql5.com
Основы языка / Переменные - Документация по MQL5
 
//+------------------------------------------------------------------+
//|                                                      fract 3.mq5 |
//|                        Copyright 2010, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2010, MetaQuotes Software Corp."
#property link      "http://www.mql5.com"
#property version   "1.00"
#property indicator_chart_window
#property indicator_buffers 2
#property indicator_plots   2
//--- plot fr_up
#property indicator_label1  "fr_up"
#property indicator_type1   DRAW_LINE
#property indicator_color1  RoyalBlue
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
//--- plot fr_dw
#property indicator_label2  "fr_dw"
#property indicator_type2   DRAW_LINE
#property indicator_color2  OrangeRed
#property indicator_style2  STYLE_SOLID
#property indicator_width2  1
//--- indicator buffers
double         fr_upBuffer[];
double         fr_dwBuffer[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
void OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,fr_upBuffer,INDICATOR_DATA);
   SetIndexBuffer(1,fr_dwBuffer,INDICATOR_DATA);
//---
   PlotIndexSetInteger(0,PLOT_LINE_STYLE,STYLE_SOLID);
   PlotIndexSetInteger(1,PLOT_LINE_STYLE,STYLE_SOLID);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate (const int rates_total,      // размер входных таймсерий
                 const int prev_calculated,  // обработано баров на предыдущем вызове
                 const datetime& time[],     // Time
                 const double& open[],       // Open
                 const double& High[],       // High
                 const double& Low[],        // Low
                 const double& close[],      // Close
                 const long& tick_volume[],  // Tick Volume
                 const long& volume[],       // Real Volume
                 const int& spread[])        // Spread

  {
  
   int i;
   int limit;
   datetime   Old_Time;           // статическая переменная
   datetime          New_Time[1];        // массив
   bool              IsNewBar = false;   // подтверждение нового бара

   
   int copied = CopyTime(_Symbol,_Period,0,1,New_Time);    // копируем время текущего бара в массив New_Time[0]

   if(copied > 0)               // если копирование прошло успешно и
     {
      if(Old_Time!=New_Time[0]) // если время предыдущего бара не равно времени текущего бара, то
        {
         IsNewBar=true;
         Old_Time=New_Time[0];
        }
     }
   else
     {
      Alert("Ошибка копирования времени, номер ошибки: ",GetLastError());
      ResetLastError();
      return(1);
     }

   if(IsNewBar == false) // советник должен проверять условия для совершения торговой операции только при новом баре
     {
      return(1);
     }
   
   if(rates_total < 3)
      return(0);

   if(prev_calculated < 3)
     {
      limit = 3;

      ArrayInitialize(fr_upBuffer,STYLE_SOLID);
      ArrayInitialize(fr_dwBuffer,STYLE_SOLID);
     }
   else limit = rates_total;
  
   for(i=limit;i<rates_total;i++)
      {
//---- Верхний фрактал
      if (High[i-2] > High[i-3] && High[i-2] > High[i+++1])
         fr_upBuffer[i] = High[i-2];
         
      else fr_upBuffer[i] = fr_upBuffer[i-1];
      


//---- Нижний фрактал
      if (Low[i-2] < Low[i-3] && Low[i-2] < Low[i-1])
         fr_dwBuffer[i] = Low[i-2];
         
      else fr_dwBuffer[i] = fr_dwBuffer[i-1];
      }
   return(rates_total);
  }

//+------------------------------------------------------------------+

1) запутался в направлениях пересчета  

 неправильно организовал циклы и что конфликтовало с направлением перебора

2) неправильно рассчитал начало отсчета.

 

тут надо внимательно с направлением индексации и направлением перебора 

 

я тоже пол года назад сталкивался с такими проблемы данные не переворачиваются 

просто они так хранятся в мкл 5 

и  такие щекотливые темы можно встретить ежемесячно.

так что почитайте и вникните с функции копи буфер, аррау инит и копу аррау 

и каждая функция по своему обращается с массивами.

и в мкл5 нету  тайм серий пока их не укажеш 

Причина обращения: