查看全课大纲(第 12 / 38 节)

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

约 2 分钟

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

基于MACD的交易信号开发(二):相切与粘合边界判定

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

在量化策略由理论公式走向实盘工程落地的过程中,最考验工程师功力的往往不是标准趋势下的常规计算,而是面对极端行情数据时的边界异常情况处理。在指标交叉信号的判定中,两条曲线恰好相等(相切 Tangency)或连续数日贴合波动(粘合 Cohesion)是造成回测与实盘信号漂移的经典工程隐患。

本讲紧承上一讲的 MACD 交叉原理,深入探讨指标曲线相切与粘合时的量化判定哲学、状态回溯机制与死区过滤算法,帮助开发者构建具备强鲁棒性的工业级信号检测器。


💡 核心导读

  • 相切(Tangency)是否算作交叉?
    • 策略定义差异:相切表示两条曲线数值相等(Δ=DIFF−DEA=0\Delta = DIFF - DEA = 0)。若随后同向反弹(并未真正穿透),是否触发买卖取决于交易者的风控偏好;
    • 严格过滤方案:若要求真正的趋势穿越,必须向前回溯历史有效方向(回溯至 t−2t-2 或更早的非零状态),仅在符号发生真正的正负反转(−1→+1-1 \to +1 或 +1→−1+1 \to -1)时才确认交叉。
  • 多根 K 线粘合(Cohesion)的工程治理:
    • 在窄幅横盘震荡行情中,快慢线可能连续多日处于极其微小的数值波动范围(受浮点数精度影响频繁在 0 附近跳变);
    • 治理手段:引入死区容差阈值(Deadband Tolerance)或确认延迟计数器,过滤微小噪音引起的虚假高频换手。
  • 信号状态机的完备性设计:
    • 量化系统切忌小觑”交叉”二字,必须保证在相切、粘合、数据缺失、浮点微差等全场景下具备确定性的逻辑闭环。
┌─────────────────────────────────────────────────────────────┐
│                    指标相切与粘合的判定逻辑                 │
└──────────────────────────────┬──────────────────────────────┘
                               │
 ┌─────────────────────────────┴─────────────────────────────┐
 ▼                                                           ▼
┌──────────────────┐                               ┌──────────────────┐
│ 相切反弹 (未穿透)│                               │   真正穿越 (穿透)│
├──────────────────┤                               ├──────────────────┤
│ t-1: DIFF < DEA  │                               │ t-1: DIFF < DEA  │
│ t  : DIFF == DEA │                               │ t  : DIFF == DEA │
│ t+1: DIFF < DEA  │                               │ t+1: DIFF > DEA  │
│ => 严格过滤,不触发│                               │ => 确认金叉,触发买入│
└──────────────────┘                               └──────────────────┘

一、指标相切与粘合的本质解析

1. 相切(Tangency)现象

在价格接近反转但动能不足时,快线 DIFFDIFF 往往向上触碰慢线 DEADEA 后再度拐头向下。在数学判定式中: DIFFt−1≤DEAt−1与DIFFt≥DEAtDIFF_{t-1} \le DEA_{t-1} \quad \text{与} \quad DIFF_t \ge DEA_t 如果条件写成 ≥\ge 或 ≤\le,相切点将被误判为金叉;若下一交易日再度回落,就会产生无意义的虚假开仓与滑点损耗。

2. 粘合(Cohesion)现象

在长时间的无趋势横盘中,DIFFDIFF 与 DEADEA 的差值可能在 10−6∼10−410^{-6} \sim 10^{-4} 之间徘徊。如果未设置浮点数死区,计算机底层的数值舍入误差可能导致买卖信号频繁来回震荡,严重干扰仓位管理。


二、鲁棒交叉检测器的工程实现方案

为杜绝边界相切与浮点微差导致的误触发,成熟量化系统通常采用如下状态机设计:

  1. 浮点死区截断(Tolerance Clean):对差值小于容差 ϵ\epsilon(如 10−510^{-5})的波动视为 0;
  2. 有效状态前向填充(Direction ffill):将相切点(0)替换为前一个非零的有效运动方向;
  3. 符号跃迁检测(Sign Shift Inversion):仅在有效方向由 −1-1 跃迁至 +1+1 时确认金叉,由 +1+1 跃迁至 −1-1 时确认死叉。

⚠️ 相切过滤是工程启发式:1e-5 容差、前向填充方向等规则都是人为设定的处理约定,换数据源或换品种可能需要调整;过滤能减少假信号,也可能误杀真突破。本节代码与输出均基于内置合成行情,仅演示信号的计算口径,不构成任何买卖建议,也不代表信号在真实市场的胜率或收益;技术指标在震荡市可能频繁假信号,信号参数(周期/阈值)过度贴合某段历史即过拟合,实盘还须计入滑点、佣金与冲击成本。回测偏差的系统讨论见 3.7、5.4。

