English
preview
За пределами GARCH (Часть VIII): Библиотека MMAR и ее использование в советнике

За пределами GARCH (Часть VIII): Библиотека MMAR и ее использование в советнике

MetaTrader 5 — Торговые системы |
35 0
Muhammad Minhas Qamar
Muhammad Minhas Qamar

Введение

В предыдущих четырех статьях мы с нуля создали библиотеку MMAR. В четвертой части рассматривались анализ разбиений и извлечение масштабных характеристик; в пятой части — подгонка спектра и выбор распределения каскада; в шестой части — модуль моделирования; в седьмой части — прогнозирование волатильности методом Монте-Карло с доверительными интервалами. Каждый модуль был разработан, протестирован и проверен независимо от остальных. Теперь мы объединяем их.

Эта статья завершает серию двумя компонентами: (1) фасадный класс CMMAR, предоставляющий API для подгонки и прогнозирования для четырех модулей; (2) рабочий советник MetaTrader 5, который загружает данные, подгоняет модель, формирует прогноз волатильности и выводит результаты. К концу статьи у вас будет готова полноценная автономная библиотека, которую любой советник может подключить одной строкой кода и использовать тремя вызовами функций.

Мы рассмотрим следующие темы:

  1. Фасадный класс CMMAR
  2. Пайплайн подгонки модели
  3. Прогнозирование и моделирование траекторий
  4. Демонстрационный советник
  5. Результаты и интерпретация
  6. Заключение


Фасадный класс CMMAR

Паттерн "Фасад" предоставляет пользователям единую точку входа в сложную подсистему. Класс CMMAR объединяет CPartitionAnalysis, CSpectrumFitter, CMonteCarlo и CSimulationEngine за интерфейсом, не требующим знания внутренних взаимодействий модулей. Пользователь передает доходности, вызывает Fit(), затем Forecast(). Все остальное — извлечение tau(q), преобразование Лежандра, конкурентный отбор распределений и адаптивная глубина каскада — выполняется внутри:

#ifndef MMAR_MQH
#define MMAR_MQH

#include "MMARConstants.mqh"
#include "PartitionAnalysis.mqh"
#include "SpectrumFitter.mqh"
#include "MonteCarlo.mqh"

//+------------------------------------------------------------------+
//| CMMAR class                                                      |
//+------------------------------------------------------------------+
class CMMAR
  {
private:
   CPartitionAnalysis m_partition;
   CSpectrumFitter    m_spectrum;

   MMARParams         m_params;
   ENUM_MMAR_STATUS   m_status;

   int               m_cascade_b;
   double            m_dt_spacing;

public:
                     CMMAR(void);
                    ~CMMAR(void);

   //--- Configuration (call before Fit)
   void              SetPartitionConfig(int dt_min, int dt_max, double spacing = 1.1);
   void              SetMomentConfig(double q_min, double q_max, double q_step);
   void              SetCascadeBase(int b)  { m_cascade_b = MathMax(2, b); }
   void              SetSeed(int seed)      { MathSrand(seed); }

   //--- Main pipeline
   bool              Fit(const double &returns[], int n_returns);

   //--- Forecasting
   bool              Forecast(int horizon_bars, int n_simulations, MMARForecast &result);

   //--- Single path generation
   bool              SimulatePath(int n_points, double &path[], double &returns[]);

   //--- Diagnostics
   MMARParams        GetParams(void)    { return m_params; }
   ENUM_MMAR_STATUS  GetStatus(void)    { return m_status; }
   bool              IsFitted(void)     { return m_status == MMAR_STATUS_FITTED; }
   bool              IsMultifractal(void) { return m_params.is_multifractal; }
   string            GetDistributionName(void);
  };

Открытый интерфейс состоит из трех слоев. Слой конфигурации (SetPartitionConfig, SetMomentConfig, SetCascadeBase, SetSeed) позволяет выполнить тонкую настройку перед подгонкой модели. Все параметры имеют разумные значения по умолчанию, поэтому этот слой необязателен. Обратите внимание: SetCascadeBase и SetSeed — простые inline-методы: SetCascadeBase ограничивает коэффициент ветвления значением не ниже 2, а SetSeed напрямую вызывает MathSrand для воспроизводимой генерации случайных чисел. Слой пайплайна (Fit, Forecast, SimulatePath) выполняет основную работу. Слой диагностики (GetParams, GetStatus, IsFitted, IsMultifractal, GetDistributionName) предоставляет доступ к внутреннему состоянию для логирования, принятия решений или отображения.

