← 返回博客列表

【量化系统从零构建 #14】择时(上):均线交叉·多均线 + MACD金叉死叉 + 动量反转

2026年09月09日 08:48 · 智兔数服 · 量化系统从零构建

摘要:【量化系统从零构建 #14】择时(上):均线交叉·多均线 + MACD金叉死叉 + 动量反转 系列:《量化系统从零构建》|连载项目 · 纯 GET 取数 · 仅依赖 requests 适用:想解决「

系列:《量化系统从零构建》|连载项目 · 纯 GET 取数 · 仅依赖 requests
适用:想解决「单标的何时进出」的读者;数据由智兔数服提供,在 #10/#11 指标上生成买卖信号:均线交叉、MACD 金叉死叉、动量反转,不依赖任何行情终端,也不发起网络请求。

1. 你将得到什么

  • ma_cross:快慢均线交叉信号,金叉 1 / 死叉 -1 / 其余 0,前 slow-1None
  • macd_cross:DIF/DEA 交叉信号,金叉 1 / 死叉 -1
  • momentum_reversal:动量反转预警,超买 -1 / 超卖 1,作为反向参考。
  • 本篇交付:单标的择时信号三件套,#15 把它们和资金面/情绪组合成综合择时。

2. 本篇取数约定

本篇是策略层,不发起网络请求,吃 #09 复权后的 close 序列(或外部传入)。数据来自 智兔数服(www.zhituapi.com)。指标计算纯 Python,不引 numpy/pandas。

3. 信号定义

信号 触发 含义
均线金叉 快线上穿慢线 看多(1)
均线死叉 快线下穿慢线 看空(-1)
MACD 金叉 DIF 上穿 DEA 看多(1)
MACD 死叉 DIF 下穿 DEA 看空(-1)
动量反转 近 window 涨跌超阈值 超买-1 / 超卖+1

4. 核心模板函数

import sys


def _sma(series, n):
    out = []
    for i in range(len(series)):
        if i < n - 1:
            out.append(None)
        else:
            out.append(sum(series[i - n + 1:i + 1]) / n)
    return out


def _ema(series, n):
    if not series:
        return []
    k = 2 / (n + 1)
    out = [series[0]]
    for i in range(1, len(series)):
        out.append(series[i] * k + out[i - 1] * (1 - k))
    return out


def _macd(close, fast=12, slow=26, signal=9):
    ef, es = _ema(close, fast), _ema(close, slow)
    dif = [ef[i] - es[i] for i in range(len(close))]
    dea = _ema(dif, signal)
    return dif, dea


def ma_cross(close, fast=5, slow=20):
    """快慢均线交叉:1 金叉 / -1 死叉 / 0 其它;前 slow-1 为 None。"""
    f, s = _sma(close, fast), _sma(close, slow)
    out = []
    for i in range(len(close)):
        if f[i] is None or s[i] is None:
            out.append(None); continue
        if i == 0 or f[i - 1] is None or s[i - 1] is None:
            out.append(0); continue
        if f[i - 1] <= s[i - 1] and f[i] > s[i]:
            out.append(1)
        elif f[i - 1] >= s[i - 1] and f[i] < s[i]:
            out.append(-1)
        else:
            out.append(0)
    return out


def macd_cross(close, fast=12, slow=26, signal=9):
    """DIF/DEA 交叉:1 金叉 / -1 死叉 / 0 其它;前 slow-1 为 None。"""
    dif, dea = _macd(close, fast, slow, signal)
    out = []
    for i in range(len(close)):
        if dif[i] is None or dea[i] is None:
            out.append(None); continue
        if i == 0 or dif[i - 1] is None or dea[i - 1] is None:
            out.append(0); continue
        if dif[i - 1] <= dea[i - 1] and dif[i] > dea[i]:
            out.append(1)
        elif dif[i - 1] >= dea[i - 1] and dif[i] < dea[i]:
            out.append(-1)
        else:
            out.append(0)
    return out


def momentum_reversal(close, window=20, thr=0.3):
    """动量反转:近 window 收益超 thr 为超买(-1),低于 -thr 为超卖(1),否则 0。"""
    out = []
    for i in range(len(close)):
        if i < window:
            out.append(None); continue
        ret = close[i] / close[i - window] - 1
        out.append(-1 if ret > thr else (1 if ret < -thr else 0))
    return out


def run_check():
    # 合成:先涨后跌再涨,非真实行情
    close = [10,11,12,13,14,15,16,17,18,19,20,19,18,17,16,15,16,17,18,19,20,21,22,23,24]
    sig = ma_cross(close, 5, 20)
    assert len(sig) == len(close)
    assert all(v is None for v in sig[:19])      # 前 slow-1 无信号
    # 针对性验证 ma_cross 能识别金叉/死叉(短序列 fast=2 slow=3)
    sc = ma_cross([1, 2, 3, 4, 5, 4, 3, 2, 3, 4, 5], 2, 3)
    assert 1 in sc and -1 in sc
    mc = macd_cross(close)
    assert len(mc) == len(close)
    assert 1 in mc and -1 in mc                  # MACD 应出现金叉与死叉
    mr = momentum_reversal(close, window=20)
    assert mr[20] is not None and mr[-1] is not None
    print("校验通过")


if __name__ == "__main__":
    if len(sys.argv) > 1 and sys.argv[1] == "--check":
        run_check()
    else:
        print("本篇基于 adj_close 序列计算,不发起网络;用 #09 的 clean 输出喂入即生成信号。")

5. 跑通示例

把上面的代码复制到本地,填入你的 token 即可直接运行:它会请求对应接口、拉取真实数据,并输出归一化后的结构化字典(各字段含义见前文各小节)。

6. 坑与注意事项

  1. 信号在 adj_close 上算:未复权价有除权断崖,交叉信号会假触发。
  2. None 要跳过:前段为 None,实盘取「最近一个非 None 信号」驱动交易。
  3. 金叉不等于必涨:均线是滞后指标,震荡市会频繁假交叉,需 #15 多信号共振。
  4. 动量反转是反向:超买给 -1 是「预警回撤」,不是立刻做空,配合仓位管理用。

7. 小结与下篇预告

本篇交出单标的择时三件套(均线 / MACD / 动量反转)。下一步把它们和资金面、市场情绪组合成综合择时。

下一篇计划写 #15《择时(下):北向资金跟随·涨跌停连板情绪·综合择时打分》:把 #14 信号叠加北向资金流与涨跌停情绪,做多信号投票的综合择时打分。

8. 免责声明

本文仅演示择时信号的算法,所有代码示例均以合成数据校验,未含任何真实数据;文中示例数据仅作演示用途,不构成投资建议,亦不承诺收益。


免费领取证书
数据来自 智兔数服(www.zhituapi.com):零 SDK、纯 GET、免费版即可起步。

领取路径:进入 www.zhituapi.com → 点击「请求证书」→「证书获取」→「免费版」(邮箱验证 3 步即可拿到 token)。

把代码里的 你的智兔token 换成你拿到的真实 token,上面的脚本就能直接打印均线交叉与MACD金叉死叉信号数据。

想亲自试一下?免费获取证书