Как реализовать расчет значений по каждому Тайм Фрейму в одном индикаторе. Как определить rates_total,prev_calculated конкретно иного ТФ.

 

Здравствуйте, увлёкся задачкой:

Задача: Рассчитать по каждому Тайм Фрейму rates_total, prev_calculatedprice. (основной вопрос)

Как определить rates_total,prev_calculated конкретно иного ТФ.

1.0. Рассчитать по каждому периоду например 100 скользящих средних, в зависимости от периода будет рассчитан разное кол-во МА

//+------------------------------------------------------------------+
//|                                                          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
//--- input parameters
input int      PmaxM15=100; // количество рассчитываемых МА 
//--- indicator buffers
#include <SMA Greed.mqh>  
CSMA_Greed sm;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
   sm.Init(PmaxM15);
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const int begin,
                const double &price[])
  {
//---
   sm.Solve(rates_total,prev_calculated,price); // с помощью элемента класса sm.d[per-1].m[Nbar] могу достать значения МА
  
//--- return value of prev_calculated for next call
   return(rates_total-1);
  }
//+------------------------------------------------------------------+

Вот параметр 

sm.Solve(rates_total,prev_calculated,price); 

Каким образом, реализовать расчет по каждому Тайм Фрейму? Подменяя параметры (rates_total,prev_calculated,price ) конкретно каждого ТФ

Начал что то мудрить, но это ерунда, можно обойти как-то эффективней?  

Как определить rates_total,prev_calculated конкретно иного ТФ.
//+------------------------------------------------------------------+------------------------------------------------------------------+
bool timTF(const int rates_total,const int prev_calculated)
  {
   for(uchar i=0; i<10; i++)
     {
      ENUM_TIMEFRAMES n_period=(ENUM_TIMEFRAMES)GetPeriodEnumerator(i);
      MqlRates raters[PmaxM15];
      int rez=CopyRates(Symbol(), n_period, 0, PmaxM15, raters);//
      if(rez==0)
        {
         Print("Error timing");
         return(false);
        }
      //--- рассчитаем значения цены Price
      for(int j=PmaxM15; j>0; j--)
         ExtBuffer[j]=MathAbs((raters[j].high+raters[j].low)/2);

      smM15.Solve(rates_total,prev_calculated,ExtBuffer); 

     }
   return(false);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int GetPeriodEnumerator(uchar n_period)
  {
   switch(n_period)
     {
      case 0:
         return(PERIOD_CURRENT);
      case 1:
         return(PERIOD_M1);
      case 2:
         return(PERIOD_M5);
      case 3:
         return(PERIOD_M15);
      case 4:
         return(PERIOD_M30);
      case 5:
         return(PERIOD_H1);
      case 6:
         return(PERIOD_H4);
      case 7:
         return(PERIOD_D1);
      case 8:
         return(PERIOD_W1);
      case 9:
         return(PERIOD_MN1);
      default:
         Print("Enumerator period must be smallest 22");
         return(-1);
     }
  }
Файлы:
SMA_Greed.zip  5 kb
 

Bars(), BarsCalculated()

 

В общем сделал такую штуку. Вычисление rates_total,prev_calculated,price

//+------------------------------------------------------------------+
//| Расчет МА по всем ТФ                                             |
//+------------------------------------------------------------------+
bool MAtime()
  {
   for(int i=1; i<10; i++)//10
     {
      bool error=false;
      ENUM_TIMEFRAMES n_period=(ENUM_TIMEFRAMES)GetPeriodEnumerator((uchar)i);
      //--- рассчитаем количество баров на n_period
      int rates_total=Bars(Symbol(), n_period), prev_calculated=0;
      if(rates_total<Pmax[i])
        {
         Print("Error Не определенно кол-во баров "+(string)n_period+" rates_total = "+(string)rates_total+" Pmax = "+(string)Pmax[i]);
         error=true;
        }
      //--
      MqlRates raters[];
      ArrayFree(ExtBuffer);
      ArrayResize(ExtBuffer,rates_total,rates_total);
      int rez=CopyRates(Symbol(), n_period, 0, rates_total, raters);//n_period
      if(rez==0)
        {
         Print("Error Не определен MqlRates");
         error=true;
        }
      //--- Расчет исторических данных времени
      ArrayFree(Time);
      ArrayResize(Time,rates_total,rates_total);
      int time=CopyTime(Symbol(), n_period,0,rates_total,Time);
      if(time==0)
        {
         Print("Error Не определен time");
         error=true;
        }
      //--- рассчитаем значения цены
      for(int j=1; j<rates_total; j++)
         ExtBuffer[j]=MathAbs((raters[j].high+raters[j].low)/2);
      //---
      if(error==false)
         if(p_c[i]!=rates_total)
           {
            //---Расчитываем МА конкретно ТФ
            sm(rates_total,p_c[i],ExtBuffer,i);
            prev_calc(ExtBuffer,i);
            //---
            // mediana0_1(rates_total,Time,i);
           }
     }
   return(true);
  }

//+------------------------------------------------------------------+
//| Расчет prev_calculated                                           |
//+------------------------------------------------------------------+
int prev_calc(const double &EB[],int i)
  {
   int rates_total=ArrayRange(EB,0);
   if(p_c[i]==0)
      p_c[i]=rates_total;
   if(p_c[i]==rates_total)
      return(p_c[i]);
   else
     {
      p_c[i]=rates_total-(rates_total-p_c[i]);
      return(MathAbs(p_c[i]));
     }
  }
 

А если прикрепить на эксперт 9 одинаковых индикаторов , где каждый индикатор это определенный тайм фрейм.

М1,М5,М15 и т.д.

Будет ли это эффективней чем рассчитывать через функцию которую реализовал выше ?


//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {

   int handle = iCustom(NULL,0,"FidMA",Pmax,numMa);
   if(handle==INVALID_HANDLE)
     {
      Print("Не удалось создать хэндл индикатора std_Handle.",GetLastError());
      return(-1);
     }
  // ArraySetAsSeries(handle,true);//--- create timer
   EventSetTimer(60);

//---
   return(INIT_SUCCEEDED);
  }
 

