用 Python 搞懂市场风向标:5 步搭建 ML 市场状态检测系统

chengsenw 网络营销评论1阅读模式

用 Python 搞懂市场风向标:5 步搭建 ML 市场状态检测系统

用 Python 搞懂市场风向标:5 步搭建 ML 市场状态检测系统

2026年重磅升级已全面落地!欢迎加入专注财经数据与量化投研的【数据科学实战】知识星球!您将获取持续更新的《财经数据宝典》与《量化投研宝典》,双典协同提供系统化指引;星球内含300篇以上独有高质量文章,深度覆盖策略开发、因子分析、风险管理等核心领域,内容基本每日更新;同步推出的「量化因子专题教程」系列(含完整可运行代码与实战案例),系统详解因子构建、回测与优化全流程,并实现日更迭代。我们持续扩充独家内容资源,全方位赋能您的投研效率与专业成长。无论您是量化新手还是资深研究者,这里都是助您少走弯路、事半功倍的理想伙伴,携手共探数据驱动的投资未来!

引言

你是否好奇过,为什么金融市场总让人"反复打脸"?明明看好的行情,说崩就崩?

这背后的核心原因之一,是市场存在不同的"状态"(Regime)——牛市、熊市、震荡市各有特征,而大多数预测模型却默认市场始终处于同一种状态。

本文将基于一篇最新的技术文章,带你了解如何用 Python 构建一套完整的混合机器学习(Hybrid ML)市场状态检测系统,涵盖数据获取、特征工程、无监督学习(PCA + K-Means)、有监督分类(Random Forest)以及可解释性分析(IML)5 大步骤。即使你还在学习 Python 的路上,也能从中获得实用的项目思路和代码技巧。


一、整体架构:5 步流水线

原文提出了一个清晰的 5 步流水线:

  1. 1. 读取交易工具数据:获取 SPY、IWM、HYG、LQD、VIX 等 ETF 和指数的历史行情
  2. 2. 准备 ML 训练数据:计算日收益率、信用利差、已实现波动率、回撤等特征
  3. 3. PCA 降维 + K-Means 聚类:用无监督学习发现隐藏的市场状态
  4. 4. 有监督 ML 分类 + 交叉验证:用随机森林对市场状态进行分类
  5. 5. 可解释机器学习(IML)可视化:用 Scikit-Plot 和 Yellowbrick 解读模型

二、为什么选这 5 个交易工具?

原文选择了以下 5 个核心工具,它们构成了一个跨资产的市场风险快照:

  • • SPY:追踪标普 500,代表美国大盘股,是风险偏好的基准
  • • IWM:追踪罗素 2000,代表小盘股,Beta 更高
  • • HYG:高收益公司债 ETF,反映信用压力
  • • LQD:投资级公司债 ETF,帮助区分流动性压力和利率驱动的变化
  • • VIX:恐慌指数,捕捉尾部风险定价

三、关键步骤详解与代码示例

步骤 1:获取数据

使用 EODHD API 获取历史 EOD(End-of-Day)数据:

import pandas as pd
import
 numpy as np
import
 requests

API_KEY = "your_api_key"  # 替换为你自己的 API Key
start_date = "2021-01-04"
end_date = "2026-02-20"

def
 fetch_eod(symbol, start_date, end_date):
    """
    从 EODHD 获取指定标的的日线数据。
    """

    url = f"https://eodhd.com/api/eod/{symbol}"
    params = {
        "api_token"
: API_KEY,
        "from"
: start_date,
        "to"
: end_date,
        "fmt"
: "json"
    }
    resp = requests.get(url, params=params)
    data = resp.json()
    df = pd.DataFrame(data)
    df = df.sort_values("date")
    df["date"] = pd.to_datetime(df["date"])
    df.set_index("date", inplace=True)
    return
 df

# 获取各标的数据

spy_df = fetch_eod("SPY.US", start_date, end_date)
iwm_df = fetch_eod("IWM.US", start_date, end_date)
hyg_df = fetch_eod("HYG.US", start_date, end_date)
lqd_df = fetch_eod("LQD.US", start_date, end_date)
vix_df = fetch_eod("VIX.VN", start_date, end_date)

步骤 2:特征工程

这一步构建了大量宏观金融因子,包括信用利差、多窗口收益率、已实现波动率、VIX 衍生指标和回撤等。以下是几个核心特征的计算方式:

df = spy_df.copy()

# 信用利差(代理):高收益债与投资级债的对数价差

df["Credit_Spread"] = np.log(hyg_df['adjusted_close']) - np.log(lqd_df['adjusted_close'])

# SPY 不同窗口的收益率

