相关性网络与最小生成树:用图论看清板块联动结构#
结论先行#
相关矩阵是个 的对称方阵,40 只股票就有 780 个数,眼睛根本读不出结构。把它翻译成一张图——节点是股票、边按相关性加权——再用最小生成树(MST)把”最能代表全局结构”的那 39 条边挑出来,市场会自己裂成几个清晰的板块簇。
MST 的妙处在于”最小”:它强制只用 条边连通全部节点、且总相关距离最小,于是每个板块内部紧密连通、跨板块只留下最”近”的少数桥接边。危机期板块间相关性飙升,MST 会”改道”、把原本远的板块直接拉通——联动结构的突变看得一清二楚。节点度分布还顺手暴露了少数枢纽股(度很大、牵一发动全身)。
下面用自洽合成数据演示:相关矩阵 → 距离 → Kruskal 求 MST(并查集实现,不依赖 networkx)→ 网络可视化与危机期改道。
一、为什么相关矩阵要”画成图”#
相关矩阵 告诉你两两关系,但它是二维表格,人脑读不出”谁和谁抱团”。图论换个角度:
- 节点(vertex):每只股票
- 边(edge):每对股票之间一条边,权重 = 相关性(或距离)
- 距离:把相关转成欧氏式距离,才能套用经典图算法 完全正相关 → 距离 0;完全负相关 → 距离 1;不相关 → 。距离越小 = 越同步。
画成全连接图会有 780 条边,糊成一团。MST 是降噪利器。
二、最小生成树:用最少的边保留骨架#
MST 是在全图上选 条边,连通所有节点,且总距离最小。对相关系数矩阵而言,“最小距离”等价于”保留最强的相关性联系、丢掉冗余的弱联系”。
Kruskal 算法(按边权升序贪心,跳过成环的边)最直观,核心是一个并查集(union-find)判环。下面是完整自洽实现,不依赖 networkx:
import numpy as np
def dist_from_corr(C):
Cc = np.clip(C, -1.0, 1.0)
return np.sqrt(np.clip(0.5 * (1.0 - Cc), 0.0, 1.0))
def kruskal_mst(Dmat):
N = Dmat.shape[0]
parent = list(range(N))
def find(x):
while parent[x] != x:
parent[x] = parent[parent[x]]
x = parent[x]
return x
edges = []
for i in range(N):
for j in range(i + 1, N):
edges.append((Dmat[i, j], i, j))
edges.sort() # 按距离升序
mst = []
for w, i, j in edges:
ri, rj = find(i), find(j)
if ri != rj: # 不在同一连通分量 → 不成都
parent[ri] = rj
mst.append((i, j, w))
if len(mst) == N - 1:
break
return mstpython跑完 kruskal_mst 拿到 39 条边,就是市场的”骨架”。
三、正常市场:MST 自己裂成板块簇#
合成 40 股分 4 板块、板块内相关 0.55~0.80、板块间接近 0。MST 画出来是这样:

四个颜色四个簇,每个板块内部用深色(短距离=强相关)边紧密连通,跨板块只有 3 条浅色桥接边。注意:MST 没有被告知”有 4 个板块”,它纯粹从相关性距离里把这个结构还原出来——这正是它的价值,板块划分是数据自己说的,不是你先验塞进去的。
四、放射状层级:谁是枢纽股#
把 MST 以度最大的节点为根,做 BFS 放射状布局,层级结构更清楚:枢纽在中心,叶子在最外层。

中心那个大节点(如 S24,度=5)就是”枢纽股”——它和多个板块都直接相连,是联动传导的关键节点。实务上,枢纽股的波动会最快扩散到全市场,是系统性风险的观察哨。
五、危机期:MST 改道,板块边界模糊#
危机期板块间相关性飙升(这里把板块间相关从 ~0 抬到 0.45)。距离被压缩,MST 被迫”改道”:

对比正常市场,跨板块的蓝色边明显增多,原本井水不犯河水的板块被 MST 直接拉通。这正对应真实市场的”危机时所有资产一起跌”——分散化失效的信号,写在 MST 的结构变化里。你甚至可以做”MST 跨板块边数”当危机监测指标。
六、节点度分布:少数枢纽、多数叶子#
MST 有 个节点、 条边,平均度 ≈ 2。但分布极不均匀——多数股票度=1(叶子,只连一只),少数股票度很大(枢纽):

