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

 
Artyom Trishkin #:

1. Из тиков можете сделать любые периоды времени.

2. Откройте код ATR и поглядите на его расчёт.

Ну ведь всё же в доступе протянутой руки.

Здесь нахожу, как расчитывается ATR: https://www.mql5.com/ru/articles/10748

Там есть алгоритм:

"Сначала нужно рассчитать истинный диапазон, который будет наибольшим значением из следующих:

  • Разница текущего High и текущего Low;
  • Разница текущего High и предыдущего Close (абсолютная величина);
  • Разница текущего Low и предыдущего Close (абсолютная величина).

Получается, для расчета индикатора нужны данные о максимумах, минимумах и ценах закрытия. После этого рассчитывается сам средний истинный диапазон."

Про то, как ведет себя индикатор, если количество периодов равно нулю, там не написано. Где-то в другом месте написано? Покажите, если возможно.

Еще. В коде ATR есть строка: "CopyBuffer(ATRDef,0,0,3,PriceArray)". Взято там же: https://www.mql5.com/ru/articles/10748. Можно узнать, почему копируется только 3 элемента? Как определить размер буфера индикатора и скопировать не три, а все элементы? Или это не нужно?


Разработка торговой системы на основе индикатора ATR
Разработка торговой системы на основе индикатора ATR
  • www.mql5.com
В этой статье мы изучим новый технический инструмент, который можно использовать в торговле. Это продолжение серии, в которой мы учимся проектировать простые торговые системы. В этот раз мы будем работать с еще одним популярным техническим индикатором — Средний истинный диапазон (Average True Range, ATR).
 
maxvoronin74 #:

Здесь нахожу, как расчитывается ATR: https://www.mql5.com/ru/articles/10748

Там есть алгоритм:

"Сначала нужно рассчитать истинный диапазон, который будет наибольшим значением из следующих:

  • Разница текущего High и текущего Low;
  • Разница текущего High и предыдущего Close (абсолютная величина);
  • Разница текущего Low и предыдущего Close (абсолютная величина).

Получается, для расчета индикатора нужны данные о максимумах, минимумах и ценах закрытия. После этого рассчитывается сам средний истинный диапазон."

Про то, как ведет себя индикатор, если количество периодов равно нулю, там не написано. Где-то в другом месте написано? Покажите, если возможно.

Еще. В коде ATR есть строка: "CopyBuffer(ATRDef,0,0,3,PriceArray)". Взято там же: https://www.mql5.com/ru/articles/10748. Можно узнать, почему копируется только 3 элемента? Как определить размер буфера индикатора и скопировать не три, а все элементы? Или это не нужно?


Открываете редактор.

Открываете файл по пути \MQL5\Indicators\Examples\ATR.mq5. Там примеры для всех индикаторов есть. И это со времён сотворения так...

Изучаете:

//+------------------------------------------------------------------+
//|                                                          ATR.mq5 |
//|                             Copyright 2000-2024, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright   "Copyright 2000-2024, MetaQuotes Ltd."
#property link        "https://www.mql5.com"
#property description "Average True Range"
//--- indicator settings
#property indicator_separate_window
#property indicator_buffers 2
#property indicator_plots   1
#property indicator_type1   DRAW_LINE
#property indicator_color1  DodgerBlue
#property indicator_label1  "ATR"
//--- input parameters
input int InpAtrPeriod=14;  // ATR period
//--- indicator buffers
double    ExtATRBuffer[];
double    ExtTRBuffer[];

int       ExtPeriodATR;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
void OnInit()
  {
//--- check for input value
   if(InpAtrPeriod<=0)
     {
      ExtPeriodATR=14;
      PrintFormat("Incorrect input parameter InpAtrPeriod = %d. Indicator will use value %d for calculations.",InpAtrPeriod,ExtPeriodATR);
     }
   else
      ExtPeriodATR=InpAtrPeriod;
//--- indicator buffers mapping
   SetIndexBuffer(0,ExtATRBuffer,INDICATOR_DATA);
   SetIndexBuffer(1,ExtTRBuffer,INDICATOR_CALCULATIONS);
//---
   IndicatorSetInteger(INDICATOR_DIGITS,_Digits);
//--- sets first bar from what index will be drawn
   PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,InpAtrPeriod);
