1. 这不是一张普通表格:Vintage分析表为什么是信贷风控的“心脏监测仪”
你手头那张密密麻麻、横纵交错的Vintage分析表,绝不是Excel里随便拉出来的数据透视图。它是一份动态的、带时间戳的“贷款健康体检报告”,是信贷风控团队每天早上第一眼要看的仪表盘。我干这行十年,从银行风控部到互金公司模型组,再到给中小贷机构做咨询,见过太多人把Vintage当成“画个图交差”的任务——结果就是逾期率突然飙升时,连问题出在哪个放款批次、哪个渠道、哪个审批策略上都搞不清楚。核心关键词就三个:信贷风控、Vintage分析、风险洞察。它解决的不是“能不能贷”,而是“贷出去的钱,到底在时间维度上表现如何”。适合三类人:刚入行的风控专员(别再只会看当期逾期率)、想把模型落地的算法工程师(你的AUC再高,不和Vintage对齐就是空中楼阁)、还有业务负责人(你得知道,上个月冲量的那批客户,三个月后坏账会吃掉多少利润)。这张表的本质,是把一笔贷款的命运,按“出生日期”(即放款月份)切片,再纵向追踪它在每个还款周期(M1、M2、M3…)的存活状态。就像医院的心电监护仪,不只显示当前心跳,更记录过去每一秒的波形变化。很多人卡在第一步:数据源混乱。比如,你用的是“合同签订日”还是“资金到账日”作为Vintage月?这两个日期在银行和小贷场景下可能相差7天甚至更久,而逾期率计算的分母(应还本金)和分子(实际未还本金)必须严格对应同一时间基线。我见过最典型的坑,是某家消费金融公司用“审批通过日”做Vintage月,结果发现M3逾期率虚高——因为大量客户在审批通过后拖了十几天才真正提款,导致“出生”和“开始还款”严重错位。所以,Vintage分析的第一课,不是建模,而是校准时间锚点。它不教你如何写SQL,但会告诉你,哪一行代码写错,会让整张表的结论南辕北辙。
2. Vintage分析表的底层逻辑与设计思路拆解
2.1 为什么非得用Vintage,而不是简单看滚动逾期率?
滚动逾期率(Rolling Delinquency Rate)是把所有存量客户按当前状态统计,比如“截至今天,所有未结清贷款中逾期90天以上的占比是5.2%”。听起来很直观,但它掩盖了关键信息:这批5.2%的坏账,到底是去年放的“老赖”,还是上个月刚放的“新雷”?Vintage分析则像X光片,把不同“出生月份”的贷款群体分开扫描。举个真实案例:某汽车金融公司2023年Q4放款的Vintage曲线异常陡峭——M6逾期率比Q3同口径高出3个百分点。起初团队以为是经济下行,但拆开看,Q4的增量客户几乎全部来自某第三方助贷平台,而该平台在Q4上线了新的“免征信初筛”流程。问题立刻定位:不是市场变了,是准入策略松动了。这就是Vintage不可替代的价值:它把时间维度和客群维度牢牢绑定,让风险归因有了确定性。而滚动率就像用一把尺子量所有人的身高,却忘了有人刚出生、有人已成年。Vintage的数学本质,是构建一个二维矩阵:横轴是Vintage月(Loan Origination Month),纵轴是账龄(Months on Book),单元格值是该Vintage月放款中,在对应账龄下逾期≥X天的余额占比(或账户数占比)。这个结构天然具备可比性——你可以把2022年1月和2023年1月的Vintage曲线并排对比,直接看出策略迭代效果,无需担心存量池老化干扰。
2.2 表结构设计:字段选择不是越多越好,而是“精准打点”
一张合格的Vintage分析表,核心字段不超过8个,但每个都必须有明确的业务含义和计算逻辑。我见过最失败的设计,是把几十个衍生变量全塞进去,结果业务看不懂、技术难维护、领导嫌太复杂。以下是经过十年实战验证的最小可行字段集:
| 字段名 | 数据类型 | 计算逻辑 | 关键说明 |
|---|---|---|---|
vintage_month | 字符串(YYYY-MM) | 取贷款合同生效日所在月 | 必须统一!银行常用“放款日”,小贷常用“资金到账日”,需全公司对齐 |
current_month | 字符串(YYYY-MM) | 统计截止日所在月 | 决定账龄计算基准,如2024-03为截止日,则2024-01放款的账龄为2个月 |
months_on_book | 整数 | DATEDIFF(current_month, vintage_month, MONTH) | 注意跨年计算,避免用字符串相减 |
origination_balance | 数值 | 该Vintage月放款总本金 | 分母基准,后续所有比率以此为锚 |
balance_at_mob | 数值 | 截止current_month,该Vintage月贷款剩余未还本金 | 动态值,随还款/核销变化 |
delinquent_balance | 数值 | balance_at_mob中逾期≥30天的部分 | 逾期定义需明文规定(如M1=逾期1-30天,M2=31-60天) |
delinquency_rate | 数值 | delinquent_balance / origination_balance * 100 | 核心指标,反映初始资金质量 |
cumulative_loss_rate | 数值 | (origination_balance - balance_at_mob) / origination_balance * 100 | 累计损失,含核销、坏账 |
提示:
delinquent_balance和cumulative_loss_rate必须区分清楚。前者是“活着但生病的病人”,后者是“已死亡或放弃治疗的病人”。很多团队混淆二者,导致对催收效果误判——比如某批次M6逾期率下降,但累计损失率持续上升,说明催收只是把坏账延后,而非真正回收。
2.3 方案选型:为什么推荐“宽表+动态视图”,而非传统OLAP立方体?
十年前,我们用SQL Server Analysis Services(SSAS)搭OLAP立方体做Vintage,好处是预计算快,缺点是灵活性为零。业务要加一个“按城市维度下钻”,IT得加班三天改Schema。现在主流方案是“宽表+BI动态视图”,底层用Hive或ClickHouse存事实宽表,BI工具(如Tableau、QuickSight)做前端聚合。优势在于:
- 敏捷性:业务人员自己拖拽字段就能生成新维度Vintage(如“按渠道+学历组合”),无需开发介入;
- 成本可控:宽表按天增量更新,存储成本远低于全量预计算;
- 可追溯:每条记录带
process_date(处理日期),能回溯任意历史时刻的Vintage快照。
我服务过一家城商行,他们曾坚持用Oracle物化视图,结果一次监管报送需求变更,要求增加“按抵押物类型”细分,开发排期两周。换成宽表方案后,数据工程师当天就补了字段,BI同事下午就出了报表。关键不是技术多先进,而是让风控决策者离数据更近一步。当然,宽表对ETL稳定性要求极高——如果某天balance_at_mob计算逻辑出错,后续所有Vintage曲线都会漂移。所以必须配套“数据血缘监控”,比如用Apache Atlas标记origination_balance到delinquency_rate的完整链路,一旦上游字段变更,自动告警下游影响范围。
3. 核心细节解析与实操要点:从数据建模到风险洞察的硬核步骤
3.1 数据建模:三步踩准时间锚点,避开90%的计算陷阱
Vintage分析的准确性,70%取决于时间维度的建模精度。我总结出必须死守的三步法:
第一步:锁定唯一“出生证”
不是合同日期、不是审批日期、不是授信日期,而是资金实际划付至借款人账户的日期(即disbursement_date)。理由很现实:只有钱到账,客户才开始产生还款义务。某次审计中,我们发现某网贷平台用“授信生效日”做Vintage月,结果其M1逾期率常年低于行业均值——不是风控好,而是授信后平均7.3天才放款,M1实际对应的是第8-37天,自然“看起来”很健康。修正后,M1逾期率跃升至行业TOP10,暴露出早期反欺诈规则失效。
第二步:定义“账龄”的物理意义
账龄(Months on Book)必须是从放款日到统计截止日的实际月份数,而非简单用current_month - vintage_month。例如:2023-12-28放款,2024-01-05统计,账龄是0个月(不足30天),不是1个月。我们用Hive SQL实现:
-- 正确计算账龄(单位:月) months_on_book = floor(months_between(to_date('${current_date}'), to_date(vintage_date))) -- 其中vintage_date取disbursement_date,current_date为统计截止日错误做法是substr(current_month,1,7) - substr(vintage_month,1,7),这会导致跨年计算失真(如2023-12到2024-01,字符串相减得-11)。
第三步:动态分母锁定origination_balance必须是该Vintage月所有贷款的初始放款本金总和,且一经生成永不变更。常见错误是用“当前剩余本金”做分母,导致后期Vintage率人为降低(因为分母变小了)。正确做法是在ETL首层就固化:
-- 在ODS层清洗时即生成 insert overwrite table vintage_base partition(dt='${dt}') select substr(disbursement_date,1,7) as vintage_month, sum(principal_amount) as origination_balance, count(*) as loan_count from loan_originations where substr(disbursement_date,1,7) = '${vintage_month}' group by substr(disbursement_date,1,7);这个表就是Vintage分析的“地基”,后续所有比率计算都引用它,确保分母恒定。
3.2 风险洞察:不止看曲线,更要读懂三条线背后的业务语言
一张Vintage图通常有三条核心曲线:M1逾期率、M3逾期率、累计损失率。但多数人只盯着数值升降,忽略了它们之间的“相对关系”才是风险信号。我整理了十年间识别出的6种典型模式及其业务解读:
| 曲线形态 | M1 vs M3走势 | 累计损失率趋势 | 业务根因 | 应对动作 |
|---|---|---|---|---|
| 健康型 | M1平稳,M3缓慢爬升 | 平缓上升至平台期 | 客户质量稳定,催收有效 | 维持现有策略 |
| 早衰型 | M1显著升高,M3快速突破 | 前期陡升后趋稳 | 获客渠道掺水(如返现诱导骗贷) | 立即暂停该渠道,重审准入规则 |
| 迟滞型 | M1正常,M3异常跳升 | 中期加速上升 | 还款能力突变(如失业潮、行业裁员) | 启动专项贷后管理,调整催收策略 |
| 核销型 | M1/M3双降,累计损失率持续攀升 | 持续上升无平台 | 坏账核销激进,掩盖真实风险 | 审计核销标准,严控人为调节 |
| 迁移型 | M1下降,M3上升 | 缓慢上升 | 催收将M1压至M2,但M2转M3失败 | 优化催收SOP,加强M2干预 |
| 断崖型 | M1/M3同步骤降,累计损失率跳升 | 短期飙升后回落 | 批量核销或技术故障(如还款系统漏记) | 排查系统日志,复核核销清单 |
注意:判断“断崖型”必须交叉验证。某次我们发现M3逾期率单月下降15%,兴奋之余核查发现,是核心系统升级导致M3还款记录丢失,实际风险并未改善。因此,任何异常波动必须关联原始交易流水、催收日志、系统告警三类数据源交叉印证。
3.3 工具链实操:用Python+Pandas完成端到端Vintage分析
虽然生产环境用SQL+BI,但日常诊断必须掌握轻量级分析工具。我用Python+Pandas搭建了一套5分钟可跑通的Vintage分析脚本,核心逻辑如下:
import pandas as pd import numpy as np from datetime import datetime, timedelta # 1. 加载基础数据(模拟从数据库导出的宽表) df = pd.read_csv('loan_data.csv', parse_dates=['disbursement_date', 'report_date'], dtype={'loan_id': str}) # 2. 计算Vintage月和账龄(关键!) df['vintage_month'] = df['disbursement_date'].dt.to_period('M') df['current_month'] = df['report_date'].dt.to_period('M') df['months_on_book'] = ((df['current_month'] - df['vintage_month']) .apply(lambda x: x.n)) # 3. 构建Vintage矩阵(核心pivot操作) vintage_pivot = df.groupby(['vintage_month', 'months_on_book']).agg({ 'origination_balance': 'first', # 分母取首次值 'current_balance': 'sum', 'delinquent_balance': 'sum' }).reset_index() # 4. 计算核心指标 vintage_pivot['delinquency_rate'] = ( vintage_pivot['delinquent_balance'] / vintage_pivot['origination_balance'] * 100 ) vintage_pivot['cumulative_loss_rate'] = ( (vintage_pivot['origination_balance'] - vintage_pivot['current_balance']) / vintage_pivot['origination_balance'] * 100 ) # 5. 生成可视化(Matplotlib) import matplotlib.pyplot as plt plt.figure(figsize=(12,6)) for vintage in vintage_pivot['vintage_month'].unique()[-6:]: # 取最近6期 subset = vintage_pivot[vintage_pivot['vintage_month']==vintage] plt.plot(subset['months_on_book'], subset['delinquency_rate'], label=f'Vintage {vintage}', marker='o') plt.xlabel('Months on Book') plt.ylabel('Delinquency Rate (%)') plt.title('Vintage Analysis Curve') plt.legend() plt.grid(True) plt.show()这段代码的关键价值在于:它强制你面对每一行数据的物理含义。比如df['disbursement_date'].dt.to_period('M')确保时间切片无歧义;groupby(['vintage_month', 'months_on_book'])天然构建二维矩阵;而origination_balance用'first'聚合,正是为了锁定初始分母。新手常犯的错是直接用sum(),导致分母被重复累加。实测下来,这套脚本处理百万级贷款数据仅需12秒,比BI工具调试快10倍——当你需要快速验证一个假设(比如“新审批模型是否改善了M6表现”),这才是真正的生产力。
4. 实操过程与核心环节实现:从0到1搭建可落地的Vintage监控体系
4.1 第一阶段:数据准备与清洗(耗时占比40%,决定成败)
这不是简单的ETL流水线,而是风控数据治理的缩影。我列出必须完成的7项清洗动作,缺一不可:
- 放款日期标准化:统一提取
disbursement_date,剔除测试订单、退款订单、重复放款记录。某次发现某渠道20%的“放款”实为系统重试,未剔除导致Vintage月虚增; - 余额一致性校验:比对核心系统
loan_balance与账务系统account_balance,差异率超0.1%需人工介入。我们曾因账务系统T+1延迟,导致当日current_balance为0,M1逾期率爆表; - 逾期状态映射:将各系统五花八门的逾期标识(如“OVERDUE_30”、“BAD_DEBT”、“WRITE_OFF”)统一映射为标准等级(M1/M2/M3/.../Loss);
- 核销标记强化:不仅记录核销日期,还需标记核销原因(如“死亡”、“失踪”、“欺诈”),这对后续损失率归因至关重要;
- 客户去重:同一身份证号在同一个月内多次放款,需合并为单笔贷款计算,避免“刷单”干扰Vintage;
- 账龄边界处理:设定最大账龄(如60个月),超出者强制归入“Loss”状态,防止长尾数据污染曲线;
- 缺失值策略:
disbursement_date缺失的贷款,按规则回填(如用合同签订日+3天),并标记为“低置信度”,不参与核心指标计算。
实操心得:清洗阶段必须产出《数据质量报告》,包含每项清洗的样本量、修复率、残留异常率。我坚持要求风控总监签字确认,因为这是后续所有分析的“法律依据”。没有这份报告,任何Vintage结论都不具备决策效力。
4.2 第二阶段:指标计算与可视化(不是炫技,而是讲清故事)
BI工具的图表再漂亮,如果不能回答业务问题,就是废图。我设计的Vintage看板只保留3个核心模块:
模块一:Vintage曲线对比图
- X轴:Months on Book(0-36)
- Y轴:Delinquency Rate(%)
- 多条曲线:最近6期Vintage(2023-10至2024-03),用不同颜色区分
- 关键标注:在M3节点画水平线(行业警戒线7%),标出各期M3值及同比变化
模块二:Vintage热力图
- 行:Vintage月(最近12期)
- 列:Months on Book(0-24)
- 单元格颜色:逾期率高低(绿色<3%,黄色3-7%,红色>7%)
- 价值:一眼识别“问题批次”——比如2024-01列在M2-M4区域全红,说明该月放款存在系统性风险
模块三:归因下钻面板
- 主维度:渠道、客群(年龄/收入)、产品类型、审批策略版本
- 交互逻辑:点击热力图中2024-01列,自动加载该Vintage月的下钻分析
- 输出:各维度下M3逾期率排名,Top3风险因子(如“某助贷渠道贡献了该月72%的M3逾期”)
这套看板的精髓在于:所有图表都服务于一个动作——“下一步该做什么”。比如热力图发现2024-01异常,下钻面板立刻指出是“渠道A的年轻客群”,那么风控经理当天就能约谈渠道负责人,而不是开三天会讨论“要不要分析”。
4.3 第三阶段:风险洞察报告撰写(让老板看懂,让执行者行动)
一份好的Vintage报告,不是数据堆砌,而是风险叙事。我采用“三段式”结构:
第一段:一句话结论(给高管)
“2024年3月Vintage显示,M3逾期率较2月上升1.2个百分点至6.8%,主要由‘线上直营’渠道贡献,其M3逾期率达12.4%,较上月提升3.7个百分点,已触发二级预警。”
第二段:归因分析(给风控总监)
- 数据证据:热力图显示2024-03列在M2-M4区域呈深红色;下钻发现该渠道3月新增客户中,25岁以下占比达68%(历史均值42%),且芝麻分<600客户占比31%(历史均值15%);
- 业务验证:调取该渠道3月营销素材,发现主打“学生专享低息贷”,与风控策略中“禁止向无稳定收入学生放款”直接冲突;
- 影响测算:若维持当前策略,预计Q2将新增坏账约2300万元。
第三段:行动建议(给执行团队)
- 立即动作:暂停该渠道3月上线的“学生专享”产品,48小时内下架相关广告;
- 中期动作:4月15日前完成该渠道准入规则修订,增加“月均收入证明”硬性要求;
- 长期动作:建立渠道风险保证金机制,按季度Vintage表现动态调整结算费率。
注意:报告中所有数字必须标注来源(如“数据截至2024-04-05,来源:风控数据仓库V2.3”),所有建议必须明确责任人与时限。我见过太多报告石沉大海,就是因为写了“建议加强审核”,却不写“由张三在4月10日前完成规则配置”。
5. 常见问题与排查技巧实录:那些没人告诉你的坑
5.1 问题一:Vintage曲线突然“断崖式”下跌,是风险改善还是数据事故?
现象:某期Vintage的M3逾期率从8.2%骤降至3.1%,团队一片欢腾,直到发现当月累计损失率同步飙升至15%。
排查路径:
- 查原始流水:筛选该Vintage月所有贷款,检查
current_balance是否批量归零(系统故障常见); - 查核销日志:确认是否有集中核销操作,重点看核销时间是否集中在统计截止日前一天;
- 查账龄计算:验证
months_on_book是否因日期格式错误(如2024-01-00)导致计算异常; - 查分母锁定:确认
origination_balance是否被错误更新(如ETL脚本误用sum()而非first())。
我的经验:90%的“断崖”源于系统故障或人为核销。解决方案是建立“Vintage健康度检查表”,每日自动运行:
- 检查各Vintage月
origination_balance环比变动是否<±0.5%; - 检查
delinquent_balance与current_balance比值是否在合理区间(如M1通常为0.8-1.2); - 检查
months_on_book最大值是否等于理论值(如2024-03截止,2024-03 Vintage的max_mob应为0)。
5.2 问题二:不同系统Vintage结果不一致,到底该信谁?
现象:风控系统算出2023-12 Vintage的M3逾期率是5.7%,而财务系统报表显示为6.9%。
根源分析:
- 定义差异:风控系统用“逾期本金/放款本金”,财务系统用“逾期本息/放款本息”;
- 时间差异:风控系统用“统计日24:00快照”,财务系统用“日终批处理后数据”,存在2小时延迟;
- 口径差异:风控系统剔除已核销贷款,财务系统包含核销中贷款。
解决方法:
- 签署《Vintage计算标准协议》:全公司统一定义、时间基线、数据源、排除规则;
- 建立“黄金数据源”:指定核心系统为唯一权威源,其他系统需定期对账;
- 开发对账工具:用Python脚本自动比对两系统结果,输出差异明细(如“财务系统多计利息12.3万元,导致分母增大”)。
实操心得:我坚持让CTO和CFO共同签字确认协议,因为这是跨部门协作的基石。没有这个协议,任何分析都是自说自话。
5.3 问题三:Vintage分析结果与业务反馈严重不符,是模型错了还是人错了?
现象:Vintage显示某渠道M3逾期率仅4.2%,但一线催收反馈“该渠道客户失联率高达60%”。
深度排查:
- 验证催收数据真实性:调取催收系统通话记录,确认“失联”是否定义为“3次拨打无人接听”,而非主观判断;
- 检查Vintage覆盖范围:发现该渠道有30%贷款走线下签约,未纳入线上风控系统,Vintage只覆盖了70%的优质客户;
- 分析样本偏差:该渠道线上申请客户中,芝麻分>650占比82%,而线下客户均分仅520,Vintage天然偏优。
应对策略:
- 立即补充线下贷款数据,重建全量Vintage;
- 对渠道实施“双轨制”监控:线上Vintage + 线下失联率专项看板;
- 在渠道合作协议中加入“数据完整性条款”,要求其提供全量客户画像。
这个问题的本质,是Vintage分析的前提假设——“数据能代表整体业务”——被打破了。我的教训是:永远不要相信单一数据源,风控的真相藏在数据缝隙里。
5.4 问题四:如何用Vintage分析驱动策略迭代,而不是沦为“事后诸葛亮”?
痛点:很多团队把Vintage当“考古报告”,等M6数据出来才分析,此时坏账已成定局。
破局方法:建立“前瞻性Vintage监控”机制:
- 缩短统计周期:从月度改为双周,对新策略上线的前3期Vintage进行高频跟踪;
- 设置前置预警指标:当某Vintage月的M1逾期率连续2周超阈值,自动触发策略复盘;
- AB测试嵌入Vintage:新审批模型上线时,将流量随机分为A/B组,分别计算Vintage,直接对比M3表现。
某次我们用此法,在新模型上线第15天就发现B组M2逾期率比A组高1.8个百分点,立即回滚,避免了潜在千万级损失。
最后分享一个小技巧:在Vintage看板右下角固定显示“最近一期M1变化率”,并用红绿灯标识(>0.5%亮红灯)。这个小小的视觉提示,能让风控经理每天第一眼就抓住风险苗头,而不是等月报邮件。
我在实际使用中发现,Vintage分析最大的价值,从来不是预测未来,而是照亮过去的选择。每一次曲线的起伏,都是业务决策留下的指纹。当你能从一条M3曲线的拐点,准确还原出三个月前某次渠道谈判的细节,你就真正掌握了信贷风控的语言。这个过程没有捷径,只有反复校准数据、追问业务、验证假设。但当你第一次用Vintage报告说服业务部门叫停一个高风险产品时,那种笃定感,是任何KPI都无法替代的。