OnCalculate

Вызывается в индикаторах при наступлении события Calculate для обработки изменений ценовых данных. Существуют два варианта функции, в пределах одного индикатора нельзя использовать оба варианта.

Вычисление на основе массива данных

int  OnCalculate(
   const int        rates_total,       // размер массива price[]
   const int        prev_calculated,   // количество обработанных баров на предыдущем вызове
   const int        begin,             // номер индекса в массиве price[], с которого начинаются значимые данные
   const double&    price[]            // массив значений для расчета
   );

Вычисления на основе таймсерий текущего таймфрейма

int  OnCalculate(
   const int        rates_total,       // размер входных таймсерий
   const int        prev_calculated,   // количество обработанных баров на предыдущем вызове
   const datetime&  time[],            // массив Time
   const double&    open[],            // массив Open
   const double&    high[],            // массив High
   const double&    low[],             // массив Low
   const double&    close[],           // массив Close
   const long&      tick_volume[],     // массив Tick Volume
   const long&      volume[],          // массив Real Volume
   const int&       spread[]           // массив Spread
   );

Параметры

rates_total

[in]  Размер массива price[] или входных таймсерий, доступных индикатору для расчета. Во втором варианте функции значение параметра соответствует количеству баров на графике, на котором он запущен.

prev_calculated

[in]  Содержит значение, которое вернула функция OnCalculate() на предыдущем вызове. Предназначено для пропуска в расчетах тех баров, которые не изменились с предыдущего запуска этой функции.

begin

[in]  Значение индекса в массиве price[], с которого начинаются значимые данные. Позволяет пропустить в расчетах отсутствующие или начальные данные, для которых нет корректных значений.

price[]

[in]  Массив значений для проведения вычислений. В качестве массива price[] может быть передана одна из ценовых таймсерий либо рассчитанный буфер какого-либо индикатора. Тип данных, которые были переданы на расчет, можно узнать с помощью предопределенной переменной _AppliedTo.

time{}

[in]  Массив со значениями времени открытия баров.

open[]

[in]  Массив со значениями цен открытия.

high[]

[in]  Массив со значениями максимальных цен.

low[]

[in]  Массив со значениями минимальных цен.

close[]

[in]  Массив со значениями цен закрытия.

tick_volume[]

[in]  Массив со значениями тиковых объемов.

volume[]

[in]  Массив со значениями торговых объемов.

spread[]

[in]  Массив со значениями спреда для баров.

Возвращаемое значение

Значение типа int, которое будет передано в качестве параметра prev_calculated при последующем вызове функции.

Примечание

Если функция OnCalculate() возвращает нулевое значение, то в окне DataWindow клиентского терминала значения индикатора не показываются.

Если с момента последнего вызова функции OnCalculate() ценовые данные были изменены (была загружена более глубокая история или были заполнены пропуски истории), то значение входного параметра prev_calculated будет установлено в нулевое значение самим терминалом.

Чтобы определить направление индексации в массивах time[], open[], high[], low[], close[], tick_volume[], volume[] и spread[], необходимо вызывать функцию ArrayGetAsSeries(). Чтобы не зависеть от умолчаний, необходимо безусловно вызывать функцию ArraySetAsSeries() для тех массивов, с которыми предполагается работать.

При использовании первого варианта функции выбор необходимой таймсерии или индикатора в качестве массива price[] осуществляется пользователем на вкладке Parameters при запуске индикатора. Для этого необходимо указать нужный элемент в выпадающем списке поля "Apply to".

Для получения значений пользовательского индикатора из других mql5-программ используется функция iCustom(), возвращающая хэндл индикатора для последующих операций. При этом также можно указать необходимый массив price[] или хэндл другого индикатора. Этот параметр должен передаваться последним в списке входных переменных пользовательского индикатора.

Необходимо использовать связь между значением, возвращаемым функцией OnCalculate(), и вторым входным параметром prev_calculated. Параметр prev_calculated при вызове функции содержит значение, которое вернула функция OnCalculate() на предыдущем вызове. Это позволяет реализовать экономные алгоритмы расчета пользовательского индикатора с тем, чтобы избежать повторных расчетов для тех баров, которые не изменились с предыдущего запуска этой функции.

 

Пример индикатора

//+------------------------------------------------------------------+
//|                                           OnCalculate_Sample.mq5 |
//|                        Copyright 2018, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2000-2024, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property description "Пример вычисления индикатора Momentum"
 
//---- indicator settings
#property indicator_separate_window
#property indicator_buffers 1
#property indicator_plots   1
#property indicator_type1   DRAW_LINE
#property indicator_color1  Blue
//---- входные параметры
input int MomentumPeriod=14; // Период для расчета
//---- индикаторный буфер
double    MomentumBuffer[];
//--- глобальная переменная для хранения периода расчетов
int       IntPeriod;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
void OnInit()
  {
//--- проверим входной параметр 
   if(MomentumPeriod<0)
     {
      IntPeriod=14;
      Print("параметр Период имеет неправльное значение. Для расчетов будет использовано значение ",IntPeriod);
     }
   else
      IntPeriod=MomentumPeriod;
//---- буферы  
   SetIndexBuffer(0,MomentumBuffer,INDICATOR_DATA);
//---- имя индикатора для показа в DataWindow и в подокне
   IndicatorSetString(INDICATOR_SHORTNAME,"Momentum"+"("+string(IntPeriod)+")");
//--- установим номер бара, с которого будет идти отрисовка
   PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,IntPeriod-1);
//--- установим 0.0 в качестве пустого значения, которое не отрисовывается
   PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0.0);
//--- с какой точностью показывать значения индикатора
   IndicatorSetInteger(INDICATOR_DIGITS,2);
  }
//+------------------------------------------------------------------+
//|  Расчет индикатора Momentum                                      |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,     // размер массива price[] 
                const int prev_calculated, // сколько баров обработано ранее
                const int begin,           // откуда начинаются значимые данные 
                const double &price[])     // массив для значения для обработки
  {
//--- стартовая позиция для вычислений
   int StartCalcPosition=(IntPeriod-1)+begin;
//---- если недостаточно данных для расчета
   if(rates_total<StartCalcPosition)
      return(0);  // выходим с нулевым значением - индикатор не рассчитан
//--- correct draw begin
   if(begin>0)
      PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,StartCalcPosition+(IntPeriod-1));
//--- начинаем расчеты, вычислим позицию начала
   int pos=prev_calculated-1;
   if(pos<StartCalcPosition)
      pos=begin+IntPeriod;
//--- основной цикл вычислений
   for(int i=pos;i<rates_total && !IsStopped();i++)
      MomentumBuffer[i]=price[i]*100/price[i-IntPeriod];
//--- выполенение OnCalculate завершено. Вернем новое значение prev_calculated для последующего вызова
   return(rates_total);
  }

Смотри также

ArrayGetAsSeries, ArraySetAsSeries, iCustom, Функции обработки событий, Выполнение программ, События клиентского терминала, Доступ к таймсериям и индикаторам