第二十九章 回测框架:将平滑曲面应用于期权定价与对冲策略回测
好了,终于到了把前面所有平滑技术串起来的时候了。
说实话,很多人在做波动率曲面平滑时,容易陷入一个误区——把曲面做得特别漂亮,各种样条、各种正则化,结果一放到回测里,效果反而不如原始数据。为什么?因为平滑本身不是目的,目的是让定价更准、对冲更稳。
我个人习惯是:先跑一个裸的回测,再逐步加入平滑曲面,对比着看。这样你才能知道,你花了大把时间调的平滑参数,到底值不值。
29.1 回测框架的核心设计思路
回测框架说白了就三件事:
- 数据输入:历史期权链数据、标的资产价格、无风险利率
- 策略逻辑:你用什么规则交易?是delta对冲?还是波动率套利?
- 曲面引擎:每次定价时,从平滑后的曲面上取波动率
我在项目中遇到过最坑的事,就是回测时每次都要重新平滑整个曲面。你想想看,如果数据量一大,回测跑一天都出不来结果。所以,预计算是关键。
核心原则:曲面平滑只做一次,回测时直接查表插值。
29.2 数据预处理与曲面缓存
我们先看数据怎么组织。假设你每天都有期权数据,我建议按以下结构存储:
# 伪代码:曲面缓存结构
class VolSurfaceCache:
def __init__(self):
self.surfaces = {} # key: 日期, value: 平滑后的曲面对象
def build_from_chain(self, date, option_chain):
# 用前面章节的SVI或样条方法平滑
surface = smooth_surface(option_chain)
self.surfaces[date] = surface
def get_vol(self, date, strike, expiry):
surface = self.surfaces[date]
return surface.interpolate(strike, expiry)
嗯,这里要注意:不要把原始数据直接丢进回测循环。我见过有人每天在回测里重新拟合SVI参数,结果一个月的回测跑了三天。正确的做法是,先离线把所有日期的曲面都算好,存成pickle或者parquet文件。
29.3 期权定价引擎集成
有了平滑曲面,定价就变成了查表。我们以欧式期权为例:
def price_option(S, K, T, r, surface, date, option_type='call'):
# 从平滑曲面获取波动率
sigma = surface.get_vol(date, K, T)
# 标准Black-Scholes定价
d1 = (np.log(S/K) + (r + 0.5*sigma**2)*T) / (sigma*np.sqrt(T))
d2 = d1 - sigma*np.sqrt(T)
if option_type == 'call':
price = S*norm.cdf(d1) - K*np.exp(-r*T)*norm.cdf(d2)
else:
price = K*np.exp(-r*T)*norm.cdf(-d2) - S*norm.cdf(-d1)
return price
你可能会问:直接用原始隐含波动率不行吗?行,但你会遇到两个问题:
- 原始数据有缺失,某些行权价没报价
- 原始数据有噪音,导致对冲时delta跳来跳去
平滑曲面解决的就是这两个问题。我曾经在回测中对比过,用平滑曲面后,delta对冲的换手率降低了约15%。
29.4 对冲策略回测示例
我们做一个最简单的delta中性策略。每天收盘前,根据平滑曲面计算期权delta,然后买卖标的资产使组合delta归零。
def run_delta_hedge_backtest(data, surface_cache):
positions = {'option': 0, 'stock': 0}
pnl = []
for date in sorted(data.keys()):
row = data[date]
S = row['spot_price']
K = row['strike']
T = row['time_to_expiry']
r = row['rate']
# 用平滑曲面算delta
sigma = surface_cache.get_vol(date, K, T)
delta = black_scholes_delta(S, K, T, r, sigma)
# 调整标的仓位
target_stock = -delta * positions['option']
trade_stock = target_stock - positions['stock']
positions['stock'] = target_stock
# 记录损益
pnl.append(compute_pnl(positions, row))
return pnl
小技巧:回测时建议同时跑两个版本——一个用原始波动率,一个用平滑曲面。这样你就能直观看到平滑带来的收益提升。我自己的经验是,平滑曲面在深度虚值期权上的效果最明显。
29.5 回测结果评估指标
光跑回测不行,你得知道怎么评价。我一般看这几个指标:
| 指标 | 说明 | 平滑曲面预期效果 |
|---|---|---|
| 年化收益率 | 策略总收益年化 | 略有提升 |
| 夏普比率 | 风险调整后收益 | 明显提升 |
| 最大回撤 | 最差情况下的亏损 | 降低 |
| 换手率 | 交易频率 | 降低(对冲更稳) |
| 对冲误差 | 实际delta与目标delta的偏差 | 显著降低 |
说实话,我最看重的是对冲误差。因为平滑曲面最大的价值,就是让delta更稳定。你想想看,如果delta每天跳来跳去,你就要频繁交易,成本全被手续费吃掉了。
29.6 核心流程图:回测框架整体架构
下面这张图是我自己项目里用的框架结构,你可以参考:
避坑指南:我曾经在回测中忘记考虑交易成本,结果平滑曲面带来的换手率降低优势完全没体现出来。记住,交易成本是回测的照妖镜,一定要加进去。
29.7 实战中的几个坑
最后分享几个我踩过的坑:
- 曲面外推问题:回测中可能会遇到行权价超出历史范围的情况。我的做法是,用最临近的波动率填充,不要外推太远。
- 时间衰减处理:期权到期日临近时,曲面会变得很不稳定。我建议到期前3天就剔除这些数据。
- 分红与拆股:这些事件会导致价格跳跃,平滑曲面要重新校准。别偷懒,该重算就重算。
嗯,回测框架这块内容其实挺多的。但核心就一句话:平滑曲面是工具,回测是检验工具的唯一标准。你花再多时间调参数,最后都要回到回测结果上来。
总结:把平滑曲面集成到回测框架中,本质上就是三步——预计算曲面、查表定价、对比评估。别搞复杂了。
公众号:蓝海资料掘金营,微信deep3321