AlphaFeed Blog

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

分析与指标 · 代码验证于 2026-09-14

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

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

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

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

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

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

第 1 步:取复权日线

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

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 参数与含义:

参数含义常用取值
nRSV 周期9(经典 (9,3,3))
k_smoothK 的平滑周期3
d_smoothD 的平滑周期3
K/D 区间一般 0~100>80 超买、<20 超卖
J3K−2D可 <0 或 >100(灵敏,会溢出)

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

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 区间,属正常现象。

关键坑与注意事项

常见问题(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——但记住它是滞后摆动指标,会钝化,别单独当买卖信号。

相关链接:


免责声明:本文仅为技术与数据接口使用示例,代码与策略仅供学习研究,不构成投资建议。市场有风险,历史数据不代表未来表现。