1. 这节究竟解决什么实际问题?¶
1.11 AR(1) 随机过程与均值回归 的具体任务是:通过 AR(1) 系数与半衰期判断序列更像趋势延续还是均值回归。 本节将明确输入数据、计算过程、输出及其在后续研究中的用途。
2. 前置知识¶
会使用百分比和基础代数;建议先完成环境配置。 对公式的理解应包括变量定义、单位、时间索引和适用条件。
3. 数据说明¶
示例优先使用仓库固定的日频复权收盘价;它不是实时行情,也不代表完整市场。 运行前先检查 shape、日期范围、列名与缺失值。数据看起来能画图,不代表它适合回答研究问题。
4. 学习目标与完成标准¶
完成本节后,你应能用自己的话解释 1.11 AR(1) 随机过程与均值回归 的输入、计算步骤、输出和局限;尤其能说明:通过 AR(1) 系数与半衰期判断序列更像趋势延续还是均值回归。 你还应能独立改动一个参数并解释结果为什么变化,指出至少一个会让结论失真的假设。
5. 核心概念与公式¶
价格表示资产在特定时点的水平,收益率表示两个时点之间的相对变化。多数跨资产比较使用收益率。
所有公式都先说明分子、分母、单位与时间尺度;年化前必须确认数据频率。 看到公式时依次确认:每个符号的单位是什么?它属于哪个时点?分母会不会为零?它是描述性统计量、预测量,还是交易规则?
6. 从零实现¶
原始代码按照“准备输入 → 计算中间量 → 得到结果 → 解释输出”的顺序组织。每个单元应检查变量类型、索引、维度和代表性数值。中间变量用于核对公式实现和定位计算错误。
7. 成熟库实现¶
NumPy/Pandas 帮你算数和对齐索引;统计库帮你估计参数,但不替你解释经济含义。 使用库函数前先阅读参数含义、默认值和返回对象;库输出一个数字,并不说明这个数字适合你的交易假设。
8. 两种实现的差异¶
从零实现便于核对公式、调试和识别隐含假设;成熟库适合在计算逻辑已验证后复用。两种实现依赖相同的数据口径与时点假设,使用库函数不会改变输入数据的质量。
9. 预期结果与检查范围¶
你应看到维度正确的 Series/DataFrame、日期单调递增的索引,以及能支持“通过 AR(1) 系数与半衰期判断序列更像趋势延续还是均值回归。”这一任务的表格或图形。金融日收益率均值通常接近 0;若出现极大的连续收益、空表、全 NaN 或索引错位,应先排查数据和对齐逻辑,而不是立即相信结果。
10. 常见错误与诊断¶
把百分比和小数混用、忘记 dropna、把日频波动率直接叫作年化波动率、把相关性当因果。
诊断顺序:先打印类型与 shape,再看 head()/tail(),接着检查日期和 NaN,最后才比较数值。这样能避免在错误的对象上反复改参数。
11. 研究偏差检查¶
概念演示也要避免事后选择样本或只展示支持结论的时间段。 结果至少应与一个简单基线比较,并明确哪些部分只是教学演示。
12. 三层练习与答案¶
- 基础练习:验证一个中间变量、补全一段小计算,并用一句话解释输出。
- 研究练习:改变窗口、样本区间、约束或标的,记录哪些结论仍成立。
- 开放项目:把本节方法嵌入模块项目,报告基线、失败结果和限制。
题目在 ../exercises/01_financial_concepts/11_ar1_processes_exercises.ipynb;完整推导、可运行参考实现与结果检查在 ../solutions/01_financial_concepts/11_ar1_processes_solutions.ipynb。请先独立作答,再打开答案。
13. 延伸阅读¶
延伸材料:Investments(Bodie, Kane, Marcus)。阅读记录应包括研究假设、数据频率、样本范围和结论适用条件。
14. 下一节¶
完成本模块后,进入下一模块的概览页,并把本节的检查清单带到后续研究中。
import numpy as np
import pandas as pd
import statsmodels.api as sm
import matplotlib.pyplot as plt
from scipy import stats
np.random.seed(42)
print('Libraries loaded')
Libraries loaded
import matplotlib.pyplot as plt
# 1. 设置系统自带的中文字体(这里使用黑体 SimHei)
plt.rcParams['font.sans-serif'] = ['SimHei'] # 如果你想用微软雅黑,可以改成 ['Microsoft YaHei']
# 2. 解决更换字体后,负号(-)显示为方块的问题
plt.rcParams['axes.unicode_minus'] = False
1. AR(1) 过程定义¶
$$X_t = \mu + \phi (X_{t-1} - \mu) + \epsilon_t, \quad \epsilon_t \sim N(0, \sigma^2)$$
- $\mu$:长期均值(均值回归的「引力中心」)
- $\phi$:自回归系数($|\phi| < 1$ 时过程平稳)
- 平稳条件:$|\phi| < 1$
量化金融意义:
- $\phi$ 接近 1 → 接近随机游走(趋势跟踪)
- $\phi$ 接近 0 → 快速回归均值(均值回归策略)
- $\phi < 0$ → 过度震荡(每期都过度修正)
# 演示不同 phi 值的 AR(1) 轨迹
np.random.seed(42)
n = 300
mu = 100
sigma = 1
fig, axes = plt.subplots(2, 2, figsize=(14, 8))
phi_values = [0.95, 0.5, 0.0, -0.5]
titles = ['φ=0.95(接近随机游走)', 'φ=0.5(缓慢均值回归)',
'φ=0.0(白噪音)', 'φ=-0.5(振荡均值回归)']
for ax, phi, title in zip(axes.flat, phi_values, titles):
X = np.zeros(n)
X[0] = mu
for t in range(1, n):
X[t] = mu + phi * (X[t-1] - mu) + np.random.normal(0, sigma)
ax.plot(X, color='steelblue', lw=1)
ax.axhline(mu, color='red', linestyle='--', lw=1.5, label=f'μ={mu}')
ax.set_title(title); ax.legend(fontsize=8); ax.grid(alpha=0.3)
plt.suptitle('AR(1) 过程:不同 φ 值的影响', fontsize=13)
plt.tight_layout(); plt.show()
print('AR(1) 均值回归半衰期:')
print(f"{'φ':>8s} {'半衰期(天)':>15s} {'适合策略':>20s}")
print('-' * 50)
for phi in [0.99, 0.95, 0.90, 0.80, 0.60, 0.20]:
hl = -np.log(2) / np.log(abs(phi))
strategy = '趋势跟踪' if phi > 0.9 else ('缓慢均回' if phi > 0.6 else '快速均回')
print(f'{phi:>8.2f} {hl:>15.1f} {strategy:>20s}')
AR(1) 均值回归半衰期:
φ 半衰期(天) 适合策略
--------------------------------------------------
0.99 69.0 趋势跟踪
0.95 13.5 趋势跟踪
0.90 6.6 缓慢均回
0.80 3.1 缓慢均回
0.60 1.4 快速均回
0.20 0.4 快速均回
3. 实际应用:估计配对交易价差的 AR(1) 参数¶
# 模拟一对协整股票的价差(AR(1) 均值回归过程)
np.random.seed(42)
phi_true = 0.85
mu_true = 0
sigma_true = 0.5
n = 252
spread = np.zeros(n)
for t in range(1, n):
spread[t] = mu_true + phi_true*(spread[t-1]-mu_true) + np.random.normal(0, sigma_true)
# OLS 估计 AR(1) 参数
df = pd.DataFrame({'y': spread[1:], 'x': spread[:-1]})
result = sm.OLS(df['y'], sm.add_constant(df['x'])).fit()
phi_hat = result.params['x']
mu_hat = result.params['const'] / (1 - phi_hat)
half_life = -np.log(2) / np.log(abs(phi_hat))
print(f'真实 φ: {phi_true:.3f} 估计 φ: {phi_hat:.4f}')
print(f'真实 μ: {mu_true:.3f} 估计 μ: {mu_hat:.4f}')
print(f'估计均值回归半衰期: {half_life:.1f} 天')
plt.figure(figsize=(12, 4))
plt.plot(spread, color='steelblue', lw=1.2)
plt.axhline(mu_hat, color='red', linestyle='--', lw=1.5, label=f'估计均值 μ={mu_hat:.3f}')
plt.axhline(mu_hat + 2*spread.std(), color='orange', linestyle=':', label='±2σ 开仓线')
plt.axhline(mu_hat - 2*spread.std(), color='orange', linestyle=':')
plt.title(f'配对交易价差 AR(1) 模型(φ={phi_hat:.3f}, 半衰期={half_life:.1f}天)')
plt.legend(); plt.grid(alpha=0.3); plt.show()
真实 φ: 0.850 估计 φ: 0.8264 真实 μ: 0.000 估计 μ: -0.0236 估计均值回归半衰期: 3.6 天
4. Ornstein-Uhlenbeck 过程(连续时间 AR(1))¶
AR(1) 的连续时间版本是 Ornstein-Uhlenbeck(OU)过程:
$$dX_t = \kappa(\theta - X_t)dt + \sigma dW_t$$
- $\kappa$:均值回归速度(越大越快)
- $\theta$:长期均值
- $\sigma$:波动率
对应 AR(1) 中:$\phi \approx e^{-\kappa \Delta t}$,从而 $\kappa = -\ln(\phi)/\Delta t$
# OU 过程参数与 AR(1) 的对应
phi = 0.85
dt = 1/252 # 日频
kappa = -np.log(phi) / dt
print(f'AR(1) φ={phi} 对应 OU 过程 κ={kappa:.2f} (年化均值回归速度)')
print(f'半衰期: {np.log(2)/kappa*252:.1f} 天 = {np.log(2)/kappa:.2f} 年')
# 模拟 OU 过程
np.random.seed(42)
T_years = 2
np.random_steps = int(T_years * 252)
kappa_sim = 3.0 # 年化均值回归速度
theta = 0.0
sigma_ou = 0.5
X = np.zeros(252)
for t in range(1, 252):
dX = kappa_sim * (theta - X[t-1]) * dt + sigma_ou * np.sqrt(dt) * np.random.randn()
X[t] = X[t-1] + dX
print(f'OU 模拟: kappa={kappa_sim}, 半衰期={(np.log(2)/kappa_sim*252):.0f}天')
AR(1) φ=0.85 对应 OU 过程 κ=40.95 (年化均值回归速度) 半衰期: 4.3 天 = 0.02 年 OU 模拟: kappa=3.0, 半衰期=58天
练习¶
- 对 A/H 股溢价率序列(同一家公司的 A 股 vs 港股)进行 AR(1) 拟合,估计其均值回归半衰期。
- 对比 DF 检验(Dickey-Fuller)的统计量与 AR(1) 中 φ=1 的原假设,理解二者的关系。
- 实现一个实时更新的 AR(1) 配对交易策略:当 |spread - μ| > 2σ 时开仓,回到 |spread - μ| < 0.5σ 时平仓。
下一节 → ../10_math_methods/01_monte_carlo.ipynb