shi_channel4_v2_Stop[1]
Download scriptThis script is designed to automatically identify and draw a dynamic pricing channel on a trading chart. Instead of relying on static lines, it uses mathematical logic to detect price trends, calculate boundaries, and provide real-time visual cues for potential trading entries and exit points.
Core Logic Overview
1. Fractal Identification (The Anchor Points) The script begins by scanning historical price data to find "Fractals"—specific peaks (highs) and valleys (lows). It looks at a defined number of past candles to determine these points. These fractals act as the "anchors" for the channel. By identifying where the price reached a local high or low, the script can establish the starting geometry of the price corridor.
2. Channel Construction and Trend Detection Once two significant fractal points are identified, the script calculates the "Step" (the slope).
- If the step is positive, it identifies a downward trend; if negative, an upward trend.
- It then projects these lines forward across a specific number of bars to create a visual channel.
- A "Middle Line" is automatically calculated as the midpoint between the upper and lower boundaries of this channel.
3. Dynamic Adjustment (The Pivot Point) The script doesn't just draw a fixed line; it continuously looks for "breaks." It evaluates the current price against the projected channel to find the most relevant pivot point. If the price pushes past a boundary, the script adjusts its internal calculations to ensure the channel remains relevant to the current market movement.
4. Volatility and "Flatness" Filtering To prevent the indicator from giving signals during choppy, sideways markets (where price isn't moving in a clear direction), the script includes a flatness filter. It compares the width of the channel against the Average True Range (ATR). If the channel is too narrow relative to the market's volatility, it identifies the market as "flat" and changes the labels accordingly to warn the user.
5. Automated Labeling (Buy/Sell/Take/Stop) The most user-friendly feature of this logic is the dynamic labeling system. Based on the interaction between the current price, the channel slope, and the volatility filter, the script automatically updates text labels on the chart:
- Buy/Sell: Indicates potential entry areas based on where the price sits relative to the channel.
- Take/Stop: Identifies "Take Profit" targets and "Stop Loss" zones based on a percentage of the channel width.
Summary for the User
Essentially, this tool automates the process of drawing trend channels by hand. It finds the highs and lows of the past, projects them into the future as a corridor, calculates the "fair value" (middle line) of the market, and then places visual markers telling you where to potentially enter a trade, where to take your profit, and where to set your safety stops.
//+------------------------------------------------------------------+
//| 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;
extern int Procent_Stop=15;//ñòîï % îò øèðèíû êàíàëà
int CurrentBar=0;
double Step=0;
int B1=-1,B2=-1;
int UpDown=0;
double P1=0,P2=0,PP=0, St=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");
ObjectDelete("Stop1");
ObjectDelete("Stop2");
}
//+------------------------------------------------------------------+
//| 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);
St=(PP-P1)*Procent_Stop/100;
//Åñëè íå áûëî ïåðåñå÷åíèÿ êàíàëà, òî 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 (ObjectFind("Stop1")==-1)
{
ObjectCreate("Stop1",OBJ_TREND,0,T2,(PP+Step*AB)+St,T1,PP+St);
}
else
{
ObjectSet("Stop1", OBJPROP_TIME1,T2);
ObjectSet("Stop1", OBJPROP_PRICE1,(PP+Step*AB)+St);
ObjectSet("Stop1", OBJPROP_TIME2,T1);
ObjectSet("Stop1", OBJPROP_PRICE2,PP+St);
}
if (ObjectFind("Stop2")==-1)
{
ObjectCreate("Stop2",OBJ_TREND,0,T2,P2-St,T1,P1-St);
}
else
{
ObjectSet("Stop2", OBJPROP_TIME1,T2);
ObjectSet("Stop2", OBJPROP_PRICE1,P2-St);
ObjectSet("Stop2", OBJPROP_TIME2,T1);
ObjectSet("Stop2", OBJPROP_PRICE2,P1-St);
}
if (flat==1)
{
//Print("flat=1");
if(PP+Step*AB>P2)
{
ObjectSetText("TL1","Sell");
ObjectSetText("TL2","Buy");
ObjectSetText("Stop1","");
ObjectSetText("Stop2","");
}
else
{
ObjectSetText("TL2","Sell");
ObjectSetText("TL1","Buy");
ObjectSetText("Stop1","");
ObjectSetText("Stop2","");
}
}
else
{
//Print("flat=0");
if((PP+Step*AB>P2)&&(trend==-1))
{
ObjectSetText("TL1","Sell");
ObjectSetText("TL2","Take");
ObjectSetText("Stop1","Stop");
ObjectSetText("Stop2","0");
}
if((PP+Step*AB>P2)&&(trend==1))
{
ObjectSetText("TL1","Take");
ObjectSetText("TL2","Buy");
ObjectSetText("Stop1","0");
ObjectSetText("Stop2","Stop");
}
if((PP+Step*AB<P2)&&(trend==-1))
{
ObjectSetText("TL2","Sell");
ObjectSetText("TL1","Take");
ObjectSetText("Stop1","0");
ObjectSetText("Stop2","Stop");
}
if((PP+Step*AB<P2)&&(trend==1))
{
ObjectSetText("TL2","Take");
ObjectSetText("TL1","Buy");
ObjectSetText("Stop1","Stop");
ObjectSetText("Stop2","0");
}
}
//----
Comment("Âåðõ êàíàëà = ",PP,"\n","Ñåðåäèíà = ",(P1+PP)/2,"\n","Íèç êàíàëà = ",P1,"\n","Øèðèíà = ",(PP-P1),"\n","Êàñàíèå Âåðõà = ",-(PP-Bid)," ïèïñîâ","\n","Êàñàíèå Íèçà = ",(P1-Ask)," ïèïñîâ", "\n","ÑÒÎÏ ëèíèÿ = ",(St)," ïèïñîâ" );
return(0);
}
//+------------------------------------------------------------------+
Comments