四种动量计算方式详解
在 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天前价格
今日价格
简单动量
实际走势
A
100
130
+30%
稳定上涨 ✅
B
80
104
+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
示例对比:
资产
年化收益率
R²
斜率动量得分
说明
A
50%
0.90
0.45
稳定上涨,信号可靠 ✅
B
80%
0.40
0.32
高收益但走势混乱
C
20%
0.95
0.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 个价格
回归方式
加权线性回归(近期权重更高)
加权线性回归(完全相同)
适用场景
收盘后调仓
日内固定时点调仓
V1 与 V2 两个版本
加权斜率动量(含分时版)目前有两个可选版本:不带后缀的
加权斜率 / 加权斜率(分时版)
(V1,历史实现)和带
"-V2"
后缀的修正版。两者年化收益率算法相同,区别在于 R² 的计算:V1 中回归拟合与 R² 计算所用的权重口径不一致,个别情况下会导致 R² 出现负值,使原本上涨的资产被打出负分(评分符号翻转);V2 统一了权重口径,修复了这个问题,评分更可靠。
详细的公式级对比参见:
斜率/加权斜率指标详解 · 加权斜率的两个版本
新建策略时建议优先选择 V2;已保存的存量策略不受影响,仍使用创建时选定的版本。
选择建议
短周期(≤ 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 动量的独特优势
微观结构视角
:通过最高价与最低价的关系,刻画市场的支撑强度与上涨弹性,而非仅看收盘价
历史标准化
:Z-Score 消除了不同标的之间的绝对值差异,使排名更公平
质量过滤
:R² 阈值和斜率上下限自动剔除异常信号,避免噪音干扰
五、四种方式综合对比
计算复杂度与信息量
简单动量 → 只用两个价格点,信息量最少
斜率动量 → 用全周期收盘价做回归,信息量中等
加权斜率动量 → 同上,但偏重近期,时效性更强
RSRS 动量 → 用全周期最高/最低价 + 历史标准化,信息量最丰富
适用场景速查
场景
推荐方式
快速筛选,计算量敏感
简单动量
中长期 ETF 轮动(60天以上)
斜率动量
短中期 ETF 轮动(30天以内)
加权斜率动量
对择时精度要求高的策略
RSRS 动量
多因子组合评分
混合使用以上多种
信号稳定性对比
当市场出现短期剧烈震荡时,四种动量的表现:
简单动量
:波动最剧烈,容易产生虚假信号
斜率动量
:线性回归平滑了噪音,信号较稳定
加权斜率动量
:近期敏感,对趋势转折反应更快,但震荡时也更容易误判
RSRS 动量
:Z-Score 标准化 + 质量过滤,综合稳定性最佳
六、总结
四种动量计算方式本质上是一个
从简到繁、从粗到精
的光谱:
简单动量
:快,粗糙,适合初步排序
斜率动量
:兼顾收益率与趋势稳定性,适合中长期策略
加权斜率动量
:在斜率动量基础上偏重近期,适合短中期策略
RSRS 动量
:利用价格微观结构与历史标准化,适合对精度要求更高的策略
在实际应用中,可以将多种动量指标组合使用,构建更全面的资产评分体系,以应对不同的市场风格。