Article-23677-EGARCH-MQL5-V.../GARCH_ParameterPositivityLimitation.mq5
2026-07-24 23:03:06 +02:00

86 lines
4 KiB
MQL5

//+------------------------------------------------------------------+
//| GARCH_ParameterPositivityLimitation.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"
#define __SLSQP__
#include "Arch\univariate\mean.mqh"
#resource "SPY2017.csv" as string equity_data
//---global variables
double ScaleFactor = 100.; //--- Rescaling multiplier to prevent optimizer underflow
ulong _P_ = 1; //--- Short-term ARCH lag order
ulong _Q_ = 1; //--- Long-term variance persistence GARCH lag order
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
//---
vector prices;
//--- --- Step 1: Historical Data Fetch ---
matrix data = np::readcsv_from_string(equity_data,false,",",true,0);
prices = data.Col(1);
//--- --- Step 2: Transform Prices to Returns ---
//--- Map closing prices to logarithmic space
prices = log(prices);
//--- Compute log returns: r_t = ln(P_t) - ln(P_{t-1})
vector returns = np::diff(prices);
//--- --- Step 3: Base Model Configuration Setup ---
//--- Initialize core specification fields mapping onto the EGARCH container
ArchParameters garch_spec;
//--- Apply the scaling factor (multiplying by 100 scales returns to percentage form)
garch_spec.observations = ScaleFactor * returns;
garch_spec.vol_model_type = VOL_GARCH;
garch_spec.dist_type = DIST_NORMAL;
garch_spec.garch_p = _P_;
garch_spec.garch_q = _Q_;
//--- --- Step 5: Model Initialization ---
//--- Instantiate the continuous tracking constant mean container wrapper
ZeroMean garch_model;
//--- Pass structural parameters down into the optimization initialization routine
if(!garch_model.initialize(garch_spec))
return;
//--- --- Step 6: Parameter Optimization (Fitting) ---
//--- Trigger the non-linear execution optimizer loop (SLSQP engine solver)
ArchModelResult garch_params = garch_model.fit();
//--- --- Step 7: Optimization Convergence Guard ---
//--- Verify that the resulting parameters array size matches the model criteria configurations
if(!garch_params.params.Size())
{
Print("Convergence failed ", GetLastError());
return;
}
//--- --- Step 8: Results Output Extraction ---
//--- Print optimal target parameter solutions to the MetaTrader Terminal panel
Print("GARCH model parameters");
//--- Extract statistical asymptotic standard deviation errors mapped out to individual p-values
vector pv = garch_params.pvalues();
Print("Check GARCH model pvalues.\nA corresponding pvalue of 1 or 0.99 is an indication of a"
"\n parameter being limited by a boundary constraint."
"\n Meaning the model parameters are not a reflection of the observed data:");
//--- Get the volatility parameter names
//--- Notice that the full model is anchored by a ZeroMean mean model
string pnames = garch_model.volatility().parameterNames();
string vol_parameter_labels[];
//--- Organize parameter names into array for display
int labels = StringSplit(pnames,StringGetCharacter(",",0),vol_parameter_labels);
//--- Check number of labels is equal to number of model parameters
if(labels != int(pv.Size()))
return;
//--- Display pvalues
PrintFormat("%10s %10s %10s","Name","Value","Pvalue");
for(ulong i = 0; i < pv.Size(); ++i)
{
//--- Log individual calculated p-values step-by-step to evaluate structural significance
PrintFormat("%10s %10.8f %10.8f",vol_parameter_labels[i], garch_params.params[i], pv[i]);
}
}
//+------------------------------------------------------------------+