//------------------------------------------------------------------------------------ // CEMDecomp.mqh // Version 1.01 // 2012, victorg // http://www.mql5.com //------------------------------------------------------------------------------------ #include //------------------------------------------------------------------------------------ // The Empirical Mode Decomposition (EMD). //------------------------------------------------------------------------------------ class CEMDecomp:public CObject { public: int N; // Input and output data size double Mean; // Mean of input data int nIMF; // IMF counter int MaxIMF; // Maximum number of IMF int MaxIter; // Maximum number of iterations int FixedIter; // 0-variable number of sifting iterations; // 1-always ten sifting iterations. double IMFResult[]; // Result. private: double X[]; double Imf[]; double XMax[]; // x of local maxima double YMax[]; // y of local maxima double XMin[]; // x of local minima double YMin[]; // y of local minima double EnvUpp[]; // Upper envelope double EnvLow[]; // Lower envelope double Eps; // Accuracy comparison of floating-point numbers double Tol; // Accuracy of calculation IMF public: void CEMDecomp(void); int Decomp(double &y[]); // Decomposition void GetIMF(double &x[], int nn); // Get IMF number nn private: int arrayprepare(void); void extrema(double &y[],int &nmax,double &xmax[],double &ymax[], int &nmin,double &xmin[],double &ymin[]); int SplineInterp(double &x[],double &y[],int n,double &x2[], double &y2[],int btype=0); }; //------------------------------------------------------------------------------------ // Constructor. //------------------------------------------------------------------------------------ void CEMDecomp::CEMDecomp(void) { FixedIter=0; MaxIMF=16; // The maximum number of IMF MaxIter=2000; // The maximum number of iterations Eps=8*DBL_EPSILON; // Accuracy comparison of floating-point numbers Tol=1e-6; // Accuracy of calculation IMF } //------------------------------------------------------------------------------------ // Decomposition. // Input: // y[] - Input data // Result: // nIMF - Number of IMF plus one; // IMFResult[0],...,IMFResult[N-1] - Input data minus mean; // IMFResult[1*N],...,IMFResult[1*N+N-1] - IMF number 1; // . . . // IMFResult[(nIMF-1)*N],...,IMFResult[(nIMF-1)*N+N-1] - IMF number nIMF-1; // IMFResult[nIMF*N],...,IMFResult[nIMF*N+N-1] - Residue of decomposition. // Return: // 0 - No error. // -1 - Insufficient length of the input data. // -2 - ArrayResize() error. //------------------------------------------------------------------------------------ int CEMDecomp::Decomp(double &y[]) { int i,j,iter,nmax,nmin,sstop; double a,b,c; N=ArraySize(y); if(N<6) { Print(__FUNCTION__,": Error! Insufficient length of the input data."); return(-1); } j=arrayprepare(); if(j<0){Print(__FUNCTION__,": Error! ArrayResize() error."); return(-2);} Mean=0; for(i=0;iDBL_MIN+Eps*MathMax(MathAbs(b),MathAbs(c))) // b != c { if(((b>c)&&(b>a))||((b XMin[],YMin[],XMax[],YMax[] extrema(Imf,nmax,XMax,YMax,nmin,XMin,YMin); // ----- Upper and Lower envelope if(nmax<2)for(i=0;i0)sstop=0; if(sstop==1)for(i=0;iTol)sstop=0; } if(sstop==1)break; // Stop sifting } else if(iter>8)break; // always only ten iterations iter++; } if(iter>=MaxIter) Print(__FUNCTION__,": Warning! Reached the maximum number of iterations."); // ----- Find extremas a=Imf[0]; b=Imf[1]; j=0; for(i=1;iDBL_MIN+Eps*MathMax(MathAbs(b),MathAbs(c))) // b != c { if(((b>c)&&(b>a))||((bN)k=N; if(nn<0||nn>nIMF||nIMF==0)for(i=0;i=-e)&&((c-b)>=-e)){xmin[2+nmin]=i; ymin[2+nmin++]=y[i];} } //------------ boundary points nb=2; while(nminymin[nb]) { if(2*xmax[nb]-xmin[2*nb-1]>0) { for(i=0;i0) { for(i=0;iymin[nmin]) { if(2*xmax[nmax]-xmin[nmin-nb+1]<(N-1)) { for(i=0;iArraySize(x)||n>ArraySize(y)||n2>ArraySize(y2)||n<2||n2<1) { Print(__FUNCTION__,": Error! Arguments has wrong size."); return(-1); } ArrayInitialize(y2,0); if(ArrayResize(a1,n)!=n) { Print(__FUNCTION__,": Error! ArrayResize() error."); return(-2); } if(ArrayResize(a2,n)!=n) { Print(__FUNCTION__,": Error! ArrayResize() error."); return(-2); } if(ArrayResize(a3,n)!=n) { Print(__FUNCTION__,": Error! ArrayResize() error."); return(-2); } if(ArrayResize(b,n)!=n) { Print(__FUNCTION__,": Error! ArrayResize() error."); return(-2); } if(ArrayResize(d,n)!=n) { Print(__FUNCTION__,": Error! ArrayResize() error."); return(-2); } for(i=1;i<=n-2;i++) { a1[i]=x[i+1]-x[i]; a2[i]=2*(x[i+1]-x[i-1]); a3[i]=x[i]-x[i-1]; b[i]=3*(y[i]-y[i-1])/(x[i]-x[i-1])*(x[i+1]-x[i])+3*(y[i+1]-y[i]) /(x[i+1]-x[i])*(x[i]-x[i-1]); } if(btype==1&&n==2) { d[0]=(y[1]-y[0])/(x[1]-x[0]); d[1]=d[0]; } else { if(btype==1) { a1[0]=0; a2[0]=1; a3[0]=1; b[0]=2*(y[1]-y[0])/(x[1]-x[0]); a1[n-1]=1; a2[n-1]=1; a3[n-1]=0; b[n-1]=2*(y[n-1]-y[n-2])/(x[n-1]-x[n-2]); } else { a1[0]=0; a2[0]=2; a3[0]=1; b[0]=3*(y[1]-y[0])/(x[1]-x[0]); a1[n-1]=1; a2[n-1]=2; a3[n-1]=0; b[n-1]=3*(y[n-1]-y[n-2])/(x[n-1]-x[n-2]); } for(i=1;i<=n-1;i++) { t=a1[i]/a2[i-1]; a2[i]=a2[i]-t*a3[i-1]; b[i]=b[i]-t*b[i-1]; } d[n-1]=b[n-1]/a2[n-1]; for(i=n-2;i>=0;i--)d[i]=(b[i]-a3[i]*d[i+1])/a2[i]; } c0=0; c1=0; c2=0; c3=0; a=0; bb=0; intervalindex=-1; pointindex=0; for(;;) { if(pointindex>=n2)break; t=x2[pointindex]; havetoadvance=false; if(intervalindex==-1)havetoadvance=true; else if(intervalindex=bb); if(havetoadvance) { intervalindex=intervalindex+1; a=x[intervalindex]; bb=x[intervalindex+1]; w=bb-a; w2=w*w; w3=w*w2; fa=y[intervalindex]; fb=y[intervalindex+1]; da=d[intervalindex]; db=d[intervalindex+1]; c0=fa; c1=da; c2=(3*(fb-fa)-2*da*w-db*w)/w2; c3=(2*(fa-fb)+da*w+db*w)/w3; continue; } t=t-a; y2[pointindex]=c0+t*(c1+t*(c2+t*c3)); pointindex=pointindex+1; } return(0); } //------------------------------------------------------------------------------------