#MTF_shi_channel_1_001

Download script
Author: Alex_Bugalter
#MTF_shi_channel_1_001

Overview of the Indicator Logic

This script is designed to identify and visualize market trends by constructing a dynamic "channel" based on historical price extremes. Instead of relying on simple moving averages, it uses a geometric approach to detect structural shifts in the market, providing visual cues for potential entry points and trend directions.

Core Logic Breakdown

1. Identifying Key Structural Points (Fractals)

The script begins by scanning historical price data to find "fractals"—specific points where the price reaches a local high or low relative to the surrounding bars. It looks for these extremes over a specific window of time (the distance of which is automatically adjusted based on the timeframe you are viewing).

By identifying two significant extremes, the script establishes the foundation for its geometric channel:

  • Point A: A primary anchor point.
  • Point B: A secondary anchor point.

2. Channel Geometry and Slope

Once these two points are established, the script calculates the "Step" (the rate of change/slope) between them. This slope determines the angle of the channel.

  • If the price is moving consistently in one direction, a clear upward or downward slope is formed.
  • The logic then projects this slope forward into the future to create a visible corridor on your chart.

3. Dynamic Trend Analysis (The "Flat" Criteria)

A key feature of this script is its ability to distinguish between a trending market and a "flat" (sideways) market. It compares the current channel width against the market's volatility (using an Average True Range calculation).

  • Trending Market: If the channel is wide enough relative to recent volatility, it considers the market to be in a clear trend.
  • Flat Market: If the price movement is tight and lacks significant expansion, the script identifies the market as "flat" or consolidating.

4. Visual Projection and Signals

The script draws three distinct lines on your chart:

  • Outer Boundary Lines: These represent the upper and lower limits of the current price channel.
  • Mid-Line: A dotted line that represents the equilibrium point (the median) of the channel.

5. Automated Labeling

Depending on the relationship between the current price, the channel's slope, and the "Flat" criteria mentioned above, the script automatically attaches text labels to the lines:

  • Buy/Sell: These appear when the market is in a trending phase and price interacts with the boundaries in a way that suggests a trend continuation or reversal.
  • Take: These labels appear when the market is identified as "flat" or reaching a specific equilibrium, suggesting a zone where price may stall or consolidate rather than break out aggressively.

Summary of User Experience

When you apply this script, it essentially "maps" the current market geography. It looks back to see how the price has behaved, draws a corridor based on that behavior, and then projects that corridor forward. It tells you whether the market is currently "running" (Trending) or "resting" (Flat), while labeling the visual boundaries with actionable trend information.

Price Data Components
Series array that contains the lowest prices of each barSeries array that contains the highest prices of each barSeries array that contains open time of each bar
Indicators Used
Indicator of the average true range
Miscellaneous
Implements a curve of type %1
14 Views
0 Downloads
0 Favorites
#MTF_shi_channel_1_001
//+------------------------------------------------------------------+ 
//| SHI_Channel.mq4                                                  | 
//|Alex_Bugalter                                                     |
//+------------------------------------------------------------------+ 
#property copyright "Alex_Bugalter" 
#property link "Alex_Bugalter@treide.ru"  

#property indicator_chart_window 
#property indicator_buffers 1 
#property indicator_color1 Red 
double ExtMapBuffer1[]; 
//---- input parameters 
extern int TimeFrame=60;
extern int AllBars=240; 
extern int BarsForFract=50; 
extern double flatCriteria=0.25;
extern color collor=Blue;

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"+TimeFrame); 
ObjectDelete("TL2"+TimeFrame); 
ObjectDelete("MIDL"+TimeFrame); 
} 