Следует подчеркнуть, что фасад и все базовые модули используют только стандартную библиотеку MetaTrader 5. В анализе разбиений для регрессии МНК используются встроенные типы матриц и векторов. Для подгонки спектра используется оптимизатор BLEIC из библиотеки ALGLIB для нелинейной подгонки с ограничениями. В модуле моделирования используются реализации FFT и разложения Холецкого из ALGLIB, а также библиотека Math\Stat для генерации случайных чисел. Внешние DLL, мосты Python и сторонние зависимости не требуются. Все это входит в состав каждой установки MetaTrader 5. Благодаря этому библиотека полностью переносима между любыми брокерами и VPS: если работает MetaTrader 5, работает и библиотека MMAR.

Класс отслеживает состояние с помощью перечисления ENUM_MMAR_STATUS, отражающего ход выполнения пайплайна:

  • MMAR_STATUS_NOT_FITTED — начальное состояние, данные ещё не обработаны.
  • MMAR_STATUS_PARTITION_ONLY — анализ разбиений завершился успешно, но подгонка спектра не удалась. Доступны показатель Херста и диагностика мультифрактальности, однако прогнозирование невозможно.
  • MMAR_STATUS_FITTED — полный пайплайн завершился успешно. Анализ разбиений и подгонка спектра завершены. Прогнозирование доступно.
  • MMAR_STATUS_ERROR — во время анализа разбиений произошла критическая ошибка. Результаты отсутствуют.

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

Рисунок 1 анимированно показывает, как фасад CMMAR объединяет четыре внутренних модуля и как данные проходят через каждый вызов API:

Рис. 1. Фасад CMMAR объединяет четыре модуля за простым API. Fit() координирует анализ разбиений и подгонку спектра; Forecast() передает выполнение CMonteCarlo, который внутри создает экземпляры CSimulationEngine. Пользователь взаимодействует только с высокоуровневым классом CMMAR.


Пайплайн подгонки модели

Метод Fit() последовательно координирует два аналитических этапа: анализ разбиений для извлечения tau(q) и H, затем подгонку спектра для выбора распределения каскада. Метод заполняет структуру MMARParams всеми данными, необходимыми последующим модулям:

//+------------------------------------------------------------------+
//| Fit - Run partition analysis + spectrum fitting                  |
//+------------------------------------------------------------------+
bool CMMAR::Fit(const double &returns[], int n_returns)
  {
   m_status = MMAR_STATUS_NOT_FITTED;
   ZeroMemory(m_params);

//--- Stage 1: Partition Analysis
   if(!m_partition.Init(returns, n_returns))
     {
      Print("MMAR::Fit - partition init failed");
      m_status = MMAR_STATUS_ERROR;
      return false;
     }

   if(!m_partition.Analyze())
     {
      Print("MMAR::Fit - partition analysis failed");
      m_status = MMAR_STATUS_ERROR;
      return false;
     }

   m_params.H = m_partition.GetH();
   m_params.sample_volatility = m_partition.GetSampleVolatility();
   m_params.mean_r_squared = m_partition.GetMeanRSquared();
   m_params.multifractal_score = m_partition.GetMultifractalScore();
   m_params.is_multifractal = m_partition.IsMultifractal();
   m_partition.GetTauQ(m_params.tau_q, m_params.q_values);

//--- Stage 2: Spectrum Fitting
   double tau[], q_vals[];
   m_partition.GetTauQ(tau, q_vals);
   int n_q = m_partition.GetNumQ();

   if(!m_spectrum.Init(q_vals, tau, n_q, m_params.H))
     {
      Print("MMAR::Fit - spectrum init failed (partition results available)");
      m_status = MMAR_STATUS_PARTITION_ONLY;
      return false;
     }

   if(!m_spectrum.ComputeSpectrum())
     {
      Print("MMAR::Fit - spectrum computation failed (partition results available)");
      m_status = MMAR_STATUS_PARTITION_ONLY;
      return false;
     }

   if(!m_spectrum.FitAllDistributions())
     {
      Print("MMAR::Fit - distribution fitting failed (partition results available)");
      m_status = MMAR_STATUS_PARTITION_ONLY;
      return false;
     }

   m_params.dist_type = m_spectrum.GetBestDistribution();
   m_spectrum.GetBestParams(m_params.dist_params);

//--- Find alpha_0 (spectrum peak)
   double alpha[], f_alpha[];
   m_spectrum.GetSpectrum(alpha, f_alpha);
   int n_spec = m_spectrum.GetSpectrumSize();
   m_params.alpha_0 = alpha[0];
   double f_max = f_alpha[0];
   for(int i = 1; i < n_spec; i++)
     {
      if(f_alpha[i] > f_max)
        {
         f_max = f_alpha[i];
         m_params.alpha_0 = alpha[i];
        }
     }

   m_status = MMAR_STATUS_FITTED;
   return true;
  }

