
用 Python 揭秘均值回归策略:你的收益从何而来?
2026年重磅升级已全面落地!欢迎加入专注财经数据与量化投研的【数据科学实战】知识星球!您将获取持续更新的《财经数据宝典》与《量化投研宝典》,双典协同提供系统化指引;星球内含 500 篇以上独有高质量文章,深度覆盖策略开发、因子分析、风险管理等核心领域,内容基本每日更新;同步推出的「量化因子专题教程」系列(含完整可运行代码与实战案例),系统详解因子构建、回测与优化全流程,并实现日更迭代。我们持续扩充独家内容资源,全方位赋能您的投研效率与专业成长。无论您是量化新手还是资深研究者,这里都是助您少走弯路、事半功倍的理想伙伴,携手共探数据驱动的投资未来!
很多交易者并不是因为缺少策略想法而失败,而是因为把这些想法在不同资产、不同周期、不同市场环境下逐一验证时,流程变得缓慢、混乱且难以复用。如果你正在学习 Python 量化,你大概率遇到过这样的困境:写了一个不错的策略脚本,却要一遍遍手动改参数、换标的、对比结果,最后连自己都搞不清哪次跑出来的数据是对的。
本文将带你了解一套基于 vectorbt 的批量回测研究工作流,帮你把零散的脚本变成可重复执行的研究流程。文章配有完整代码案例,适合有一定 Python 基础、想系统化做策略研究的同学。
单文件、单标的的回测脚本在学习阶段没问题,但一旦进入真正的研究阶段,问题就来了:
一个成熟的研究工作流,应该包含:可读的策略库、批量运行器、参数优化输出、买入持有对比、CSV 汇总、净值图以及 HTML 看板。下面我们一步步用代码实现核心部分。
这是一个简单但实用的策略思路 —— 在 RSI 超卖时买入回调,但只在价格处于 50 日 EMA 上方(即趋势向上)时才入场,当 RSI 回升或趋势被破坏时离场。
import yfinance as yfimport vectorbt as vbtimport pandas as pdsymbol = "ETH-USD"# 下载近一年的日线数据data = yf.download(symbol, period="1y", interval="1d", auto_adjust=False)close = data["Close"]# 计算 14 周期 RSI 指标rsi = vbt.RSI.run(close, window=14).rsi# 计算 50 周期指数移动平均线,作为趋势过滤器ema = vbt.MA.run(close, window=50, ewm=True).ma# 入场条件:RSI 低于 35(超卖)且价格在 EMA 上方(趋势向上)entries = (rsi < 35) & (close > ema)# 离场条件:RSI 高于 60(回升)或价格跌破 EMA(趋势走坏)exits = (rsi > 60) | (close < ema)# 根据信号构建组合pf = vbt.Portfolio.from_signals( close, entries, exits, init_cash=10000, # 初始资金 fees=0.001, # 手续费率 slippage=0.0005, # 滑点 freq="1d")print(pf.stats()) # 打印组合统计指标pf.plot().show() # 绘制净值曲线这段代码的核心思路是:用趋势过滤器约束均值回归信号,避免在下跌趋势中盲目抄底。
策略好不好,得有参照物。下面这段代码在回测的同时计算了买入持有收益,并把关键指标整理成一张表,最后导出为 CSV。
import yfinance as yfimport vectorbt as vbtimport pandas as pdsymbol = "SPY"data = yf.download(symbol, period="1y", interval="1d", auto_adjust=False)close = data["Close"]rsi = vbt.RSI.run(close, window=14).rsiema = vbt.MA.run(close, window=50, ewm=True).maentries = (rsi < 35) & (close > ema)exits = (rsi > 60) | (close < ema)pf = vbt.Portfolio.from_signals( close, entries, exits, init_cash=10000, fees=0.001, slippage=0.0005, freq="1d")# 策略总收益率(百分比)strategy_return = pf.total_return() * 100# 买入持有收益率:用期末价格除以期初价格buy_hold_return = ((close.iloc[-1] / close.iloc[0]) - 1) * 100# 把关键指标整理成一行表格results = pd.DataFrame({ "Symbol": [symbol], "Strategy Return %": [strategy_return], "Buy Hold Return %": [buy_hold_return], "Sharpe": [pf.sharpe_ratio()], # 夏普比率 "Max Drawdown %": [pf.max_drawdown() * 100], # 最大回撤 "Total Trades": [pf.trades.count()] # 总交易次数})print(results)# 导出为 CSV,方便后续汇总分析results.to_csv("single_asset_backtest.csv", index=False)这样你就得到了一张清晰对比「主动策略 vs 被动持有」的结果表。
研究的真正提速来自批量化。与其一个个打开策略文件手动运行,不如让脚本自动遍历整个资产清单。
import subprocess# 待测试的资产清单:涵盖 ETF、个股、加密货币、商品、债券symbols = [ "SPY", "QQQ", "DIA", "IWM", "AAPL", "MSFT", "NVDA", "TSLA", "BTC-USD", "ETH-USD", "SOL-USD", "GLD", "SLV", "TLT"]period = "1y"interval = "1d"# 遍历每个标的,依次调用回测脚本for symbol in symbols: print("Running:", symbol) subprocess.run([ "python", "backtest_all_strategies.py", "--symbol", symbol, "--period", period, "--interval", interval ])print("All batch backtests complete.")借助这种批量运行器,你可以一次性测试股票、ETF、加密货币、外汇、商品、债券,甚至自定义的 OHLCV CSV 数据,并在每次运行后自动生成汇总与看板。
批量跑完之后,最有价值的就是一张策略优化看板。它通常会按优化后的总收益排序,标出表现最好的策略、最佳收益、买入持有基准、跑赢基准的策略数量,并配上「Top 收益柱状图」与「收益 vs 回撤散点图」。
例如在一次 ETH-USD 一年期的回测中,最佳策略的优化总收益可达 +188.28%,而同期买入持有为 -17.17%,40 个策略中有 36 个跑赢了基准。这种可视化对比,能让你迅速判断哪些策略真正具备研究价值。
对学习 Python 量化的同学来说,从「写脚本」升级到「搭工作流」是关键一步。本文展示了三个递进的核心环节:
需要强调的是,这类内容属于教育与研究范畴,不构成任何投资建议,也不保证实盘交易表现。回测漂亮不等于实盘赚钱,过拟合是量化研究最大的陷阱。把工具用好的同时,更要保持对结果的批判性思考。
动手把上面的代码跑一遍,你会对「系统化策略研究」有全新的体会。
加入专注于财经数据与量化投研的知识星球【数据科学实战】,获取本文完整研究解析、代码实现细节。
2026年全面升级已落地!【数据科学实战】知识星球核心权益如下:
星球已沉淀丰富内容生态——涵盖量化文章专题教程库、因子日更系列、高频数据集、PyBroker实战课程、专家深度分享与实时答疑服务。无论您是初探量化的学习者,还是深耕领域的从业者,这里都是助您少走弯路、高效成长的理想平台。诚邀加入,共探数据驱动的投资未来!
好文推荐
1. 用 Python 打造股票预测系统:Transformer 模型教程(一)
2. 用 Python 打造股票预测系统:Transformer 模型教程(二)
3. 用 Python 打造股票预测系统:Transformer 模型教程(三)
4. 用 Python 打造股票预测系统:Transformer 模型教程(完结)
6. YOLO 也能预测股市涨跌?计算机视觉在股票市场预测中的应用
9. Python 量化投资利器:Ridge、Lasso 和 Elastic Net 回归详解
好书推荐