English Deutsch 日本語
preview
Построение моделей волатильности в MQL5 (Часть I): Первичная реализация

Построение моделей волатильности в MQL5 (Часть I): Первичная реализация

MetaTrader 5Примеры |
53 2
Francis Dube
Francis Dube

Введение

В этой статье мы представляем библиотеку MQL5 для моделирования и прогнозирования волатильности. Основная цель — предоставить гибкий инструмент для задания различных типов процессов волатильности. Эти инструменты сопровождаются набором аналитических утилит, используемых для количественной оценки качества построенных моделей. Мы продемонстрируем построение различных процессов волатильности из семейств ARCH и GARCH в MQL5.


Обзор кода

Представленная здесь библиотека вдохновлена пакетом arch в Python — специализированным инструментарием для финансовой эконометрики, ориентированным на модели авторегрессионной условной гетероскедастичности, или ARCH, и обобщённые ARCH-модели, то есть GARCH. Хотя основная функция пакета arch заключается в реализации различных моделей волатильности, он также предоставляет разнообразные возможности для моделирования уравнения среднего, например модели с постоянным средним, нулевым средним или авторегрессионные модели AR. Кроме того, пользователи могут задавать различные распределения для стандартизированных остатков, включая нормальное распределение, распределение Стьюдента и асимметричное распределение Стьюдента. Наша цель — нативно воспроизвести эту функциональность в MQL5.

Структура библиотеки

Архитектура этой нативной реализации является модульной: процесс среднего отделён от процесса волатильности и распределения ошибок. Следовательно, модель представляет собой композицию из этих трёх отдельных компонентов. Процесс среднего выступает в качестве основного компонента, к которому присоединяются остальные; примечательно, что все параметры модели оцениваются совместно через этот центральный компонент. Каждый элемент реализован в виде базового класса, а подклассы представляют конкретные варианты.

Все классы библиотеки следуют стандартизированной структуре. В каждом из них предусмотрен параметрический конструктор в дополнение к конструктору по умолчанию. Кроме того, каждый класс включает метод initialize(), который должен вызываться, когда экземпляр создаётся через конструктор по умолчанию. Для удобства метод initialize() вызывается неявно при использовании параметрического конструктора. В следующих разделах рассматривается реализация процессов среднего, процессов волатильности и распределений ошибок.


Настройка модели

Код для моделирования условного среднего находится в файле mean.mqh. В этом файле класс HARX определён как базовый тип для всех реализаций моделей среднего. Как уже упоминалось, модели среднего также служат основным интерфейсом для полной модели волатильности. Этот класс предоставляет функциональность, необходимую для подгонки моделей к данным и генерации прогнозов.

//+------------------------------------------------------------------+
//| Heterogeneous Autoregression (HAR)                               |
//+------------------------------------------------------------------+
class HARX: public CArchModel
  {
protected:
   bool _initialize(ArchParameters &vol_dist_params);

public:
   HARX(void):m_extra_simulation_params(0)
   HARX(ArchParameters& model_specification)
   ~HARX(void)

      bool    initialize(ArchParameters& vol_dist_params)
      matrix  get_x(void) { return m_model_spec.x; }
      matrix  get_regressors(void) { return m_regressors; }
      vector  get_y(void) { return m_model_spec.y; }

   virtual vector resids(vector &params, vector &y, matrix &regressors);
   virtual ulong  num_params(void);

   bool set_volatility_process(CVolatilityProcess* &vp);
   bool set_distribution(CDistribution* &dist);

   virtual matrix simulate(vector &params, ulong nobs, ulong burn, 
                           vector &initial_vals,matrix &x, 
                           vector &initial_vals_vol);

   ArchForecast forecast(ulong horizon = 1, long start = -1, 
                         ENUM_FORECAST_METHOD method=FORECAST_ANALYTIC, 
                         ulong simulations=1000, uint seed=0);

   ArchForecast forecast(matrix& x[],ulong horizon = 1, long start = -1, 
                         ENUM_FORECAST_METHOD method=FORECAST_ANALYTIC, 
                         ulong simulations=1000, uint seed=0);

   virtual ArchForecast forecast(vector& params, matrix& x[],ulong horizon = 1, 
                                 long start = -1, 
                                 ENUM_FORECAST_METHOD method=FORECAST_ANALYTIC, 
                                 ulong simulations=1000, uint seed=0);

   ArchModelFixedResult fix(vector& params,long first_obs = 0, long last_obs = -1);

   ArchModelResult fit(double scaling = 1.0, uint maxits = 0,
                       ENUM_COVAR_TYPE cov_type = COVAR_ROBUST, 
                       long first = 0, long last = -1, double tol = 1e-9, 
                       bool guardsmoothness=false, 
                       double gradient_test_step = 0.0);

   ArchModelResult fit(vector& startingvalues,vector& backcast,
                       double scaling = 1.0, uint maxits = 0,
                       ENUM_COVAR_TYPE cov_type = COVAR_ROBUST, 
                       long first = 0, long last = -1, double tol = 1e-9, 
                       bool guardsmoothness=false, 
                       double gradient_test_step = 0.0);

  };

Вариации моделей среднего реализованы как подклассы класса HARX. Параметрические конструкторы всех моделей среднего, а также методы initialize() принимают один и тот же параметр — пользовательскую структуру ArchParameters.