df["SPX_Daily_Return"] = spy_df['close'].pct_change()       # 日收益率
df["SPX_21D_Return"]   = spy_df['close'].pct_change(21)     # 21 日收益率
df["SPX_63D_Return"]   = spy_df['close'].pct_change(63)     # 63 日收益率
df["SPX_126D_Return"]  = spy_df['close'].pct_change(126)    # 126 日收益率

# 已实现波动率:滚动标准差 × sqrt(252) 进行年化

def
 realized_vol(series, window=21, trading_days=252):
    return
 series.rolling(window).std() * np.sqrt(trading_days)

df["SPX_21D_RealVol"] = realized_vol(df["SPX_Daily_Return"], window=21)

# 6 个月回撤:当前价格相对于 126 日滚动最高价的跌幅

spx_roll_max = spy_df["close"].rolling(126, min_periods=1).max()
df["SPX_126D_Drawdown"] = spy_df["close"] / spx_roll_max - 1.0

# 清除缺失值

df = df.dropna().reset_index(drop=True)

学习要点pct_change(n) 计算 n 期百分比变化,rolling(window).std() 计算滚动标准差——这两个函数在金融时间序列分析中极为常用。

步骤 3:PCA 降维 + K-Means 聚类

先标准化特征,再用 PCA 提取主成分,最后用 K-Means 将数据聚成不同的市场状态:

from sklearn.preprocessing import StandardScaler
from
 sklearn.decomposition import PCA
from
 sklearn.cluster import KMeans
from
 sklearn.metrics import silhouette_score

# 标准化:均值为 0,标准差为 1

scaler = StandardScaler()
X_scaled = scaler.fit_transform(X_df.values)

# PCA 降维,保留 95% 的方差

variance_target = 0.95
pca = PCA()
X_pca = pca.fit_transform(X_scaled)
explained_var = pca.explained_variance_ratio_

# 确定需要保留的主成分数量

n_components = np.argmax(np.cumsum(explained_var) >= variance_target) + 1
X_pca_reduced = X_pca[:, :n_components]
print
(f"保留 {n_components} 个主成分,解释 {np.cumsum(explained_var)[n_components-1]:.3f} 的方差")
# 输出示例:保留 13 个主成分,解释 0.962 的方差


# 用轮廓系数选择最佳聚类数

def
 silhouette_over_k(X, k_min=2, k_max=6, seed=42):
    scores = {}
    for
 k in range(k_min, k_max + 1):
        km = KMeans(n_clusters=k, n_init=50, random_state=seed)
        labels = km.fit_predict(X)
        scores[k] = silhouette_score(X, labels)
    return
 scores

scores_pca = silhouette_over_k(X_pca_reduced, 2, 6)
print
("轮廓系数:", {k: round(v, 3) for k, v in scores_pca.items()})
# 输出示例:{2: 0.233, 3: 0.191, 4: 0.173, 5: 0.186, 6: 0.178}


# 使用最佳 k 进行聚类

best_k = max(scores_pca, key=scores_pca.get)
kmeans = KMeans(n_clusters=best_k, n_init=50, random_state=42)
final_labels = kmeans.fit_predict(X_pca_reduced)

学习要点:轮廓系数(Silhouette Score)范围为 -1 到 1,越接近 1 表示聚类质量越好。原文最终选择了 k=2,即将市场分为两种状态。

步骤 4:随机森林分类

将 K-Means 的聚类标签作为目标变量,训练有监督分类模型:

from sklearn.model_selection import train_test_split
from
 sklearn.ensemble import RandomForestClassifier
from
 sklearn.metrics import accuracy_score, classification_report

# 70% 训练,30% 测试,分层采样保持类别比例

X_train, X_test, y_train, y_test = train_test_split(
    X_pca_reduced, final_labels,
    test_size=0.3, random_state=42, stratify=final_labels
)

# 训练随机森林分类器

clf = RandomForestClassifier(n_estimators=100, random_state=42)
clf.fit(X_train, y_train)

# 预测并评估

y_pred = clf.predict(X_test)
print
("准确率:", accuracy_score(y_test, y_pred))
# 输出:准确率:0.985


print
(classification_report(y_test, y_pred, target_names=["Regime 0", "Regime 1"]))

原文的分类报告显示,精确率、召回率和 F1 分数均达到 0.98-0.99,模型表现非常优秀。

步骤 5:可解释机器学习(IML)

这一步使用 Scikit-Plot 和 Yellowbrick 对模型进行多角度诊断:

import scikitplot as skplt
from
 yellowbrick.classifier import ROCAUC, DiscriminationThreshold

# 校准曲线:检查预测概率是否与实际结果一致

y_probas = clf.predict_proba(X_test)
skplt.metrics.plot_calibration_curve(y_test, [y_probas], ['Random Forest'], n_bins=15)

# KS 统计量:衡量模型区分两个类别的能力

skplt.metrics.plot_ks_statistic(y_test, y_probas)
# 原文 KS 值为 0.98,说明模型区分度极高


