第十三章:压力测试与情景分析

压力测试这东西,说白了就是给自己找不痛快。

我做了十几年交易,见过太多人平时风控做得漂漂亮亮,一到极端行情就崩盘。为什么?因为常规风控只覆盖了95%的情况,剩下那5%才是要命的。压力测试,就是专门对付那5%的。

13.1 历史情景模拟

历史情景模拟,是最直观的方法。说白了就是——过去发生过什么,我们就假设它再来一次。

核心思路:找出历史上对基差影响最大的事件,把当时的市场参数套到现在。

我个人习惯把历史情景分成三类:

  • 系统性危机:2008年金融危机、2020年疫情、2015年股灾
  • 行业性冲击:2014年原油暴跌、2022年伦镍事件
  • 品种特有事件:某个品种的逼仓、交割违约

实操案例:2020年3月,原油基差从+2美元瞬间变成-30美元。我当时手里有大量多头头寸,要不是提前做了历史情景模拟,那波直接爆仓。嗯,从那以后我再也不敢轻视历史数据了。

历史情景模拟的步骤:

  1. 确定历史事件的时间窗口(比如2020年3月9日-3月20日)
  2. 提取该时段的价格波动率、基差变化、成交量
  3. 将波动率映射到当前持仓
  4. 计算最大回撤和保证金压力
# 历史情景模拟示例代码
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 压力测试报告生成

测试做完了,得写报告。报告不是给风控看的,是给老板看的。老板只关心两件事:亏多少?怎么办?

报告的核心结构:

  1. 情景描述:什么情况下会发生
  2. 损失测算:最大亏损、保证金追加额
  3. 应对措施:减仓、对冲、融资
  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)

一个小技巧:压力测试的频率不要太高。每天跑一次就够了。跑太频繁,你会被噪音淹没。我见过有人每小时跑一次,结果自己把自己吓死了。

知识体系总览

下面这张图,是我自己总结的压力测试核心逻辑。你把它存下来,每次做测试前看一眼,思路就清晰了。

压力测试与情景分析核心框架 历史情景模拟 假设情景构建 极端市场事件模拟 2008金融危机 2020疫情冲击 品种逼仓事件 价格涨跌停 流动性枯竭 政策突变 系统宕机 融资冻结 对手违约 压力测试报告生成 损失测算 应对措施

压力测试不是用来预测未来的,是用来让你心里有底的。你想想看,如果每个极端情况你都提前想过应对方案,真到那天,你慌什么?

最后提醒一句:压力测试报告写完了,一定要发给老板看。别自己藏着。我见过有人测试结果很糟糕,但不敢上报,结果出事之后责任全在他。记住,风控不是一个人的事。


公众号:蓝海资料掘金营,微信deep3321