ESG数据获取与清洗:主流数据源与预处理实战
做ESG因子预测,第一步就是搞数据。说实话,这一步往往是最磨人的。我见过太多团队,模型建得花里胡哨,结果数据源选错了,或者清洗不到位,最后全白干。今天咱们就聊聊ESG数据从哪来、怎么洗、怎么标准化。
主流ESG数据源:三巨头对比
目前市场上主流的ESG数据供应商有三家:MSCI、Sustainalytics和Refinitiv。这三家我都用过,各有各的脾气。
| 数据源 | 覆盖范围 | 评分体系 | 更新频率 | 我的评价 |
|---|---|---|---|---|
| MSCI | 约8,500家公司 | AAA-CCC七档 | 月度/季度 | 覆盖面广,但新兴市场数据稀疏 |
| Sustainalytics | 约12,000家公司 | 0-100分(低风险=高分) | 月度 | 风险导向,适合做风险因子 |
| Refinitiv | 约9,000家公司 | 0-100分(百分制) | 季度 | 数据颗粒度最细,但API调用限制多 |
核心观点:没有完美的数据源。我个人习惯是至少融合两家数据源,取交集或加权平均。你想想看,如果只用一家,万一它某个月评分逻辑调整了,你的模型就跟着抽风。
数据获取实战:API调用与爬虫策略
获取ESG数据,通常有两种方式:官方API和网页爬虫。我建议优先用API,除非你预算有限。
以Refinitiv为例,它的API调用代码大概长这样:
import requests
import pandas as pd
# Refinitiv API配置
api_key = "your_api_key_here"
base_url = "https://api.refinitiv.com/esg/v1/"
# 获取某只股票的ESG综合评分
def get_esg_score(ticker):
endpoint = f"{base_url}scores/{ticker}"
headers = {"Authorization": f"Bearer {api_key}"}
response = requests.get(endpoint, headers=headers)
if response.status_code == 200:
data = response.json()
return data['esgScore']
else:
print(f"请求失败: {response.status_code}")
return None
# 批量获取
tickers = ['AAPL', 'MSFT', 'GOOGL']
scores = [get_esg_score(t) for t in tickers]
print(pd.DataFrame({'ticker': tickers, 'esg_score': scores}))
小技巧:调用API时,记得加个重试机制。我曾经遇到过Refinitiv的API在月底特别不稳定,不加重试的话,数据获取到一半就断了,气得我直接写了个带指数退避的重试函数。
数据缺失值处理:别让空值毁了你的模型
ESG数据的缺失率有多高?我告诉你,A股公司的ESG数据缺失率经常超过40%。为什么会这样?因为很多中小公司根本不披露ESG信息。
处理缺失值,我一般按这个优先级来:
- 删除法:如果某只股票缺失超过70%的ESG指标,直接删掉。别心疼,留着也是噪声。
- 均值/中位数填充:对于连续型指标,用行业均值填充。注意是按行业分,不是全局均值。科技公司的ESG评分和能源公司能一样吗?
- 前向填充:对于时间序列数据,用上一期的值填充。ESG评分变化很慢,这个办法挺靠谱。
- 模型预测填充:如果缺失值集中在某些特定指标,可以用随机森林或KNN来预测缺失值。这个方法计算量大,但精度最高。
避坑指南:我曾经在做一个跨市场策略时,直接用全局均值填充了所有缺失值。结果呢?模型在发达市场表现很好,在新兴市场一塌糊涂。后来才发现,新兴市场的ESG数据缺失模式跟发达市场完全不同。所以,填充前一定要先分析缺失模式。
数据标准化方法:让不同量纲的数据对齐
ESG数据来自不同源,量纲千差万别。MSCI是AAA-CCC的等级制,Sustainalytics是0-100分,Refinitiv也是0-100分但评分逻辑不同。不标准化的话,模型根本没法用。
我常用的标准化方法有三种:
| 方法 | 公式 | 适用场景 | 注意事项 |
|---|---|---|---|
| Z-score标准化 | (x - μ) / σ | 数据近似正态分布 | 对异常值敏感 |
| Min-Max归一化 | (x - min) / (max - min) | 数据有明确边界 | 新数据可能超出范围 |
| 排名百分位 | rank(x) / N | 数据分布未知或偏态 | 丢失了数值间的距离信息 |
我个人最常用的是排名百分位法。为什么?因为ESG数据往往不是正态分布,很多公司集中在中间分数段,两头少。用Z-score的话,中间那堆数据会被压缩得很厉害。用排名百分位,至少保留了相对顺序。
import pandas as pd
from sklearn.preprocessing import MinMaxScaler, StandardScaler
# 示例数据
esg_data = pd.DataFrame({
'company': ['A', 'B', 'C', 'D', 'E'],
'esg_score': [65, 78, 42, 91, 55]
})
# 方法1:Z-score标准化
scaler = StandardScaler()
esg_data['zscore'] = scaler.fit_transform(esg_data[['esg_score']])
# 方法2:Min-Max归一化
scaler = MinMaxScaler()
esg_data['minmax'] = scaler.fit_transform(esg_data[['esg_score']])
# 方法3:排名百分位
esg_data['percentile'] = esg_data['esg_score'].rank(pct=True)
print(esg_data)
知识体系总览
下面这张图,是我梳理的本章核心逻辑。你看一眼,心里就有谱了。
我的经验:整个流程走下来,最耗时的不是建模,而是数据清洗。我做过一个统计,ESG因子预测项目里,数据获取和清洗占了60%的时间,建模和调参只占30%,剩下10%是写报告。所以,别急着上模型,先把数据搞干净。
嗯,关于ESG数据获取与清洗,核心就是这些。数据源选对、缺失值处理好、标准化方法选合适,后面建模就顺了。记住一句话:垃圾进,垃圾出。数据质量决定了模型的天花板。