//--- name for DataWindow and indicator subwindow label
   string short_name=StringFormat("ATR(%d)",ExtPeriodATR);
   IndicatorSetString(INDICATOR_SHORTNAME,short_name);
   PlotIndexSetString(0,PLOT_LABEL,short_name);
  }
//+------------------------------------------------------------------+
//| Average True Range                                               |
//+------------------------------------------------------------------+
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<=ExtPeriodATR)
      return(0);

   int i,start;
//--- preliminary calculations
   if(prev_calculated==0)
     {
      ExtTRBuffer[0]=0.0;
      ExtATRBuffer[0]=0.0;
      //--- filling out the array of True Range values for each period
      for(i=1; i<rates_total && !IsStopped(); i++)
         ExtTRBuffer[i]=MathMax(high[i],close[i-1])-MathMin(low[i],close[i-1]);
      //--- first AtrPeriod values of the indicator are not calculated
      double firstValue=0.0;
      for(i=1; i<=ExtPeriodATR; i++)
        {
         ExtATRBuffer[i]=0.0;
         firstValue+=ExtTRBuffer[i];
        }
      //--- calculating the first value of the indicator
      firstValue/=ExtPeriodATR;
      ExtATRBuffer[ExtPeriodATR]=firstValue;
      start=ExtPeriodATR+1;
     }
   else
      start=prev_calculated-1;
//--- the main loop of calculations
   for(i=start; i<rates_total && !IsStopped(); i++)
     {
      ExtTRBuffer[i]=MathMax(high[i],close[i-1])-MathMin(low[i],close[i-1]);
      ExtATRBuffer[i]=ExtATRBuffer[i-1]+(ExtTRBuffer[i]-ExtTRBuffer[i-ExtPeriodATR])/ExtPeriodATR;
     }
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
 
maxvoronin74 #:

Здесь нахожу, как расчитывается ATR: https://www.mql5.com/ru/articles/10748

Там есть алгоритм:

"Сначала нужно рассчитать истинный диапазон, который будет наибольшим значением из следующих:

  • Разница текущего High и текущего Low;
  • Разница текущего High и предыдущего Close (абсолютная величина);
  • Разница текущего Low и предыдущего Close (абсолютная величина).

Получается, для расчета индикатора нужны данные о максимумах, минимумах и ценах закрытия. После этого рассчитывается сам средний истинный диапазон."

Про то, как ведет себя индикатор, если количество периодов равно нулю, там не написано. Где-то в другом месте написано? Покажите, если возможно.

Еще. В коде ATR есть строка: "CopyBuffer(ATRDef,0,0,3,PriceArray)". Взято там же: https://www.mql5.com/ru/articles/10748. Можно узнать, почему копируется только 3 элемента? Как определить размер буфера индикатора и скопировать не три, а все элементы? Или это не нужно?

Всё! Не мучайтесь. Вот Вам код для получения значений индикатора ATR:

//+------------------------------------------------------------------+
//| Input variables                                                  |
//+------------------------------------------------------------------+
input ushort Averaging_Period=14; // Период усреднения индикатора ATR

int Handle_ATR;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   Handle_ATR=iATR(_Symbol, PERIOD_CURRENT, Averaging_Period); // получим хэндл индикатора ATR
   if(Handle_ATR==INVALID_HANDLE)
     {
      Print("Некорректный хэндл индикатора ATR!");
      return(INIT_FAILED);
     }
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   IndicatorRelease(Handle_ATR);
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   double atr_array_value[]; // создадим массив для значений индикатора ATR
   ArraySetAsSeries(atr_array_value, true); // зададим индексацию элементов массива, как в таймсериях
   int copy_buffer = CopyBuffer(Handle_ATR, 0, 0, 3, atr_array_value); // копируем в массив данные указанного буфера индикатора ATR
   if(copy_buffer > 0) // если скопированные данные больше нуля
      Print("Значение ATR = ", atr_array_value[0]); // выведем на печать
  }
