【别再到处找免费股票数据API了:官方204个接口,32篇一次讲透 #09】MACD_KDJ还要自己算?4大技术指标一次拿

0 阅读5分钟

【别再到处找免费股票数据API了:官方204个接口,32篇一次讲透 #09】MACD_KDJ还要自己算?4大技术指标一次拿

系列:别再到处找免费股票数据API了:官方204个接口,32篇一次讲透|连载项目 · 纯 GET 取数 · 仅依赖 requests 适用:想做技术面选股 / 指标共振,但还在 pandas 里手搓 EMA、算 MACD 算到怀疑人生的读者;数据由官方公开接口提供。本篇给沪深A股「MACD / MA / BOLL / KDJ」4 个技术指标的端点地图、一次取全的代码、周期参数与字段结构的坑,全部只依赖 requests,所有示例均为演示数据,不构成投资建议。

1. 你将得到什么

读完这一篇,你能拿走四样东西:

  1. 一张分组地图:4 个技术指标端点按「趋势 / 均线 / 通道 / 摆动」分成 4 类;
  2. 一次取全的代码:/hs/history/macd 拿 MACD,/hs/history/kdj 拿 KDJ;
  3. 周期参数的取法:技术指标支持日 / 周 / 月,要传 period;
  4. 三个真实踩坑点,都是第一次用几乎一定会踩的。

代码全部自包含,复制进 .py 直接能跑,不依赖 numpy / pandas。

2. 本篇取数约定

  • 全部接口都是 GET + query 参数,token 放在查询串里(?token=xxx);
  • 统一基址 https://api.zhituapi.com;
  • 代码块里的 你的token 是占位符,换成你的 token 即可;
  • 所有接口路径均取自官方已验证文档,跨篇零重复。

3. 4 个端点分 4 类

先建立地图。技术指标类一共 4 个端点,按用途分:

类端点用途更新频率
趋势/hs/history/macdMACD(DIF / DEA / MACD 柱)每日盘后
均线/hs/history/ma移动平均(MA5 / MA10 / MA20 / MA60)每日盘后
通道/hs/history/boll布林带(上轨 / 中轨 / 下轨)每日盘后
摆动/hs/history/kdjKDJ(K / D / J)每日盘后

4. 核心模板函数

import requests, time

BASE = "https://api.zhituapi.com"
TOKEN = "你的token"

def _hit_key(d, *cands, default=None):
    if not isinstance(d, dict):
        return default
    for c in cands:
        if c in d and d[c] not in (None, "", "-", "null"):
            return d[c]
    low = {str(k).lower(): v for k, v in d.items()}
    for c in cands:
        v = low.get(str(c).lower())
        if v not in (None, "", "-", "null"):
            return v
    return default


def _to_float(v, default=None):
    try:
        if v in (None, "", "-", "null", "None"):
            return default
        return float(v)
    except (TypeError, ValueError):
        return default


def _get(path, params=None, timeout=10, retries=2, backoff=0.6, default=None):
    q = {"token": TOKEN}
    if params:
        q.update(params)
    last = ""
    for i in range(retries + 1):
        try:
            r = requests.get(BASE + path, params=q, timeout=timeout)
            if r.status_code == 200:
                try:
                    return r.json()
                except ValueError:
                    return default
            last = "HTTP %s %s" % (r.status_code, (r.text or "").strip()[:80])
        except Exception as e:
            last = "%s: %s" % (type(e).__name__, e)
        if i < retries:
            time.sleep(backoff * (i + 1))
    return {"_error": last}


# ---------- 封装(均需 code + period)----------
def fetch_macd(code, period="day"):
    return _get("/hs/history/macd", {"code": code, "period": period}, default=[])
def fetch_ma(code, period="day"):
    return _get("/hs/history/ma",   {"code": code, "period": period}, default=[])
def fetch_boll(code, period="day"):
    return _get("/hs/history/boll", {"code": code, "period": period}, default=[])
def fetch_kdj(code, period="day"):
    return _get("/hs/history/kdj",  {"code": code, "period": period}, default=[])


# ---------- 最新一日 MACD 三值 ----------
def latest_macd(code, period="day"):
    rows = fetch_macd(code, period)
    if isinstance(rows, dict) and "_error" in rows:
        return None, rows["_error"]
    row = (rows or [{}])[-1]
    return {
        "dif":  _to_float(_hit_key(row, "dif", "macd_dif", default=None)),
        "dea":  _to_float(_hit_key(row, "dea", "macd_dea", default=None)),
        "macd": _to_float(_hit_key(row, "macd", "macd_bar", default=None)),
    }, None


# ---------- 校验 ----------
def run_check():
    fake = [{"dif": "0.12", "dea": "0.08", "macd": "0.08"}]
    _orig = fetch_macd
    fetch_macd = lambda c, p="day": fake
    m, err = latest_macd("000001.SZ")
    fetch_macd = _orig
    assert err is None and m["dif"] == 0.12 and m["macd"] == 0.08

    # 周线也能取
    assert fetch_kdj("000001.SZ", "week") is not None
    print("校验通过")


if __name__ == "__main__":
    run_check()
    print("-" * 62)
    code = "000001.SZ"
    for name, fn in [("MACD", lambda: fetch_macd(code)),
                     ("MA",   lambda: fetch_ma(code)),
                     ("BOLL", lambda: fetch_boll(code)),
                     ("KDJ",  lambda: fetch_kdj(code))]:
        data = fn()
        if isinstance(data, dict) and "_error" in data:
            print("%-8s -> %s" % (name, data["_error"][:60]))
        else:
            print("%-8s -> %d 条" % (name, len(data) if isinstance(data, list) else 1))

5. 跑通示例

把上面的代码复制到本地,填入你的 token 即可直接运行:传入代码,latest_macd 取最新一日的 DIF / DEA / MACD 柱,4 个技术指标接口一次取全(各字段含义见前文各小节)。

6. 坑与注意事项

坑 1:技术指标要传 period,日 / 周 / 月口径不同。 4 个接口都支持 period=day/week/month,不传默认日线。周线 MACD 和日线 MACD 金叉位置完全不同,做中长期策略别误用日线,做短线别误用周线,参数传错信号会整反。

坑 2:MACD 返回三列,别只拿一列。 /hs/history/macd 返回 dif / dea / macd(柱)三列,金叉看 DIF 上穿 DEA、柱体看 macd。做共振别只存 macd 一列,否则金叉死叉判断不了。

坑 3:指标是盘后算好的,盘中是前一交易日值。 这 4 个技术指标都是每日盘后基于收盘序列计算,盘中调用拿到的是上一交易日的值,不是实时更新。做盘中指标信号要等收盘后重算,别在盘中拿它当实时触发。

7. 小结与下篇预告

本篇把沪深A股 4 个技术指标端点分成 4 类,latest_macd 一行取 DIF / DEA / MACD 柱,_to_float 处理指标数值。

下一篇:《【别再到处找免费股票数据API了:官方204个接口,32篇一次讲透 #10】财务报表三表去哪下?8个接口,资产负债表·利润表·现金流一次取》:用 /hs/fin 一组接口,把资产负债表 / 利润表 / 现金流量表 / 财务指标一次取全。

8. 免责声明

本文仅演示沪深A股技术指标数据的取数方法,所有代码示例均为演示数据,未含任何真实行情数值,不构成投资建议,亦不承诺收益。