311 lines
9.2 KiB
MQL5
311 lines
9.2 KiB
MQL5
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| 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<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()
|
||
|
|
{
|
||
|
|
#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; 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)
|
||
|
|
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<jsize; ++i)
|
||
|
|
parameters[i] = js["x"][i].ToDbl();
|
||
|
|
Print("Python's Model Parameters ", parameters);
|
||
|
|
Print("Python's LogLikelihood: ", js["fun"].ToDbl());
|
||
|
|
}
|
||
|
|
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);
|
||
|
|
}
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
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;
|
||
|
|
}
|
||
|
|
//+------------------------------------------------------------------+
|