Скользящая средняя(SMA) в количестве 2000 шт. расчитать при минимальных затрат ресурсов.

 

 Народный умелец, с форума mql4 щедро предоставил мне вот такую реализацию подсчета SMA в массив! За что ему примного благодарен. 

 

//+------------------------------------------------------------------+
//|                                                         SSMA.mq4 |
//|                                            Copyright 2014, Vinin |
//|                                             http://vinin.ucoz.ru |
//+------------------------------------------------------------------+
#property copyright "Copyright 2014, Vinin"
#property link      "http://vinin.ucoz.ru"
#property version   "1.00"
#property strict
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_plots   1
//--- plot average
#property indicator_label1  "average"
#property indicator_type1   DRAW_ARROW
#property indicator_color1  clrRed
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
//--- input parameters
input int      CountMA=2000;
input int      Period_start=5;
input int      Period_shift=3;
//--- indicator buffers
double         averageBuffer[];
double         maxBuffer[];
double         minBuffer[];
double         Label1Buffer[];

double tmparray[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,averageBuffer);
//--- setting a code from the Wingdings charset as the property of PLOT_ARROW
   PlotIndexSetInteger(0,PLOT_ARROW,159);
   
   ArrayResize(tmparray, CountMA+1);
//---
   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[])
  {
//---
   if (rates_total<Period_start+Period_shift*CountMA+1) return(0);
   ArrayInitialize(tmparray,0);
   
   int limit=rates_total-prev_calculated;
   if (limit>1) limit=rates_total-(Period_start+Period_shift*CountMA+1);
   
   double min=999999,max=-99999, sum=0;
   int count, countMA;
   
   for (int i=limit;i>=0;i--)
   {
      sum=0;
      count=0;
      countMA=0;
      
      // формируем массив со значенияи машек
      for (int j=0;j<Period_start+Period_shift*CountMA;j++)
      {
         sum+=(High[i+j]+Low[i+j])*0.5;
         count++;
         if (count==Period_start+Period_shift*countMA)
         {
            tmparray[countMA]=sum/count;
            countMA++;
         }
      }
      // Массив создан. МОжно обрабатывать
      
   
   }
   
   
   
//--- return value of prev_calculated for next call
   return(rates_total);
  } 

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

 

Так же в OnCalculate 

//***** Расчитать количество повторенний SMA, в десятичном интервале.
   for (int b=0;b<CountMA;b++)
   {
     schet=0;
     for (int a =CountMA;a>=0;a--) 
     {
       if(NormalizeDouble(tmparray[a],4)==NormalizeDouble(tmparray[b],4)&&tmparray[a]!=0) // 1.30000 = 1.30004 ищем места с уплотнением жгутов

       {
         scBuf[b][0]=schet;                       // количество повторений МА
         scBuf[b][1]=tmparray[b];                 // Цена
         tmparray[a]=0;                           // Обнуляем посчитанную ячейку
         schet++;
       }
     } 
   }
   
   ArraySort(scBuf,WHOLE_ARRAY,0,MODE_DESCEND);   // Сортируем массив 

   for (int x=0;x<CountMA+1;x++) 
   {
     averageBuffer[x]=scBuf[x][1];           //переносим значения в одномерный массив, для отображения через индикатор    
   }  
  

 

 Цель: разместить на экране крестики там где скользящие средние повторяются(в заданном диапазоне цены, в данном случае 1.30000 = 1.30004) , 

Но результат:  крестики разбросаны  не там где нужно. 

 

Создал 8 буферов, теперь в принципе разобрался, что происходит с объектами.

писец какой-то!) 

 

Как же сделать без 8 буферов, чтоб без ограничений выставлять объекты индикатором в столбец

 

Начать можно проще, без повторов и отдельного счетчика:

   for ( int b = 0; b < CountMA; b ++ )
   {
     scBuf[b][0]=0;
     for ( int a = b+1; a < CountMA; a++ ) 
     {
       if ( MathAbs( tmparray[a] - tmparray[b] ) < _Point ) // разница между МА меньше 0.0001 (четырехзнак)
       {
         scBuf[b][0]=scBuf[b][0] + 1;             // количество повторений МА
         scBuf[b][1]=tmparray[b];                 // Цена
       }
     } 
   }

 

А сортировку надо заменить простым перебором и поиском максимального scBuf[х][0] и выводом результата на экран.

Только не понятно, надо ли на каждом баре выводить весь "жгут" (несколько МА, которые близки друг к другу), или достаточно только одно значение?

 

PS: ArraySort работает только с одномерными массивами.

 

Если одно значение, то как-то так:

      // Массив создан. МОжно обрабатывать

      // Находим самую популярную МА (возле которой максимум других)
      int bestMA = -1, bestCount = 0;
      for ( int b = 0; b < CountMA; b ++ )
      {
        int curCount = 0;
        for ( int a = 0; a < CountMA; a++ ) 
        {
          if ( a == b ) cnontinue;
          if ( MathAbs( tmparray[a] - tmparray[b] ) < _Point ) // разница между МА меньше 0.0001 (четырехзнак)
          {
            curCount ++; // количество МА [a] возле МА [b]
          }
        } 
        // Если это лучший на данный момент результат, запомним его
        if ( curCount > bestCount )
        {
           bestCount = curCount;
           bestMA = b;
        }
      }

      // Если нашли, рисуем
      if ( bestMA >= 0 ) averageBuffer[i] = tmparray[bestMA];
   }
   