struct ArchParameters
  {
  // --- Data & Core Configuration
   vector            observations;          
   matrix            exog_data;             
   vector            mean_lags;             
   
   ENUM_MEAN_MODEL   mean_model_type;       
   ENUM_VOLATILITY_MODEL    vol_model_type;        
   ENUM_DISTRIBUTION_MODEL   dist_type;             
   
   ulong             holdout_size;          
   bool              is_rescale_enabled;    
   double            scaling_factor;        
   
   // --- Mean Model Parameters
   bool              include_constant;      
   bool              use_har_rotation;      
   
   // --- Volatility Process Parameters (GARCH/ARCH)
   int               vol_rng_seed;         
   ulong             garch_p;               
   ulong             garch_o;               
   ulong             garch_q;              
   double            vol_power;            
   
   long              sample_start_idx;      
   long              sample_end_idx;       
   ulong             min_bootstrap_sims;   
   
   // --- Distribution Parameters
   vector            dist_init_params;      
   int               dist_rng_seed;  
};

Эта структура инкапсулирует все переменные, необходимые для создания полной модели волатильности. Её свойства перечислены ниже.

Свойство  Тип данных  Описание 
observations vector Этот вектор должен содержать временной ряд, который требуется смоделировать.
exog_data matrix  Необязательная матрица для любых экзогенных переменных, которые должны быть включены в модель. Каждый столбец представляет отдельную переменную, а количество строк должно совпадать с длиной зависимой переменной, заданной в свойстве y структуры.
mean_lags vector Здесь пользователи могут задавать произвольные лаги для процесса AR или HAR. Для модели AR лаги являются простыми ссылками на предыдущие значения относительно текущего значения. Эти лаги могут быть как последовательными, так и непоследовательными. Для процесса HAR значения лагов представляют длины периодов, или окна просмотра назад, по которым рассчитываются средние значения.
mean_model_type перечисление ENUM_MEAN_MODEL Это перечисление явно задаёт процесс среднего, используемый для моделирования ожидаемого значения зависимой переменной. В настоящее время реализовано шесть моделей среднего: модель с постоянным средним, модель с нулевым средним, а также процессы AR и HAR — каждый с экзогенными переменными или без них.
vol_model_type перечисление ENUM_VOLATILITY_MODEL Это свойство определяет процесс волатильности, используемый для моделирования условной дисперсии зависимой переменной y. Доступно семь вариантов — от постоянной дисперсии до различных семейств процессов волатильности ARCH и GARCH. По умолчанию используется процесс с постоянной дисперсией.
dist_type перечисление ENUM_DISTRIBUTION_MODEL Это свойство представляет собой перечисление, задающее распределение ошибок для полной модели. В настоящее время доступны четыре распределения: нормальное распределение, распределение Стьюдента, асимметричное распределение Стьюдента и обобщённое распределение ошибок, или GED. По умолчанию используется нормальное распределение.
holdout_size unsigned long Это свойство задаёт количество наблюдений, которые должны быть отложены при подгонке модели к данным.
is_rescale_enabled bool Этот логический флаг указывает, следует ли проверять масштаб данных. Если он установлен в true, модель оценит масштаб данных; если потребуется перемасштабирование, в терминал MetaTrader 5 будет выведено предупреждение с рекомендацией масштабировать данные, а также с рекомендуемым коэффициентом масштабирования.
include_constant bool  Это логическое свойство указывает, следует ли включать константу в модель среднего.
use_har_rotation bool Это свойство актуально только тогда, когда задана HAR-модель среднего с лагами. Если оно установлено в true, это означает, что усреднение должно выполняться по непересекающимся периодам. Например, предположим, что заданы лаги {1,5,22}: если это свойство равно false, модель использует средние значения по предыдущим 1, 5 и 22 значениям зависимой переменной. И наоборот, если оно равно true, средние рассчитываются с использованием непересекающихся окон — а именно: первый лаг, равный 1, период от 2 до 5 и период от 6 до 22.
vol_rng_seed integer Необязательное значение seed для генератора случайных чисел, используемого процессом волатильности.
garch_p unsigned long  Параметр p для процессов ARCH/GARCH.
garch_o unsigned long 
Параметр o для процессов типа GARCH.
garch_q  unsigned long  Параметр q для процессов типа GARCH. 
vol_power  double Параметр степени процесса волатильности типа GARCH.
 min_bootstrap_sims  unsigned long  Минимальное количество бутстрэп-моделирований, используемых при прогнозировании методом бутстрэпа.
 dist_init_params  vector Этот вектор содержит начальные параметры для распределения ошибок.
 dist_rng_seed  integer Необязательное значение seed для генератора случайных чисел, используемого заданным распределением.

Переменная типа ArchParameters должна быть объявлена и настроена до того, как она будет передана либо в параметрический конструктор модели среднего, либо в её метод initialize().

Метод initialize() отвечает за проверку всех параметров, чтобы убедиться, что они корректно соответствуют выбранному процессу среднего, процессу волатильности и распределению ошибок. Любые незначительные конфликты, выявленные на этом этапе, автоматически исправляются без вывода сообщений.