Метод последовательно заполняет структуру MMARParams. После анализа разбиений доступны H, sample_volatility, mean_r_squared и диагностические показатели мультифрактальности. После подгонки спектра добавляются тип распределения, его параметры и пиковое значение alpha_0. Извлечение alpha_0 в конце — поиск значения alpha, при котором f(alpha) достигает максимума, — дает сводную статистику, полезную для отчетности, но не строго необходимую для прогнозирования: параметры распределения уже содержат всю информацию, нужную генератору каскада.

Обратите внимание: при каждом сбое на этапе подгонки спектра устанавливается статус MMAR_STATUS_PARTITION_ONLY, а не MMAR_STATUS_ERROR. Это означает, что советник может проверить статус и сделать вывод: "данные не обладают выраженной мультифрактальностью, подгонка спектра не удалась, но показатель Херста все еще доступен — возможно, для этого периода стоит использовать более простую модель".

На рисунке 2 показан двухэтапный пайплайн. На этапе 1 из необработанных доходностей получают H, выборочную волатильность, R², оценку мультифрактальности и кривую tau(q). На этапе 2 выполняется подгонка четырех распределений-кандидатов и выбирается наилучшее из них — биномиальное распределение в прогоне по EURUSD — для заполнения MMARParams. Анимация также показывает последовательность статусов: ERROR — если этап 1 завершился сбоем; PARTITION_ONLY — если сбой произошел только на этапе 2; FITTED — если оба этапа завершились успешно.

Рис. 2. Пайплайн Fit(): этап 1 извлекает масштабные свойства, этап 2 выбирает лучшее распределение каскада, а при сбое любого из этапов система корректно переходит в режим ограниченной функциональности.


Прогнозирование и моделирование траекторий

После подгонки модели метод Forecast() напрямую делегирует выполнение классу CMonteCarlo, созданному в седьмой части:

//+------------------------------------------------------------------+
//| Forecast - Monte Carlo volatility forecast                       |
//+------------------------------------------------------------------+
bool CMMAR::Forecast(int horizon_bars, int n_simulations, MMARForecast &result)
  {
   if(m_status != MMAR_STATUS_FITTED)
     {
      Print("MMAR::Forecast - model not fitted");
      return false;
     }

   CMonteCarlo mc;
   if(!mc.Init(m_params.H, m_params.dist_type, m_params.dist_params,
               m_params.sample_volatility, n_simulations, horizon_bars, m_cascade_b))
     {
      Print("MMAR::Forecast - Monte Carlo init failed");
      return false;
     }

   if(!mc.Run())
     {
      Print("MMAR::Forecast - Monte Carlo run failed");
      return false;
     }

   result = mc.GetForecast();
   return true;
  }

Этот метод создает новый экземпляр CMonteCarlo, передает ему все подогнанные параметры, запускает симуляции и копирует результат прогноза в структуру вызывающей стороны. Проверка статуса в начале гарантирует, что прогнозирование не будет выполняться для неподогнанной модели.

Для пользователей, которым нужны отдельные синтетические траектории (для визуализации, анализа сценариев или передачи в другие модели), метод SimulatePath() предоставляет прямой доступ к модулю моделирования:

