//+------------------------------------------------------------------+ //| acf.mqh | //| Copyright 2025, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2025, MetaQuotes Ltd." #property link "https://www.mql5.com" #include"..\..\np_graphics.mqh" #include //+------------------------------------------------------------------+ //| autocorrelation function result struct | //+------------------------------------------------------------------+ struct ACFResult { vector acf; vector qstats; vector pvalues; matrix conf_intervals; ACFResult(void) { acf = qstats = pvalues = vector::Zeros(0); conf_intervals = matrix::Zeros(0,0); } ACFResult(vector& _acf, vector& _qstats, vector& _pvalues, matrix& _confintervals) { acf = _acf; qstats = _qstats; pvalues = _pvalues; conf_intervals = _confintervals; } ACFResult(ACFResult& other) { acf = other.acf; qstats = other.qstats; pvalues = other.pvalues; conf_intervals = other.conf_intervals; } void operator=(ACFResult& other) { acf = other.acf; qstats = other.qstats; pvalues = other.pvalues; conf_intervals = other.conf_intervals; } }; //+------------------------------------------------------------------+ //| ACF function | //+------------------------------------------------------------------+ ACFResult acf(vector& x, ulong nlags = 0, double alpha = 0.05, bool bartlett_conf=false, bool demean= true, bool adjusted = false) { ACFResult out; ulong nobs = x.Size(); if(!nobs) { Print(__FUNCTION__, " input container is empty "); return out; } if(!nlags) nlags = MathMin(ulong(10*log10(nobs)), nobs-1); vector avf = acovf(x,0,demean,adjusted); if(!avf.Size()) return out; out.acf = np::sliceVector(avf,0,long(nlags+1)); out.acf /=avf[0]; int ec = 0; if(bartlett_conf) { vector varacf = vector::Ones(out.acf.Size())/double(nobs); varacf[0] = 0.; varacf[1] = 1./double(nobs); vector temp = np::sliceVector(out.acf,1,out.acf.Size()-1); vector tempsq = pow(temp,2.); temp = np::sliceVector(varacf,2); temp*=1.0+2.*tempsq.CumSum(); np::vectorCopy(varacf,temp,2); vector interval = CNormalDistr::InvNormalCDF(1. - alpha/2.)*sqrt(varacf); out.conf_intervals = matrix::Zeros(2,varacf.Size()); out.conf_intervals.Row(out.acf-interval,0); out.conf_intervals.Row(out.acf+interval,1); } else { double varacf = 1./double(x.Size()); double nv = CNormalDistr::InvNormalCDF(1. - alpha/2.); double interval = nv*sqrt(varacf); out.conf_intervals = matrix::Zeros(2,out.acf.Size()); out.conf_intervals.Row(out.acf-interval,0); out.conf_intervals.Row(out.acf+interval,1); } vector temp = np::sliceVector(out.acf,1); q_stat(temp,nobs,out.qstats,out.pvalues); return out; } /*//+------------------------------------------------------------------+ //|Find the next regular number greater than or equal to target. | //+------------------------------------------------------------------+ long next_target(long target) { if(target<=6) return target; if(!(target&(target-1))) return target; double match = AL_POSINF; long p5 = 1; long p35,quotient,N,p2; while(p5=2) { var = var/2; ++count; } return count; }*/ //+------------------------------------------------------------------+ //|acovf | //+------------------------------------------------------------------+ vector acovf(vector &in, ulong lags = 0,bool demean= true, bool adjusted = false) { vector xo,acov; if(demean) xo = in - in.Mean(); else xo = in; ulong n = in.Size(); ulong laglen = lags; if(!laglen) laglen = n-1; else if(lags>n-1) { Print(__FUNCTION__, " nlag must be smaller than ",n - 1); return vector::Zeros(0); } acov = vector::Zeros(laglen+1); acov[0] = xo.Dot(xo); if(lags) { vector a,b; for(ulong i = 0; i