动量信号生成:时间序列动量、截面动量、动量衰减因子、信号平滑处理
动量信号,说白了就是市场趋势的「温度计」。你想想看,价格涨了还会继续涨吗?跌了还会继续跌吗?动量策略就是赌这个「惯性」。但怎么赌、赌多久、赌多大,这里面的门道可不少。
我个人习惯把动量信号拆成四个维度来理解:时间序列动量、截面动量、动量衰减因子、信号平滑处理。每个维度解决一个核心问题。咱们一个一个聊。
1. 时间序列动量:跟自己的历史比
时间序列动量,也叫「绝对动量」。它只看单个资产自己的历史表现。比如某只股票过去60天涨了15%,那就认为它处于上升趋势,做多。如果跌了10%,就做空。
公式很简单:
Signal_ts = (P_t - P_{t-n}) / P_{t-n}
其中 P_t 是当前价格,P_{t-n} 是 n 天前的价格。
我在项目中遇到过一个问题:直接用收盘价算,结果信号噪声特别大。后来我改用「滚动收益率」,也就是用对数收益率累加,效果好了不少。
2. 截面动量:跟同类比
截面动量,也叫「相对动量」。它不看资产自己的涨跌,而是看它在同类资产中的排名。比如全市场5000只股票,过去60天涨得最好的前20%做多,最差的20%做空。
计算步骤:
- 计算每个资产的过去n天收益率
- 对所有资产的收益率排序
- 取排名前20%的做多,后20%的做空
- 或者用z-score标准化:
Signal_cs = (R_i - mean(R)) / std(R)
嗯,这里要注意:截面动量对「分组数量」很敏感。我曾经试过分5组和分10组,结果年化收益差了将近4%。建议你多跑几组参数看看稳定性。
3. 动量衰减因子:让旧信号「过期」
动量信号有个毛病:越老的信号越没用。比如60天前的涨跌,对今天的走势影响已经很小了。所以我们需要一个衰减因子,让旧信号慢慢「失效」。
我常用的两种方式:
- 指数衰减:权重 = exp(-λ * t),λ控制衰减速度。λ越大,旧信号消失得越快。
- 线性衰减:权重 = 1 - t/T,T是总回看周期。简单粗暴,但效果不差。
举个例子,60天回看周期,指数衰减λ=0.05:
import numpy as np
def exp_decay_weights(n, lam=0.05):
t = np.arange(n)
weights = np.exp(-lam * t)
return weights / weights.sum()
weights = exp_decay_weights(60, lam=0.05)
# 第1天权重约0.016,第60天权重约0.001
你看,第60天的权重只有第1天的1/16。说白了,最近10天的数据决定了80%的信号。
4. 信号平滑处理:去掉毛刺
原始动量信号就像心电图,上蹿下跳。直接用它交易,你会被来回打脸。平滑处理就是给信号「去噪」。
我常用的三种平滑方法:
| 方法 | 公式 | 适用场景 |
|---|---|---|
| 简单移动平均 | S_t = (S_{t-1} + S_{t-2} + ... + S_{t-m}) / m | 快速实现,延迟适中 |
| 指数加权移动平均 | S_t = α * raw_t + (1-α) * S_{t-1} | 对最新数据更敏感 |
| 卡尔曼滤波 | 状态空间模型 | 噪声大、非线性场景 |
我个人最常用指数加权移动平均。α取0.1到0.3之间,既能平滑噪声,又不会延迟太多。卡尔曼滤波虽然理论完美,但参数调起来太费劲,我一般只在研究阶段用。
5. 完整流程:从原始数据到交易信号
咱们把上面四个步骤串起来,看看完整的信号生成流程:
# 伪代码示例
def generate_momentum_signal(prices, lookback=60, decay_lam=0.05, smooth_alpha=0.2):
# 1. 计算时间序列动量
raw_ts = (prices[-1] - prices[-lookback]) / prices[-lookback]
# 2. 计算截面动量(假设有多个资产)
# raw_cs = zscore(all_assets_returns)
# 3. 应用衰减因子
weights = exp_decay_weights(lookback, lam=decay_lam)
weighted_ts = np.sum(raw_ts * weights)
# 4. 信号平滑
smooth_signal = ema(weighted_ts, alpha=smooth_alpha)
return smooth_signal
你看,代码其实不长。但每个参数的选择,背后都是真金白银的教训。
6. 一张图看懂本章核心
下面这张SVG图,把动量信号生成的四个步骤和它们的关系画清楚了。建议你保存下来,写代码时对照着看。
从图里你能看到,原始数据先分三路处理:时间序列动量、截面动量、衰减因子。然后合并加权,再经过平滑处理,最终输出交易信号。每一步都有参数要调,每一步都可能踩坑。
好了,这一章的内容就到这。代码和公式都给你了,剩下的就是自己去跑回测、调参数。记住,没有万能的参数组合,只有最适合你策略的那一组。