Skip to content

四种动量计算方式详解

在 ETF 轮动等趋势跟踪策略中,动量是核心评分指标——它衡量的是一段时间内资产的上涨强度与趋势质量。次方量化平台提供四种动量计算方式,各有侧重,适用于不同的市场环境和策略诉求。

动量类型计算复杂度对趋势的刻画抗噪能力适用场景
简单动量⭐ 低只看涨跌幅快速筛选、短线参考
斜率动量⭐⭐ 中趋势方向 + 稳定性中长期趋势跟踪
加权斜率动量⭐⭐ 中偏重近期趋势 + 稳定性短中期趋势跟踪
RSRS 动量⭐⭐⭐ 高支撑/阻力弹性 + 标准化择时精度要求高的策略

一、简单动量

核心思想

最直观的动量计算方式:用当前价格相对 N 天前价格的涨跌幅来衡量动量强弱。涨得越多,动量越强。

计算公式

简单动量 = (P_当前 - P_N天前) / P_N天前

其中:

  • P_当前 — 最新收盘价
  • P_N天前 — N 个周期前的收盘价(momentum_period 参数控制)

计算步骤

第一步:取价格

python
current_price = df['close'].iloc[-1]    # 最新收盘价
past_price    = df['close'].iloc[-momentum_period]  # N 天前收盘价

第二步:计算涨跌幅

python
momentum = (current_price - past_price) / past_price

第三步:保留 4 位小数

python
return int(momentum * 10000) / 10000

特点分析

优点:

  • 计算简单、直观,无需复杂数学
  • 计算速度快,适合大规模标的快速排序

缺点:

  • 仅看"起点"和"终点",忽略了中间走势
  • 对极端值非常敏感:N 天前若恰好是某次暴跌低点,会虚高动量分数
  • 无法区分"稳健上涨"和"大起大落后持平"

示例:

资产N天前价格今日价格简单动量实际走势
A100130+30%稳定上涨 ✅
B80104+30%暴跌后缓慢反弹 ❌

两者得分相同,但 B 的实际走势远弱于 A。这正是简单动量的局限所在。

分时版(简单动量分时版)

与普通版的区别: 不再取 N 天前的收盘价,而是取 N 天前同一分钟时刻 M 的价格作为基准价,当前价格也同样取今日 M 时刻的价格。

计算公式

简单动量(分时版)= (P_今日M时刻 - P_N天前M时刻) / P_N天前M时刻

其中:

  • P_今日M时刻 — 今日 M 时间点(如 10:00)的分钟级价格,(实时动量计算工具取当前价格)
  • P_N天前M时刻 — N 个交易日前同一时间点 M 的分钟级价格

适用场景

  • 策略在日内固定时点执行调仓(如每日 10:00、14:30 等)
  • 希望避免使用收盘价,减少尾盘集中交易带来的滑点干扰
  • 基于日内同一时刻的价格序列进行动量比较,保持时间口径一致

二、斜率动量

核心思想

通过对对数价格做线性回归,用回归斜率代表趋势方向与速度,再用 R² 衡量趋势稳定性,最终综合评分:

斜率动量得分 = 年化收益率 × R²

相比简单动量,斜率动量同时考虑了趋势强度与趋势的可信度

计算步骤

第一步:获取收盘价并做对数转换

python
close_prices = df['close'].values[-momentum_period:]
y = np.log(close_prices)   # 对数价格
x = np.arange(len(y))      # 时间序列:[0, 1, 2, ..., N-1]

为什么用对数?

  • 对数收益率具有时间可加性,连续多日收益可以直接累加
  • 更好地处理复利效应,价格变化更接近正态分布

第二步:等权线性回归

python
slope, intercept = np.polyfit(x, y, 1)

对 N 个 (时间, 对数价格) 数据点拟合一条直线 y = slope × x + intercept

  • slope(斜率):每个交易日的对数收益率
  • intercept(截距):趋势线的起始位置

所有数据点权重相同,平等对待历史与近期数据。

第三步:将斜率年化

python
annualized_returns = math.exp(slope * 250) - 1
  • slope × 250 = 一年(250个交易日)的累计对数收益率
  • exp(...) - 1 = 将对数收益率转换为实际涨幅百分比

示例:slope = 0.002(每天0.2%的对数增长),则年化收益率 = exp(0.5) − 1 ≈ 64.87%

第四步:计算 R²(趋势拟合优度)

python
y_pred = slope * x + intercept

ss_residual = np.sum((y - y_pred) ** 2)   # 残差平方和
ss_total    = np.sum((y - np.mean(y)) ** 2)  # 总平方和

r_squared = 1 - (ss_residual / ss_total)

R² 的含义:

  • R² → 1:价格走势几乎完美贴合趋势线,趋势非常稳定
  • R² → 0:价格走势杂乱,趋势线几乎没有解释力

第五步:综合评分

python
slope_momentum = annualized_returns * r_squared
return int(slope_momentum * 10000) / 10000

示例对比:

资产年化收益率斜率动量得分说明
A50%0.900.45稳定上涨,信号可靠 ✅
B80%0.400.32高收益但走势混乱
C20%0.950.19趋势稳定但涨速慢

资产 A 综合得分最高,因为它兼具较高的收益率与趋势稳定性。

分时版(斜率动量分时版)

与普通版的区别: 不再使用过去 N 天的收盘价序列,而是取过去 N 个交易日中每天同一时间点 M 的分钟级价格,构成 N 个价格数据点后再做对数转换与线性回归。

计算步骤

第一步:获取每日 M 时刻价格并做对数转换

python
# 取过去 N 个交易日中每天 M 时刻(如 10:00)的价格
intraday_prices = [day_data.loc[M, 'price'] for day_data in last_N_days]
y = np.log(intraday_prices)   # 对数转换
x = np.arange(len(y))         # 时间序列:[0, 1, 2, ..., N-1]

后续步骤与普通斜率动量完全相同: 等权线性回归 → 斜率年化 → 计算 R² → 综合评分。

与普通斜率动量的对比

对比项斜率动量(普通版)斜率动量(分时版)
价格来源每日收盘价每日固定时刻 M 的分钟级价格
数据个数过去 N 天的 N 个收盘价过去 N 天中每天 M 时刻的 N 个价格
回归方式等权线性回归等权线性回归(完全相同)
适用场景收盘后调仓日内固定时点调仓

适用场景

  • 策略在日内固定时点(如每日开盘 30 分钟后)触发调仓信号
  • 希望动量评分与实际成交时刻的价格口径保持一致,避免收盘价与调仓价之间的偏差
  • 通过分时价格序列更精准地捕捉日内趋势的方向与稳定性

三、加权斜率动量

核心思想

与斜率动量完全相同,唯一的区别在于线性回归时为近期数据赋予更高权重,使动量评分更加偏重最近的价格走势。

权重:从 1 到 2 线性增长(最旧数据 → 最新数据)

与斜率动量的区别

对比项斜率动量加权斜率动量
数据权重所有时间点相同近期权重是早期的 2 倍
趋势敏感性中等更高(对近期变化反应更快)
抗噪能力较强略弱(更容易受近期波动影响)
适用周期中长期(60天以上)短中期(30天以内)

计算步骤

第一步:构造权重序列

python
weights = np.linspace(1, 2, len(y))
  • 最旧数据的权重 = 1.0
  • 最新数据的权重 = 2.0
  • 中间数据线性插值

直觉理解: 对 60 天的回看窗口,第 1 天的影响力是第 60 天的一半,系统认为近期走势比远期走势更能代表当前动量。

第二步:加权线性回归

python
slope, intercept = np.polyfit(x, y, 1, w=weights)

用带权重的最小二乘法拟合,近期数据对斜率的贡献更大。

第三步:年化收益率(与斜率动量相同)

python
annualized_returns = math.exp(slope * 250) - 1

第四步:加权 R²

python
y_pred = slope * x + intercept
weights = np.linspace(1, 2, len(y))

ss_residual = np.sum(weights * (y - y_pred) ** 2)
ss_total    = np.sum(weights * (y - np.mean(y)) ** 2)

r_squared = 1 - (ss_residual / ss_total)

注意:R² 的计算也需要加权,确保评估标准与回归过程一致。

第五步:综合评分(与斜率动量相同)

python
slope_momentum = annualized_returns * r_squared

分时版(加权斜率动量分时版)

与普通版的区别: 不再使用过去 N 天的收盘价序列,而是取过去 N 个交易日中每天同一时间点 M 的分钟级价格,构成 N 个价格数据点后再做对数转换与加权线性回归。

计算步骤

第一步:获取每日 M 时刻价格并做对数转换

python
# 取过去 N 个交易日中每天 M 时刻(如 10:00)的价格
intraday_prices = [day_data.loc[M, 'price'] for day_data in last_N_days]
y = np.log(intraday_prices)   # 对数转换
x = np.arange(len(y))         # 时间序列:[0, 1, 2, ..., N-1]

后续步骤与普通加权斜率动量完全相同: 构造线性权重序列 → 加权线性回归 → 斜率年化 → 计算加权 R² → 综合评分。

与普通加权斜率动量的对比

对比项加权斜率动量(普通版)加权斜率动量(分时版)
价格来源每日收盘价每日固定时刻 M 的分钟级价格
数据个数过去 N 天的 N 个收盘价过去 N 天中每天 M 时刻的 N 个价格
回归方式加权线性回归(近期权重更高)加权线性回归(完全相同)
适用场景收盘后调仓日内固定时点调仓

选择建议

  • 短周期(≤ 30 天):建议使用加权斜率动量,能更快响应近期趋势转变
  • 长周期(≥ 60 天):斜率动量更稳健,避免被短期波动误导
  • 可以同时计算两种动量,构建多周期评分体系:
python
score_short  = calculate_slope_momentum(df, 20, use_weighted_regression=True)
score_medium = calculate_slope_momentum(df, 60, use_weighted_regression=False)
final_score  = 0.6 * score_short + 0.4 * score_medium

