Среднее периодов усреднения МА

 

Поднял на официальных костылях индикатор среднего периодов усреднения МА. Само собой хромает и серьёзно на младших ТФ.

Подскажите пожалуйста, как ускорить работу индикатора? Следующий этап зацикливать по ТФ и далее усложнять, но уже эта скорость MQL5 не радует. Что и где можно улучшить?  

//+------------------------------------------------------------------+
//|                                                          вап.mq5 |
//+------------------------------------------------------------------+

#property version   "1.01"
#property indicator_chart_window
#property indicator_buffers 3
#property indicator_plots   1
//--- plot Label1
#property indicator_type1   DRAW_COLOR_LINE
#property indicator_color1  clrBlue
#property indicator_style1  STYLE_SOLID
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int Handle;
double middle1[];
double middle_ind[];

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,middle_ind,INDICATOR_CALCULATIONS);
 //  SetIndexBuffer(1,middle1,INDICATOR_CALCULATIONS);
   PlotIndexSetInteger(0,PLOT_LINE_WIDTH,4);
//---
   ArrayInitialize(middle_ind,0);
   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(middle_ind,true);
   ArraySetAsSeries(middle1,true);
   int count=Bars(Symbol(),PERIOD_CURRENT)-10;

   int limit=rates_total-prev_calculated;
   if(limit>1)
     {
      limit=rates_total-1;
     }
   for(int i=limit; i>=0 && !IsStopped(); i--)
     {
      if(i>=rates_total-10)
         continue;

      double SumBP=0.0;
      int NumBP=0;
      int BandsPeriod;
      for(BandsPeriod=2; BandsPeriod<=10; BandsPeriod++)
        {
         NumBP++;
         Handle=iMA(Symbol(),PERIOD_CURRENT,BandsPeriod,0,MODE_SMA,PRICE_OPEN);
         if(true)
           {
            if(!iGetArray(Handle,BASE_LINE,0,count,middle1))
              {
               return(false);
              }
           }

         SumBP=SumBP+middle1[i];
         if(i==1)
           {
            Print(BandsPeriod,"  ",middle_ind[0],"  ",middle_ind[1],"  ",middle_ind[2]," -- ",SumBP," -- ",NumBP);
           }
         
        }
         middle_ind[i]=SumBP/NumBP;

     }
   return(rates_total);

  }
//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
bool iGetArray(const int handle,const int buffer,const int start_pos,
               const int count,double &arr_buffer[])
  {
   bool result=true;
   if(!ArrayIsDynamic(arr_buffer))
     {
      if(true)
         PrintFormat("ERROR! EA: %s, FUNCTION: %s, this a no dynamic array!",__FILE__,__FUNCTION__);
      return(false);
     }
   ArrayFree(arr_buffer);
//--- reset error code
   ResetLastError();
//--- fill a part of the iBands array with values from the indicator buffer
   int copied=CopyBuffer(handle,buffer,start_pos,count,arr_buffer);
   int i;
   if(copied<=0)
     {
      Sleep(50);
      for(i=0; i<100; i++)
        {
         if(BarsCalculated(handle)>0)
            break;
         Sleep(50);
        }
     }
   if(copied!=count)
     {
      //--- if the copying fails, tell the error code
      if(true)
         PrintFormat("ERROR! EA: %s, FUNCTION: %s, amount to copy: %d, copied: %d, error code %d",
                     __FILE__,__FUNCTION__,count,copied,GetLastError());
      //--- quit with zero result - it means that the indicator is considered as not calculated
      return(false);
     }

   return(result);
  }
//+------------------------------------------------------------------+
//| Indicator deinitialization function                              |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   if(Handle!=INVALID_HANDLE)
      IndicatorRelease(Handle);
//--- почистим график при удалении индикатора
   Comment("");
  }
//+------------------------------------------------------------------+
 
Николай К:

Поднял на официальных костылях индикатор среднего периодов усреднения МА. Само собой хромает и серьёзно на младших ТФ.

Подскажите пожалуйста, как ускорить работу индикатора? Следующий этап зацикливать по ТФ и далее усложнять, но уже эта скорость MQL5 не радует. Что и где можно улучшить?  

Если это Ваша разработка, то исправьте (или уберите) директивы copyright и link
 
