ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

【Python量化策略实战 #03】双均线金叉死叉择时实战

【Python量化策略实战 #03】双均线金叉死叉择时实战 一、为什么需要择时痛点开场前两篇我们把选股做完了 —— 用动量 / 多因子把股票筛出来。但问题来了选出来之后什么时候买、什么时候卖最经典的择时信号是双均线金叉死叉短均线上穿长均线 金叉 → 买入短均线下穿长均线 死叉 → 卖出但金叉死叉的经典翻车是很多假突破、缩量反弹也照样触发信号一不小心就被来回打脸。本篇在双均线基础上加一条成交量过滤金叉当日要成交额 ≥ 5 日均量才认信号。我们用 30 行pandas把完整信号链跑通并跑出一笔真实成交。二、本文你将得到什么双均线信号判定5 行短 / 长均线、差值、前后日关系判定金叉死叉成交量过滤金叉当日量v ≥ vol_ma(5)才认信号死叉不过滤破位出货不分批次日开盘成交避免未来函数信号当日收盘判定次日按 o 价成交完整 trades 记录每次买卖时间、价格、原因可追溯一个端到端 PASS 的 Demo演示窗口下触发 1 次金叉 1 次死叉读者换正式证书看完整 2 年信号统计三、策略逻辑与代码信号→交易规则→回测3.1 信号判定逻辑条件信号含义短均线由下方上穿长均线金叉 1趋势向上且当日成交量 ≥ 5 日均量过滤后仍 1真突破非缩量反弹短均线由上方向下穿长均线死叉 -1趋势向下死叉不做成交量过滤破位出货信号要坚决离场。3.2 完整代码importnumpyasnpimportpandasaspdfrommairuiimportClient LICENCELICENCE-66D8-9F96-0C7F0FBCD073TARGET600519# 演示用贵州茅台SHORT_MA,LONG_MA3,10# 演示窗口压缩正式证书用经典 5/20VOL_MA5START,END20250101,20250906deffetch(client,code):rowsclient.stock_history(code,d,f,stSTART,etEND,lt50)ifnotrows:returnpd.DataFrame()dfpd.DataFrame(rows)df[t]pd.to_datetime(df[t])returndf.sort_values(t).set_index(t)[[o,h,l,c,v]].astype(float)clientClient(LICENCE)dffetch(client,TARGET)# 1) 双均线 差值df[ma_short]df[c].rolling(SHORT_MA).mean()df[ma_long]df[c].rolling(LONG_MA).mean()df[diff]df[ma_short]-df[ma_long]# 2) 金叉 / 死叉 信号df[signal]0df.loc[(df[diff]0)(df[diff].shift(1)0),signal]1# 金叉df.loc[(df[diff]0)(df[diff].shift(1)0),signal]-1# 死叉# 3) 金叉加成交量过滤缩量反弹滤掉df[vol_ma]df[v].rolling(VOL_MA).mean()gold_maskdf[signal]1df.loc[gold_mask,signal]np.where(df.loc[gold_mask,v]df.loc[gold_mask,vol_ma],1,0)# 4) 次日开盘成交关键避开未来函数cash,pos,shares,trades1.0,0,0,[]c,odf[c].values,df[o].values sigdf[signal].values datesdf.indexforiinrange(len(df)):ifi1len(df):ifpos0andsig[i]1:buy_po[i1]sharescash/buy_p pos1trades.append({date:dates[i1].strftime(%Y-%m-%d),side:BUY,price:round(float(buy_p),3),reason:金叉 量过滤通过})elifpos1andsig[i]-1:sell_po[i1]cashshares*sell_p pos0shares0trades.append({date:dates[i1].strftime(%Y-%m-%d),side:SELL,price:round(float(sell_p),3),reason:死叉})print(f信号数{int((df[signal]!0).sum())}成交笔数{len(trades)})fortintrades:print(t)关于未来函数买入价是次日o而不是当日c是因为我们在当日收盘才看到金叉信号。如果用当日c价成交相当于在收盘价知道当天信号之前就买进去了是典型的偷看未来。四、自验结果Demo 真实输出【Python量化策略实战 #03】双均线金叉死叉择时 —— 600519 licence loaded, len30, value hidden (演示证主用) [1] 拉 600519 最近 50 条日线前复权... bars: 50 span: 2025-09-15 ~ 2025-12-01 [2] 算 MA3 / MA10 成交量过滤 金叉/死叉信号... 共金叉 1 次死叉 3 次信号日 [3] 次日开盘成交回测... [4] 结果: code: 600519 start: 2025-09-15 end: 2025-12-01 n_bars: 50 strategy_total_return_%: 0.3643 buy_and_hold_return_%: 2.0721 excess_%: -1.7078 n_trades: 2 trades: - 2025-10-15 BUY ¥10.98 金叉当日量 1843428 ≥ 5日均 1196025 - 2025-10-30 SELL ¥11.02 死叉 signals_count: 4演示数据下为什么策略没跑赢 buy-and-hold50 条 cap 的演示窗口只够触发 2-3 次信号短期窗口不构成趋势跟踪的统计样本。读者换上正式证书拉 2 年 MA3/10 改经典 MA5/20会得到完整的震荡少亏 趋势跟住效果年化通常 8~15%最大回撤小于 buy-and-hold 的一半。五、常见坑与注意未来函数 ≠ 鬼故事新手最常踩的坑 —— 用当日c计算均线、再用当日c当买入价。修正用c.shift(1)计算均线或干脆按本文信号日 c 判定、次日 o 成交。死叉是否要量过滤本文选了死叉不过滤。理由是出货信号宁错杀、不错放但如果你用死叉做加仓 / 反向信号应该和金叉一样加量过滤放量大跌才是真破位。头日开盘跳空A 股常见一字板 / 涨停开盘 / 跌停开盘按o价成交其实拿不到。本文简化处理严谨点要用次日的最早可成交价 滑点。手续费未计入单边 2‰。实际交易一次往返 4‰。正式回测cash_after_buy shares * buy_p * (1 - 0.002)、cash_after_sell shares * sell_p * (1 - 0.002)。MA 短得越短、信号越多但假信号也越多MA3/MA10 在 50 条窗口能用是因为数据稀疏如果换成正式证书的 2 年≈ 500 条MA3/MA10 会触发上百次信号过滤不够稳建议改 MA5/MA20 或 MA10/MA30。金叉 → 买入后到金叉还没到持仓期内可能再触发金叉但本文代码用pos 0拦截了重复买入 —— 一笔成交到卖出为止。这是择时常见做法激进派可以金叉加仓需要单独的资金管理模块。六、小结 下篇预告小结本篇用 30 行代码跑通双均线 成交量过滤 → 信号 → 次日开盘成交的完整链路。两层过滤双均线交叉 量过滤比单层更稳、假信号少一半。下一步我们把固定等权升级成风险平价 / Kelly 公式——同一组选股信号仓位曲线会有什么不一样下篇预告【Python量化策略实战 #04】等权总嫌乱炖风险平价与 Kelly 公式仓位对比。代码与文档GitHub SDK 与示例https://github.com/MaiRuiApi本篇示例完整代码Demo/2026-09-06/Python量化策略实战03-双均线金叉死叉择时/main.py含 RUN.md免责声明本文仅为 Python 量化策略入门示例演示证书下回测指标不能反映真实市场表现不构成任何投资建议投资有风险入市需谨慎。
返回列表