//+------------------------------------------------------------------+
//| SimulatePath - Generate a single MMAR sample path                |
//+------------------------------------------------------------------+
bool CMMAR::SimulatePath(int n_points, double &path[], double &returns[])
  {
   if(m_status != MMAR_STATUS_FITTED)
     {
      Print("MMAR::SimulatePath - model not fitted");
      return false;
     }

   int cascade_k = (int)MathCeil(MathLog((double)(n_points + 1)) / MathLog((double)m_cascade_b));
   int actual_n = (int)MathPow(m_cascade_b, cascade_k);

   CSimulationEngine engine;
   if(!engine.Init(m_params.H, m_params.dist_type, m_params.dist_params,
                   m_params.sample_volatility, m_cascade_b, cascade_k))
      return false;

   if(!engine.Generate())
      return false;

   engine.GetProcess(path);

   int n_ret;
   engine.GetReturns(returns, n_ret);

   if(actual_n > n_points)
     {
      ArrayResize(path, n_points);
      ArrayResize(returns, MathMax(0, n_points - 1));
     }

   return true;
  }

Этот метод использует ту же логику адаптивной глубины каскада, что и модуль Монте-Карло: определяется минимальное k, покрывающее требуемое число точек, генерируется полная траектория b^k, затем она усекается до требуемой длины. Вызывающая сторона получает ряд как процесс ценовых уровней, так и лог-доходности и может использовать и то, и другое.

Вспомогательная функция GetDistributionName() преобразует перечисление в удобочитаемую строку для логирования:

//+------------------------------------------------------------------+
//| GetDistributionName - Human-readable name of fitted distribution |
//+------------------------------------------------------------------+
string CMMAR::GetDistributionName(void)
  {
   switch(m_params.dist_type)
     {
      case MMAR_DIST_NORMAL:
         return "Normal";
      case MMAR_DIST_BINOMIAL:
         return "Binomial";
      case MMAR_DIST_POISSON:
         return "Poisson";
      case MMAR_DIST_GAMMA:
         return "Gamma";
     }
   return "Unknown";
  }


Демонстрационный советник

При наличии готового фасадного класса создать советник, использующий библиотеку MMAR, несложно. Демонстрационный советник подгоняет модель при инициализации и выполняет полный прогноз волатильности. В рабочей среде модель следует периодически подгонять заново, например ежедневно или еженедельно, и использовать прогноз для корректировки размера позиции, расстояния до стоп-лосса или частоты торговли:

//+------------------------------------------------------------------+
//|                                                     MMAR Demo EA |
//|                      Copyright 2026, MMQ - Muhammad Minhas Qamar |
//|                           https://www.mql5.com/ru/articles/22539 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2026, Muhammad Minhas Qamar - MMQ"
#property link      "https://www.mql5.com/ru/articles/22539"
#property version   "1.00"
#property strict

#include <MMAR\MMAR.mqh>

input int    InpBars           = 50000;
input int    InpForecastBars   = 7200;
input int    InpSimulations    = 1000;
input int    InpCascadeB       = 2;
input int    InpSeed           = 42;

input double InpQMin           = 0.01;
input double InpQMax           = 30.0;
input double InpQStep          = 0.5;
input int    InpDtMin          = 1;
input int    InpDtMax          = 150;
input double InpDtSpacing      = 1.1;

