4. 度量库存风险价值(VaR)
任务目标
本案例针对做市商持有的库存头寸,使用历史模拟法计算日度VaR(95%置信水平),评估正常市场条件下库存可能面临的最大损失。输入为库存中每个资产的历史日收益率序列,输出为组合层面的日VaR值。
实现思路
历史模拟法不假设收益率服从特定分布,直接使用历史收益率分布的分位数来估计VaR。核心步骤:
- 将每个资产的当前市值与历史日收益率相乘,得到该资产的历史每日损益序列;
- 将同一历史日所有资产的损益加总,得到组合的历史每日损益序列;
- 取该序列在95%置信水平下的分位数(即第5百分位数的损失值),即为日VaR。
关键完整代码
import numpy as np
import pandas as pd
def calculate_historical_var(returns_df, current_positions, confidence_level=0.95):
"""
使用历史模拟法计算做市库存的日VaR
Parameters:
-----------
returns_df : pd.DataFrame
历史日收益率矩阵,每列对应一个资产,行索引为日期
current_positions : dict
当前持仓市值,格式: {'资产名称': 当前市值}
confidence_level : float
置信水平,默认95%
Returns:
--------
dict: 包含VaR值、历史损益序列及对应百分位数的结果
"""
# 1. 校验输入
assert set(returns_df.columns) == set(current_positions.keys()), \
"收益率列与持仓资产不匹配"
# 2. 计算每个资产的历史日损益序列(市值 × 收益率)
pnl_df = pd.DataFrame(index=returns_df.index)
for asset in returns_df.columns:
pnl_df[asset] = returns_df[asset] * current_positions[asset]
# 3. 组合历史日损益 = 各资产损益之和
portfolio_pnl = pnl_df.sum(axis=1)
# 4. 计算VaR(取损失侧分位数,VaR为正数表示损失金额)
var = -np.percentile(portfolio_pnl, (1 - confidence_level) * 100)
return {
'VaR': var,
'portfolio_pnl': portfolio_pnl,
'percentile': (1 - confidence_level) * 100
}
# ========== 最小可复现示例 ==========
if __name__ == "__main__":
# 构造示例数据:3个资产,500个历史交易日
np.random.seed(42)
dates = pd.date_range('2023-01-01', periods=500, freq='D')
# 模拟历史日收益率(均值0,标准差0.02/0.015/0.01)
returns_data = {
'AAPL': np.random.normal(0, 0.02, len(dates)),
'MSFT': np.random.normal(0, 0.015, len(dates)),
'TSLA': np.random.normal(0, 0.025, len(dates))
}
returns_df = pd.DataFrame(returns_data, index=dates)
# 当前做市库存持仓市值(美元)
current_positions = {
'AAPL': 500000,
'MSFT': 300000,
'TSLA': 200000
}
# 计算95%日VaR
result = calculate_historical_var(returns_df, current_positions, confidence_level=0.95)
print(f"95%日VaR: ${result['VaR']:,.2f}")
print(f"历史损益序列长度: {len(result['portfolio_pnl'])}天")
print(f"对应分位数: {result['percentile']}%")
# 输出预期结果(基于上述固定随机种子可复现)
# 预期输出示例(实际数值由np.random.seed(42)决定):
# 95%日VaR: $XX,XXX.XX
# 历史损益序列长度: 500天
# 对应分位数: 5.0%
运行与验证
运行方式:直接执行脚本(需安装 numpy 和 pandas):
pip install numpy pandas
python var_historical.py
验证方法:
- 程序正常输出VaR金额、损益序列长度(500天)和分位数(5.0%);
- 手动验证:将
portfolio_pnl按升序排列,取第25个值(500×5%)的相反数,应与输出的VaR一致; - 改变置信水平为0.99,VaR值应增大(更极端的尾部损失);
- 将任一资产市值设为0,VaR应相应减小,反映该资产不再贡献风险。
常见问题
- 历史数据长度不足:历史模拟法要求至少100个以上交易日数据,否则分位数估计不稳定;
- 持仓变化:本方法假设持仓在历史期间保持不变,若实际持仓动态变化,需按日重新计算或使用加权历史模拟法;
- VaR的局限性:VaR不衡量超过分位点的尾部损失规模,如需评估极端风险应结合预期亏损(ES)分析。