halo 的技术博客

返回

2021 年那颗汽车芯片,让无数整车厂停产;一家果链公司被踢出供应链,股价一天腰斩。一家公司的基本面风险,很大一部分不在它自己利润表里,而在它最依赖的那几个名字手里。 客户集中度、供应商集中度,就是给这种「依赖风险」量化的尺子。本文把它做成一个可回测的横截面因子。

直觉很直接:客户集中度高的公司,前两大客户贡献一半营收,其中一个不续约,收入就塌一块;供应商集中度高的公司,关键原材料只有一两家能供,断供或涨价就直接吃进毛利。反之,客户分散、供应商多元的公司,单点失效伤不到筋骨。多低集中度、空高集中度,赚的就是『单点依赖的脆弱性折价』。

一、用 HHI 量化集中度#

集中度用赫芬达尔指数(HHI)度量。给定一家公司的客户份额向量 w=(w1,...,wk)w = (w_1, ..., w_k)

HHIc=j=1kwj2HHI_c = \sum_{j=1}^{k} w_j^2

份额越平均,HHI 越接近 1/k1/k;份额越集中到一两家,HHI 越接近 1。供应商侧同理 HHIsHHI_s。我们用 Dirichlet 抽样合成份额,再平方求和:

import numpy as np

N, T = 150, 240
rng = np.random.default_rng(20260721)

def make_hhi(n_cust, alpha_conc):
    base = rng.dirichlet([alpha_conc] * n_cust, size=N)
    return (base**2).sum(1)              # 真实 HHI, 前 n_cust 大份额

HHI_c = make_hhi(4, 1.0)                  # 客户集中度(前 4 大客户)
HHI_s = make_hhi(4, 0.9)                  # 供应商集中度(前 4 大供应商)
size = rng.lognormal(0, 0.6, N)
python

图 1 是合成的客户集中度分布,跨度从 0.25 到 0.78——足够让分组有区分度(真实 A 股前五大客户占比中位数约 30%,HHI 与此同源)。

客户集中度 HHI 分布(合成 150 家,份额 Dirichlet 抽样)

二、注入「依赖冲击」:风险如何变成亏损#

我们用一个隐藏的「依赖冲击」事件来释放集中度风险——在 150–175 月注入一次大客户流失的需求冲击,和一次断供的供给冲击:

MKT = rng.normal(0.008, 0.04, T-1)
demand_shock = np.zeros(T-1)
supply_shock = np.zeros(T-1)
for t in range(150, 175):
    demand_shock[t] = rng.normal(-0.05, 0.02)   # 大客户流失: 收入塌
    supply_shock[t] = rng.normal(0.045, 0.02)   # 断供: 成本升/停产

beta = rng.normal(1.0, 0.3, N)
kappa, sb_c, sb_s = 0.009, 3.0, 2.4
R = (MKT[None, :]
     + beta[:, None] * MKT[None, :]
     - kappa * HHI_c[:, None]                    # 持续脆弱性折价
     + sb_c * HHI_c[:, None] * demand_shock[None, :]   # 大客户流失 -> 高集中度亏更狠
     - sb_s * HHI_s[:, None] * supply_shock[None, :]   # 断供 -> 高集中度亏更狠
     + rng.normal(0, 0.018, (N, T-1)))
python

关键设计:需求/供给冲击都乘以 HHI,所以冲击对高集中度公司是放大器,对低集中度公司几乎无感。图 2 把 140–185 月的累计净值拆出来——高集中度组在冲击期明显下沉,低集中度组基本走平。这就是因子 alpha 的物理来源。

冲击期(150-175m): 高集中度组被重定价, 低集中度组免疫

三、构建因子:空高集中度 / 多低集中度#

和碳因子一样,按 HHI 分五分位,多空组合:

order = np.argsort(HHI_c)
n = N // 5
groups = [order[i*n:(i+1)*n] for i in range(5)]
grp_ret = np.array([R[g, :].mean(0) for g in groups])   # (5, T-1)
scc_factor = grp_ret[0] - grp_ret[4]                    # 多 Q1(低) / 空 Q5(高)
python

净值见图 3。因子年化 9.5%、Sharpe 1.66,且红色阴影区(危机期)贡献了绝大部分上行——这是一个典型的「危机保险型」因子:平时赚一点脆弱性折价,危机时赚一大笔依赖风险重定价。

供应链集中度因子净值: alpha 主要集中在危机期

四、横截面检验:t 统计量说了算#