CMMAR mmar;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
void OnInit()
  {
   PrintFormat("========================================");
   PrintFormat("  MMAR Demo EA");
   PrintFormat("  Symbol: %s | Period: %s", _Symbol, EnumToString(_Period));
   PrintFormat("========================================");

//--- Load historical data
   double close[];
   int copied = CopyClose(_Symbol, _Period, 0, InpBars, close);
   if(copied < 1000)
     {
      PrintFormat("Not enough bars: %d (need 1000+)", copied);
      return;
     }
   PrintFormat("Loaded %d bars", copied);

//--- Compute log returns
   double returns[];
   int n_returns = copied - 1;
   ArrayResize(returns, n_returns);
   for(int i = 0; i < n_returns; i++)
      returns[i] = MathLog(close[i + 1] / close[i]);

//--- Configure and fit
   mmar.SetSeed(InpSeed);
   mmar.SetPartitionConfig(InpDtMin, InpDtMax, InpDtSpacing);
   mmar.SetMomentConfig(InpQMin, InpQMax, InpQStep);
   mmar.SetCascadeBase(InpCascadeB);

   uint t0 = GetTickCount();

   if(!mmar.Fit(returns, n_returns))
     {
      if(mmar.GetStatus() == MMAR_STATUS_PARTITION_ONLY)
        {
         MMARParams params = mmar.GetParams();
         PrintFormat("\nPartial fit (spectrum fitting failed):");
         PrintFormat("  H = %.4f", params.H);
         PrintFormat("  Sample vol = %.6f", params.sample_volatility);
         PrintFormat("  Mean R2 = %.4f", params.mean_r_squared);
         PrintFormat("  Score = %d/9 | Multifractal: %s",
                   params.multifractal_score,
                   params.is_multifractal ? "YES" : "NO");
         Print("Cannot forecast without distribution fit.");
        }
      else
         Print("MMAR fitting failed completely.");
      return;
     }

   uint t_fit = GetTickCount() - t0;

//--- Print fit results
   MMARParams params = mmar.GetParams();

   PrintFormat("\n--- Model Fit (%u ms) ---", t_fit);
   PrintFormat("H (Hurst):      %.4f", params.H);
   PrintFormat("Distribution:   %s", mmar.GetDistributionName());
   PrintFormat("Alpha_0:        %.4f", params.alpha_0);
   PrintFormat("Sample vol:     %.6f", params.sample_volatility);
   PrintFormat("Mean R2:        %.4f", params.mean_r_squared);
   PrintFormat("Multifractal:   %s (score %d/9)",
               params.is_multifractal ? "YES" : "NO",
               params.multifractal_score);

   PrintFormat("Dist params:");
   switch(params.dist_type)
     {
      case MMAR_DIST_NORMAL:
         PrintFormat("  alpha_0 = %.6f", params.dist_params[0]);
         break;
      case MMAR_DIST_BINOMIAL:
         PrintFormat("  alpha_min = %.6f", params.dist_params[0]);
         PrintFormat("  alpha_max = %.6f", params.dist_params[1]);
         break;
      case MMAR_DIST_POISSON:
         PrintFormat("  alpha_0 = %.6f", params.dist_params[0]);
         break;
      case MMAR_DIST_GAMMA:
         PrintFormat("  alpha_0 = %.6f", params.dist_params[0]);
         PrintFormat("  gamma   = %.6f", params.dist_params[1]);
         break;
     }

//--- Forecast
   t0 = GetTickCount();

   MMARForecast forecast;
   if(!mmar.Forecast(InpForecastBars, InpSimulations, forecast))
     {
      Print("Forecast failed");
      return;
     }

   uint t_forecast = GetTickCount() - t0;

   PrintFormat("\n--- Volatility Forecast (%u ms) ---", t_forecast);
   PrintFormat("Horizon:     %d bars", forecast.forecast_horizon);
   PrintFormat("Simulations: %d", forecast.n_simulations);
   PrintFormat("Mean vol:    %.6f", forecast.mean_volatility);
   PrintFormat("Median vol:  %.6f", forecast.median_volatility);
   PrintFormat("Std vol:     %.6f", forecast.std_volatility);
   PrintFormat("95%% CI:      [%.6f, %.6f]", forecast.ci_lower, forecast.ci_upper);
   PrintFormat("Historical:  %.6f", params.sample_volatility);
   PrintFormat("Ratio:       %.2f (forecast / historical)", forecast.mean_volatility / params.sample_volatility);

//--- Summary
   PrintFormat("\n========================================");
   PrintFormat("  Total time: %u ms", t_fit + t_forecast);
   PrintFormat("========================================");
  }
//+------------------------------------------------------------------+

Структура советника намеренно минимальна. Вся работа выполняется в OnInit(): модель подгоняется один раз при загрузке советника. Класс CMMAR освобождает ресурсы в своем деструкторе. В рабочем советнике прогноз сохраняется, модель периодически подгоняется заново, например на первом тике каждого нового дня, а прогнозные значения используются для торговых решений в OnTick().

