Demark趋势线指标实战精解
📈

Demark趋势线指标实战精解

用MQL4还原TD线绘制逻辑与避坑指南

技术分析基础 难度 · 进阶 2026-04-16 5 分钟阅读
#Demark#趋势线#MQL4#指标开发

一、Thomas Demark趋势线方法的核心思想

在技术分析领域,买卖双方力量的博弈往往通过趋势线来可视化。传统趋势线依赖人工目测两点连线,带有极强主观性。Thomas Demark提出了一套客观选定趋势线上两个检查点(TD点)的规则,使趋势识别标准化。他认为市场最后的状态对交易者最重要,因此指标中当前趋势方向用粗实线绘制,而之前邻近的反向趋势用细虚线绘制,便于看清态势演变。

Demark方法不预测未来,而是确认已发生的趋势结构是否有效。它基于局部极值(峰顶与谷底)与收盘价的关系,过滤掉假突破噪音。这种客观性特别适合自动化交易系统,因为机器无法像人一样‘感觉’支撑阻力,只能执行明确条件。

✦ 学习价值
掌握该指标逻辑后,你可将其移植为EA信号过滤器,或改编为MQL5版本用于MT5平台。

二、指标缓冲区与基础架构设计

原文指标使用了四个缓冲区,这是MQL4中指标计算的核心数据存储区。两个箭头缓冲区用于标记TD点方向(上涨箭头236、下跌箭头238),两个线条缓冲区用于将TD线向左延长显示。前十个柱(第二TD点左侧)由缓冲区以Aqua色绘制,代表历史趋势延长。

这种多缓冲区设计分离了‘信号标记’与‘线形渲染’职责,避免相互干扰。注意SetIndexEmptyValue将0.0设为空值,使得未触发区域不绘图。以下为缓冲区声明与初始化关键片段:

#property indicator_chart_window
#property indicator_buffers 4
#property indicator_color1 Chartreuse
#property indicator_color2 Tomato
#property indicator_color3 Aqua
#property indicator_color4 Aqua

double   TrendUpBuffer[];
double   TrendDownBuffer[];
double   TrendLineBufferUp[];
double   TrendLineBufferDown[];

int init()
  {
   SetIndexStyle(0,DRAW_ARROW);
   SetIndexArrow(0,236);
   SetIndexBuffer(0,TrendUpBuffer);
   SetIndexEmptyValue(0,0.0);
   SetIndexStyle(1,DRAW_ARROW);
   SetIndexArrow(1,238);
   SetIndexBuffer(1,TrendDownBuffer);
   SetIndexEmptyValue(1,0.0);
   SetIndexStyle(2,DRAW_LINE);
   SetIndexBuffer(2,TrendLineBufferUp);
   SetIndexEmptyValue(2,0.0);
   SetIndexStyle(3,DRAW_LINE);
   SetIndexBuffer(3,TrendLineBufferDown);
   SetIndexEmptyValue(3,0.0);
   return(0);
  }

三、TD检查点的搜索与条件判定

指标从第二根柱开始循环(i=2),因为需要与右侧非零柱比较以验证局部极值。搜索峰顶时,条件#1要求当前High高于左右相邻柱High;条件#2要求该峰值高于其左侧两个柱之前的收盘价。两条件同时满足则匹配计数器U加1。

当U首次触发,记录第一检查点价格、索引、时间;当U第二次触发,记录第二检查点并进入下跌趋势验证:第一点价格必须低于第二点(即右侧更低),否则计数器回退并清零变量重新搜索。满足后计算TD线下降速度V_up,并验证条件#3:第一检查点左侧收盘价比TD线推算值更低,确认下跌有效。

for(int i=2;i<48;i++)
  if(High[i]>High[i+1]&&High[i]>High[i-1])
    if(High[i]>Close[i+2])
      { U++; 
        if(U==1) { TD_up[1]=High[i]; index_up_1=i; Pr_up_Cl_1=Close[i-1]; }
        if(U==2) { TD_up[2]=High[i]; index_up_2=i;
          if((U==2 && TD_up[1]<TD_up[2])==false) { U--; TD_up[2]=0.0; continue; }
          else { V_up=(TD_up[2]-TD_up[1])/(index_up_2-index_up_1);
            Pr_Tr_up_1=TD_up[1]-V_up;
            if((Pr_up_Cl_1< Pr_Tr_up_1)==false) { i=index_up_1+2; U=0; continue; }
            else { TrendDownBuffer[index_up_1]=TD_up[1]+5*Point; } } } }
