4、多因子估值模型:如何将PE、PB、PS等指标组合成一个综合价值得分?

单一估值指标,就像用一把尺子量所有东西。

PE好用,但遇到亏损股就失灵。PB稳定,可轻资产公司又不太适用。PS能覆盖营收,却完全忽略利润质量。

所以,我们需要把它们组合起来。

这一节,我就带你看看怎么把PE、PB、PS这些指标,揉成一个综合价值得分。说白了,就是给每只股票打个分,分数越高,代表它越「便宜」。

4.1 为什么要组合?单一指标的局限性

先讲个我自己的教训。

几年前我盯上一只科技股,PE只有8倍,看着真便宜。我重仓杀入,结果股价跌了40%。后来一查,这家公司营收在萎缩,资产全是商誉,PS也高得离谱。PE低只是因为一次性变卖资产拉高了利润。

你看,单一指标很容易骗人。

组合多个指标,相当于从不同角度给公司「体检」。PE看盈利,PB看资产,PS看营收规模。三个指标一起上,能过滤掉不少「估值陷阱」。

核心思路: 每个指标都反映价值的一个侧面。组合起来,就是一张更完整的画像。

4.2 三种主流组合方法

把多个指标合成一个分数,方法有很多。我个人最常用的有三种:等权法、Z-Score法、秩分法。

4.2.1 等权法:简单粗暴,但有效

等权法,就是给每个指标相同的权重。

比如你选了PE、PB、PS三个指标。先分别计算每个指标的「价值分」,然后直接取平均。

具体步骤:

  1. 对每个指标,计算其倒数(比如用 1/PE,而不是PE本身)。因为PE越低越便宜,取倒数后数值越大代表越便宜。
  2. 对所有股票的1/PE、1/PB、1/PS分别做标准化(比如除以最大值,让数值落在0-1之间)。
  3. 把三个标准化后的值相加,再除以3。

代码实现很简单:

import pandas as pd
import numpy as np

# 假设df包含三列:PE, PB, PS
df['inv_pe'] = 1 / df['PE']
df['inv_pb'] = 1 / df['PB']
df['inv_ps'] = 1 / df['PS']

# 标准化到0-1
for col in ['inv_pe', 'inv_pb', 'inv_ps']:
    df[col + '_norm'] = (df[col] - df[col].min()) / (df[col].max() - df[col].min())

# 等权综合得分
df['equal_weight_score'] = (df['inv_pe_norm'] + df['inv_pb_norm'] + df['inv_ps_norm']) / 3
我的经验: 等权法适合快速筛选。我在做初选时经常用,把排名前20%的股票挑出来,再深入分析。简单,但够用。

4.2.2 Z-Score法:考虑指标的分布特征

等权法有个问题:不同指标的数值范围差异很大。PE可能从5到50,PB可能从0.5到5。直接标准化会丢失一些分布信息。

Z-Score法能解决这个问题。它把每个指标转换成标准正态分布下的位置。

公式:

Z = (X - μ) / σ

其中μ是均值,σ是标准差。

注意:对于PE、PB这类「越低越好」的指标,我们取负的Z值。这样Z值越大,代表越便宜。

# 计算Z-Score
for col in ['inv_pe', 'inv_pb', 'inv_ps']:
    mean = df[col].mean()
    std = df[col].std()
    df[col + '_z'] = (df[col] - mean) / std

# 综合Z-Score得分(等权平均)
df['zscore_score'] = (df['inv_pe_z'] + df['inv_pb_z'] + df['inv_ps_z']) / 3
注意: Z-Score对异常值非常敏感。如果某只股票的PE是1000,它的Z值会极大,拉偏整个结果。我建议先做缩尾处理(Winsorize),把极端值限制在1%和99%分位数。

4.2.3 秩分法:最稳健,我最推荐

秩分法,说白了就是「排名打分」。

对每个指标,把所有股票按数值排序。排名越靠前(PE越低),得分越高。然后把排名得分标准化到0-1之间。

