← 返回《初阶量化交易:策略编写及系统搭建》
📑 查看全课大纲(第 11 / 38 节)

基于MACD的交易信号开发(1)

约 23 分钟

📺 正在播放小象官方高清录播(支持倍速与清晰度调节)

基于MACD的交易信号开发(一)

小象实战讲义 · 初阶量化交易:策略编写及系统搭建 本讲义仅用于编程与量化方法教学,不构成任何投资建议。

在二级市场的技术分析体系中,MACD(Moving Average Convergence Divergence,平滑异同移动平均线) 被誉为”指标之王”。它由杰拉尔德·阿佩尔(Gerald Appel)于 1970 年代提出,通过对快速与慢速两条指数加权移动平均线(EMA) 进行离差运算与二次平滑,兼具了均线系统的趋势追踪能力与振荡指标的超买超卖预警特征。

本讲将从底层数学公式出发,严密拆解 DIFF(离差值)、DEA(讯号线)与 MACD 柱状图(红绿柱) 的递推计算逻辑;建立严格的金叉与死叉边沿触发数学判定准则;并深入探讨 EMA 初始数据衰减效应在量化系统工程落地中的防坑实践。


💡 核心导读

  • MACD 三大核心构成与数学公式
    • 快速与慢速 EMA(经典参数:short=12,long=26short=12, long=26EMAi=αClosei+(1α)EMAi1,α=2N+1EMA_i = \alpha \cdot Close_i + (1 - \alpha) \cdot EMA_{i-1}, \quad \alpha = \frac{2}{N + 1}
    • 离差值 DIFF(快线)DIFF=EMA12(Close)EMA26(Close)DIFF = EMA_{12}(Close) - EMA_{26}(Close)
    • 讯号线 DEA(慢线,DIFF 的 9 日 EMA)DEA=EMA9(DIFF)DEA = EMA_9(DIFF)
    • MACD 柱状图(红绿柱)MACD=2×(DIFFDEA)MACD = 2 \times (DIFF - DEA) 注:公式中乘以 2 纯属图表工程可视化需求,放大数值落差以便肉眼清晰观察柱体起伏。
  • 金叉与死叉的严格数学边沿判定
    • 黄金交叉(金叉 / 多头买入信号)DIFFi1DEAi1DIFF_{i-1} \le DEA_{i-1}DIFFi>DEAiDIFF_i > DEA_i(DIFF 由下往上穿过 DEA);
    • 死亡交叉(死叉 / 空头卖出信号)DIFFi1DEAi1DIFF_{i-1} \ge DEA_{i-1}DIFFi<DEAiDIFF_i < DEA_i(DIFF 由上往下穿过 DEA)。
  • 工程落地关键:EMA 初始衰减与数据预热
    • EMA 具有递推依赖性。若回测或实盘仅从最近几天开始计算,初始设定 EMA0=Close0EMA_0 = Close_0 会引入显著截断误差;
    • 工程防坑铁律:计算 MACD 时,必须向前预热并保留至少 100~200 根历史 K 线,确保 (1α)k0(1-\alpha)^k \to 0,使指数衰减权重完全收敛。
┌─────────────────────────────────────────────────────────────┐
│                       MACD 指标计算管道                      │
└──────────────────────────────┬──────────────────────────────┘

 ┌─────────────────────────────┴─────────────────────────────┐
 ▼                                                           ▼
┌──────────────────┐                               ┌──────────────────┐
│  EMA_12 (短周期)  │                               │  EMA_26 (长周期)  │
└────────┬─────────┘                               └────────┬─────────┘
         │                                                  │
         └──────────────────────┬───────────────────────────┘

         ┌──────────────────────────────────────────┐
         │     DIFF = EMA_12(Close) - EMA_26(Close) │
         └──────────────────────┬───────────────────┘

         ┌──────────────────────────────────────────┐
         │        DEA = EMA_9(DIFF) (二次平滑)       │
         └──────────────────────┬───────────────────┘

         ┌──────────────────────────────────────────┐
         │       MACD = 2 * (DIFF - DEA) (红绿柱)   │
         └──────────────────────────────────────────┘

一、MACD 的数学原理与递推公式

1. 指数加权移动平均(EMA)的平滑机制

简单移动平均(SMA)对窗口期内所有数据赋予相同权重,存在明显的滞后性与”数据离开窗口”时的跳跃冲击。EMA 则赋予越近的数据越高的权重,权重按指数级衰减:

α=2N+1\alpha = \frac{2}{N+1}

EMAi=αClosei+(1α)EMAi1EMA_i = \alpha \cdot Close_i + (1 - \alpha) \cdot EMA_{i-1}

2. DIFF、DEA 与 MACD 柱状图

  • DIFF(Difference):反映了短期价格动量与长期趋势均值之间的差距。当短期价格快速上冲时,EMA12 扩张快于 EMA26,DIFF 迅速攀升;
  • DEA(Difference Exponential Average):对 DIFF 进行 9 日 EMA 平滑,充当动量变化的基准线;
  • MACD 柱状图:当 DIFF 在 DEA 之上时,DIFFDEA>0DIFF - DEA > 0,绘制红色正向柱;反之绘制绿色负向柱。

二、金叉与死叉的量化判定准则

在量化策略开发中,我们绝不能使用模糊的状态判断,而必须使用严密的**边沿交叉(Cross Over / Cross Under)**逻辑:

┌─────────────────────────────────────────────────────────────┐
│                    金叉与死叉边沿触发判定                      │
├─────────────────────────────────────────────────────────────┤
│ • 金叉条件: (DIFF[t-1] <= DEA[t-1]) and (DIFF[t] > DEA[t])  │
│ • 死叉条件: (DIFF[t-1] >= DEA[t-1]) and (DIFF[t] < DEA[t])  │
└─────────────────────────────────────────────────────────────┘

参数非同质化与防收割

标准默认参数 (12,26,9)(12, 26, 9) 被全市场极其广泛地使用。在实盘量化中,由于大量程序化资金在标准金叉点位挂单,容易被大资金实施反向收割。量化团队常根据标的日内波动率进行参数自适应微调(如 10,22,710, 22, 7 或结合 ATR 动态调整)。


📝 动手练一练

下面我们用 Python 编写一段标准的 MACD 指标计算与金叉/死叉信号生成引擎,基于 Pandas 矢量化计算 EMA 与边沿交叉事件:

import pandas as pd
import numpy as np

def compute_macd_signals(df, short=12, long=26, m=9):
    """
    基于指数滑动平均 (EMA) 矢量化计算 MACD 指标与金叉/死叉边沿触发信号
    """
    df = df.copy()
    # 1. 计算快慢周期 EMA
    df['EMA_Fast'] = df['Close'].ewm(span=short, adjust=False).mean()
    df['EMA_Slow'] = df['Close'].ewm(span=long, adjust=False).mean()
    
    # 2. 计算 DIFF (快线 - 慢线)
    df['DIFF'] = df['EMA_Fast'] - df['EMA_Slow']
    
    # 3. 计算 DEA (DIFF 的 M 日 EMA 平滑)
    df['DEA'] = df['DIFF'].ewm(span=m, adjust=False).mean()
    
    # 4. 计算 MACD 柱状图 (2 倍差值)
    df['MACD_Bar'] = 2.0 * (df['DIFF'] - df['DEA'])
    
    # 5. 边沿触发判定: 金叉与死叉
    df['Pre_DIFF'] = df['DIFF'].shift(1)
    df['Pre_DEA'] = df['DEA'].shift(1)
    
    df['Gold_Cross'] = (df['Pre_DIFF'] <= df['Pre_DEA']) & (df['DIFF'] > df['DEA'])
    df['Dead_Cross'] = (df['Pre_DIFF'] >= df['Pre_DEA']) & (df['DIFF'] < df['DEA'])
    
    return df

def test_macd_run():
    np.random.seed(42)
    # 构造 30 天价格序列 (模拟波段震荡走势)
    n_days = 30
    dates = pd.date_range("2023-01-01", periods=n_days, freq="D")
    base_prices = 10.0 + np.sin(np.linspace(-np.pi/2, np.pi*1.5, n_days)) * 2.0
    prices = base_prices + np.random.normal(0, 0.1, n_days)
    
    df = pd.DataFrame({'Close': prices}, index=dates)
    res = compute_macd_signals(df, short=12, long=26, m=9)
    
    gold_cross_dates = res[res['Gold_Cross']].index.strftime('%Y-%m-%d').tolist()
    dead_cross_dates = res[res['Dead_Cross']].index.strftime('%Y-%m-%d').tolist()
    
    print("================ MACD 金叉/死叉量化信号引擎 ================")
    print(res[['Close', 'DIFF', 'DEA', 'MACD_Bar', 'Gold_Cross', 'Dead_Cross']].tail(8))
    print("----------------------------------------------------------")
    print(f"检测到 MACD 金叉日期: {gold_cross_dates}")
    print(f"检测到 MACD 死叉日期: {dead_cross_dates}")
    print("==========================================================")

if __name__ == "__main__":
    test_macd_run()

运行结果输出:

================ MACD 金叉/死叉量化信号引擎 ================
                Close      DIFF       DEA  MACD_Bar  Gold_Cross  Dead_Cross
2023-01-23   9.898475  0.522456  0.740297 -0.435681       False       False
2023-01-24   9.322469  0.366966  0.665631 -0.597330       False       False
2023-01-25   9.008745  0.215934  0.575691 -0.719515       False       False
2023-01-26   8.716320  0.071816  0.474916 -0.806200       False       False
2023-01-27   8.292715 -0.075707  0.364792 -0.880997       False       False
2023-01-28   8.222419 -0.196032  0.252627 -0.897319       False       False
2023-01-29   7.986695 -0.306875  0.140727 -0.895203       False       False
2023-01-30   7.970831 -0.391486  0.034284 -0.851539       False       False
----------------------------------------------------------
检测到 MACD 金叉日期: ['2023-01-03']
检测到 MACD 死叉日期: ['2023-01-02', '2023-01-21']
==========================================================

本章小结

  1. 掌握 MACD 数学内涵:DIFF 为快慢 EMA 差值,DEA 为 DIFF 的再次平滑,柱状图为两者的放大可视化呈现。
  2. 严格边沿触发逻辑:量化回测必须使用 shift(1) 对比前后两日的相对位置,精准锁定金叉与死叉发生点。
  3. 数据预热消除误差:计算指数滑动平均时,前置数据应至少保留 100~200 根 K 线,确保 EMA 初始权重彻底衰减。

📋 行动清单 (Action Checklist)

  • 运行本讲代码,观察调整 shortlong 参数(如 8, 21)对金叉死叉产生时机的影响;
  • 验证数据预热重要性:尝试只用 15 天数据计算 EMA26,对比与 200 天预热数据的数值差异;
  • 进入下一讲,探讨均线与指标相切等边界异常情况的判定处理。

— 小象教研组

配套学习资源与课件
  • 第2章课件:认识量化信号系统(PDF · 2.1MB)
    下载
  • 开发环境准备:软件安装指导(PDF · 0.9MB · 建议第3章动手实践前先通读)
    下载
  • 量化入门推荐书单(PDF · 318KB)
    下载
🎁 免费学习资源

领取《小象 11GB VIP 课件资料包与大厂真题手册》

包含全套实战 Jupyter 源码、清洗后数据集、大厂高频面试真题与专属学员答疑交流群。

  • 完整 Python / 数据分析 Jupyter 实战源码
  • 大厂真实业务数据集与练习题
  • 微信扫码添加课程顾问,免费获取网盘下载链接
微信二维码:扫码添加课程顾问微信扫码添加顾问