⚠ 常见坑
循环上限设为48根柱(约2天),在长周期图表可能漏掉早期TD点;实盘应参数化周期长度。

四、谷底搜索与上升趋势对称逻辑

对于上涨趋势,指标用对称循环搜索谷底(Low[j]低于左右邻柱且低于左二收盘价)。计数器D记录匹配,第二谷底必须高于第一谷底,且条件#3要求右侧收盘价高于TD线上升推算值。若不满足,变量归零并从index_down_1+1重搜。这种对称设计保证多空逻辑一致,便于维护。

原文代码中谷底部分与峰顶高度平行,但注意变量命名与方向判断符号相反。移植时务必单元测试多空分支,防止符号错写导致线倒挂。

五、趋势线的对象绘制与样式控制

确认TD点后,程序使用ObjectCreate()在图表右侧画OBJ_TREND对象。关键过滤:若未找到反向第二TD点,则固定索引值使时间过滤器生效,避免中间值污染。最新趋势用粗实线(STYLE_SOLID,宽度2),前邻反向用细虚线(STYLE_DOT,宽度1),颜色均黄。

DelObj1();
ObjectCreate("TrDdown",OBJ_TREND,0,T_u2,TDu2,T_u1,TDu1);
if(index_up_1>index_down_1)
  { ObjectSet("TrDdown",OBJPROP_COLOR,Yellow); ObjectSet("TrDdown",OBJPROP_WIDTH,1); ObjectSet("TrDdown",OBJPROP_STYLE,STYLE_DOT); }
else
  { ObjectSet("TrDdown",OBJPROP_COLOR,Yellow); ObjectSet("TrDdown",OBJPROP_WIDTH,2); ObjectSet("TrDdown",OBJPROP_STYLE,STYLE_SOLID); }
✦ 调试技巧
原文大量Print与TimeToStr用于可视化控制,上线前可注释掉以降低日志负载,但保留时间转换便于排错。

六、与主观趋势线及其他指标的对比

相比手工画线,Demark指标消除犹豫空间,信号可回测;相比普通ZigZag,它增加收盘价确认条件#3,减少假转折。但缺点是依赖局部极值窗口,在剧烈单边市中可能长期不画反向线,此时指标仅显示当前粗线,需结合其他过滤器。

与MACD或均线类趋势工具比,TD线给出具体价格射线而非平滑值,更利于挂单布局。不过计算复杂度为O(n)扫描,历史重算时需注意性能。

七、实操部署与移植建议

在MT4加载mq4文件即可编译使用。若需MT5,须将缓冲区改为plot索引、用CopyHigh代替数组直接访问,并将ObjectCreate参数调整为MT5时间表。建议将48柱上限改为输入参数,适配不同品种波动。

实盘前应用历史数据观察线型重绘情况:指标基于已闭合柱计算,不会未来函数重绘,但新TD点出现时旧线可能被删,属正常更新。可搭配警报模块在粗实线生成时推送通知。

⚠ 版权注意
原文由MetaQuotes译自俄文,禁止整段转载;教学改写须保留个人观点属性,不对盈利负责。

常见问题

用ObjectCreate("名称",OBJ_TREND,0,时间2,价2,时间1,价1)连接两TD点,再用ObjectSet设OBJPROP_STYLE为STYLE_SOLID或STYLE_DOT区分新旧趋势,宽度设1或2。
条件#3要求右侧收盘价突破TD线推算值确认趋势有效,不满足说明前两点为假突破,须将TD价格、索引、时间、计数器全清零并从第一点左二柱重新循环。
因长时间单边市未找到反向第二TD点,反向线索引被固定为50且价格置0,过滤器阻止绘制;此时仅最新方向粗实线显示,属正常。
重写缓冲区为#property indicator_plots,用CopyBuffer/CopyHigh取数据,ObjectCreate时间参数用datetime,并调整事件函数名为OnCalculate与OnDeinit。