Вот можно попробовать этот класс

https://www.mql5.com/ru/code/768

IsNewBar
IsNewBar
  • www.mql5.com
Класс СIsNewBar для определения момента времени, когда происходит смена бара.
 

Разбираюсь в структурировании классов.

Подскажите как вытащить m_TOld из protected:; не нарушая логику возврата bool IsNewBar

//+------------------------------------------------------------------+
//|  Алгоритм определения момента появления нового бара              |
//+------------------------------------------------------------------+  
class CIsNewBar
  {
   //----
public:
   //---- функция определения момента появления нового бара
   bool IsNewBar(string symbol,ENUM_TIMEFRAMES timeframe)//, ENUM_SERIES_INFO_INTEGER InfoHist
     {
      //---- получим время появления текущего бара
      datetime TNew=datetime(SeriesInfoInteger(symbol,timeframe,SERIES_LASTBAR_DATE));//SERIES_LASTBAR_DATE

      if(TNew!=m_TOld && TNew) // проверка на появление нового бара
        {
         m_TOld=TNew;
         return(true); // появился новый бар!
        }
      //----
      return(false); // новых баров пока нет!
     };
   //---- конструктор класса    
                     CIsNewBar(){m_TOld=-1;};

protected: datetime m_TOld;
   //---- 
  };
NB[i].IsNewBar(Symbol(),n_period) - по запросу возвращает bool 

как запросить m_TOld ?
 

Я-бы сделал проще. Определяем появление нового минутного бара…

Если новый бар, то считаем остаток от деления текущего времени на PeriodSeconds(PERIOD_M5) и если остаток меньше минуты, то значит появился новый бар на М5. Аналогично и по другим периодам.

А вот если надо иметь возможность получить событие появления нового бара на других инструментах, то это надо искать… Где-то было обсуждение этого и я выкладывал класс А. Тришкина. Если сейчас без затруднений найду, то скину сцильку.

Вот отыскал… Читайте дальше, там есть некоторые поправки и объяснения.
Вопросы от начинающих MQL5 MT5 MetaTrader 5
Вопросы от начинающих MQL5 MT5 MetaTrader 5
  • 2021.08.04
  • www.mql5.com
Подскажите пожалуйста, такой показатель тестера в жизни реален? И хороший это или плохой результат за год с депо 3000...
 
Alexey Viktorov #:

Я-бы сделал проще. Определяем появление нового минутного бара…

