Author: Forte928
geHMA_HP

Technical Overview: geHMA_HP Logic

This script is designed to provide a smoothed price trend for trading charts by combining two advanced mathematical concepts: the Hodrick-Prescott (HP) Filter and specialized data processing routines. Unlike standard moving averages that simply average past prices, this logic aims to isolate long-term trends from short-term "noise" or volatility.

Core Mathematical Engine: The Hodrick-Prescott Filter

The primary engine of this script is the Hodrick-Prescott Filter. In financial analysis, this filter is frequently used to decompose a time series into two parts: the trend and the cycle (fluctuations).

The script applies this filter using a specific variable called Lambda. By adjusting this value, the logic determines how "smooth" the resulting line should be. A higher value results in a smoother curve that follows the broad direction of the market, while a lower value allows the indicator to react more quickly to recent price changes.

Multi-Stage Processing Logic

Instead of applying a single filter, the script performs a multi-layered calculation sequence to refine the final output:

  1. Initial Smoothing: It first takes the closing prices and runs them through an HP Filter using a base value derived from the user's settings.
  2. Trend Reversal & Comparison: The script then performs a secondary filtering operation. It takes the results of the first step, applies a mathematical transformation (multiplying and subtracting values), and processes it again through another filter.
  3. Final Synthesis: By layering these filters in a specific order, the script attempts to balance two competing needs: capturing the true underlying momentum of the market while eliminating the erratic "jitter" caused by minor price swings.

Key Functional Components

  • Dynamic Data Buffering: The script includes a management system that automatically calculates how much historical data is required for the math to be accurate. If there isn't enough historical data on the chart, it provides a warning to ensure the calculations remain reliable.
  • Forward and Backward Pass: Because the Hodrick-Prescott Filter requires looking at both past and "future" data points (relative to the current candle) to find the most efficient curve, the script performs a "Forward Pass" to calculate coefficients and a "Backward Pass" to finalize the trend line.
  • Visual Output: The final result is rendered as a clean, solid line on the main chart. This line represents the "cleaned" price action, intended to help traders identify the core direction of the market more clearly than raw price action alone.

Summary for the User

Essentially, this script acts as a high-level "lens" for your price chart. It takes the chaotic movement of market prices and processes them through a sophisticated double-filtering system that prioritizes the smooth, long-term trend over short-term volatility.

Miscellaneous
It issuies visual alerts to the screenImplements a curve of type %1
12 Views
0 Downloads
0 Favorites
geHMA_HP
//+------------------------------------------------------------------+
//|																geHMA_HP.mq4		|
//|                      Copyright © 2007, ver 1.0							|
//|                      Forte928           									|
//+------------------------------------------------------------------+
#property copyright "Forte928"
#property link      ""
#define		IndicatorName "geHMA_HP"

#property indicator_chart_window
//#property indicator_separate_window


#property indicator_buffers 1
#property indicator_color1 Tomato
#property indicator_color2 YellowGreen

extern int		Alpha		=3;
extern int		Shift		=0;
extern int	 	Counter	=2000;

//double  FreqTOL  =0.0001;//Tolerance of frequency calculation for Method 1

double	FxView1[];
double	FxView2[];
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~V~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Work Variables ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
int Ix;
int Sx;