因子有没有「统计上的存在感」,要看横截面回归的 t 值。控制市场和规模后,回归个股月均收益对 HHI:

def xs_reg(y, Xcols):
    X = np.column_stack([np.ones(N)] + Xcols)
    coef, *_ = np.linalg.lstsq(X, y, rcond=None)
    resid = y - X @ coef
    dof = N - X.shape[1]
    se = np.sqrt((resid @ resid)/dof) * np.sqrt(np.diag(np.linalg.inv(X.T @ X)))
    return coef, se

coef, se = xs_reg(R.mean(1), [HHI_c, size])
t_HHI = coef[1] / se[1]          # ≈ -15.7
python

t(HHI) = −15.7,远超过 |2| 的显著性门槛,负号说明「客户集中度越高,收益越低」。图 4 的拟合线直观展示这条负斜率。注意我们控制了 size——否则小公司天然更脆弱,集中度效应会和规模效应混淆。

横截面: 客户集中度越高, 收益越低(t 显著)

五、五分位单调性#

def ann(r): return (np.prod(1 + r))**(12/len(r)) - 1
dec_ann = np.array([ann(grp_ret[k]) for k in range(5)])
# 从 Q1(低 ci) 到 Q5(高 ci) 单调下行
python

图 5 显示五分位年化收益严格随客户集中度升高而下降——因子是「干净」的单调暴露,不是头尾两组臆造。

五分位年化收益: 客户集中度越高收益越低

六、六类真实陷阱#

  1. 披露失真与滞后:年报只披露「前五大客户占比」,不给完整份额向量,你算出的 HHI 是下界估计;且披露滞后一整年,而在芯片荒、疫情那种冲击里,集中度风险是即时释放的——数据频率卡死了因子的反应速度
  2. 共同冲击混淆:一次全行业需求下行,会让所有公司一起跌,高低集中度组都亏。本文把冲击设成「乘 HHI」来分离纯度,但真实世界里你很难证明某次下跌「纯粹来自客户集中」还是「来自宏观」。
  3. 幸存者偏差(最致命):高集中度公司如果因为大客户流失而退市/ST,它会从面板里消失,你算 HHI 时只看到「活下来的低集中度公司」——因子效果会被幸存者偏差系统性高估。必须用含退市的全样本。
  4. 行业结构混淆:ToB 制造业天然客户集中(给主机厂供货),ToC 消费天然分散。不做行业中性化,你交易的其实是「制造业空头」。和碳因子一样,行业中性化是必做项
  5. 集中度 ≠ 风险:极少数公司是「主动集中」——比如独家供应某爆款、议价权极强,高集中度反而是护城河。把这类公司和高集中度脆弱公司混在一起做空,会吃到哑巴亏。实战要用「集中度 × 议价能力(毛利率/转换成本)」做二阶过滤。
  6. 做空成本与可得性:因子要空高集中度组,但这类公司常是小盘、低流动性,借券难、冲击成本高;A 股几乎不可直接做空,退化成「只多低集中度」后,因子从「危机保险」变成「平时小幅跑赢」,Sharpe 结构会变。

七、落地清单#

  • 数据层:拉取年报「前五大客户/供应商占比」,对单一大客户占比 >30% 直接标红;用行业中位数补全未披露项;
  • 组合层:组内等权、季度调仓(匹配披露频率)、强制申万一级行业内中性化;
  • 二阶过滤:在空高集中度组里剔除「高毛利 + 高转换成本」的主动集中型公司,避免做空真护城河;
  • 危机增强:当宏观进入供应链压力窗口(如运价/芯片库存异动),临时超配该因子作为组合保险。

结语#

供应链集中度因子量化的是一句大白话:你的命脉攥在几个人手里,你就有多脆弱。 客户/供应商 HHI 越高,单点失效时的收入塌方、成本飙升就越狠。本文用自洽合成证明:横截面 t 统计量 −15.7、年化 9.5%、Sharpe 1.66,且 alpha 几乎全部来自危机期(71.9% vs 平静 3.9%)——它是一个典型的「危机保险型」因子。但六类陷阱里,幸存者偏差和披露滞后是真正会让你在实盘里栽跟头的两道坎:你回测看到的漂亮曲线,可能只是因为最惨的那批公司已经「消失」在数据里了。

供应链集中度因子:用客户/供应商依赖量化基本面风险
https://blog.halo26812.eu.org/blog/supply-chain-concentration-factor
Author halo
Published at 2026年7月20日
版权声明 CC BY-NC-SA 4.0
Comment seems to stuck. Try to refresh?✨