//--- return value of prev_calculated for next call
   return(rates_total);
  } 
 
komposter:

Начать можно проще, без повторов и отдельного счетчика:

 

А сортировку надо заменить простым перебором и поиском максимального scBuf[х][0] и выводом результата на экран.

Только не понятно, надо ли на каждом баре выводить весь "жгут" (несколько МА, которые близки друг к другу), или достаточно только одно значение?

 

PS: ArraySort работает только с одномерными массивами.

Спасибо!) 

Что касается: "надо ли на каждом баре выводить весь "жгут", или достаточно только одно значение?" - Там не только один жгут надо выделить, а множество.

Тоже проблема что делать когда буферов не хватит.

Получается что ArraySort  сортирует по первому измерению, не синхронизируя второе с первым?

 
Top2n:

Спасибо!) 

Что касается: "надо ли на каждом баре выводить весь "жгут", или достаточно только одно значение?" - Там не только один жгут надо выделить, а множество.

Тоже проблема что делать когда буферов не хватит.

Получается что ArraySort  сортирует по первому измерению, не синхронизируя второе с первым?

Используйте вместо стандартной ArraySort, QuickSort, в нём можно прописать сортировку многомерного массива по заданному измерению.

А вообще дети у вас хорошие, а всё что вы делаете руками плохо :)

Вы изначально в написании алгоритма пошли ущербным (наиболее затратным путём), сизифов труд. 

 
Top2n:

Спасибо!) 

Что касается: "надо ли на каждом баре выводить весь "жгут", или достаточно только одно значение?" - Там не только один жгут надо выделить, а множество.

Тоже проблема что делать когда буферов не хватит.

Вы себе представляете 256 точек на одном баре (кажется, именно столько буферов доступно)?
Какой в этом смысл?

Постарайтесь для начала представить результат. Нарисуйте.
Скорее всего, придет понимание, что нужно что-то другое. Тогда и возвращайтесь )

 

Может пригодится

https://www.mql5.com/ru/articles/26

Построение излучений индикаторов в MQL5
Построение излучений индикаторов в MQL5
  • 2010.03.23
  • Sergey Pavlov
  • www.mql5.com
В статье рассматриваются излучения индикаторов - новое направление исследования рынка. Принцип построения излучений основан на пересечении линий различных индикаторов - с каждым тиком на графике появляются всё новые и новые точки с различным цветом и формой. Они образуют многочисленные скопления в виде туманностей, облаков, дорожек, линий, дуг и т.п. Эти характерные области точек помогают обнаружить невидимые пружины и силы, которые влияют на движение рыночных цен.
 

Здравствуйте, начал с начала, только теперь не могу опять же создать массив значений.

Идея такая:

Создаем массив из 2000 значений простой скользящей средней, применить к Median Price (HL/2)(не знаю как реализовать)

Через реализацию по подобию стандартного индикатора, путем вычисления предыдущих скользящих имея значение конечной 2000-ой MA.

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

                 //  sma99[i]=(sma100[i]*100-d[i-100])/99;

                 //  Y(n+1)=(Y(n)*n+x[n+1])/(n+1)

                // (firstValue*InpMAPeriod+price[i+1])/InpMAPeriod;

                // (firstValue*InpMAPeriod+price[InpMAPeriod+1])/(InpMAPeriod+1); 

                //  Y[i]=Y[i+1]+(X[0]-X[N])/N;

               // Y(N)=1/N*(Y(N+1)*(N+1)-X[N]), где Y(i) - значение МА(i) на нулевом баре, X[j] - значение цены на j-ом баре; 

//+------------------------------------------------------------------+
//|  Moving Average                                                  |
//+------------------------------------------------------------------+
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[])
  {
//--- check for bars count
   if(rates_total<InpMAPeriod-1 || InpMAPeriod<2)
      return(0);
//--- counting from 0 to rates_total
   ArraySetAsSeries(ExtLineBuffer,false);
   ArraySetAsSeries(ExtLineBufferFid,false);
   ArraySetAsSeries(close,false);
//--- first calculation or number of bars was changed
   if(prev_calculated==0)
      ArrayInitialize(ExtLineBuffer,0);
      ArrayInitialize(ExtLineBufferFid,0);
//--- calculation

      CalculateSimpleMA(rates_total,prev_calculated,close);
 ExtLineBufferFid[1]=(ExtLineBuffer[rates_total-2]*InpMAPeriod-close[rates_total-2-InpMAPeriod])/(InpMAPeriod-1); 
//Подставлял всякое и в разные места- кавардак здесь пытаюсь получить просто значение предпоследней МА
   return(rates_total);
  }
//+------------------------------------------------------------------+
//|   simple moving average                                          |
//+------------------------------------------------------------------+
void CalculateSimpleMA(int rates_total,int prev_calculated,const double &price[])
  {
   int i,limit;
//--- first calculation or number of bars was changed
   if(prev_calculated==0)
   
     {
      limit=InpMAPeriod;
      //--- calculate first visible value
      double firstValue=0;
      for(i=0; i<limit; i++)
         firstValue+=price[i];
      firstValue/=InpMAPeriod;
      ExtLineBuffer[limit-1]=firstValue;
     }
   else
      limit=prev_calculated-1;
//--- main loop
   for(i=limit; i<rates_total && !IsStopped(); i++)
    {                                    
      ExtLineBuffer[i]=ExtLineBuffer[i-1]+(price[i]-price[i-InpMAPeriod])/InpMAPeriod;
    }   
//---
  }