一、违约概率(PD)基础
各位同学好,今天我们来聊聊信用风险里最核心的一个概念——违约概率(PD)。
说实话,我做了这么多年风控模型,PD 就像是我们这行的“地基”。地基不稳,上面盖再多高楼都是白搭。你想想看,不管是算预期损失,还是定贷款利率,最后都得回到 PD 这个数字上来。
1.1 PD 到底是什么?
违约概率,英文叫 Probability of Default,缩写就是 PD。它的定义其实很简单:在未来某个特定时间段内,借款人发生违约的可能性。
举个例子。假设我们有 1000 个信用评分差不多的客户,银行给他们每人贷了 10 万块。一年之后,有 20 个人没还钱。那这组客户的 PD 就是 20/1000 = 2%。
嗯,这里要注意一点:PD 是一个概率值,不是 0 就是 1。它介于 0 和 1 之间,表示的是“可能性”,而不是“已经发生”。
核心公式:
PD = 违约客户数 / 总客户数
但实际建模中,我们用的是更复杂的统计模型来估算这个值。
1.2 PD 在信用风险中的角色
PD 在信用风险管理里,可以说是“牵一发而动全身”。我个人习惯把信用风险拆成三个部分来看:
- 违约概率(PD):借款人会不会违约?
- 违约损失率(LGD):违约了能收回多少钱?
- 违约风险敞口(EAD):违约时欠了多少钱?
这三个东西乘在一起,就是咱们常说的预期损失(EL):
EL = PD × LGD × EAD
我在项目中遇到过不少新手,一上来就急着算 LGD 和 EAD,结果 PD 没算准,整个预期损失全偏了。说白了,PD 是这三个变量里最基础、也最敏感的一个。
为什么这么说?因为 PD 直接影响银行的资本计提。巴塞尔协议里规定,银行必须根据 PD 来算风险加权资产(RWA)。PD 高一点,银行就要多留一点资本金。这可不是小数目,动辄就是几亿甚至几十亿的差别。
避坑指南:
我曾经犯过一个错误——直接用历史违约率当 PD 用。后来发现,历史违约率是“过去时”,而 PD 是“未来时”。市场环境一变,历史数据就不灵了。所以 PD 建模一定要考虑前瞻性信息。
1.3 PD 与评级的关系
说到 PD,就绕不开评级。评级和 PD 是什么关系?
我打个比方你就明白了。评级就像是给借款人贴标签,比如“AAA”、“BBB”、“CCC”。而 PD 就是这些标签背后的数字。每个评级等级,都对应着一个 PD 范围。
举个例子,标准普尔的评级体系里:
| 评级等级 | 1 年 PD 范围(典型值) | 含义 |
|---|---|---|
| AAA | 0.01% - 0.05% | 极低风险 |
| AA | 0.05% - 0.10% | 很低风险 |
| A | 0.10% - 0.25% | 低风险 |
| BBB | 0.25% - 1.00% | 中等风险 |
| BB | 1.00% - 5.00% | 投机级 |
| B | 5.00% - 15.00% | 高风险 |
| CCC | 15.00% - 50.00% | 极高风险 |
你看,评级越高,PD 越低。反过来,评级下调往往意味着 PD 上升。这就是为什么评级变动会引发市场剧烈反应——它背后是 PD 在变。
我建议你在做 PD 建模时,可以把评级当作一个重要的输入变量。但千万别完全依赖外部评级。为什么?因为外部评级更新慢,有时候市场都变天了,评级还没动。我自己做模型时,通常会结合内部评分卡和外部评级,取一个加权结果。
注意:
评级和 PD 不是一一对应的关系。同一个评级等级内的借款人,PD 也可能有差异。比如两个 BBB 级的企业,一个 PD 是 0.3%,另一个是 0.8%,虽然都在 BBB 范围内,但风险程度明显不同。所以 PD 建模要精细到个体层面,不能只看评级。
1.4 PD 建模的核心逻辑
好了,讲了这么多理论,咱们来看看 PD 建模到底是怎么做的。我画了一张图,帮你理清思路:
这张图展示的是 PD 建模的完整流程。从数据输入开始,到特征工程、模型训练、模型验证,最后输出 PD 分值。每一步都有讲究。
举个例子,特征工程这一步,我习惯用 WOE(Weight of Evidence)来做变量转换。为什么?因为 WOE 能把分类变量和连续变量统一处理,而且它天然跟逻辑回归的线性假设很搭。
# 一个简单的 WOE 计算示例
import pandas as pd
import numpy as np
def calc_woe(df, feature, target):
"""
计算 WOE 和 IV 值
df: 数据框
feature: 特征名
target: 目标变量(0=未违约,1=违约)
"""
total_good = df[target].sum()
total_bad = len(df) - total_good
grouped = df.groupby(feature)[target].agg(['sum', 'count'])
grouped.columns = ['bad', 'total']
grouped['good'] = grouped['total'] - grouped['bad']
grouped['bad_rate'] = grouped['bad'] / total_bad
grouped['good_rate'] = grouped['good'] / total_good
# 避免除零
grouped['bad_rate'] = grouped['bad_rate'].replace(0, 0.0001)
grouped['good_rate'] = grouped['good_rate'].replace(0, 0.0001)
grouped['woe'] = np.log(grouped['good_rate'] / grouped['bad_rate'])
grouped['iv'] = (grouped['good_rate'] - grouped['bad_rate']) * grouped['woe']
return grouped[['woe', 'iv']]
# 使用示例
# woe_df = calc_woe(data, 'income_level', 'default_flag')
# print(woe_df)
这段代码看起来简单,但实际项目中,WOE 的计算要考虑很多细节。比如分组太少会丢失信息,分组太多又会过拟合。我一般建议分 5-10 组,具体看样本量。
个人经验:
PD 建模最忌讳的就是“黑箱模型”。你想想看,如果模型只告诉你 PD 是 3.5%,但说不清为什么,监管那边根本过不了。所以我一直坚持用可解释性强的模型,比如逻辑回归。虽然 XGBoost 精度更高,但解释起来太费劲。
1.5 小结
这一章我们讲了 PD 的定义、它在信用风险中的核心地位,以及跟评级的关系。说白了,PD 就是信用风险的“体温计”——体温高了,说明病人有问题;PD 高了,说明借款人风险大。
下一章我们会深入 PD 建模的具体方法,包括数据准备、变量筛选和模型训练。到时候我会拿一个真实项目的数据来演示,保证让你看得过瘾。
公众号:蓝海资料掘金营,微信deep3321