查看全课大纲(第 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=26): EMAi=α⋅Closei+(1−α)⋅EMAi−1,α=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×(DIFF−DEA)MACD = 2 \times (DIFF - DEA) 注:公式中乘以 2 纯属图表工程可视化需求,放大数值落差以便肉眼清晰观察柱体起伏。
  • 金叉与死叉的严格数学边沿判定:
    • 黄金交叉(金叉 / 多头买入信号):DIFFi−1≤DEAi−1DIFF_{i-1} \le DEA_{i-1} 且 DIFFi>DEAiDIFF_i > DEA_i(DIFF 由下往上穿过 DEA);
    • 死亡交叉(死叉 / 空头卖出信号):DIFFi−1≥DEAi−1DIFF_{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−α)k→0(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−α)⋅EMAi−1EMA_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 之上时,DIFF−DEA>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 动态调整)。

⚠️ 风险提示(信号类指标):MACD 金叉/死叉只是对已发生趋势切换的统计描述,不构成任何买卖建议,也不预示未来收益;信号在极端行情会频繁假突破(拉锯磨损),在单一品种、单一参数上反复回测挑选”最优”信号极易陷入过拟合(防范方法见 5.4),实盘还须计入滑点、佣金与冲击成本。

📌 合规自查(回测/策略类内容的通用前提):本讲数值来自内置合成数据或人为设定的假设输入,仅用于演示方法,不代表真实交易结果;幸存者偏差(回测样本必须包含当时在市、日后可能退市的全部标的,只在幸存股票上计算会虚增表现);前视偏差(未来函数)(当日收盘后得到的信息只能用于其后的交易决策,财报须按实际披露日对齐)。


📝 动手练一练

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

import pandas as pd
import numpy as np

# 保证宽表在任意终端宽度下都完整打印(不折叠中间列),使输出确定、可复现
pd.set_option("display.width", 200)
pd.set_option("display.max_columns", None)

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 天价格序列 (模拟波段震荡走势)
    # 注意:30 根仅用于在有限篇幅内演示金叉/死叉的判定逻辑;EMA26 在此短样本上
    # 仍受初始值影响,真实计算必须按本讲上文所述向前预热 100~200 根 K 线后再取信号。
    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("==========================================================")

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']
==========================================================

👉 点击查看解析

本练习重点是基于MACD指标构建基础交易信号,理解DIF、DEA及柱线之间的关系,并掌握金叉、死叉等常见买卖点的判断逻辑。

本章小结

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

📋 行动清单 (Action Checklist)

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

—— 小象教研组

配套资料 · 直接下载

课件、代码、数据集等配套资料全部免费,点击即可直接下载,无需分享或解锁。

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