This script is designed to automatically identify and project structural trend channels on a trading chart. By analyzing historical price action, it calculates the trajectory of the market to help traders visualize the current "flow" of price movement.
Core Logic Overview
The script functions by searching through recent historical data to find specific structural pivot points, known as fractals. It focuses on identifying two distinct peaks or valleys that define the boundaries of a trend.
1. Identification of Key Points The tool automatically scans a set number of past bars (determined by the timeframe you are viewing) to locate:
- A significant high point (peak).
- A significant low point (valley).
It looks for these points dynamically; if it finds a high first, it prepares to find a corresponding low, and vice versa. This ensures that the resulting channel is based on meaningful structural shifts rather than minor price fluctuations.
2. Trend Calculation and Projection Once these two points are identified, the script performs a mathematical calculation to determine the "Step" or the rate of change between them. Using this data, it constructs three distinct lines:
- The Upper Boundary: Projects the upper limit of the price movement.
- The Lower Boundary: Projects the lower limit of the price movement.
- The Median Line: A dotted center line that represents the average momentum of the trend.
To make these lines useful for future trading, the script projects them forward into the "empty" space of the chart, allowing you to see where the trend is mathematically headed based on previous behavior.
3. Dynamic Adjustments The logic includes a "filtering" mechanism. It checks if recent price action has broken outside of the calculated boundaries. If the current price violates the projected channel in a significant way, the script identifies this as a potential trend exhaustion or shift.
4. Visual Feedback To keep the user informed without cluttering the screen, the script provides:
- Visual Lines: It draws solid lime-colored lines for the boundaries and a dotted line for the median.
- Data Overlay: It displays a text comment on the chart that informs you of the total "Channel Size" (the distance between the boundaries) and the "Slope" (the steepness of the trend).
In summary, this tool automates the process of drawing trend lines by identifying historical structural anchors and projecting them forward to provide a clear visual map of the current market direction.
/*-----------------------------+
| |
| Shared by www.Aptrafx.com |
| |
+------------------------------*/
//+------------------------------------------------------------------+
//| SHI_Channel.mq4 |
//| Copyright © 2004, Shurka & Kevin |
//| |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2004, Shurka & Kevin"
#property link ""
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_color1 Red
double ExtMapBuffer1[];
//---- input parameters
extern int AllBars=240;
extern int BarsForFract=0;
int CurrentBar=0;
double Step=0;
int B1=-1,B2=-1;
int UpDown=0;
double P1=0,P2=0,PP=0;
int i=0,AB=300,BFF=0;
int ishift=0;
double iprice=0;
datetime T1,T2;
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
//---- indicators
SetIndexStyle(0,DRAW_ARROW);
SetIndexArrow(0,164);
SetIndexBuffer(0,ExtMapBuffer1);
SetIndexEmptyValue(0,0.0);
//----
return(0);
}
//+------------------------------------------------------------------+
//| Custor indicator deinitialization function |
//+------------------------------------------------------------------+
int deinit()
{
//----
//----
return(0);
}
void DelObj()
{
ObjectDelete("TL1");
ObjectDelete("TL2");
ObjectDelete("MIDL");
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int start()
{
int counted_bars=IndicatorCounted();
//----
if ((AllBars==0) || (Bars<AllBars)) AB=Bars; else AB=AllBars; //AB-êîëè÷åñòâî îáñ÷èòûâàåìûõ áàðîâ
if (BarsForFract>0)
BFF=BarsForFract;
else
{
switch (Period())
{
case 1: BFF=12; break;
case 5: BFF=48; break;
case 15: BFF=24; break;
case 30: BFF=24; break;
case 60: BFF=12; break;
case 240: BFF=15; break;
case 1440: BFF=10; break;
case 10080: BFF=6; break;
default: DelObj(); return(-1); break;
}
}
CurrentBar=2; //ñ÷èòàåì ñ òðåòüåãî áàðà, ÷òîáû ôðàêòàë "çàêðåïèëñÿ
B1=-1; B2=-1; UpDown=0;
while(((B1==-1) || (B2==-1)) && (CurrentBar<AB))
{
//UpDown=1 çíà÷èò ïåðâûé ôðàêòàë íàéäåí ñâåðõó, UpDown=-1 çíà÷èò ïåðâûé ôðàêòàë
//íàéäåí ñíèçó, UpDown=0 çíà÷èò ôðàêòàë åù¸ íå íàéäåí.
//Â1 è Â2 - íîìåðà áàðîâ ñ ôðàêòàëàìè, ÷åðåç íèõ ñòðîèì îïîðíóþ ëèíèþ.
//Ð1 è Ð2 - ñîîòâåòñòâåííî öåíû ÷åðåç êîòîðûå áóäåì ëèíèþ ïðîâîäèòü
if((UpDown<1) && (CurrentBar==Lowest(Symbol(),Period(),MODE_LOW,BFF*2+1,CurrentBar-BFF)))
{
if(UpDown==0) { UpDown=-1; B1=CurrentBar; P1=Low[B1]; }
else { B2=CurrentBar; P2=Low[B2];}
}
if((UpDown>-1) && (CurrentBar==Highest(Symbol(),Period(),MODE_HIGH,BFF*2+1,CurrentBar-BFF)))
{
if(UpDown==0) { UpDown=1; B1=CurrentBar; P1=High[B1]; }
else { B2=CurrentBar; P2=High[B2]; }
}
CurrentBar++;
}
if((B1==-1) || (B2==-1)) {DelObj(); return(-1);} // Çíà÷èò íå íàøëè ôðàêòàëîâ ñðåäè 300 áàðîâ 8-)
Step=(P2-P1)/(B2-B1);//Âû÷èñëèëè øàã, åñëè îí ïîëîæèòåëüíûé, òî êàíàë íèñõîäÿùèé
P1=P1-B1*Step; B1=0;//ïåðåñòàâëÿåì öåíó è ïåðâûé áàð ê íóëþ
//À òåïåðü îïîðíóþ òî÷êó ïðîòèâîïîëîæíîé ëèíèè êàíàëà.
ishift=0; iprice=0;
if(UpDown==1)
{
PP=Low[2]-2*Step;
for(i=3;i<=B2;i++)
{
if(Low[i]<PP+Step*i) { PP=Low[i]-i*Step; }
}
if(Low[0]<PP) {ishift=0; iprice=PP;}
if(Low[1]<PP+Step) {ishift=1; iprice=PP+Step;}
if(High[0]>P1) {ishift=0; iprice=P1;}
if(High[1]>P1+Step) {ishift=1; iprice=P1+Step;}
}
else
{
PP=High[2]-2*Step;
for(i=3;i<=B2;i++)
{
if(High[i]>PP+Step*i) { PP=High[i]-i*Step;}
}
if(Low[0]<P1) {ishift=0; iprice=P1;}
if(Low[1]<P1+Step) {ishift=1; iprice=P1+Step;}
if(High[0]>PP) {ishift=0; iprice=PP;}
if(High[1]>PP+Step) {ishift=1; iprice=PP+Step;}
}
//Òåïåðü ïåðåñòàâèì êîíå÷íóþ öåíó è áàð íà ÀÂ, ÷òîáû ëèíèè êàíàëà ðèñîâàëèñü ïîäëèííåå
P2=P1+AB*Step;
T1=Time[B1]; T2=Time[AB];
//Åñëè íå áûëî ïåðåñå÷åíèÿ êàíàëà, òî 0, èíà÷å ñòàâèì ïñèñó.
if(iprice!=0) ExtMapBuffer1[ishift]=iprice;
DelObj();
ObjectCreate("TL1",OBJ_TREND,0,T2,PP+Step*AB,T1,PP);
ObjectSet("TL1",OBJPROP_COLOR,Lime);
ObjectSet("TL1",OBJPROP_WIDTH,2);
ObjectSet("TL1",OBJPROP_STYLE,STYLE_SOLID);
ObjectCreate("TL2",OBJ_TREND,0,T2,P2,T1,P1);
ObjectSet("TL2",OBJPROP_COLOR,Lime);
ObjectSet("TL2",OBJPROP_WIDTH,2);
ObjectSet("TL2",OBJPROP_STYLE,STYLE_SOLID);
ObjectCreate("MIDL",OBJ_TREND,0,T2,(P2+PP+Step*AB)/2,T1,(P1+PP)/2);
ObjectSet("MIDL",OBJPROP_COLOR,Lime);
ObjectSet("MIDL",OBJPROP_WIDTH,1);
ObjectSet("MIDL",OBJPROP_STYLE,STYLE_DOT);
Comment(" Channel size = ", DoubleToStr(MathAbs(PP - P1)/Point,0), " Slope = ", DoubleToStr(-Step/Point, 2));
//----
//----
return(0);
}
//+------------------------------------------------------------------+
Comments