//+------------------------------------------------------------------+

Дальше, уж будьте добры, сами.

С уважением, Владимир.

 
MrBrooklin #:

Всё! Не мучайтесь. Вот Вам код для получения значений индикатора ATR:

Дальше, уж будьте добры, сами.

С уважением, Владимир

Не правлильно.

Вы в OnInit() проверяете хендл и выходите из обработчика, если хендл не валидный (а он нулевой в лучшем случае. В худшем - там мусор, так как Handle_ATR не инициализирована). Создаёте же индикатор с присвоением хендлу корректного значения только в OnTick() - а зачем там? В OnInit() создавайте индикатор и получайте его хендл. В OnTick() обращайтесь по хендлу за данными индикатора.

 
Artyom Trishkin #:

Не правлильно.

Вы в OnInit() проверяете хендл и выходите из обработчика, если хендл не валидный (а он нулевой в лучшем случае. В худшем - там мусор, так как Handle_ATR не инициализирована). Создаёте же индикатор с присвоением хендлу корректного значения только в OnTick() - а зачем там? В OnInit() создавайте индикатор и получайте его хендл. В OnTick() обращайтесь по хендлу за данными индикатора.

Спасибо, Артём. Ещё не до конца проснулся. )) Сейчас исправлю.

С уважением, Владимир.

P.S. Исправил код.
 
MrBrooklin #:
double atr_value=NormalizeDouble(atr_array_value[0], 5); // нормализуем значения индикатора ATR
А зачем? Какой смысл?
 
Artyom Trishkin #:
А зачем? Какой смысл?

Говорю же, спросонья написал. )) Поправил.

С уважением, Владимир.

 

Исправленный вариант:

//+------------------------------------------------------------------+
//| Input variables                                                  |
//+------------------------------------------------------------------+
input ushort Averaging_Period=14; // Период усреднения индикатора ATR

int Handle_ATR;
double atr_array_value[]; // создадим массив для значений индикатора ATR
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   Handle_ATR=iATR(_Symbol, PERIOD_CURRENT, Averaging_Period); // получим хэндл индикатора ATR
   if(Handle_ATR==INVALID_HANDLE)
     {
      Print("Некорректный хэндл индикатора ATR!");
      return(INIT_FAILED);
     }
   ArraySetAsSeries(atr_array_value, true); // зададим индексацию элементов массива, как в таймсериях
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   IndicatorRelease(Handle_ATR);
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   int copy_buffer = CopyBuffer(Handle_ATR, 0, 0, 3, atr_array_value); // копируем в массив данные указанного буфера индикатора ATR
   if(copy_buffer > 0) // если скопированные данные больше нуля
      Print("Значение ATR = ", DoubleToString(atr_array_value[0], 5)); // выведем на печать
  }
//+------------------------------------------------------------------+

С уважением, Владимир.

 

а ничего так,что  SYMBOL_PRICE_VOLATILITY и ATR в общем разные вещи ?

как в школе, проверяем в чём измеряется и от чего считается...


первый это справочный параметр из спецификации (или транслируемый DC), не связан с таймфреймами и измеряемый в %

второй статистический за произвольный период конкретного таймфрейма, измеряемый в единицах котировки


для привычного Форекс SYMBOL_PRICE_VOLATILITY не используется и не транслируется. Но у нас тут не только Форекс. 

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

 
Maxim Kuznetsov #:
а ничего так,что  SYMBOL_PRICE_VOLATILITY и ATR в общем разные вещи ?

Максим, хорошо, что отреагировали на данную тему. Честно говоря, сам вообще далёк от темы волатильности и, до сих пор никак не могу понять на кой ляд эта волатильность нужна, а также почему эту тему много раз поднимают, но до конца не раскрывают. Единственное, что понял, это якобы существует зависимость разворота ценового графика при значительном повышении волатильности. Кроме того, прочитал несколько тем, связанных с применением индикатора волатильности ATR, но установив его на график, ни чего такого ценного не увидел. Может Вы в сжатой форме подскажете, чем так ценна волатильность для трейдера? Буду очень признателен.

С уважением, Владимир.