Author: ryaz
HPMA102
0 Views
0 Downloads
0 Favorites
HPMA102
//+--------------------------------------------------------------------------+
//|                                                                 HPMA.mq4 |
//| Hodrick-Prescott filter MA                                               |
//| based on HP filter implementation by gwpr (http://codebase.mql4.com/5169)|
//+--------------------------------------------------------------------------+
#define IND "HPMA"
#define VER "1_02"
#property copyright "ryaz"
#property link      "outta@here"
#property indicator_chart_window
#property indicator_buffers 8
#property indicator_color1 Gray
#property indicator_color2 Blue
#property indicator_color3 Red
#property indicator_color4 Olive
#property indicator_color5 Indigo
#property indicator_color6 Indigo
#property indicator_color7 SeaGreen
#property indicator_color8 SeaGreen

//Input parameters
extern int nobs     =150; //Number of bars to process for filter evaluation
extern double lambda=1600; //Higher lambda leads to the smoother data
extern int timeframe=0;//The applied timeframe, 0=the same as chart
extern int price    =PRICE_CLOSE;//The applied price
extern int delay    =0; //Shows the result of delaying (or advancing if negative) the HP filter
extern int trend    =10; //how many consecutive filter bars to check to determine trend
extern int future   =8; //How many bars in the future to display for the HP filter
extern int bands     = 0; //how many bars to include in bands calculation
extern double band1 =2; //deviations for first band
extern double band2 =2; //deviations for second Band
extern int type1    =-1; //Type for the first band -1=Filter Band or else Price Band 0=applied price 1=mean 2=exterme High/Low 3=inside High/Low 4=median 5=typical 6=weighted
extern int type2    =0; //Type for second band as above
extern bool repaint =FALSE; //To repaint last bar, FALSE for faster execution
extern bool points  =FALSE; //Plot up/downtrend as points instead of line
extern bool alerts  =FALSE; //Enable visual alert
extern string audio ="alert.wav"; //Enable audioalert
extern int history  =500; //history bars to display on initialisation, 0 means all history
//Indicator buffers
double hp0[], hpu0[],hpd0[],hpf0[], fhi0[], flo0[], phi0[], plo0[];
//Global vars
double hp[], hpu[],hpd[],hpf[], fhi[], flo[], phi[], plo[];
double dat[],a[],b[],c[];
datetime time;
string tframe;
bool alerting;
bool showf;
//+----------------------------------------------------------------------------------------+
int init()
{
   if (timeframe==0) timeframe=Period();
   SetIndexBuffer(0,hp0);
   SetIndexStyle(0,DRAW_LINE);
   SetIndexLabel(0,"hpma");
   SetIndexBuffer(1,hpu0);
   SetIndexLabel(1,"up");
   SetIndexBuffer(2,hpd0);
   SetIndexLabel(2,"down");
   if (points) {
     SetIndexStyle(1,DRAW_ARROW);
     SetIndexArrow(1,4);
     SetIndexStyle(2,DRAW_ARROW);
     SetIndexArrow(2,4);
   } else {
     SetIndexStyle(1,DRAW_LINE);  
     SetIndexStyle(2,DRAW_LINE);  
   }  
   SetIndexBuffer(3,hpf0);
   if (trend>0) {
     SetIndexStyle(3,DRAW_LINE);
     SetIndexLabel(3,"filter");
     SetIndexShift(3,future);
   } else    
     SetIndexStyle(3,DRAW_LINE);
   SetIndexBuffer(4,fhi0);
   SetIndexBuffer(5,flo0);
   SetIndexBuffer(6,phi0);
   SetIndexBuffer(7,plo0);
   if (history==0) history=iBarShift(NULL,0,iTime(NULL,timeframe,iBars(NULL,timeframe)-nobs)); 
   SetIndexDrawBegin(0,Bars-history);
   SetIndexDrawBegin(1,Bars-history);
   SetIndexDrawBegin(2,Bars-history);
   SetIndexDrawBegin(3,Bars-history+future);
   if (bands>0 && band1!=0) {
     SetIndexLabel(4,"Fhi");
     SetIndexLabel(5,"Flo");
     SetIndexStyle(4,DRAW_LINE);
     SetIndexStyle(5,DRAW_LINE);
     if (band1>0) {
       SetIndexDrawBegin(4,Bars-history);
       SetIndexDrawBegin(5,Bars-history);
     }  
   } else {
     SetIndexStyle(4,DRAW_NONE);
     SetIndexStyle(5,DRAW_NONE);
   }  
   if (bands>0 && band2!=0) {
     SetIndexLabel(6,"Phi");
     SetIndexLabel(7,"Plo");
     SetIndexStyle(6,DRAW_LINE);
     SetIndexStyle(7,DRAW_LINE);
     if (band2>0) {
       SetIndexDrawBegin(6,Bars-history);
       SetIndexDrawBegin(7,Bars-history);
     }  
   } else {
     SetIndexStyle(6,DRAW_NONE);
     SetIndexStyle(7,DRAW_NONE);
   }  
   ArrayResize(hpf,nobs);
   ArrayResize(dat,nobs);
   ArrayResize(a,nobs);
   ArrayResize(b,nobs);
   ArrayResize(c,nobs);
   time=Time[history-1];
   if (lambda<1) lambda=MathExp(-lambda);
   switch (timeframe) {
     case 60:{tframe="H1";break;}
     case 240:{tframe="H4";break;}
     case 1440:{tframe="D1";break;}
     case 10080:{tframe="W1";break;}
     case 43200:{tframe="MN1";break;}
     default:tframe="M"+Period();
   }
   IndicatorShortName(IND+"("+tframe+")");
   tframe=Symbol()+" "+tframe+": ";
   history=MathMax(iBarShift(NULL,timeframe,time),bands);
   ArrayResize(hp,history);
   ArrayResize(hpu,history);
   ArrayResize(hpd,history);
   ArrayResize(fhi,history);
   ArrayResize(flo,history);
   ArrayResize(phi,history);
   ArrayResize(plo,history);
   alerting=alerts || audio!="";
   showf=trend>0;
   if (trend<0) trend=-trend;
   return(0);
}
//+----------------------------------------------------------------------------------------+
int start()
{
   double H1,H2,H3,H4,H5,HH1,HH2,HH3,HH4,HH5,HB,HC,Z,V;
   int i, disp, bar, limit;
   if (iBars(NULL,timeframe)<nobs) return(0);
   if (!repaint && time==Time[0]) return(0); 
   limit=iBarShift(NULL,timeframe,time);
   time=Time[0];
   if (limit>=history) limit=history-1;
   if (limit<history-1)
     for (bar=history-1-limit; bar>=0; bar--) {
       hp[bar+limit] =hp[bar];
       hpu[bar+limit]=hpu[bar];
       hpd[bar+limit]=hpd[bar];
       fhi[bar+limit]=fhi[bar];
       flo[bar+limit]=flo[bar];
       phi[bar+limit]=phi[bar];
       plo[bar+limit]=plo[bar];
     }
   for (bar=limit; bar>=0; bar--) {
     hpu[bar]=EMPTY_VALUE;
     hpd[bar]=EMPTY_VALUE;
     fhi[bar]=EMPTY_VALUE;
     flo[bar]=EMPTY_VALUE;
     phi[bar]=EMPTY_VALUE;
     plo[bar]=EMPTY_VALUE;
     H1=0;H2=0;H3=0;H4=0;H5=0;HH1=0;HH2=0;HH3=0;HH4=0;HH5=0;
     switch (price) {
       case PRICE_CLOSE: {for(i=0;i<nobs;i++) dat[i]=iClose(NULL,timeframe,bar+i);break;}
       case PRICE_OPEN: {for(i=0;i<nobs;i++)dat[i]=iOpen(NULL,timeframe,bar+i);break;}
       case PRICE_HIGH: {for(i=0;i<nobs;i++)dat[i]=iHigh(NULL,timeframe,bar+i);break;}
       case PRICE_LOW: {for(i=0;i<nobs;i++)dat[i]=iLow(NULL,timeframe,bar+i);break;}
       case PRICE_MEDIAN: {for(i=0;i<nobs;i++)dat[i]=(iHigh(NULL,timeframe,bar+i)+iLow(NULL,timeframe,bar+i))/2;break;}
       case PRICE_TYPICAL: {for(i=0;i<nobs;i++)dat[i]=(iHigh(NULL,timeframe,bar+i)+iLow(NULL,timeframe,bar+i)+iClose(NULL,timeframe,bar+i))/3;break;}
       case PRICE_WEIGHTED: {for(i=0;i<nobs;i++)dat[i]=(iHigh(NULL,timeframe,bar+i)+iLow(NULL,timeframe,bar+i)+2*iClose(NULL,timeframe,bar+i))/4;break;}
       default: for(i=0;i<nobs;i++) dat[i]=(iHigh(NULL,timeframe,bar+i)+iLow(NULL,timeframe,bar+i)+iOpen(NULL,timeframe,bar+i)+iClose(NULL,timeframe,bar+i))/4;
     }
     V=dat[0];  
     a[0]=1.0+lambda;
     b[0]=-2.0*lambda;
     c[0]=lambda;
     for(i=1;i<nobs-2;i++)
     {
        a[i]=6.0*lambda+1.0;
        b[i]=-4.0*lambda;
        c[i]=lambda;
     }
     a[1]=5.0*lambda+1;
     a[nobs-1]=1.0+lambda;
     a[nobs-2]=5.0*lambda+1.0;
     b[nobs-2]=-2.0*lambda;
     b[nobs-1]=0.0;
     c[nobs-2]=0.0;
     c[nobs-1]=0.0;
   
   //Forward
     for(i=0;i<nobs;i++)
     {
        Z=a[i]-H4*H1-HH5*HH2;
        HB=b[i];
        HH1=H1;
        H1=(HB-H4*H2)/Z;
        b[i]=H1;
        HC=c[i];
        HH2=H2;
        H2=HC/Z;
        c[i]=H2;
        a[i]=(dat[i]-HH3*HH5-H3*H4)/Z;
        HH3=H3;
        H3=a[i];
        H4=HB-H5*HH1;
        HH5=H5;
        H5=HC;
     }
   
   //Backward 
     H2=0;
     H1=a[nobs-1];
     hpf[nobs-1]=H1;
     for(i=nobs-2;i>=0;i--)
     {
        hpf[i]=a[i]-b[i]*H1-c[i]*H2;
        H2=H1;
        H1=hpf[i];
     }
     hp[bar]=hpf[0];
     if (hpu[bar+1]==EMPTY_VALUE && (hp[bar]<hp[bar+1] || V<hp[bar]))  
       hpu[bar]=EMPTY_VALUE;
     else if (trend>0) {  
       for (i=0; i<trend; i++)
         if (hpf[i]<hpf[i+1]) break;
       if (i<trend)  
         hpu[bar]=EMPTY_VALUE;
       else  
         hpu[bar]=hpf[0];
     } else {
       if (hp[bar]<hp[bar+1])  
         hpu[bar]=EMPTY_VALUE;
       else  
         hpu[bar]=hpf[0];
     }   
     if (hpd[bar+1]==EMPTY_VALUE && (hp[bar]>hp[bar+1] || V>hp[bar]))  
       hpd[bar]=EMPTY_VALUE;
     else if (trend>0) {  
       for (i=0; i<trend; i++)
         if (hpf[i]>hpf[i+1]) break;
       if (i<trend)  
         hpd[bar]=EMPTY_VALUE;
       else  
         hpd[bar]=hpf[0];
     } else {
       if (hp[bar]>hp[bar+1])  
         hpd[bar]=EMPTY_VALUE;
       else  
         hpd[bar]=hpf[0];
     }
     if (bands>0 && (band1>0  || (band1<0 && bar==0))) {
       Z=0;    
       for (i=0; i<bands; i++) {
         V=hpf[i];
         switch (type1) {
           case -1: {V-=hp[bar+i];break;}
           case 0: {V-=dat[i];break;}
           case 1: {V-=(2*(iHigh(NULL,timeframe,bar+i)+iLow(NULL,timeframe,bar+i))+iOpen(NULL,timeframe,bar+i)+iClose(NULL,timeframe,bar+i))/6;break;}
           case 2: {V=MathMax(MathAbs(iHigh(NULL,timeframe,bar+i)-V),MathAbs(iLow(NULL,timeframe,bar+i)-V));break;}
           case 3: {V=MathMin(MathAbs(iHigh(NULL,timeframe,bar+i)-V),MathAbs(iLow(NULL,timeframe,bar+i)-V));break;}
           case 4: {V-=(iHigh(NULL,timeframe,bar+i)+iLow(NULL,timeframe,bar+i))/2;break;}
           case 5: {V-=(iHigh(NULL,timeframe,bar+i)+iLow(NULL,timeframe,bar+i)+iClose(NULL,timeframe,bar+i))/3;break;}
           case 6: {V-=(iHigh(NULL,timeframe,bar+i)+iLow(NULL,timeframe,bar+i)+2*iClose(NULL,timeframe,bar+i))/4;break;}
           default: V-=iClose(NULL,timeframe,bar+i);
         }
         Z+=V*V;
       }
       Z=band1*MathSqrt(Z/bands);
       if (band1>0) {
         fhi[bar]=hp[bar]+Z;
         flo[bar]=hp[bar]-Z;
       } else {
         limit=iBarShift(NULL,0,iTime(NULL,timeframe,nobs-1));
         SetIndexDrawBegin(6,limit);
         SetIndexDrawBegin(7,limit);
         for (i=0; i<nobs; i++) {
           fhi[i]=hpf[i]-Z;
           flo[i]=hpf[i]+Z;
         }  
       }  
     }  
     if (bands>0 && (band2>0  || (band2<0 && bar==0))) {
       Z=0;    
       for (i=0; i<bands; i++) {
         V=hpf[i];
         switch (type2) {
           case -1: {V-=hp[bar+i];break;}
           case 0: {V-=dat[i];break;}
           case 1: {V-=(2*(iHigh(NULL,timeframe,bar+i)+iLow(NULL,timeframe,bar+i))+iOpen(NULL,timeframe,bar+i)+iClose(NULL,timeframe,bar+i))/6;break;}
           case 2: {V=MathMax(MathAbs(iHigh(NULL,timeframe,bar+i)-V),MathAbs(iLow(NULL,timeframe,bar+i)-V));break;}
           case 3: {V=MathMin(MathAbs(iHigh(NULL,timeframe,bar+i)-V),MathAbs(iLow(NULL,timeframe,bar+i)-V));break;}
           case 4: {V-=(iHigh(NULL,timeframe,bar+i)+iLow(NULL,timeframe,bar+i))/2;break;}
           case 5: {V-=(iHigh(NULL,timeframe,bar+i)+iLow(NULL,timeframe,bar+i)+iClose(NULL,timeframe,bar+i))/3;break;}
           case 6: {V-=(iHigh(NULL,timeframe,bar+i)+iLow(NULL,timeframe,bar+i)+2*iClose(NULL,timeframe,bar+i))/4;break;}
           default: V-=iClose(NULL,timeframe,bar+i);
         }
         Z+=V*V;
       }  
       Z=band2*MathSqrt(Z/bands);
       if (band2>0) {
         phi[bar]=hp[bar]+Z;
         plo[bar]=hp[bar]-Z;
       } else {
         limit=iBarShift(NULL,0,iTime(NULL,timeframe,nobs-1));
         SetIndexDrawBegin(4,limit);
         SetIndexDrawBegin(5,limit);
         for (i=0; i<nobs; i++) {
           phi[i]=hpf[i]-Z;
           plo[i]=hpf[i]+Z;
         }  
       }  
     }  
     if (bar<history-1) {
       if (bar==0)
         disp=0;
       else if (timeframe<=Period())
         disp=iBarShift(NULL,0,iTime(NULL,timeframe,bar));
       else  
         disp=iBarShift(NULL,0,iTime(NULL,timeframe,bar-1))+1;
       if (delay>=0)
         hp0[disp]=hpf[delay];
       else
         hp0[disp]=newt(hpf,0,-delay);
       if (hpu[bar]!=EMPTY_VALUE)
         hpu0[disp]=hp0[disp];
       else    
         hpu0[disp]=EMPTY_VALUE;
       if (hpd[bar]!=EMPTY_VALUE)
         hpd0[disp]=hp0[disp];
       else  
         hpd0[disp]=EMPTY_VALUE;
       fhi0[disp]=fhi[bar];
       flo0[disp]=flo[bar];
       phi0[disp]=phi[bar];
       plo0[disp]=plo[bar];
       if (timeframe<=Period())
         limit=iBarShift(NULL,0,iTime(NULL,timeframe,bar+1));
       else  
         limit=iBarShift(NULL,0,iTime(NULL,timeframe,bar))+1;
       i=limit-disp;
       if (i<2) continue;
       H1=hp[bar+1];
       HH1=(hp[bar]-H1)/i;
       if (bands>0 && band1>0) {
         H2=fhi[bar+1];
         HH2=(fhi[bar]-H2)/i;
         H3=flo[bar+1];
         HH3=(flo[bar]-H3)/i;
       }
       if (bands>0 && band2>0) {
         H4=phi[bar+1];
         HH4=(phi[bar]-H4)/i;
         H5=plo[bar+1];
         HH5=(plo[bar]-H5)/i;
       }
       for (i=limit-1; i>disp; i--) {
         H1+=HH1;
         hp0[i]=H1;
         if (hpu[bar+1]!=EMPTY_VALUE) hpu0[i]=H1; else hpu0[i]=EMPTY_VALUE;
         if (hpd[bar+1]!=EMPTY_VALUE) hpd0[i]=H1; else hpd0[i]=EMPTY_VALUE;
         if (bands>0 && band1>0) {
           H2+=HH2;
           H3+=HH3;
           fhi0[i]=H2;
           flo0[i]=H3;
         }
         if (bands>0 && band2>0) {
           H4+=HH4;
           H5+=HH5;
           phi0[i]=H4;
           plo0[i]=H5;
         }
       }
     } 
   }
   if (showf>0) {
     limit=iBarShift(NULL,0,iTime(NULL,timeframe,nobs-1));
     SetIndexDrawBegin(3,limit);
     if (future>0) {
       V=Period();
       V/=timeframe;
       for (bar=0; bar<future; bar++)
         hpf0[bar]=newt(hpf,0,(future-bar)*V); 
     }
     for (bar=nobs-1; bar>=0; bar--) {
       if (bar==0)
         disp=future;
       else if (timeframe<=Period())
         disp=iBarShift(NULL,0,iTime(NULL,timeframe,bar))+future;
       else  
         disp=iBarShift(NULL,0,iTime(NULL,timeframe,bar-1))+future+1;
       hpf0[disp]=hpf[bar];
       if (bar<nobs-1) {
         limit=iBarShift(NULL,0,iTime(NULL,timeframe,bar+1))+future;
         i=limit-disp;
         if (i<2) continue;
         H1=hpf[bar];
         HH1=(H1-hpf[bar+1])/i;
         for (i=limit-1; i>disp; i--) {
           H1+=HH1;
           hpf0[i]=H1;
         }  
       }  
     }  
   }
   if (bands>0 && band1<0) {
     limit=iBarShift(NULL,0,iTime(NULL,timeframe,nobs-1));
     for (bar=nobs-1; bar>=0; bar--) {
       if (bar==0)
         disp=0;
       else if (timeframe<=Period())
         disp=iBarShift(NULL,0,iTime(NULL,timeframe,bar));
       else  
         disp=iBarShift(NULL,0,iTime(NULL,timeframe,bar-1))+1;
       fhi0[disp]=fhi[bar];
       flo0[disp]=flo[bar];
       if (bar<nobs-1) {
         if (timeframe<=Period())
           limit=iBarShift(NULL,0,iTime(NULL,timeframe,bar+1));
         else  
           limit=iBarShift(NULL,0,iTime(NULL,timeframe,bar))+1;
         i=limit-disp;
         if (i<2) continue;
         H2=fhi[bar+1];
         HH2=(fhi[bar]-H2)/i;
         H3=flo[bar+1];
         HH3=(flo[bar]-H3)/i;
         for (i=limit-1; i>disp; i--) {
           H2+=HH2;
           H3+=HH3;
           fhi0[i]=H2;
           flo0[i]=H3;
         }  
       }  
     }  
   }
   if (bands>0 && band2<0) {
     limit=iBarShift(NULL,0,iTime(NULL,timeframe,nobs-1));
     for (bar=nobs-1; bar>=0; bar--) {
       if (bar==0)
         disp=0;
       else if (timeframe<=Period())
         disp=iBarShift(NULL,0,iTime(NULL,timeframe,bar));
       else  
         disp=iBarShift(NULL,0,iTime(NULL,timeframe,bar-1))+1;
       phi0[disp]=phi[bar];
       plo0[disp]=plo[bar];
       if (bar<nobs-1) {
         if (timeframe<=Period())
           limit=iBarShift(NULL,0,iTime(NULL,timeframe,bar+1));
         else  
           limit=iBarShift(NULL,0,iTime(NULL,timeframe,bar))+1;
         i=limit-disp;
         if (i<2) continue;
         H4=phi[bar+1];
         HH4=(phi[bar]-H4)/i;
         H5=plo[bar+1];
         HH5=(plo[bar]-H5)/i;
         for (i=limit-1; i>disp; i--) {
           H4+=HH4;
           H5+=HH5;
           phi0[i]=H4;
           plo0[i]=H5;
         }  
       }  
     }  
   }
   if (alerting) {
     if (hpu[0]!=EMPTY_VALUE && hpu[1]==EMPTY_VALUE) {
         MyAlert("Up Trend");
     } else 
     if (hpu[0]==EMPTY_VALUE && hpu[1]!=EMPTY_VALUE && hpd[0]==EMPTY_VALUE) {
         MyAlert("No Trend");
     } else 
     if (hpd[0]!=EMPTY_VALUE && hpd[1]==EMPTY_VALUE) {
         MyAlert("Down Trend");
     } else 
     if (hpd[0]==EMPTY_VALUE && hpd[1]!=EMPTY_VALUE && hpu[0]==EMPTY_VALUE) {
         MyAlert("No Trend");
     }         
   }
   return(0);
}