double	TimeBuf1[];
double	TimeBuf2[];
double	TimeBuf3[];
double	TimeBuf4[];
double	TimeBuf5[];
double	TimeBuf6[];

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~V~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Initialization program Buffers ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void	InitBufferam(int iBufferSize)
{
	ArrayResize(TimeBuf1,iBufferSize);
	ArrayResize(TimeBuf2,iBufferSize);
	ArrayResize(TimeBuf3,iBufferSize);
	ArrayResize(TimeBuf4,iBufferSize);
	ArrayResize(TimeBuf5,iBufferSize);
	ArrayResize(TimeBuf6,iBufferSize);
	return;
}
void	EmptyBufferam()
{
	ArrayInitialize(TimeBuf1,EMPTY_VALUE);
	ArrayInitialize(TimeBuf2,EMPTY_VALUE);
	ArrayInitialize(TimeBuf3,EMPTY_VALUE);
	ArrayInitialize(TimeBuf4,EMPTY_VALUE);
	ArrayInitialize(TimeBuf5,EMPTY_VALUE);
	ArrayInitialize(TimeBuf6,EMPTY_VALUE);
// -->
	return;
}
void	DoneBufferam()
{
	ArrayResize(TimeBuf1,0);
	ArrayResize(TimeBuf2,0);
	ArrayResize(TimeBuf3,0);
	ArrayResize(TimeBuf4,0);
	ArrayResize(TimeBuf5,0);
	ArrayResize(TimeBuf6,0);
	return;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~V~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Program Constants ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
int		MaxPeriod=0;
int		CalcCount=0;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Custom indicator initialization function ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
int init()
  {
//---- initialization program values  --------------------------------
	MaxPeriod=0;//MathMax(EMAPrd,WinSize);
	InitBufferam(MaxCounter(Counter,MaxPeriod));
	CalcCount=InitCounter(Counter,MaxPeriod);
//---- initialization indicators -------------------------------------
	SetupChartLine(0,FxView1,0,2,"HMA_HP"+Alpha);// SetIndexStyle(0,DRAW_LINE,STYLE_SOLID,1); SetIndexBuffer(0,ValueBuf0);
//   IndicatorShortName(IndicatorName+"("+WinSize+"("+EMAPrd+"))");
  	IndicatorDigits(MarketInfo(Symbol(),MODE_DIGITS));
	
//----
   return(0);
  }
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~V~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Custom indicator deinitialization function ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
int deinit()
  {
//----
	DoneBufferam();	
//----
   return(0);
  }
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~V~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Start defination ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
int start()
{
	if (!StartCounter(IndicatorName,Counter,CalcCount,MaxPeriod)) return(-1);
//------------------------------------------------------------------------------------
	EmptyBufferam();
//+-------------------------- Begin Cycle ---------------------------------------------------+\\
	for (int Rx=0;Rx<Counter;Rx++) TimeBuf1[Rx]=Close[Rx+Shift];
	
	HPFilter(TimeBuf1,TimeBuf2,MathFloor(Alpha/2),Counter);
	HPFilter(TimeBuf1,TimeBuf3,Alpha,Counter);
	for (Rx=Counter-1;Rx>=0;Rx--) TimeBuf2[Rx]=2.0*TimeBuf2[Rx]-TimeBuf3[Rx];
	HPFilter(TimeBuf2,TimeBuf1,MathFloor(MathSqrt(Alpha)),Counter);

	ArrayCopy(FxView1,TimeBuf1,Shift,0,Counter);
	
//----
   return(0);
  }
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~														 InitCounter																		~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 int InitCounter(int iPreCount,int iMaxPeriod)
{
	// Rule 1
	//if ((Result==0)||(Result>Bars)) Result=Bars;
	int Result=MaxCounter(iPreCount,iMaxPeriod);
	// Rule 2
	if ((Result+iMaxPeriod)>Bars) Result=Bars-iMaxPeriod;
	// Rule 3
	if (Result<iMaxPeriod) Result=0;
	else Result=Result+iMaxPeriod;
	return(Result);
}
//------------------------------------------ StartCounter --------------------------
bool StartCounter(string WindowName,int iPreCount,int& iCalcCount,int iMaxPeriod)
{
	if ((iPreCount>iCalcCount)||(iPreCount==0)) iCalcCount=InitCounter(iPreCount,iMaxPeriod);
	if (iCalcCount==0) 
	{
		Alert(WindowName+" "+Symbol()+"("+Period()+") - Limited Calculate Period");
		return(false);
	}
	return(true);
	//int iBarCount=IndicatorCounted();
	//if (iBarCount>0) return(true);
	//Print("StartCounter");
	return(false);
}
//------------------------------------------ StartCounter --------------------------
int MaxCounter(int iPreCount,int iMaxPeriod)
{
	int Result=iPreCount;
	// Rule 1
	//if ((Result==0)||(Result>Bars)) Result=Bars;
	if (Result==0) Result=Bars-1;
	if (Result<iMaxPeriod) Result=iMaxPeriod;
	return(Result+iMaxPeriod);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~														 Style active Line																~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void SetupChartLine(int Index,double& ViewAy[],int Style,int Width,string Label)
{
	switch(Style)
	{
		case 0 : SetIndexStyle(Index,DRAW_LINE,STYLE_SOLID,Width);break;
		case 1 : SetIndexStyle(Index,DRAW_HISTOGRAM,STYLE_SOLID,Width);break;
		case 2 : SetIndexStyle(Index,DRAW_ARROW,STYLE_SOLID,Width);break;
		default : SetIndexStyle(Index,DRAW_LINE,STYLE_SOLID,Width);break;
	}
	if (Label!="") SetIndexLabel(Index,Label);
	SetIndexBuffer(Index,ViewAy);
	return(0);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~											HPFilter	- Ôèëüòð Õîäðèêà-Ïðåñêîòòà														~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Hodrick-Prescott Filter-----------------------------------------------------------------+
void HPFilter(double& aySource[],double& ayResult[],int Lambda,int iCount)
{
   double Ak[],Bk[],Ck[],H1,H2,H3,H4,H5,HH1,HH2,HH3,HH4,HH5,HB,HC,Z;
   ArrayResize(Ak,iCount);
   ArrayResize(Bk,iCount);
   ArrayResize(Ck,iCount);
     
   Ak[0]=1.0+Lambda;
   Bk[0]=-2.0*Lambda;
   Ck[0]=Lambda;
   for(int Hx=1;Hx<iCount-2;Hx++)
   {
      Ak[Hx]=6.0*Lambda+1.0;
      Bk[Hx]=-4.0*Lambda;
      Ck[Hx]=Lambda;
   }
   Ak[1]=5.0*Lambda+1;
   Ak[iCount-1]=1.0+Lambda;
   Ak[iCount-2]=5.0*Lambda+1.0;
   Bk[iCount-2]=-2.0*Lambda;
   Bk[iCount-1]=0.0;
   Ck[iCount-2]=0.0;
   Ck[iCount-1]=0.0;
   
   //Forward
   for(Hx=0;Hx<iCount;Hx++)
   {
      Z=Ak[Hx]-H4*H1-HH5*HH2;
      HB=Bk[Hx];
      HH1=H1;
      H1=(HB-H4*H2)/Z;
      Bk[Hx]=H1;
      HC=Ck[Hx];
      HH2=H2;
      H2=HC/Z;
      Ck[Hx]=H2;
      Ak[Hx]=(aySource[Hx]-HH3*HH5-H3*H4)/Z;
      HH3=H3;
      H3=Ak[Hx];
      H4=HB-H5*HH1;
      HH5=H5;
      H5=HC;
   }
   
   //Backward 
   H2=0;
   H1=Ak[iCount-1];
   ayResult[iCount-1]=H1;
   for(Hx=iCount-2;Hx>=0;Hx--)
   {
      ayResult[Hx]=Ak[Hx]-Bk[Hx]*H1-Ck[Hx]*H2;
      H2=H1;
      H1=ayResult[Hx];
   }
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Comments