SHI Channel11
Download scriptThis script is designed to analyze market price action by automatically identifying structural trends and projecting a dynamic trading "channel" on the chart. It focuses on identifying significant price extremes to establish the boundaries of the current market movement.
Core Logic Overview
The script operates through a multi-step process to determine the geometry of the market:
1. Identification of Structural Extremes (Fractals) Instead of looking at every single price tick, the script searches for "Fractals"—these are local peaks (highs) and valleys (lows) where the price significantly reverses direction compared to its immediate neighbors. The script automatically adjusts how many bars it looks at based on the timeframe you are using (e.g., looking at a larger window on daily charts and a smaller window on 1-minute charts).
2. Establishing the Trend Line Once two significant points are identified—either two consecutive highs or two consecutive lows—the script calculates the "Step" (the rate of change) between them. This allows it to determine if the market is trending upward, downward, or moving sideways. It uses these two points as the anchor for a projected path.
3. Dynamic Channel Projection Using the calculated slope and the identified extremes, the script constructs a three-part channel:
- The Median Line: The central path of the trend.
- Upper and Lower Boundaries: These lines run parallel to the median line, creating a " коридор" (corridor) or envelope that represents the current price volatility and range.
4. Intelligent Boundary Adjustment A unique feature of this logic is its ability to detect "breakouts." The script doesn't just blindly draw a line; it checks if recent price action has exceeded the established boundaries. If a significant violation occurs, it identifies the specific point of breach to ensure the channel reflects the most current market reality rather than outdated data.
5. Visual Output and Data Tracking
- Dynamic Rendering: The script calculates these values for a look-back period (defaulting to 240 bars), providing a continuous visual representation of the trend.
- On-Screen Diagnostics: It provides a real-time "Comment" on the trading chart, displaying the actual size of the channel (in points) and the specific slope of the trend.
Summary for the User
Essentially, this script acts as an automated "trend mapper." It finds the most important peaks and valleys in recent history, draws a corridor around them to show where the price is "supposed" to stay, and alerts you visually if the price begins to break out of that established territory.
//+------------------------------------------------------------------+
//| SHI_Channel11.mq4 |
//| Copyright © 2004, Shurka & Kevin |
//| |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2004, Shurka & Kevin"
#property link ""
#property indicator_chart_window
#property indicator_buffers 4
#property indicator_color1 Blue
#property indicator_color2 Green
#property indicator_color3 Red
#property indicator_color4 Red
double ExtMapBuffer1[];
double midBuffer1[];
double ABuffer1[];
double BBuffer1[];
//---- 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);
SetIndexStyle(1,DRAW_LINE);
SetIndexBuffer(1,midBuffer1);
SetIndexEmptyValue(1,0.0);
SetIndexStyle(2,DRAW_LINE);
SetIndexBuffer(2,ABuffer1);
SetIndexStyle(3,DRAW_LINE);
SetIndexBuffer(3,BBuffer1);
//----
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;
for(i=0;i<=240;i++)
{
if (Step<=0)
{
midBuffer1[i]=(P1+PP)/2-MathAbs(Step*i);
ABuffer1[i]=(P1+PP)/2-MathAbs(Step*i)+MathAbs(PP - P1)/2;
BBuffer1[i]=(P1+PP)/2-MathAbs(Step*i)-MathAbs(PP - P1)/2;
}
else
{
midBuffer1[i]=(P1+PP)/2+MathAbs(Step*i);
ABuffer1[i]=(P1+PP)/2+MathAbs(Step*i)+MathAbs(PP - P1)/2;
BBuffer1[i]=(P1+PP)/2+MathAbs(Step*i)-MathAbs(PP - P1)/2;
}
}
DelObj();
Comment(" Channel size = ", DoubleToStr(MathAbs(PP - P1)/Point,0), " Slope = ", DoubleToStr(-Step/Point, 2));
//----
return(0);
}
//+------------------------------------------------------------------+
Comments