void MyAlert(string alert) {
  static string last;
  if (alert==last) return;
  last=alert; 
  if (alerts) Alert(IND+tframe+alert);
  if (audio!="") PlaySound(audio);
}

double newt(double x[], int pos, double n) {
  double r=x[pos],k=1;
  int l=MathCeil(n), i;
  if (pos+l>=ArraySize(x)) l=ArraySize(x)-pos-1;
  if (n==0) return(r);
  if (n<0) return(EMPTY_VALUE);
  for (i=1; i<=l; i++) {
    k*=n/i;
    r+=k*dlt(x,pos,i);
  }
  return(r);
}

double dlt(double x[], int pos, int d) {
  double r=0;
  int i, k=1, pod=pos+d, l=d>>1;
  if (pos>=ArraySize(x)) return(EMPTY_VALUE);
  if (pos+d>=ArraySize(x)) return(0);
  if (d%2>0)
    for (i=0; i<=l; i++, pos++, pod--) {
      r+=k*(x[pos]-x[pod]);
      k*=i-d;
      k/=i+1;
    }
  else {
    for (i=0; i<l; i++, pos++, pod--) {
      r+=k*(x[pos]+x[pod]);
      k*=i-d;
      k/=i+1;
    }
    r+=k*x[pos];
  }  
  return(r);
}


Comments