zvezdocheet:
Если это Ваша разработка, то исправьте (или уберите) директивы copyright и link

Piece of cake. Thank you.

 
Николай К:

Поднял на официальных костылях индикатор среднего периодов усреднения МА. Само собой хромает и серьёзно на младших ТФ.

Подскажите пожалуйста, как ускорить работу индикатора? Следующий этап зацикливать по ТФ и далее усложнять, но уже эта скорость MQL5 не радует. Что и где можно улучшить?  


Не надо пересчитывать всю историю на каждом вызове.
Надо считать только нерассчитанные значения.
 
PapaYozh:

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

А как это сделать? Когда и как это происходит в limit или Handle? В букваре подобного примера обращения к хендлу нет, а лимит вроде таков. 

 
Николай К:


1. Читать документацию нужно обязательно. Пример индикатора: iMA

2. Грубейшая ошибка - Вы НА КАЖДОМ ТИКЕ СОЗДАЁТЕ хендл индикатора!!! В MQL5 хендл индикатора СОЗДАЁТСЯ ОДНИ РАЗ и делается это в OnInit.

Документация по MQL5: Технические индикаторы / iMA
Документация по MQL5: Технические индикаторы / iMA
  • www.mql5.com
iMA - Технические индикаторы - Справочник MQL5 - Справочник по языку алгоритмического/автоматического трейдинга для MetaTrader 5
 
Vladimir Karputov:

1. Читать документацию нужно обязательно. Пример индикатора: iMA

2. Грубейшая ошибка - Вы НА КАЖДОМ ТИКЕ СОЗДАЁТЕ хендл индикатора!!! В MQL5 хендл индикатора СОЗДАЁТСЯ ОДНИ РАЗ и делается это в OnInit.

@Vladimir Karputov Понимаю, но нужен перебор периодов и ТФ для построения индикатора в один тик это всё не вытаскивается! А так работает считает, но тупит - и хорошо. Писать свою MA может тоже решение.

 
Николай К:

А как это сделать? Когда и как это происходит в limit или Handle? В букваре подобного примера обращения к хендлу нет, а лимит вроде таков. 

Вот это:

Handle=iMA(Symbol(),PERIOD_CURRENT,BandsPeriod,0,MODE_SMA,PRICE_OPEN);

закиньте в OnInit(). Из переменной Handle сделайте массив, объявленный на глобальном уровне. Это если нужно несколько копий Handle для каждого из ТФ. Правда, в коде я не вижу, чтобы была подобная потребность. Поэтому для текущего случая - просто перенести строку в OnInit() и объявить переменную глобально.

 

Добрый час. Вернулся к работе над задачей, переделал индикатор в соответствии с рекомендациями, стало всё ещё хуже, нет отрисовки графика и ещё жоще тормозит.  Но нет сообщений о не готовности данных, единственный + 

//+------------------------------------------------------------------+
//|                                                          вап.mq5 |
//+------------------------------------------------------------------+
#property version   "1.02"
#property indicator_chart_window
#property indicator_buffers 3
#property indicator_plots   1
//--- plot Label1
#property indicator_type1   DRAW_COLOR_LINE
#property indicator_color1  clrBlue
#property indicator_style1  STYLE_SOLID
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int Handle[10][11];
double middle1[];
double middle_ind[];
int Tick=0;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,middle_ind,INDICATOR_CALCULATIONS);
//  SetIndexBuffer(1,middle1,INDICATOR_CALCULATIONS);
   PlotIndexSetInteger(0,PLOT_LINE_WIDTH,4);
