Перенести код индикатора IVAR в советник!

 

Доброго времени суток!

Нужно перенести код индикатора iVAR в советник, чтобы не использовать функцию iCustom. Индикатор через неё вызывается аж 8 раз, это замедляет процесс оптимизации.

Прошу помочь, за ранее спасибо!


Я попытался написать индикаторную функцию в советнике, но не получилось. Выкладываю код индикаторной функции:

//+------------------------------------------------------------------+
//|                                               Get_IVARISeries.mqh |
//|                      Copyright © 2007, MetaQuotes Software Corp. |
//|                                       http://www.metaquotes.net/ |
//+------------------------------------------------------------------+
bool Get_iVARSeries(int Number, string symbol,int timeframe, 
                    bool NullBarRecount_, int n, int nBars, 
                    double& InputBuffer[])    
  {
//---- получение количества всех баров графика
   int IBARS = iBars(symbol, timeframe);

//---- ЭМУЛЯЦИЯ ИНДИКАТОРНЫХ БУФЕРОВ
   if(ArraySize(InputBuffer) < IBARS)
     {
       ArraySetAsSeries(InputBuffer, false);
       //----  
       ArrayResize(InputBuffer, IBARS); 
       //----
       ArraySetAsSeries(InputBuffer, true);
     } 

//----+  введение статических переменных памяти
   static int IndCounted[]; 
//----+ изменение размеров статических переменных
   if(ArraySize(IndCounted) < Number + 1)
     {
       ArrayResize(IndCounted, Number + 1); 
     }

 //----+ Введение целой переменной
   int LastCountBar;
//----+ Проверка разрешения пересчёта нулевого бара
   if(!NullBarRecount_)
      LastCountBar = 1;
   else 
      LastCountBar = 0;

//----+ Введение переменных с плавающей точкой 
   double Delta, Xc, Yc, Sx, Sy, Sxx, Sxy;

//----+ Введение целых переменных и  получение уже посчитанных баров
   int i, j, k, nTotal, nCountedBars = IndCounted[Number];
   int ihigh, ilow, nInterval;
   
//----+ Запоминание количества всех баров графика
   IndCounted[Number] = IBARS - 1;

//---- определение номера самого старого бара, 
// начиная с которого будет произедён пересчёт новых баров
   
   if (nBars>0)
            nTotal = MathMin(nBars,MathMin(IBARS-nCountedBars,IBARS-1));
      else  nTotal = MathMin(IBARS-nCountedBars,IBARS-1);
   
   //---- основной цикл индикатора
   for(j=nTotal; j>=LastCountBar; j--)
   {
      Sx = 0; Sy = 0; Sxx = 0; Sxy = 0;
      for(i=0; i<=n; i++)
      {
         nInterval = MathPow(2,n-i);
      //---- суммируем разницы максимальной и минимальной цен на интервале
         for(Delta=0, k=0; k<MathPow(2,i); k++)
         {
            ihigh = iHighest(symbol,timeframe,MODE_HIGH,nInterval,nInterval*k+j);
            ilow = iLowest(symbol,timeframe,MODE_LOW,nInterval,nInterval*k+j);
            Delta += High[ihigh]-Low[ilow];
         }
      //---- вычисляем координаты вариации в двойном логарифмическом масштабе
         Xc = (n-i)*MathLog(2.0);
         Yc = MathLog(Delta);
      //---- накапливаем данные для нахождения коэффициентов линии регрессии с помощью МНК
         Sx += Xc; 
         Sy += Yc;
         Sxx += Xc*Xc; 
         Sxy += Xc*Yc;
      }
   //---- вычисляем индекс вариации (коэффициент наклона линии регрессии)
      InputBuffer[j] = -(Sx*Sy-(n+1)*Sxy)/(Sx*Sx-(n+1)*Sxx);
   }

   return(true);
  }
//+------------------------------------------------------------------+


Сам индикатор:

//+------------------------------------------------------------------+
//|                                                         iVAR.mq4 |
//|                                        (C)opyright © 2008, Ilnur |
//|                                        http://www.metaquotes.net |
//+------------------------------------------------------------------+

