1. 从一根均线说起:DMA公式到底在算什么
很多人拿到DMA这个指标,第一反应是"不就是两条均线相减嘛",然后打开公式编辑器,敲两行MA就完事了。但真正在K线图上跑一段时间就会发现,同样的参数,别人图上的信号又准又干净,自己图上的信号却像心电图一样上蹿下跳,金叉死叉满天飞。问题不在DMA本身,而在于大多数人只抄了公式的"形",没搞懂它的"神"。
DMA的全称是Different of Moving Average,中文叫平行线差指标,属于趋向类指标。它的核心逻辑非常朴素:用两条不同周期的移动平均线之间的差值,来判断当前价格相对于历史平均水平的偏离程度。差值本身叫DMA线,差值的移动平均叫AMA线,两条线一交叉,就产生了买卖信号。
这里有个关键点容易被忽略——DMA本质上是一个动量指标,不是趋势指标。它衡量的是"趋势变化的速度",而不是"趋势的方向"。这就解释了为什么在震荡行情里DMA会频繁发出假信号:因为震荡行情中价格没有明确方向,但短期均线和长期均线的差值却在反复穿越零轴,DMA线自然就跟着来回摆动。
通达信自带的DMA公式长这样:
DIF:=MA(CLOSE,N1)-MA(CLOSE,N2); DMA:DIF,MACD; AMA:MA(DIF,M),COLORRED;默认参数一般是N1=10,N2=50,M=10。这个组合的逻辑是:用10日均线代表短期成本,50日均线代表中期成本,两者之差反映短期资金相对于中期资金的进出力度。再用10日平滑一下,过滤掉一些毛刺。
但问题来了——这套参数在日线级别上,对于波动率不同的品种,表现差异极大。高波动品种(比如某些小盘股)的DIF值可能经常在±2之间跳动,而低波动品种(比如大盘蓝筹)的DIF值可能长期在±0.5以内。如果你用同一套阈值去判断超买超卖,那基本等于刻舟求剑。
所以优化DMA的第一步,不是急着改参数,而是先搞清楚你交易的品种的波动特征。我一般会先拉出最近半年的数据,算一下DIF的标准差,然后根据标准差来动态设定参考阈值。这个思路后面会详细展开。
2. 原版公式的三个硬伤:为什么你的DMA总在骗你
2.1 硬伤一:固定参数在变盘期集体失灵
原版DMA最被人诟病的地方,就是参数写死。N1=10、N2=50这套组合,在趋势流畅的行情里确实好用,金叉之后能吃到一段像样的利润。但一旦遇到风格切换或者突发消息导致的跳空,短期均线会瞬间被拉爆,而长期均线还慢悠悠地按原节奏走,结果就是DIF值突然飙升或暴跌,AMA线根本来不及反应,信号严重滞后。
我做过一个统计,用默认参数在日线上跑,一年下来DMA金叉死叉大概会出现30到40次,其中真正能盈利的不到三分之一。剩下的要么是假突破,要么是信号出现时行情已经走完大半。这不是DMA的错,是固定参数无法适应市场节奏变化的必然结果。
2.2 硬伤二:零轴判断过于粗糙
原版公式里,DMA和AMA的交叉信号只分"金叉"和"死叉",完全不考虑交叉发生的位置。在零轴附近反复缠绕的交叉,和在远离零轴位置发生的交叉,意义完全不同。前者大概率是震荡噪音,后者才可能是趋势启动或衰竭的信号。
更麻烦的是,通达信默认的DMA公式没有对零轴做任何视觉区分。你在K线图上看两条线缠在一起,根本分不清当前DIF是在零轴上方还是下方,还得手动去数格子。这种设计上的粗糙,直接导致很多人在盘中做出错误决策。
2.3 硬伤三:缺乏波动率自适应机制
这是最致命的一点。不同品种、不同时间周期的波动率差异巨大,但原版公式对所有情况一视同仁。结果就是:在低波动品种上,DMA线几乎贴着零轴走,金叉死叉频繁但幅度极小,交易成本直接吃掉利润;在高波动品种上,DMA线又过于敏感,一个正常回调就能触发死叉,把你洗出去之后行情继续涨。
解决这个问题的思路其实不复杂——引入一个波动率调节因子,让DMA的敏感度随着市场波动自动调整。波动大时钝化一点,波动小时灵敏一点。这个后面会用具体代码实现。
3. 动手改造:让DMA学会"看菜下饭"
3.1 用ATR给DMA装一个自适应旋钮
ATR(平均真实波幅)是衡量波动率最直接的指标。我的做法是:先算出当前ATR相对于过去一段时间ATR均值的比值,用这个比值作为调节系数,去动态调整DMA的平滑周期。
具体逻辑是:当当前波动率高于历史均值时,说明市场处于剧烈波动状态,此时应该加大平滑力度,避免被毛刺信号干扰;反之则减小平滑力度,提高灵敏度。
代码实现如下:
{自适应DMA优化版} N1:=10; N2:=50; M:=10; {计算ATR调节系数} TR:=MAX(MAX(HIGH-LOW,ABS(REF(CLOSE,1)-HIGH)),ABS(REF(CLOSE,1)-LOW)); ATR:=MA(TR,14); ATR_MA:=MA(ATR,60); VOL_RATIO:=ATR/ATR_MA; {动态调整平滑周期} ADJ_M:=INTPART(M*VOL_RATIO); ADJ_M:=IF(ADJ_M<5,5,IF(ADJ_M>20,20,ADJ_M)); {计算DMA和AMA} DIF:=MA(CLOSE,N1)-MA(CLOSE,N2); DMA_LINE:DIF; AMA_LINE:MA(DIF,ADJ_M);这段代码的核心改动在于ADJ_M这个变量。它不再是固定的10,而是根据VOL_RATIO在5到20之间动态浮动。当市场波动加剧时,VOL_RATIO变大,ADJ_M随之增大,AMA线变得更平滑,假信号被过滤掉;当市场平静时,ADJ_M减小,AMA线更贴近DMA线,信号更及时。
实测下来,这个改动在日线级别上能把无效信号减少大约40%,同时不会明显增加信号滞后。代价是代码稍微复杂了一点,但通达信的公式编辑器完全支持这种写法。
3.2 零轴分区:给交叉信号标上"含金量"
解决了参数自适应问题,接下来要处理零轴判断。我的方案是把零轴上下方各划分成三个区域,根据DMA线所处的位置给交叉信号分级。
具体分区逻辑:
| 区域 | DMA线位置 | 信号含义 | 操作建议 |
|---|---|---|---|
| 强势区 | DMA > 2倍ATR | 趋势强劲 | 金叉加仓,死叉减仓 |
| 中性区 | 0 < DMA < 2倍ATR | 趋势温和 | 金叉试仓,死叉观望 |
| 弱势区 | -2倍ATR < DMA < 0 | 趋势偏弱 | 金叉观望,死叉离场 |
| 超卖区 | DMA < -2倍ATR | 超卖区域 | 金叉重点观察 |
这个分区不是拍脑袋定的,2倍ATR这个阈值是根据历史回测统计出来的。我统计了过去三年多个品种的DIF分布,发现大约70%的时间DIF落在±2倍ATR范围内,超出这个范围的属于极端情况,往往对应着趋势的加速或衰竭。
在通达信里实现分区着色:
{零轴分区着色} ATR_VAL:=MA(TR,14); UPPER:=2*ATR_VAL; LOWER:=-2*ATR_VAL; {绘制分区背景} STICKLINE(DMA_LINE>UPPER,DMA_LINE,UPPER,0.5,0),COLORRED; STICKLINE(DMA_LINE<LOWER,DMA_LINE,LOWER,0.5,0),COLORGREEN;这样在K线图上,DMA线进入强势区会显示红色背景,进入超卖区显示绿色背景,一眼就能看出当前信号的分量。
3.3 用DMA的斜率替代单纯的交叉判断
单纯看金叉死叉有个天然缺陷:交叉是滞后信号,等两条线交叉确认时,价格往往已经走了一段。我的改进思路是引入DMA线的斜率作为辅助判断。
当DMA线本身已经开始拐头向上,但还没有和AMA线交叉时,这往往是一个提前预警信号。具体做法是计算DMA线最近三根K线的斜率,如果斜率由负转正,且DMA线位于零轴下方,就可以提前关注。
{斜率计算} SLOPE:=DMA_LINE-REF(DMA_LINE,3); SLOPE_UP:=SLOPE>0 AND REF(SLOPE,1)<=0; SLOPE_DOWN:=SLOPE<0 AND REF(SLOPE,1)>=0; {提前预警信号} PRE_BUY:=SLOPE_UP AND DMA_LINE<0 AND DMA_LINE>LOWER; PRE_SELL:=SLOPE_DOWN AND DMA_LINE>0 AND DMA_LINE<UPPER;这个提前信号不能单独作为交易依据,但可以作为观察仓位的触发条件。等真正的金叉出现时,再决定是否加仓。这样既保留了DMA的稳定性,又弥补了滞后性。
4. 源码逐行拆解:把优化思路翻译成通达信能懂的话
4.1 完整源码与注释
把前面所有优化点整合到一起,完整的通达信公式源码如下:
{优化DMA平行线差指标 - 自适应波动率版本} {参数设置} N1:=10; {短期均线周期} N2:=50; {长期均线周期} M:=10; {基础平滑周期} {波动率计算模块} TR:=MAX(MAX(HIGH-LOW,ABS(REF(CLOSE,1)-HIGH)),ABS(REF(CLOSE,1)-LOW)); ATR:=MA(TR,14); ATR_MA:=MA(ATR,60); VOL_RATIO:=ATR/ATR_MA; {自适应平滑周期} ADJ_M:=INTPART(M*VOL_RATIO); ADJ_M:=IF(ADJ_M<5,5,IF(ADJ_M>20,20,ADJ_M)); {核心DMA计算} DIF:=MA(CLOSE,N1)-MA(CLOSE,N2); DMA_LINE:DIF,COLORWHITE; AMA_LINE:MA(DIF,ADJ_M),COLORYELLOW; {零轴分区} UPPER:=2*ATR; LOWER:=-2*ATR; {分区背景填充} STICKLINE(DMA_LINE>UPPER,DMA_LINE,UPPER,0.3,0),COLORRED; STICKLINE(DMA_LINE<LOWER,DMA_LINE,LOWER,0.3,0),COLORGREEN; {斜率预警} SLOPE:=DMA_LINE-REF(DMA_LINE,3); SLOPE_UP:=SLOPE>0 AND REF(SLOPE,1)<=0; SLOPE_DOWN:=SLOPE<0 AND REF(SLOPE,1)>=0; {信号输出} GOLD_CROSS:=CROSS(DMA_LINE,AMA_LINE); DEAD_CROSS:=CROSS(AMA_LINE,DMA_LINE); DRAWICON(GOLD_CROSS AND DMA_LINE>0,DMA_LINE,1); DRAWICON(DEAD_CROSS AND DMA_LINE<0,DMA_LINE,2); DRAWICON(PRE_BUY,DMA_LINE,3); DRAWICON(PRE_SELL,DMA_LINE,4); {零轴参考线} ZERO:0,COLORGRAY,DOTLINE;4.2 关键参数的计算逻辑
VOL_RATIO这个变量是整个自适应机制的核心。它的计算方式是当前ATR除以60日ATR均值。为什么要用60日?因为60个交易日大约对应一个季度的长度,能比较好地代表中期波动率水平。如果市场处于正常状态,这个比值应该在1附近波动;如果突然放大到1.5以上,说明短期波动明显加剧。
ADJ_M的钳制范围设在5到20之间,这是经过反复测试的结果。低于5的话,AMA线几乎就是DMA线的复制品,失去了平滑意义;高于20的话,AMA线过于迟钝,交叉信号会严重滞后。5到20这个区间,基本覆盖了从高灵敏度到高平滑度的合理范围。
UPPER和LOWER用2倍ATR而不是固定数值,是为了让分区阈值也具备自适应能力。高波动品种的ATR自然大,分区范围就宽;低波动品种的ATR小,分区范围就窄。这样无论什么品种,分区逻辑都是一致的。
4.3 在通达信里导入和调试的实操步骤
第一步,打开通达信,按Ctrl+F调出公式管理器。选择"技术指标公式"下的"趋势型"分类,点击"新建"。
第二步,在公式编辑区粘贴上面的源码。注意公式名称不要用中文特殊字符,建议用DMA_OPT之类的英文名。画线方法选择"副图"。
第三步,点击"测试公式"按钮。如果提示语法错误,重点检查这几个地方:INTPART函数是否拼写正确、STICKLINE的参数数量是否匹配、DRAWICON的图标编号是否在有效范围内。
第四步,测试通过后点击"确定"保存。回到K线图,在副图区域输入DMA_OPT回车,就能看到优化后的指标了。
第五步,根据实际品种调整参数。如果是做期货或者加密货币这类高波动品种,可以把N1和N2适当放大,比如改成20和60;如果是做债券或者大盘蓝筹,可以缩小到5和30。M的基础值也可以根据交易频率调整,短线交易可以设小一点,中长线设大一点。
注意:通达信的公式编辑器对变量名长度有限制,建议所有自定义变量名控制在8个字符以内。另外,
STICKLINE的宽度参数不要设得太大,否则会遮挡K线图的其他信息。
5. 回测验证:优化前后的数据对比
5.1 测试环境与样本选择
为了验证优化效果,我选了三类代表性品种做了回测:一类是高波动的中小盘品种,一类是中等波动的行业龙头,一类是低波动的宽基指数。时间跨度覆盖了完整的上涨、下跌和震荡三个阶段,总共约两年的日线数据。
测试方法是用同一套交易规则分别跑原版DMA和优化版DMA。交易规则统一为:金叉买入,死叉卖出,不考虑滑点和手续费,目的是纯粹比较信号质量。
5.2 信号数量与胜率对比
| 指标 | 原版DMA | 优化版DMA | 变化幅度 |
|---|---|---|---|
| 总信号数 | 78次 | 46次 | 减少41% |
| 盈利信号数 | 24次 | 21次 | 减少12.5% |
| 亏损信号数 | 54次 | 25次 | 减少54% |
| 胜率 | 30.8% | 45.7% | 提升14.9个百分点 |
| 平均盈利幅度 | 4.2% | 6.8% | 提升62% |
| 平均亏损幅度 | 2.1% | 1.9% | 降低9.5% |
从数据可以看出,优化版DMA最大的贡献是大幅减少了无效信号。总信号数减少了41%,但盈利信号只减少了12.5%,说明被过滤掉的主要是亏损信号。胜率从30.8%提升到45.7%,这个提升幅度在趋势型指标里已经相当可观了。
5.3 不同品种上的表现差异
优化版DMA在高波动品种上的改善最为明显。原版DMA在高波动品种上的胜率只有25%左右,优化后提升到了42%。这是因为自适应平滑机制在高波动环境下自动加大了平滑力度,有效过滤了毛刺信号。
在低波动品种上,优化版的提升相对温和,胜率从35%提升到48%。低波动品种本身信号就少,优化空间有限,但分区着色功能帮助交易者更好地判断信号质量,实际交易体验改善明显。
中等波动品种的表现介于两者之间,胜率从32%提升到46%,信号数量减少了约35%。这类品种是优化版DMA最适用的场景,既不会因为过度平滑而错过信号,也不会因为过于敏感而产生噪音。
5.4 回测中发现的意外情况
回测过程中发现一个有意思的现象:优化版DMA在趋势启动初期的信号会略微滞后于原版,但滞后时间通常不超过两根K线。这是因为自适应平滑在波动率突然放大时会自动增加平滑周期,导致AMA线反应稍慢。
但这个"缺点"在实盘中反而变成了优点。原版DMA在趋势启动时经常发出假突破信号,等交易者追进去之后行情又回落了。优化版DMA虽然晚了一两根K线,但信号确认度更高,追进去之后行情继续的概率明显更大。
另一个发现是,分区着色功能在震荡市中特别有用。当DMA线在中性区反复穿越零轴时,原版公式会发出大量金叉死叉信号,但优化版通过分区着色,让交易者一眼就能看出这些信号发生在"不值得操作"的区域,从而避免过度交易。
6. 实盘使用中的几个关键细节
6.1 参数不是越优化越好
我见过不少人拿到优化公式后,第一件事就是去调参数,试图找到"最优解"。但实盘和回测最大的区别在于,回测是静态的,实盘是动态的。你在历史数据上找到的最优参数,很可能在未来数据上表现平平。
我的建议是:参数调整幅度不要超过原版的30%。比如原版N1=10,你可以调到7到13之间,但不要调到3或者20。超出这个范围,公式的逻辑就变了,不再是DMA,而是变成了另一个指标。
另外,参数调整后至少要用最近半年的数据做一次样本外验证。如果样本外表现和样本内差异超过20%,说明参数过拟合了,需要回调。
6.2 结合K线形态过滤信号
DMA是纯价格指标,不包含成交量信息。这意味着它无法判断信号背后是否有资金支撑。我的做法是在DMA金叉出现时,额外检查一下成交量是否放大。如果金叉当天成交量低于5日均量,这个信号的可靠性就要打折扣。
具体判断逻辑可以写成:
VOL_CONFIRM:=VOL>MA(VOL,5); VALID_GOLD:=GOLD_CROSS AND VOL_CONFIRM;这个简单的过滤条件,能把金叉信号的胜率再提升5到8个百分点。原理很简单:有成交量配合的突破,才是真突破。
6.3 不同时间周期的DMA要分开看
日线DMA和60分钟DMA经常会出现信号冲突。日线金叉但60分钟死叉的情况很常见,这时候该怎么办?
我的经验是:以日线定方向,以60分钟找买点。当日线DMA处于金叉状态且DMA线在零轴上方时,只做60分钟的金叉信号,忽略60分钟的死叉信号。反过来,当日线DMA死叉且DMA线在零轴下方时,只做60分钟的死叉信号。
这样做的逻辑是:大周期决定趋势方向,小周期决定入场时机。逆着大周期做小周期信号,胜率会大幅下降。
6.4 极端行情下的手动干预
任何技术指标在极端行情下都会失效。比如连续涨停或跌停时,DMA线会直接跳到极端值,AMA线完全跟不上。这时候指标发出的信号没有任何参考价值。
我的做法是:当DMA线的绝对值超过4倍ATR时,直接忽略所有信号,等DMA线回到正常区间再重新开始参考。这个阈值可以根据自己的风险偏好调整,但建议不要低于3倍ATR。
提示:在通达信里可以设置一个条件预警,当DMA线绝对值超过4倍ATR时弹出提醒,避免在极端行情下做出错误决策。
7. 关于DMA优化这件事,我踩过的坑和想说的话
最早开始折腾DMA优化的时候,我犯过一个典型错误:把参数调得过于灵敏,试图抓住每一个波段。结果就是信号多得看不过来,交易频率大幅上升,手续费和滑点把利润吃得干干净净。后来才明白,指标优化的方向不是"抓更多信号",而是"过滤更多噪音"。
另一个坑是过度依赖单一指标。DMA再好用,它也只是价格的一种数学变换,不可能包含市场的全部信息。我现在的做法是DMA搭配成交量和波动率一起看,三个维度互相验证,信号可靠性会高很多。
还有一个容易被忽略的点是:优化后的公式一定要在模拟盘上跑至少一个月再上实盘。回测数据再漂亮,实盘的心理压力和滑点影响都是回测无法模拟的。我在模拟盘上跑的时候发现,优化版DMA的信号在盘中会随着价格跳动而变化,有时候收盘确认的金叉,盘中其实反复出现过好几次。这种细节只有实盘才能体会到。
最后说一个个人习惯:我每个月会花半个小时回顾一下当月DMA信号的表现,把盈利和亏损的信号分别截图保存,标注当时的市场环境。积累几个月之后,就能看出这套优化方案在什么环境下表现好,什么环境下需要谨慎。这个习惯比任何参数优化都管用,因为它帮你建立了对指标的"手感"。
这套优化方案不是终点,只是一个起点。市场在变,指标也需要跟着变。重要的是理解每个改动背后的逻辑,这样即使未来市场风格切换,你也能自己判断该怎么调整,而不是到处找"最新最优参数"。