bool              _initialize(ArchParameters &vol_dist_params)
     {
      if(m_model_spec.mean_model_type!=WRONG_VALUE && vol_dist_params.mean_model_type!=WRONG_VALUE && vol_dist_params.mean_model_type!=m_model_spec.mean_model_type)
        {
         m_initialized = false;
         Print(__FUNCTION__" Incorrect initialization of mean model. \nMake sure input parameters correspond with the correct class ");
         return false;
        }

      if(m_model_spec.mean_model_type!=WRONG_VALUE && vol_dist_params.mean_model_type==WRONG_VALUE)
         vol_dist_params.mean_model_type = m_model_spec.mean_model_type;

      m_model_spec = vol_dist_params;

      switch(m_model_spec.mean_model_type)
        {
         case MEAN_CONSTANT:
            m_model_spec.mean_lags = vector::Zeros(0);
            m_name = "Constant Mean";
            m_model_spec.include_constant = true;
            m_model_spec.use_har_rotation = false;
            break;
         case MEAN_AR:
            m_model_spec.use_har_rotation = false;
            m_model_spec.exog_data = matrix::Zeros(0,0);
            m_name = "AR";
            break;
         case MEAN_ARX:
            m_model_spec.use_har_rotation = false;
            m_name ="AR-X";
            break;
         case MEAN_HAR:
            m_model_spec.exog_data = matrix::Zeros(0,0);
            m_name = "HAR";
            break;
         case MEAN_HARX:
            m_name = "HAR-X";
            break;
         case MEAN_ZERO:
            m_model_spec.exog_data=matrix::Zeros(0,0);
            m_model_spec.mean_lags = vector::Zeros(0);
            m_model_spec.include_constant = false;
            m_model_spec.use_har_rotation = false;
            m_name = "Zero Mean";
            break;
         default:
            m_name = "HAR-X";
            break;
        }

      m_fit_indices = vector::Zeros(2);
      m_fit_indices[1] = (m_model_spec.observations.Size())?double(m_model_spec.observations.Size()):-1.;
      if(m_model_spec.mean_lags.Size())
        {
         switch(m_model_spec.mean_model_type)
           {
            case MEAN_AR:
            case MEAN_ARX:
               m_lags = matrix::Zeros(2,m_model_spec.mean_lags.Size());
               m_lags.Row(m_model_spec.mean_lags,0);
               m_lags.Row(m_model_spec.mean_lags,1);
               break;
            case MEAN_HAR:
            case MEAN_HARX:
               m_lags = matrix::Zeros(1,m_model_spec.mean_lags.Size());
               m_lags.Row(m_model_spec.mean_lags,0);
               break;
           }
        }
      else
         m_lags = matrix::Zeros(0,0);
      m_constant = m_model_spec.include_constant;
      m_rescale = m_model_spec.is_rescale_enabled;
      m_rotated = m_model_spec.use_har_rotation;
      m_holdback = m_model_spec.holdout_size;
      m_initialized = _init_model();
      if(!m_initialized)
         return false;

      m_num_params = num_params();

      if(CheckPointer(m_vp)==POINTER_DYNAMIC)
         delete m_vp;
      m_vp = NULL;

      switch(vol_dist_params.vol_model_type)
        {
         case VOL_CONST:
            m_vp = new CConstantVariance(m_model_spec.vol_rng_seed,m_model_spec.min_bootstrap_sims);
            break;
         case VOL_ARCH:
            m_vp = new CArchProcess(m_model_spec.garch_p,m_model_spec.vol_rng_seed,m_model_spec.min_bootstrap_sims);
            break;
             case VOL_GARCH:
            m_vp = new CGarchProcess(m_model_spec.garch_p,m_model_spec.garch_q,m_model_spec.vol_rng_seed,m_model_spec.min_bootstrap_sims);
            break;
         default:
            m_vp = new CConstantVariance(m_model_spec.vol_rng_seed,m_model_spec.min_bootstrap_sims);
            break;
        }

      if(CheckPointer(m_distribution)==POINTER_DYNAMIC)
         delete m_distribution;
      m_distribution = NULL;

      switch(vol_dist_params.dist_type)
        {
         case DIST_NORMAL:
            m_distribution = new CNormal();
            break;
         default:
            m_distribution = new CNormal();
            break;
        }

      m_initialized = (
                         m_distribution!=NULL  &&
                         m_vp!=NULL            &&
                         m_vp.is_initialized() &&
                         m_distribution.initialize(m_model_spec.dist_init_params,
                               m_model_spec.dist_rng_seed)
                      );

      return m_initialized;
     }

Метод вернёт false только в том случае, если существуют проблемы с выборочными данными или если указанные параметры конфликтуют с предоставленным выборочным рядом; в таких случаях метод возвращает false. Если спецификация модели корректна, метод переходит к инициализации остальных компонентов полной модели. Если на этом втором этапе возникают какие-либо ошибки, метод initialize() помечает их и возвращает false. После успешного выполнения метода initialize() можно начинать процесс подгонки модели.

Совместная оценка параметров модели выполняется путём вызова одного из методов fit().


Подгонка модели к данным

Процедура подгонки выполняется с помощью алгоритма нелинейной оптимизации с ограничениями и предобусловленным расширенным лагранжианом из библиотеки Alglib, реализованного в виде класса CMinNLC. Минимизируемой функцией является функция логарифмического правдоподобия, определённая как член класса HARX. 

vector objective(vector& parameters, vector& sigma2, 
                 vector &backcast, matrix& varbounds, 
                 bool individual=false)
     {
      return _loglikelihood(parameters,sigma2,backcast,varbounds,individual);
     }

