ESG因子构建基础:从数据到信号
各位同学,欢迎来到实战课的第二讲。上一章我们聊了ESG因子为什么能赚钱,这一章我们得动真格的了——把ESG因子从概念变成可计算的数字。
说实话,ESG因子构建是整个策略中最枯燥、也最容易踩坑的环节。我做了这么多年量化,见过太多人拿着漂亮的ESG评分直接跑回测,结果一塌糊涂。为什么?因为数据源没搞清楚,指标定义有偏差,清洗步骤漏掉了。
今天我们就来拆解E、S、G三大维度的核心指标,以及数据怎么拿、怎么洗。嗯,这部分内容虽然基础,但决定了你后面所有工作的成败。
核心观点:ESG因子不是简单的评分加总,而是需要根据行业特性、数据质量、时效性进行精细化构建。一个粗糙的ESG因子,还不如不用。
一、环境(E)因子:碳排与资源效率
环境因子是ESG里最「硬」的一块。为什么?因为碳排放、能耗这些数据相对可量化,不像「企业文化」那么虚。我个人习惯把E因子拆成三个子维度:
- 碳排放强度:范围1(直接排放)+ 范围2(能源间接排放),除以营收。这是最核心的指标。
- 能源效率:单位营收能耗,或者单位产品能耗。不同行业差异巨大,钢铁和互联网没法比。
- 环境管理:有没有环境认证?有没有环境违规记录?这个偏定性,但也很重要。
实战技巧:我在做A股ESG因子时发现,很多公司不披露范围3(供应链排放)。这时候别硬算,直接用范围1+2就够了。数据缺失本身也是一种信号——不披露的公司往往环境风险更高。
举个例子,我们拿万得ESG数据里的碳排放字段,通常长这样:
# 伪代码:碳排放强度计算
df['carbon_intensity'] = df['scope1_emission'] + df['scope2_emission']
df['carbon_intensity_ratio'] = df['carbon_intensity'] / df['revenue'] * 1e6 # 吨/百万元
你想想看,同样的碳排放量,放在一家万亿市值的银行和一家百亿市值的化工企业里,意义完全不同。所以一定要做营收标准化。
二、社会(S)因子:人、产品与社区
S因子是最难量化的。我刚开始做ESG研究时,最头疼的就是S因子——你说员工满意度怎么量化?总不能每个季度发问卷吧?
实践中,我们通常用这些代理变量:
| 子维度 | 常用指标 | 数据来源 |
|---|---|---|
| 员工关系 | 员工流失率、人均培训时长、薪酬水平 | 年报、社会责任报告 |
| 产品安全 | 产品召回次数、质量认证、客户投诉率 | 监管公告、第三方评测 |
| 社区关系 | 公益捐赠占比、本地化采购比例 | 企业ESG报告 |
| 供应链责任 | 供应商ESG审核覆盖率、冲突矿产政策 | 供应链披露文件 |
避坑指南:我曾经踩过一个坑——直接用「员工人数」作为S因子。结果发现,劳动密集型行业天然得分高,科技公司反而低。这完全颠倒了逻辑。后来我改用「人均培训投入」和「员工流失率」的组合,效果才正常。
这里有个关键点:S因子指标之间经常存在多重共线性。比如「人均薪酬」和「员工流失率」高度相关。我建议用PCA或者因子分析先降维,别一股脑全塞进去。
三、治理(G)因子:公司质量的底色
治理因子,说白了就是看这家公司是不是在「好好经营」。我个人认为G因子是ESG三兄弟里最稳定的——E和S可能受行业影响大,但好的治理在任何行业都管用。
核心指标包括:
- 董事会独立性:独立董事占比、董事长是否兼任CEO
- 股权结构:大股东持股比例、机构投资者占比
- 信息披露质量:财务重述次数、审计意见类型
- 高管薪酬:薪酬与业绩的挂钩程度、股权激励比例
我记得有一次做回测,发现G因子在熊市里特别能抗跌。为什么?因为治理好的公司,管理层不会乱投资、不会搞利益输送,现金流更稳健。嗯,这个逻辑在A股尤其明显。
# 治理评分示例
def governance_score(df):
score = 0
# 独立董事占比 > 1/3 加1分
score += (df['indep_director_ratio'] > 0.333).astype(int)
# 董事长不兼任CEO 加1分
score += (df['chairman_ceo_separate'] == 1).astype(int)
# 近3年无财务重述 加1分
score += (df['restatement_3y'] == 0).astype(int)
return score / 3 # 归一化到0-1
四、数据来源与清洗:80%的功夫在这里
做量化的人都知道一句话:garbage in, garbage out。ESG数据尤其如此。我见过太多人从万得或者Bloomberg拉下来数据就直接用,结果回测曲线漂亮得不像话——后来发现是数据前向填充导致的未来函数。
常用的数据源有:
- 万得ESG数据:覆盖A股最全,但部分指标更新频率低(季度甚至年度)
- 商道融绿:ESG评级数据,适合做截面比较
- 中财绿金院:偏学术,有碳排放估算数据
- 公司年报/ESG报告:最原始的数据源,但需要NLP提取
清洗环节,我建议按这个流程走:
- 缺失值处理:ESG数据缺失率经常超过30%。别直接删,试试行业均值填充,或者用「缺失即差」的逻辑(缺失值赋最低分)。
- 异常值检测:比如碳排放强度突然翻10倍,大概率是数据录入错误。用3-sigma或者IQR方法处理。
- 标准化:不同指标量纲差异巨大,必须做Z-score或者Min-Max归一化。
- 行业调整:这是ESG因子构建的灵魂。银行和钢铁的碳排放强度能比吗?不能。所以要做行业内标准化。
核心代码:行业调整标准化
def industry_neutralize(df, factor_col, industry_col):
"""
行业中性化处理:在每个行业内做Z-score标准化
"""
df['factor_z'] = df.groupby(industry_col)[factor_col].transform(
lambda x: (x - x.mean()) / x.std()
)
return df
# 使用示例
df = industry_neutralize(df, 'carbon_intensity_ratio', 'sw_industry')
# 注意:碳排放是负向指标,标准化后要取负号
df['e_score'] = -df['factor_z']
你想想看,如果不做行业调整,你拿到的ESG因子其实反映的是「行业属性」而不是「公司质量」。煤炭股天然E因子低,但你不能说所有煤炭公司都不好——得在同行业里比谁做得更好。
我的经验:数据清洗这一步,我通常会花整个项目60%的时间。别嫌慢,后面回测阶段出问题再回头找数据原因,那才叫痛苦。我曾经因为一个数据对齐错误,浪费了两周时间——从那以后,我每步清洗都写日志。
好了,这一章的内容就到这里。ESG因子构建是个细活,E、S、G每个维度都有各自的脾气。下一章我们会把这些因子组合起来,看看怎么在行业轮动策略里真正用起来。
公众号:蓝海资料掘金营,微信deep3321