第 20 课 均值回归、配对交易与网格思路¶
这一家族关注偏离是否会修复。研究的难点不在发现价格离得很远,而在证明那个中心仍然有意义。
跌得多以后可能继续跌,也可能修复¶
某项资产从 10 元跌到 8 元。趋势研究者可能认为方向已经向下,应当回避或顺势做空;均值回归研究者可能认为价格暂时离开正常范围,未来有机会回到中心。两种判断都能从同一段历史出发,区别在于它们对“8 元为什么出现”提出了不同解释。
若下跌来自短暂流动性冲击、投资者过度反应或交易价格在买卖报价间跳动,偏离可能很快修复。若公司盈利永久下降、行业制度改变或市场进入新状态,过去 10 元附近的中心便可能失效。价格越跌,简单回归指标会觉得机会越大,错误仓位也可能随之增加。
均值回归不是“跌多了就买”的同义词。完整假设需要说明哪个变量会回到什么中心,中心怎样用过去数据估计,偏离尺度是什么,预计多久修复,以及哪些证据表示关系已经断裂。价格、收益率、两项资产价差和去除共同因素后的残差,都可以成为回归对象,它们的经济含义并不相同。
回归对象、中心与尺度是三件事¶
回归对象是研究者希望观察修复的变量。中心表示这个变量在当前窗口中围绕的位置,尺度表示日常波动有多大。当前价差为 3 元、历史中心为 2 元时,偏离 1 元;若它平时只晃动 0.1 元,这次偏离很极端,若平时晃动 2 元,同样一元就很普通。
| 方法 | 回归对象 | 中心与尺度 | 主要失效风险 |
|---|---|---|---|
| Z 分数回归 | 价格、价差或残差 | 滚动均值与滚动标准差 | 中心漂移、极端值改变估计 |
| RSI 回调 | 近期上涨与下跌强度 | 指标内部的相对强弱区间 | 强趋势中长期停留在极端 |
| 布林带回归 | 价格相对移动平均的位置 | 移动平均与波动带 | 波动状态突然变化 |
| 短期截面反转 | 同日资产的近期收益排名 | 当日候选池横向分布 | 低流动性、买卖价反弹与不可成交 |
| 配对交易 | 两项相关资产的对冲价差 | 训练期估计的价差中心与尺度 | 业务关系、对冲比例和共同趋势断裂 |
中心不是自然常数。移动平均会随新价格前进,配对价差会受对冲比例影响,公司关系也可能永久改变。策略卡要把中心更新频率、最长持有期和失效判断放在信号旁边,防止账户用不断加仓表达对旧中心的执着。
Z 分数先把偏离换成日常波动单位¶
假设某个价差在过去窗口的平均值为 2.0,标准差为 0.5,当前值为 3.0。当前比平均值高 1.0,再用 1.0 除以日常尺度 0.5,得到 2。这个结果表示当前价差高出滚动中心两个历史标准差。
若另一项价差平均值为 100,标准差为 10,当前值为 120,它同样高于中心两个标准差。原始偏离分别是 1 与 20,Z 分数把它们放到相对自身波动的共同尺度上。
把这段手算压缩成公式,可以得到滚动 Z 分数。
\(x_t\) 是当前回归对象,\(\mu_{t,n}\) 是截至当前、长度为 \(n\) 的滚动均值,\(\sigma_{t,n}\) 是同一窗口的滚动标准差。Z 分数为 2 只描述历史窗口中的相对位置,不表示未来必然下跌,也不表示不同市场都应该用 2 作为入场阈值。
下面代码输入一列按日期排列的价差或残差,任务是计算二十期滚动中心、滚动尺度和 Z 分数。前十九行历史不足,应保留为空;标准差为零的窗口不能做除法,要先替换为空值。
rolling_mean = value.rolling(20, min_periods=20).mean()
rolling_std = value.rolling(20, min_periods=20).std(ddof=1)
zscore = (value - rolling_mean) / rolling_std.replace(0, np.nan)
value - rolling_mean 得到原始偏离,再除以滚动标准差。极端值进入窗口以后会同时改变均值和标准差,随后几日的 Z 分数可能被压低。窗口长度、异常处理与更新顺序都属于模型条件,不能只选择历史表现最好的组合。
从 Z 分数到策略还需要方向、退出和停止¶
一条教学规则可以规定,Z 分数低于负 2 时做多回归对象,高于正 2 时做空,回到 0 附近退出。入场阈值越靠外,交易较少、偏离更极端;阈值越靠近中心,信号增多,成本与噪声也会增加。恰好等于阈值是否触发,都要在规则中写清。
做多价差与买入一项股票不是同一动作。价差若由 A 减去某个比例的 B 构成,做多价差通常意味着买 A、同时卖出相应数量 B。两边成交时间、费用、做空可得性和数量比例都会影响账户。只画 Z 分数曲线无法替代订单与持仓账本。
最大持有期是均值回归的重要停止条件。假设预计偏离在十日内修复,持有半年仍未回归,即使理论上未来某天可能返回,对这条十日策略也已经失去意义。关系稳定指标、单笔损失上限和重大事件同样可以触发退出。
RSI 描述近期上涨与下跌的相对强度¶
RSI 的中文常译为相对强弱指标。它把一段时间内平均上涨幅度与平均下跌幅度压缩到 0 至 100 之间。近期大多上涨时,RSI 靠近高端;近期大多下跌时,它靠近低端。市场习惯把低值称为超卖、高值称为超买,这两个名称容易让新手误以为反转已经确定。
假设五天价格变化为正 1、负 1、负 2、正 0.5 和负 0.5 元。计算时先把上涨幅度与下跌幅度分开,分别平滑,再比较两边相对大小。下跌一侧明显更大时,RSI 会落到较低区域。它说明近期下跌力量占优,没有说明第六天一定上涨。
下面代码输入按日期排列的收盘价,任务是先计算每日变化,把正变化放入 gain、负变化的绝对值放入 loss,再使用十四期指数平滑得到 RSI。运行前应检查价格单调上涨时损失接近零,指标会靠近 100。
change = close.diff()
gain = change.clip(lower=0)
loss = -change.clip(upper=0)
average_gain = gain.ewm(alpha=1 / 14, adjust=False).mean()
average_loss = loss.ewm(alpha=1 / 14, adjust=False).mean()
rsi = 100 * average_gain / (average_gain + average_loss)
长期下跌中,RSI 可以在低位停留很久。将低 RSI 与长期向上趋势结合,可以把研究问题改成“上升背景中的短期回调是否修复”,也会增加长期均线与 RSI 两组参数。新增过滤要与无过滤版本、公平成本和未见时间比较,不能只保留更平滑的一条曲线。
布林带把移动中心与滚动波动画在一起¶
假设二十日移动平均为 10 元,滚动标准差为 0.50 元。若带宽系数取 2,上轨为 10 加 2 乘 0.50,得到 11 元;下轨为 10 减同样距离,得到 9 元。价格跌到 8.90 元时位于下轨外,表示它相对于近期中心和波动处在较低位置。
\(MA_t\) 是移动平均,\(\sigma_t\) 是滚动标准差,\(k\) 决定带宽。上下轨会随中心与波动共同移动,因此不等于固定支撑阻力。波动突然上升时,标准差估计会滞后,价格也可能沿着带外持续运行。
策略需要区分“触碰下轨立即买入”“跌破以后重新回到带内才确认”和“只在长期趋势向上时研究下轨回调”。三种规则拥有不同时间、交易次数和风险。代码块只计算带宽时,还没有形成完整策略。
短期反转在同日寻找近期输家¶
短期截面反转会在同一日期比较许多资产近期收益,买入排名靠后的对象,卖出或回避近期赢家。它可能捕捉暂时流动性冲击、投资者短期过度反应,也可能主要来自低价资产的买卖价跳动和难以实现的收盘价。
假设四项资产过去五日收益为 6%、2%、负 3% 和负 8%。反转规则把负 8% 排在最强买入候选一侧,因为它最近跌得最多。这个判断没有区分价格下跌来自短暂冲击还是永久坏消息,候选池、事件过滤、成交容量和持有期都要补充。
下面代码输入多资产收盘表,先计算五日收益,再按每个日期横向排名。rank <= 0.10 只得到最弱十分之一的布尔标记,下一日订单与可成交检查仍要另写。
five_day_return = close / close.shift(5) - 1
percentile_rank = five_day_return.rank(axis=1, pct=True)
long_group = percentile_rank <= 0.10
短周期优势通常很小、换手很高,对买卖价差和成交延迟十分敏感。延迟一天、扩大滑点、排除停牌恢复与价格限制日期、限制订单占成交量比例,是最低限度的压力检查。若信号只在微盘和低价资产中出现,名义收益可能无法转成账户收益。
网格策略把回归假设写成一组分层订单¶
网格会在一系列价格层级安排买卖。例如以 10 元为中心,每下跌 1 元买入一份,每上涨 1 元卖出一份。价格在 9、10、11 元之间反复时,订单可能多次完成,账本看起来不断获得小价差。这种结构隐含了价格会在有限区间往返的假设。
单边下跌会把另一面暴露出来。账户初始现金 40 元,分别在 10、9 和 8 元各买一份,现金只剩 13 元,持仓三份,平均成本为 9 元。价格继续跌到 6 元而没有回到卖出层,持仓市值为 18 元,总权益变成 31 元,尚未计费用。网格没有实现三次盈利,只积累了越来越便宜的库存。
| 价格事件 | 订单动作 | 累计持仓 | 剩余现金 | 按当前价估值的总权益 |
|---|---|---|---|---|
| 起点 10 元 | 买入一份 | 1 | 30 | 40 |
| 下跌到 9 元 | 再买一份 | 2 | 21 | 39 |
| 下跌到 8 元 | 再买一份 | 3 | 13 | 37 |
| 继续跌到 6 元 | 达到仓位上限,不再买 | 3 | 13 | 31 |
研究网格必须规定价格范围、每格数量、最大层数、现金下限、单边趋势停止条件和跳空处理。层数增加会制造更多历史交易,也会扩大尾部库存。回测区间若只包含来回震荡,就没有覆盖最危险的单边行情。
配对交易尝试让共同趋势相互抵消¶
两家业务相近的公司可能同时受到行业需求影响,价格长期一起上升或下降。配对交易尝试构造一多一空的组合,减少共同方向,观察两者关系偏离后是否修复。它交易的对象通常是价差或残差,不是单只价格。
假设 A 价格为 120 元,B 价格为 60 元,历史研究认为 A 大约对应 B 的两倍。一股 A 减去两股 B 的名义价差为 120 减 2 乘 60,得到 0。后来 A 为 130 元、B 仍为 60 元,价差变为 10 元。若关系仍然有效,研究者可能做空 A、做多两份 B,等待价差下降。
两项资产价格尺度与敏感度不同,不能随意一股对一股相减。用来让两边共同变化尽量抵消的比例叫作对冲比率。它通常在过去训练窗口估计,并在随后的交易窗口固定或按事先频率更新。
对数价格价差常写成下面的形式。
\(P_A\) 与 \(P_B\) 是两项价格,\(\beta\) 是训练期估计的对冲比率,\(s_t\) 是价差。使用对数能够把比例关系写成差,但不会自动保证价差稳定。研究者还会对价差计算滚动中心、标准差与 Z 分数,再把信号翻译成两边订单。
Gatev、Goetzmann 与 Rouwenhorst 的研究是配对交易经典文献之一,入口列在参考资料中。阅读原文时要还原配对选择、距离定义、形成期、交易期、成本与做空假设。
高相关不等于价差会回到中心¶
两项价格都在长期上涨时,相关系数可能很高,彼此差距仍能不断扩大。相关性描述同期线性共同变化,没有说明某个线性组合会围绕稳定水平。配对研究常进一步检查协整,协整可以先理解为,两条各自漂移的序列是否存在一个相对稳定的长期组合关系。
统计检验只能提供有限样本证据。先从许多资产中筛出最稳定配对,再回到同一历史交易,会让选择过程获得未来关系。业务相似性、资本结构、并购和监管变化也可能让过去协整在交易期断裂。
平稳性表示一个序列的中心、波动等分布特征不会任意漂移。现实市场很少严格平稳,检验结果也会随窗口变化。策略卡应把统计关系与经济关系并列,任何一边出现重大变化都能触发重新估计或退出。
配对选择与交易必须在时间上分开¶
正确流程先在过去窗口寻找有经济联系的候选,估计对冲比率、价差中心与阈值,然后冻结这些决定,在随后窗口模拟交易。交易窗口结束以后才向前滚动,重新判断关系是否仍可使用。
flowchart LR
accTitle: 配对交易的滚动研究流程
accDescr: 过去窗口先选择配对并估计对冲关系,参数冻结后进入随后交易窗口,窗口结束再检查关系,稳定时向前滚动,断裂时停止并退出
select["过去窗口<br/>选择有机制依据的配对"] --> estimate["估计对冲比率、中心和尺度"]
estimate --> freeze["冻结交易窗口参数"]
freeze --> trade["随后窗口<br/>执行两边订单并记账"]
trade --> review{"关系与风险仍在允许范围吗"}
review -->|是| roll["向前移动窗口并重新估计"]
review -->|否| exit["停止新信号并按规则退出"]
roll --> select
全样本选配对、全样本估计对冲比例,再从第一天回测,会把未来关系送回过去。每个滚动窗口还要重新拟合标准化与阈值,不能先用全历史均值处理价差。
半衰期只是一项速度估计¶
若价差大致呈现向中心拉回的过程,可以估计偏离衰减一半需要多少时间,这段时间叫作半衰期。假设偏离从 2 元平均五天后缩小到 1 元,教学上可以说半衰期约五天。它能帮助研究者选择观察与最大持有时间,不能保证每次偏离都按固定速度回归。
半衰期会随市场状态与估计窗口变化。估计为五天的关系若持有三十天仍没有修复,研究者应检查结构断裂,不能只因为理论上“最终会回归”就无限等待。策略的资金期限必须与回归速度相容。
最大风险是把模型错误解释成更好机会¶
均值回归最危险的心理与程序行为,是偏离越大就不断增加仓位。若中心仍有效,较大偏离可能带来更大修复空间;若中心已经移动,仓位会把模型错误成倍放大。最大仓位、单笔损失、最大持有期、关系稳定检查和重大事件停止,都应在结果出现以前写下。
配对交易还要处理两边成交不同步、做空借券、股息补偿、融资成本和强制平仓。网格要处理库存与现金。短期反转要处理价格限制与容量。所有方法都可能表现为许多小盈利加一次大损失,成绩单需要展示尾部与最差市场状态。
回归策略排雷清单¶
- 明确回归对象、中心、尺度和它们的经济含义。
- 滚动估计只使用当时及过去数据,没有全历史中心与配对选择。
- 入场、退出、最大持有期和结构断裂停止条件都能执行。
- 与无交易、简单固定阈值、随机配对或买入持有公平比较。
- 延迟成交、扩大价差和限制容量后,微小优势还剩多少。
- 震荡、单边趋势、跳空、停牌与公司事件分别进入压力情景。
- 网格展示库存、现金与仓位上限,配对展示两边成交与做空成本。
- 参数邻近、滚动窗口和未见数据中不只剩一个冠军版本。
容易弄错的地方¶
| 常见误解 | 隐藏风险 | 检查办法 |
|---|---|---|
| Z 分数达到 2 就一定回归 | 它只描述历史相对位置 | 检查中心稳定、机制与未见时期 |
| RSI 低等于价格已经超卖 | 强下跌中指标可长期保持低位 | 加入市场状态与最大持有期 |
| 高相关资产天然适合配对 | 共同趋势不保证价差平稳 | 检查对冲关系、协整与结构变化 |
| 网格每格都有小盈利,所以风险低 | 单边走势会持续积累库存与现金占用 | 展示完整库存账本和趋势压力 |
| 价差继续扩大说明机会更好 | 关系可能已经断裂 | 设置仓位、损失和关系停止条件 |
一分钟自测¶
某价差过去均值为 10,标准差为 1,当前值为 13。Z 分数为 3,能否据此断言它一定会回到 10?
查看答案
不能。Z 分数只说明当前值在过去窗口中离中心较远。还要检查中心是否稳定、关系是否发生结构变化、订单能否执行,以及最大持有与损失条件。本课术语¶
| 词语 | 先这样理解 |
|---|---|
| 均值回归 | 某个变量偏离当前中心后可能向中心修复的假设 |
| 回归对象 | 被研究是否会修复的价格、价差、残差或其他变量 |
| Z 分数 | 当前值离滚动中心多少个滚动标准差 |
| RSI | 比较近期平均上涨与平均下跌强度的指标 |
| 布林带 | 以移动平均为中心、按滚动波动形成的动态区间 |
| 对冲比率 | 为减少两项资产共同变化而设置的数量比例 |
| 协整 | 多条漂移序列之间可能存在稳定长期组合关系的性质 |
| 半衰期 | 偏离按估计过程衰减一半所需的时间 |
| 结构断裂 | 过去中心、关系或分布因环境变化而失效 |
课后练习¶
1 手算 Z 分数¶
当前价差为 12,滚动均值为 10,滚动标准差为 1。Z 分数是多少?若标准差改为 4,结果又是多少?
提示
先求当前值与均值之差,再除以标准差。答案
标准差为 1 时,Z 分数为 2;标准差为 4 时,Z 分数为 0.5。同样两元偏离在不同日常波动中具有不同相对程度。2 计算网格库存¶
账户从 50 元开始,在 10、9、8、7 元各买一份,忽略费用。最终现金、持仓数量和按 7 元估值的总权益是多少?
提示
先把四次买入金额相加,再用现金加四份持仓市值。答案
买入共花 34 元,现金剩 16 元,持仓四份,按 7 元估值为 28 元,总权益为 44 元。3 寻找配对泄漏¶
研究者用完整十年挑出价差最稳定的一对,再从十年前第一天开始交易。问题在哪里?
提示
配对选择时看过哪些未来关系?答案
完整十年的稳定性参与了配对选择,过去策略提前知道后来哪一对关系最好。应在过去训练窗口选配对,并在随后窗口冻结交易。4 动手补全停止条件¶
为一条 Z 分数回归规则补上最大持有期、最大仓位与结构断裂条件。
提示
条件要能从账本或数据中明确判断,不能只写“情况不对就停”。答案
示例可以规定最多持有十日、单对名义仓位不超过账户 10%,价差连续若干日超出训练期极端范围或发生重大业务事件时停止新单并退出。具体数值需要研究依据。5 开放思考¶
价格大跌究竟是暂时偏离还是新中心形成,回测怎样诚实处理这份未知?
评价要点
不能根据后来反弹与否倒推当时答案。应提前写机制、市场状态、最大持有、风险预算和结构断裂指标,使用滚动时间验证,并允许策略承认无法区分而停止交易。参考资料¶
配对交易、协整、短期反转与常见技术指标的文献入口统一列在参考资料中。阅读时请把统计关系、经济联系、配对选择时间、做空成本和失效规则一同还原。
均值回归总要说清什么东西会回到哪里,偏离用什么尺度衡量,结构改变时怎样退出。Z 分数只负责把偏离换成标准差单位;配对交易还要估计两边比例,并把挑选关系的时期与模拟交易的时期分开。缺少其中任何一项,“跌多了会反弹”都还只是一句故事。