Вопросы от начинающих MQL5 MT5 MetaTrader 5 - страница 1467

 
Novichokkk #:

Почему тогда так и не писать вместо  rates_total - Bars() ?

По своей сути  rates_total и Bars()  это одно и то же, только Bars() это функция, соответственно её вызов обойдётся дороже по времени выполнения, чем прочесть значение переменной  rates_total.

 
Artyom Trishkin #:

А что, Вы считаете, я написал не так? Обоснуйте, пожалуйста.

Чему равен limit, и откуда цикл будет в моём и Вашем примере.

Упс)))

Вот это не правильно увидел

if(limit>1)

увидел совсем не то, что у вас написано.

Извиняюсь.

 
Alexey Viktorov #:

Артём, иногда любой человек устаёт и делает ошибки. Не сочти за критику, но rates_total - Bars() всегда будет ноль…

А вообще, этому персонажу объяснять очень сложно. Жертва ЕГЭ…

 rates_total - Bars() в предложении было. То есть   rates_total - это Bars().

В коде ниже ведь 

int limit=Bars()-prev_calculated;

Он прав.

Я, если что, ЕГЭ не сдавал. Тогда не было его.
 
Novichokkk #:

Не могу понять что в итоге значит  rates_total и prev_calculated.

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

Например   МА5, среднее от 5 баров, задать чтобы отобразилось на 100 барах. Тогда индикатор сделает расчёт с 104-го по 100-й бар и начнёт отрисовывать линию с 100-го бара. Тогда  rates_total=5, или 100, или 104?

   int limit = rates_total-100;

   if(prev_calculated <= 0)
     {
      // Вот тут нужно инициализировать все буферы пустыми значениями
      ArrayInitialize(Buffer0, EMPTY_VALUE);
      ArrayInitialize(Buffer1, 0);
      ArrayInitialize(Buffer2, clrNONE);
      // ... и т.д.
     }
   else
      limit = prev_calculated - 1;

//--- Экономный просчёт индикатора
   for(int i = limit; i < rates_total; i++)
     {
      Buffer0[i] = (/*что-то там*/);
     }

Так расчёт будет сделан на последних 100 бар.

 
Aleksandr Slavskii #:

По своей сути  rates_total и Bars()  это одно и то же, только Bars() это функция, соответственно её вызов обойдётся дороже по времени выполнения, чем прочесть значение переменной  rates_total.

Спасибо, доходчиво. 

 
Artyom Trishkin #:

А что, Вы считаете, я написал не так? Обоснуйте, пожалуйста.

Чему равен limit, и откуда цикл будет в моём и Вашем примере.

Ну тогда нужно  Buffer0 задать индексацию как в тайм серии  ArraySetAsSeries(Buffer0,true); иначе пример получается не понятным.

 

В общем вот так. Считаю, что индикаторы рассчитывать от нулевого бара в прошлое - не очень верно.

Всегда их считаю из прошлого в настоящее. Вот, нарисуем линию по Close:

//+------------------------------------------------------------------+
//|                                                TestCalculate.mq5 |
//|                                  Copyright 2023, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_plots   1
//--- plot BufferClose
#property indicator_label1  "BufferClose"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrRed
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
//--- indicator buffers
double         BufferClose[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,BufferClose,INDICATOR_DATA);
   ArraySetAsSeries(BufferClose,true);
//---
   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(close,true);
   ArraySetAsSeries(time,true);
   string txt="";
   int limit=rates_total-prev_calculated;
   
//--- Первый запуск или изменение исторических данных
   if(limit>1)
     {
      limit=rates_total-1;
      txt=StringFormat
        ("Первый запуск или изменение исторических данных. \nrates_total=%ld, prev_calculated=%ld, rates_total-prev_calculated=%ld, limit=%ld\nИнициализируем буфер",
         rates_total,prev_calculated,rates_total-prev_calculated,limit
        );
      Print(txt);
      ArrayInitialize(BufferClose,EMPTY_VALUE);
     }
     
//--- Новый бар
   if(limit==1)
     {
      txt="Новый бар, рассчитываем 2 бара - первый и нулевой";
      PrintFormat("%s. %s, limit=%ld",(string)time[0],txt,limit);
     }
     
