Author: ryaz
HPMA102
Price Data Components
Series array that contains close prices for each barSeries array that contains open prices of each barSeries array that contains the highest prices of each barSeries array that contains the lowest prices of each bar
Miscellaneous
Implements a curve of type %1It issuies visual alerts to the screenIt plays sound alerts
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