//+------------------------------------------------------------------+ //| VolatilityModelParameterComparison.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 #property description "The script downloads data from the terminal" "to build a conditional volatility model using" "the MQL5 library then Pythons ARCH module. By" "default MQL5 lib uses minNLC. To use the SLSQP " "solver define __SLSQP__ before including" "the arch library and compile" #define __SLSQP__ #include #include #include #include //--- #define FILENAME "arch.json" #define SPACE " " #define PYFILE "\\MQL5\\Scripts\\slsqp_article\\mt5_volatility_processor.py" //--- input string Symbol_="AUDUSD"; input ENUM_TIMEFRAMES TimeFrame=PERIOD_D1; input datetime StartDate=D'2025.01.01'; input ulong HistoryLength = 1000; input double ScaleFactor=100.; input ENUM_MEAN_MODEL MeanModel = MEAN_CONSTANT; input bool MeanConstant = true; input string MeanLags =""; input ENUM_VOLATILITY_MODEL VolatilityModel = VOL_GJR_GARCH; input ENUM_DISTRIBUTION_MODEL ErrorDistribution = DIST_NORMAL; input ulong _P_ = 1; input ulong _O_ = 1; input ulong _Q_ = 1; //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { #ifdef __SLSQP__ Print("USING SLSQP"); #else Print("USING minNLC"); #endif Print(EnumToString(MeanModel)); Print(EnumToString(VolatilityModel)); Print(EnumToString(ErrorDistribution)); //--- string pstring = EnumToString(TimeFrame); if(StringFind(pstring,"CURRENT")>=0) { Print("Invalid parameter setting. Please do not use PERIOD_CURRENT option, be explicit."); return; } //--- ArchParameters spec; spec.mean_model_type = MeanModel; //--- string lag_info[]; int nlags = StringSplit(MeanLags,StringGetCharacter(",",0),lag_info); if(nlags>0) { for(uint i = 0; i0) { if(spec.mean_lags.Resize(spec.mean_lags.Size()+1,3)) spec.mean_lags[spec.mean_lags.Size()-1] = StringToDouble(lag_info[i]); else { Print(" error ", GetLastError()); return; } } } } //--- spec.vol_model_type = VolatilityModel; spec.garch_o = _O_; spec.garch_p = _P_; spec.garch_q = _Q_; spec.dist_type = ErrorDistribution; //---download data vector prices; if(!prices.CopyRates(Symbol_,TimeFrame,COPY_RATES_CLOSE,StartDate,HistoryLength)) { Print(" failed to get close prices for ", Symbol_,". Error ", GetLastError()); return; } //--- prices = log(prices); //---get returns vector returns = np::diff(prices); //--- if(ScaleFactor>1) returns*=ScaleFactor; //--- spec.observations = returns; //--- HARX* arma_garch = arch_model(spec); if(!arma_garch) return; //--- ArchParameters final_spec = arma_garch.get_specification(); Print("GARCH spec"); PrintFormat("P(%d) O(%d) Q(%d) Power(%f)",final_spec.garch_p,final_spec.garch_o,final_spec.garch_q,final_spec.vol_power); //--- #ifdef __SLSQP__ ArchModelResult mt5_result = arma_garch.fit(); #else ArchModelResult mt5_result = arma_garch.fit(ScaleFactor); #endif //--- if(mt5_result.params.Size()) { Print("MT5 model parameters: ", mt5_result.params); Print("MT5 model LogLikelihood: ", -1.*mt5_result.loglikelihood); } else Print("Fitting model failed"); delete arma_garch; //--- string cmdLine = StringFormat("%s %s%s%s","python ",TerminalInfoString(TERMINAL_DATA_PATH),PYFILE,cmd_builder(Symbol_, StartDate,TimeFrame,HistoryLength,VolatilityModel, ScaleFactor,MeanModel,MeanConstant,MeanLags, ErrorDistribution,final_spec.garch_p,final_spec.garch_o,final_spec.garch_q)); //Print(cmdLine); //--- PROCESS_INFORMATION piProcInfo; STARTUPINFOW siStartInfo; BOOL process_run = false; //--- ZeroMemory(piProcInfo); ZeroMemory(siStartInfo); siStartInfo.cb = sizeof(STARTUPINFOW); vector parameters; //--- if(CreateProcessW(NULL,cmdLine,NULL,NULL,0,DETACHED_PROCESS,NULL,NULL,siStartInfo,piProcInfo)) { WaitForSingleObject(piProcInfo.hProcess,INFINITE); uint exitcode; GetExitCodeProcess(piProcInfo.hProcess,exitcode); if(!exitcode) { CFileTxt jfile; if(jfile.Open(FILENAME,FILE_READ|FILE_COMMON) != INVALID_HANDLE) { CJAVal js; if(js.Deserialize(jfile.ReadString())) { int jsize = js["x"].Size(); parameters = vector::Zeros(jsize); for(int i = 0; i 0) ? mlags : "0"; string out = StringFormat("%s %s %s %s %s %G %I64u %I64u %I64u %I64u %s %d %s %s %s", SPACE, FILENAME, stime, symb, tf_str, scalef, hist, P, O, Q, mmod_str, (mconst ? 1 : 0), vmod_str, edist_str, final_lags); return out; } //+------------------------------------------------------------------+