通达信指标公式(4)MACD指标3个进阶版本与C++源代码(值得收藏)
相信大家都了解MACD这个技术指标,它是基于移动平均线的原理,通过计算短期和长期移动平均线之间的差异和聚合状态,来预测价格的走势,属于趋势型指标。
今天主要分享我在实战中,使用MACD的3个进阶版本(如下图),介绍每个版本的由来,如何一步步优化、调整,从而去除一些干扰的信号(去噪),最终提供相对正确率较高的入场信号。
前情回顾
限时福利
在公众号后台回复关键字,免费获取优质策略资源:
策略大礼包
通达信教程
高盛报告
…
更多资源尽情期待,文末还有重磅福利!!!
基础知识
MACD指标由三部分组成:快线(DIF)、慢线(DEA)和柱状图(MACD),这三个值的计算方式也比较简单,不过多介绍了,有几个概念需要提前说明下:
- 金叉:当 DIF 上穿DEA时,通常表示买入信号。
- 死叉:当 DIF 下穿DEA时,通常表示卖出信号。
- 顶背离:当价格上涨,但 DIF 和 DEA 下降,表示上涨动能减弱。
- 底背离:当价格下跌,但 DIF 和 DEA 上升,表示下跌动能减弱。
V2.0 版本
我们希望通过金叉/死叉,提供买入/卖出的信号,但是传统的MACD指标没有这些信号的标记,V2.0版本由此诞生,我们用红色向上的箭头标记买入信号,绿色向下的箭头标记卖出信号。
这个版本的代码比较简单,就是将金叉、死叉的位置标记出来,其他的没有进行任何过滤。
{ 金叉条件 }
GOLD_CROSS := CROSS(DIF,DEA);
{ 死叉条件 }
DEATH_CROSS := CROSS(DEA,DIF);
V3.0版本
V2.0版本相比标准的MACD指标,只是将金叉死叉标记了出来,那这个版本存在哪些问题呢?
问题1-干扰信号过多
当行情k线处于横盘阶段,市场波动不大的时候,会产生很多干扰信号,如上图V2.0版本中,这段时间产生了19次信号,尤其在三个紫色框的部分,我们希望过滤掉这些不太明显的趋势信号。
问题2-零轴分水岭
如果你身边有老股民,他们会经常把一句话挂在嘴巴:“零轴之上不做多、零轴之下不做空”,这个零轴分水岭在很多趋势型技术指标中都适用。
如上图V2.0版本中,在MACD零轴之上有4次做多的信号(买入),在MACD零轴之下有2次做空的信号(卖出),这6个信号也是我们不想要的。
V3.0版本,解决了上面两个问题,代码如下:
{ 定义过滤条件 }
DIF_V := 0.1; { DIF阈值,可调参数 }
THRESHOLD := 0.1; { 差值阈值,可调参数 }
ZERO_FILTER := 0; { 零轴过滤开关:1启用/0禁用 }
{ 金叉条件优化 }
GOLD_CROSS := CROSS(DIF,DEA)
AND ABS(DIF) > DIF_V
AND DIF < 0
AND ABS(DIF-DEA) > THRESHOLD
AND (ZERO_FILTER = 0 OR (DIF > 0 OR DEA > 0))
AND MACD > REF(MACD,1);
{ 死叉条件优化 }
DEATH_CROSS := CROSS(DEA,DIF)
AND ABS(DIF) > DIF_V
AND DIF > 0
AND ABS(DEA-DIF) > THRESHOLD
AND (ZERO_FILTER = 0 OR (DIF < 0 OR DEA < 0))
AND MACD < REF(MACD,1);
上面代码,我们在金叉死叉的判断上,增加了更多条件,这个版本优化下来,直接从V2.0版本的19个信号,降低到了10个信号。
当然信号也不是越少越好,而是要相对更高的正确率。
V3.0版本的要点
这个版本优化下来,已经比传统MACD指标强了不少,截至目前也没有将MACD与k线图放到一直进行验证,最开始也说了:优化的目的是为了过滤掉一些干扰信号(去噪),提供相对正确率较高的入场信号。不可能做到百分之百正确率的,主要说下使用该版本的要点:
- 适用于相对长周期的趋势策略,从我的使用来看,至少在30分钟及以上的k线上
- 过滤条件定义了2个阈值,需要结合不同市场(股票、期货),不同品种进行调整,这些阈值会相差比较大
- 我在期货上使用比较多,重点在自己常做的品种上进行阈值调整,找到适合自己的参数
V3.0版本的问题
这个版本的问题,其实也是大多数趋势型技术指标的共性问题,那就是只关注‘价格’这一个维度产生的信号,‘量价量价’,不把‘量’加进来,单单由‘价‘产生的信号,往往会存在欺骗行为。
如上图,MACD金叉产生了买入信号,但是之后行情k线一路下跌,这样的信号就可以称之为虚假信号。那么如何识别并过滤掉这些虚假信号呢?
加入成交量指标进行过滤,上面的截图已经非常明了了,虽然MACD金叉产生了买入信号,但是这根k线的成交量非常低,甚至还不到前一根k线成交量的一半。
V4.0版本
V4.0版本不仅仅是增加了成交量Volume的指标,我还增加了一些更复杂的计算逻辑:MACD值的线性回归斜率等,最终V4.0版本从V3.0版本的10个信号,降到了6个。
1、增加成交量指标
下面的代码相比V3.0版本,只增加了2行,这两是一样的,当前K线的成交量要大于前一根K线的成交量:AND VOL > REF(VOL, 1)。
{ 金叉条件优化 }
GOLD_CROSS := CROSS(DIF,DEA)
AND ABS(DIF) > DIF_V
AND DIF < 0
AND ABS(DIF-DEA) > THRESHOLD
AND (ZERO_FILTER = 0 OR (DIF > 0 OR DEA > 0))
AND VOL > REF(VOL, 1)
AND MACD > REF(MACD,1);
{ 死叉条件优化 }
DEATH_CROSS := CROSS(DEA,DIF)
AND ABS(DIF) > DIF_V
AND DIF > 0
AND ABS(DEA-DIF) > THRESHOLD
AND (ZERO_FILTER = 0 OR (DIF < 0 OR DEA < 0))
AND VOL > REF(VOL, 1)
AND MACD < REF(MACD,1);
同样,这个条件针对不同品种还需进一步调整,比如成交量要大于前一根k线成交量的1.5倍、2倍、3倍等等。
看到这里,相信我,目前的MACD指标进阶版本,已经可以战胜市场上绝大多数使用传统MACD指标的投资者了。
2、增加线性回归斜率
以下仅展示斜率的计算代码,至于斜率如何加入使用,暂且留个悬念,后面找机会分享。
{ 参数设置,默认与前5个周期计算斜率 }
N:=5;
{ 线性回归斜率计算 }
MACD_SLOPE:=SLOPE(MACD, N);
DIF_SLOPE:=SLOPE(DIF, N);
DEA_SLOPE:=SLOPE(DEA, N);
比如我常做的期货日内趋势型策略,需要关注短周期的变化,尤其是反转行情,斜率就可以用上了。
其他优化方案
- 可调整MACD参数,比如将快慢EMA调整为14和28,信号线调整为10,或者其他组合。
- 采用自定义K线周期进行观察,比如31分钟、37分钟等
- 调整更合适的成交量阈值
- 如果是股票,可以加入成交额参数进行过滤
- 如果是期货,可以加入持仓量参数进行过滤
C++代码(主要函数源码)
// 判断金叉或死叉
inline BoolArray CROSS(const DoubleArray& S1, const DoubleArray& S2) {
BoolArray result = xt::empty<bool>(S1.shape());
for (size_t i = 1; i < S1.size(); ++i) {
result(i) = (S1(i - 1) <= S2(i - 1)) && (S1(i) > S2(i));
}
result(0) = false; // 第一个值无效
return result;
}
// 线性回归斜率
inline DoubleArray SLOPE(const DoubleArray& S, int N) {
DoubleArray result = xt::empty_like(S);
DoubleArray X = xt::arange(0, N);
for (size_t i = 0; i < S.size(); ++i) {
if (i >= N - 1) {
auto sub_array = xt::view(S, xt::range(i - N + 1, i + 1));
double numerator = xt::sum((X - xt::mean(X)) * (sub_array - xt::mean(sub_array)))();
double denominator = xt::sum(xt::square(X - xt::mean(X)))();
double slope = numerator / denominator;
result(i) = slope;
}
else {
result(i) = get_nan();
}
}
return result;
}
// EMA 指标
inline DoubleArray EMA(const DoubleArray& close, std::size_t period) {
double alpha = 2.0 / (period + 1);
DoubleArray ema = xt::empty<double>({ close.size() });
ema(0) = close(0);
for (std::size_t i = 1; i < close.size(); ++i) {
ema(i) = (close(i) - ema(i - 1)) * alpha + ema(i - 1);
}
return ema;
}
// MACD 指标
inline std::tuple<DoubleArray, DoubleArray, DoubleArray> MACD(const DoubleArray& close, std::size_t short_period, std::size_t long_period, std::size_t mid_period) {
auto dif = EMA(close, short_period) - EMA(close, long_period);
auto dea = EMA(dif, mid_period);
auto macd = (dif - dea) * 2;
return std::make_tuple(dif, dea, macd);
}
MACD指标最终版本获取方式
创作不易,如果想要最终版本的MACD指标源码,打赏50及以上,在后台留下你的邮箱,发给你,或者加我微信进行交流沟通。
社群介绍:码上君量化互助社群介绍
📌 声明:交易有风险,入市需谨慎。