//   Индикатор отображает индекс вариации ценового ряда, вычисленного
// на минимальном предшествующем интервале длины 2^n. Индекс вариации
// показывает, что преобладает во временном ряду – трендовая или флетовая
// составляющая, или же ряд ведет себя случайно.

// М.М. Дубовиков и др. - Размерность минимального покрытия и локальный
// анализ фрактальных временных рядов.

#property copyright "(C)opyright © 2008, Ilnur"
#property link      "http://www.metaquotes.net"
//---- настройки индикатора
#property indicator_separate_window
#property indicator_buffers 1
#property indicator_color1 Red
#property indicator_level1 0.5
//---- входные параметры
extern int n = 5;
extern int nBars = 1000;
//---- буфер индикатора
double ibuffer[];
//+------------------------------------------------------------------+
//| Функция инициализации индикатора                                 |
//+------------------------------------------------------------------+
int init()
{
//---- настройка параметров отрисовки
   SetIndexBuffer(0,ibuffer);
   SetIndexStyle(0,DRAW_LINE);
   SetIndexDrawBegin(0,Bars-nBars);
   SetIndexLabel(0,"iVAR");
//---- "короткое имя" отображаемое в окне индикатора
   IndicatorShortName("iVAR("+n+")");
   return(0);
}
//+------------------------------------------------------------------+
//| Основная функция индикатора                                      |
//+------------------------------------------------------------------+
int start()
{
   int i, j, k, nTotal, nCountedBars = IndicatorCounted();
   int ihigh, ilow, nInterval;
   double Delta, Xс, Yс, Sx, Sy, Sxx, Sxy;
//---- последний посчитанный бар будет пересчитан
   if(nCountedBars<0) return(-1);
   if(nCountedBars>0) nCountedBars--;
      if (nBars>0)
            nTotal = MathMin(nBars,MathMin(Bars-nCountedBars,Bars-1));
      else  nTotal = MathMin(Bars-nCountedBars,Bars-1);

//---- основной цикл индикатора
   for(j=nTotal; j>=0; j--)
   {
      Sx = 0; Sy = 0; Sxx = 0; Sxy = 0;
      for(i=0; i<=n; i++)
      {
         nInterval = MathPow(2,n-i);
      //---- суммируем разницы максимальной и минимальной цен на интервале
         for(Delta=0, k=0; k<MathPow(2,i); k++)
         {
            ihigh = iHighest(Symbol(),0,MODE_HIGH,nInterval,nInterval*k+j);
            ilow = iLowest(Symbol(),0,MODE_LOW,nInterval,nInterval*k+j);
            Delta += High[ihigh]-Low[ilow];
         }
      //---- вычисляем координаты вариации в двойном логарифмическом масштабе
         Xс = (n-i)*MathLog(2.0);
         Yс = MathLog(Delta);
      //---- накапливаем данные для нахождения коэффициентов линии регрессии с помощью МНК
         Sx += Xс; 
         Sy += Yс;
         Sxx += Xс*Xс; 
         Sxy += Xс*Yс;
      }
   //---- вычисляем индекс вариации (коэффициент наклона линии регрессии)
      ibuffer[j] = -(Sx*Sy-(n+1)*Sxy)/(Sx*Sx-(n+1)*Sxx);
   }
   return(0);
}

И тест, который не проходит не совпадают значения в буферах:

