shi_channel4-1(for trade channel)
Download scriptThis script is designed to automatically analyze price action on a trading chart to identify and draw structural trend channels. It helps traders visualize the prevailing direction of the market by finding key high and low points and connecting them with geometric lines.
How the Logic Works
1. Identifying Key Pivot Points The core of the script involves searching through historical price data to find "fractals"—these are significant peaks (highs) and valleys (lows) in the market. The script looks at a specific number of past bars (which changes automatically depending on your timeframe, such as 1-minute or 1-hour charts) to determine if a specific price point is a local maximum or minimum.
2. Establishing the Channel Structure Once the script identifies two primary points of interest (a significant high and a significant low), it calculates the "Step" or slope between them. Using this slope, it constructs a dynamic channel consisting of three distinct visual components:
- The Upper Boundary: A line representing the ceiling of the current price movement.
- The Lower Boundary: A line representing the floor of the current price movement.
- The Median Line: A center line that acts as a baseline for the trend's progression.
3. Dynamic Trend Analysis and Filtering The script doesn't just draw lines; it actively evaluates the "health" of the trend:
- Flatness Detection: It measures the volatility of the market (using an Average True Range calculation) against the width of the channel. If the channel is too narrow relative to recent price swings, it identifies the market as being in a "flat" or sideways state.
- Boundary Protection: The logic includes a verification step to ensure the trend lines aren't being "broken" by minor price spikes. It checks if the most recent price action respects the boundaries established by the channel's slope.
4. Visual Labels and Guidance Based on the direction of the slope and the current market state, the script provides real-time text labels on the chart. Depending on whether the market is trending or consolidating, it will display dynamic prompts such as "Buy," "Sell," or "Take" (indicating a target area).
5. Real-Time Data Output Finally, the script provides a data summary in the corner of the screen. This gives you the raw numbers behind the visuals, including the current channel width, the exact distance of the current price from the upper and lower boundaries, and the coordinates of the median line.
//+------------------------------------------------------------------+
//| 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;
extern double flatCriteria=0.25;
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;
int trend,flat;
//+------------------------------------------------------------------+
//| 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();
int X = (Ask-P1);
int X2 = (Bid-P2);
//----
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;
X = P1;
}
}
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 áàðîâ
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];
//Print("P1=",P1," P2=",P2);
//Åñëè íå áûëî ïåðåñå÷åíèÿ êàíàëà, òî 0, èíà÷å ñòàâèì ïñèñó.
if(iprice!=0) ExtMapBuffer1[ishift]=iprice;
//DelObj();
if (Step>0) trend=-1; else trend=1;
if (MathAbs(Step*20)>=2*iATR(NULL,0,40,0)*flatCriteria) flat=0; else flat=1;
if (ObjectFind("TL1")==-1)
{
ObjectCreate("TL1",OBJ_TREND,0,T2,PP+Step*AB,T1,PP);
}
else
{
ObjectSet("TL1", OBJPROP_TIME1,T2);
ObjectSet("TL1", OBJPROP_PRICE1,PP+Step*AB);
ObjectSet("TL1", OBJPROP_TIME2,T1);
ObjectSet("TL1", OBJPROP_PRICE2,PP);
}
/*
ObjectSet("TL1",OBJPROP_COLOR,ForestGreen);
ObjectSet("TL1",OBJPROP_WIDTH,2);
ObjectSet("TL1",OBJPROP_STYLE,STYLE_SOLID);
*/
if (ObjectFind("TL2")==-1)
{
ObjectCreate("TL2",OBJ_TREND,0,T2,P2,T1,P1);
}
else
{
ObjectSet("TL2", OBJPROP_TIME1,T2);
ObjectSet("TL2", OBJPROP_PRICE1,P2);
ObjectSet("TL2", OBJPROP_TIME2,T1);
ObjectSet("TL2", OBJPROP_PRICE2,P1);
}
/*
ObjectSet("TL2",OBJPROP_COLOR,ForestGreen);
ObjectSet("TL2",OBJPROP_WIDTH,2);
ObjectSet("TL2",OBJPROP_STYLE,STYLE_SOLID);
*/
if (ObjectFind("MIDL")==-1)
{
ObjectCreate("MIDL",OBJ_TREND,0,T2,(P2+PP+Step*AB)/2,T1,(P1+PP)/2);
}
else
{
ObjectSet("MIDL", OBJPROP_TIME1,T2);
ObjectSet("MIDL", OBJPROP_PRICE1,(P2+PP+Step*AB)/2);
ObjectSet("MIDL", OBJPROP_TIME2,T1);
ObjectSet("MIDL", OBJPROP_PRICE2,(P1+PP)/2);
}
/*
ObjectSet("MIDL",OBJPROP_COLOR,ForestGreen);
ObjectSet("MIDL",OBJPROP_WIDTH,1);
ObjectSet("MIDL",OBJPROP_STYLE,STYLE_DOT);
*/
if (flat==1)
{
//Print("flat=1");
if(PP+Step*AB>P2)
{
ObjectSetText("TL1","Sell");
ObjectSetText("TL2","Buy");
}
else
{
ObjectSetText("TL2","Sell");
ObjectSetText("TL1","Buy");
}
}
else
{
//Print("flat=0");
if((PP+Step*AB>P2)&&(trend==-1))
{
ObjectSetText("TL1","Sell");
ObjectSetText("TL2","Take");
}
if((PP+Step*AB>P2)&&(trend==1))
{
ObjectSetText("TL1","Take");
ObjectSetText("TL2","Buy");
}
if((PP+Step*AB<P2)&&(trend==-1))
{
ObjectSetText("TL2","Sell");
ObjectSetText("TL1","Take");
}
if((PP+Step*AB<P2)&&(trend==1))
{
ObjectSetText("TL2","Take");
ObjectSetText("TL1","Buy");
}
}
//----
Comment("Âåðõ êàíàëà = ",PP,"\n","Ñåðåäèíà = ",(P1+PP)/2,"\n","Íèç êàíàëà = ",P1,"\n","Øèðèíà = ",(PP-P1),"\n","Êàñàíèå Âåðõà = ",-(PP-Bid)," ïèïñîâ","\n","Êàñàíèå Íèçà = ",(P1-Ask)," ïèïñîâ");
return(0);
}
//+------------------------------------------------------------------+
Comments