# ROC 曲线:使用 Yellowbrick 可视化

viz = ROCAUC(RandomForestClassifier(random_state=123))
viz.fit(X_train, y_train)
viz.score(X_test, y_test)
viz.show()
# 原文 AUC 达到 1.0

原文还发现一个重要的实践洞见:最佳分类阈值约为 0.3 而非默认的 0.5。这意味着在实际应用中,当模型给出 30% 的状态切换概率时就应该引起警觉,从而实现更早的风险预警。


四、市场状态的直觉理解

原文对 2021-2026 年的市场做了定性解读:

  • • 2021 年:流动性驱动的平稳上涨,各标的同步走高,VIX 保持低位
  • • 2022 年:全面紧缩冲击,股债双杀,VIX 持续高企
  • • 2023 年:窄幅复苏,大盘股领涨,小盘股和债券横盘
  • • 2024 年:全面扩张,各标的同步上行
  • • 2025 年:晚周期特征,大盘股缓慢攀升,小盘股落后

这些"状态"正是 K-Means 聚类试图自动识别的模式。


总结

这篇文章展示了一个完整的 Python 市场状态检测流水线,核心思路可以总结为:

  1. 1. 数据为王:跨资产的高质量历史数据是一切分析的基础
  2. 2. 无监督发现模式:PCA 降维 + K-Means 聚类,自动找到隐藏的市场状态
  3. 3. 有监督学习预测:随机森林等分类器可以在新数据上复现这些状态判断
  4. 4. 可解释性不可少:通过校准曲线、KS 统计量、ROC 曲线等工具,理解模型"为什么"做出这样的判断

对于 Python 学习者而言,这个项目涉及 Pandas 数据处理、Scikit-Learn 机器学习、Matplotlib/Seaborn 可视化等核心技能,是一个非常好的综合练手项目。

⚠️ 免责声明:本文内容仅供学习和教育目的,不构成任何投资建议。任何投资决策请自行承担风险。


参考文章

加入专注于财经数据与量化投研的知识星球【数据科学实战】,获取本文完整研究解析、代码实现细节。

财经数据与量化投研知识社区

2026年全面升级已落地!【数据科学实战】知识星球核心权益如下:

  1. 1. 双典系统赋能:获赠《财经数据宝典》与《量化投研宝典》完整文档,凝练多年实战经验,构建系统化知识框架;
  2. 2. 量化因子日更教程(2026重磅新增):每日更新「量化因子专题教程」,配套完整可运行代码与实战案例,深度拆解因子构建、回测与优化全流程;
  3. 3. 量化文章专题教程库:300+篇星球独有高质量教程式文章,系统覆盖策略开发、因子研究、风险管理等核心领域,内容基本每日更新,并配套精选学习资料与实战参考;
  4. 4. PyBroker实战课程:赠送《PyBroker-入门及实战》视频课程,手把手教学,快速掌握量化策略开发技能;
  5. 5. 财经数据支持:定期更新国内外财经数据,为策略研发提供精准、可靠的数据基础;
  6. 6. 顶尖学者与行业专家分享:年度邀请学术界博士与业界资深专家开展前沿论文精讲与实战案例分享,不少于4场,直击研究前沿与产业实践;
    专家直连答疑:与核心开发者及领域专家实时互动,高效解决投研实战难题;
  7. 7. 专业社群与专属福利:加入高质量交流社群,获取课程折扣及更多独家资源。

星球已沉淀丰富内容生态——涵盖量化文章专题教程库、因子日更系列、高频数据集、PyBroker实战课程、专家深度分享与实时答疑服务。无论您是初探量化的学习者,还是深耕领域的从业者,这里都是助您少走弯路、高效成长的理想平台。诚邀加入,共探数据驱动的投资未来!

好文推荐

1. 用 Python 打造股票预测系统:Transformer 模型教程(一)

2. 用 Python 打造股票预测系统:Transformer 模型教程(二)

3. 用 Python 打造股票预测系统:Transformer 模型教程(三)

4. 用 Python 打造股票预测系统:Transformer 模型教程(完结)

5. 揭秘隐马尔可夫模型:因子投资的制胜武器

6. YOLO 也能预测股市涨跌?计算机视觉在股票市场预测中的应用

7. 金融 AI 助手:FinGPT 让你轻松掌握市场分析

8. 量化交易秘籍:为什么专业交易员都在用对数收益率?

9. Python 量化投资利器:Ridge、Lasso 和 Elastic Net 回归详解

10. 掌握金融波动率模型:完整 Python 实现指南

好书推荐

 
chengsenw
  • 本文由 chengsenw 发表于 2026年3月18日 00:41:06
  • 转载请务必保留本文链接:https://www.gewo168.com/13086.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: