☰
PYTHON用时变马尔可夫区制转换(MARKOV REGIME SWITCHING)自回归模型分析经济时间序列:TaoToken统一Key通道下的可复现建模流程
2026/10/8 6:37:31 网站建设 项目流程

1. 经济时间序列里为什么需要区制转换模型

如果你用普通 AR 模型去拟合 GDP 增速、工业增加值或者失业率,经常会遇到一个尴尬:模型残差在衰退期明显偏大,参数在扩张期和收缩期像是两套逻辑。Hamilton 在 1989 年那篇经典论文里给出的解释是——经济序列的均值、方差甚至自回归结构本身,会随着「区制」切换而改变。这就是马尔可夫区制转换自回归模型(Markov Regime Switching Autoregression,简称 MS-AR)要解决的问题。

它到底能做什么?简单说,它假设序列背后有一个不可直接观测的状态变量 S_t,比如「扩张」和「衰退」,每个状态对应一组不同的 AR 参数。状态之间按转移概率矩阵切换,而我们要做的,就是用观测到的经济数据反推出这些参数,以及每个时点处于某个状态的概率。这个概率曲线,就是大家常说的「衰退概率」。

适合谁看?如果你已经会用 Python 做时间序列,想从 ARIMA、VAR 往非线性模型走一步;或者你在做宏观、金融、行业景气度分析,需要给「拐点」一个概率化的度量,那这篇就是为你写的。我会用 statsmodels 的MarkovAutoregression和MarkovRegression两个类,把 Hamilton(1989)的均值切换模型、Kim-Nelson-Startz(1998)的方差切换模型、以及 Filardo(1994)的时变转移概率模型都跑一遍,并且把环境配置、参数估计、平滑概率可视化、预期持续时间计算这些环节全部做成可复制的流程。

另外,这类建模经常需要反复调用大模型来辅助读文档、改代码、解释报错。我会顺带说明怎么用 TaoToken 的统一 Key/API 通道管理这些调用凭据,让整个分析流程在换机器、换项目时依然可复现,而不是把 Key 散落在各个脚本里。

2. TaoToken 统一 Key 通道的前置准备

在正式写模型之前,先把「调用凭据」这件事理清楚。做经济时间序列分析时,我经常一边跑 statsmodels,一边让模型帮我解释summary()里某个参数的含义,或者排查MarkovAutoregression拟合不收敛的原因。如果每个工具都单独配一套 Key,时间一长就乱了。TaoToken 的思路是给你一个统一的 API 入口,把模型对话、编码辅助、文档查询这些能力收敛到同一套凭据下。

你需要先拿到一个 API Key。登录官网 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,进入控制台,在 API Keys 页面创建一个新的 Key。创建时建议按项目命名,比如econ-msar-2024,这样后面在多个脚本里复用时能一眼看出用途。控制台地址是 https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,API Keys 页面是 https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= 。

拿到 Key 之后,不要直接硬编码在 Python 文件里。我习惯用环境变量加.env文件的方式管理。先安装依赖:

pip install python-dotenv requests statsmodels pandas numpy matplotlib pandas_datareader

然后在项目根目录建一个.env文件:

TAOTOKEN_API_KEY=sk-你的实际Key TAOTOKEN_BASE_URL=https://taotoken.net/api

注意 Base URL 这里不带 UTM 参数,就是纯粹的 API 地址https://taotoken.net/api。在 Python 里这样读取:

import os from dotenv import load_dotenv load_dotenv() api_key = os.getenv("TAOTOKEN_API_KEY") base_url = os.getenv("TAOTOKEN_BASE_URL") assert api_key, "TAOTOKEN_API_KEY 未设置,请检查 .env 文件" print("Base URL:", base_url)

如果你用的是 Claude Code 这类编码工具,可以在它的配置里把 Base URL 指向https://taotoken.net/api,Key 填上面创建的,Model ID 按你实际使用的模型填写。这样你在终端里让模型帮你改 statsmodels 代码时,走的就是同一套凭据。模型对话入口在 https://taotoken.net/chat?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,接入文档在 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= 。

这里有个我踩过的坑:.env文件一定要加进.gitignore,否则 Key 会跟着代码一起提交。另外,如果你在 Jupyter 里跑,load_dotenv()要在 import 其他模块之前调用,不然环境变量读不到。

3. 可复制的模型配置与代码片段

这一节是核心。我会把数据获取、模型创建、参数估计、平滑概率提取这几个步骤拆开写,每一步都给完整代码。先建一个msar_config.py,把路径和模型参数集中管理:

# msar_config.py import os from dataclasses import dataclass, field from typing import List @dataclass class MSARConfig: data_start: str = "1947-01-01" data_end: str = "2013-04-01" k_regimes: int = 2 order: int = 4 switch_ar: bool = False search_reps: int = 20 random_seed: int = 12345 output_dir: str = "outputs" figure_dpi: int = 120 def ensure_output_dir(self): os.makedirs(self.output_dir, exist_ok=True) return self.output_dir config = MSARConfig()