Входные параметры методов fit() перечислены и объяснены в таблице ниже.

Название параметра  Тип данных  Описание 
startingvalues vector Вектор начальных значений параметров модели, используемых в процессе оптимизации. Пользователи могут задать собственные значения; в противном случае параметр принимает пустой вектор, и тогда подходящие начальные значения будут рассчитаны автоматически.
backcast vector Этот вектор используется для оценки параметров процесса условной волатильности. Поскольку уравнение условной дисперсии является рекурсивным, для вычисления первого наблюдения требуются начальные значения, если предвыборочные данные недоступны. Этот параметр также принимает пустой вектор, и в таком случае подходящие значения backcast определяются внутренне.
scaling double  Коэффициент масштабирования, используемый для преобразования выборочного ряда. Оптимизатор работает эффективнее, если ему известно, каким образом данные были преобразованы, если такое преобразование выполнялось. Значение по умолчанию — 1.
cov_type перечисление ENUM_COV_TYPE Перечисление, задающее метод, используемый для оценки ковариационной матрицы параметров.
maxits unsigned long Значение, задающее максимальное количество итераций, разрешённых для оптимизатора.
first,last integers Эти значения являются индексами, задающими начало и конец диапазона в выборочном ряду, который будет использоваться для оценки параметров модели.
tol double Этот параметр задаёт уровень допуска, или порог, используемый для определения момента сходимости процесса оптимизации.
guardsmoothness bool Это значение настраивает оптимизатор, включая или отключая мониторинг негладкости. При включении оптимизатор учитывает функции, которые могут быть не идеально дифференцируемыми; дополнительные сведения об этом механизме можно найти в документации ALGLIB.
gradient_test_step double Если этот параметр включён, то есть установлен в ненулевое значение, он предписывает оптимизатору проверить предоставленную аналитическую функцию градиента или якобиана. Хотя это обеспечивает математическую согласованность и может предотвратить ошибки в логике оптимизации, оно существенно снижает скорость процесса. Обратитесь к документации ALGLIB, чтобы определить подходящее значение конфигурации для конкретного варианта использования.

Метод fit() возвращает структуру ArchModelResult, которая инкапсулирует результат процесса оптимизации, включая оценённые коэффициенты, статистическую значимость и диагностические показатели модели.

struct ArchModelFixedResult
  {
   double            loglikelihood;
   vector            params;
   vector            conditional_volatility;
   ulong             nobs;
   vector            resid;
 };

