RelDownTrLen_forCodeBase_v01
Download scriptThis technical tool is designed to analyze market price action and quantify the strength or extent of a prevailing downtrend within a specific timeframe. Instead of simply looking at whether the price is falling, the logic seeks to identify the most significant "structural" move downward over a user-defined number of candles.
Core Logic Overview
The script operates by examining a history of price points (the "bars") and determining how much of that history is dominated by a consistent downward movement. It doesn't just measure from one point to another; it uses a geometric approach to filter out "noise" or minor fluctuations, focusing instead on the primary structural trend.
Key Functional Steps
1. Data Selection The user can choose whether the script focuses on the Candle Bodies (the actual range between open and close prices) or the Highs of the candles. By default, it looks at the maximum price reached within each candle's body to create a clean map of price movement.
2. Geometric Analysis (The Convex Hull) To identify the "true" trend, the script employs a geometric concept known as a Convex Hull. Think of this as stretching a virtual rubber band over the tops of all the candles in the selected timeframe.
- It calculates the boundaries of the price action to find the "outer shell."
- By analyzing these outer points, the script can distinguish between a jagged, volatile market and a smooth, directional move.
3. Identifying the Longest Down-Trend Once the structure is mapped, the logic scans the data specifically for the longest continuous downward segment. It looks for the largest distance (in terms of bars) where the price at the start of the segment is higher than the price at the end, while ensuring this move follows the primary downward trajectory identified by the geometry.
4. Relative Strength Calculation The final output provided by the script is a relative length value. Rather than giving you a raw price number, it calculates:
- (The length of the best identified down-trend) divided by (the total number of bars processed).
How to Interpret the Results
The result is displayed on a separate window as a numerical value between 0 and 1:
- A value near 0 indicates that there is no significant downward trend or the market is moving sideways/upward.
- A value approaching 1 indicates that a very large portion of the analyzed timeframe consists of a single, dominant downward move.
This allows traders to quickly visualize how much of the recent price action is "committed" to a downtrend, providing a normalized metric for trend intensity.
//This shows the relative length of the down trend.
//+------------------------------------------------------------------+
//| RelDownTrLen_....mq4 |
//| Author: Martes |
//| http://championship.mql4.com/2007/ru/users/Martes/ |
//+------------------------------------------------------------------+
#property copyright "Martes"
#property link "http://championship.mql4.com/2007/ru/users/Martes/"
//Fix minimum (0) and maximum (1) levels manually. Levels below do not work.
#property indicator_level1 0
#property indicator_level2 1
#property indicator_levelcolor LimeGreen
#property indicator_levelwidth 2
#property indicator_levelstyle 0
#property indicator_separate_window
#property indicator_buffers 1
#property indicator_color1 MidnightBlue
#property indicator_width1 2
extern int barsToProcess=100;
extern int StartingBarNumber=0;
extern bool DrawForCandleBodies=true;
//---- buffers
double ExtMapBuffer1[];
//----
datetime ProcessedTime=0;
double CandleBodyMinimum(int CandleNumber)
{
return(MathMin(Open[CandleNumber], Close[CandleNumber]));
}
double CandleBodyMaximum(int CandleNumber)
{
return(MathMax(Open[CandleNumber], Close[CandleNumber]));
}
// isLeft(): tests if a point is Left|On|Right of an infinite line.
// Input: three points P0=(x0,y0), P1=(x1,y1), and P2=(x2,y2).
// Return: >0 for P2 left of the line through P0 and P1
// =0 for P2 on the line
// <0 for P2 right of the line
double isLeft( double x0, double y0, double x1, double y1, double x2, double y2) {
return( (x1-x0)*(y2-y0) - (x2-x0)*(y1-y0) );
}
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
//---- indicators
SetIndexStyle(0,DRAW_LINE);
SetIndexBuffer(0,ExtMapBuffer1);
//----
return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function |
//+------------------------------------------------------------------+
int deinit()
{
//----
//----
return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int start()
{
int counted_bars=IndicatorCounted();
//----
int limit;
//Variables for finding best down-trend
int Length, StartIdx, EndIdx,
BestLength=0, BestStartIdx, BestEndIdx;
datetime BestStartTime, BestEndTime;
double BestStartPrice, BestEndPrice;
//Do nothing if the current candle is already processed.
if(ProcessedTime==Time[StartingBarNumber])
{
return(0);
}
else //Process.
{
ProcessedTime=Time[StartingBarNumber];
if(barsToProcess<=2)
{
if(barsToProcess<=1)
{
Print("Too few bars to calculate a down-trend");
return(0);
}
else
{
if(DrawForCandleBodies)
{
BestStartPrice=CandleBodyMaximum(StartingBarNumber+2);
BestEndPrice=CandleBodyMaximum(StartingBarNumber+1);
}
else
{
BestStartPrice=High[StartingBarNumber+2];
BestEndPrice=High[StartingBarNumber+1];
}
if(BestStartPrice<=BestEndPrice)
{
ExtMapBuffer1[0]=0;
Print("No down trend");
return(0);
}
BestStartTime=Time[StartingBarNumber+2];
BestEndTime=Time[StartingBarNumber+1];
}
}
else //Find a Down-Trend with a convex hull.
{
ProcessedTime=Time[StartingBarNumber];
int NumbersOfConvexHullVertices[], //To store indices (numbers) of Vertices in Convex Hull
ConvexHullIdx, //This points to the last valid element of NumbersOfConvexHullVertices
i;
ArrayResize(NumbersOfConvexHullVertices, barsToProcess);
double CandleBodyMaxima[],
x0, y0,
x1, y1,
x2, y2;
ArrayResize(CandleBodyMaxima, barsToProcess);
//Fill array CandleBodyMaxima[] with values from
//the range StartingBarNumber+1 ... StartingBarNumber+barsToProcess of the chart
for(i=1; i<=barsToProcess; i++)
{
if(DrawForCandleBodies)
{
CandleBodyMaxima[i-1]=CandleBodyMaximum(StartingBarNumber+i);
}
else
{
CandleBodyMaxima[i-1]=High[StartingBarNumber+i];
}
}
//Find the lower part of the convex hull for points (i, CandleBodyMaxima[i]) of
//the plane
NumbersOfConvexHullVertices[0]=0;//This is the index of CandleBodyMaxima[0]
ConvexHullIdx=0;//This says that NumbersOfConvexHullVertices[ConvexHullIdx] is valid.
NumbersOfConvexHullVertices[1]=1;//This is the index of CandleBodyMaxima[1]
ConvexHullIdx=1;//NumbersOfConvexHullVertices[ConvexHullIdx] is still thought to be valid.
for(i=2; i<barsToProcess; i++)
{
ConvexHullIdx++;
NumbersOfConvexHullVertices[ConvexHullIdx]=i;//The new point is added in the hull.
//Now we will make the hull convex
x0=NumbersOfConvexHullVertices[ConvexHullIdx-2];
y0=CandleBodyMaxima[NumbersOfConvexHullVertices[ConvexHullIdx-2]];
x1=NumbersOfConvexHullVertices[ConvexHullIdx-1];
y1=CandleBodyMaxima[NumbersOfConvexHullVertices[ConvexHullIdx-1]];
x2=NumbersOfConvexHullVertices[ConvexHullIdx];
y2=CandleBodyMaxima[NumbersOfConvexHullVertices[ConvexHullIdx]];
while( (isLeft(x0, y0, x1, y1, x2, y2)>=0) && (ConvexHullIdx>=2))
{
NumbersOfConvexHullVertices[ConvexHullIdx-1]=NumbersOfConvexHullVertices[ConvexHullIdx];
ConvexHullIdx--;
if(ConvexHullIdx>=2)//Enough points in the hull to process.
{
x0=NumbersOfConvexHullVertices[ConvexHullIdx-2];
y0=CandleBodyMaxima[NumbersOfConvexHullVertices[ConvexHullIdx-2]];
x1=NumbersOfConvexHullVertices[ConvexHullIdx-1];
y1=CandleBodyMaxima[NumbersOfConvexHullVertices[ConvexHullIdx-1]];
x2=NumbersOfConvexHullVertices[ConvexHullIdx];
y2=CandleBodyMaxima[NumbersOfConvexHullVertices[ConvexHullIdx]];
}//if
}//while
}//for
//Find the longest down-trend
for(i=0; i<ConvexHullIdx; i++)
{
StartIdx=NumbersOfConvexHullVertices[i];
EndIdx=NumbersOfConvexHullVertices[i+1];
Length=EndIdx-StartIdx;
if(Length>BestLength &&
CandleBodyMaxima[StartIdx]<CandleBodyMaxima[EndIdx])
{
BestStartIdx=StartIdx;
BestEndIdx=EndIdx;
BestLength=Length;
}//if
}//for
if(BestLength==0)
{
ExtMapBuffer1[0]=0;
Print("No down trend");
return(0);
}
BestStartTime=Time[BestEndIdx+StartingBarNumber+1];
BestEndTime=Time[BestStartIdx+StartingBarNumber+1];
BestStartPrice=CandleBodyMaxima[BestEndIdx];
BestEndPrice=CandleBodyMaxima[BestStartIdx];
}//else //Find an Up-Trend with a convex hull.
ExtMapBuffer1[0]=(1.0*BestLength)/barsToProcess;
// Âàðèàíò: ExtMapBuffer1[0]=BestEndIdx/barsToProcess;
}//else Process
//----
return(0);
}
//+------------------------------------------------------------------+
Comments