//+------------------------------------------------------------------+ //| utils.mqh | //| Copyright 2025, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2025, MetaQuotes Ltd." #property link "https://www.mql5.com" #include //+------------------------------------------------------------------+ //| Constant and trend used in regression model | //+------------------------------------------------------------------+ enum ENUM_TREND { TREND_NONE=0, TREND_CONST_ONLY, TREND_LINEAR_ONLY, TREND_LINEAR_CONST, TREND_QUAD_LINEAR_CONST }; //+------------------------------------------------------------------+ //| Options for how to handle existing constants | //+------------------------------------------------------------------+ enum ENUM_HAS_CONST { HAS_CONST_RAISE=0, HAS_CONST_SKIP, HAS_CONST_ADD }; //+------------------------------------------------------------------+ //| Options for trimming invalid observations | //+------------------------------------------------------------------+ enum ENUM_TRIM { TRIM_NONE=0, TRIM_FORWARD, TRIM_BACKWARD, TRIM_BOTH }; //+------------------------------------------------------------------+ //| options for how to handle original data set | //+------------------------------------------------------------------+ enum ENUM_ORIGINAL { ORIGINAL_EX=0, ORIGINAL_IN, ORIGINAL_SEP }; //+------------------------------------------------------------------+ //| Yule walker calculation options | //+------------------------------------------------------------------+ enum ENUM_YW_METHOD { YW_ADJUSTED=0,//adjusted YW_MLE//mle }; //+------------------------------------------------------------------+ //| YW result struct | //+------------------------------------------------------------------+ struct YWResult { double sigma; vector rho; matrix inv; YWResult(void) { sigma = EMPTY_VALUE; rho = vector::Zeros(0); inv = matrix::Zeros(0,0); } ~YWResult(void) { } YWResult(YWResult& other) { sigma = other.sigma; rho = other.rho; inv = other.inv; } void operator=(YWResult& other) { sigma = other.sigma; rho = other.rho; inv = other.inv; } }; //+------------------------------------------------------------------+ //| sequence | //+------------------------------------------------------------------+ //| The function generates a sequence of double numbers | //| with given starting and ending values and step. | //| | //| Arguments: | //| from : Starting value of the sequence | //| to : Last value of the sequence | //| step : Step of the sequence | //| result[] : Array for the sequence values | //| | //| Return value: true if successful, otherwise false. | //+------------------------------------------------------------------+ bool Sequence(const double from,const double to,const double step,double &result[]) { //--- check NaN if(!MathIsValidNumber(from) || !MathIsValidNumber(to) || !MathIsValidNumber(step)) return(false); if(to=nobs) { Print("mlag should be < number of rows of the input matrix"); return false; } //--- if(original==ORIGINAL_EX || original==ORIGINAL_SEP) dropidx = nvars; //--- matrix nn; //--- if(!nn.Resize(nobs + mlag,nvars * (mlag + 1))) { Print(__FUNCTION__," ",__LINE__," Resize Error ", ::GetLastError()); return false; } //--- nn.Fill(0.0); //--- ulong maxlag=mlag; //--- ulong row_end,row_start,col_end,col_start,j,z; row_end=row_start=col_end=col_start=j=z=0; //--- for(ulong k = 0; k<(maxlag+1); k++) { row_start = maxlag-k; row_end = nobs+maxlag-k; col_start = nvars*(maxlag-k); col_end = nvars*(maxlag-k+1); j = 0; for(ulong irow = row_start; irow < row_end; irow++, j++) { z = 0; for(ulong icol = col_start; icol < col_end; icol++, z++) nn[irow][icol]=in[j][z]; } } //--- ulong startobs,stopobs; if(trim==TRIM_NONE || trim==TRIM_FORWARD) startobs=0; else startobs=maxlag; //--- if(trim==TRIM_NONE || trim==TRIM_BACKWARD) stopobs=nn.Rows(); else stopobs=nobs; //--- if(dropidx && original==ORIGINAL_SEP) ArrayResize(out,2); else ArrayResize(out,1); //--- if(!out[0].Resize(stopobs-startobs,nn.Cols()-dropidx)) { Print(__FUNCTION__," ",__LINE__," Resize Error ", ::GetLastError()); return false; } //--- for(ulong irow = startobs; irow1) { if(!out[1].Resize(stopobs-startobs,dropidx)) { Print(__FUNCTION__," ",__LINE__," Resize Error ", GetLastError()); return false; } //--- for(ulong irow = startobs; irow matrix toeplitz(vector& x) { ulong n = x.Size(); matrix out(n,n); for(ulong i = 0; i matrix toeplitz(vector& x, vector& y) { ulong nx = x.Size(); ulong ny = y.Size(); vector z = vector::Zeros(nx+ny-1); ulong start = 1; for(ulong i = 0; i out(nx,ny); for(ulong i = 0; i0?df:long(in.Size()); vector r = vector::Zeros(order+1); r[0] = pow(in,2.0).Sum()/double(n); double adj_needed = (double)(method == YW_ADJUSTED); for(long k = 1; k<(order+1); ++k) { double sum = 0; for(long i = 0; i<(long(in.Size()) - k); ++i) sum+=(in[i]*in[k+i]); r[k] = sum/double(n - k*adj_needed); } vector rslice = vector::Zeros(r.Size()-1); for(ulong i = 0; i0) out.sigma = sqrt(sigmasq); else out.sigma = double("nan"); if(inv) out.inv = R.Inv(); return out; } //+------------------------------------------------------------------+