This script is designed to analyze market trends by automatically drawing a dynamic price channel on your trading chart. It identifies the structural boundaries of the current market movement to help traders visualize potential zones of interest and price extremes.
Core Logic Overview
The tool operates by analyzing historical price data over a specific timeframe (defined by the user) to calculate a linear trend. Instead of just looking at the most recent price, it performs a mathematical calculation to determine the "path" the market has taken, establishing a baseline for where the price is heading.
Key Functional Components
1. Trend Analysis and Channel Construction The script identifies the highest highs and lowest lows within a specific look-back period. It uses these points to construct a multi-layered channel consisting of three distinct lines:
- Upper Boundary: Represents the resistance or ceiling of the current trend.
- Lower Boundary: Represents the support or floor of the current trend.
- Middle Line: A dotted center line that represents the average equilibrium of the price movement.
2. Dynamic Adaptation The channel is not static; it recalculates based on recent market activity. The script constantly compares the relationship between price highs and lows to determine which boundary is more significant for the current trend direction. This ensures that the visual channel adjusts as the market shifts from bullish (upward) to bearish (downward) momentum.
3. Automated Entry Alerts (Trigger System) One of the most practical features of this script is its "Trigger" logic. It monitors how close the live market price is to the boundaries of the channel:
- Overextended Alerts: If the price moves too close to the upper boundary, the script can signal that the market may be overbought or nearing resistance, suggesting a potential "Short" opportunity.
- Undersold Alerts: Conversely, if the price drops near the lower boundary, it can signal that the market may be oversold, suggesting a potential "Long" opportunity.
4. Visual Feedback and Reporting The script provides immediate visual confirmation by changing line colors when these trigger zones are hit. Additionally, it displays a live comment on the corner of your chart showing:
- The total size of the current channel.
- The current recommended entry type (Long, Short, or both).
- The active trigger distance.
Summary for the User
Essentially, this tool acts as a visual guide that "maps out" the current market's territory. It tells you where the boundaries are, identifies the middle ground, and alerts you when the price is stretching toward the edges, helping you stay informed on potential reversal zones or breakout points without having to manually calculate support and resistance levels.
//+------------------------------------------------------------------+
//| TMLM_Channel-v1.mq4 |
//| Copyright © 2007, Shurka & Kevin |
//| ANG3110@latchess.com, join frantacech |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2004, Shurka & Kevin, ANG3110@latchess.com"
#property link ""
//----------------------------------
#property indicator_chart_window
//----------------------------------
extern bool ShowComments = true;
extern int Trigger = 50;
extern int Hours=720;
extern color MainAlert=Red;
extern color MainUpper=Gold;
extern color MainLower=Gold;
extern color MainMiddle=Magenta;
string name = "WTL";
string entry = "";
bool OnlyLong = false, OnlyShort = false;
//------------------
double lr,lr0,lrp;
double sx,sy,sxy,sx2,aa,bb;
int p,fs;
int f,f0,f1;
double dh,dl,dh_1,dl_1,dh_2,dl_2;
int ai_1,ai_2,bi_1,bi_2;
double hai,lai,dhi,dli,dhm,dlm,ha0,hap,la0,lap;
double price_p1,price_p0,price_p2,price_01,price_00,price_02;
int p1,p0,p2,fp;
//*****************************************
int init() {
p=Hours*60/Period();
if (fs==0) {
fs=1;
}
return(0);
}
//*******************************
int deinit() {
ObjectDelete(name+"1");
ObjectDelete(name+"0");
ObjectDelete(name+"2"); }
//*******************************
int start() {
int i,n;
//------------------------------------------------------------------------------
if (f==1) {
p1=iBarShift(Symbol(),Period(),ObjectGet(name+"1",OBJPROP_TIME1));
p0=iBarShift(Symbol(),Period(),ObjectGet(name+"0",OBJPROP_TIME1));
p2=iBarShift(Symbol(),Period(),ObjectGet(name+"2",OBJPROP_TIME1));
if (fp==0 && p!=p1) {p=p1; fp=1;}
if (fp==0 && p!=p0) {p=p0; fp=1;}
if (fp==0 && p!=p2) {p=p2; fp=1;}
}
//====================================================
sx=0; sy=0; sxy=0; sx2=0;
for (n=0; n<=p; n++) {sx+=n; sy+=Close[n]; sxy+=n*Close[n]; sx2+=MathPow(n,2);}
aa=(sx*sy-(p+1)*sxy)/(MathPow(sx,2)-(p+1)*sx2); bb=(sy-aa*sx)/(p+1);
//----------------------------------------------------
for (i=0; i<=p; i++) {
lr=bb+aa*i;
dh=High[i]-lr; dl=Low[i]-lr;
//----------------------------------------------------
if (i<p/2) {if (i==0) {dh_1=0.0; dl_1=0.0; ai_1=i; bi_1=i;}
if (dh>=dh_1) {dh_1=dh; ai_1=i;}
if (dl<=dl_1) {dl_1=dl; bi_1=i;}}
//----------------------------------------------------
if (i>=p/2) {if (i==p/2) {dh_2=0.0; dl_2=0.0; ai_2=i; bi_2=i;}
if (dh>=dh_2) {dh_2=dh; ai_2=i;}
if (dl<=dl_2) {dl_2=dl; bi_2=i;}}}
//-------------------------------------
lr0=bb; lrp=bb+aa*(i+p);
//===================================================
if (MathAbs(ai_1-ai_2)>MathAbs(bi_1-bi_2)) f=1;
if (MathAbs(ai_1-ai_2)<MathAbs(bi_1-bi_2)) f=2;
if (MathAbs(ai_1-ai_2)==MathAbs(bi_1-bi_2)) {if (MathAbs(dh_1-dh_2)<MathAbs(dl_1-dl_2)) f=1; if (MathAbs(dh_1-dh_2)>=MathAbs(dl_1-dl_2)) f=2;}
//=================================================
if (f==1) {
for (n=0; n<=20; n++) { f1=0;
for (i=0; i<=p; i++) {hai=High[ai_1]*(i-ai_2)/(ai_1-ai_2)+High[ai_2]*(i-ai_1)/(ai_2-ai_1);
if (i==0 || i==p/2) dhm=0.0;
if (High[i]-hai>dhm && i<p/2) {ai_1=i; f1=1;}
if (High[i]-hai>dhm && i>=p/2) {ai_2=i; f1=1;} }
if (f==0) break;}
//----------------------------
for (i=0; i<=p; i++) {hai=High[ai_1]*(i-ai_2)/(ai_1-ai_2)+High[ai_2]*(i-ai_1)/(ai_2-ai_1);
dli=Low[i]-hai;
if (i==0) dlm=0.0; if (dli<dlm) dlm=dli;}
ha0=High[ai_1]*(0-ai_2)/(ai_1-ai_2)+High[ai_2]*(0-ai_1)/(ai_2-ai_1);
hap=High[ai_1]*(p-ai_2)/(ai_1-ai_2)+High[ai_2]*(p-ai_1)/(ai_2-ai_1);
//----------------------------
//i have changed the code so the name of the trend does not change // Fadi
price_p1=hap;
price_p0=hap+dlm/2;
price_p2=hap+dlm;
price_01=ha0;
price_00=ha0+dlm/2;
price_02=ha0+dlm;
}
//=================================================
if (f==2) {
for (n=0; n<=20; n++) { f1=0;
for (i=0; i<=p; i++) {lai=Low[bi_1]*(i-bi_2)/(bi_1-bi_2)+Low[bi_2]*(i-bi_1)/(bi_2-bi_1);
if (i==0 || i==p/2) dlm=0.0;
if (Low[i]-lai<dlm && i<p/2) {bi_1=i; f1=1;}
if (Low[i]-lai<dlm && i>=p/2) {bi_2=i; f1=1;}}
if (f==0) break;}
//----------------------------
for (i=0; i<=p; i++) {lai=Low[bi_1]*(i-bi_2)/(bi_1-bi_2)+Low[bi_2]*(i-bi_1)/(bi_2-bi_1);
dhi=High[i]-lai;
if (i==0) dhm=0.0; if (dhi>dhm) dhm=dhi;}
la0=Low[bi_1]*(0-bi_2)/(bi_1-bi_2)+Low[bi_2]*(0-bi_1)/(bi_2-bi_1);
lap=Low[bi_1]*(p-bi_2)/(bi_1-bi_2)+Low[bi_2]*(p-bi_1)/(bi_2-bi_1);
//----------------------------------------------------------------
//i have changed the code so the name of the trend does not change // Fadi
price_p1=lap;
price_p0=lap+dhm/2;
price_p2=lap+dhm;
price_01=la0;
price_00=la0+dhm/2;
price_02=la0+dhm;
}
//===================================================================================
if (price_02 > price_01)
{
ObjectCreate(name+"1",2, 0,Time[p],price_p1,Time[0],price_01);
ObjectCreate(name+"0",2, 0,Time[p],price_p0,Time[0],price_00);
ObjectCreate(name+"2",2, 0,Time[p],price_p2,Time[0],price_02);
//-----------------------------------------------------------------
ObjectSet(name+"2",OBJPROP_COLOR,MainUpper);
ObjectSet(name+"1",OBJPROP_COLOR,MainLower);
entry = "LONG&SHORT";
OnlyLong = false;
OnlyShort = false;
if (NormalizeDouble((price_02 - Ask)/Point,0) < Trigger )
{
ObjectSet(name+"2",OBJPROP_COLOR,MainAlert);
entry = "Only SHORT";
OnlyShort = true;
}
if (NormalizeDouble((Bid - price_01)/Point,0) < Trigger )
{
ObjectSet(name+"1",OBJPROP_COLOR,MainAlert);
entry = "Only LONG";
OnlyLong = true;
}
ObjectSet(name+"0",OBJPROP_COLOR,MainMiddle);
ObjectSet(name+"0",OBJPROP_STYLE,STYLE_DOT);
ObjectSet(name+"0",OBJPROP_WIDTH,2); // these vaules control the width of the line
ObjectSet(name+"1",OBJPROP_WIDTH,2);
ObjectSet(name+"2",OBJPROP_WIDTH,2);
//---------------------------------------------
ObjectSet(name+"1",OBJPROP_TIME1,Time[p]);
ObjectSet(name+"1",OBJPROP_PRICE1,price_p1);
ObjectSet(name+"1",OBJPROP_TIME2,Time[0]);
ObjectSet(name+"1",OBJPROP_PRICE2,price_01);
ObjectSet(name+"0",OBJPROP_TIME1,Time[p]);
ObjectSet(name+"0",OBJPROP_PRICE1,price_p0);
ObjectSet(name+"0",OBJPROP_TIME2,Time[0]);
ObjectSet(name+"0",OBJPROP_PRICE2,price_00);
ObjectSet(name+"2",OBJPROP_TIME1,Time[p]);
ObjectSet(name+"2",OBJPROP_PRICE1,price_p2);
ObjectSet(name+"2",OBJPROP_TIME2,Time[0]);
ObjectSet(name+"2",OBJPROP_PRICE2,price_02);
} else
{
ObjectCreate(name+"2",2, 0,Time[p],price_p1,Time[0],price_01);
ObjectCreate(name+"0",2, 0,Time[p],price_p0,Time[0],price_00);
ObjectCreate(name+"1",2, 0,Time[p],price_p2,Time[0],price_02);
//-----------------------------------------------------------------
ObjectSet(name+"2",OBJPROP_COLOR,MainUpper);
ObjectSet(name+"1",OBJPROP_COLOR,MainLower);
entry = "LONG&SHORT";
OnlyLong = false;
OnlyShort = false;
if (NormalizeDouble((price_01 - Ask)/Point,0) < Trigger )
{
ObjectSet(name+"2",OBJPROP_COLOR,MainAlert);
entry = "Only SHORT";
OnlyShort = true;
}
if (NormalizeDouble((Bid - price_02)/Point,0) < Trigger )
{
ObjectSet(name+"1",OBJPROP_COLOR,MainAlert);
entry = "Only LONG";
OnlyLong = true;
}
ObjectSet(name+"0",OBJPROP_COLOR,MainMiddle);
ObjectSet(name+"0",OBJPROP_STYLE,STYLE_DOT);
ObjectSet(name+"0",OBJPROP_WIDTH,2); // these vaules control the width of the line
ObjectSet(name+"2",OBJPROP_WIDTH,2);
ObjectSet(name+"1",OBJPROP_WIDTH,2);
//---------------------------------------------
ObjectSet(name+"2",OBJPROP_TIME1,Time[p]);
ObjectSet(name+"2",OBJPROP_PRICE1,price_p1);
ObjectSet(name+"2",OBJPROP_TIME2,Time[0]);
ObjectSet(name+"2",OBJPROP_PRICE2,price_01);
ObjectSet(name+"0",OBJPROP_TIME1,Time[p]);
ObjectSet(name+"0",OBJPROP_PRICE1,price_p0);
ObjectSet(name+"0",OBJPROP_TIME2,Time[0]);
ObjectSet(name+"0",OBJPROP_PRICE2,price_00);
ObjectSet(name+"1",OBJPROP_TIME1,Time[p]);
ObjectSet(name+"1",OBJPROP_PRICE1,price_p2);
ObjectSet(name+"1",OBJPROP_TIME2,Time[0]);
ObjectSet(name+"1",OBJPROP_PRICE2,price_02);
}
//==================================================================
f=1; p1=p; p0=p; p2=p; fp=0;
//*************************************************************************************
if (ShowComments) Comment(" Main Channel size: ", DoubleToStr(MathAbs(price_02 - price_01)/Point,0), ", Entry: ",entry, ", Trigger: ", DoubleToStr(Trigger,0));
//if (ShowComments) Comment(" Main Channel size = ", DoubleToStr(MathAbs(price_02 - price_01)/Point,0), " Slope = ");
//Comment( "Ask:", Ask,", Bid:", Bid,"\n","price_02: ",price_02, "\n","price_01: ",price_01, "\n",entry);
Sleep(10000);
RefreshRates();
return(0);}
//=====================================================================================
Comments