//+------------------------------------------------------------------+ //| EconometricsM.mqh | //| Copyright 2000-2026, MetaQuotes Ltd. | //| www.mql5.com | //+------------------------------------------------------------------+ //--- #include "EconometricsA.mqh" //--- //+------------------------------------------------------------------+ //| struct for coefficients testing | //+------------------------------------------------------------------+ struct CoefficientStats { double estimate; // point estimate double std_error; // standard error double t_stat; // t-statistic double p_value; // one-sided p-value double conf_low; // low bound of confidence interval double conf_high; // high bound of confidence interval }; //+------------------------------------------------------------------+ //| struct for prognosed data | //+------------------------------------------------------------------+ struct SPrognose { vector xnew; // regressors for prognose (xnew[0]==1!) double point_progn; // point prognose (mean) double conf_low; // low bound of confidence interval double conf_high; // high bound of confidence interval double progn_low; // low bound of prognose interval double progn_high; // high bound of prognose interval void print() // print struct { PrintFormat("point prognose: %.3f",point_progn); PrintFormat("confidence interval, low bound: %.3f, high bound: %.3f",conf_low,conf_high); PrintFormat("prognose interval, low bound: %.3f, high bound: %.3f",progn_low,progn_high); }; }; //+------------------------------------------------------------------+ //| struct for prognosed data for TSLS | //+------------------------------------------------------------------+ struct SPrognose_TSLS { vector xnew_exo; // regressors for prognose (xnew_exo[0]==1!) vector xnew_endo; // regressors for prognose vector znew_iv; // instruments for prognose double point_progn; // point prognose (mean) double conf_low; // low bound of confidence interval double conf_high; // high bound of confidence interval double progn_low; // low bound of prognose interval double progn_high; // high bound of prognose interval void print() // print struct { PrintFormat("point prognose: %.3f",point_progn); PrintFormat("confidence interval, low bound: %.3f, high bound: %.3f",conf_low,conf_high); PrintFormat("prognose interval, low bound: %.3f, high bound: %.3f",progn_low,progn_high); }; }; //+------------------------------------------------------------------+ //| Computation of parameters and residuals for multiple regression | //| Inputs: y - target variable, X - regressors | //| Outputs: b - parameters, e - residuals, c - residuals' SD | //+------------------------------------------------------------------+ void regression(vector& y, matrix& X, vector& b, vector& e, double& c) { //--- Input data validation ulong k=X.Cols(); if(k<1) {Print("error: empty X"); return;} ulong n=X.Rows(); if(n 0) { stats[i].t_stat = stats[i].estimate / stats[i].std_error; //--- MathCumulativeDistributionT returns the left-tail probability P(T <= t) double p_cumulative = MathCumulativeDistributionT(MathAbs(stats[i].t_stat), (double)df, err_code); stats[i].p_value = 1.0 - p_cumulative; } else { stats[i].t_stat = 0.0; stats[i].p_value = 1.0; } //--- Calculate the confidence interval bounds for the coefficient stats[i].conf_low = stats[i].estimate - (t_crit * stats[i].std_error); stats[i].conf_high = stats[i].estimate + (t_crit * stats[i].std_error); } //--- Out-of-sample forecasting stage using the instrumented approach //--- 1. Construct the complete out-of-sample instrument vector Z0 = [xnew_exo | znew_iv] vector z0 = prog.xnew_exo.Concat(prog.znew_iv); //--- 2. Clean the future: project the future endogenous variables using first-stage coefficients prog.xnew_endo = z0.MatMul(B_first); //--- 3. Form the final cleaned out-of-sample regressor vector for the second-stage equation vector x0_hat = prog.xnew_exo.Concat(prog.xnew_endo); //--- 4. Calculate the symmetric point forecast (mean prediction) using vector dot product prog.point_progn = x0_hat.MatMul(b_vec); //--- 5. Calculate the variance scale factor (g-factor) for the out-of-sample bar matrix X0_mat(1, x0_hat.Size()); X0_mat.Row(x0_hat, 0); matrix X0_T = X0_mat.Transpose(); matrix shift_mat = X0_mat.MatMul(XX_inv).MatMul(X0_T); //--- Extract the scalar value from the 1x1 matrix using explicit indexing double g_factor = shift_mat[0][0]; //--- 6. Calculate the standard errors for both the confidence interval and the prediction interval double se_conf = MathSqrt(sigma_sq * g_factor); double se_pred = MathSqrt(sigma_sq * (1.0 + g_factor)); //--- 7. Derive half-widths for the interval bounds using the critical t-value double conf_width = t_crit * se_conf; double pred_width = t_crit * se_pred; //--- 8. Write upper and lower boundaries into the SPrognose_TSLS structure fields prog.conf_low = prog.point_progn - conf_width; prog.conf_high = prog.point_progn + conf_width; prog.progn_low = prog.point_progn - pred_width; prog.progn_high = prog.point_progn + pred_width; } //+------------------------------------------------------------------+ //| Computation of the correlation matrix (assumed X1==const) | //| Inputs: y - target variable, X - regressors | //| Output: CM - correlation matrix | //+------------------------------------------------------------------+ void corr_matrix(vector& y, matrix& X, matrix& CM) { //--- Input data validation ulong k=X.Cols(); if(k<1) {Print("corr_matrix() error: empty X"); return;} ulong n=X.Rows(); if(y.Size()!=n) {Print("corr_matrix() error: wrong size of y"); return;} matrix yX=X; yX.Col(y,0); CM=yX.CorrCoef(false); } //+------------------------------------------------------------------+ //| Residuals plot vs. price bar index | //+------------------------------------------------------------------+ void t_residuals_plot(vector& residuals) { double e[]; vector2array(residuals,e); t_residuals_plot(e); } //+------------------------------------------------------------------+ //| EPDF of residuals vs. normal density with residual SD | //| nofx - number of points on plot | //+------------------------------------------------------------------+ void epdf_vs_normalpdf(vector& residuals, int nofx = 30) { double e[]; vector2array(residuals,e); epdf_vs_normalpdf(e,nofx); } //+------------------------------------------------------------------+ //| QQ-plot of residuals vs. normal distribution with residual SD | //+------------------------------------------------------------------+ void qq_plot(vector& residuals) { double e[]; vector2array(residuals,e); qq_plot(e); } //+------------------------------------------------------------------+ //| Correlogram of residuals | //+------------------------------------------------------------------+ void correlogram(vector& residuals) { double e[]; vector2array(residuals,e); correlogram(e); } //+------------------------------------------------------------------+ //| Scatter plot of (x, y) points with line y = a * x + b | //+------------------------------------------------------------------+ void scatter_plot(vector& x, vector& y, bool add_line = false, double a = 0.0, double b = 0.0) { double xa[],ya[]; vector2array(x,xa); vector2array(y,ya); scatter_plot(xa,ya,add_line,a,b); } //+------------------------------------------------------------------+ //| Scatter plot of (Xi, y) and fitted regression line | //| Inputs: X - regressors matrix, y - target variable, | //| i - regressor's index (X column index) | //+------------------------------------------------------------------+ void scatter_plot_Xi_y(matrix& X, ulong i, vector& y) { if(i>=X.Cols()) { Print("input regressor's index is out of range"); return; } double a,b,c; vector e; regression1(y,X.Col(i),a,b,c,e); scatter_plot(X.Col(i),y,true,a,b); } //+------------------------------------------------------------------+ //| Scatter plot of (Xi, Xj) and fitted regression line | //| Inputs: X - regressors matrix, | //| i, j - regressors' indexes (X columnes indexes) | //+------------------------------------------------------------------+ void scatter_plot_Xi_Xj(matrix& X, ulong i, ulong j) { if(i>=X.Cols()||j>=X.Cols()) { Print("input regressor's index is out of range"); return; } double a,b,c; vector e; regression1(X.Col(j),X.Col(i),a,b,c,e); scatter_plot(X.Col(i),X.Col(j),true,a,b); } //+------------------------------------------------------------------+ //| Partial regression plot for Xi | //| Inputs: X - regressors matrix, y - target variable, | //| i - regressor's index (X column index) | //+------------------------------------------------------------------+ void partial_regression_plot(matrix& X, ulong i, vector& y) { //--- Input data validation ulong k=X.Cols(); if(k<2) { Print("too few regressors"); return; } if(i>=k) { Print("input regressor's index is out of range"); return; } double a,b,c; vector x=X.Col(i),ey,ex,e1,bv; //--- matrix without Xi matrix X_1=X; if(i!=k-1) X_1.Col(X_1.Col(k-1),i); X_1.Resize(X_1.Rows(),k-1); regression(y,X_1,bv,ey,c); regression(x,X_1,bv,ex,c); regression1(ey,ex,a,b,c,e1); scatter_plot(ex,ey,true,a,b); } //+------------------------------------------------------------------+ //| Scatter plot of (Yfit, Yreal) and line y = x | //| Inputs: X - regressors matrix, b - parameters vector | //| y - real values of dependent variable | //+------------------------------------------------------------------+ void scatter_plot_Yfit_Yreal(matrix& X, vector& b, vector& y) { //--- Input data validation ulong k=X.Cols(); if(k<1) {Print("error: empty X"); return;} if(b.Size()!=k) {Print("error: wrong size of b"); return;} ulong n=X.Rows(); if(y.Size()!=n) {Print("error: wrong size of y"); return;} scatter_plot(X.MatMul(b),y,true,0.0,1.0); } //+------------------------------------------------------------------+ //| Scatter plot of (Yfit, residuals) | //| Inputs: X - regressors matrix, b - parameters vector | //| e - residuals | //+------------------------------------------------------------------+ void scatter_plot_Yfit_residuals(matrix& X, vector& b, vector& e) { //--- Input data validation ulong k=X.Cols(); if(k<1) {Print("error: empty X"); return;} if(b.Size()!=k) {Print("error: wrong size of b"); return;} ulong n=X.Rows(); if(e.Size()!=n) {Print("error: wrong size of e"); return;} scatter_plot(X.MatMul(b),e); } //+------------------------------------------------------------------+ //| R^2, coefficient of determination | //| Inputs: y - real values of dependent variable, e - residuals | //+------------------------------------------------------------------+ double R2(vector& y, vector& e) { //--- Input data validation ulong n=y.Size(); if(n<2) {Print("R2() error: y too short"); return 0.0;} if(e.Size()!=n) {Print("R2() error: different sizes of y and e"); return 0.0;} double Sy=y.Var(0); if(Sy<=DBL_MIN) {Print("R2() error: y = const"); return 0.0;} return 1.0-e.Var(0)/Sy; } //+------------------------------------------------------------------+ //| R^2_adj, adjusted coefficient of determination | //| Inputs: y - real values of dependent variable, e - residuals | //| k - number of regressors | //+------------------------------------------------------------------+ double R2_adj(vector& y, vector& e, ulong k) { //--- Input data validation ulong n=y.Size(); if(n<2) {Print("R2_adj() error: y too short"); return 0.0;} if(n<=k) {Print("R2_adj() error: n <= k"); return 0.0;} if(e.Size()!=n) {Print("R2_adj() error: different sizes of y and e"); return 0.0;} double Sy=y.Var(1); if(Sy<=DBL_MIN) {Print("R2_adj() error: y = const"); return 0.0;} return 1.0-e.Var((int)k)/Sy; } //+------------------------------------------------------------------+ //| VIF, Variance Inflation Factor for X2, ..., Xk (assumed X1=const)| //| Input: X - regressors | //| Output: vif - (k-1)-size VIF vector | //+------------------------------------------------------------------+ void VIF(matrix& X, vector& vif) { //--- Input data validation ulong k=X.Cols(), n=X.Rows(); if(k<2) {Print("VIF() error: not enough regressors"); return;} if(n=k) {Print("error: out of regressors range"); return;} for(int i=0;i=0;--i) { if(irs[i]to) return; if(to>=A.Cols()) return; if(A.Rows()<2) return; double m, s; for(ulong i=from;i<=to; ++i) {m=A.Col(i).Mean(); s=A.Col(i).Std(); A.Col((A.Col(i)-m)/s,i);} } //+------------------------------------------------------------------+ //| Helper functions to export vector, matrix and vector+matrix | //| to text file (for data analysis in other programs) | //+------------------------------------------------------------------+ string vector2string(vector& v) { ulong k=v.Size(); if(k<1) return ""; string res=DoubleToString(v[0]); for(ulong i=1;i