//+------------------------------------------------------------------+
//|                                           Get_iVARSeriesTest.mq4 |
//|                      Copyright © 2007, MetaQuotes Software Corp. |
//|                                       http://www.metaquotes.net/ |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2007, MetaQuotes Software Corp."
#property link      "http://www.metaquotes.net/"
//---- ВХОДНЫЕ ПАРАМЕТРЫ ЭКСПЕРТА
extern bool NullBarRecount = true;
//---- индикаторные буфферы
double iVAR_Buffer0[];
double iVAR_Buffer1[];
double iVAR_Buffer2[];
//+------------------------------------------------------------------+
//| Get_RAVISeries() function                                        |
//+------------------------------------------------------------------+
#include <Get_iVARSeries.mqh>
//+------------------------------------------------------------------+
//| Custom Expert initialization function                            |
//+------------------------------------------------------------------+
int init()
  {
//----
//---- завершение инициализации
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom Expert iteration function                                 |
//+------------------------------------------------------------------+
int start()
  {
//---- 
double Ind_Velue,Resalt;
//---- 
if (!Get_iVARSeries(0,Symbol(),0,NullBarRecount,3,1000,iVAR_Buffer0))
   return(0);
   
if (!Get_iVARSeries(1,Symbol(),240,NullBarRecount,5,1000,iVAR_Buffer1))
   return(0);
   
if (!Get_iVARSeries(2,Symbol(),1440,NullBarRecount,8,1000,iVAR_Buffer2))
   return(0);
   
//---- получение индикаторных значений для теста 0

Ind_Velue=iCustom (Symbol(),0,"iVAR",3,1000,0,2);

Resalt=iVAR_Buffer0[2]-Ind_Velue; 

Print( "  "+Ind_Velue+"    "+iVAR_Buffer0[2]+"    "+Resalt+"" );

//---- получение индикаторных значений для теста 1

Ind_Velue=iCustom (Symbol(),240,"iVAR",5,1000,0,2);

Resalt=iVAR_Buffer1[2]-Ind_Velue; 

Print( "  "+Ind_Velue+"    "+iVAR_Buffer1[2]+"    "+Resalt+"" );

//---- получение индикаторных значений для теста 2

Ind_Velue=iCustom (Symbol(),1440,"iVAR",8,1000,0,2);

Resalt=iVAR_Buffer2[2]-Ind_Velue; 

Print( "  "+Ind_Velue+"    "+iVAR_Buffer2[2]+"    "+Resalt+"" );
//----
   return(0);
  }
//+------------------------------------------------------------------+

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

Файлы:
 
Постников Артем:

Нужно перенести код индикатора iVAR в советник, чтобы не использовать функцию iCustom. Индикатор через неё вызывается аж 8 раз, это замедляет процесс оптимизации.
Прошу помочь, за ранее спасибо!
Я попытался написать индикаторную функцию в советнике, но не получилось.

Переместить этот код в советник

extern int n = 5;
extern int nBars = 1000;
//---- буфер индикатора
int tf;
double ibuffer[];
//----
void init(){
    tf=PERIOD_CURRENT;     
    SetIndexBuffer(0,ibuffer);
    SetIndexStyle(0,DRAW_NONE);
return;}
//----
void start(){
//=========== ЭМУЛЯЦИЯ ИНДИКАТОРНЫХ БУФЕРОВ ============|
   if(ArraySize(ibuffer)<Bars){
      ArraySetAsSeries(ibuffer,false); 
      ArrayResize(ibuffer,iBars(Symbol(),tf)); 
      ArraySetAsSeries(ibuffer,true);} 
      
   int bars = iBars(Symbol(),tf);
   if (bars < n) return;  
   
   int i, j, k, nTotal;
   int ihigh, ilow, nInterval;
   double Delta, Xс, Yс, Sx, Sy, Sxx, Sxy;
//---- последний посчитанный бар будет пересчитан
   static int nCountedBars;   
   nCountedBars=bars-1;
   if(nCountedBars<0) return;
   if(nCountedBars>0) nCountedBars--;
   
      if (nBars>0)
            nTotal = MathMin(nBars,MathMin(bars-nCountedBars,bars-1));
      else  nTotal = MathMin(bars-nCountedBars,bars-1);

//---- основной цикл индикатора
   for(j=nTotal; j>=0; j--)
   {
      Sx = 0; Sy = 0; Sxx = 0; Sxy = 0;
      for(i=0; i<=n; i++)
      {
         nInterval = MathPow(2,n-i);
      //---- суммируем разницы максимальной и минимальной цен на интервале
         for(Delta=0, k=0; k<MathPow(2,i); k++)
         {
            ihigh = iHighest(Symbol(),0,MODE_HIGH,nInterval,nInterval*k+j);
            ilow = iLowest(Symbol(),0,MODE_LOW,nInterval,nInterval*k+j);
            Delta += High[ihigh]-Low[ilow];
         }
      //---- вычисляем координаты вариации в двойном логарифмическом масштабе
         Xс = (n-i)*MathLog(2.0);
         Yс = MathLog(Delta);
      //---- накапливаем данные для нахождения коэффициентов линии регрессии с помощью МНК
         Sx += Xс; 
         Sy += Yс;
         Sxx += Xс*Xс; 
         Sxy += Xс*Yс;
      }
   //---- вычисляем индекс вариации (коэффициент наклона линии регрессии)
      ibuffer[j] = -(Sx*Sy-(n+1)*Sxy)/(Sx*Sx-(n+1)*Sxx);
   }
return;}
 
FXwin:

Переместить этот код в советник

for(Delta=0, k=0; k<MathPow(2,i); k++)
         {
            ihigh = iHighest(Symbol(),0,MODE_HIGH,nInterval,nInterval*k+j);
            ilow = iLowest(Symbol(),0,MODE_LOW,nInterval,nInterval*k+j);
            Delta += High[ihigh]-Low[ilow];
         }

Спасибо, но в этом участке кода точно не нужно менять символ и таймфрейм?
 
Постников Артем:
но в этом участке кода точно не нужно менять символ и таймфрейм?

Зачем там менять?
Код по умолчанию использует текущий символ и тф на графике куда брошен советник.

 
FXwin:

Зачем там менять?
Код по умолчанию использует текущий символ и тф на графике куда брошен советник.

  Если оформить как процедуру и считывать данные с других тайфреймов? Он будет считать в данном случае только с текущего. Моя идея была оформить как функцию, которая будет работать по аналогу, как iCustom, только заточенная для данного индикатора с возможностью считывать данные с любого тайфрейма и смещением на 1 - 2 и тд баров назад, если к примеру нужно будет замерить разность между значениями индикатора. В этом был смысл темы. ))

 
