TD_Points & Line
Download scriptThis script is designed as a visual analysis tool for traders who use TD (Tom DeMarco) sequential logic. Its primary purpose is to automatically identify key market structure points, visualize trend lines based on those points, and highlight potential price "breakout" targets on the trading chart.
Here is a breakdown of the logic used by the script:
Identification of Key Market Points
The script constantly scans recent historical data to find specific "swing" points in the market. It looks for local peaks (Resistance) and local troughs (Support).
- Resistance Points: The script identifies highs that are significantly higher than the surrounding price candles.
- Support Points: The script identifies lows that are significantly lower than the surrounding price candles.
It specifically looks for these "turning points" to determine the current trajectory of the market, ensuring it only selects significant structural changes rather than minor price fluctuations.
Trend Line Generation
Once the most recent major Support and Resistance points are identified, the script automatically draws two dynamic trend lines on your chart:
- The Upward Trend (Blue): Connects the two most recent significant high points.
- The Downward Trend (Orange-Red): Connects the two most recent significant low points.
These lines provide a visual representation of the current market "path," allowing you to see where price is heading relative to historical highs and lows.
Breakout Detection & Signal Logic
Beyond just drawing lines, the script calculates the mathematical intersection of these trends with the current price action. It looks for specific moments where the price crosses through these established trend lines.
When a crossover is detected, the script evaluates three optional filters (user-configurable settings) to confirm if the move is "valid" or just noise:
- Price Momentum: Checking if the previous candle closed higher/lower than the current one.
- Opening Position: Checking if the current candle started above or below the trend line.
- Body Confirmation: Evaluating the relationship between the candle's body and its wicks to ensure there is enough "strength" in the move to be considered a true breakout.
Visual Signals and Targets
If the script confirms a valid breakout based on the logic above, it provides two visual cues:
- Signal Arrows: It places a Lime (Upward) or Red (Downward) arrow at the exact point where the price broke the trend line.
- Dynamic Target Line: The script performs a calculation to estimate a potential "target" price based on the geometry of the move. It draws a dotted Yellow-Green horizontal line on the chart to show you where the price might head next following the breakout.
In summary, this tool automates the tedious process of manually drawing trend lines and calculating breakout targets, providing a clean visual map of market structure and potential price destinations.
//+------------------------------------------------------------------+
//| TD_Points&Lines_mgtd1.mq4 |
//| Vladislav Goshkov (VG) |
//| 4vg@mail.ru |
//+------------------------------------------------------------------+
#property copyright "Vladislav Goshkov (VG)"
#property link "4vg@mail.ru"
#property indicator_chart_window
extern int SetPoint=0;
extern int StepBack=0;
extern int Qw1=1;
extern int Qw2=1;
extern int Qw3=1;
int i=1,NP=0,D=0,
iB_Up=0,iB_Dn=0,
S1=0,
S2=0,
UpLev=0,
DownLev=0,
iP_Up=0,
iP_Dn=0,
value=0,
CurPeriod=0,
shift=0;
datetime nTime=0;
double UpV=0,
DownV=0,
iP=0,
target = 0,
UpP[2]={0,0},
DownP[2]={0,0},
PP1=0,PP2=0,PP3=0;
int DownBT[2]={0,0}, // Bar Time
UpBT[2]={0,0},
UpB[2]={0,0}, // Bar Num
DownB[2]={0,0};
string buff_str = "";
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
//---- indicators
//----
return(0);
}
//+------------------------------------------------------------------+
//| Custor indicator deinitialization function |
//+------------------------------------------------------------------+
int deinit()
{
//---- TODO: add your code here
Comment(" ");
ObjectDelete("TD_Up");
ObjectDelete("TD_Dn");
ObjectDelete("Target");
ObjectDelete("Break_Sig_Up");
ObjectDelete("Break_Sig_Dn");
//----
return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int start()
{
//int counted_bars=IndicatorCounted();
//---- TODO: add your code here
if ( (nTime!=Time[0]) || (CurPeriod!=Period()) ) {
UpP[0] = 0;
UpP[1] = 0;
//=================================================
//******** Ïîèñê îïîðíûõ òî÷åê ïðåäëîæåíèÿ ********
//=================================================
for(i=2+StepBack,D=2,NP=0; (NP<D)&&(i<Bars); i++) {//Begin
if (High[i]!= High[i+1]) {
if( (High[i]>High[i+1] && High[i]>High[i-1] && High[i]>Close[i+2] )
&& High[i]> UpP[0] ) {
UpB[NP] = i;
UpBT[NP] = Time[i];
UpP[NP] = High[i];
NP++;
}
}
if (High[i]== High[i+1]) {
if ( (High[i]>High[i+2] && High[i]>High[i-1] && High[i]>Close[i+3] ) && High[i]> UpP[0] ) {
UpB[NP] = i;
UpBT[NP] = Time[i];
UpP[NP] = High[i];
NP++;
}
}
if(i == (Bars-2) ) {
UpB[NP] = i;
UpBT[NP] = Time[i];
UpP[NP] = High[i];
break;
}
}//for(i=2+StepBack,D=2,NP=0; NP<D; ) {//End;
//=================================================
//********** Ïîèñê îïîðíûõ òî÷åê ñïðîñà ***********
//=================================================
DownP[0] = 1000000000;
DownP[1] = 1000000000;
for(i=2+StepBack,D=2,NP=0; (NP<D)&&(i<Bars); i++) {//Begin
if (Low[i]!= Low[i+1]) {
if ( (Low[i]<Low[i+1] && Low[i]<Low[i-1] && Low[i]<Close[i+2] ) && Low[i]< DownP[0] ){
DownB[NP] = i;
DownBT[NP]= Time[i];
DownP[NP] = Low[i];
NP++;
}
//i++;
}
if (Low[i]== Low[i+1]) {
if ( (Low[i]<Low[i+2] && Low[i]<Low[i-1] && Low[i]<Close[i+3] ) && Low[i]< DownP[0] ){
DownB[NP] = i;
DownBT[NP]= Time[i];
DownP[NP] = Low[i];
NP++;
}
//i++;
}
if (i == (Bars-2) ) {
DownB[NP] = i;
DownBT[NP]= Time[i];
DownP[NP] = Low[i];
break;
}
}//End;
UpV = (UpP[1]-UpP[0])/(UpB[0]-UpB[1]);
DownV = (DownP[1]-DownP[0])/(DownB[0]-DownB[1]);
//=================================================
//**** Ðèñóåì TD-ëèíèè ****
//=================================================
buff_str = "TD_Up";
if(ObjectFind(buff_str) == -1) {
ObjectCreate(buff_str, OBJ_TREND, 0, UpBT[1], UpP[1],UpBT[0], UpP[0]);
ObjectSet(buff_str, OBJPROP_STYLE, STYLE_SOLID);
ObjectSet(buff_str, OBJPROP_COLOR, DodgerBlue);
//ObjectMove(buff_str, 0, UpBT[1], UpP[1],UpBT[0], UpP[0]);
}
else {
ObjectMove(buff_str, 1, UpBT[0], UpP[0]);
ObjectMove(buff_str, 2, UpBT[1], UpP[1]);
}
buff_str = "TD_Dn";
if(ObjectFind(buff_str) == -1) {
ObjectCreate(buff_str, OBJ_TREND, 0, DownBT[1], DownP[1],DownBT[0], DownP[0]);
ObjectSet(buff_str, OBJPROP_STYLE, STYLE_SOLID);
ObjectSet(buff_str, OBJPROP_COLOR, OrangeRed);
//ObjectMove(buff_str, 0, UpBT[1], UpP[1],UpBT[0], UpP[0]);
}
else {
ObjectMove(buff_str, 1, DownBT[0], DownP[0]);
ObjectMove(buff_str, 2, DownBT[1], DownP[1]);
}
CurPeriod = Period();
nTime = Time[0];
}//if (nTime <> Time[0]) {
//----
target = 0;
for( i=UpB[0]; i>=StepBack; i--){
if( (Close[i]>UpP[0]+UpV*(UpB[0]-i)) && (Close[i+1]<UpP[0]+UpV*(UpB[0]-(i+1))) ) {
iB_Up=i;
iP=UpP[0]+UpV*(UpB[0]-i);
iP_Up = iP;
S1=Lowest(NULL,0,MODE_LOW,UpB[1],0);
S2=Lowest(NULL,0,MODE_CLOSE,UpB[1],0);
PP1=iP+((UpP[1]+UpV*(UpB[1]-S1))-Low[S1]);
PP2=iP+((UpP[1]+UpV*(UpB[1]-S2))-Low[S2]);
PP3=iP+((UpP[1]+UpV*(UpB[1]-S1))-Close[S1]);
if((Qw1!=0 && Close[2]>Close[1])
|| (Qw2!=0 && Open[0]> iP)
|| (Qw3!=0 && (Close[0]+(Close[0]-MathMin(Low[0],Close[1])))<iP) ) {
target = (PP1+PP2+PP3)/3;
buff_str = "Break_Sig_Up";
if(ObjectFind(buff_str) == -1) {
ObjectCreate(buff_str, OBJ_ARROW,0, Time[iB_Up], iP+2*Point );
ObjectSet(buff_str, OBJPROP_ARROWCODE, 164);
ObjectSet(buff_str, OBJPROP_COLOR, Lime);
}
else {
ObjectMove(buff_str, 0, Time[iB_Up], iP+2*Point );
}
}
}
}
for( i=DownB[0]; i>=StepBack;i--) {
if( (Close[i]<DownP[0]+DownV*(DownB[0]-i)) && (Close[i+1]>DownP[0]+DownV*(DownB[0]-(i+1))) ) {
iB_Dn=i;
iP=DownP[0]+DownV*(DownB[0]-i);
iP_Dn = iP;
S1=Highest(NULL,0,MODE_HIGH,DownB[1],0);
S2=Highest(NULL,0,MODE_CLOSE,DownB[1],0);
PP1=iP-(High[S1]-(DownP[1]+DownV*(DownB[1]-S1)));
PP2=iP-(High[S2]-(DownP[1]+DownV*(DownB[1]-S2)));
PP3=iP-(Close[S1]-(DownP[1]+DownV*(DownB[1]-S1)));
if((Qw1!=0 && Close[1]<Close[0] )
|| (Qw2!=0 && Open[0] < iP )
|| (Qw3!=0 && (Close[0]+(Close[0]-MathMax(High[0],Close[1])))>iP) ) {
target = (PP1+PP2+PP3)/3;
buff_str = "Break_Sig_Dn";
if(ObjectFind(buff_str) == -1) {
ObjectCreate(buff_str, OBJ_ARROW,0, Time[iB_Dn], iP+2*Point );
ObjectSet(buff_str, OBJPROP_ARROWCODE, 164);
ObjectSet(buff_str, OBJPROP_COLOR, Red);
}
else {
ObjectMove(buff_str, 0, Time[iB_Dn], iP+2*Point );
}
}
}
}//for( i=DownB[1]; i>=StepBack;i--) {
buff_str = "Target";
if(ObjectFind(buff_str) == -1) {
ObjectCreate(buff_str, OBJ_HLINE,0, Time[0], target );
ObjectSet(buff_str, OBJPROP_STYLE, STYLE_DOT);
ObjectSet(buff_str, OBJPROP_COLOR, YellowGreen);
//ObjectMove(buff_str, 0, UpBT[1], UpP[1],UpBT[0], UpP[0]);
}
else {
ObjectMove(buff_str, 0, Time[0], target );
}
//----
return(0);
}
//+------------------------------------------------------------------+
Comments