//+------------------------------------------------------------------+ 
//| Custom indicator iteration function | 
//+------------------------------------------------------------------+ 
int start() 
   { 
 
   int    i,limit,y=0;
   int counted_bars=IndicatorCounted();  
 
      limit=Bars-counted_bars;
 
   int X = (Ask-P1);
   int X2 = (Bid-P2);
   //---- 
 
    if ((AllBars==0) || (Bars<AllBars)) AB=Bars; else AB=AllBars; //AB-êîëè÷åñòâî îáñ÷èòûâàåìûõ áàðîâ 
//    string TimeFrame;
 
   if (BarsForFract>0) 
      BFF=BarsForFract; 
   else 
      { 
      switch (TimeFrame) 
      { 
      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=y-1; B2=y-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(),TimeFrame,MODE_LOW,BFF*2+1,CurrentBar-BFF))) 
         { 
         if(UpDown==0) 
            {
            UpDown=-1; B1=CurrentBar; P1=iLow(Symbol(),TimeFrame,B1); 
            } 
         else 
            { 
            B2=CurrentBar; P2=iLow(Symbol(),TimeFrame,B2);
            } 
         } 
      if((UpDown>-1) && (CurrentBar==Highest(Symbol(),TimeFrame,MODE_HIGH,BFF*2+1,CurrentBar-BFF)))
         { 
         if(UpDown==0) 
            { 
            UpDown=1; B1=CurrentBar; P1=iHigh(Symbol(),TimeFrame,B1); 
            } 
         else 
            { 
            B2=CurrentBar; P2=iHigh(Symbol(),TimeFrame,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=iLow(Symbol(),TimeFrame,2)-2*Step; 
      for(i=3;i<=B2;i++) 
         { 
         if(iLow(Symbol(),TimeFrame,i)<PP+Step*i) 
            { 
            PP=iLow(Symbol(),TimeFrame,i)-i*Step; 
            } 
         } 
      if(iLow(Symbol(),TimeFrame,0)<PP) 
         {
         ishift=0; 
         iprice=PP;
         } 
      if(iLow(Symbol(),TimeFrame,1)<PP+Step) 
         {
         ishift=1; 
         iprice=PP+Step;
         } 
      if(iHigh(Symbol(),TimeFrame,0)>P1) 
         {
         ishift=0; 
         iprice=P1;
         } 
      if(iHigh(Symbol(),TimeFrame,1)>P1+Step) 
         {
         ishift=1; 
         iprice=P1+Step;
         } 
      } 
   else 
      { 
      PP=iHigh(Symbol(),TimeFrame,2)-2*Step; 
      for(i=3;i<=B2;i++) 
         { 
         if(iHigh(Symbol(),TimeFrame,i)>PP+Step*i) 
            { 
            PP=iHigh(Symbol(),TimeFrame,i)-i*Step;
            } 
         } 
      if(iLow(Symbol(),TimeFrame,0)<P1) 
         {
         ishift=0; 
         iprice=P1;
         } 
      if(iLow(Symbol(),TimeFrame,1)<P1+Step) 
         {
         ishift=1; 
         iprice=P1+Step;
         } 
      if(iHigh(Symbol(),TimeFrame,0)>PP) 
         {
         ishift=0; 
         iprice=PP;
         } 
      if(iHigh(Symbol(),TimeFrame,1)>PP+Step) 
         {
         ishift=1; 
         iprice=PP+Step;
         } 
      } 
      
   //Òåïåðü ïåðåñòàâèì êîíå÷íóþ öåíó è áàð íà ÀÂ, ÷òîáû ëèíèè êàíàëà ðèñîâàëèñü ïîäëèííåå 
   P2=P1+AB*Step; 
    T1=Time[iBarShift(Symbol(),0,iTime(Symbol(),TimeFrame,B1))]; 
    T2=Time[iBarShift(Symbol(),0,iTime(Symbol(),TimeFrame,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(Symbol(),TimeFrame,40,0)*flatCriteria) flat=0; else flat=1;
   
   if (ObjectFind("TL1"+TimeFrame)==-1)   
      {
      ObjectCreate("TL1"+TimeFrame,OBJ_TREND,0,T2,PP+Step*AB,T1,PP); 
      ObjectSet("TL1"+TimeFrame,OBJPROP_COLOR,collor); 
		ObjectSet("TL1"+TimeFrame,OBJPROP_WIDTH,1); 
      }
   else
      {
      ObjectSet("TL1"+TimeFrame, OBJPROP_TIME1,T2);       
      ObjectSet("TL1"+TimeFrame, OBJPROP_PRICE1,PP+Step*AB);       
      ObjectSet("TL1"+TimeFrame, OBJPROP_TIME2,T1);       
      ObjectSet("TL1"+TimeFrame, OBJPROP_PRICE2,PP); 
      ObjectSet("TL1"+TimeFrame,OBJPROP_COLOR,collor); 
		ObjectSet("TL1"+TimeFrame,OBJPROP_WIDTH,1);       
      }   
/*
   ObjectSet("TL1",OBJPROP_COLOR,ForestGreen); 
   ObjectSet("TL1",OBJPROP_WIDTH,1); 
   ObjectSet("TL1",OBJPROP_STYLE,STYLE_SOLID);
*/
   if (ObjectFind("TL2"+TimeFrame)==-1) 
      {
      ObjectCreate("TL2"+TimeFrame,OBJ_TREND,0,T2,P2,T1,P1); 
      ObjectSet("TL2"+TimeFrame,OBJPROP_COLOR,collor); 
		ObjectSet("TL2"+TimeFrame,OBJPROP_WIDTH,1); 
      }
   else
      {
      ObjectSet("TL2"+TimeFrame, OBJPROP_TIME1,T2);       
      ObjectSet("TL2"+TimeFrame, OBJPROP_PRICE1,P2);       
      ObjectSet("TL2"+TimeFrame, OBJPROP_TIME2,T1);       
      ObjectSet("TL2"+TimeFrame, OBJPROP_PRICE2,P1);   
     	ObjectSet("TL2"+TimeFrame,OBJPROP_COLOR,collor); 
		ObjectSet("TL2"+TimeFrame,OBJPROP_WIDTH,1);     
      }   
/*
   ObjectSet("TL2",OBJPROP_COLOR,ForestGreen); 
   ObjectSet("TL2",OBJPROP_WIDTH,1); 
   ObjectSet("TL2",OBJPROP_STYLE,STYLE_SOLID); 
*/
   if (ObjectFind("MIDL"+TimeFrame)==-1)  
      {
      ObjectCreate("MIDL"+TimeFrame,OBJ_TREND,0,T2,(P2+PP+Step*AB)/2,T1,(P1+PP)/2); 
     	ObjectSet("MIDL"+TimeFrame,OBJPROP_COLOR,collor); 
		ObjectSet("MIDL"+TimeFrame,OBJPROP_WIDTH,1); 
		ObjectSet("MIDL"+TimeFrame,OBJPROP_STYLE,STYLE_DOT); 
      }
   else
      {
      ObjectSet("MIDL"+TimeFrame, OBJPROP_TIME1,T2);       
      ObjectSet("MIDL"+TimeFrame, OBJPROP_PRICE1,(P2+PP+Step*AB)/2);       
      ObjectSet("MIDL"+TimeFrame, OBJPROP_TIME2,T1);       
      ObjectSet("MIDL"+TimeFrame, OBJPROP_PRICE2,(P1+PP)/2);    
      ObjectSet("MIDL"+TimeFrame,OBJPROP_WIDTH,1); 
		ObjectSet("MIDL"+TimeFrame,OBJPROP_STYLE,STYLE_DOT); 
		ObjectSet("MIDL"+TimeFrame,OBJPROP_COLOR,collor);   
      }   
/*
   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"+TimeFrame,"Sell"); 
         ObjectSetText("TL2"+TimeFrame,"Buy"); 
         }
      else
         {
         ObjectSetText("TL2"+TimeFrame,"Sell"); 
         ObjectSetText("TL1"+TimeFrame,"Buy"); 
         }   
      }
   else
      {
      //Print("flat=0");
      if((PP+Step*AB>P2)&&(trend==-1))
         {
         ObjectSetText("TL1"+TimeFrame,"Sell"); 
         ObjectSetText("TL2"+TimeFrame,"Take"); 
         }   
      if((PP+Step*AB>P2)&&(trend==1))
         {
         ObjectSetText("TL1"+TimeFrame,"Take"); 
         ObjectSetText("TL2"+TimeFrame,"Buy"); 
         }
      if((PP+Step*AB<P2)&&(trend==-1))
         {
         ObjectSetText("TL2"+TimeFrame,"Sell"); 
         ObjectSetText("TL1"+TimeFrame,"Take"); 
         }   
      if((PP+Step*AB<P2)&&(trend==1))
         {
         ObjectSetText("TL2"+TimeFrame,"Take"); 
         ObjectSetText("TL1"+TimeFrame,"Buy"); 
         }
      }   
 //}  //---- 
 //  Comment("Âåðõ êàíàëà = ",PP,"\n","Ñåðåäèíà = ",(P1+PP)/2,"\n","Íèç êàíàëà = ",P1,"\n","Øèðèíà = ",(PP-P1),"\n","Êàñàíèå Âåðõà = ",-(PP-Bid)," ïèïñîâ","\n","Êàñàíèå Íèçà = ",(P1-Ask)," ïèïñîâ"); 
   return(0); 
   } 
//+------------------------------------------------------------------+

Comments