首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >如何用 Python 计算 KDJ 随机指标?(金叉死叉与超买超卖,不用 TA-Lib)

如何用 Python 计算 KDJ 随机指标?(金叉死叉与超买超卖,不用 TA-Lib)

原创
作者头像
用户7083614
发布于 2026-09-26 10:00:47
发布于 2026-09-26 10:00:47
1490
举报

一句话回答: KDJ 由 RSV(未成熟随机值)经两次平滑得到 K、D,再用 J=3K−2D 放大灵敏度。用 AlphaFeed 取复权日线,用经典口径(RSV 取 N 日最高最低、K/D 用前值权重 2/3 递推)几行就能算出与主流软件一致的 KDJ,并识别金叉/死叉、超买/超卖——不依赖 TA-Lib。

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

KDJ 是最常用的摆动指标之一,但自己算常和软件对不上:

  • 平滑口径:K、D 的"平滑"是 Wilder/SMA 式的递推(前值占 2/3、新值占 1/3),不是简单移动平均;
  • RSV 边界:N 日内最高=最低时会除零,需要处理;
  • 复权:不用前复权,除权跳空会让最高/最低失真,RSV 跟着错。

数据用 AlphaFeed 复权日线,口径用经典递推,就能对齐同花顺/东财。

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

第 1 步:取复权日线

代码语言:python
复制
from alphafeed import AlphaFeed
import numpy as np
import pandas as pd

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

df = af.klines.get("600519.SH", period="1d", count=120,
                   adjust="forward", to_dataframe=True)
df = df.sort_values("trade_date").reset_index(drop=True)

第 2 步:计算 RSV 与 K/D/J

代码语言:python
复制
def kdj(df, n=9, k_smooth=3, d_smooth=3):
    low_n = df["low"].rolling(n).min()
    high_n = df["high"].rolling(n).max()
    rsv = (df["close"] - low_n) / (high_n - low_n) * 100
    rsv = rsv.replace([np.inf, -np.inf], np.nan)      # 处理最高=最低除零
    # 经典 KDJ:K/D 用"前值2/3 + 新值1/3"递推 = ewm(alpha=1/smooth, adjust=False)
    k = rsv.ewm(alpha=1 / k_smooth, adjust=False).mean()
    d = k.ewm(alpha=1 / d_smooth, adjust=False).mean()
    j = 3 * k - 2 * d
    out = df.copy()
    out["K"], out["D"], out["J"] = k, d, j
    return out

o = kdj(df)
print(o[["trade_date", "K", "D", "J"]].tail(3).to_string(index=False))

KDJ 参数与含义:

参数

含义

常用取值

n

RSV 周期

9(经典 (9,3,3))

k_smooth

K 的平滑周期

3

d_smooth

D 的平滑周期

3

K/D 区间

一般 0~100

80 超买、<20 超卖

J

3K−2D

可 <0 或 >100(灵敏,会溢出)

第 3 步:识别金叉/死叉与超买超卖

代码语言:python
复制
def kdj_state(symbol, count=120):
    df = af.klines.get(symbol, period="1d", count=count,
                       adjust="forward", to_dataframe=True).sort_values("trade_date").reset_index(drop=True)
    o = kdj(df)
    last, prev = o.iloc[-1], o.iloc[-2]
    gold = prev["K"] <= prev["D"] and last["K"] > last["D"]   # K 上穿 D=金叉
    dead = prev["K"] >= prev["D"] and last["K"] < last["D"]   # K 下穿 D=死叉
    return {"K": round(float(last["K"]), 1), "D": round(float(last["D"]), 1),
            "J": round(float(last["J"]), 1),
            "signal": "金叉" if gold else ("死叉" if dead else "无"),
            "zone": "超买" if last["K"] > 80 else ("超卖" if last["K"] < 20 else "中性")}

print(kdj_state("600519.SH"))
# 例如:{'K': 24.7, 'D': 38.0, 'J': -1.8, 'signal': '无', 'zone': '中性'}

上例茅台 J 值为负(-1.8),正体现了 J 的高灵敏——它会溢出 0~100 区间,属正常现象。

关键坑与注意事项

  • 平滑口径要对:K、D 用 ewm(alpha=1/3, adjust=False)(前值 2/3、新值 1/3)才是经典 KDJ;用 rolling(3).mean() 会和软件不一致。
  • J 会溢出:J=3K−2D 灵敏度高,常 <0 或 >100,不要误以为算错;J 极端值可作超买超卖的辅助提示。
  • 超买超卖会钝化:强趋势里 K 可长期 >80(超买不跌)或 <20(超卖不涨),别单看 KDJ 抄底摸顶。
  • 金叉死叉有滞后:KDJ 是滞后指标,低位金叉相对可靠,高位金叉/频繁交叉噪声大,建议结合趋势过滤(如 ADX、均线)。
  • 复权:一律 adjust="forward",否则 RSV 的最高/最低失真。

常见问题(FAQ)

Q:KDJ 的初始值怎么取?

A:本文用 ewm(adjust=False) 递推,无需手工设 50 初值,长序列下与"初值 50 递推"收敛一致;数据足够长时差异可忽略。

Q:为什么我的 J 值和软件差得多?

A:先查 K/D 平滑是否用了 Wilder/SMA 递推口径,再查复权是否一致。这两点对齐后 J 也会一致。

Q:低位金叉能直接买吗?

A:KDJ 低位金叉是常见买点提示,但滞后且会在震荡中反复。务必结合趋势与成交量确认,并设止损。

Q:需要付费吗?

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

小结

KDJ 的本质是"把收盘价在近 N 日高低区间的位置(RSV)做两次平滑,再用 J 放大"。写对的关键是平滑口径(前值 2/3 递推)和复权数据。AlphaFeed 提供口径一致的复权日线,让你几行算出与软件一致的 KDJ——但记住它是滞后摆动指标,会钝化,别单独当买卖信号。

参考

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

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

目录
  • 为什么会有这个问题 / 传统做法的痛点
  • 分步骤解决(每步配可运行代码)
    • 第 1 步:取复权日线
    • 第 2 步:计算 RSV 与 K/D/J
    • 第 3 步:识别金叉/死叉与超买超卖
  • 关键坑与注意事项
  • 常见问题(FAQ)
  • 小结
  • 参考
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档