This script is designed as a visual analysis tool for the MetaTrader trading platform. Its primary purpose is to automatically identify market trends by detecting specific price patterns and drawing a dynamic "channel" on your chart to highlight potential support and resistance zones.
Core Logic Overview
The logic follows a structured sequence to interpret market movement:
1. Identification of Key Pivot Points The script begins by scanning a specific historical range of price bars (user-configurable, but defaults to 240 bars). It looks for "fractals"—which are essentially local peaks (highs) and valleys (lows) in the price action. It intelligently adjusts how far back it looks based on the timeframe you are currently using (e.g., looking further back on lower timeframes and closer on higher ones).
2. Trend Direction and Step Calculation Once it finds two significant opposite points (a high and a low), it calculates the "Step." This is essentially the rate of change between those two points over time.
- If the price moved upward from the first point to the second, the script recognizes an ascending trend.
- If the price moved downward, it identifies a descending trend.
3. Channel Projection Using these points and the calculated step, the script projects a visual channel onto the chart:
- The Primary Trend Line: A thick line that represents the main trajectory of the market movement.
- The Opposite Boundary: A secondary line that mirrors the primary trend, creating a "corridor" or channel where the price is expected to move.
- The Equilibrium Line (Take): The script also calculates and draws a dotted center line, representing the mathematical average between the two boundaries of the channel.
4. Dynamic Breach Detection The logic includes a "breach check." It monitors whether the current market price has crossed outside the established boundaries of the channel. If the price breaks out of this corridor, the script identifies it as a significant event and marks it accordingly on the chart using specific symbols/arrows.
Visual Output
For the user, this logic translates into three distinct visual elements on the trading screen:
- Buy Line (Lime): Represents the primary upward or supporting trend line.
- Sell Line (Red): Represents the opposing downward or resistance trend line.
- Take Line (Green Dotted): Provides a visual guide for the "middle ground" of the current price channel.
In summary, the script automates the heavy lifting of geometry—calculating slopes, identifying peaks/valleys, and projecting boundaries—so that a trader can quickly see the current market "corridor" and identify when the price is moving toward its limits or breaking out of them.
//+------------------------------------------------------------------+
//| 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("Sell");
ObjectDelete("Buy");
ObjectDelete("Take");
}
//+------------------------------------------------------------------+
//| 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("Sell",OBJ_TREND,0,T2,PP+Step*AB,T1,PP);
ObjectSet("Sell",OBJPROP_COLOR,Red);
ObjectSet("Sell",OBJPROP_WIDTH,2);
ObjectSet("Sell",OBJPROP_STYLE,STYLE_SOLID);
ObjectSetText("Sell","Sell",10, "Times New Roman", Red);
ObjectCreate("Buy",OBJ_TREND,0,T2,P2,T1,P1);
ObjectSet("Buy",OBJPROP_COLOR,Lime);
ObjectSet("Buy",OBJPROP_WIDTH,2);
ObjectSet("Buy",OBJPROP_STYLE,STYLE_SOLID);
ObjectSetText("Buy","Buy",10, "Times New Roman", Blue);
ObjectCreate("Take",OBJ_TREND,0,T2,(P2+PP+Step*AB)/2,T1,(P1+PP)/2);
ObjectSet("Take",OBJPROP_COLOR,Green);
ObjectSet("Take",OBJPROP_WIDTH,1);
ObjectSet("Take",OBJPROP_STYLE,STYLE_DOT);
ObjectSetText("Take","Take",10, "Times New Roman", Green);
//----
return(0);
}
//+------------------------------------------------------------------+
Comments