TMLM-Channel-v2.1

Download script
Author: Copyright � 2004, Shurka & Kevin, ANG3110@latchess.com
TMLM-Channel-v2.1

Technical Logic Overview

This script is designed to provide visual and analytical support for traders by identifying market trends, calculating dynamic "channels," and alerting users to potential entry points based on price proximity to these channels. It works by combining linear regression analysis with fractal identification to map out where the price is currently heading.

1. Trend Identification via Linear Regression

The script begins by analyzing a specific look-back period (defined by the Hours parameter) to determine the overall "path" of the market. It uses a mathematical method called Linear Regression to calculate a best-fit line through recent price data. This helps the tool distinguish between short-term noise and the actual underlying trend of the asset.

2. Dynamic Channel Construction

Once the primary trend is established, the script identifies "Fractals"—significant local peaks and valleys in the price action. It uses these points to construct a visual channel on your chart:

  • Upper and Lower Boundaries: The script projects lines that represent the limits of the current price movement.
  • Midline: A dotted center line is drawn to help visualize the "fair value" or equilibrium of the trend.
  • Dynamic Adjustment: Unlike static lines, these channels are designed to react to new data. If the price breaks through certain levels or establishes new significant highs/lows, the script recalculates the channel's slope and width.

3. Intelligent Alerts and Entry Signals

A core feature of this script is its ability to communicate "trading intent" directly to the user through visual cues and on-screen comments:

  • Proximity Alerts: The script monitors how close the current market price (Ask/Bid) is to the channel boundaries. If the price gets within a specific distance (the Trigger value), the corresponding line will change color to alert you of a potential reaction.
  • Directional Guidance: Depending on where the price sits in relation to the calculated channel, the script updates an on-screen comment to suggest whether the environment is favorable for "Only Long," "Only Short," or both positions simultaneously.
  • Real-time Data Display: The script provides a live summary of the channel size, the current slope (the steepness of the trend), and the current alert status in a text box on your screen.

4. Visual Execution

The script handles all the heavy lifting of drawing and redrawing objects. It automatically creates, updates, and deletes the Trend Lines (TL1, TL2, and MIDL) as the market moves. This ensures that your chart remains clean—showing only the most relevant, currently active trend information without cluttering the workspace with obsolete historical data.

Miscellaneous
Implements a curve of type %1
4 Views
0 Downloads
0 Favorites
TMLM-Channel-v2.1
//+------------------------------------------------------------------+
//|                                              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
#property indicator_buffers 1
#property indicator_color1 Red
double ExtMapBuffer1[];
//----------------------------------
extern bool ShowComments = true;
//---- input parameters for MainChannel
extern int Trigger = 50;
extern int   Hours=720;
extern color MainAlert=Red;
extern color MainUpper=Gold;
extern color MainLower=Gold;
extern color MainMiddle=Magenta;
//---- input parameters for SHI
extern int   AllBars=240;
extern int   BarsForFract=0;

//---- internal parameters
string name = "WTL";
string entry = "";
bool OnlyLong = false, OnlyShort = false;

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;
//------------------
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;
    }
//---- indicators SHI
   SetIndexStyle(0,DRAW_ARROW);
   SetIndexArrow(0,164);
   SetIndexBuffer(0,ExtMapBuffer1);
   SetIndexEmptyValue(0,0.0);
//----

   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; 
//*************************************************************************************
//----
   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();
	//Comment (PP,P1);
	
	if (PP<P1)
	{
   if (OnlyShort == false)
     {
	   ObjectCreate("TL1",OBJ_TREND,0,T2,PP+Step*AB,T1,PP); 
		ObjectSet("TL1",OBJPROP_COLOR,Lime); 
		ObjectSet("TL1",OBJPROP_WIDTH,2); 
		ObjectSet("TL1",OBJPROP_STYLE,STYLE_SOLID); 
	  }
   
   if (OnlyLong == false)
     {
	   ObjectCreate("TL2",OBJ_TREND,0,T2,P2,T1,P1); 
		ObjectSet("TL2",OBJPROP_COLOR,Lime); 
		ObjectSet("TL2",OBJPROP_WIDTH,2); 
		ObjectSet("TL2",OBJPROP_STYLE,STYLE_SOLID); 
	  }

	   ObjectCreate("MIDL",OBJ_TREND,0,T2,(P2+PP+Step*AB)/2,T1,(P1+PP)/2);
		ObjectSet("MIDL",OBJPROP_COLOR,Lime); 
		ObjectSet("MIDL",OBJPROP_WIDTH,1); 
		ObjectSet("MIDL",OBJPROP_STYLE,STYLE_DOT);
		}
		if (PP>P1)
	{
   if (OnlyLong == false)
     {
	   ObjectCreate("TL2",OBJ_TREND,0,T2,PP+Step*AB,T1,PP); 
		ObjectSet("TL2",OBJPROP_COLOR,Lime); 
		ObjectSet("TL2",OBJPROP_WIDTH,2); 
		ObjectSet("TL2",OBJPROP_STYLE,STYLE_SOLID); 
	  }

   if (OnlyShort == false)
     {
	   ObjectCreate("TL1",OBJ_TREND,0,T2,P2,T1,P1); 
		ObjectSet("TL1",OBJPROP_COLOR,Lime); 
		ObjectSet("TL1",OBJPROP_WIDTH,2); 
		ObjectSet("TL1",OBJPROP_STYLE,STYLE_SOLID); 
	  }

   	ObjectCreate("MIDL",OBJ_TREND,0,T2,(P2+PP+Step*AB)/2,T1,(P1+PP)/2);
		ObjectSet("MIDL",OBJPROP_COLOR,Lime); 
		ObjectSet("MIDL",OBJPROP_WIDTH,1); 
		ObjectSet("MIDL",OBJPROP_STYLE,STYLE_DOT);
		}
		//Comment(" Channel size = ", DoubleToStr(MathAbs(PP - P1)/Point,0), " Slope = ", DoubleToStr(-Step/Point, 2));
//----
//----

if (ShowComments)
 {
 Comment(" Main Channel size: ", DoubleToStr(MathAbs(price_02 - price_01)/Point,0), ", Entry: ",entry, ", Trigger: ", DoubleToStr(Trigger,0), "\n"," Channel size = ", DoubleToStr(MathAbs(PP - P1)/Point,0), " Slope = ", DoubleToStr(-Step/Point, 2));
 }
//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);}
//=====================================================================================

void DelObj()
{
	ObjectDelete("TL1");
	ObjectDelete("TL2");
	ObjectDelete("MIDL");
}

Comments