//--- Текущий бар
   if(limit==0)
     {
      txt=StringFormat
        ("Рассчитываем текущий бар. rates_total=%ld, prev_calculated=%ld, rates_total-prev_calculated=%ld, limit=%ld",
         rates_total,prev_calculated,rates_total-prev_calculated,limit
        );
     }
   Comment(txt);
     
//--- Основной цикл
   for(int i=limit;i>=0;i--)
     {
      BufferClose[i]=close[i];
     }
     
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
 

С указанием количества просчитываемых баров:

//+------------------------------------------------------------------+
//|                                                TestCalculate.mq5 |
//|                                  Copyright 2023, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_plots   1
//--- plot BufferClose
#property indicator_label1  "BufferClose"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrRed
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
//--- input parameters
input int InpBarsCalc = 100;  /* Number of calculated bars */  // Количество рассчитываемых баров
//--- indicator buffers
double         BufferClose[];
//--- global variables
int calc_total;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,BufferClose,INDICATOR_DATA);
   ArraySetAsSeries(BufferClose,true);
   calc_total=(InpBarsCalc<1 ? 1 : InpBarsCalc);
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//--- indicator buffers mapping
   Comment("");
  }
//+------------------------------------------------------------------+
//| 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(close,true);
   ArraySetAsSeries(time,true);
   string txt="";
   int limit=rates_total-prev_calculated;
   
//--- Первый запуск или изменение исторических данных
   if(limit>1)
     {
      limit=rates_total-1;
      txt=StringFormat
        ("Первый запуск или изменение исторических данных. \nrates_total=%ld, prev_calculated=%ld, rates_total-prev_calculated=%ld, limit=%ld\nИнициализируем буфер",
         rates_total,prev_calculated,rates_total-prev_calculated,limit
        );
      Print(txt);
      ArrayInitialize(BufferClose,EMPTY_VALUE);
     }
     
//--- Новый бар
   if(limit==1)
     {
      txt="Новый бар, рассчитываем 2 бара - первый и нулевой";
      PrintFormat("%s. %s, limit=%ld",(string)time[0],txt,limit);
     }
     
//--- Текущий бар
   if(limit==0)
     {
      txt=StringFormat
        ("Рассчитываем текущий бар. rates_total=%ld, prev_calculated=%ld, rates_total-prev_calculated=%ld, limit=%ld",
         rates_total,prev_calculated,rates_total-prev_calculated,limit
        );
     }
   Comment(txt);
     
//--- Количество просчитываемых баров (начало расчёта)
   int total=fmin(limit,calc_total);
//--- Основной цикл
   for(int i=total;i>=0;i--)
     {
      BufferClose[i]=close[i];
     }
     
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
 
Artyom Trishkin #:

С указанием количества просчитываемых баров:

Спасибо. Отличный развёрнутый ответ!

В общем вот так. Считаю, что индикаторы рассчитывать от нулевого бара в прошлое - не очень верно.

Вы опять запутываете новичков)

В индикаторах MQL5, пока не развернёшь индексацию в обратном направлении нулевой бар это прошлое. 


P.S. Артём опять прав. Я применил не правильный термин, вместо "нулевой бар" нужно было написать "нулевой индекс".

 
Aleksandr Slavskii #:

Спасибо. Отличный развёрнутый ответ!

Вы опять запутываете новичков)

В индикаторах MQL5, пока не развернёшь индексацию в обратном направлении нулевой бар это прошлое. 

Я вроде бы дал исчерпывающий ответ. Два индикатора прикрепил чуть отличающихся. Новичок, увидевший смысл - вырастет в нормального старожилу, и ещё сам потом подскажет. А кто запутается - ну так значит "а оно надо?"

У меня все буферы, их индексация, развёрнуты. А нулевой бар - это на графике. В индикаторе, в его рисуемом буфере (да и в расчётном тоже) может быть только нулевой индекс массива. Предпочитаю, чтобы нулевой бар на графике совпадал с нулевым индексом массива буфера индикатора - дабы новички не путались напрочь.