📌 合规自查(回测/策略类内容的通用前提):幸存者偏差(回测样本必须包含当时在市、日后可能退市的全部标的,只在幸存股票上计算会虚增表现);前视偏差(未来函数)(当日收盘后得到的信息只能用于其后的交易决策,财报须按实际披露日对齐)。


📝 动手练一练

下面我们通过 Python 代码,实现一个具备相切过滤与死区容差能力的鲁棒交叉信号检测器,测试在指标相切并反弹的数据形态下能否精准杜绝误报:

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

def robust_cross_detector(series_fast, series_slow, tolerance=1e-5):
    """
    鲁棒的交叉信号检测器:
    妥善处理指标相切 (Tangency) 与 多日粘合 (Cohesion) 等极端边界情况
    """
    delta = series_fast - series_slow
    # 1. 消除浮点数微小精度误差,落入死区内的置为 0
    delta_clean = delta.apply(lambda x: 0.0 if abs(x) < tolerance else x)
    
    # 2. 计算方向符号: +1 (快线在上), -1 (快线在下), 0 (粘合/相切)
    sign = np.sign(delta_clean)
    
    # 3. 有效方向前向填充: 排除相切反弹与中途粘合
    valid_sign = sign.replace(0, np.nan).ffill().fillna(0)
    
    # 4. 严格边沿判定: 仅当方向真正跨越 0 轴时确认交叉
    strict_gold_cross = (valid_sign.shift(1) < 0) & (valid_sign > 0)
    strict_dead_cross = (valid_sign.shift(1) > 0) & (valid_sign < 0)
    
    df = pd.DataFrame({
        'Fast': series_fast,
        'Slow': series_slow,
        'Delta': delta_clean,
        'Strict_Gold': strict_gold_cross,
        'Strict_Dead': strict_dead_cross
    })
    return df

def test_tangency_case():
    dates = pd.date_range("2023-01-01", periods=6, freq="D")
    # 构造一条 Fast 与 Slow 在第 3、4 天连续相切但未向上穿透的价格序列
    fast = pd.Series([10.0, 9.5, 9.0, 9.0, 8.5, 8.0], index=dates)
    slow = pd.Series([11.0, 10.0, 9.0, 9.0, 9.5, 10.0], index=dates)
    
    res = robust_cross_detector(fast, slow)
    print("================ 指标相切与粘合异常检测 ================")
    print(res)
    print("-------------------------------------------------------")
    print(f"严格金叉触发次数: {res['Strict_Gold'].sum()} (成功过滤中途相切假信号)")
    print("=======================================================")
test_tangency_case()

运行结果输出:

================ 指标相切与粘合异常检测 ================
            Fast  Slow  Delta  Strict_Gold  Strict_Dead
2023-01-01  10.0  11.0   -1.0        False        False
2023-01-02   9.5  10.0   -0.5        False        False
2023-01-03   9.0   9.0    0.0        False        False
2023-01-04   9.0   9.0    0.0        False        False
2023-01-05   8.5   9.5   -1.0        False        False
2023-01-06   8.0  10.0   -2.0        False        False
-------------------------------------------------------
严格金叉触发次数: 0 (成功过滤中途相切假信号)
=======================================================

👉 点击查看解析

本练习的核心是利用 DIF 与 DEA 的差值、持续时间及粘合程度来区分“相切”与“粘合”边界,避免把短暂接触误判为有效交叉。代码演示的关键结论是:粘合边界往往对应窄幅震荡后的变盘窗口,需要结合后续分离方向确认交易信号。

本章小结

  1. 重视工程边界条件:简单的交叉判定在面对相切与粘合数据时极易产生虚假信号,必须设计明确的边界仲裁规则。
  2. 引入死区与状态回溯:使用容差阈值消除浮点精度抖动,使用有效方向前向回溯确认真实的符号反转。
  3. 保持逻辑自洽与完备:在编写量化信号函数时,切忌依赖偶然性假设,务必确保各类边缘用例均有确定性处理。

📋 行动清单 (Action Checklist)

  • 运行本讲鲁棒交叉检测代码,尝试将第 4 天 fast 改为 9.5,观察状态机能否正确触发严格金叉;
  • 在自己的技术指标计算模块中引入浮点死区截断机制(如 10−510^{-5});
  • 预习下一讲,学习摆动型指标代表 RSI 的相对强弱数学建模与超买超卖信号开发。

—— 小象教研组

配套资料 · 直接下载

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

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