RelUpTrLen_forCodeBase_v01
Download scriptOverview of Technical Logic
This script is designed to identify and measure the strength of an "Up-Trend" within a specific timeframe on a trading chart. Rather than simply looking at whether the price moved from point A to point B, it uses a sophisticated geometric approach to determine the most significant upward movement over a set number of bars.
How the Logic Works
1. Data Selection The script begins by looking at a user-defined number of historical candles (bars). It allows for two different ways to interpret price: it can either look at the "Body" of the candle (the area between the open and close prices) or the absolute "Low" of each candle. This helps the user decide if they want to focus on the actual completed movement of the market or the extreme lows reached during that time.
2. Geometric Construction (The Convex Hull) To find the most reliable trend, the script employs a mathematical concept known as a "Convex Hull." Imagine stretching a rubber band around a group of scattered points; the shape the rubber band takes is the convex hull.
- The script treats each candle's price point as a coordinate on a graph.
- It builds this "hull" to identify the outer boundary of the price action.
- By focusing on the lower boundary of this shape, the script can filter out minor market "noise" and focus on the structural foundation of the price movement.
3. Identifying the Best Up-Trend Once the geometric boundary is established, the script analyzes the segments of that boundary to find the longest continuous upward move. It specifically looks for:
- A clear trajectory where the price at the end of a segment is higher than it was at the start.
- The specific segment that covers the greatest distance in terms of time (the most bars).
4. Final Output After identifying the strongest "Up-Trend" within the requested window, the script calculates a value based on the length of that trend relative to the total number of bars analyzed.
Summary for the User
In simple terms, this tool ignores minor fluctuations and looks for the most dominant, structural climb in price over a specific period. It provides a normalized value that tells you what percentage of your chosen window is occupied by the strongest upward move, helping you gauge the momentum and "strength" of the current trend.
//Èíäèêàòîð ïîêàçûâàåò îòíîñèòåëüíóþ äëèíó âîñõîäÿùåãî òðåíäà.
//+------------------------------------------------------------------+
//| RelUpTrLen_....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 SeaGreen
#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 up-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 an up-trend");
return(0);
}
else
{
if(DrawForCandleBodies)
{
BestStartPrice=CandleBodyMinimum(StartingBarNumber+2);
BestEndPrice=CandleBodyMinimum(StartingBarNumber+1);
}
else
{
BestStartPrice=Low[StartingBarNumber+2];
BestEndPrice=Low[StartingBarNumber+1];
}
if(BestStartPrice>=BestEndPrice)
{
ExtMapBuffer1[0]=0;
Print("No up trend");
return(0);
}
BestStartTime=Time[StartingBarNumber+2];
BestEndTime=Time[StartingBarNumber+1];
}
}
else //Find an Up-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 CandleBodyMinima[],
x0, y0,
x1, y1,
x2, y2;
ArrayResize(CandleBodyMinima, barsToProcess);
//Fill array CandleBodyMinima[] with values from
//the range StartingBarNumber+1 ... StartingBarNumber+barsToProcess of the chart
for(i=1; i<=barsToProcess; i++)
{
if(DrawForCandleBodies)
CandleBodyMinima[i-1]=CandleBodyMinimum(StartingBarNumber+i);
else
CandleBodyMinima[i-1]=Low[StartingBarNumber+i];
}
//Find the lower part of the convex hull for points (i, CandleBodyMinima[i]) of
//the plane
NumbersOfConvexHullVertices[0]=0;//This is the index of CandleBodyMinima[0]
ConvexHullIdx=0;//This says that NumbersOfConvexHullVertices[ConvexHullIdx] is valid.
NumbersOfConvexHullVertices[1]=1;//This is the index of CandleBodyMinima[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=CandleBodyMinima[NumbersOfConvexHullVertices[ConvexHullIdx-2]];
x1=NumbersOfConvexHullVertices[ConvexHullIdx-1];
y1=CandleBodyMinima[NumbersOfConvexHullVertices[ConvexHullIdx-1]];
x2=NumbersOfConvexHullVertices[ConvexHullIdx];
y2=CandleBodyMinima[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=CandleBodyMinima[NumbersOfConvexHullVertices[ConvexHullIdx-2]];
x1=NumbersOfConvexHullVertices[ConvexHullIdx-1];
y1=CandleBodyMinima[NumbersOfConvexHullVertices[ConvexHullIdx-1]];
x2=NumbersOfConvexHullVertices[ConvexHullIdx];
y2=CandleBodyMinima[NumbersOfConvexHullVertices[ConvexHullIdx]];
}//if
}//while
}//for
//Find the longest up-trend
for(i=0; i<ConvexHullIdx; i++)
{
StartIdx=NumbersOfConvexHullVertices[i];
EndIdx=NumbersOfConvexHullVertices[i+1];
Length=EndIdx-StartIdx;
if(Length>BestLength &&
CandleBodyMinima[StartIdx]>CandleBodyMinima[EndIdx])
{
BestStartIdx=StartIdx;
BestEndIdx=EndIdx;
BestLength=Length;
}//if
}//for
if(BestLength==0)
{
ExtMapBuffer1[0]=0;
Print("No up trend");
return(0);
}
BestStartTime=Time[BestEndIdx+StartingBarNumber+1];
BestEndTime=Time[BestStartIdx+StartingBarNumber+1];
BestStartPrice=CandleBodyMinima[BestEndIdx];
BestEndPrice=CandleBodyMinima[BestStartIdx];
}//else //Find an Up-Trend with a convex hull.
ExtMapBuffer1[0]=(1.0*BestLength)/barsToProcess;
}//else Process
//----
return(0);
}
//+------------------------------------------------------------------+
Comments