
用 Python 揭秘均值回归策略:你的收益从何而来?
2026年重磅升级已全面落地!欢迎加入专注财经数据与量化投研的【数据科学实战】知识星球!您将获取持续更新的《财经数据宝典》与《量化投研宝典》,双典协同提供系统化指引;星球内含400篇以上独有高质量文章,深度覆盖策略开发、因子分析、风险管理等核心领域,内容基本每日更新;同步推出的「量化因子专题教程」系列(含完整可运行代码与实战案例),系统详解因子构建、回测与优化全流程,并实现日更迭代。我们持续扩充独家内容资源,全方位赋能您的投研效率与专业成长。无论您是量化新手还是资深研究者,这里都是助您少走弯路、事半功倍的理想伙伴,携手共探数据驱动的投资未来!
在量化交易的世界里,均值回归(Mean-Reversion) 是一种经典策略——它假设价格偏离均值后终将回归。但你有没有想过,这类策略的收益到底和股票本身的涨跌有多大关系?
最近,一篇来自 Medium 的技术分析文章用 Python 做了一项有趣的实证研究:通过分析 70 多只美股在不同行业板块中的表现,发现均值回归策略的日收益与股票日收益在 约 47% 的时间里高度相关。
本文将带你拆解这篇研究的核心思路、关键代码和结论,帮你理解均值回归策略背后的驱动逻辑。
均值回归的核心假设很简单:价格涨多了会跌,跌多了会涨。
具体实现方式是利用 Z-score(标准分数)来衡量当前价格偏离均值的程度:
策略使用 20 日滚动窗口 计算移动平均线和标准差。
文章特别强调了一个常见"陷阱":不要用累计收益率来计算相关性,而应该使用日收益率。 因为累计收益率会引入虚假的趋势性相关,导致结论失真。
正确做法是:
当 R² > 0.7 时,认为两者高度相关。
以下是均值回归策略的 Python 实现(基于 yfinance 和 pandas):
import numpy as npimport pandas as pdimport yfinance as yfimport matplotlib.pyplot as pltfrom scipy.stats import shapirodef mean_reversion_strategy(close, window: int = 20, z_entry=1.5, z_exit=0.0, fees=0.001): """均值回归策略函数""" df = pd.DataFrame({"close": close}) # 计算 20 日移动平均线和标准差(向前偏移 1 日,避免未来数据泄露) df["ma"] = df["close"].rolling(window).mean().shift(1) df["std"] = df["close"].rolling(window).std().shift(1) # 计算 Z-score:当前价格偏离均值的标准差倍数 df["zscore"] = (df["close"] - df["ma"]) / df["std"] # 根据 Z-score 生成交易信号 df["signal"] = 0 df.loc[df["zscore"] < -z_entry, "signal"] = 1 # Z-score 低于 -1.5,做多 df.loc[df["zscore"] > z_entry, "signal"] = -1 # Z-score 高于 1.5,做空 df.loc[df["zscore"].abs() < z_exit, "signal"] = 0 # Z-score 接近 0,平仓 # 使用前向填充来维持持仓状态 raw_signal = df["signal"].copy().astype(float) raw_signal[raw_signal == 0] = np.nan exit_mask = df["zscore"].abs() < z_exit raw_signal[exit_mask] = 0 df["position"] = raw_signal.ffill().fillna(0) # 计算日收益率 df["daily_return"] = df["close"].pct_change() # 计算交易成本 position_change = df["position"].diff().abs() df["trade_cost"] = position_change * fees # 策略日收益 = 持仓方向 × 股票日收益 - 交易成本 df["strategy_return"] = df["position"].shift(1) * df["daily_return"] - df["trade_cost"] # 累计收益率的日变化(用于后续相关性分析) df["cumulative_return"] = (1 + df["strategy_return"]).cumprod().pct_change() return df.dropna(subset=["cumulative_return"])文章对 8 个行业板块(科技、金融、医疗、消费、能源、工业、电信、其他)中的 70 多只股票进行了测试。
对于每只股票,计算 20 日滚动 R² 大于 0.7 的时间占比。以下是主要代码逻辑:
# 定义各行业股票池tickers = { "Tech": ["AAPL", "MSFT", "GOOGL", "AMZN", "NVDA", "META", "TSLA", "AVGO"], "Finance": ["JPM", "BAC", "WFC", "GS", "MS", "C", "BLK", "AXP", "V", "MA"], "Healthcare": ["JNJ", "UNH", "PFE", "MRK", "ABBV", "LLY", "TMO", "ABT"], "Consumption": ["WMT", "HD", "TGT", "COST", "LOW", "MCD", "SBUX", "NKE"], "Energy": ["XOM", "CVX", "COP", "SLB", "EOG", "MPC", "VLO", "PSX", "OXY"], "Industry": ["CAT", "DE", "HON", "GE", "MMM", "UPS", "FDX", "LMT", "RTX"], "Telecom": ["T", "VZ", "TMUS", "NFLX", "DIS", "CMCSA", "WBD"], "Other": ["BRK-B", "SPGI", "MCO", "ICE", "CME"]}list_list_distribution = []for sector in tickers.keys(): list_distribution = [] for ticker in tickers[sector]: # 下载过去 1 年的股价数据 data = yf.download(ticker, period="1y", auto_adjust=True, progress=False) # 计算股票日收益率(百分比) pct_change_asset = data["Close"].pct_change() * 100 # 运行均值回归策略 result = mean_reversion_strategy(data["Close"].squeeze()) # 计算 20 日滚动相关系数的平方(即 R²) rolling_corr = result["cumulative_return"].rolling(20).corr(pct_change_asset) # 统计 R² > 0.7 的时间占比 list_distribution.append( 100 * len([el for el in rolling_corr if el > 0.7]) / len(rolling_corr) ) list_list_distribution.append((list_distribution, sector))研究绘制了每个行业的直方图,展示 R² > 0.7 的时间占比分布情况。各行业的核心区间大致在 35%–60% 之间,表明不同行业的结果具有一致性。
将所有股票汇总后,使用 Shapiro-Wilk 检验 验证分布的正态性:
from scipy.stats import shapiro# 合并所有行业的分布数据list_total_distribution = []for el in list_list_distribution: list_total_distribution += el[0]np_total = np.array(list_total_distribution)# Shapiro-Wilk 正态性检验statistic, p_value = shapiro(list_total_distribution)print(f"检验统计量:{statistic:.4f}") # 结果:0.9930print(f"P 值:{p_value:.4f}") # 结果:0.9220# 输出分布参数print(f"均值:{np_total.mean():.2f}%") # 结果:47.07%print(f"标准差:{np_total.std():.2f}%") # 结果:9.25%检验结果表明(检验统计量 = 0.9930,P 值 = 0.9220,均接近 1),该分布高度符合正态分布,均值为 47.07%,标准差为 9.25%。
这个数字意味着:在大约一半的交易时间里,均值回归策略的日收益变化方向与股票本身的涨跌高度一致。
换句话说:
这提醒我们:均值回归策略并非独立于市场的"印钞机",它的收益来源在很大程度上依赖于底层股票的价格行为。
本文基于一项实证研究,带你用 Python 分析了均值回归策略收益与股票收益之间的关系。核心要点如下:
第一,用日收益率而非累计收益率来计算相关性。 这是避免虚假相关的关键。
第二,均值回归策略在约 47% 的时间里与股票日收益高度相关(R² > 0.7)。 这个比例在不同行业之间表现一致,且符合正态分布。
第三,策略并非"黑箱"。 理解收益来源有助于你判断策略在什么市场环境下有效、在什么环境下失效,从而做出更好的风控决策。
如果你正在学习 Python 量化交易,这个案例是一个很好的练手项目——它涵盖了数据获取(yfinance)、信号生成(Z-score)、滚动统计(rolling correlation)和统计检验(Shapiro-Wilk)等常用技能。
加入专注于财经数据与量化投研的知识星球【数据科学实战】,获取本文完整研究解析、代码实现细节。
2026年全面升级已落地!【数据科学实战】知识星球核心权益如下:
星球已沉淀丰富内容生态——涵盖量化文章专题教程库、因子日更系列、高频数据集、PyBroker实战课程、专家深度分享与实时答疑服务。无论您是初探量化的学习者,还是深耕领域的从业者,这里都是助您少走弯路、高效成长的理想平台。诚邀加入,共探数据驱动的投资未来!
好文推荐
1. 用 Python 打造股票预测系统:Transformer 模型教程(一)
2. 用 Python 打造股票预测系统:Transformer 模型教程(二)
3. 用 Python 打造股票预测系统:Transformer 模型教程(三)
4. 用 Python 打造股票预测系统:Transformer 模型教程(完结)
6. YOLO 也能预测股市涨跌?计算机视觉在股票市场预测中的应用
9. Python 量化投资利器:Ridge、Lasso 和 Elastic Net 回归详解
好书推荐