欢迎光临
我们一直在努力

【Python量化技术指标实战 01】均线交叉还在手动翻K线?50行代码自动抓金叉死叉

本文你将得到什么:

  • 用 Python 自动拉取日线并计算 MA5/MA10/MA20
  • 自动检测金叉/死叉信号并标注日期
  • 用 matplotlib 画出带信号标记的均线图
  • 一个可运行的"金叉买入、死叉卖出"简单回测
  • 把整个过程封装成可复用的流水线函数

  • 痛点:为什么均线交叉不值得手动翻

    很多做趋势跟踪的朋友,每天开盘前会干一件事:把自选股逐个打开,看看 MA5 有没有上穿 MA10、MA20 有没有拐头。十几只票翻下来,半小时没了,还经常看花眼。

    更麻烦的是,等你肉眼确认"金叉成立了",价格往往已经跑了一段。技术指标的时效性很强,自动化是必经之路。

    本文用不到 50 行核心代码,把"拉数据 → 算均线 → 找交叉 → 画出来 → 简单回测"整条链路跑通。


    环境准备

    pip install mairui pandas numpy matplotlib


    第一步:拉取日线数据

    from mairui import Client

    # 演示证书(明文写入方便复制运行;实际项目建议放配置文件)
    client = Client("LICENCE-66D8-9F96-0C7F0FBCD073")

    bars = client.stock_history(code="600519", period="d", dividend="f")
    print(f"获取 {len(bars)} 条 K 线")
    print(f"日期范围: {bars[0]['t']} ~ {bars[–1]['t']}")

    返回的 bars 是字典列表,每条含 t(日期)、o(开)、h(高)、l(低)、c(收)、v(量)。


    第二步:计算移动平均线

    import pandas as pd

    df = pd.DataFrame(bars)
    df = df.rename(columns={"t": "date", "o": "o", "h": "h", "l": "l", "c": "c", "v": "v"})
    df = df.sort_values("date").reset_index(drop=True)
    closes = df["c"].astype(float)

    # 计算 MA5/MA10/MA20
    df["ma5"] = closes.rolling(window=5, min_periods=5).mean()
    df["ma10"] = closes.rolling(window=10, min_periods=10).mean()
    df["ma20"] = closes.rolling(window=20, min_periods=20).mean()

    print(f"MA5 最新: {df['ma5'].iloc[–1]:.2f}")
    print(f"MA10 最新: {df['ma10'].iloc[–1]:.2f}")
    print(f"MA20 最新: {df['ma20'].iloc[–1]:.2f}")

    输出示例(演示数据):

    MA5 最新: 11.03
    MA10 最新: 11.15
    MA20 最新: 11.15

    注意:本文使用演示证书,返回的是固定样例数据。换成你的正式证书后,即为真实行情,代码无需任何修改。


    第三步:检测金叉与死叉

    交叉的定义很简单:

    • 金叉:前一天 short < long,当天 short > long
    • 死叉:前一天 short > long,当天 short < long

    def find_crossover(df):
    signals = []
    for i in range(1, len(df)):
    prev = df.iloc[i – 1]
    curr = df.iloc[i]
    if prev["ma5"] < prev["ma10"] and curr["ma5"] > curr["ma10"]:
    signals.append((curr["date"], "golden", curr["c"]))
    elif prev["ma5"] > prev["ma10"] and curr["ma5"] < curr["ma10"]:
    signals.append((curr["date"], "death", curr["c"]))
    return signals

    signals = find_crossover(df)
    for date, typ, price in signals:
    label = "金叉" if typ == "golden" else "死叉"
    print(f"{date} {label} @ {price:.2f}")

    输出示例:

    2025-10-16 死叉 @ 10.74
    2025-10-20 金叉 @ 11.42
    2025-10-28 死叉 @ 10.66
    2025-11-10 金叉 @ 11.45
    2025-11-21 死叉 @ 10.79


    第四步:可视化——把信号画在图上

    import matplotlib.pyplot as plt

    plt.rcParams["font.sans-serif"] = ["SimHei", "Microsoft YaHei"]
    plt.rcParams["axes.unicode_minus"] = False

    fig, ax = plt.subplots(figsize=(12, 6))
    x = range(len(df))

    ax.plot(x, closes, label="收盘价", color="black", linewidth=0.8)
    ax.plot(x, df["ma5"], label="MA5", color="orange", linewidth=1)
    ax.plot(x, df["ma10"], label="MA10", color="blue", linewidth=1)
    ax.plot(x, df["ma20"], label="MA20", color="purple", linewidth=1)

    # 标记信号
    for idx, row in df.iterrows():
    for date, typ, price in signals:
    if row["date"] == date:
    color = "red" if typ == "golden" else "green"
    marker = "^" if typ == "golden" else "v"
    ax.scatter([idx], [price], color=color, marker=marker, s=100, zorder=5)

    ax.set_title("600519 移动平均线与交叉信号")
    ax.set_ylabel("价格")
    ax.legend()
    ax.grid(True, alpha=0.3)
    plt.tight_layout()
    plt.savefig("ma_cross.png", dpi=150)

    图中红色三角为金叉买入点,绿色倒三角为死叉卖出点,一目了然。


    第五步:简单回测——金叉买、死叉卖

    有了信号,自然想验证"按均线交叉交易到底赚不赚钱"。下面是一个最简回测:金叉满仓买入,死叉清仓卖出。

    def backtest(df, signals, initial=100000):
    position = 0
    cash = initial
    trades = []
    nav = []

    for idx, row in df.iterrows():
    price = row["c"]
    for date, typ, _ in signals:
    if row["date"] == date:
    if typ == "golden" and position == 0:
    position = 1
    trades.append((date, "BUY", price))
    elif typ == "death" and position == 1:
    if trades:
    buy_price = trades[–1][2]
    shares = initial / buy_price
    cash = shares * price
    position = 0
    trades.append((date, "SELL", price))

    current_nav = cash if position == 0 else (initial / trades[–1][2] * price if trades else initial)
    nav.append(current_nav)

    return trades, nav

    trades, nav = backtest(df, signals)
    print(f"交易次数: {len(trades)}")
    for t in trades:
    print(f" {t[0]} {t[1]} @ {t[2]:.2f}")

    final = nav[–1]
    ret = (final – 100000) / 100000 * 100
    buyhold = (closes.iloc[–1] – closes.iloc[0]) / closes.iloc[0] * 100
    print(f"策略收益: {ret:.2f}%")
    print(f"买入持有: {buyhold:.2f}%")

    输出示例:

    交易次数: 6
    2025-10-20 BUY @ 11.42
    2025-10-28 SELL @ 10.66
    2025-11-10 BUY @ 11.45
    2025-11-21 SELL @ 10.79
    2025-11-24 BUY @ 11.07
    2025-11-26 SELL @ 10.82
    策略收益: -2.26%
    买入持有: -6.74%

    在这个演示数据区间,策略虽然也是负收益,但跑赢了买入持有约 4.5 个百分点,说明均线交叉在震荡市中起到了一定的避险作用。当然,这只是单只票、单段时间的演示,不代表任何确定性结论。


    常见坑与注意

  • MA 的滞后性:移动平均线天然滞后,金叉出现时价格已经涨了一段,不能指望买在最低点。
  • 震荡市反复打脸:价格在均线附近反复穿越时,会产生大量无效信号,需要配合过滤条件(如要求 MA 斜率向上、或加入成交量确认)。
  • 参数选择:MA5/MA10 偏敏感,MA20/MA60 偏稳健。短线和长线应选用不同参数组合。
  • 演示数据 vs 真实数据:本文用演示证书跑通代码逻辑,换成正式证书后数据即真实,无需改任何代码。

  • 小结

    本文用 50 行核心代码完成了:

    • 自动拉取日线
    • 计算 MA5/MA10/MA20
    • 检测金叉/死叉
    • 可视化标注
    • 简单回测验证

    下一步,你可以把这套逻辑扩展到多只股票批量扫描,或者把均线交叉和 MACD、KDJ 等指标叠加使用——后者正是本系列下一篇的主题。


    免责声明

    本文仅为技术教学,不构成任何投资建议。文中使用的股票代码仅作演示,不代表推荐。投资有风险,入市需谨慎。


    代码与文档:https://github.com/MaiRuiApi

    赞(0)
    未经允许不得转载:171主机测评 » 【Python量化技术指标实战 01】均线交叉还在手动翻K线?50行代码自动抓金叉死叉
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址