339 lines
12 KiB
MQL5
339 lines
12 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| base.mqh |
|
|
//| Copyright 2025, MetaQuotes Ltd. |
|
|
//| https://www.mql5.com |
|
|
//+------------------------------------------------------------------+
|
|
#property copyright "Copyright 2025, MetaQuotes Ltd."
|
|
#property link "https://www.mql5.com"
|
|
#include<np.mqh>
|
|
#include"..\Utility\wald.mqh"
|
|
#include<Regression\OLS.mqh>
|
|
#include<Regression\utils.mqh>
|
|
//---
|
|
#define EMPTY_VECTOR vector::Zeros(0)
|
|
#define EMPTY_MATRIX matrix::Zeros(0,0)
|
|
//---
|
|
vector EMPTY_VECTOR_ARRAY[];
|
|
matrix EMPTY_MATRIX_ARRAY[];
|
|
//+------------------------------------------------------------------+
|
|
//| covariance type |
|
|
//+------------------------------------------------------------------+
|
|
enum ENUM_COVAR_TYPE
|
|
{
|
|
COVAR_CLASSIC = 0,//classic
|
|
COVAR_ROBUST//robust
|
|
};
|
|
//+------------------------------------------------------------------+
|
|
//| forecasting method |
|
|
//+------------------------------------------------------------------+
|
|
enum ENUM_FORECAST_METHOD
|
|
{
|
|
FORECAST_ANALYTIC=0,//analytic
|
|
FORECAST_SIMULATION,//simulation
|
|
FORECAST_BOOTSTRAP//bootstrap
|
|
};
|
|
//+------------------------------------------------------------------+
|
|
//| forecast alignment |
|
|
//+------------------------------------------------------------------+
|
|
enum ENUM_FORECAST_ALIGNMENT
|
|
{
|
|
ALIGN_ORIGIN = 0,//origin
|
|
ALIGN_TARGET//target
|
|
};
|
|
//+------------------------------------------------------------------+
|
|
//| mean models |
|
|
//+------------------------------------------------------------------+
|
|
enum ENUM_MEAN_MODEL
|
|
{
|
|
MEAN_CONSTANT=0,//Constant Mean
|
|
MEAN_ZERO,//Zero Mean
|
|
MEAN_AR,//AR
|
|
MEAN_ARX,//AR-X
|
|
MEAN_HAR,//HAR
|
|
MEAN_HARX//HAR-X
|
|
};
|
|
//---
|
|
//+------------------------------------------------------------------+
|
|
//| volatility models |
|
|
//+------------------------------------------------------------------+
|
|
enum ENUM_VOLATILITY_MODEL
|
|
{
|
|
VOL_CONST=0,//Constant Variance
|
|
VOL_ARCH,//ARCH
|
|
VOL_GARCH//GARCH
|
|
};
|
|
//---
|
|
//+------------------------------------------------------------------+
|
|
//| distributions |
|
|
//+------------------------------------------------------------------+
|
|
enum ENUM_DISTRIBUTION_MODEL
|
|
{
|
|
DIST_NORMAL=0//Normal
|
|
};
|
|
//---
|
|
//+------------------------------------------------------------------+
|
|
//|Test a matrix for an implicit constant |
|
|
//+------------------------------------------------------------------+
|
|
bool implicit_constant(matrix &exog_data)
|
|
{
|
|
ulong nobs = exog_data.Rows();
|
|
matrix temp(nobs,exog_data.Cols()+1);
|
|
vector ones = vector::Ones(nobs);
|
|
temp.Col(ones,0);
|
|
for(ulong i = 1; i<temp.Cols(); ++i)
|
|
temp.Col(exog_data.Col(i-1),i);
|
|
ulong rank = temp.Rank();
|
|
return (rank == exog_data.Cols());
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//|reindex |
|
|
//+------------------------------------------------------------------+
|
|
bool _reindex(ulong actual, matrix& in[], matrix& out[])
|
|
{
|
|
ulong obs = ulong(in.Size());
|
|
if(actual>obs)
|
|
{
|
|
ArrayResize(out,int(actual));
|
|
matrix temp = matrix::Zeros(in[0].Rows(),in[0].Cols());
|
|
temp.Fill(EMPTY_VALUE);
|
|
for(uint i = 0; i<uint(actual - obs); ++i)
|
|
out[i] = (i<uint(actual - obs))?temp:in[i-uint(actual - obs)];
|
|
}
|
|
return true;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//|reindex |
|
|
//+------------------------------------------------------------------+
|
|
matrix _reindex(ulong actual, matrix& in)
|
|
{
|
|
ulong obs = ulong(in.Rows());
|
|
if(actual>obs)
|
|
{
|
|
matrix out(actual);
|
|
vector temp = vector::Zeros(in.Cols());
|
|
temp.Fill(EMPTY_VALUE);
|
|
for(ulong i = 0; i<(actual - obs); ++i)
|
|
out.Row((i<(actual - obs))?temp:in.Row(i-(actual - obs)),i);
|
|
return out;
|
|
}
|
|
return in;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//|reindex |
|
|
//+------------------------------------------------------------------+
|
|
vector _reindex(ulong actual, vector& in)
|
|
{
|
|
ulong obs = ulong(in.Size());
|
|
if(actual>obs)
|
|
{
|
|
vector out(actual);
|
|
double temp = EMPTY_VALUE;
|
|
for(ulong i = 0; i<(actual - obs); ++i)
|
|
out[i] = (i<(actual - obs))?temp:in[i-(actual - obs)];
|
|
return out;
|
|
}
|
|
return in;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| generate parameter names |
|
|
//+------------------------------------------------------------------+
|
|
string common_names(ulong p, ulong o, ulong q)
|
|
{
|
|
string names = "omega";
|
|
for(ulong i = 0; i<p; ++i)
|
|
names += ",alpha["+string(i+1)+"]";
|
|
for(ulong i = 0; i<o; ++i)
|
|
names += ",gamma["+string(i+1)+"]";
|
|
for(ulong i = 0; i<q; ++i)
|
|
names += ",beta["+string(i+1)+"]";
|
|
return names;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Arch parameters |
|
|
//+------------------------------------------------------------------+
|
|
|
|
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;
|
|
|
|
ArchParameters(void)
|
|
{
|
|
observations = vector::Zeros(0);
|
|
exog_data = matrix::Zeros(0,0);
|
|
mean_lags = vector::Zeros(0);
|
|
vol_model_type=WRONG_VALUE;
|
|
dist_type=WRONG_VALUE;
|
|
holdout_size=0;
|
|
scaling_factor = 1.0;
|
|
is_rescale_enabled=false;
|
|
mean_model_type = WRONG_VALUE;
|
|
include_constant = true;
|
|
use_har_rotation =false;
|
|
vol_rng_seed = 0;
|
|
garch_p = 1;
|
|
garch_o = 0;
|
|
garch_q = 1;
|
|
vol_power=2.;
|
|
sample_start_idx=1;
|
|
sample_end_idx=-1;
|
|
min_bootstrap_sims=100;
|
|
dist_init_params = vector::Zeros(0);
|
|
dist_rng_seed = 0;
|
|
}
|
|
|
|
|
|
ArchParameters(ArchParameters &other)
|
|
{
|
|
observations = other.observations;
|
|
exog_data = other.exog_data;
|
|
scaling_factor = other.scaling_factor;
|
|
mean_lags = other.mean_lags;
|
|
vol_model_type=other.vol_model_type;
|
|
dist_type=other.dist_type;
|
|
holdout_size=other.holdout_size;
|
|
is_rescale_enabled=other.is_rescale_enabled;
|
|
include_constant = other.include_constant;
|
|
use_har_rotation = other.use_har_rotation;
|
|
vol_rng_seed = other.vol_rng_seed;
|
|
garch_p = other.garch_p;
|
|
garch_o = other.garch_o;
|
|
garch_q = other.garch_q;
|
|
vol_power=other.vol_power;
|
|
sample_start_idx=other.sample_start_idx;
|
|
sample_end_idx=other.sample_end_idx;
|
|
min_bootstrap_sims=other.min_bootstrap_sims;
|
|
dist_init_params = other.dist_init_params;
|
|
dist_rng_seed = other.dist_rng_seed;
|
|
}
|
|
|
|
void operator=(ArchParameters &other)
|
|
{
|
|
observations = other.observations;
|
|
exog_data = other.exog_data;
|
|
scaling_factor = other.scaling_factor;
|
|
mean_lags = other.mean_lags;
|
|
vol_model_type=other.vol_model_type;
|
|
dist_type=other.dist_type;
|
|
holdout_size=other.holdout_size;
|
|
is_rescale_enabled=other.is_rescale_enabled;
|
|
include_constant = other.include_constant;
|
|
use_har_rotation = other.use_har_rotation;
|
|
vol_rng_seed = other.vol_rng_seed;
|
|
garch_p = other.garch_p;
|
|
garch_o = other.garch_o;
|
|
garch_q = other.garch_q;
|
|
vol_power=other.vol_power;
|
|
sample_start_idx=other.sample_start_idx;
|
|
sample_end_idx=other.sample_end_idx;
|
|
min_bootstrap_sims=other.min_bootstrap_sims;
|
|
dist_init_params = other.dist_init_params;
|
|
dist_rng_seed = other.dist_rng_seed;
|
|
}
|
|
};
|
|
//+------------------------------------------------------------------+
|
|
//| arch simulation |
|
|
//+------------------------------------------------------------------+
|
|
struct ArchSimulation
|
|
{
|
|
matrix values[];
|
|
matrix residuals[];
|
|
matrix variances[];
|
|
matrix residual_variances[];
|
|
|
|
ArchSimulation(void)
|
|
{
|
|
}
|
|
ArchSimulation(matrix& _values[],matrix& _residuals[], matrix& _variances[], matrix& _residual_variances[])
|
|
{
|
|
np::copy3D(_values,values);
|
|
np::copy3D(_residuals,residuals);
|
|
np::copy3D(_variances,variances);
|
|
np::copy3D(_residual_variances,residual_variances);
|
|
}
|
|
ArchSimulation(ArchSimulation &other)
|
|
{
|
|
np::copy3D(other.values,values);
|
|
np::copy3D(other.residuals,residuals);
|
|
np::copy3D(other.variances,variances);
|
|
np::copy3D(other.residual_variances,residual_variances);
|
|
}
|
|
void operator=(ArchSimulation &other)
|
|
{
|
|
np::copy3D(other.values,values);
|
|
np::copy3D(other.residuals,residuals);
|
|
np::copy3D(other.variances,variances);
|
|
np::copy3D(other.residual_variances,residual_variances);
|
|
}
|
|
};
|
|
//+------------------------------------------------------------------+
|
|
//| arch forecast result |
|
|
//+------------------------------------------------------------------+
|
|
struct ArchForecast
|
|
{
|
|
matrix mean;
|
|
matrix variance;
|
|
matrix residual_variance;
|
|
ArchSimulation simulation;
|
|
|
|
ArchForecast(void)
|
|
{
|
|
mean = variance = residual_variance = matrix::Zeros(0,0);
|
|
}
|
|
ArchForecast(ulong startindex, matrix& _mean, matrix& _variance, matrix& _res_var, matrix& _values[], matrix& _residuals[], matrix& _variances[], matrix& _residual_variances[])
|
|
{
|
|
mean = _mean;
|
|
variance = _variance;
|
|
residual_variance = _res_var;
|
|
|
|
np::copy3D(_values,simulation.values);
|
|
np::copy3D(_residuals,simulation.residuals);
|
|
np::copy3D(_variances,simulation.variances);
|
|
np::copy3D(_residual_variances,simulation.residual_variances);
|
|
}
|
|
ArchForecast(ArchForecast &other)
|
|
{
|
|
mean = other.mean;
|
|
variance = other.variance;
|
|
residual_variance = other.residual_variance;
|
|
simulation = other.simulation;
|
|
}
|
|
|
|
void operator=(ArchForecast &other)
|
|
{
|
|
mean = other.mean;
|
|
variance = other.variance;
|
|
residual_variance = other.residual_variance;
|
|
simulation = other.simulation;
|
|
}
|
|
};
|
|
//+------------------------------------------------------------------+
|