Схема использования сводится к пяти строкам содержательного кода:

//--- Minimal MMAR usage pattern
CMMAR mmar;
mmar.Fit(returns, n_returns);

MMARForecast forecast;
mmar.Forecast(7200, 1000, forecast);

//--- forecast.mean_volatility is now your estimate

За этими двумя вызовами выполняется все остальное: загрузка данных (50 000 баров), вычисление функции разбиения (61 порядок моментов), преобразование Лежандра, выбор распределения и 1 000 симуляций Монте-Карло с траекториями из 8 192 точек.


Результаты и их интерпретация

Запуск демонстрационного советника на EURUSD на таймфрейме M10 с 50 000 барами, горизонтом 7 200 баров и 1 000 симуляциями дает следующие результаты:

========================================
  MMAR Demo EA
  Symbol: EURUSD | Period: PERIOD_M10
========================================
Loaded 50000 bars
Multifractality check: concavity=1 linearity=1 variation=1 total=3/9
SpectrumFitter: 58 spectrum points, alpha=[0.1351, 0.5149],
                peak at alpha_0=0.5149 f=0.9923
Fitting spectrum to 4 distributions...
  Normal:   SSE=69.033271  alpha_0=0.514942
  Binomial: SSE=0.123991  alpha_min=0.188628  alpha_max=0.772413
  Poisson:  SSE=10.212081  alpha_0=0.514942
  Gamma:    SSE=0.178587  alpha_0=0.514942  gamma=1.244125
BEST FIT: Binomial (SSE=0.123991, RMSE=0.046236)

--- Model Fit (422 ms) ---
H (Hurst):      0.4817
Distribution:   Binomial
Alpha_0:        0.5149
Sample vol:     0.000419
Mean R2:        0.8838
Multifractal:   NO (score 3/9)
Dist params:
  alpha_min = 0.188628
  alpha_max = 0.772413
MonteCarlo: 1000 simulations, horizon=7200 bars, k=13, N=8192
MonteCarlo complete: 1000 sims in 8984 ms
  Mean vol: 0.000339 | Std: 0.000008 | Median: 0.000339
  95% CI: [0.000322, 0.000353]

--- Volatility Forecast (8984 ms) ---
Horizon:     7200 bars
Simulations: 1000
Mean vol:    0.000339
Median vol:  0.000339
Std vol:     0.000008
95% CI:      [0.000322, 0.000353]
Historical:  0.000419
Ratio:       0.81 (forecast / historical)

========================================
  Total time: 9406 ms
========================================

Разберем, что эти результаты означают для торговой системы:

Диагностика модели. Показатель Херста, равный 0,4817, немного ниже 0,5, что указывает на очень слабую антиперсистентность — прошлые тренды слабо склонны к развороту на таймфрейме M10. Оценка мультифрактальности 3/9 ниже порогового значения 5, поэтому данное окно из 50 000 баров не демонстрирует выраженной мультифрактальности. Тем не менее подгонка спектра успешна: биномиальная модель дает отличный RMSE 0,046, поэтому модель все еще может формировать осмысленные прогнозы. Флаг мультифрактальности — диагностический признак, а не ограничение: библиотека в любом случае продолжает подгонку модели.

Прогноз. MMAR прогнозирует будущую волатильность 0,000339 на бар, что на 19% ниже исторического значения 0,000419. 95-процентный доверительный интервал [0,000322; 0,000353] узок — модель высоко уверена в своей оценке. На практике при расчете размера позиции по ожидаемой волатильности MMAR допускает немного больший размер позиции, чем наивный подход на основе исторической волатильности, поскольку ближайшее будущее прогнозируется более спокойным, чем недавнее прошлое.

Производительность. Общее время 9,4 секунды в основном определяется 1 000 симуляций Монте-Карло: 8,98 секунды, или около 9 мс на симуляцию. Этап подгонки занимает всего 422 мс. Для рабочего советника с ежедневной повторной подгонкой это вполне приемлемо: даже на скромном VPS 9-секундное вычисление раз в день незаметно. Если результат нужен быстрее, например при почасовой повторной подгонке, сокращение числа симуляций до 100 уменьшает время Монте-Карло до менее чем 1 секунды, сохраняя достаточно узкий доверительный интервал.

