1
0
Derivar 0
Article-22714-Volatility-Mo.../Scripts/slsqp_article/LogLikelihoodVerification.mq5

297 linhas
9 KiB
MQL5

2026-06-03 20:14:05 +02:00
//+------------------------------------------------------------------+
//| LogLikelihoodVerification.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"
"Pythons ARCH module. It then gets the model"
"parameters and uses them to evaluate the loglikelihood"
"function in MQL5 for comparison with the final"
"return of the optimization procedure."
#include<slsqp_article\Arch\Univariate\mean.mqh>
#include<slsqp_article\win32_utils.mqh>
#include<slsqp_article\JAson.mqh>
#include<Files\FileTxt.mqh>
//---
#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()
{
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; i<uint(nlags); ++i)
{
if(StringLen(lag_info[i])>0)
{
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)
{
Print("Invalid HARX pointer");
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);
//---
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));
//---
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<jsize; ++i)
parameters[i] = js["x"][i].ToDbl();
Print("Python's LogLikelihood: ", js["fun"].ToDbl());
Print("Python's Model Parameters ", parameters);
}
else
Print("Failed to deserialize the model");
jfile.Delete(FILENAME,FILE_COMMON);
}
else
Print("File open error ", GetLastError());
}
else
Print("Python process failed to execute successfully.");
}
else
printf("CreateProcess failed with error %d\n", kernel32::GetLastError());
//---
CloseHandle(piProcInfo.hProcess);
CloseHandle(piProcInfo.hThread);
//---
double mt5_loglikelihood = 0;
vector mt5_jac;
if(arma_garch.eval_loglikelihood(parameters,mt5_loglikelihood))
Print("MT5 LogLikelihood: ", mt5_loglikelihood);
else
Print("Failed to evaluate the objective function.");
delete arma_garch;
}
//+------------------------------------------------------------------+
HARX* arch_model(ArchParameters &archparameters)
{
HARX* out = NULL;
switch(archparameters.mean_model_type)
{
case MEAN_CONSTANT:
out = new ConstantMean();
break;
case MEAN_AR:
out = new AR();
break;
case MEAN_ARX:
out = new ARX();
break;
case MEAN_HAR:
out = new HAR();
break;
case MEAN_HARX:
out = new HARX();
break;
case MEAN_ZERO:
out = new ZeroMean();
break;
default:
out = new ConstantMean();
break;
}
if(CheckPointer(out)==POINTER_DYNAMIC)
{
if(out.initialize(archparameters))
return out;
else
{
delete out;
return NULL;
}
}
else
return out;
}
//+------------------------------------------------------------------+
//| parse model options |
//+------------------------------------------------------------------+
string cmd_builder(string symb, datetime sdate, ENUM_TIMEFRAMES tf, ulong hist,ENUM_VOLATILITY_MODEL vmod, double scalef, ENUM_MEAN_MODEL mmod, bool mconst, string mlags, ENUM_DISTRIBUTION_MODEL edist, ulong P, ulong O, ulong Q)
{
string stime = TimeToString(sdate, TIME_DATE|TIME_MINUTES);
StringReplace(stime, " ", "_");
string tf_str = EnumToString(tf);
tf_str = StringSubstr(tf_str, 7);
string mmod_str = "";
switch(mmod)
{
case MEAN_CONSTANT:
mmod_str = "constant";
break;
case MEAN_ZERO:
mmod_str = "zero";
break;
case MEAN_AR:
mmod_str = "ar";
break;
case MEAN_ARX:
mmod_str = "arx";
break;
case MEAN_HAR:
mmod_str = "har";
break;
case MEAN_HARX:
mmod_str = "harx";
break;
default:
mmod_str = "constant";
break;
}
string vmod_str = "garch";
switch(vmod)
{
case VOL_ARCH:
vmod_str = "arch";
break;
case VOL_CONST:
vmod_str = "constant";
break;
case VOL_AVARCH:
vmod_str = "avarch";
break;
case VOL_AVGARCH:
vmod_str = "avgarch";
break;
case VOL_TARCH:
vmod_str = "tarch";
break;
case VOL_GJR_GARCH:
vmod_str = "gjr-garch";
break;
default:
vmod_str = "garch";
break;
}
string edist_str = "";
switch(edist)
{
case DIST_NORMAL:
edist_str = "normal";
break;
case DIST_GEN_ERROR:
edist_str = "gen-error";
break;
case DIST_SKEW_STUDENT:
edist_str = "skewed-student";
break;
case DIST_STUDENT:
edist_str = "student";
break;
default:
edist_str = "normal";
break;
}
string final_lags = (StringLen(mlags) > 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;
}
//+------------------------------------------------------------------+