数据获取用pandas_datareader,这里以 GDP 数据为例。如果你本地已经有gndata文件,直接pd.read_csv也行:

import numpy as np import pandas as pd import matplotlib.pyplot as plt from pandas_datareader.data import DataReader from datetime import datetime from msar_config import config config.ensure_output_dir() start = datetime(1947, 1, 1) end = datetime(2013, 4, 1) gdp = DataReader("GDPC1", "fred", start, end) gdp["growth"] = gdp["GDPC1"].pct_change() * 100 gdp = gdp.dropna() print(gdp.head()) print("样本区间:", gdp.index.min(), "至", gdp.index.max()) print("观测数:", len(gdp))

接下来创建 Hamilton(1989)风格的均值切换 AR(4) 模型。关键参数是k_regimes=2、order=4、switch_ar=False:

import statsmodels.api as sm y = gdp["growth"].values model = sm.tsa.MarkovAutoregression( y, k_regimes=config.k_regimes, order=config.order, switch_ar=config.switch_ar, trend="c" ) res = model.fit(search_reps=config.search_reps, maxiter=500) print(res.summary())

search_reps=20的意思是,在正式优化之前,对起始参数做 20 次随机扰动,挑一个最好的作为起点。马尔可夫转换模型的似然函数经常有多个局部极大值,不做随机搜索很容易卡在次优解。为了结果可复现,记得设随机种子:

np.random.seed(config.random_seed) res = model.fit(search_reps=config.search_reps, maxiter=500)

拟合完成后,提取平滑概率。statsmodels 里res.smoothed_marginal_probabilities是一个 DataFrame,列是区制编号:

smoothed = res.smoothed_marginal_probabilities filtered = res.filtered_marginal_probabilities print(smoothed.head()) print("区制0平均平滑概率:", smoothed[0].mean()) print("区制1平均平滑概率:", smoothed[1].mean())

转移矩阵和预期持续时间这样算:

trans_mat = res.regime_transition[:, :, 0] print("转移矩阵:\n", trans_mat) expected_durations = 1 / (1 - np.diag(trans_mat)) print("各区制预期持续时间(季度):", expected_durations)

如果你要跑 Kim-Nelson-Startz(1998)的方差切换模型,换成MarkovRegression,指定trend="nc"、k_regimes=3、switching_variance=True:

model_kns = sm.tsa.MarkovRegression( y, k_regimes=3, trend="nc", switching_variance=True ) res_kns = model_kns.fit(search_reps=config.search_reps) print(res_kns.summary()) smoothed_kns = res_kns.smoothed_marginal_probabilities

Filardo(1994)的时变转移概率模型,需要传入外生变量exog_tvtp。这里用滞后一期的领先指标作为驱动变量:

exog_tvtp = gdp["growth"].shift(1).dropna() y_tvtp = gdp["growth"].iloc[1:] model_tvtp = sm.tsa.MarkovAutoregression( y_tvtp.values, k_regimes=2, order=4, switch_ar=False, trend="c", exog_tvtp=exog_tvtp.values.reshape(-1, 1) ) res_tvtp = model_tvtp.fit(search_reps=config.search_reps) print(res_tvtp.summary())

把配置集中到 dataclass 的好处是,换数据、换区制数、换滞后阶数时只改一处,脚本其余部分不用动。这也是保证流程可复现的关键。

4. 验证请求与成功结果对照

代码跑通不等于结果可信。这一节说几个验证动作,帮你确认模型确实在工作。

第一,看summary()里的对数似然值和 AIC/BIC。如果search_reps从 20 加到 50,对数似然明显提升,说明之前可能卡在局部最优。我实测下来,Hamilton 的 GDP 模型在search_reps=20时通常已经稳定,但方差切换模型有时需要更多次。

第二,检查平滑概率的形态。扩张区制的概率应该在 NBER 衰退区间明显下探。你可以把平滑概率和衰退区间画在一起:

fig, axes = plt.subplots(2, 1, figsize=(12, 7), sharex=True) axes[0].plot(gdp.index, y, color="steelblue", linewidth=1) axes[0].set_title("GDP 环比增长(%)") axes[1].plot(smoothed.index, smoothed[0], color="darkred", linewidth=1.2) axes[1].set_title("区制0(低增长/衰退)平滑概率") axes[1].set_ylim(-0.05, 1.05) plt.tight_layout() plt.savefig(f"{config.output_dir}/smoothed_prob.png", dpi=config.figure_dpi) plt.show()

第三,验证转移矩阵每行是否和为 1。这是马尔可夫链的基本约束,如果某行加起来不等于 1,说明模型设定有问题:

row_sums = trans_mat.sum(axis=1) print("转移矩阵行和:", row_sums) assert np.allclose(row_sums, 1.0, atol=1e-6), "转移矩阵行和不为1"