Коэффициент. Соотношение прогнозной и исторической волатильности 0,81 означает, что, по оценке модели, недавняя волатильность превышала средний уровень относительно структурной нормы. В этом главное преимущество MMAR перед GARCH: оценка основана на масштабной структуре используемых данных (долгосрочном свойстве), а не на квадратах недавних доходностей (краткосрочном свойстве). Поэтому модель менее чувствительна к всплескам волатильности. Модель GARCH, только что зафиксировавшая высокую волатильность, прогнозировала бы ее сохранение с медленным возвратом к среднему. MMAR, напротив, показывает: "структурные свойства этих данных указывают на более низкий долгосрочный уровень волатильности".

Рисунок 3 наглядно показывает это сравнение. Историческая волатильность и прогноз MMAR показаны рядом — снижение на 19% видно сразу. Узкий 95-процентный доверительный интервал показывает высокую уверенность модели, а концептуальное сопоставление внизу отражает фундаментальное различие: GARCH реагирует на недавние шоки, тогда как MMAR привязывает оценку к долгосрочной масштабной структуре данных.

Рис. 3. Историческая волатильность и прогноз MMAR: модель прогнозирует волатильность на 19% ниже с узким доверительным интервалом, что отражает ее структурный, а не реактивный подход к оценке.


Заключение

Эта статья завершает серию "За пределами GARCH". В восьми частях мы прошли путь от теоретических основ мультифрактального анализа (часть 1) через эмпирическую проверку и прототипирование на Python (части 2-3) до полноценной нативной библиотеки MQL5 (части 4-8). В результате получилась самодостаточная система, которая:

  • обнаруживает мультифрактальную структуру рыночных данных с помощью анализа функции разбиения и строгой статистической диагностики (часть 4);
  • подгоняет спектр сингулярностей к четырем теоретическим распределениям с помощью нелинейной оптимизации с ограничениями (часть 5);
  • моделирует синтетические траектории MMAR на основе мультипликативных каскадов и фракционного броуновского движения с использованием FFT и метода Холецкого (часть 6);
  • прогнозирует волатильность методом Монте-Карло, формируя точечные оценки с границами неопределенности (часть 7);
  • объединяет все компоненты в единый фасадный интерфейс с API из трех вызовов: настройка, подгонка модели, прогнозирование (эта статья).

Библиотека спроектирована с учетом расширяемости. Несколько логичных следующих шагов:

  • Периодическая повторная подгонка: вызывайте Fit() на скользящем окне, например ежедневно, чтобы отслеживать изменение параметров модели во времени. Отслеживайте стабильность H, изменение распределения с лучшей подгонкой и колебания оценки мультифрактальности.
  • Расчет размера позиции: используйте доверительный интервал прогноза для динамической корректировки размера лотов — уменьшайте позиции при широком интервале и увеличивайте при узком.
  • Обнаружение режима: используйте оценку мультифрактальности и показатель Херста как индикаторы режима. Скачок H с 0,48 до 0,55 может сигнализировать о переходе от поведения с возвратом к среднему к следованию за трендом.
  • Анализ на нескольких таймфреймах: выполняйте анализ разбиений одновременно на нескольких таймфреймах и сравнивайте показатели Херста и оценки мультифрактальности для более полной характеристики рынка.

MMAR — не торговая стратегия, а модель волатильности. MMAR показывает вероятную величину движения рынка, но не его направление. Ее использование в сочетании с моделью направления движения — фильтрами тренда, сигналами возврата к среднему или классификаторами машинного обучения — может обеспечить реальное торговое преимущество. Прогноз волатильности помогает определить допустимый риск: "При заданной уверенности в направлении движения какой риск следует принять?" Именно на этот вопрос отвечает библиотека.

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


Получение исходного кода через MQL5 Algo Forge

Все исходные файлы прикреплены ниже к этой статье, но полный репозиторий также доступен на MQL5 Algo Forge — платформе сообщества на базе Git для публикации торговых проектов и совместной работы над ними.

В таблице ниже перечислены все файлы полной библиотеки MMAR, накопленные за восемь частей серии:

