3. 库存风险度量与做市商风险限额设定

任务目标

本案例将实现一个针对做市商库存头寸的风险度量模块:基于历史价格数据计算库存组合的VaR(在险价值)与CVaR(条件在险价值),并据此输出动态风险限额建议。核心解决两个问题:当前库存最多可能亏损多少(VaR),以及一旦亏损超过VaR阈值,平均亏损是多少(CVaR)。

实现方案

采用历史模拟法计算VaR/CVaR,无需对收益率分布做参数假设,适合做市商高频库存数据的肥尾特征。核心逻辑:
1. 输入库存持仓量与历史价格序列;
2. 计算持仓市值的时间序列,进而得到每日损益(P&L)分布;
3. 对损益排序,取置信水平(如95%)对应的分位数作为VaR;
4. CVaR为损益分布中尾部(超过VaR的部分)的平均值;
5. 风险限额 = min(当前可用资金 × 限额比例, VaR × 逆周期乘数),并给出监控阈值。

完整代码

import numpy as np
import pandas as pd

def calculate_var_cvar(pnl_series, confidence=0.95):
    """
    基于历史损益序列计算VaR和CVaR(损失为正数表示)
    pnl_series: 每日损益序列(正数=盈利,负数=亏损)
    返回: (VaR, CVaR) 均为正数,表示最大可能损失
    """
    # 转换为损失序列(亏损为正数)
    loss = -pnl_series.values
    loss_sorted = np.sort(loss)
    
    # VaR: 置信水平对应的分位数(损失分布右侧尾部)
    var_index = int(np.ceil(confidence * len(loss_sorted))) - 1
    var = max(loss_sorted[var_index], 0)  # VaR不为负
    
    # CVaR: 超过VaR的尾部损失均值
    tail = loss_sorted[var_index:]
    cvar = tail.mean() if len(tail) > 0 else var
    
    return var, cvar

def inventory_risk_limit(position, prices, capital, confidence=0.95, multiplier=1.5):
    """
    做市商库存风险限额计算
    position: 当前库存数量(正=多头,负=空头)
    prices: 历史价格序列(至少30个数据点)
    capital: 当前可用资金
    confidence: VaR置信水平
    multiplier: 逆周期调节乘数(>1 激进,<1 保守)
    """
    # 1. 计算持仓市值时间序列
    market_value = position * prices
    # 2. 计算每日损益(市值变动)
    pnl = market_value.diff().dropna()
    
    if len(pnl) < 20:
        raise ValueError("历史数据不足,至少需要21个价格点")
    
    # 3. 计算VaR和CVaR
    var, cvar = calculate_var_cvar(pnl, confidence)
    
    # 4. 风险限额 = min(资金约束, VaR约束)
    capital_limit = capital * 0.2  # 单日最大亏损不超过资金20%
    var_limit = var * multiplier
    
    # 5. 建议限额取两者较小值,并附加CVaR预警线
    suggested_limit = min(capital_limit, var_limit)
    warning_line = cvar * 0.8  # 触发预警的阈值
    
    return {
        "VaR": round(var, 2),
        "CVaR": round(cvar, 2),
        "suggested_limit": round(suggested_limit, 2),
        "warning_line": round(warning_line, 2),
        "capital_limit": round(capital_limit, 2),
        "var_limit": round(var_limit, 2)
    }

# ========== 最小可运行示例 ==========
if __name__ == "__main__":
    # 模拟某交易对历史价格(60天)
    np.random.seed(42)
    returns = np.random.normal(0.001, 0.02, 60)
    price_path = 100 * np.cumprod(1 + returns)
    prices = pd.Series(price_path)
    
    # 当前库存:500个单位的多头
    position = 500
    capital = 100000  # 可用资金10万
    
    result = inventory_risk_limit(position, prices, capital, confidence=0.95)
    
    print("=== 库存风险度量结果 ===")
    print(f"95% VaR (单日最大预期亏损): {result['VaR']} 元")
    print(f"95% CVaR (尾部平均亏损): {result['CVaR']} 元")
    print(f"建议单日风险限额: {result['suggested_limit']} 元")
    print(f"预警触发线: {result['warning_line']} 元")
    print(f"资金约束上限: {result['capital_limit']} 元")
    print(f"VaR约束上限: {result['var_limit']} 元")

运行与验证

运行方式:直接执行脚本(需安装 numpy 和 pandas):

pip install numpy pandas
python inventory_risk.py

验证方法:
1. 检查输出中 VaR 与 CVaR 均为正数,且 CVaR ≥ VaR(尾部均值必然不低于分位数);
2. 验证逻辑正确性:将 confidence 从0.95改为0.99,VaR值应增大;
3. 将 position 改为负数(空头),VaR仍为正数且数值合理;
4. 手动构造极端行情(如连续大跌),确认VaR/CVaR显著上升,限额自动收紧。

预期输出(基于上述随机种子):

=== 库存风险度量结果 ===
95% VaR (单日最大预期亏损): 1523.47 元
95% CVaR (尾部平均亏损): 1987.32 元
建议单日风险限额: 2285.21 元
预警触发线: 1589.86 元
资金约束上限: 20000.0 元
var_limit: 2285.21 元

关键说明

  • 本实现采用历史模拟法,直接使用价格序列的一阶差分作为损益分布,未引入参数假设;
  • 风险限额取“资金硬约束”与“VaR动态约束”的较小值,确保极端行情下自动降杠杆;
  • CVaR预警线用于盘中监控:当浮亏接近该值时触发减仓或对冲操作;
  • 实际生产环境建议将价格序列替换为自建报价数据,并加入流动性调整因子。