SHI_Mod_vLine_v3
Download scriptThis script is designed to automatically identify and draw price channels on a trading chart based on historical "fractals" (significant high or low points). Rather than using static horizontal lines, it creates dynamic trend channels that adjust to the direction of the market.
Core Logic and Functionality
1. Dynamic Anchor Point Selection The script begins by looking for specific price peaks and valleys in the market history. It uses a "Fractal" logic, which means it identifies points that are higher or lower than a set number of surrounding candles. Depending on your timeframe (e.g., 5-minute vs. Hourly), the script automatically adjusts how many bars it inspects to ensure it finds relevant structural turning points.
2. Channel Construction Once it identifies two significant opposite points (a high and a low), it calculates the "Step" or the slope of the price movement between them. Using this slope, it constructs a channel consisting of:
- The Upper Bound: A line tracking the ceiling of the price action.
- The Lower Bound: A line tracking the floor of the price action.
- The Median Line: A dotted center line that represents the average price path between the two bounds.
3. Intelligent Projection and Extension The script doesn't just draw a line between two past points; it projects the channel forward into the future. It calculates where the price should be based on the established trend slope, allowing traders to see potential support and resistance zones for upcoming price action.
4. Interactive Positioning (The "VLine" Feature) A unique feature of this specific version is the ability to shift the entire analysis by dragging a vertical line on your chart. This allows you to manually select the exact starting point in history from which you want the script to begin its calculations. When you move this line, the script automatically recalculates all peaks, valleys, and channel slopes starting from that new time coordinate.
5. Automatic Timeframe Adjustment The script is "timeframe-aware." It includes built-in logic to normalize price data for different chart types (like M5, H1, or D1). For instance, it ensures that on higher timeframes like Weekly or Monthly, the lines are calculated correctly without distorting the scale.
Visual Output
The script provides a clear visual map on your chart:
- Solid Tomato Lines: Represent the main active channel boundaries and the median path.
- Dotted Lime Lines: Show the projected continuation of the trend.
- Aqua Vertical Line: Acts as your "anchor," determining the starting point for all calculations.
In summary, this tool automates the tedious process of drawing trend channels by identifying mathematical peaks and valleys, providing a visual representation of the current market's trajectory while giving the user the flexibility to choose the starting point of that analysis.
/*-----------------------------+
| |
| Shared by www.Aptrafx.com |
| |
+------------------------------*/
//+------------------------------------------------------------------+
//| SHI_Mod_vLine.mq4 |
//| Copyright © 2004, Shurka & Kevin |
//| Corrected&Upgraded by Modest |
//| Additional idea Rosh |
//+------------------------------------------------------------------+
// Modest- èñïðàâëåí àëãîðèòì íàõîæäåíèÿ îïîðíîé òî÷êè ìåæäó
// îáíàðóæåííûìè ôðàêòàëàìè äëÿ ïîñòðîåíèÿ ëèíèè êàíàëà
// Äîáàâëåíà âîçìîæíîñòü òåñòèðîâàíèÿ íà èñòîðèè ïðè ïîìîùè ïðîãðàììû MetaClick.
// Ïðè òåñòèðîâàíèè ëèíèè êàíàëà ïðîäîëæàþòñÿ â áóäóøåå
// Âåðñèÿ SHI_Mod_vLine: ïåðåìåùåíèå âñåãî ïîñòðîåíèÿ ïóòåì ïåðåòàñêèâàíèÿ VLINE -èäåÿ Rosh'a
#property copyright "Copyright © 2004, Shurka & Kevin "
#property link ""
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_color1 Red
double ExtMapBuffer1[];
double UpLabel[];
extern int BarsForFract=0;
extern bool DOT_Line_Ray=True;
int CurrentBar=0;
double Step=0;
int B1=-1,B2=-1,iB1=0,iB2=0,flag=0;
int UpDown=0;
double P1=0,P2=0,PP=0,P1f=0,PPf=0;
int i=0,AB=300,BFF=0;
int ishift=0;
double iprice=0;
datetime T1,T2,Tf,myTime;
string fileNAME;
int myYear,myMonth,myDay,myHour,myMinute;
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
//---- indicators
SetIndexStyle(0,DRAW_ARROW);
SetIndexArrow(0,164);
SetIndexBuffer(0,ExtMapBuffer1);
SetIndexEmptyValue(0,0.0);
SetIndexStyle(1,DRAW_ARROW,EMPTY,1,Blue);
SetIndexBuffer(1,UpLabel);
SetIndexArrow(1, 251);
SetIndexEmptyValue(1,0);
return(0);
}
//+------------------------------------------------------------------+
//| Custor indicator deinitialization function |
//+------------------------------------------------------------------+
int deinit()
{
//----
FileDelete(fileNAME);
//----
return(0);
}
void DelObj()
{
ObjectDelete("TL1"); ObjectDelete("TL2"); ObjectDelete("MIDL");
ObjectDelete("Lab1");ObjectDelete("Lab2");ObjectDelete("Lab3");
ObjectDelete("TL1f");ObjectDelete("TL2f");
//ObjectDelete("MyBarLine");
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int start()
{
double iPP,Lab1Val,Lab2Val,Lab3Val;
int MyBar,lastBarTime,h1,ii;
string v1,fileFrame;
ObjectCreate("MyBarLine",OBJ_VLINE,0,Time[1],High[1]);
ObjectSet("MyBarLine",OBJPROP_COLOR,Aqua);
ObjectSet("MyBarLine",OBJPROP_WIDTH,1);
ObjectSet("MyBarLine",OBJPROP_STYLE,STYLE_DOT);
//****************************************************************************************
// ×òåíèå äàííûõ (ñòðîêà) èç âíåøíåãî ôàéëà, ñôîðìèðîâàííîãî ïðîãðàììîé MetaClick,
// ïóò¸ì òûêà â áàð (Z+LeftMouse) óêàçûâàþùåé âðåìÿ, äî êîòîðîãî ñòðîèòñÿ èíäèêàòîð.
// Èùåì íóæíûé íîìåð áàðà
//****************************************************************************************
/* // Âýòîé âåðñèè MetaClick íå èñïîëüçóåòñÿ
switch (Period()) // Ôîðìèðîâàíèå ÷àñòè èìåíè âíåøíåãî ôàéëà
{
case PERIOD_M1: fileFrame=",M1";break;
case PERIOD_M5: fileFrame=",M5";break;
case PERIOD_M15: fileFrame=",M15";break;
case PERIOD_M30: fileFrame=",M30";break;
case PERIOD_H1: fileFrame=",H1";break;
case PERIOD_H4: fileFrame=",H4";break;
case PERIOD_D1: fileFrame=",Daily";break;
case PERIOD_W1: fileFrame=",Weekly";break;
case PERIOD_MN1: fileFrame=",Monthly";break;
}
fileNAME=Symbol()+fileFrame+".csv";
h1=FileOpen(Symbol()+fileFrame+".csv",FILE_CSV,";");
v1 = FileReadString(h1);
FileClose(h1);
Comment(v1);
lastBarTime=StrToTime(v1);
i=0;
while (i<=Bars-1 )
{if (lastBarTime==Time[i])
{ MyBar=i;break;}
i++;
}
*/
//**^^^*****^^ Çàêîí÷èëè èñêàòü ïîñëåäíèé áàð äëÿ ïîñòðîåíèÿ èíäèêàòîðà ****************
myTime=ObjectGet("MyBarLine",OBJPROP_TIME1);
if(myTime>Time[0] || myTime< Time[Bars-1])
{ObjectDelete("MyBarLine"); Alert("SHI_Mod_vLine: TimeFrames are not correct"); return(0); }
myYear=TimeYear(myTime); myMonth=TimeMonth(myTime);myDay=TimeDay(myTime);
myHour=TimeHour(myTime); myMinute=TimeMinute(myTime);
// Äëÿ âîçìîæíîòè ïåðåêëþ÷åíèÿ òàéìôðåéìîâ ÎÄÍÎÃÎ È ÒÎÃÎ ÆÅ ÃÐÀÔÈÊÀ íàäî âûðîâíÿòü
// âðåìÿ ðàñïîëîæåíèÿ âåðòèêàëüíîé ëèíèè íà ãðàíèöó ñòàðøåãî òàéìôðåéìà.
if (Period()==PERIOD_MN1 || Period()==PERIOD_W1)
{Alert("SHI_Mod_vLine can''t work with Weekly and Monthly charts");
ObjectDelete("MyBarLine"); return(0);}
switch (Period()) //
{
case PERIOD_M1: break;
case PERIOD_M5: myMinute=MathFloor(myMinute/5)*5; break;
case PERIOD_M15: myMinute=MathFloor(myMinute/15)*15; break;
case PERIOD_M30: myMinute=MathFloor(myMinute/30)*30; break;
case PERIOD_H1: myMinute=0; break;
case PERIOD_H4: myHour=MathFloor(myHour/4)*4; myMinute=0; break;
case PERIOD_D1: myHour=0; myMinute=0; break;
case PERIOD_W1: /*i=0; while(i<=Bars-1)
{
if (TimeYear(Time[i])==myYear && TimeMonth(Time[i])==myMonth &&
myDay-TimeDay(Time[i])<=6 && myDay-TimeDay(Time[i])>=0)
myDay=TimeDay(Time[i]); break;
i++; //Íåïðàâèëüíî!!
}*/
break;
case PERIOD_MN1: break;
}
ObjectDelete("MyBarLine");
myTime=StrToTime(myYear + "." + myMonth + "." + myDay + " " + myHour + ":" + myMinute);
ObjectCreate("MyBarLine",OBJ_VLINE,0,myTime,High[0]);
ObjectSet("MyBarLine",OBJPROP_COLOR,Aqua);
ObjectSet("MyBarLine",OBJPROP_WIDTH,1);
ObjectSet("MyBarLine",OBJPROP_STYLE,STYLE_DOT);
//Îòëàäêà
/*
Alert(myYear + "." + myMonth + "." + myDay + " " + myHour + ":" + myMinute);
myYear=TimeYear(myTime); myMonth=TimeMonth(myTime);myDay=TimeDay(myTime);
myHour=TimeHour(myTime); myMinute=TimeMinute(myTime);
Alert(myYear + "." + myMonth + "." + myDay + " " + myHour + ":" + myMinute);
*/
//return(0);
i=0;
while(Time[i]!=myTime) {i++;}
MyBar=i;
ArrayInitialize(UpLabel,0.0);
if (Bars<MyBar+303) {Alert("Too little history");return(-1);}
int counted_bars=IndicatorCounted();
//----
//if(Bars<AllBars) AllBars=Bars; //return(-1);
//if(AllBars<AB) {Comment("Ìàëî áàðîâ"); return(-1);}
//Alert("MyBar=",MyBar);
//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+MyBar; //ñ÷èòàåì ñ òðåòüåãî áàðà, ÷òîáû ôðàêòàë "çàêðåïèëñÿ
B1=-1; B2=-1; UpDown=0; flag=0;
while(((B1==-1) || (B2==-1)) && (CurrentBar<(AB+MyBar)))
{
//UpDown=1 çíà÷èò ïåðâûé ôðàêòàë íàéäåí ñâåðõó, UpDown=-1 çíà÷èò ïåðâûé ôðàêòàë
//íàéäåí ñíèçó, UpDown=0 çíà÷èò ôðàêòàë åù¸ íå íàéäåí.
//Â1 è Â2 - íîìåðà áàðîâ ñ ôðàêòàëàìè, ÷åðåç íèõ ñòðîèì îïîðíóþ ëèíèþ.
//Ð1 è Ð2 - ñîîòâåòñòâåííî öåíû ÷åðåç êîòîðûå áóäåì ëèíèþ ïðîâîäèòü
// if (CurrentBar==4 ) Alert("CurrentBar=",CurrentBar," ","BFF=",BFF);
if((UpDown<1) && (CurrentBar==Lowest(Symbol(),Period(),MODE_LOW,BFF*2+1,CurrentBar-BFF)))
// Âûðàæåíèå CurrentBar-BFF ìîæåò áûòü â äàí ñëó÷àå îòðèöàòåëüíûì. Íî âðîäå ðàáîòàåò
{
if(UpDown==0) { UpDown=-1; B1=CurrentBar; iB1=CurrentBar; P1=Low[B1];}
else { B2=CurrentBar; iB2=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; iB1=CurrentBar; P1=High[B1];}
else { B2=CurrentBar; iB2=CurrentBar; P2=High[B2];}
}
CurrentBar++;
}
if((B1==-1) || (B2==-1)) {DelObj(); return(-1);} // Çíà÷èò íå íàøëè ôðàêòàëîâ ñðåäè 300 áàðîâ 8-)
Step=(P2-P1)/(B2-B1);//Âû÷èñëèëè øàã, åñëè îí ïîëîæèòåëüíûé, òî êàíàë íèñõîäÿùèé
P1=P1-(B1-MyBar)*Step; B1=0+MyBar;//ïåðåñòàâëÿåì öåíó è ïåðâûé áàð ê íóëþ (çíà÷åíèå îïîðíîé ëèíèè íà 0 áàðå)
//À òåïåðü îïîðíóþ òî÷êó ïðîòèâîïîëîæíîé ëèíèè êàíàëà.
ishift=0+MyBar; iprice=0;
//Alert(UpDown);
if(UpDown==1)
{
// Èñïðàâëåíî!! Îïîðíóþ òî÷êó áóäåì èñêàòü ÌÅÆÄÓ îáíàðóæåííûìè ôðàêòàëàìè,
// à íå ñ 0-ãî (MyBar) áàðà. iB1-ýòî íå èçìåíåííûé B1
//PP=Low[2+MyBar]-(2)*Step;
PP=Low[2+iB1]-(2)*Step;
iPP=Low[2+iB1]-(2)*Step;
ii=2+iB1;
//for(i=3+MyBar;i<=B2;i++)
for(i=3+iB1;i<=B2;i++)
{
//if(Low[i]<PP+Step*(i-MyBar)) { PP=Low[i]-(i-MyBar)*Step; ii=i;}
if(Low[i]<iPP+Step*(i-iB1))
//PP-çíà÷åíèå ëèíèè íà ïîñëåäíåì áàðå
// iPP-çíà÷åíèå ëèíèè íà áàðå iB1 -ïðàâûé ôðàêòàë
{ PP=Low[i]-(i-MyBar)*Step; ii=i;
iPP=Low[i]-(i-iB1)*Step;
}
}
//Alert(iB1," ",iB2," ",ii," ","Step=",Step," ","PP=",PP);
//Lab1Val=(High[iB1]+5*Point); Lab2Val=(High[iB2]+5*Point); Lab3Val=(Low[ii]-5*Point);
UpLabel[iB1]=High[iB1]+5*Point;
UpLabel[iB2]=High[iB2]+5*Point;
UpLabel[ii]=Low[ii]-5*Point;
//Alert(iB1," ",ii," ",iB2," ","Step=",Step," ","PP=",PP," ","Lab1Val=",Lab1Val);
if(Low[0+MyBar]<PP) {ishift=0+MyBar; iprice=PP;}
if(Low[1+MyBar]<PP+Step) {ishift=1+MyBar; iprice=PP+Step;}
if(High[0+MyBar]>P1) {ishift=0+MyBar; iprice=P1;}
if(High[1+MyBar]>P1+Step) {ishift=1+MyBar; iprice=P1+Step;}
}
else //òðåíä âíèç
{
PP=High[2+MyBar]-(2)*Step;
iPP=High[2+iB1]-(2)*Step;
ii=2+iB1;
//for(i=3+MyBar;i<=B2;i++)
for(i=3+iB1;i<=B2;i++)
{
if(High[i]>iPP+Step*(i-iB1)) { PP=High[i]-(i-MyBar)*Step;ii=i;
iPP=High[i]-(i-iB1)*Step;
} //èùåì çíà÷åíèå âåðõíåé ëèíèè íà 0 áàðå
}
//Lab1Val=(Low[iB1]-5*Point);Lab2Val=(Low[iB2]-5*Point);Lab3Val=(High[ii]+5*Point);
UpLabel[iB1]=Low[iB1]-5*Point;
UpLabel[iB2]=Low[iB2]-5*Point;
UpLabel[ii]=High[ii]+5*Point;
//Alert(iB1," ",iB2," ","ii=",ii," ","Step=",Step," ","PP=",PP," ",
// "Lab1Val=",Lab1Val,"Lab3Val=",Lab3Val);
// îïðåäåëÿåì, áûëî ëè ïåðåñå÷åíèå ëèíèé êàíàëà íà 0 èëè 1 áàðàõ(÷òîáû ñòàâèòü ïñèñó)
if(Low[0+MyBar]<P1) {ishift=0+MyBar; iprice=P1;}
if(Low[1+MyBar]<P1+Step) {ishift=1+MyBar; iprice=P1+Step;}
if(High[0+MyBar]>PP) {ishift=0+MyBar; iprice=PP;}
if(High[1+MyBar]>PP+Step) {ishift=1+MyBar; iprice=PP+Step;}
}
//Òåïåðü ïåðåñòàâèì êîíå÷íóþ öåíó è áàð íà ÀÂ, ÷òîáû ëèíèè êàíàëà ðèñîâàëèñü ïîäëèííåå
P2=P1+AB*Step;
T1=Time[B1]; T2=Time[AB+MyBar];
//Åñëè íå áûëî ïåðåñå÷åíèÿ êàíàëà, òî 0, èíà÷å ñòàâèì ïñèñó.
//if(iprice!=0) ExtMapBuffer1[ishift]=iprice;
DelObj();
//Alert("B1=",B1," ","B2=",AB+MyBar," ","AB=",AB," ","MyBar=",MyBar);
// Alert("T1=",T1," ","T2=",T2);
//***************************************** Ðèñóåì ëèíèè êàíàëà ************************
ObjectCreate("TL1",OBJ_TREND,0,T2,PP+Step*(AB),T1,PP);
ObjectSet("TL1",OBJPROP_COLOR,Tomato);
ObjectSet("TL1",OBJPROP_WIDTH,2);
ObjectSet("TL1",OBJPROP_STYLE,STYLE_SOLID);
ObjectSet("TL1",OBJPROP_RAY,False);
ObjectCreate("TL2",OBJ_TREND,0,T2,P2,T1,P1);
ObjectSet("TL2",OBJPROP_COLOR,Tomato);
ObjectSet("TL2",OBJPROP_WIDTH,2);
ObjectSet("TL2",OBJPROP_STYLE,STYLE_SOLID);
ObjectSet("TL2",OBJPROP_RAY,False);
ObjectCreate("MIDL",OBJ_TREND,0,T2,(P2+PP+Step*AB)/2,T1,(P1+PP)/2);
ObjectSet("MIDL",OBJPROP_COLOR,Tomato);
ObjectSet("MIDL",OBJPROP_WIDTH,1);
ObjectSet("MIDL",OBJPROP_STYLE,STYLE_DOT);
ObjectSet("MIDL",OBJPROP_RAY,DOT_Line_Ray);
//*********************************** Ðèñóåì ïðîäîëæåíèå êàíàëà ************************
if (MyBar>30) {Tf=Time[MyBar-30];
PPf=PP-Step*30; P1f=P1-Step*30;
}
else {Tf=Time[0];PPf=PP-Step*MyBar; P1f=P1-Step*MyBar;
}
ObjectCreate("TL1f",OBJ_TREND,0,T1,PP,Tf,PPf);
ObjectSet("TL1f",OBJPROP_COLOR,Lime);
ObjectSet("TL1f",OBJPROP_WIDTH,1);
ObjectSet("TL1f",OBJPROP_STYLE,STYLE_DOT);
ObjectSet("TL1f",OBJPROP_RAY,DOT_Line_Ray);
ObjectCreate("TL2f",OBJ_TREND,0,T1,P1,Tf,P1f);
ObjectSet("TL2f",OBJPROP_COLOR,Lime);
ObjectSet("TL2f",OBJPROP_WIDTH,1);
ObjectSet("TL2f",OBJPROP_STYLE,STYLE_DOT);
ObjectSet("TL2f",OBJPROP_RAY,DOT_Line_Ray);
//************************* Îòìå÷àåì êëèêíóòûé áàð ************************************
/*if (MyBar>0)
{
ObjectCreate("MyBarLine",OBJ_VLINE,0,Time[MyBar],High[MyBar]);
ObjectSet("MyBarLine",OBJPROP_COLOR,MediumOrchid);
ObjectSet("MyBarLine",OBJPROP_WIDTH,1);
ObjectSet("MyBarLine",OBJPROP_STYLE,STYLE_DOT);
}
*/
//----
return(0);
}
//+------------------------------------------------------------------+
Comments