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

 
Andrey Khatimlianskii:

Что вы называете фидом?

Любый данные (числовые) можно положить в буфер индикатора. Начните с этого. Чтоб нужные данные были видны, если не на графике, то в окне данных (Ctrl+D).

А потом из советника просто возьмите значение нужного буфера на нужном баре. 

Фид - это n-ое количество скользящих средних. Допустим 2000-и скользящих средних на нулевом баре.

То есть извлечь данные с индикатора, который высчитывает значение 50 - ой МА (пример) на нулевом баре.

for(int a=prev_calculated>Pmax?prev_calculated:Pmax;a<rates_total;a++)
     {
     Lx[a]=NormalizeDouble(sm.d[numMa-1].m[a],Digits());
     }  
   return(rates_total-1);

 numMa - это количество вычисляемого фида МА, то есть в индикаторе будет хранится значение заданного количества МА.(например 2000 значений периодов МА)

 a - номер бара, на каком баре произвести расчет.

 
Top2n:

И что, работает?

Если нет, мои предыдущие советы остаются в силе. 

 
Andrey Khatimlianskii:

И что, работает?

Если нет, мои предыдущие советы остаются в силе. 

 

//+------------------------------------------------------------------+
//|                                                          Top.mq5 |
//|                                            Copyright 2015, Urain |
//|                            https://login.mql5.com/ru/users/Urain |
//+------------------------------------------------------------------+
#property copyright "Copyright 2015, Urain"
#property link      "https://login.mql5.com/ru/users/Urain"
#property version   "1.00"
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_plots   1
//--- plot Label1
#property indicator_label1  "NaZnPrd" //****************
#property indicator_type1   DRAW_ARROW
#property indicator_color1  clrRed
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1

//--- input parameters
input int      Pmax=2000;
input int      numMa=51;
//--- indicator buffers
double         Lx[11];
//== Определяем Кол-во =
int nBar;
int den=1;
double CenaMuv[];
double KolMuv[];
//== Определяем Наибольшее =
int NaZnKol[11];
double NaZnPrd[]; //******************
int vsc, Kol;

