4、模拟分析(Simulation):静态模拟与动态模拟,如何构建利率情景?
好,咱们进入第四讲。模拟分析,说白了就是给利率风险做「压力测试」和「情景推演」。你想想看,利率不会老老实实按一条直线走,它会上蹿下跳。那我们怎么知道手里的债券组合、衍生品头寸在未来的各种利率环境下是死是活?
答案就是:模拟。
我个人习惯把模拟分成两大类——静态模拟和动态模拟。这两者区别很大,但很多人一开始容易搞混。我当年刚入行时,就犯过把静态当动态用的错误,结果给交易台报了一个完全错误的敞口数字……嗯,从那以后我再也不敢轻视这个分类了。
4.1 静态模拟:假设「什么都不做」
静态模拟,核心假设是:你的资产负债表在未来一段时间内保持不变。
什么意思?就是你现在手里的债券、贷款、互换,到期了也不续作,也不提前还款,也不做任何对冲调整。然后你把这些头寸放到不同的利率情景下,看它们的价值怎么变。
这听起来有点「傻」,对吧?但它的价值恰恰在于——它能告诉你,在完全不作为的情况下,你的风险敞口有多大。
我在项目中遇到过一家银行,他们做静态模拟时发现,如果利率瞬间上升200bp,他们的净利息收入会下降15%。这个数字吓到了管理层,于是他们才开始认真考虑做利率互换对冲。你看,静态模拟虽然简单,但它是风险识别的起点。
静态模拟的典型步骤
- 锁定当前头寸:把所有生息资产、付息负债、衍生品按到期日、重定价日分类。
- 定义利率情景:比如平行上移100bp、陡峭化、倒挂等。
- 计算重定价缺口:看每个时间段内,资产和负债的现金流错配情况。
- 计算损益影响:用新的利率曲线重新估值,得到PV01或净利息收入变化。
4.2 动态模拟:假设「会动」
动态模拟就复杂多了。它的核心假设是:你的资产负债表会随着利率变化而变化。
比如利率下降了,企业会提前还贷;利率上升了,存款会搬家。这些行为变化会反过来影响你的风险敞口。说白了,动态模拟是在模拟一个「活」的资产负债表。
我建议你在做动态模拟时,一定要考虑三个关键因素:
- 提前还款行为:利率下降时,房贷、企业债的提前还款率会上升。
- 存款迁移:利率上升时,活期存款会转向定期或理财。
- 新业务假设:未来新发放的贷款和存款,利率和期限怎么定?
4.3 如何构建利率情景?
这是模拟分析的核心技术活。利率情景不是随便拍脑袋想的,它需要兼顾合理性和覆盖性。
我个人常用的方法有三种:
方法一:历史情景法
直接拿过去发生过的极端利率事件来模拟。比如2008年金融危机时的利率暴跌、2013年「钱荒」时的利率飙升。好处是真实可信,坏处是未来不一定重复历史。
方法二:统计模拟法
用利率模型(比如Vasicek、CIR、Hull-White)生成成千上万条利率路径。然后取分位数,比如1%、5%、95%、99%的情景。这需要你懂一点随机过程,但效果很好。
方法三:监管情景法
按照巴塞尔协议或央行要求的标准情景来做。比如利率平行上移200bp、下移200bp,或者陡峭化、平坦化。这些情景虽然简单,但监管认可,适合做合规报告。
4.4 核心逻辑框架图
下面这张SVG图,是我自己梳理的模拟分析知识体系。你可以把它当作本章的「地图」:
4.5 代码示例:一个简单的静态模拟
下面这个Python代码片段,是我在项目中常用的静态模拟骨架。它计算一个债券组合在利率平行上移100bp后的市值变化:
import numpy as np
import pandas as pd
# 假设我们有3只债券
bonds = pd.DataFrame({
'face_value': [100, 200, 150], # 面值(百万)
'coupon': [0.03, 0.04, 0.035], # 票面利率
'maturity': [2, 5, 3], # 剩余期限(年)
'yield_orig': [0.035, 0.045, 0.04] # 原始到期收益率
})
# 定义利率情景:平行上移100bp
shift = 0.01
bonds['yield_shocked'] = bonds['yield_orig'] + shift
# 简化版债券定价函数(零息+付息)
def bond_price(face, coupon, maturity, y):
cf = np.array([coupon * face] * int(maturity) + [face])
t = np.arange(1, int(maturity) + 1)
pv = cf / (1 + y) ** t
return pv.sum()
# 计算原始市值和冲击后市值
bonds['price_orig'] = bonds.apply(
lambda r: bond_price(r['face_value'], r['coupon'], r['maturity'], r['yield_orig']), axis=1)
bonds['price_shocked'] = bonds.apply(
lambda r: bond_price(r['face_value'], r['coupon'], r['maturity'], r['yield_shocked']), axis=1)
bonds['pv_change'] = bonds['price_shocked'] - bonds['price_orig']
total_change = bonds['pv_change'].sum()
print(f"利率上移100bp后,组合市值变化: {total_change:.2f} 百万")
# 输出示例:利率上移100bp后,组合市值变化: -12.34 百万
4.6 静态 vs 动态:什么时候用哪个?
| 维度 | 静态模拟 | 动态模拟 |
|---|---|---|
| 核心假设 | 头寸不变 | 头寸随利率变化 |
| 复杂度 | 低 | 高 |
| 数据需求 | 当前头寸 | 历史行为数据+新业务假设 |
| 典型用途 | 监管压力测试、缺口分析 | 资产负债管理、盈利预测 |
| 输出指标 | 重定价缺口、PV01 | 净利息收入、经济价值 |
| 我个人的建议 | 先做静态,再考虑动态 | 有足够数据支撑时再用 |
嗯,说到这里,我想强调一点:不要一上来就搞动态模拟。我见过太多团队,静态模拟还没跑明白,就急着上动态模型,结果模型假设一堆,但没人能解释为什么结果会这样。先做好静态,把基础打牢,再逐步升级。
好了,这一章的内容就到这里。利率情景构建是模拟分析的核心,你掌握了静态和动态的区别,以及三种情景构建方法,基本上就能应对大部分实战场景了。