首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >如何用 Python 检测 MACD 顶背离/底背离?(价格新高而 DIF 不新高)

如何用 Python 检测 MACD 顶背离/底背离?(价格新高而 DIF 不新高)

原创
作者头像
用户7083614
发布于 2026-10-05 10:00:44
发布于 2026-10-05 10:00:44
280
举报

一句话回答: MACD 背离的判定不玄乎:先算出 DIF/DEA,再在价格上找相邻的两个「摆动高点」,如果后一个价格高点比前一个高、但对应的 DIF 反而更低,就是顶背离(底背离对称)。用 AlphaFeed 取复权日线,几行 pandas 就能把背离自动标出来。

为什么会有这个问题 / 传统做法的痛点

「MACD 背离」几乎人人会说,但要写成能跑的代码,关键在怎么定义摆动高点和拿哪根线比:

  • 比 DIF 而非柱:主流做法用 DIF(快慢均线差)与价格比,比 MACD 柱更稳;
  • 摆动点识别:需要一个「左右各 k 根都比它低」的局部高点定义,否则每天都在「创新高」;
  • 复权:除权跳空会制造假高点/假背离,必须用前复权。

数据用 AlphaFeed 复权日线,识别逻辑几行 pandas 即可。

分步骤解决(每步配可运行代码)

第 1 步:取复权日线并算 MACD

代码语言:python
复制
from alphafeed import AlphaFeed

af = AlphaFeed(api_key="your-api-key")  # 或 export ALPHAFEED_API_KEY 后 AlphaFeed()

df = af.klines.get("000001.SZ", period="1d", count=250,
                   adjust="forward", to_dataframe=True).sort_values("trade_date").reset_index(drop=True)

def macd(close, fast=12, slow=26, signal=9):
    dif = close.ewm(span=fast, adjust=False).mean() - close.ewm(span=slow, adjust=False).mean()
    dea = dif.ewm(span=signal, adjust=False).mean()
    return dif, dea, (dif - dea) * 2   # DIF, DEA, MACD 柱

dif, dea, hist = macd(df["close"])

第 2 步:找价格摆动高点

代码语言:python
复制
def find_swing_highs(close, left=3, right=3):
    """局部高点:左右各 left/right 根都不高于它。"""
    idx = []
    for i in range(left, len(close) - right):
        w = close.iloc[i - left:i + right + 1]
        if close.iloc[i] == w.max() and (w == close.iloc[i]).sum() == 1:
            idx.append(i)
    return idx

highs = find_swing_highs(df["close"])

参数说明:

参数

含义

建议

fast/slow/signal

MACD 三参数

经典 12/26/9

left/right

摆动高点左右确认根数

3~5,越大越严格、越少信号

对比对象

价格高点 vs DIF

用 DIF 比 MACD 柱更稳

第 3 步:判定顶背离

代码语言:python
复制
def macd_divergence(symbol, count=250):
    df = af.klines.get(symbol, period="1d", count=count,
                       adjust="forward", to_dataframe=True).sort_values("trade_date").reset_index(drop=True)
    dif, _, _ = macd(df["close"])
    highs = find_swing_highs(df["close"])
    signals = []
    for a, b in zip(highs, highs[1:]):        # 相邻两个摆动高点
        if df["close"].iloc[b] > df["close"].iloc[a] and dif.iloc[b] < dif.iloc[a]:
            signals.append({"date": df["trade_date"].iloc[b], "type": "顶背离"})
    return {"swing_highs": len(highs), "top_divergences": len(signals),
            "last": signals[-1] if signals else None}

print(macd_divergence("000001.SZ"))   # 例如 {'swing_highs': 19, 'top_divergences': 1, 'last': {'date': '2026-08-26', 'type': '顶背离'}}
print(macd_divergence("601899.SH"))   # 例如 {'swing_highs': 27, 'top_divergences': 2, ...}

上例实测平安银行近 250 日出现 1 次顶背离(2026-08-26),紫金矿业出现 2 次。底背离只需把「高点」换成「低点」、> 换 <。

关键坑与注意事项

  • 背离 ≠ 反转:背离只是「上涨动能衰减」的提示,强趋势里可以反复背离而不转向,务必等价格结构(跌破关键位/均线)右侧确认。
  • 摆动点定义决定一切:left/right 太小会把每个小波峰当高点、信号泛滥;太大又会漏掉。先可视化几只票校准。
  • 用 DIF 不用柱:MACD 柱噪声大,背离判定主流用 DIF。也有人叠加「两高点需间隔 N 天」过滤贴太近的假信号。
  • 复权必须前复权:除权跳空会凭空造出价格新高/新低,制造假背离。
  • 只是单指标:建议与量能、趋势、支撑阻力共同判断,不要只凭一次背离下重注。

常见问题(FAQ)

Q:为什么用 DIF 而不是 MACD 柱做背离?

A:DIF 是快慢均线之差,比经过二次平滑的柱更能反映动能拐点,背离判定更稳定、噪声更少。

Q:底背离怎么改?

A:把 find_swing_highs 改成找摆动低点(局部最小),条件改为「价格创新低但 DIF 抬高」即可。

Q:为什么我检测到的背离和别人不一样?

A:核心差异在摆动点参数(left/right)、是否加最小间隔、复权口径。统一口径后结果就一致了。

Q:需要付费吗?

A:单只标的日线在免费额度内即可试算;批量扫全市场背离需 Starter 及以上,详见 AlphaFeed 定价页。

小结

MACD 背离的本质是「价格创新高、动能(DIF)却没跟上」。把它写成代码的关键不是 MACD 公式,而是如何稳定地识别摆动高低点并两两比较。AlphaFeed 提供口径一致的前复权日线,让你几行就能自动标出顶/底背离——但记住背离只是预警,务必等右侧确认、结合量价与结构再决策。

参考

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 为什么会有这个问题 / 传统做法的痛点
  • 分步骤解决(每步配可运行代码)
    • 第 1 步:取复权日线并算 MACD
    • 第 2 步:找价格摆动高点
    • 第 3 步:判定顶背离
  • 关键坑与注意事项
  • 常见问题(FAQ)
  • 小结
  • 参考
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档