geGapADX
Download scriptThe geGapADX script is a technical analysis tool designed to measure market momentum and price volatility by identifying the relationship between "gaps" in price movement and the overall strength of the trend. Instead of looking at simple price changes, it focuses on the intensity of price action over specific windows of time.
Here is a breakdown of the logic used by the script:
Core Mechanics
The tool operates by analyzing the price range (the distance between the highest high and the lowest low) within a user-defined small window of bars. It then performs the following steps to translate this data into visual signals:
- Trend Polarization: The script looks at the price movement within its designated window. If the price moves in a specific direction, it assigns a positive value to one category (labeled as "Plus") and sets the opposite category ("Minus") to zero. If it moves in the opposite direction, the values are swapped. This effectively separates upward momentum from downward momentum.
- Smoothing via EMA: To prevent the data from appearing erratic or "noisy," the script applies an Exponential Moving Average (EMA) to both the "Plus" and "Minus" values. This smoothing helps identify the underlying trend rather than reacting to minor, insignificant price flickers.
- The ADX Calculation: The final core component of the script takes these smoothed values and calculates a percentage-based intensity. It measures the difference between the upward momentum and downward momentum relative to their sum. This results in a specific percentage that represents the strength of the current trend.
Visual Output
The script provides four distinct visual components on the chart:
- Gap: Represents the raw price range calculation within the specified window.
- Plus: Displays the smoothed momentum of upward price movements.
- Minus: Displays the smoothed momentum of downward price movements.
- ADX: Provides a consolidated percentage value indicating the relative strength of the market's trend.
Summary for the User
Essentially, this script filters out the "jitter" of the market to show you how much "push" is behind a move. By watching the ADX line, you can see the intensity of the trend; by watching the Plus and Minus lines, you can see which direction that strength is currently favoring. It is designed to help traders distinguish between a strong, trending market and a weak, sideways market.
//+------------------------------------------------------------------+
//| geGapADX.mq4 |
//| Copyright © 2007, ver 1.0 |
//| Forte928 |
//+------------------------------------------------------------------+
#property copyright "Forte928"
#property link ""
#define IndicatorName "geGapADX"
//#property indicator_chart_window
#property indicator_separate_window
//#property indicator_level1 1.4
//#property indicator_level2 1.2
//#property indicator_level3 1
//#property indicator_level4 0.8
#property indicator_buffers 4
#property indicator_color1 Tomato
#property indicator_color2 YellowGreen
#property indicator_color3 Wheat
#property indicator_color4 LightSeaGreen
extern int WinSize =3;
extern int EMAPrd =8;
extern int Shift =0;
extern int Counter =2000;
//double FreqTOL =0.0001;//Tolerance of frequency calculation for Method 1
double FxView1[];
double FxView2[];
double FxView3[];
double FxView4[];
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~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=MathMax(EMAPrd,WinSize);
InitBufferam(MaxCounter(Counter,MaxPeriod));
CalcCount=InitCounter(Counter,MaxPeriod);
//---- initialization indicators -------------------------------------
SetupChartLine(0,FxView1,0,1,"Gap"+WinSize);// SetIndexStyle(0,DRAW_LINE,STYLE_SOLID,1); SetIndexBuffer(0,ValueBuf0);
SetupChartLine(1,FxView2,0,1,"Plus");// SetIndexStyle(0,DRAW_LINE,STYLE_SOLID,1); SetIndexBuffer(0,ValueBuf0);
SetupChartLine(2,FxView3,0,1,"Minus");// SetIndexStyle(0,DRAW_LINE,STYLE_SOLID,1); SetIndexBuffer(0,ValueBuf0);
SetupChartLine(3,FxView4,0,1,"ADX");// 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 (Ix=CalcCount-1;Ix>=0;Ix--){
TimeBuf1[Ix]=(High[iHighest(NULL,0,MODE_HIGH,WinSize,Ix)]-Low[iLowest(NULL,0,MODE_LOW,WinSize,Ix)])/Point; // Çíà÷åíèå 0 áóôåðà íà i-îì áàðå
if(Open[Ix+WinSize-1]>Close[Ix]) // Åñëè ñâå÷à ÷¸ðíàÿ..
TimeBuf1[Ix]=-TimeBuf1[Ix]; // .. òî ðåâåðñ çíà÷åíèÿ
if (TimeBuf1[Ix]>=0) {
TimeBuf2[Ix]=TimeBuf1[Ix];
TimeBuf3[Ix]=0;
}
else {
TimeBuf3[Ix]=-TimeBuf1[Ix];
TimeBuf2[Ix]=0;
}
}
EMAOnArray(TimeBuf2,TimeBuf4,EMAPrd,CalcCount);
EMAOnArray(TimeBuf3,TimeBuf5,EMAPrd,CalcCount);
for (Ix=CalcCount-1;Ix>=0;Ix--)
{
double Div=MathAbs(TimeBuf4[Ix]+TimeBuf5[Ix]);
if(Div==0.00) TimeBuf6[Ix]=0;
else TimeBuf6[Ix]=100*(MathAbs(TimeBuf4[Ix]-TimeBuf5[Ix])/Div);
}
ArrayCopy(FxView1,TimeBuf1,Shift,0,CalcCount);
ArrayCopy(FxView2,TimeBuf4,Shift,0,CalcCount);
ArrayCopy(FxView3,TimeBuf5,Shift,0,CalcCount);
ArrayCopy(FxView4,TimeBuf6,Shift,0,CalcCount);
//----
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);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//-------------------------------------------------------------------------------------------------
void EMAOnArray(double aySource[],double& ayResult[],int iPeriod,int iCount)
{
double iMuver=2/(iPeriod*1.0+1);
ayResult[iCount-1]=0;
for(int Ex=iCount-2; Ex>=0; Ex--) {
ayResult[Ex]=ayResult[Ex+1]+iMuver*(aySource[Ex]-ayResult[Ex+1]);
}
return;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Comments