//---
   ArrayInitialize(middle_ind,0);
   for(int BandsPeriod=2; BandsPeriod<=10; BandsPeriod++)
     {
      Handle[0][BandsPeriod]=iMA(Symbol(),PERIOD_CURRENT,BandsPeriod,0,MODE_SMA,PRICE_OPEN);
     }
   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(middle_ind,true);
   ArraySetAsSeries(middle1,true);
   int count=Bars(Symbol(),PERIOD_CURRENT)-10;

   int limit=rates_total-prev_calculated;
   if(limit>1)
     {
      limit=rates_total-1;
     }
   for(int i=limit; i>=0 && !IsStopped(); i--)
     {
      if(i>=rates_total-10)
         continue;

      double SumBP=0.0;
      int NumBP=0;
      int BandsPeriod;
      for(BandsPeriod=2; BandsPeriod<=10; BandsPeriod++)
        {
         NumBP++;
         //         Handle=iMA(Symbol(),PERIOD_CURRENT,BandsPeriod,0,MODE_SMA,PRICE_OPEN);
         if(true)
           {
            if(!iGetArray(Handle[0][BandsPeriod],BASE_LINE,0,count,middle1))
              {
               return(false);
              }
           }

         SumBP=SumBP+middle1[i];
         if(i==1)
           {
            Print(BandsPeriod,"  ",middle_ind[0],"  ",middle_ind[1],"  ",middle_ind[2]," -- ",SumBP," -- ",NumBP);
           }
        }
      middle_ind[i]=SumBP/NumBP;

     }
   return(rates_total);

  }
//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
bool iGetArray(const int handle,const int buffer,const int start_pos,
               const int count,double &arr_buffer[])
  {
   bool result=true;
   if(!ArrayIsDynamic(arr_buffer))
     {
      if(true)
         PrintFormat("ERROR! EA: %s, FUNCTION: %s, this a no dynamic array!",__FILE__,__FUNCTION__);
      return(false);
     }
   ArrayFree(arr_buffer);
//--- reset error code
   ResetLastError();
//--- fill a part of the iBands array with values from the indicator buffer
   int copied=CopyBuffer(handle,buffer,start_pos,count,arr_buffer);
   int i;
   if(copied<=0)
     {
      Sleep(50);
      for(i=0; i<100; i++)
        {
         if(BarsCalculated(handle)>0)
            break;
         Sleep(50);
        }
     }
   if(copied!=count)
     {
      //--- if the copying fails, tell the error code
      if(true)
         PrintFormat("ERROR! EA: %s, FUNCTION: %s, amount to copy: %d, copied: %d, error code %d",
                     __FILE__,__FUNCTION__,count,copied,GetLastError());
      //--- quit with zero result - it means that the indicator is considered as not calculated
      return(false);
     }

   return(result);
  }
//+------------------------------------------------------------------+
//| Indicator deinitialization function                              |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   for(int BandsPeriod=2; BandsPeriod<=10; BandsPeriod++)
     {

      if(Handle[0][BandsPeriod]!=INVALID_HANDLE)
         IndicatorRelease(Handle[0][BandsPeriod]);
     }
//--- почистим график при удалении индикатора
   Comment("");
  }
//+------------------------------------------------------------------+
 
Николай К:

Поднял на официальных костылях индикатор среднего периодов усреднения МА. Само собой хромает и серьёзно на младших ТФ.

Подскажите пожалуйста, как ускорить работу индикатора? Следующий этап зацикливать по ТФ и далее усложнять, но уже эта скорость MQL5 не радует. Что и где можно улучшить?  

никакие хендлы и индикаторы здесь вообще не нужны.

выпишите ф-лы (а) SMA (б) усреднения SMA

подставьте (a) в (б) - получите конечную формулу. 

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

PS/ можно ещё быстрее прийти к тому-же результату используя вектора и матрицы. Простейшие SMA/EMA/LWMA они от рождения и по определению "нормированный вектор весов"

 
Николай К:

Добрый час. Вернулся к работе над задачей, переделал индикатор в соответствии с рекомендациями, стало всё ещё хуже, нет отрисовки графика

Отображается:


и ещё жоще тормозит. 

не заметил особых тормозов. Правда, в тестере не пробовал.

Но нет сообщений о не готовности данных, единственный + 

Зачем на каждом расчетном баре в цикле запрашивается вся история?

if(!iGetArray(Handle[0][BandsPeriod],BASE_LINE,0,count,middle1))

Такие артефакты:

int Handle[10][11]; // Не используются 9 элементов в первом измерении и два - во втором
         if(true)   // Условие всегда выполняется

лучше убирать из демо-кодов. Ведь они затрудняют понимание кода другими.

Ну и по мелочам:

  1. Не рекомендуется инициализировать индикаторные буферы в OnInit().
  2. Sleep() в индикаторах не работает.
Причина обращения: