//+------------------------------------------------------------------+ //| GRI.mq5 | //| Copyright 2025, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2025, MetaQuotes Ltd." #property link "https://www.mql5.com" #property version "1.00" #property indicator_separate_window #property indicator_buffers 1 #property indicator_plots 1 //--- plot GRI #property indicator_label1 "GRI" #property indicator_type1 DRAW_LINE #property indicator_color1 clrDodgerBlue #property indicator_style1 STYLE_SOLID #property indicator_width1 1 //--- input parameters input(name="ChaoticPeriod") int InpPeriod = 5; // Период расчёта //--- indicator buffers double BufferGRI[]; //--- global variables int ExtPeriod; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- indicator buffers mapping SetIndexBuffer(0,BufferGRI,INDICATOR_DATA); ArraySetAsSeries(BufferGRI,true); // буфер как таймсерия //--- Устанавливаем параметры индикатора ExtPeriod=(InpPeriod<2 ? 2 : InpPeriod); // корректируем период расчёта string short_name=StringFormat("GRI(%d)",ExtPeriod); // определяем короткое имя IndicatorSetString(INDICATOR_SHORTNAME,short_name); // устанавливаем короткое имя IndicatorSetInteger(INDICATOR_DIGITS,_Digits); // точность отображения IndicatorSetDouble(INDICATOR_MINIMUM,0.0); // Минимальное значение шкалы //--- Всё успешно return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Custom indicator iteration function | //+------------------------------------------------------------------+ int OnCalculate(const int32_t rates_total, const int32_t 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 int32_t &spread[]) { //--- Массив close - как таймсерия ArraySetAsSeries(close,true); //--- Проверка количества доступных баров if(rates_total1) { limit=rates_total-ExtPeriod-1; // расчёт начинаем от начала исторических данных ArrayInitialize(BufferGRI,EMPTY_VALUE); // инициализируем буфер индикатора пустым значением } //--- Основной цикл for(int i=limit;i>=0;i--) { //--- рассчитываем диапазон цен закрытия за ExtPeriod баров int mx=ArrayMaximum(close,i,ExtPeriod); int mn=ArrayMinimum(close,i,ExtPeriod); if(mx==WRONG_VALUE || mn==WRONG_VALUE) return 0; //--- максимальное и минимальное значения Close за период ExtPeriod double max=close[mx]; double min=close[mn]; double range = max-min; //--- рассчитаем и запишем в буфер значение "хаотичности" за ExtPeriod баров BufferGRI[i] = (MathLog(1.0 + range)/MathLog((double)ExtPeriod))/_Point; // Диапазон значений от нуля и выше } //--- return value of prev_calculated for next call return(rates_total); } //+------------------------------------------------------------------+