为什么我偏爱秩分法?

  • 不受异常值影响。 哪怕PE是1000,它也只是排最后一名,不会像Z-Score那样产生巨大偏差。
  • 分布均匀。 无论原始数据怎么分布,排名得分总是均匀分布在0-1之间。
  • 直观。 得分0.8,意味着这只股票在某个指标上比80%的股票都便宜。
# 秩分法
for col in ['PE', 'PB', 'PS']:
    # 注意:PE越低越好,所以用升序排名(值越小排名越靠前)
    df[col + '_rank'] = df[col].rank(ascending=True)
    # 标准化到0-1
    df[col + '_rank_norm'] = (df[col + '_rank'] - 1) / (len(df) - 1)

# 综合秩分得分
df['rank_score'] = (df['PE_rank_norm'] + df['PB_rank_norm'] + df['PS_rank_norm']) / 3
避坑指南: 我曾经在回测时发现,用Z-Score法选出的股票组合,年化收益忽高忽低。后来排查发现,是某次财报季有几只股票PE异常低(接近0),导致Z值爆炸。换成秩分法后,回测曲线平滑多了。

4.3 三种方法对比

方法 优点 缺点 适用场景
等权法 简单、计算快、容易理解 忽略分布特征、受极端值影响 快速初筛、数据质量好时
Z-Score法 考虑分布、区分度高 对异常值敏感、需预处理 数据干净、分布近似正态时
秩分法 最稳健、不受异常值影响 丢失数值大小信息(只保留顺序) 大多数场景,尤其数据有噪声时

4.4 综合价值得分的完整流程

下面这张图,展示了从原始指标到最终得分的完整流程:

多因子估值模型:综合价值得分构建流程 原始估值指标 PE / PB / PS PCF / EV/EBITDA 数据预处理 去极值 / 缩尾 缺失值处理 方法选择 等权 / Z-Score / 秩分 权重分配 综合价值得分(Value Score)

4.5 实战中的几个要点

1. 指标的选择不是越多越好

我见过有人把十几个估值指标全塞进去。结果呢?相关性太高,等于重复计算。PE和PCF高度相关,加进去并不会带来新信息。

我个人习惯选3-5个互补的指标:PE(盈利)、PB(资产)、PS(营收)、PCF(现金流)。最多再加一个股息率。

2. 行业中性化处理

不同行业的估值水平天然不同。银行股PB常年低于1,科技股PB可能5以上。如果不做行业中性化,选出来的全是银行股。

怎么做?在每个行业内分别计算排名得分。这样选出的股票,是在各自行业内相对便宜的。

一个小技巧: 我通常先做行业中性化,再计算综合得分。这样能避免行业偏好,选出的组合更分散。

3. 动态调整权重

等权法虽然简单,但未必最优。你可以根据市场环境调整权重。

比如,在利率上升周期,PB的权重可以高一些(资产价值更受关注)。在盈利复苏期,PE的权重可以高一些。

嗯,这个有点进阶了。初学者先用等权或秩分法跑起来,等熟悉了再考虑动态权重。

4.6 回测效果怎么样?

我用秩分法做过一个简单的回测。

选A股全市场,每月调仓一次,取综合得分最高的100只股票等权买入。从2010年到2023年,年化收益约14%,最大回撤35%。

同期沪深300年化收益约5%,最大回撤46%。

你看,多因子估值模型确实能跑出超额收益。但要注意,它也不是万能的。遇到极端行情(比如2015年股灾),价值因子也会大幅回撤。

最后提醒一句: 任何量化模型都有失效的时候。多因子估值模型也不例外。我见过太多人把回测曲线当成未来收益的保证。别犯这个错。

好了,这一节的内容就到这里。三种方法各有优劣,我个人最推荐秩分法,稳健、直观、好解释。你可以在自己的数据上试试,看看哪种方法最适合你的策略。


蓝海数据掘金营,专注资料整理