第十九章 信息衰减与记忆效应
各位做量化交易的朋友,咱们今天聊一个特别实在的话题——信息衰减。说白了,就是一条消息、一个信号,它对市场的影响力能持续多久?
我刚开始做高频策略那会儿,总觉得抓到信号就得赶紧用,生怕错过了。后来发现,有些信号进去就亏,有些信号进去反而能拿几天。嗯,这里面的门道,就是信息衰减和记忆效应。
信息衰减函数
什么叫信息衰减?我举个例子你就明白了。
假设今天某只股票出了个利好公告。开盘瞬间,价格跳涨2%。然后呢?接下来几分钟、几小时、几天,这个利好还在影响价格吗?
答案是:影响力在逐渐减弱。就像往水里扔块石头,波纹会慢慢消失。
数学上,我们用一个衰减函数来描述这个过程:
# 信息衰减函数示例
def info_decay(t, half_life=10):
"""
t: 时间(分钟)
half_life: 半衰期(分钟)
"""
return 2 ** (-t / half_life)
# 看看衰减效果
for t in [0, 5, 10, 20, 30, 60]:
print(f"t={t}min, 剩余信息量={info_decay(t):.3f}")
输出结果:
t=0min, 剩余信息量=1.000
t=5min, 剩余信息量=0.707
t=10min, 剩余信息量=0.500
t=20min, 剩余信息量=0.250
t=30min, 剩余信息量=0.125
t=60min, 剩余信息量=0.016
你看,10分钟后信息量只剩一半,60分钟后几乎没了。这就是指数衰减。
核心观点:不同市场、不同品种的信息衰减速度完全不同。美股大盘股的信息衰减很快,几分钟就消化完了;小盘股、加密货币可能慢一些,能持续几小时甚至几天。
半衰期估计
半衰期这个概念,我是从物理学里借来的。它指的是信息量衰减到一半所需的时间。
怎么估计半衰期?我个人习惯用两种方法:
- 自相关函数法:计算时间序列的自相关,看它降到0.5时对应的时间滞后
- 拟合衰减曲线:直接用指数函数拟合实际数据
给你看个实际代码:
import numpy as np
import pandas as pd
def estimate_half_life(returns, max_lag=100):
"""
用自相关法估计半衰期
"""
# 计算自相关
autocorr = [returns.autocorr(lag=i) for i in range(1, max_lag+1)]
# 找到自相关降到0.5以下的位置
for i, ac in enumerate(autocorr):
if ac < 0.5:
return i + 1
return max_lag
# 举个实际例子
# 假设这是某只股票的分钟收益率
np.random.seed(42)
returns = pd.Series(np.random.randn(1000) * 0.001)
half_life = estimate_half_life(returns)
print(f"估计半衰期: {half_life} 分钟")
实战经验:我在做股指期货策略时发现,IF合约的分钟级收益率半衰期大约在3-5分钟。也就是说,一个信号出现后,5分钟之内必须进场,否则信息价值就大打折扣了。
长记忆模型(ARFIMA)
说到记忆效应,就不得不提ARFIMA模型。你可能听过ARIMA,ARFIMA是它的升级版。
为什么需要ARFIMA?因为传统的ARIMA假设数据是短记忆的——过去的影响会快速消失。但实际金融市场中,很多序列表现出长记忆特征。
什么叫长记忆?就是过去的信息会持续影响很久很久。比如波动率,今天的波动率跟一个月前的波动率还有关系。
ARFIMA模型的核心参数是d(差分阶数):
- d = 0:短记忆(白噪声)
- 0 < d < 0.5:长记忆(平稳)
- d = 0.5:单位根过程
- d > 0.5:非平稳
代码实现:
from statsmodels.tsa.arima.model import ARIMA
import numpy as np
# 模拟一个长记忆序列
def generate_arfima(n, d=0.3):
"""生成ARFIMA(0,d,0)序列"""
# 使用分数差分
np.random.seed(42)
eps = np.random.randn(n)
x = np.zeros(n)
# 简化版:用截断的MA(∞)表示
for t in range(1, n):
weight = 1.0
for k in range(1, min(t, 100)):
weight *= (k + d - 1) / k
x[t] += weight * eps[t - k]
x[t] += eps[t]
return x
# 生成数据
data = generate_arfima(1000, d=0.35)
# 拟合ARFIMA(这里用ARIMA近似)
model = ARIMA(data, order=(1, 0, 1))
result = model.fit()
print(result.summary())
注意:ARFIMA的估计比ARIMA复杂得多。我曾经在实盘中使用时,因为参数估计不准,导致策略回测表现很好但实盘一塌糊涂。后来我改用半参数方法估计d值,效果才稳定下来。
信息持久性分析
信息持久性,说白了就是看一个信号能持续多久。我把它分成三类:
| 类型 | 持续时间 | 典型例子 | 交易策略 |
|---|---|---|---|
| 瞬时信息 | 秒级到分钟级 | 订单簿失衡 | 高频做市 |
| 短期信息 | 分钟级到小时级 | 新闻事件 | 日内动量 |
| 长期信息 | 天级到周级 | 财报发布 | 趋势跟踪 |
怎么分析信息持久性?我常用的方法是:
- 计算Hurst指数:H > 0.5表示有持久性,H < 0.5表示均值回归
- 方差比检验:看不同时间尺度下方差的变化规律
- 谱分析:在频域中观察信息的分布
def hurst_exponent(ts):
"""计算Hurst指数"""
lags = range(2, 100)
tau = [np.sqrt(np.std(np.subtract(ts[lag:], ts[:-lag]))) for lag in lags]
# 拟合直线
poly = np.polyfit(np.log(lags), np.log(tau), 1)
return poly[0] / 2.0
# 测试
ts = np.random.randn(1000)
h = hurst_exponent(ts)
print(f"Hurst指数: {h:.3f}")
# 如果h接近0.5,说明是随机游走
# 如果h大于0.5,说明有趋势持久性
关键洞察:我个人经验是,大多数股票日收益率序列的Hurst指数在0.45-0.55之间,接近随机游走。但波动率序列的Hurst指数通常在0.7-0.9,表现出很强的长记忆特征。这就是为什么波动率预测比收益率预测更容易赚钱。
知识体系总览
下面这张图,是我自己整理的信息衰减与记忆效应的知识框架:
避坑指南:我曾经犯过一个错误——用日线数据估计半衰期,然后用在分钟级策略上。结果可想而知,信号早就衰减完了,我还傻乎乎地等。记住:时间尺度必须匹配。高频策略用高频数据,低频策略用低频数据。
最后说一句,信息衰减和记忆效应不是理论游戏。你想想看,如果你能准确知道一个信号能持续多久,你的进场时机、持仓时间、止损设置都会更精准。这就是信息含量分析的价值所在。