#include <SMA_Greed.mqh>  
CSMA_Greed sm;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping

   SetIndexBuffer(0,NaZnPrd); //*************
   ArrayResize(CenaMuv,Pmax+1);
   ArrayResize(KolMuv,Pmax+1);
   sm.Init(Pmax);
    EventSetTimer(1);
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const int begin,
                const double &price[])
  {
/*
  ArrayFill(NaZnKol,0,11,0);  //???
  ArrayFill(NaZnPrd,0,11,0);  //???
  ArrayFill(Lx,0,11,0);       //???
//---
*/
nBar=rates_total-1;
sm.Solve(rates_total,prev_calculated,price);
/*
 for(int a=prev_calculated>Pmax?prev_calculated:Pmax;a<rates_total;a++)
   {
  // Lx[a]=NormalizeDouble(sm.d[numMa-1].m[a],Digits());    
   }*/
   
//========================================= Определяем Кол-во =====================================//  
double vper;// double vperc;
    for(int i=3; i<Pmax; i++)
   {
    CenaMuv[i] = NormalizeDouble(sm.d[i-1].m[nBar-1],4);
    KolMuv[i] = 0;
    
      for(int j=3; j<Pmax; j++)
       {  
       vper = NormalizeDouble(sm.d[j-1].m[nBar-1],4);
       if(CenaMuv[i]==vper && j!=i && i-j<22 && i-j>-22)
        KolMuv[i]++;
       }
    }
//=======
//========================================= Определяем Наибольшее =====================================//  
int vsc_;
bool f=false, fl = true, fla=true; 
 Kol=0;   // ?????????------------
 
  for(int x=1; x<=10; x++)
  {
   for(int y=3; y<Pmax; y++)
   { 
        
   fla=true;
   
   if(KolMuv[y]==NaZnKol[x-1]){ KolMuv[y]=0; CenaMuv[y]=0; }
 
     for(int z=1; z<=10; z++) {
      if(funOtrVPol(Lx[z],CenaMuv[y])<0.0005) fla=false;
      }
       
   if(KolMuv[y]>Kol)
     if(fla==true)
     {
       Kol=KolMuv[y];
       vsc=y;
     }  
     
   }
    NaZnKol[x]=KolMuv[vsc]; //Количество
    NaZnPrd[x]=vsc;        /************* //Период
    Lx[x]=CenaMuv[vsc];     //Цена 
    KolMuv[vsc]=0;
    Kol=0;
    f=true;
    fl=false;
   // vsc=0;
  }
//=======

   Comment("sm.d ",sm.d[50].m[nBar-1]
   ,"\n","NaZn[1] ",NaZnKol[1] ," - ",NaZnPrd[1]," - ",Lx[1]
   ,"\n","NaZn[2] ",NaZnKol[2] ," - ",NaZnPrd[2]," - ",Lx[2]
   ,"\n","NaZn[3] ",NaZnKol[3] ," - ",NaZnPrd[3]," - ",Lx[3]
   ,"\n","NaZn[4] ",NaZnKol[4] ," - ",NaZnPrd[4]," - ",Lx[4]
   ,"\n","NaZn[5] ",NaZnKol[5] ," - ",NaZnPrd[5]," - ",Lx[5]
   ,"\n","NaZn[6] ",NaZnKol[6] ," - ",NaZnPrd[6]," - ",Lx[6]
   ,"\n","NaZn[7] ",NaZnKol[7] ," - ",NaZnPrd[7]
   ,"\n","NaZn[8] ",NaZnKol[8] ," - ",NaZnPrd[8]
   ,"\n","NaZn[9] ",NaZnKol[9] ," - ",NaZnPrd[9]
   ,"\n","NaZn[10] ",NaZnKol[10] ," - ",NaZnPrd[10]

   );

   return(rates_total-1);
  }
//+------------------------------------------------------------------+

double funOtrVPol(double Lxv,double CenaM){
double vperc;
   if(Lxv-CenaM>=0) 
   vperc = NormalizeDouble(Lxv-CenaM,5);
   else
   if(Lxv-CenaM<0)
   vperc = NormalizeDouble(CenaM-Lxv,5);

return(vperc);
}

    

 

 NaZnPrd - Значение пытаюсь присвоить нюлевому буферу, что то делаю не так?

 
Top2n

 NaZnPrd - Значение пытаюсь присвоить нюлевому буферу, что то делаю не так?

А что не получается? Не присваивается?

Упростите код, чтоб вы сами понимали, что он делает.

Начните с такого:

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[])
  {
    for ( int i = 0; i < rates_total; i ++ ) NaZnPrd[i] = close[i];

 

А потом усложняйте. Когда появится проблема, пишите конкретно о ней.

Потому что разбирать весь ваш код не интересно.

 
Andrey Khatimlianskii:

А что не получается? Не присваивается?

Упростите код, чтоб вы сами понимали, что он делает.

Начните с такого:

 

А потом усложняйте. Когда появится проблема, пишите конкретно о ней.

Потому что разбирать весь ваш код не интересно.

Да уж, удивляет что до сих пор отвечаете!)

Блин я уже просто не знаю, как ...

 

int OnCalculate(const int rates_total,
                const int prev_calculated,
                const int begin,
                const double &price[])
  {
//---
sm.Solve(rates_total,prev_calculated,price);

 for(int a=prev_calculated>Pmax?prev_calculated:Pmax;a<rates_total;a++)
   {
  Lx[a]=sm.d[numMa-1].m[a];
   }
   return(rates_total-1);
  }

sm.d[numMa-1] - Задаем нужный период скользящей средней,или количество SMA для расчета.

m[a] - Задаем № бара.

sm.d[numMa-1].m[a] - по заданным параметрам получаем значение цены на требуемом баре, с требуемом периодом SMA

Как связать эту информацию, с буферами индикатора.

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

 
Top2n:

Да уж, удивляет что до сих пор отвечаете!)

Блин я уже просто не знаю, как ...

 

sm.d[numMa-1] - Задаем нужный период скользящей средней,или количество SMA для расчета.

m[a] - Задаем № бара.

sm.d[numMa-1].m[a] - по заданным параметрам получаем значение цены на требуемом баре, с требуемом периодом SMA

Как связать эту информацию, с буферами индикатора.

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

У вас в предыдущем коде были правильные строки:

double NaZnPrd[]; //******************
...
SetIndexBuffer(0,NaZnPrd);
...
NaZnPrd[x]=vsc;

Объявили массив, привязали его к буфферу, присвоили значение на определенном баре.

 

Чтоб присвоить значение для бара с индексом а, как в последнем примере, сделайте так:

NaZnPrd[a]=12345;


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

Если и это выйдет, тогда присваивайте то, что вы посчитали в своих многоэтажных массивах ) 

 
Top2n:

Да уж, удивляет что до сих пор отвечаете!)

Я сам в шоке, если честно ;)
 

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

//+------------------------------------------------------------------+
//| Custom indicator iteration function     Работает                         |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const int begin,
                const double &price[])
  {
//---

nBar=rates_total-1;
sm.Solve(rates_total,prev_calculated,price);

   return(rates_total-1);
  }
//+-----------------------------------------------------

 объявляю в эксперте, выдает ошибку

  MqlRates mrate[];           // Будет содержать цены, объемы и спред для каждого бара
     
   //--- Получить исторические данные последних 2000-х баров
   if(CopyRates(_Symbol,_Period,0,Pmax,mrate)<0)
     {
      Alert("Ошибка копирования исторических данных - ошибка:",GetLastError(),"!!");
      return;
     }  
  
  sm.Solve(Mybars,Mybars-1,mrate[].close);
 
Dmitry Fedoseev:

Тогда не надо хранить старые значения. На каждой итерации делаем 2000 сложений. Меньше никак. 

Если надо не с периода 1 или 2 начать, тогда для минимального периода применять ускоренный алгоритм с хранением старого значения, а дальше только прибавлять.

Ускоренный алгоритм это два действия - отнять старое, прибавить новое. Значит если минимальный период больше от 4, то есть смысл в его использовании для минимального периода.

 

Andrey Khatimlianskii:

Тогда вам надо 2000 буферов, и по каждому из них экономно считать SMA ;)

Это будет экономнее по процессору, но затратнее по памяти. 


Можно ускориться еще больше и при этом сократить используемую память по минимуму.

Идея в следующем: рассчитывать все требуемые периоды SMA на одном массиве данных (вернее на одном списке). Массив данных будет один - его длина будет равна периоду самой медленной MA. Параллельно хранится массив из, в данном случае, 2000 значений double, содержащих суммы ряда. При запросе значения MA с произвольным периодом, делается пересчет нужной суммы и ее средней, которая затем возвращается. 

Естественно, такой алгоритм можно будет реализовать только с помощью классов, потому что внутренняя реализация будет весьма нетривиальной и базироваться на словарях (для быстрого доступа к произвольному индексу). Но скорость потенциально может быть просто феерической. При том выигрыш будет особенно заметен именно при расчете кластеров индикаторов (1000, 2000, 10000 индикаторов в одном флаконе).

З.Ы. Интерфейс класса будет примерно следующим:

CSMA SMA;       //Создаем простую скользящую среднюю 

void OnTick()
{ 
  double last = SymbolInfoDouble(Symbol(), SYMBOL_LAST);
  SMA.AddValue(last);
  double sma_200 = SMA.GetValue(200);  // Получаем значение скользящей средней с периодом усреднение 200 тиков
  double sma_100 = SMA.GetValue(100);  // Получаем значение скользящей средней с периодом усреднение 100 тиков 
  double sma_200 = SMA.GetValue(1328); // Получаем значение скользящей средней с периодом усреднение 1328 тиков
  ...
}

Период усреднения можно будет задавать произвольно, непосредственно перед получением значения. Никаких промежуточных расчетов выполнять не нужно (все расчеты будут выполнены за пользователя внутри класса).

 
Top2n:

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

 объявляю в эксперте, выдает ошибку

Что за функция sm.Solve?

Вы скопировали Pmax элементов MqlRates. А что хотите передать?

Массива close нет, у вас массив MqlRates. Можете передать нужный close - mrate[index].close.

А если нужен массив клоузов - используйте CopyClose()