第四,用 TaoToken 的模型对话能力做交叉验证。把summary()的输出贴给模型,问它「区制0的 AR 系数是否显著、预期持续时间是否合理」。这一步不是让模型替你下结论,而是帮你快速定位可疑参数。模型对话入口在 https://taotoken.net/chat?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= 。

成功的结果大概长这样:区制0对应负增长、高波动,平滑概率在 1980 年代初、1990 年代初、2008 年前后明显抬升;区制1对应正增长、低波动。预期持续时间上,衰退约 4 个季度,扩张约 10 个季度,和 Kim-Nelson 的经典结论量级一致。

如果你跑的是方差切换模型,三个区制的平滑概率里,高方差区制应该只在少数时期出现,比如 1970 年代石油危机和 2008 年金融危机。如果高方差区制概率长期居高不下,可能是k_regimes设多了,或者数据频率不对。

5. 本篇常见报错与排查

这一节按真实报错来写,你遇到时可以直接对照。

报错一:ValueError: The model has no regime transition probabilities

这个通常出现在你用了MarkovRegression但没指定switching_variance,或者k_regimes和数据结构不匹配。检查你的模型类是否和模型设定一致:均值切换用MarkovAutoregression,纯方差切换用MarkovRegression且trend="nc"。

报错二:LinAlgError: Singular matrix

转移矩阵或协方差矩阵奇异。常见原因是样本太短、区制数太多。比如你只有 40 个观测却设k_regimes=4,参数比数据点还多。解决办法是减少区制数,或者换更长的时间序列。另外,如果某个区制的观测数几乎为 0,也会触发这个错误,可以在拟合前先做一次简单的聚类看看数据分布。

报错三:ConvergenceWarning: Maximum Likelihood optimization failed to converge

这是最常见的。先加search_reps,从 20 加到 50 甚至 100。再检查数据是否做了标准化,GDP 增速这种量纲一般没问题,但如果你用的是原始 GDP 水平值,数值太大容易导致优化不稳定。还有,maxiter默认可能不够,显式设成 500 或 1000。

报错四:KeyError: 0或KeyError: 1

提取平滑概率时列名不对。statsmodels 不同版本里,smoothed_marginal_probabilities的列名可能是整数 0/1,也可能是字符串。先print(smoothed.columns)确认,再用smoothed.iloc[:, 0]这种位置索引更稳。

报错五:401 Unauthorized或local proxy failed

如果你在脚本里调用 TaoToken 的 API 做辅助分析,遇到 401,先检查.env里的 Key 是否有多余空格,以及 Base URL 是否写成了https://taotoken.net/api(不要带 UTM)。local proxy failed一般是本地网络环境问题,确认没有额外的代理层拦截请求。接入文档在 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,里面有完整的鉴权说明。

报错六:reading choices相关解析错误

如果你让模型返回 JSON 格式的参数建议,但返回内容里混了自然语言,解析就会失败。解决办法是在 prompt 里明确要求「只返回 JSON,不要任何解释」,并且在代码里用try/except包住json.loads,失败时打印原始返回内容再排查。

报错七:OAuth 相关错误

如果你用 Claude Code 或类似工具接入,遇到 OAuth 报错,检查三件套是否齐全:Base URL 填https://taotoken.net/api,Key 填控制台创建的 Key,Model ID 填你实际使用的模型标识。三者缺一不可,且 Model ID 要和文档里列出的名称完全一致。

6. 长期编码与 Agent 场景的凭据管理

跑完这一轮 MS-AR 建模,你会发现真正花时间的不是模型本身,而是反复调试、查文档、改代码。如果你打算把这类分析做成长期项目,比如每周更新一次衰退概率、或者把模型封装成 Agent 自动跑,那凭据管理就值得认真对待。

我的做法是:把 TaoToken 的 Key 放在统一的.env里,所有脚本、Notebook、编码工具都从这里读。这样换项目时只需要复制一个文件,不用到处找 Key。如果你需要长期跑编码任务或者 Agent 工作流,可以了解一下 Coding Plan,入口在 https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,它更适合高频、持续的调用场景。

具体到 Claude Code 这类工具,配置时记住三件套:Base URL 用https://taotoken.net/api,Key 用控制台创建的,Model ID 按文档填写。配置好之后,你在终端里让模型帮你重构msar_config.py、解释res.summary()里的参数、或者生成平滑概率的绘图代码,走的都是同一套凭据。这样整个「数据获取—模型估计—结果验证—文档辅助」的链路就是闭环的,换机器也能复现。

最后给一个实用技巧:在项目根目录放一个Makefile,把常用命令固化下来:

.PHONY: run clean run: python msar_hamilton.py python msar_kns.py python msar_tvtp.py clean: rm -rf outputs/*.png

这样每次更新数据后,只需要make run,三个模型的平滑概率图会自动生成到outputs/目录。配合.env里的统一 Key,整个经济时间序列的区制转换分析流程就真正做到了可复制、可追溯。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询