You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

同列存储多债券历史价格场景下计算各债券历史波动率的问题求解

代码调整方案

问题根因

  • 原代码最后一行直接对全列log_return计算标准差,没有按ISIN分组,且标量无法正确匹配到每行,所以返回NaN
  • 滚动窗口代码参数设置错误:window=1, freq='A'代表按年频率取窗口,每个窗口仅统计1个观测值的标准差,自然每个ISIN只有少量结果
  • 不需要将ISIN转为宽表计算,长表分组计算是更节省内存的方案,完全适配9000只债券的计算需求

方案1:计算单只债券全时间段的静态历史波动率

如果你需要的是每只债券在整个数据集时间范围内的固定波动率,直接对log_return按ISIN分组后用transform回填结果即可:

import pandas as pd
import numpy as np

vol_df = pd.read_csv('hist_prices.csv')
vol_df['BusinessDate'] = pd.to_datetime(vol_df['BusinessDate'])
# 按ISIN+日期排序,避免收益率计算顺序错误
vol_df = vol_df.sort_values(['ISIN', 'BusinessDate']).reset_index(drop=True)
vol_df['Mid Price'] = vol_df[['Bid', 'Ask']].mean(axis=1)
vol_df['log_return'] = vol_df.groupby('ISIN')['Mid Price'].apply(lambda x: np.log(x) - np.log(x.shift(1)))
# 分组计算标准差后回填到对应行
vol_df['hist_vol'] = vol_df.groupby('ISIN')['log_return'].transform('std') * np.sqrt(252)

方案2:计算单只债券的滚动历史波动率

如果需要按窗口滚动计算动态波动率,调整滚动窗口参数即可,支持按观测值数量或者时间范围两种窗口模式:

# 先将日期设为索引,适配时间窗口计算
vol_df = vol_df.set_index('BusinessDate')
# 滚动波动率计算
rolling_vol = vol_df.groupby('ISIN')['log_return'].rolling(
    # 可选1:按观测值数量设窗口,适配不同债券交易日数不一致的场景,window=252代表取最近252个有效交易日的收益率
    window=252,
    # 可选2:按时间范围设窗口,window='252D'代表取最近252个自然日内的所有有效收益率
    # window='252D',
    min_periods=60,  # 窗口内最少有60个有效收益率才计算,避免样本太少结果失真,可根据需求调整
    closed='left'  # 排除当前行的收益率,避免未来数据引用,可根据需求调整
).std() * np.sqrt(252)
# 结果回填到原表
vol_df = vol_df.reset_index()
vol_df['rolling_hist_vol'] = rolling_vol.reset_index(drop=True)

注意事项

  • 单只债券如果有效收益率记录少于min_periods的设定值,对应波动率结果会返回NaN,属于正常情况
  • 计算前务必按ISIN+交易日排序,避免收益率计算顺序错误导致结果偏差

内容的提问来源于stack exchange,提问作者user16708102

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 13:24:03