halo 的技术博客

返回

先说结论:线性 VAR 有个致命的隐含假设——股票收益和宏观动量之间的联动系数从 2008 年到 2021 年始终是同一套。但市场明显有两副面孔:牛市里宏观动量温和推动收益,熊市里却变成下跌的自我强化回路。MS-VAR(Markov-Switching VAR)的做法是给 VAR 挂一条隐藏马尔可夫链,每个 regime 拥有独立的截距、系数矩阵和残差协方差,让数据自己决定”现在是牛还是熊”。 合成数据实测:EM 算法 17 次迭代收敛,转移矩阵估计值 [0.970, 0.954] 对真值 [0.97, 0.94],regime 识别准确率 95.9%。择时端更直接:样本外 300 周,用滤波概率控制仓位,Sharpe 从买入持有的 −1.90 翻到 +1.06,最大回撤从 89.3% 压缩到 25.5%。但有一个多数教程避而不谈的坑:回测里能用的只有滤波概率,不是平滑概率——后者用了未来数据,直接进回测就是 look-ahead。

MS-VAR:收益序列与隐藏 regime

一、线性 VAR 的问题:一套系数描述两种世界#

标准 VAR(1) 写作:

yt=c+Ayt1+εt,εtN(0,Σ)y_t = c + A y_{t-1} + \varepsilon_t, \quad \varepsilon_t \sim N(0, \Sigma)

其中 yty_t 是变量向量(本文用两维:股票周收益、宏观动量指标)。这个模型里 ccAAΣ\Sigma 都是常数——意味着无论市场处于什么状态,变量间的动态关系都一样。

现实的打脸方式很具体:

  • 漂移不同:牛市周收益均值为正,熊市为负;
  • 波动不同:熊市方差往往是牛市的 3~6 倍(本实验设定 6 倍);
  • 联动结构不同:熊市里”下跌 → 恐慌 → 继续下跌”的正反馈更强,对应更大的自回归系数。

MS-VAR 的解法是引入一个隐藏状态 st{0,1}s_t \in \{0, 1\}(牛/熊),服从马尔可夫链:

P(st=jst1=i)=pijP(s_t = j \mid s_{t-1} = i) = p_{ij}

每个状态一套完整参数:

yt=cst+Astyt1+εt,εtN(0,Σst)y_t = c_{s_t} + A_{s_t} y_{t-1} + \varepsilon_t, \quad \varepsilon_t \sim N(0, \Sigma_{s_t})

关键在于 sts_t 不可观测——你永远不知道”今天确定是熊市”,只能算出”今天是熊市的概率”。这既是 MS-VAR 的麻烦,也是它的价值:概率本身就是仓位信号

二、合成数据:把牛熊写进生成过程#

为了能对照真值检验估计质量,用已知参数生成 900 周数据:

生成的序列牛市占 59.2%、熊市占 40.8%。转移概率 0.97/0.94 意味着 regime 有持久性——这是马尔可夫链设定的核心价值:它天然编码了”牛熊不会一天一换”的先验。

三、EM 估计:Hamilton 滤波 + Kim 平滑#

MS-VAR 的估计是经典的 EM 结构:E 步算出每个时点属于各 regime 的概率,M 步用这些概率做加权 OLS 重估参数。

E 步的核心是 Hamilton 滤波(前向递推,只用截至 t 的信息):

然后 Kim 平滑从后往前回溯,把未来信息也吸收进来得到平滑概率;M 步用平滑概率做加权 OLS:

def ols_var(Yl, Yc, w):
    """加权 OLS: 每个观测按其属于该 regime 的概率加权"""
    X = np.column_stack([np.ones(len(Yl)), Yl])
    beta = np.linalg.lstsq(X * np.sqrt(w[:, None]),
                           Yc * np.sqrt(w[:, None]), rcond=None)[0]
    resid = Yc - X @ beta
    Sigma = (resid * w[:, None]).T @ resid / w.sum()
    return beta, Sigma