合成里最大度=5、16/40 是叶子。真实市场更极端:指数权重股、龙头往往度极高,是组合风险传导的瓶颈。做对冲时,枢纽股的边际风险贡献要单独估。
七、代码串联:从相关矩阵到危机监测指标#
把前面几步拼成一条流水线,并量化”危机期 MST 改道”这件事——数一数跨板块边(桥接边)在正常 vs 危机下各有多少条。桥接边越多,说明板块边界越模糊、分散化越失效:
import numpy as np
def build_corr(within, between, SECT_N, seed=42):
"""构造板块结构相关矩阵(板块内强、板块间弱)。"""
r = np.random.default_rng(seed)
wv = within + 0.25 * r.random(len(SECT_N))
bv = between + 0.10 * r.random((len(SECT_N), len(SECT_N)))
np.fill_diagonal(bv, 0.0)
N = sum(SECT_N)
C = np.zeros((N, N))
idx, blocks = 0, []
for k, n in enumerate(SECT_N):
sl = slice(idx, idx + n); C[sl, sl] = wv[k]; blocks.append(sl); idx += n
for a in range(len(SECT_N)):
for b in range(a + 1, len(SECT_N)):
C[blocks[a], blocks[b]] = C[blocks[b], blocks[a]] = bv[a, b]
np.fill_diagonal(C, 1.0)
return C, blocks
def cross_edges(mst, blocks):
"""数 MST 里跨板块的桥接边数量。"""
sect = np.concatenate([[k]*n for k, n in enumerate(SECT_N)])
return sum(1 for (i, j, _) in mst if sect[i] != sect[j])
Cn, blocks = build_corr(0.55, 0.0, [10,10,10,10])
Cc, _ = build_corr(0.55, 0.45, [10,10,10,10]) # 危机期板块间相关飙升
mst_n = kruskal_mst(dist_from_corr(Cn))
mst_c = kruskal_mst(dist_from_corr(Cc))
print("正常期 跨板块桥接边数:", cross_edges(mst_n, blocks))
print("危机期 跨板块桥接边数:", cross_edges(mst_c, blocks))python跑出来会是”正常期 3 条、危机期更多”——这个差值就是可以直接钉进监控面板的危机信号。不用预测涨跌,只监控结构:桥接边一旦异常增多,就该降低组合集中度、把枢纽股权重砍一截。
八、真实陷阱:比想象中更硬的六类#
陷阱一:距离是相关性的单调变换,但不是唯一选择。 只是最常用的一族(基于角距离),还有基于收益率欧氏距离、基于互信息的变体。不同距离定义的 MST 结构会略有差异,别把一种当真理。
陷阱二:MST 只用 条边,丢信息。 它保留骨架、丢掉冗余边,但”冗余”里也有信息——两个板块间有 5 条强边 vs 1 条强边,风险含义完全不同,MST 看不出。要叠加全部边(按阈值过滤)才完整。
陷阱三:相关性本身是时变的。 用一年数据算的 MST,结构可能和上月不同。危机监测要滚动窗口重算,单张 MST 只是快照。
陷阱四:MST 的边权是线性相关,看不到非线性/尾部联动。 两只股票平时不相关、崩盘时同跌,线性 低估了真实联动,MST 也会误判为”远”。可改用尾部相关(如尾部 Clayton 依赖)重算距离。
陷阱五:并查集实现要路径压缩,否则大数据慢。 这里 无所谓,但 时朴素 find 会退化成 ;必须路径压缩 + 按秩合并,否则 Kruskal 卡死。
陷阱六:板块划分是启发式,不是统计检验。 MST 露出的簇”看起来像板块”,但没有 p 值说”这簇显著”。要真做板块聚类,应叠一层社区发现(如 Louvain)或层次聚类,MST 只是第一步可视化。
九、和层次风险平价(HRP)的关系#
如果你读过本专栏的层次风险平价,会发现它和本文是同一套世界观的两半:HRP 用距离矩阵做 Ward 层次聚类、再递归二分切权重,本质是”先看清板块结构、再按结构分散风险”;而 MST 是这套结构的最小骨架可视化——HRP 的聚类树里藏着 MST,MST 是那棵聚类树里权重最轻、不断开全图的那 39 条边。实务上可以先画 MST 看结构、再用 HRP 配权重,两件事拼起来才是”看得懂、也配得稳”。
十、诚实结论#
相关性网络 + MST 是一套”把看不见的结构画出来”的工具:相关矩阵是 780 个数,MST 是 39 条边,市场骨架一目了然。它不预测涨跌,但能回答三个实操问题——板块怎么分、谁是枢纽、危机时结构怎么变。
落地顺序:相关矩阵 → 距离变换 → Kruskal(并查集)→ 网络/放射可视化 + 滚动重算监测危机。先过本文六类陷阱,尤其”MST 丢信息""相关性时变""尾部联动看不见”这三关,再决定怎么用进组合构建与风险监控。
注:全文数据为自洽合成(40 只股票分 4 板块、板块内强相关板块间弱相关,危机期参数经数值校准使结构对比清晰),仅用于演示相关性网络与 MST 的图论机制。真实复现请替换为实际收益序列,并对距离定义、滚动窗口、尾部依赖与社区发现做稳健性检验。