Постников Артем:

  Если оформить как процедуру и считывать данные с других тайфреймов? Он будет считать в данном случае только с текущего. Моя идея была оформить как функцию, которая будет работать по аналогу, как iCustom, только заточенная для данного индикатора с возможностью считывать данные с любого тайфрейма и смещением на 1 - 2 и тд баров назад, если к примеру нужно будет замерить разность между значениями индикатора. В этом был смысл темы. ))

Ну тогда так можно поправить

extern int TF = 0; //если (=0) текущий тф

//----
ihigh = iHighest(Symbol(),TF,MODE_HIGH,nInterval,nInterval*k+j);
ilow = iLowest(Symbol(),TF,MODE_LOW,nInterval,nInterval*k+j);
Delta += iHigh(Symbol(),TF,ihigh)-iLow(Symbol(),TF,ilow);
 
FXwin:

Ну тогда так можно поправить

Спасибо.

 
FXwin:

Ну тогда так можно поправить

А как можно реализовать смещение на 1 -  2 бара к примеру назад?  Чтобы замерить разницу значений индикатора?

 
Постников Артем:

А как можно реализовать смещение на 1 -  2 бара к примеру назад?  Чтобы замерить разницу значений индикатора?

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

extern int Bar = 0; //если (=0) текущий бар, если (=1) предыдущий бар

double buf=0.0;
//===================================================================|

   //---- вычисляем индекс вариации (коэффициент наклона линии регрессии)
      ibuffer[j] = -(Sx*Sy-(n+1)*Sxy)/(Sx*Sx-(n+1)*Sxx);
      buf = ibuffer[j+Bar];
   }

//Получаем сигнал от buf на указанном баре
 
FXwin:

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

Спасибо, по коду и точности переноса все ок... Значения совпадают индикатора с тем что в советнике, но скорость работы и оптимизации еще меньше стала, чем была ((( с чем это может быть связано?

 
Постников Артем:

но скорость работы и оптимизации еще меньше стала, чем была ((( с чем это может быть связано?

Я не проверял этот код, на скорость работы влияет цикл баров в истории

тут надо разбираться

      if (nBars>0)
            nTotal = MathMin(nBars,MathMin(bars-nCountedBars,bars-1));
      else  nTotal = MathMin(bars-nCountedBars,bars-1);

//---- основной цикл индикатора
   for(j=nTotal; j>=0; j--)
   {

      for(i=0; i<=n; i++)
      {