Имя файла
Описание
MQL5\Include\MMAR\MMARConstants.mqh
Общие перечисления, структуры и определения типов библиотеки MMAR (часть 4)
MQL5\Include\MMAR\OLS.mqh
Регрессия методом наименьших квадратов через псевдообратную матрицу на основе SVD с полным набором диагностических показателей (часть 4)
MQL5\Include\MMAR\HurstGHE.mqh
Оценщик обобщенного показателя Херста, резервный метод (часть 4)
MQL5\Include\MMAR\PartitionAnalysis.mqh
Мультифрактальный анализ функции разбиения с диагностикой масштабирования (часть 4)
MQL5\Include\MMAR\SpectrumFitter.mqh
Вычисление мультифрактального спектра и подгонка к четырем распределениям методом оптимизации BLEIC (часть 5)
MQL5\Include\MMAR\SimulationEngine.mqh
Модуль моделирования MMAR: мультипликативный каскад, генерация FBM (метод Дэвиса — Харта и разложение Холецкого) и композиция с деформацией времени (часть 6)
MQL5\Include\MMAR\MonteCarlo.mqh
Прогнозирование волатильности методом Монте-Карло: выполняет N симуляций MMAR и вычисляет среднее, медиану, стандартное отклонение и 95%-ный доверительный интервал (часть 7)
MQL5\Include\MMAR\MMAR.mqh
Высокоуровневый фасадный класс: API для подгонки и прогнозирования — Fit() и Forecast() (часть 8)
MQL5\Scripts\MMAR\MMAR_PartitionTest.mq5
Тестовый скрипт для анализа разбиений на реальных рыночных данных (часть 4)
MQL5\Scripts\MMAR\MMAR_SpectrumTest.mq5
Тестовый скрипт полного пайплайна анализа разбиений и подгонки спектра на реальных рыночных данных (часть 5)
MQL5\Scripts\MMAR\MMAR_SimulationTest.mq5
Тестовый скрипт для проверки инвариантов каскада, свойств FBM и согласованности результатов нескольких прогонов (часть 6)
MQL5\Scripts\MMAR\MMAR_MonteCarloTest.mq5
Сквозной тестовый скрипт: анализ разбиений + подгонка спектра + прогнозирование волатильности методом Монте-Карло (часть 7)
MQL5\Experts\MMAR\MMAR_Demo_EA.mq5
Демонстрационный советник, показывающий полный пайплайн MMAR (часть 8)

Перевод с английского произведен MetaQuotes Ltd.
Оригинальная статья: https://www.mql5.com/en/articles/22539

Прикрепленные файлы |
MQL5.zip (94.78 KB)
Особенности написания Пользовательских Индикаторов Особенности написания Пользовательских Индикаторов
Написание пользовательских индикаторов в торговой системе MetaTrader 4
MQL5 Bootstrap (II): Основные валидаторы для надежных торговых систем MQL5 Bootstrap (II): Основные валидаторы для надежных торговых систем
В статье создается переиспользуемый слой валидации для советников MQL5. В ней реализованы правила размера лота и его нормализации, проверки SL/TP и уровня заморозки, нормализация цен по количеству знаков, проверка достаточности маржи, фильтрация неизменных уровней при модификации, контроль лимита ордеров на счете, обнаружение нового бара, проверка доступности символа для торговли, новостные окна экономического календаря и функции определения торговых сессий. В результате код становится чище, а число ошибок терминала в реальной торговле уменьшается.
Особенности написания экспертов Особенности написания экспертов
Написание и тестирование экспертов в торговой системе MetaTrader 4.
Персистентная гомология в MQL5: Алгоритм приведения и диаграмма персистентности Персистентная гомология в MQL5: Алгоритм приведения и диаграмма персистентности
Мы завершаем реализацию персистентной гомологии в MQL5, приводя граничную матрицу Вьеториса-Рипса к диаграмме персистентности. В статье реализованы столбцовое приведение над Z/2 (CTDAReduction), контейнер диаграммы с аналитическими методами (CTDADiagram) и фасад CTDA, запускающий шестиэтапный пайплайн одним вызовом. Результаты проверяются сравнением с Ripser до численного совпадения, что позволяет надежно вычислять метрики по диаграммам.