第十三章:压力测试与情景分析
压力测试这东西,说白了就是给自己找不痛快。
我做了十几年交易,见过太多人平时风控做得漂漂亮亮,一到极端行情就崩盘。为什么?因为常规风控只覆盖了95%的情况,剩下那5%才是要命的。压力测试,就是专门对付那5%的。
13.1 历史情景模拟
历史情景模拟,是最直观的方法。说白了就是——过去发生过什么,我们就假设它再来一次。
核心思路:找出历史上对基差影响最大的事件,把当时的市场参数套到现在。
我个人习惯把历史情景分成三类:
- 系统性危机:2008年金融危机、2020年疫情、2015年股灾
- 行业性冲击:2014年原油暴跌、2022年伦镍事件
- 品种特有事件:某个品种的逼仓、交割违约
实操案例:2020年3月,原油基差从+2美元瞬间变成-30美元。我当时手里有大量多头头寸,要不是提前做了历史情景模拟,那波直接爆仓。嗯,从那以后我再也不敢轻视历史数据了。
历史情景模拟的步骤:
- 确定历史事件的时间窗口(比如2020年3月9日-3月20日)
- 提取该时段的价格波动率、基差变化、成交量
- 将波动率映射到当前持仓
- 计算最大回撤和保证金压力
# 历史情景模拟示例代码
def historical_scenario(portfolio, event_date):
# 提取历史波动率
hist_vol = get_historical_vol(event_date, window=10)
# 映射到当前持仓
stress_pnl = portfolio.mark_to_market() * hist_vol
# 计算保证金压力
margin_call = stress_pnl * 1.2 # 120%保证金追加
return stress_pnl, margin_call
13.2 假设情景构建
历史不会简单重复。所以光靠历史数据不够,还得自己编一些极端情况。
假设情景的构建逻辑:
我一般从三个维度去编:
- 价格维度:单日涨跌停、连续三天涨跌停、基差从升水变贴水
- 流动性维度:成交量萎缩80%、买卖价差扩大10倍
- 政策维度:交易所提高保证金、限制开仓、强制平仓
我的经验:假设情景不要编得太离谱。比如你假设原油跌到0美元,那没意义。合理的极端是——比历史极值再放大20%-30%。
举个例子:
假设当前螺纹钢基差是+50元/吨,我构建一个情景:
- 需求突然崩塌,现货一天跌200元
- 期货因为预期更差,只跌100元
- 基差从+50变成-50
- 我的库存头寸亏损 = 200元/吨 × 库存量
- 我的期货空头盈利 = 100元/吨 × 空头量
- 净亏损 = 库存亏损 - 期货盈利
你看,这样一算,就知道自己扛不扛得住。
13.3 极端市场事件模拟
极端事件,就是那些你根本想不到的事。比如:
- 交易所系统宕机,无法平仓
- 银行间市场冻结,无法融资
- 主要交易对手违约,无法交割
极端事件模拟的核心:不是算亏多少钱,而是算——你还能不能活下来。
我曾经踩过的坑:2018年有个品种,我做了大量期现套利。结果交割月前一周,交易所突然修改交割标准。我的货交不进去,期货又平不掉。那三天我基本没睡觉。后来我所有策略都加了一条——「交割规则变更」的极端情景。
极端事件模拟的框架:
| 事件类型 | 影响维度 | 模拟参数 |
|---|---|---|
| 技术故障 | 无法交易 | 停盘1-3天 |
| 流动性枯竭 | 无法平仓 | 价差扩大5倍 |
| 政策突变 | 规则变更 | 保证金翻倍 |
| 对手违约 | 无法交割 | 替代成本+20% |
13.4 压力测试报告生成
测试做完了,得写报告。报告不是给风控看的,是给老板看的。老板只关心两件事:亏多少?怎么办?
报告的核心结构:
- 情景描述:什么情况下会发生
- 损失测算:最大亏损、保证金追加额
- 应对措施:减仓、对冲、融资
- 触发条件:什么信号出现时启动应对
报告模板示例:
压力测试报告(第X期)
日期:2024-XX-XX
测试人:XXX
一、测试情景
情景名称:原油基差极端贴水
触发条件:WTI单日跌幅超过8%
二、损失测算
最大亏损:-1,200万元(占总权益15%)
保证金追加:800万元
流动性缺口:300万元
三、应对措施
1. 立即减仓30%的现货多头
2. 买入虚值看跌期权对冲
3. 启动银行授信额度
四、结论
风险可控,但需提前准备流动性
报告生成自动化:
我建议把压力测试做成自动化流程。每天收盘后自动跑一遍,生成报告。这样一旦触发条件,系统会自动报警。
# 自动化压力测试报告生成
def generate_stress_report(portfolio):
scenarios = ['历史情景', '假设情景', '极端事件']
results = []
for scenario in scenarios:
pnl, margin = run_stress_test(portfolio, scenario)
results.append({
'scenario': scenario,
'max_loss': pnl,
'margin_call': margin
})
# 生成HTML报告
return render_report(results)
一个小技巧:压力测试的频率不要太高。每天跑一次就够了。跑太频繁,你会被噪音淹没。我见过有人每小时跑一次,结果自己把自己吓死了。
知识体系总览
下面这张图,是我自己总结的压力测试核心逻辑。你把它存下来,每次做测试前看一眼,思路就清晰了。
压力测试不是用来预测未来的,是用来让你心里有底的。你想想看,如果每个极端情况你都提前想过应对方案,真到那天,你慌什么?
最后提醒一句:压力测试报告写完了,一定要发给老板看。别自己藏着。我见过有人测试结果很糟糕,但不敢上报,结果出事之后责任全在他。记住,风控不是一个人的事。
公众号:蓝海资料掘金营,微信deep3321