//Индикатор показывает относительную длину восходящего тренда. //+------------------------------------------------------------------+ //| 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=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; iBestLength && 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); } //+------------------------------------------------------------------+