//+------------------------------------------------------------------+
//| arch model result                                                |
//+------------------------------------------------------------------+
struct ArchModelResult: public ArchModelFixedResult
  {
   long              fit_indices[2];
   matrix            param_cov;
   double            r2;
   ENUM_COVAR_TYPE   cov_type;

Ниже приведены свойства и методы, содержащиеся в структуре ArchModelResult.

Название свойства  Тип данных  Описание 
params vector Результаты процесса оптимизации, представляющие параметры модели волатильности. Значения организованы в определённом последовательном порядке:
Параметры модели среднего: идут первыми, например константа, коэффициенты AR/HAR, экзогенные переменные.
Параметры волатильности: идут вторыми, например omega, alpha и beta в процессе GARCH.
Параметры распределения: перечисляются последними, например степени свободы или параметры асимметрии.
conditional_volatility vector Этот вектор содержит внутривыборочную условную волатильность, представляющую прогнозы волатильности модели за период оценки.
nobs integer Это свойство указывает общее количество наблюдений из выборочного ряда, фактически использованных для подгонки параметров модели.
resids vector Этот вектор содержит остатки полной модели, представляющие разницу между наблюдаемыми значениями и значениями, предсказанными уравнением среднего. Они могут использоваться для оценки качества подгонки модели.
loglikelihood double Значение функции логарифмического правдоподобия в точке сходимости. Оно представляет минимальное значение, достигнутое целевой функцией в процессе оптимизации.
fit_indices vector Этот вектор содержит два элемента, которые явно задают диапазон индексов — начало и конец — выборочного ряда, использованного при оценке модели.
param_cov matrix Эта матрица содержит оценённую ковариационную матрицу параметров модели. Это квадратная матрица, размерность которой соответствует общему количеству оценённых параметров.
r2 double Даёт меру доли дисперсии зависимой переменной, объясняемой моделью среднего.
cov_type enumeration Это свойство указывает конкретный метод или оцениватель, использованный для вычисления ковариационной матрицы параметров.

Методы структуры ArchModelResult обеспечивают более глубокий статистический анализ, выходящий за рамки простых точечных оценок, чтобы определить, действительно ли модель является адекватной. Ниже приведены статистические методы и метрики, которые они предоставляют:

tvalues(void) tvalues(void) — возвращает вектор t-статистик для каждого параметра. Он рассчитывается как отношение оценённого коэффициента к его стандартной ошибке.
vector tvalues(void)
     {
      return params/std_err();
     }
pvalues(void) pvalues(void) — возвращает p-значения, связанные с t-статистиками. Это помогает определить вероятность того, что наблюдаемое значение параметра возникло случайно; обычно значение меньше 0.05 указывает на статистическую значимость.
vector pvalues(void)
     {
      vector pvals = tvalues();
      for(ulong i = 0; i<pvals.Size(); ++i)
         pvals[i] = CAlglib::NormalCDF(-1.0*MathAbs(pvals[i]))*2.0;

      return pvals;
     }
rsquaredadj(void) Возвращает скорректированный коэффициент детерминации R² для модели среднего. В отличие от стандартного R², этот показатель штрафует за включение лишних переменных, показывая, какая доля дисперсии объясняется моделью с учётом её сложности.
double rsquared_adj(void)
     {
      return 1.0 - ((1.0-r2)*double(nobs-1)/double(nobs-num_params()));
     }
stderror(void) Возвращает стандартные ошибки параметров. Они отражают точность оценок; меньшие ошибки указывают на более надёжные оценки параметров.
vector std_err(void)
     {
      return sqrt(param_cov.Diag());
     }

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


Прогнозирование

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

Название параметра  Тип данных  Описание 
horizon unsigned long Целое число, определяющее горизонт прогнозирования. Оно задаёт, на сколько шагов вперёд модель будет прогнозировать как условное среднее, так и условную волатильность. Значение по умолчанию — 1.
start  integer Этот параметр определяет точку в вашем ряде данных, которая служит началом прогноза. Он задаёт, за каким наблюдением непосредственно последуют будущие прогнозные значения. По умолчанию устанавливается последний доступный индекс в данных.
method ENUM_FORECAST_METHOD Этот параметр определяет математический подход, используемый для прогнозирования будущей волатильности. Хотя модель среднего обычно следует стандартной схеме, процесс волатильности может прогнозироваться несколькими способами в зависимости от сложности модели. Возможные варианты: Analytic, Simulation или Bootstrap. По умолчанию используется Analytic.

Аналитический метод использует замкнутые математические формулы для вычисления ожидаемой дисперсии. Однако у него есть существенное ограничение, связанное с параметром степени. Если модель предполагает, что дисперсия выражается через квадраты остатков, аналитический метод работает для любого горизонта. В противном случае, если модель использует степень, отличную от 2, аналитический метод нельзя применять для горизонтов больше одного. Это связано с тем, что математическое ожидание нелинейного преобразования не имеет простого рекурсивного решения.

Метод симуляции, или Монте-Карло, использует предполагаемое распределение для моделирования множества возможных траекторий и усредняет их. В то же время метод бутстрэпа напрямую выполняет повторную выборку из исторических остатков для построения будущих траекторий без предположения о конкретном распределении.
simulations integer Целое число, задающее количество траекторий или случайных выборок, которые необходимо сгенерировать. Используется исключительно тогда, когда параметр method установлен в Simulation или Bootstrap.
seed  integer Необязательное целое значение, используемое для инициализации генератора псевдослучайных чисел, или RNG. Оно обеспечивает воспроизводимость случайных траекторий, сгенерированных во время прогнозирования методом симуляции или бутстрэпа.
params vector Необязательный вектор коэффициентов. Если он предоставлен, прогноз будет рассчитан с использованием этих конкретных значений вместо результатов внутреннего метода fit().
x array of matrices Этот параметр актуален, когда модель среднего включает экзогенные переменные. Поскольку эти переменные являются внешними по отношению к самому процессу волатильности, модель не может "предсказать" их будущие значения; они должны быть заранее заданы для формирования полного прогноза. Если модель была подогнана с k экзогенными переменными, этот входной параметр необходим для вычисления прогноза.

Обратите особое внимание на размерности каждой матрицы, переданной для этой переменной. Требуемая форма зависит от параметра horizon, количества экзогенных переменных и значения start относительно размера выборочного ряда, использованного для построения модели.

Размер массива, то есть общее количество матриц, должен быть равен количеству экзогенных переменных. Для каждой матрицы количество строк должно быть как минимум равно разнице между общим размером выборки и начальным индексом, то есть началом прогноза. Наконец, количество столбцов должно соответствовать параметру horizon.

При вызове метод forecast() возвращает структуру ArchForecast. Этот контейнер инкапсулирует прогнозируемые траектории как для среднего, так и для волатильности. Структура организована в три основные матрицы.

//+------------------------------------------------------------------+
//|  arch forecast result                                            |
//+------------------------------------------------------------------+
struct ArchForecast
  {
   matrix            mean;
   matrix            variance;
   matrix            residual_variance;

Матрица mean содержит прогнозные значения условного среднего, то есть ожидаемой цены или доходности. Поле variance содержит матрицу прогнозных значений условной дисперсии. И наконец, матрица residual_variance представляет прогнозы условной дисперсии остатков.


Валидация модели

После подгонки модели тест множителей Лагранжа, или LM-тест, иногда называемый ARCH-тестом Энгла, является стандартным диагностическим инструментом, используемым для проверки того, остаются ли в остатках какие-либо ARCH-эффекты, то есть гетероскедастичность. Если модель адекватна, остатки должны представлять собой белый шум; это означает, что тест не должен выявлять значимой автокорреляции в квадратах остатков. Функция archlmtest() оценивает это, выполняя регрессию квадратов остатков на их собственные лаги.

//+------------------------------------------------------------------+
//| The Lagrange multiplier test                                     |
//+------------------------------------------------------------------+
WaldTestStatistic archlmtest(vector& residuals,vector& conditional_volatility,ulong lags,bool standardized = false)
  {
   WaldTestStatistic out;
   vector resids = residuals;
   if(standardized)
      resids = resids/conditional_volatility;
   if(resids.HasNan())
     {
      vector nresids = vector::Zeros(resids.Size() - resids.HasNan());
      for(ulong i = 0, k = 0; i<resids.Size(); ++i)
         if(MathClassify(resids[i]) == FP_NAN)
            continue;
         else
            nresids[k++] = resids[i];
      resids = nresids;
     }
   int nobs = (int)resids.Size();
   vector resid2 = MathPow(resids,2.0);
   if(!lags)
      lags = ulong(ceil(12.0*pow(nobs/100.0,1.0/4.0)));
   lags = MathMax(MathMin(resids.Size()/2 - 1,lags),1);
   if(resid2.Size()<3)
     {
      Print(__FUNCTION__, " Test requires at least 3 non-nan observations ");
      return out;
     }
   matrix matres = matrix::Zeros(resid2.Size(),1);
   matres.Col(resid2,0);
   matrix lag[];
   if(!lagmat(matres,lag,lags,TRIM_BOTH,ORIGINAL_SEP))
     {
      Print(__FUNCTION__, " lagmat failed ");
      return out;
     }
   matrix lagout;
   if(!addtrend(lag[0],lagout,TREND_CONST_ONLY,true,HAS_CONST_SKIP))
     {
      Print(__FUNCTION__, " addtrend failed ");
      return out;
     }
   lag[0] = lagout;
   OLS ols;
   if(!ols.Fit(lag[1].Col(0),lag[0]))
     {
      Print(__FUNCTION__, " OLS fitting failed ");
      return out;
     }

   out.stat = nobs*ols.Rsqe();
   if(standardized)
     {
      out.null = "Standardized residuals are homoskedastic";
      out.alternative = "Standardized residuals are conditionally heteroskedastic";
     }
   else
     {
      out.null = "Residuals are homoskedastic";
      out.alternative = "Residuals are conditionally heteroskedastic";
     }

   out.df = lags;
   return out;
  }

Для неё требуются следующие входные параметры. 

Название параметра  Тип данных  Описание 
residuals vector Вектор остатков, полученный из ArchModelResult. Это исходные ошибки подогнанной модели.
conditional_volatility vector Внутривыборочная условная волатильность для подогнанной модели. 
lags unsigned long Целое число, задающее количество лагов, которые нужно включить в тестовую регрессию. 
standardized bool Этот логический флаг указывает, следует ли стандартизировать остатки с использованием conditional_volatility. 

Вызов функции archlmtest() возвращает структуру WaldTestStatistic.

//+------------------------------------------------------------------+
//|Test statistic holder for Wald-type tests                         |
//+------------------------------------------------------------------+
struct WaldTestStatistic
 {
  ulong df;
  double stat;
  string null;
  string alternative;
  
  WaldTestStatistic(void)
   {
    stat = EMPTY_VALUE;
    df = 0; 
    null = alternative = NULL;
   }
  WaldTestStatistic(double _stat, ulong _df, string _null, string _alt)
   {
    stat = _stat;
    df = _df;
    null = _null;
    alternative = _alt;
   }
  WaldTestStatistic(WaldTestStatistic &other)
   {
    stat = other.stat;
    df = other.df;
    null = other.null;
    alternative = other.alternative;
   }
  void operator=(WaldTestStatistic &other)
   {
    stat = other.stat;
    df = other.df;
    null = other.null;
    alternative = other.alternative;
   }
  double pvalue(void)
   {
    int ecode = 0;
    double val = 1.- MathCumulativeDistributionChiSquare(stat,double(df),ecode);
    
    if(ecode)
     Print(__FUNCTION__," Chisquare cdf error ", ecode);
    return val;
   }
  vector critical_values(void)
   {
    vector out = {0.9,0.95,0.99};
    int ecode = 0;
    for(ulong i = 0; i<out.Size(); ++i)
         out[i] = MathQuantileChiSquare(out[i],double(df),ecode);
    if(ecode)
     Print(__FUNCTION__," Chisquare cdf error ", ecode);
    return out;
   }
 };

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

Название свойства  Тип данных  Описание 
df unsigned long Степени свободы теста, что соответствует количеству лагов, указанному при вызове функции.
stat double Рассчитанная тестовая статистика. При нулевой гипотезе это значение следует распределению хи-квадрат.
pvalue(void) double Метод pvalue() возвращает вероятность наблюдения тестовой статистики, столь же экстремальной, как рассчитанная, при условии, что ARCH-эффекты больше не сохраняются.
crtical(void) vector  Метод critical() возвращает вектор критических значений для трёх уровней доверия: 90%, 95% и 99%.

Для оценки адекватности модели мы в первую очередь смотрим на p-значение. Если p-значение больше 0.05, это означает, что модель проходит проверку. Это означает, что мы не можем отвергнуть нулевую гипотезу. Такой результат указывает на то, что остатки являются гомоскедастичными, то есть имеют постоянную дисперсию, а значит, модель ARCH/GARCH выполнила свою задачу. С другой стороны, если p-значение меньше или равно 0.05, мы отвергаем нулевую гипотезу. Это означает, что ARCH-эффекты всё ещё сохраняются в остатках, и модель, вероятно, является неадекватной. В таком случае может потребоваться увеличить порядок лагов или попробовать другой тип модели. Значение stat увеличивается по мере роста корреляции в квадратах остатков. Очень большое значение stat приведёт к очень малому p-значению, сигнализируя о том, что модель пропустила значимые паттерны волатильности.


Пример с включением экзогенных переменных

В этом разделе демонстрируется, как задать модель, включающую экзогенные переменные. Буква X в ARX и HARX относится к этим внешним независимым переменным в уравнении регрессии. В данной структуре моделируемый временной ряд выступает в качестве зависимой переменной, тогда как экзогенные предикторы передаются в виде матрицы, где каждый столбец представляет одну переменную.

Чтобы проиллюстрировать гибкость экзогенных переменных, мы рассмотрим интересную взаимосвязь между моделями ARX и гетерогенными авторегрессионными моделями, или HAR. Используя усреднённые исторические данные как экзогенные входные переменные в модели ARX, мы можем воспроизвести поведение HAR-модели. Это сравнение подчёркивает как практическое применение экзогенных переменных, так и базовую структуру HAR-моделей. HAR-модель была специально разработана для моделирования реализованной волатильности на финансовых рынках, хотя её можно адаптировать и для других переменных. Она называется "гетерогенной", потому что разбивает влияние прошлого на разные временные горизонты — краткосрочный, среднесрочный и долгосрочный — исходя из предположения, что разные типы участников рынка реагируют на волатильность на разных временных масштабах.

Формула HAR-модели

Наиболее распространённая версия HAR-модели использует измерения реализованной волатильности по трём длинам периодов: краткосрочной, среднесрочной и долгосрочной. Каждый период определяет количество временных точек, используемых для расчёта средней реализованной волатильности. HAR-модель улавливает долгосрочную память в волатильности за счёт перекрывающихся средних членов. 

Модель ARX объединяет стандартный авторегрессионный процесс, или AR, с   экзогенными входными переменными (Х). Она предполагает, что текущее значение зависит от собственных прошлых значений, а также от текущих или прошлых значений внешних переменных. Общая формула модели ARX(p,q) выглядит следующим образом.

Формула ARX-модели

Скрипт HAR_as_ARX_Demo.ex5 демонстрирует, как модель ARX может использоваться для имитации HAR-модели. Скрипт выполняет следующие шаги:

  • Строит стандартную HAR-модель с использованием выбираемого количества усреднённых членов.
  • Задаёт ARX-модель, используя те же усреднённые члены в качестве матрицы экзогенных входных данных.
  • Сравнивает параметры обеих моделей, чтобы продемонстрировать их эквивалентность.
//+------------------------------------------------------------------+
//|                                              HAR_as_ARX_Demo.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 script_show_inputs
#include<Arch\Univariate\mean.mqh>

//--- input parameters
input string   Symbol_="AUDUSD";
input ENUM_TIMEFRAMES   TimeFrame=PERIOD_D1;
input datetime StartDate=D'2025.01.01';
input ulong HistoryLen = 504;
input double ScaleFactor=100.;
input bool MeanConstant = true;
input string MeanLags ="1,5,22";

//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//---download data
   vector prices;
   if(!prices.CopyRates(Symbol_,TimeFrame,COPY_RATES_CLOSE,StartDate,HistoryLen))
    {
     Print(" failed to get close prices for ", Symbol_,". Error ", GetLastError());
     return;
    }
//---
   prices = log(prices);
//---
   vector returns = np::diff(prices);
//---
   string lag_info[];
//---
   vector lags=vector::Zeros(0);
//---
   int nlags = StringSplit(MeanLags,StringGetCharacter(",",0),lag_info);
//---
   double atod;
   if(nlags>0)
    {
     for(uint i = 0; i<uint(nlags); ++i)
      {
       if(StringLen(lag_info[i])>0)
        {
         atod = StringToDouble(lag_info[i]);
         if(atod>0 && ulong(atod)<returns.Size()-1)
           if(lags.Resize(lags.Size()+1,3))
              lags[lags.Size()-1] = atod;
        }
      }
    }
//---
  if(lags.Size())
    np::sort(lags);
//---build the HAR model
  ArchParameters har_spec;
  har_spec.observations=returns*ScaleFactor;
  har_spec.include_constant = MeanConstant;
  har_spec.mean_lags = lags;
  har_spec.vol_model_type = VOL_CONST;
//---
  HAR harmodel;
//---
  if(!harmodel.initialize(har_spec))
    return;
//---
  ArchModelResult har = harmodel.fit(ScaleFactor);
//---
  if(!har.params.Size())
   {
    Print("Convergence failed ", GetLastError());
    return;
   }
//---
  Print(" Har model parameters\n", har.params);
//---Now we build an equivalent ARX model
  matrix exogvars = matrix::Zeros(returns.Size(),lags.Size());
//---calculate averages  
  double sum;
  ulong lag,count;
  for(ulong i = 0; i<exogvars.Cols(); ++i)
   {
    lag = (ulong)lags[i];
    count = lag;
    for(ulong k = lag; k<exogvars.Rows(); ++k)
     {
       sum = 0.0;
       for(ulong j = 0; j<count; ++j)
         sum+=returns[k-j-1];
       exogvars[k,i] = sum/double(count);
     }
   }
//---
  ArchParameters arx_spec;
  arx_spec.observations = ScaleFactor*np::sliceVector(returns,long(lags[lags.Size()-1]));
  arx_spec.exog_data = ScaleFactor*np::sliceMatrixRows(exogvars,long(lags[lags.Size()-1]));
  arx_spec.include_constant = MeanConstant;
  arx_spec.vol_model_type=VOL_CONST; 
//---
  ARX arxmodel;
  if(!arxmodel.initialize(arx_spec))
   return;
//---
  ArchModelResult arx = arxmodel.fit(ScaleFactor);
  if(!arx.params.Size())
   {
    Print(" convergence failed ", GetLastError());
    return;
   }
//---
  Print("ARX model parameters\n", arx.params);
 } 
//+------------------------------------------------------------------+

Скрипт был запущен с параметрами по умолчанию.

Параметры скрипта

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

NR      0       22:12:43.671    HAR_as_ARX_Demo (XAUUSD,D1)      Har model parameters
CE      0       22:12:43.672    HAR_as_ARX_Demo (XAUUSD,D1)     [-0.02336784243846212,-0.04576660950059414,0.02963893847811298,-0.1589020837643845,0.3352700836173772]
RE      0       22:12:43.691    HAR_as_ARX_Demo (XAUUSD,D1)     ARX model parameters
HN      0       22:12:43.691    HAR_as_ARX_Demo (XAUUSD,D1)     [-0.02336784243846212,-0.04576660950059416,0.02963893847811294,-0.1589020837643847,0.3352700836173772]

Демонстрация подтверждает, что оба подхода дают идентичные параметры модели, как показано в выводе скрипта.


Заключение

В этой статье мы заложили основу для нативного моделирования волатильности в MQL5. Стандартизировав интерфейс с помощью структур ArchParameters и ArchModelResult, мы создали рабочий процесс, который позволяет задавать спецификацию модели, выполнять оптимизацию и проводить валидацию. Этот фреймворк позволяет просто и последовательно инициализировать модель, подгонять её к набору данных и выполнять строгие диагностические проверки, такие как тест ARCH-LM, чтобы убедиться, что остатки свободны от гетероскедастичности.

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

Файл  Описание 
MQL5/include/Arch Эта папка содержит все заголовочные файлы библиотеки моделирования волатильности.
MQL5/include/Regression Эта папка содержит некоторые регрессионные утилиты, используемые в коде моделирования волатильности. 
MQL5/include/np.mqh Этот заголовочный файл содержит различные утилиты для работы с векторами и матрицами. 
MQL5/scripts/HAR_as_ARX_Demo.mq5 Это скрипт, демонстрирующий спецификацию HAR-модели как AR-модели с экзогенными переменными.

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

Прикрепленные файлы |
Последние комментарии | Перейти к обсуждению на форуме трейдеров (2)
Osmar Sandoval Espinosa
Osmar Sandoval Espinosa | 12 февр. 2026 в 01:05

Очень интересная идея!

Сочетание волатильности нескольких таймфреймов.

cemal
cemal | 12 февр. 2026 в 09:34
Osmar Sandoval Espinosa #:

Очень интересная идея!

Сочетание волатильности нескольких таймфреймов.

Удалось ли вам создать индикатор с помощью библиотек, приведенных в статье?
Автоматизация торговых стратегий в MQL5 (Часть 26): Создание системы усреднения на основе пин-баров для многопозиционной торговли Автоматизация торговых стратегий в MQL5 (Часть 26): Создание системы усреднения на основе пин-баров для многопозиционной торговли
В данной статье мы разрабатываем систему усреднения на основе пин-баров на языке MQL5, которая обнаруживает паттерны пин-баров для открытия сделок и использует стратегию усреднения для управления несколькими позициями, дополненную трейлинг-стопами и переводом в безубыток. Мы объединяем настраиваемые параметры с дашбордом для мониторинга позиций и прибыли в реальном времени.
Тестер стратегий для Python и MetaTrader 5 (Часть 02): Работа с барами, тиками и реализация встроенных функций в симуляторе Тестер стратегий для Python и MetaTrader 5 (Часть 02): Работа с барами, тиками и реализация встроенных функций в симуляторе
В этой статье мы представим функции, аналогичные тем, которые предоставляет модуль Python–MetaTrader 5, предоставляя симулятору привычный интерфейс и собственный механизм внутренней обработки баров и тиков.
Особенности написания экспертов Особенности написания экспертов
Написание и тестирование экспертов в торговой системе MetaTrader 4.
Разработка инструментария для анализа Price Action (Часть 43): Вероятностный анализ свечных паттернов и пробоев Разработка инструментария для анализа Price Action (Часть 43): Вероятностный анализ свечных паттернов и пробоев
Улучшите рыночный анализ с помощью советника Candlestick Probability на MQL5 – компактного инструмента, который преобразует исходные ценовые бары в вероятностную аналитику в реальном времени по конкретному инструменту. Он классифицирует пин-бары, паттерны поглощения и доджи на закрытии бара, использует фильтрацию с учетом волатильности по ATR и при необходимости подтверждение пробоя. Советник рассчитывает простые и взвешенные по объему проценты отработки, помогая понять, каков типичный исход каждого паттерна на конкретных символах и таймфреймах. Маркеры на графике, компактная информационная панель и интерактивные переключатели позволяют быстро проверять результаты и сосредоточиться на нужном. Экспортируйте подробные CSV-логи для последующего анализа вне терминала. Используйте советник, чтобы строить вероятностные профили, оптимизировать стратегии и превращать распознавание паттернов в измеримое преимущество.