Если новый бар, то считаем остаток от деления текущего времени на PeriodSeconds(PERIOD_M5) и если остаток меньше минуты, то значит появился новый бар на М5. Аналогично и по другим периодам.

А вот если надо иметь возможность получить событие появления нового бара на других инструментах, то это надо искать… Где-то было обсуждение этого и я выкладывал класс А. Тришкина. Если сейчас без затруднений найду, то скину сцильку.

Вот отыскал… Читайте дальше, там есть некоторые поправки и объяснения.

Интересно, спасибо.

Вот бы еще подсказали, что такое list_new_bar.Add(nb), где его взять.

   for(int i = 0; i < 1; i++)
     {
      CNewBar *nb = new CNewBar("PHB", PERIOD_M5);
      if(nb==NULL)
         continue;
      if(!list_new_bar.Add(nb))
        {
         delete nb;
         continue;
        }
      Print(nb.IsNewBar(), " ***** ", Rates[i].m_Symbols, " ***** ", nb.Time());
     }
 
Mikhail Toptunov #:

Интересно, спасибо.

Вот бы еще подсказали, что такое list_new_bar.Add(nb), где его взять.

Если нужны подробные объяснения, то лучше задать вопрос Артёму, процитировав одно из его сообщений по этой теме. А у меня просто есть такая строка в области глобальных переменных

CArrayObj         list_new_bar;
как я понимаю, это переменная списка
 

Подскажите пожалуйста как объявить массив в классе, для того чтобы его вытащить в советнике? 

Или где лучше рассчитать значение цены, в классе или в эксперте? 

m_pr_hl2[b]=MathAbs((iHigh(this.m_symbol,this.m_timeframe,b) + iLow(this.m_symbol,this.m_timeframe,b))/2);
class CNewBar : public CObject
  {
private:
   string            m_symbol;
   ENUM_TIMEFRAMES   m_timeframe;
   datetime          m_time;
   double            m_pr_hl2[];
   datetime          Time(void);
   string            Symbol(void)         { return this.m_symbol;    }
public:
   ENUM_TIMEFRAMES   Timeframe(void)      { return this.m_timeframe; }
   datetime          GetTime(void)        { return this.m_time;      } //  Возвращает время последнего обращения
   int               PriceHL2(void);      
   bool              IsNewBar(void);                                   //  Основная функция класса
                     CNewBar(const string symbol,const ENUM_TIMEFRAMES timeframe);
                    ~CNewBar(void) {;}
  };
//+------------------------------------------------------------------+
//| Конструктор                                                      |
//+------------------------------------------------------------------+
CNewBar::CNewBar(const string symbol,const ENUM_TIMEFRAMES timeframe) : m_time(0)
  {
   this.m_symbol = symbol;
   this.m_timeframe = (timeframe == PERIOD_CURRENT ? Period() : timeframe);
   m_rt=this.RatesTotal();
   m_pc=0;
   PriceHL2();
  }
//+------------------------------------------------------------------+
//| CNewBar Time Возвращает время нулевого бара                      |SERIES_LASTBAR_DATE
//+------------------------------------------------------------------+
datetime CNewBar::Time(void)
  {
   datetime array[1], ret;
   ret = CopyTime(this.m_symbol, this.m_timeframe, 0, 1, array) == 1 ? array[0] : 0;
   return(array[0]);
  }

//+------------------------------------------------------------------+
//| Расчет цены                                                      |
//+------------------------------------------------------------------+
int CNewBar::PriceHL2(void)
  {
   int res=ArrayResize(this.m_pr_hl2,this.m_rt);
   for(int b=this.m_pc; b<this.m_rt; b++)
      m_pr_hl2[b]=MathAbs((iHigh(this.m_symbol,this.m_timeframe,b) + iLow(this.m_symbol,this.m_timeframe,b))/2);
   return(res);
  }
//+------------------------------------------------------------------+
//| CNewBar IsNewBar Основная функция класса                         |
//+------------------------------------------------------------------+
bool CNewBar::IsNewBar(void)
  {
   datetime tm=this.Time();
   if(tm==0)
      return false;
   if(tm!=this.m_time)
     {
      //--- определяем время
      this.m_time=tm;
      this.PriceHL2();
      return true;
     }
   return false;
  }
Причина обращения: