_2523DeMark
Download scriptThis script is a specialized technical analysis tool designed for the MetaTrader platform. It utilizes DeMark Theory, a trading methodology that focuses on identifying specific price "turning points" to project potential trendlines, support/resistance levels, and target prices.
Instead of just looking at standard moving averages, this tool searches for significant highs and lows based on DeMark's logic—specifically looking for bars where the price reaches a peak or trough relative to its neighbors. Once these key points are identified, the script performs several automated actions:
Core Functionalities
- Trendline Construction: The script automatically identifies and draws trendlines based on the high and low points it finds. It can be configured to show only upward trends, downward trends, or both simultaneously.
- Breakout Detection & Alerts: A significant feature of this tool is its ability to monitor for "breakouts." If the current price closes beyond a projected trendline, the script can trigger an instant visual alert on your chart, an audible notification, and even send an email notification.
- Dynamic Level Projection: It calculates specific price levels (horizontal lines) that represent potential breakout zones. This helps traders identify "danger zones" where the market might shift direction or experience high volatility.
- Channel & Target Mapping: The logic includes the ability to project parallel channels and specific profit targets. These targets are mathematically derived from the trend's geometry, providing a roadmap of where price might travel after a successful breakout.
User Interface and Visual Aids
- On-Chart Visuals: The tool places arrows on the chart to mark exactly where a trendline was broken. It also features an "auto-cancel" logic: if a price breaks a line but then reverses back into the previous range without a significant move, the script can visually "cancel" the signal to reduce noise.
- Real-Time Commentary: The script provides a text summary in the corner of the chart. This includes a countdown timer showing how many minutes/seconds remain until the current candle closes, as well as status updates on the current trend steps and calculated targets.
- Customizable Visuals: Users can toggle various components on or off, such as the trendlines, horizontal breakout levels, channels, and take-profit lines, allowing for a clean chart tailored to individual preferences.
Summary of Logic Flow
- Scan: The script scans recent price history to find DeMark-compliant highs and lows.
- Calculate: It calculates the slope of the trend between these points to project future paths.
- Monitor: It constantly compares the current "live" price against these projected lines.
- Notify: If a breach occurs, it validates the move using specific "qualifiers" (checks on open/close prices) and alerts the user immediately via sound, text, or email.
//------------------------------------------------------------------/
// Indicator-advisor based on Demark threory with additions
// Some part of the code was taken from Ind-TD-DeMark-3-1.mq4 [Kara ©]
//------------------------------------------------------------------/
#property copyright "GreenDog"
#property link "krot@inbox.ru" // v2.3
#property indicator_chart_window
#property indicator_buffers 2
#property indicator_color1 Red
#property indicator_color2 Blue
extern int showBars=3000; // if showBars= 0 so the indicator will be shown for all the chart
extern int LevDP=2; // Demar Pint Levels; 2 = central bar will be higher (lower) then 2 bars on the left side and 2 bars on the right one.
extern int qSteps=1; // number of steps/ no more than 3
extern int BackStep=0; // number of staps back
extern int startBar=0; // ifstartBar=0 so we have recommendation for the current bar, if 1 - for possible next bar
extern bool TrendLine=true; // false = no trend lines
extern bool HorizontLine=false; // true = break levels
extern bool ChannelLine=false; // true = channels which is parallel with trend lines
extern bool TakeLines=false; // true = take profit lines
extern bool Comments=false; // true = comments
extern int Trend=0; // 1 = for UpTrendLines only, -1 = for DownTrendLines only, 0 = for all TrendLines
extern bool ShowArrows=false;
extern bool CustomFeatures=true;
extern color UpTrendColor=Green;
extern color DownTrendColor=Red;
extern int TrendlineWidth=3;
extern bool ShowAlerts=true;
extern bool EmailAlert=true;
int trendwidth;
color trendcol;
//int ColNum[];
double Buf1[];
double Buf2[];
string Col[]={"Red","DarkBlue","Coral","DodgerBlue","SaddleBrown","MediumSeaGreen"};
//int ColNum[1]=coll1; //={coll1,coll2,coll3,coll4,coll5,coll6};
int ColNum[]={Red,DeepSkyBlue,Coral,Aqua,SaddleBrown,MediumSeaGreen}; //DeepSkyBlue
int qPoint=0; // ïåðåìåííàÿ äëÿ íîðìàëèçàöèè öåíû
int qBars; double qTime=0; // ïåðåìåííûå äëÿ ëèêâèäàöèè ãëþêîâ ïðè çàãðóçêå
int init()
{
qBars=Bars;
qSteps=MathMin(3,qSteps);
while (NormalizeDouble(Point,qPoint)==0)qPoint++;
int code=161; string Rem="DLines © GameOver";
IndicatorShortName(Rem);
if (ShowArrows){
SetIndexStyle(0,DRAW_ARROW);
SetIndexStyle(1,DRAW_ARROW);
}
SetIndexArrow(0,code);
SetIndexArrow(1,code);
SetIndexBuffer(0,Buf1);
SetIndexBuffer(1,Buf2);
SetIndexEmptyValue(0,0.0);
SetIndexEmptyValue(1,0.0);
SetIndexLabel(0,Rem);
SetIndexLabel(1,Rem);
return(0);
}
int deinit() {
ObjectsDeleteAll();
Comment("");
ArrayInitialize(Buf1,0.0);
ArrayInitialize(Buf2,0.0);
for(int i=1;i<=LevDP;i++){
ObjectDelete("HA_"+i);ObjectDelete("LA_"+i);
ObjectDelete("HL_"+i);ObjectDelete("LL_"+i);
ObjectDelete("HHL_"+i);ObjectDelete("HLL_"+i);
ObjectDelete("HCL_"+i);ObjectDelete("LCL_"+i);
for(int j=0;j<4;j++) {ObjectDelete("HTL_"+i+j);ObjectDelete("LTL_"+i+j);}
}
}
int start(){
if (qBars!=Bars){ deinit(); Sleep(1000); qBars=Bars; qTime=0; return(0);}
if (qTime==Time[0]) return(0); qTime=Time[0]; // çàïóñêàåöà òîêà íà 1ì òèêå
// çàïîëíèëè è îòîáðàçèëè òî÷êè äåìàðêà
if (showBars==0) showBars=Bars-LevDP;
for (int cnt=showBars;cnt>LevDP;cnt--) {
Buf1[cnt]=DemHigh(cnt,LevDP);
Buf2[cnt]=DemLow(cnt,LevDP);
}
string Comm;
double j;
int m,s,k;
m=Time[0]+Period()*60-CurTime();
j=m/60.0;
s=m%60;
m=(m-m%60)/60;
Comm=Comm+"Demark with alerts";
Comm=Comm+( m + " minutes " + s + " seconds left to bar end")+"\n";
if (Comments){Comment(Comm);}else{Comment("Demark with alerts" + "\n" + m + " minutes " + s + " seconds left to bar end" +"\n");}
Comm=Comm+"Trend Line["+On(TrendLine)+"]; Channel ["+On(ChannelLine)+
"]; Breakout level ["+On(HorizontLine)+"]; Targets ["+On(TakeLines)+"]\n";
for(cnt=1;cnt<=qSteps;cnt++) Comm=Comm+(TDMain(cnt));
Comm=Comm+" © GameOver ";
if (Comments==true) Comment(Comm);
return(0);
}
string TDMain(int Step){
int H1,H2,L1,L2,qExt,i,col;
double tmp,qTL,qLevel,HT[4],LT[4];
bool isHitch;
string Comm="»»» Step "+Step+" of "+qSteps+" (BackStep "+BackStep+")\n",Text,Rem,qp;
static datetime timealertupper, timealertlower;
// äëÿ DownTrendLines
if (Trend<=0){
Comm=Comm+"» "+Col[Step*2-2]+" DownTrendLine ";
col=ColNum[Step*2-2];
H1=GetTD(Step+BackStep,Buf1);
H2=GetNextHighTD(H1);
qTL=(High[H2]-High[H1])/(H2-H1);
qExt=Lowest(NULL,0,MODE_LOW,H2-H1-1,H1+1); // ëîêàëüíûé ìèíèìóì ìåæäó òî÷êàìè
qLevel=High[H2]-qTL*(H2); if (Step+BackStep==1) qLevel=qLevel-qTL*startBar;
if (H1<0 || H2<0) Comm=Comm+"not enough points on the chart for construction\n";
else {
Comm=Comm+"["+DoubleToStr(High[H2],qPoint)+"»"+DoubleToStr(High[H1],qPoint)+"]";
Comm=Comm+"; Level "+DoubleToStr(qLevel,qPoint);
if (Step+BackStep==1) {
if (startBar>0) Comm=Comm+"; Future Bar "+UpHitch(-1,qLevel);
else Comm=Comm+"; Last Bar "+UpHitch(startBar,qLevel);
}
Comm=Comm+"\n";
// Àíàëèç - áûë ëè ïðîáîé òðåíäîâîé ëèíèè
i=H1;isHitch=false;Text="";
while(i>0 && isHitch==false){
tmp=High[H2]-qTL*(H2-i);
Rem="HA_"+Step;
if (Close[i]>tmp){
qp=UpHitch(i,tmp);
if (qp!=""){
isHitch=true;
Text=Text+"Source "+DoubleToStr(tmp,qPoint)+" "+qp;
if (timealertupper!=Time[i]){
if (ShowAlerts){
Alert ("MOUTEKI: Upper trendline broken on " + Symbol() + " TF: " + Period() + " @ " + Bid);
}
ObjectCreate(Rem,OBJ_ARROW,0,0,0,0,0);
ObjectSet(Rem,OBJPROP_COLOR,col);
ObjectSet(Rem,OBJPROP_PRICE1,Low[i]-Point);
ObjectSet(Rem,OBJPROP_TIME1,Time[i]);
ObjectSet(Rem,OBJPROP_ARROWCODE,241);
//}
if (EmailAlert){
SendMail("MOUTEKI: Upper trendline broken on " + Symbol() + " TF: " + Period() + " @ " + Bid, "MOUTEKI: Upper trendline broken on " + Symbol() + " TF: " + Period() + " @ " + Bid + "\n" + "Alerts by LightKeeper. martkoz@optusnet.com.au");
}
timealertupper=Time[i];
}
/////////////////////////////////////
ObjectCreate(Rem,OBJ_ARROW,0,0,0,0,0);
ObjectSet(Rem,OBJPROP_COLOR,col);
ObjectSet(Rem,OBJPROP_PRICE1,Low[i]-Point);
ObjectSet(Rem,OBJPROP_TIME1,Time[i]);
ObjectSet(Rem,OBJPROP_ARROWCODE,241);
////////////////////////////////////
if (ShowArrows==true){
while(i>0){ // ïðîáîé îòìåíåí, åñëè ïîñëå ïðîáîÿ áûë íîâûé ëîó èëè çàêðûòèå íèæå
i--;
if (Low[i]<Low[qExt] || Close[i]<(Low[qExt]+(High[H1]-Low[qExt])*0.236)){
Text=Text+" (cancel)";
ObjectSet(Rem,OBJPROP_PRICE1,Low[i]-Point);
ObjectSet(Rem,OBJPROP_TIME1,Time[i]);
ObjectSet(Rem,OBJPROP_ARROWCODE,251);
break;
}
}
}
}
else { Text=Text+"False "+DoubleToStr(tmp,qPoint)+"; "; ObjectDelete(Rem);}
}
i--;
}
if (Text=="") Text="No breakout";
Comm=Comm+Text+"\n";
// end analysis
Rem="HL_"+Step; // ñîáñíî ëèíèÿ òðåíäà
if (CustomFeatures){trendcol=DownTrendColor;}else{trendcol=col;}
if (TrendLine){
if (CustomFeatures==false){trendwidth=3-MathMin(2,Step);}else{trendwidth=TrendlineWidth;}
ObjectCreate(Rem,OBJ_TREND,0,0,0,0,0);
ObjectSet(Rem,OBJPROP_TIME1,Time[H2]);ObjectSet(Rem,OBJPROP_TIME2,Time[H1]);
ObjectSet(Rem,OBJPROP_PRICE1,High[H2]);ObjectSet(Rem,OBJPROP_PRICE2,High[H1]);
ObjectSet(Rem,OBJPROP_COLOR,trendcol);
ObjectSet(Rem,OBJPROP_WIDTH,trendwidth);
}
else ObjectDelete(Rem);
Rem="HHL_"+Step; // óðîâåíü ïðîáîÿ ëèíèè òðåíäà
if (HorizontLine && (Step+BackStep)==1){
ObjectCreate(Rem,OBJ_HLINE,0,0,0,0,0);
ObjectSet(Rem,OBJPROP_PRICE1,qLevel);
ObjectSet(Rem,OBJPROP_COLOR,trendcol);
}
else ObjectDelete(Rem);
Rem="HCL_"+Step; // ëèíèÿ êàíàëà
if (ChannelLine){
ObjectCreate(Rem,OBJ_TREND,0,0,0,0,0);
ObjectSet(Rem,OBJPROP_TIME1,Time[qExt]);ObjectSet(Rem,OBJPROP_TIME2,Time[0]);
ObjectSet(Rem,OBJPROP_PRICE1,Low[qExt]);ObjectSet(Rem,OBJPROP_PRICE2,Low[qExt]-qTL*qExt);
ObjectSet(Rem,OBJPROP_COLOR,trendcol);
}
else ObjectDelete(Rem);
Rem="HTL_"+Step; // ëèíèè öåëåé
if (TakeLines){
HT[3]=Low[qExt]+(High[H1]-Low[qExt])*1.618-qLevel; // äîï óðîâåíü
HT[0]=High[H2]-qTL*(H2-qExt)-Low[qExt];
HT[1]=High[H2]-qTL*(H2-qExt)-Close[qExt];
qExt=Lowest(NULL,0,MODE_CLOSE,H2-H1,H1);
HT[2]=High[H2]-qTL*(H2-qExt)-Close[qExt];
Comm=Comm+"Targets: ";
for(i=0;i<4;i++){
qTL=NormalizeDouble(qLevel+HT[i],qPoint);
ObjectCreate(Rem+i,OBJ_HLINE,0,0,0,0,0);
ObjectSet(Rem+i,OBJPROP_PRICE1,qTL);
ObjectSet(Rem+i,OBJPROP_STYLE,STYLE_DOT);
ObjectSet(Rem+i,OBJPROP_COLOR,trendcol);
Comm=Comm+DoubleToStr(qTL,qPoint)+" ("+DoubleToStr(HT[i]/Point,0)+"p.) ";
}
Comm=Comm+"\n";
}
else {
for(i=0;i<4;i++) ObjectDelete(Rem+i);
}
}
}
// äëÿ UpTrendLines
if (Trend>=0){
Comm=Comm+"» "+Col[Step*2-1]+" UpTrendLine ";
col=ColNum[Step*2-1];
L1=GetTD(Step+BackStep,Buf2);
L2=GetNextLowTD(L1);
qTL=(Low[L1]-Low[L2])/(L2-L1);
qExt=Highest(NULL,0,MODE_HIGH,L2-L1-1,L1+1); // ëîêàëüíûé ìèíèìóì ìåæäó òî÷êàìè
qLevel=Low[L2]+qTL*L2; if (Step+BackStep==1) qLevel=qLevel+qTL*startBar;
if (L1<0 || L2<0) Comm=Comm+"not enough points on the chart for construction\n";
else {
Comm=Comm+"["+DoubleToStr(Low[L2],qPoint)+"»"+DoubleToStr(Low[L1],qPoint)+"]";
Comm=Comm+"; Level "+DoubleToStr(qLevel,qPoint);
if (Step+BackStep==1) {
if (startBar>0) Comm=Comm+"; Future Bar "+DownHitch(-1,qLevel);
else Comm=Comm+"; Last Bar "+DownHitch(startBar,qLevel);
}
Comm=Comm+"\n";
// Àíàëèç - áûë ëè ïðîáîé òðåíäîâîé ëèíèè
i=L1;isHitch=false;Text="";
while(i>0 && isHitch==false){
tmp=Low[L2]+qTL*(L2-i);
Rem="LA_"+Step;
if (Close[i]<tmp){
qp=DownHitch(i,tmp);
if (qp!=""){
isHitch=true;
Text=Text+"Source "+DoubleToStr(tmp,qPoint)+" "+qp;
if (timealertlower!=Time[i]){
if(ShowAlerts){
Alert ("MOUTEKI: Lower trendline broken on " + Symbol() + " TF: " + Period() + " @ " + Bid);
}
ObjectCreate(Rem,OBJ_ARROW,0,0,0,0,0);
ObjectSet(Rem,OBJPROP_COLOR,col);
ObjectSet(Rem,OBJPROP_PRICE1,Low[i]-Point);
ObjectSet(Rem,OBJPROP_TIME1,Time[i]);
ObjectSet(Rem,OBJPROP_ARROWCODE,242);
//}
if (EmailAlert){
SendMail("MOUTEKI: Lower trendline broken on " + Symbol() + " TF: " + Period() + " @ " + Bid, "MOUTEKI: Lower trendline broken on " + Symbol() + " TF: " + Period() + " @ " + Bid + "\n" + "Alerts by LightKeeper. martkoz@optusnet.com.au");
}
timealertlower=Time[i];
}
///////////////////////////////
ObjectCreate(Rem,OBJ_ARROW,0,0,0,0,0);
ObjectSet(Rem,OBJPROP_COLOR,col);
ObjectSet(Rem,OBJPROP_PRICE1,Low[i]-Point);
ObjectSet(Rem,OBJPROP_TIME1,Time[i]);
ObjectSet(Rem,OBJPROP_ARROWCODE,242);
//////////////////////////////
if (ShowArrows==true){
while(i>0){ // ïðîáîé îòìåíåí, åñëè ïîñëå ïðîáîÿ áûë íîâûé õàé èëè çàêðûòèå âûøå
i--;
if (High[i]>High[qExt] || Close[i]>High[qExt]-(High[qExt]-Low[L1])*0.236){
Text=Text+" (cancel)";
ObjectSet(Rem,OBJPROP_PRICE1,Low[i]-Point);
ObjectSet(Rem,OBJPROP_TIME1,Time[i]);
ObjectSet(Rem,OBJPROP_ARROWCODE,251);
break;
}
}
} }
else { Text=Text+"False "+DoubleToStr(tmp,qPoint)+"; "; ObjectDelete(Rem);}
}
i--;
}
if (Text=="") Text="No breakout";
Comm=Comm+Text+"\n";
// end analysis
Rem="LL_"+Step; // ñîáñíî ëèíèÿ òðåíäà
if (CustomFeatures){trendcol=UpTrendColor;}else{trendcol=col;}
if (TrendLine==1) {
if (CustomFeatures==false){trendwidth=3-MathMin(2,Step);}else{trendwidth=TrendlineWidth;}
ObjectCreate(Rem,OBJ_TREND,0,0,0,0,0);
ObjectSet(Rem,OBJPROP_TIME1,Time[L2]);ObjectSet(Rem,OBJPROP_TIME2,Time[L1]);
ObjectSet(Rem,OBJPROP_PRICE1,Low[L2]);ObjectSet(Rem,OBJPROP_PRICE2,Low[L1]);
ObjectSet(Rem,OBJPROP_COLOR,trendcol);
ObjectSet(Rem,OBJPROP_WIDTH,trendwidth);
}
else ObjectDelete(Rem);
Rem="HLL_"+Step; // óðîâåíü ïðîáîÿ ëèíèè òðåíäà
if (HorizontLine && (Step+BackStep)==1){
ObjectCreate(Rem,OBJ_HLINE,0,0,0,0,0);
ObjectSet(Rem,OBJPROP_PRICE1,qLevel);
ObjectSet(Rem,OBJPROP_COLOR,trendcol);
}
else ObjectDelete(Rem);
Rem="LCL_"+Step; // ëèíèÿ êàíàëà
if (ChannelLine){
ObjectCreate(Rem,OBJ_TREND,0,0,0,0,0);
ObjectSet(Rem,OBJPROP_TIME1,Time[qExt]);ObjectSet(Rem,OBJPROP_TIME2,Time[0]);
ObjectSet(Rem,OBJPROP_PRICE1,High[qExt]);ObjectSet(Rem,OBJPROP_PRICE2,High[qExt]+qTL*qExt);
ObjectSet(Rem,OBJPROP_COLOR,trendcol);
}
else ObjectDelete(Rem);
Rem="LTL_"+Step;
if (TakeLines){ // ëèíèè öåëåé
LT[3]=qLevel-High[qExt]+(High[qExt]-Low[L1])*1.618; // äîï óðîâåíü
LT[0]=High[qExt]-qTL*(L2-qExt)-Low[L2];
LT[1]=Close[qExt]-qTL*(L2-qExt)-Low[L2];
qExt=Highest(NULL,0,MODE_CLOSE,L2-L1,L1);
LT[2]=Close[qExt]-qTL*(L2-qExt)-Low[L2];
Comm=Comm+"Targets: ";
for(i=0;i<4;i++){
qTL=NormalizeDouble(qLevel-LT[i],qPoint);
ObjectCreate(Rem+i,OBJ_HLINE,0,0,0,0,0);
ObjectSet(Rem+i,OBJPROP_PRICE1,qTL);
ObjectSet(Rem+i,OBJPROP_STYLE,STYLE_DOT);
ObjectSet(Rem+i,OBJPROP_COLOR,trendcol);
Comm=Comm+DoubleToStr(qTL,qPoint)+" ("+DoubleToStr(LT[i]/Point,0)+"p.) ";
}
Comm=Comm+"\n";
}
else {
for(i=0;i<4;i++) ObjectDelete(Rem+i);
}
}
}
return(Comm);
}
int GetTD(int P, double Arr[]){
int i=0,j=0;
while(j<P){ i++; while(Arr[i]==0){i++;if(i>showBars-2)return(-1);} j++;}
return (i);
}
int GetNextHighTD(int P){
int i=P+1;
while(Buf1[i]<=High[P]){i++;if(i>showBars-2)return(-1);}
return (i);
}
int GetNextLowTD(int P){
int i=P+1;
while(Buf2[i]>=Low[P] || Buf2[i]==0){i++;if(i>showBars-2)return(-1);}
return (i);
}
// ðåêóðñèâíàÿ ïðîâåðêà íà óñëîâèÿ Äåìàðêà (õàé), âîçâðàùàåò çíà÷åíèå èëè 0
double DemHigh(int cnt, int sh){
if (High[cnt]>=High[cnt+sh] && High[cnt]>High[cnt-sh]) {
if (sh>1) return(DemHigh(cnt,sh-1));
else return(High[cnt]);
}
else return(0);
}
// ðåêóðñèâíàÿ ïðîâåðêà íà óñëîâèÿ Äåìàðêà (ëîó), âîçâðàùàåò çíà÷åíèå èëè 0
double DemLow(int cnt, int sh){
if (Low[cnt]<=Low[cnt+sh] && Low[cnt]<Low[cnt-sh]) {
if (sh>1) return(DemLow(cnt,sh-1));
else return(Low[cnt]);
}
else return(0);
}
string On(bool On){
if (On) return("on"); else return("off");
}
string UpHitch(int P, double qLevel){ // îïðåäåëåíèå êâàëèôèêàòîðîâ ïðîðûâà ââåðõ
string Comm="";
if (Close[P+1]<Close[P+2]) Comm=Comm+" 1";
if (P>=0 && Open[P]>qLevel) Comm=Comm+" 2";
if (2*Close[P+1]-Low[P+1]<qLevel) Comm=Comm+" 3";
if (Comm!="") Comm="[ Break Qualificator:"+Comm+" ]";
return(Comm);
}
string DownHitch(int P, double qLevel){ // îïðåäåëåíèå êâàëèôèêàòîðîâ ïðîðûâà âíèç
string Comm="";
if (Close[P+1]>Close[P+2]) Comm=Comm+" 1";
if (P>=0 && Open[P]<qLevel) Comm=Comm+" 2";
if (2*Close[P+1]-High[P+1]>qLevel) Comm=Comm+" 3";
if (Comm!="") Comm="[ Break Qualificator:"+Comm+" ]";
return(Comm);
}
Comments