在物理学中,牛顿第一定律告诉我们:物体在没有受到外力作用时,会保持匀速直线运动状态。
在金融市场中,这种现象同样存在,我们称之为动量效应(Momentum Effect)。简单来说,就是“强者恒强”——过去一段时间涨得好的股票,在未来一段时间继续上涨的概率较大。
今天,我们就来硬核拆解量化交易中最经典的策略之一:截面动量策略(Cross-Sectional Momentum)。我们将从数学定义出发,一步步用Python搭建一个完整的策略回测框架。
01 什么是动量?背后的数学逻辑
动量策略的核心假设是价格具有“惯性”。在学术界,Jegadeesh和Titman在1993年发表的论文奠定了动量策略的基础。
数学定义
假设我们在时刻 tt,想要衡量资产 ii 在过去 JJ 个月(Lookback Period)的动量。通常我们计算其累积收益率。
定义
为资产i 在时刻 tt 的价格,那么该资产的动量可以表示为:
💡 注意:细心的读者可能发现,我们计算的是从 t-J-1到t-1的收益,特意剔除了最近一个月(t-1到t)。这是量化中的一个Important Trick:短期反转效应。短期内(1个月)涨得太猛的股票往往会有回调压力,因此剔除最近一个月能显著提高动量策略的稳定性。这就是经典的 "12-1 Momentum"(回顾过去12个月,剔除最近1个月)。策略构建公式
在截面动量中,我们在每个调仓日,对所有资产按动量值排序。
假设资产池中有 NN 只股票,我们构建一个多头组合,持有动量排名靠前的 KK 只股票。那么资产i的权重
02 策略逻辑流程图
在写代码之前,我们需要理清逻辑:
- 数据获取
- 因子计算
- 信号生成
- 回测执行
03 Python代码实战
下面我们使用 pandas 和 numpy 来实现一个简易的向量化回测。为了方便大家复现,我们使用随机生成的模拟数据(实际应用中请替换为 tushare 或 yfinance 数据)。
第一步:环境准备与数据模拟
import numpy as npimport pandas as pdimport matplotlib.pyplot as pltimport seaborn as sns# 设置绘图风格plt.style.use('ggplot')sns.set_palette("husl")# 1. 模拟生成5只股票,1000个交易日的价格数据np.random.seed(42)dates = pd.date_range(start='2020-01-01', periods=1000)tickers = ['Stock_A', 'Stock_B', 'Stock_C', 'Stock_D', 'Stock_E']# 模拟随机漫步价格returns = pd.DataFrame(np.random.normal(0.0005, 0.02, (1000, 5)), index=dates, columns=tickers)prices = (1 + returns).cumprod() * 100print("--- 价格数据前5行 ---")print(prices.head())
第二步:计算动量因子
我们将使用 60日动量(近似3个月),并且为了简化演示,暂不剔除最近一个月(如果想剔除,可以使用 .shift(20))。
第二步:计算动量因子我们将使用 60日动量(近似3个月),并且为了简化演示,暂不剔除最近一个月(如果想剔除,可以使用 .shift(20))。
第三步:生成持仓信号
逻辑:每天持有动量值最大的 2只 股票。
# 3. 生成持仓信号# rank(axis=1) 对每一行(每天)的股票进行排名,method='min'rank_df = momentum_factor.rank(axis=1, ascending=False)# 选取排名前2的股票,标记为1(持有),否则为0long_position = (rank_df <= 2).astype(int)# 即使是动量策略,通常也是按月调仓,但为了演示向量化回测,# 我们这里假设每天都根据昨天的动量调整持仓(注意:实盘中这会产生巨额手续费)# 信号必须滞后一天,因为今天的收盘价算出的动量只能用于明天的交易position = long_position.shift(1).fillna(0)
第四步:计算策略收益
# 4. 计算策略收益# 假设等权重持有选中的2只股票# 每日策略收益 = sum(个股次日收益 * 持仓权重) / 持仓数量strategy_returns = (returns * position).sum(axis=1) / 2# 计算基准收益(买入并持有所有股票的平均收益)benchmark_returns = returns.mean(axis=1)# 计算累计净值strategy_cum = (1 + strategy_returns).cumprod()benchmark_cum = (1 + benchmark_returns).cumprod()
04 结果可视化
05 风险提示与总结
动量策略虽然经典,但并非完美的“圣杯”。在实战中,你需要注意以下几点:
- 动量崩溃(Momentum Crash)在市场剧烈反转(如熊市见底反弹)时,前期跌幅大的垃圾股往往反弹最猛,而抗跌的动量股补跌,导致策略回撤巨大。
- 换手率与手续费动量策略需要频繁换仓。如果按周或按月调仓,交易成本会显著侵蚀利润。务必在代码中加入
cost 扣除逻辑。 - 参数过拟合Lookback Period选3个月、6个月还是12个月?需要通过参数敏感性测试来确定,切忌只选表现最好的参数。
量化交易不是黑魔法,而是将逻辑代码化、将风险可视化的过程。