python

实现层面必须交代的一个坑:滤波递推中预测概率和似然密度相乘时极易数值下溢——某个 regime 概率趋近 0 后,0 × 极小密度 = NaN,NaN 会顺着 EM 传染到加权 OLS 让 SVD 崩溃。本实验第一版就死在这里,修法是在预测概率、密度、归一化分母三处全部加下限截断(np.maximum(x, 1e-12))。这不是理论问题,是任何 handroll HMM/MS 模型都会踩的工程坑。

估计结果对照真值:

参数真值EM 估计
转移概率 p00 / p110.97 / 0.940.970 / 0.954
牛市漂移 c₁+0.30+0.19
熊市漂移 c₁−0.45−0.51
牛市方差 σ²1.000.97
熊市方差 σ²6.006.27
regime 识别准确率95.9%

方差和转移矩阵还原得很好,漂移略有偏差(0.19 vs 0.30)——这符合预期:漂移的信噪比天然低(0.3% 的周漂移对 1% 的周波动),而方差差 6 倍是强信号。MS 模型主要是靠波动差异区分 regime 的,漂移只是搭车。这一点直接影响你对它的期望:它擅长识别”高波动状态”,而”高波动”与”熊市”的重合度在股票市场上很高,但不是 100%。

拟合上,股票方程 RSS 比线性 VAR 低 6.9%。数字不大——regime 切换模型的拟合优势从来不是卖点,它卖的是状态概率这个副产品

四、滤波 vs 平滑:实盘只能用前者#

这是全文最重要的一节。EM 输出两种概率:

  • 平滑概率 P(sty1:T)P(s_t \mid y_{1:T}):用了全样本(包括 t 之后的数据),事后看非常准;
  • 滤波概率 P(sty1:t)P(s_t \mid y_{1:t}):只用截至 t 的信息,实时可得。

滤波 vs 平滑概率对比 + 参数还原

左图能看清两者的差别:平滑概率在 regime 边界处切换干脆利落(它”知道”后面发生了什么),滤波概率则会在切换初期迟疑几周——因为单凭一两个高波动观测,无法区分”熊市开始了”和”牛市里的偶发大跌”。

用平滑概率做回测是 MS 模型最常见的 look-ahead 错误,而且极其隐蔽:代码看起来完全正常,回测结果漂亮得惊人,但整条概率序列在每个时点都偷看了未来。正确做法只有一种:训练段跑 EM 定参数,样本外用 Hamilton 滤波逐步递推,且 t 时刻的概率决定 t+1 的仓位。

五、样本外择时:Sharpe 从 −1.90 到 +1.06#

前 600 周训练(重新跑 EM,不复用全样本参数),后 300 周样本外。滤波概率转仓位,两种映射:

prob_bull = filt_te[:, 0]                # 样本外滤波牛市概率
pos_soft = np.r_[0.0, prob_bull[:-1]]    # 软仓位 = 概率本身, t 确认 t+1 生效
pos_hard = np.r_[0.0, (prob_bull[:-1] > 0.5).astype(float)]  # 硬仓位 0/1
python

结果:

策略总收益Sharpe最大回撤
买入持有−85.0%−1.9089.3%
硬仓位(prob>0.5)+54.2%1.0625.5%
软仓位(=牛市概率)+45.9%0.9925.1%

样本外 300 周滤波概率择时

先泼冷水再说亮点。这个对比被样本外区间”美化”了:这 300 周恰好包含一段长熊市(买入持有 −85% 就是证据),regime 择时在长熊里优势最大。如果样本外是单边牛市,择时反而会因为切换迟疑损失收益。所以正确的读法不是”MS-VAR 能赚 54%“,而是:它把一个 −85% 的灾难变成了 +54%,代价是在牛市里会偶尔踏空几周——这是典型的”用收益上限换回撤下限”的交易。

有趣的细节是这次硬仓位小胜软仓位(Sharpe 1.06 vs 0.99),与上一篇 STAR 文章里软仓位碾压硬仓位的结论相反。原因在于概率的形状:MS 滤波概率大部分时间贴在 0 或 1 附近(regime 持久性强,后验很自信),软硬仓位的实际差异只发生在切换的几周里;而 STAR 的过渡函数输出连续分布在中间的值,软仓位的信息增量大得多。结论:软仓位的价值取决于信号本身是不是”软”的,把一个本质上二值的信号做成连续仓位,收益寥寥。

六、诚实的翻车与边界#

1. EM 对初始化敏感,且有 label-switching 问题。 EM 只保证局部最优。本实验用”按波动中位数分组”初始化,17 次迭代干净收敛;但换一个随机初始化可能收敛到把两个 regime 估成几乎相同参数的退化解。工程上必须做两件事:多组初始化取似然最高者;收敛后按某个可识别特征(如方差大小)重新排序 regime,否则”regime 0”这周指牛市、重估后指熊市,回测逻辑直接错乱。

2. regime 数不是越多越好。 本文用 2 个 regime 是因为数据就是 2 个 regime 生成的。真实数据上 3-regime、4-regime 模型似然一定更高,但每加一个 regime,参数量增加一整套 (c, A, Σ),2 变量 VAR(1) 就是 10 个参数。有限样本下多出来的 regime 往往只是在拟合某一段特殊时期(比如把 2020 年 3 月单独拟成一个”崩盘 regime”),样本外毫无泛化。regime 数选择用 BIC 或 regime 分类的经济可解释性,别用似然。

3. 漂移估计不可靠是结构性的。 上面已经提到,MS 模型区分 regime 靠的主要是二阶矩(波动)。如果你的两个 regime 波动接近、只有漂移不同(比如”温和牛市”vs”温和震荡”),MS-VAR 基本切不出来。这决定了它的适用边界:波动 regime 明确的市场(股指、商品)好用,波动平稳但趋势切换的市场(部分汇率)不好用。

4. 本实验是合成数据。 数据生成过程就是 MS-VAR,模型设定完全正确——这是估计质量的上限展示,不是真实市场的期望值。真实市场的 regime 未必是马尔可夫的(持续时间可能有记忆),残差未必是高斯的(滤波概率会被肥尾污染)。前者可以用 duration-dependent MS 缓解,后者可以把残差换成 t 分布,但每个补丁都是新的参数和新的过拟合面。

七、什么时候该用 MS-VAR#

适合: 波动 regime 分明的资产择时和风险预算(滤波概率直接映射目标波动);宏观变量联动关系的状态依赖分析(利率-股市相关性在危机中变号是 MS-VAR 的经典应用);作为其他策略的 regime 过滤器——趋势策略只在”高波动 regime 概率低”时开仓。

不适合: 高频信号(EM + 滤波的反应速度以周计);漂移差异为主、波动差异小的场景;样本太短的市场——每个 regime 至少需要几十个观测才能估出一套 VAR 参数,5 年日线数据切 3 个 regime 就已经很勉强。

一句话总结:MS-VAR 把”市场有牛熊”这句人人都会说的话变成了一套可估计、可滤波、可回测的机制,它给你的最有价值的东西不是预测,而是一个实时更新的、带持久性先验的状态概率——只要你管住手,别用平滑概率回测。


本文实验代码基于 numpy 手写实现(Hamilton 滤波 + Kim 平滑 + EM 共约 150 行),合成数据参数与估计结果均为真实运行输出。文中回测为教学演示,不构成投资建议。

马尔可夫区制转移 VAR:让宏观变量在牛熊状态间自行切换
https://blog.halo26812.eu.org/blog/markov-switching-var
Author halo
Published at 2026年7月24日
版权声明 CC BY-NC-SA 4.0
Comment seems to stuck. Try to refresh?✨