四、RSRS 动量

核心思想

RSRS(Resistance Support Relative Strength,阻力支撑相对强度)是一种基于最高价与最低价之间关系的动量指标,并通过历史 Z-Score 标准化,使得跨标的、跨时期的比较更加客观。

详细原理参见:RSRS 指标详解

RSRS 动量得分 = 当期 RSRS 值相对过去历史分布的标准分(Z-Score)

计算步骤

第一步:确定所需数据长度

python
standardization_period = rsrs_period * 2
required_length = standardization_period + rsrs_period

RSRS 动量需要比其他动量更多的历史数据:

  • rsrs_period:计算单期 RSRS 值的回看窗口(即用于线性回归的天数)
  • standardization_period:用于历史标准化的 RSRS 值个数(= rsrs_period × 2)
  • required_length:总共所需的最少历史数据长度

第二步:计算每日 RSRS 值序列

对每个时间点 i,取过去 rsrs_period 天的数据做以下计算:

以最低价(Low)为自变量 X,最高价(High)为因变量 Y,进行线性回归:

python
mean_low  = np.mean(window_low)
mean_high = np.mean(window_high)

cov     = np.mean((window_low - mean_low) * (window_high - mean_high))
var_low = np.mean((window_low - mean_low) ** 2)

slope = cov / var_low   # 回归斜率 β

计算 R²:

python
ss_res = np.sum((window_high - (mean_high + slope * (window_low - mean_low))) ** 2)
ss_tot = np.sum((window_high - mean_high) ** 2)

r_squared = 1 - (ss_res / ss_tot)

计算当日 RSRS 值(仅在通过质量过滤后赋值):

python
# 过滤极端斜率(排除异常市场)和低拟合度(排除无规律窗口)
if (slope_lower_limit <= slope <= slope_upper_limit) and (r_squared >= r_squared_threshold):
    rsrs_values[i] = slope * r_squared

RSRS 原始值 = 斜率 × R²,同时考虑了支撑/阻力关系的强度与可信度。

第三步:取当前 RSRS 值

python
current_rsrs = rsrs_values[-1]

若当前值为 NaN(数据不足或未通过质量过滤),则返回 0。

第四步:Z-Score 标准化

python
rsrs_for_std = rsrs_values[-(standardization_period + 1):-1]  # 不含当前值
valid_rsrs   = rsrs_for_std[~np.isnan(rsrs_for_std)]

mean_rsrs = np.mean(valid_rsrs)
std_rsrs  = np.std(valid_rsrs)

standardized_rsrs = (current_rsrs - mean_rsrs) / std_rsrs

Z-Score 的意义:

Z-Score = (当期 RSRS - 历史均值μ) / 历史标准差σ
  • Z > 0:当前趋势强度高于历史均值
  • Z > 1.5:趋势处于历史极强水平,可能超买
  • Z < −1.5:趋势处于历史极弱水平,可能超卖
  • 标准化后的得分无量纲,可以直接跨标的比较

RSRS 动量的独特优势

  1. 微观结构视角:通过最高价与最低价的关系,刻画市场的支撑强度与上涨弹性,而非仅看收盘价
  2. 历史标准化:Z-Score 消除了不同标的之间的绝对值差异,使排名更公平
  3. 质量过滤:R² 阈值和斜率上下限自动剔除异常信号,避免噪音干扰

五、四种方式综合对比

计算复杂度与信息量

简单动量   → 只用两个价格点,信息量最少
斜率动量   → 用全周期收盘价做回归,信息量中等
加权斜率动量 → 同上,但偏重近期,时效性更强
RSRS 动量  → 用全周期最高/最低价 + 历史标准化,信息量最丰富

适用场景速查

场景推荐方式
快速筛选,计算量敏感简单动量
中长期 ETF 轮动(60天以上)斜率动量
短中期 ETF 轮动(30天以内)加权斜率动量
对择时精度要求高的策略RSRS 动量
多因子组合评分混合使用以上多种

信号稳定性对比

当市场出现短期剧烈震荡时,四种动量的表现:

  • 简单动量:波动最剧烈,容易产生虚假信号
  • 斜率动量:线性回归平滑了噪音,信号较稳定
  • 加权斜率动量:近期敏感,对趋势转折反应更快,但震荡时也更容易误判
  • RSRS 动量:Z-Score 标准化 + 质量过滤,综合稳定性最佳

六、总结

四种动量计算方式本质上是一个从简到繁、从粗到精的光谱:

  1. 简单动量:快,粗糙,适合初步排序
  2. 斜率动量:兼顾收益率与趋势稳定性,适合中长期策略
  3. 加权斜率动量:在斜率动量基础上偏重近期,适合短中期策略
  4. RSRS 动量:利用价格微观结构与历史标准化,适合对精度要求更高的策略

在实际应用中,可以将多种动量指标组合使用,构建更全面的资产评分体系,以应对不同的市场风格。

蜀ICP备20013273号-1 | 返回主站