ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

波动率曲面预测:融合随机过程的 Transformer 方法

波动率曲面预测:融合随机过程的 Transformer 方法 简介面向金融量化研究与机器学习交叉领域的一份PDF资料聚焦随机过程Transformer在期权波动率曲面预测中的应用。文档从期权与波动率曲面基础讲起涵盖Black-Scholes模型局限、波动率微笑、曲面构建再深入Transformer架构与随机过程结合的动机、模型构建及优势并详细展开数据处理、特征工程、训练优化与实验评估最后给出金融机构风险管理、投资组合配置、交易策略制定等实际案例及挑战展望。适合金融工程、量化分析、深度学习方向的研究人员与开发者作为建模思路与论文框架参考。资源为1个PDF文件共27页约2.05MB支持目录跳转与大纲定位图表文字显示正常阅读检索方便。已有71人学习浏览可作为入门到进阶的完整学习材料。1. 波动率曲面预测里随机过程 Transformer 想解决什么问题期权交易台每天最头疼的不是希腊字母算不准而是波动率曲面只有稀疏报价手里攒三五个到期日、七八个行权价就得预测未来一整片曲面。直接拿普通 Transformer 做这件事最尴尬的是位置编码里的时间戳是确定性整数模型只会均匀外推市场一旦出现跳跃或波动率聚簇预测曲面会当场压成平板。随机过程 Transformer 的思路是把随机微分方程SDE的状态演化装进注意力结构注意力负责同一个时间点上几十个行权价的横截面关系随机过程层负责时间轴上的路径相关性两者共享同一套隐状态。衍生品定价里曲面预测误差会直接变成 vega 对冲成本这也是它值得动手去试的原因。适合谁做期权曲面预测、波动率标定、或者风控情景生成的人。下文我会按自己平时做这类模型的惯用方案从原理、数据、核心代码到高频翻车点完整走一遍。2. 为什么偏要给 Transformer 接随机过程从期权市场的三条硬规律说起2.1 均值回归、波动率聚簇与跳跃决定了纯注意力模型的边界期权波动率曲面不是一张静止的图片它背后有三个被做市商当成信仰的随机规律。第一是均值回归。隐含波动率不管短期冲到多少长期看都会往一个随机但稳定的水平回摆。这来自波动率交易者的存在当曲面出现极度扭曲套利盘会进来把期限结构重新拉回常态。第二是波动率聚簇。大涨大跌之后波动率往往持续偏高然后慢慢回落这个性质在期权市场比股票市场更明显因为做市商的重新定价行为会放大延续性。第三是跳跃。财报、央行决议、盘中闪崩都会让波动率曲面在几分钟内完成一次显著的截面重构和刚才还完全不同的期限结构。普通 Transformer 处理时间轴用的是位置编码本质是给每个时间点分配一个确定性向量。这个向量只能表达第几天了表达不了这个时点有百分之多少的概率进入高波动状态。于是模型在训练集上看似学懂了曲面形态实际上只是把历史当成静态图片做外推。2.2 Transformer 干得漂亮的部分横截面与长程依赖Transformer 真正擅长的是横截面建模。一组到期日、一组行权价、一组隐含波动率数值打包成一个二维网格注意力机制能在一次前向传播里同时观察到所有格点之间的相互关系。讲个实实在在的好处曲面某处的凸度异常往往不是孤立存在的它会沿同一到期日扩展到相邻行权价也会沿同一 delta 区域跨期限传播。CNN 需要堆很多层才让感受野覆盖完整曲面Transformer 第一层注意力就能做全网格的隐式连接。如果我们要的是上保真风险情景路径跟踪和状态更新是必需的——这里就该听随机过程的。说直白点Transformer 负责像人一样把曲面当成一张图来看但图的演变规律它缺少一个天然组件来表达不确定性。2.3 随机过程层的三种接法前馈注入、隐状态升级与融合注意力我见过不少设计总结了三条主流的融合路线。第一种是前馈注入。位置编码照常使用在每一层 TransformerBlock 的输入上叠加一个由 SDE 采样生成的扰动向量。实现简单训练稳定但随机性只影响输入没有真正参与状态演化表达能力有限。第二种是隐状态升级。把 Transformer 每层的输出当作 SDE 的初始状态做一步欧拉丸山采样得到带随机性的下一层输入。这种做法和 Neural ODE 的思路同源能表达连续时间状态演化是现在做随机过程 Transformer 最常见的落法。第三种是融合注意力。把随机过程的协方差矩阵逼近成注意力矩阵的一支——在 QK 相似度之外再叠加一个源自扩散核的相似度项。理论上最优但实现复杂度高而且训练时对数值稳定性非常敏感。我平时做项目首选第二种折中最好。它不会让模型变成一个黑匣子随机过程和注意力各司其职出了问题也容易定位。2.4 用白话描述一个随机过程 Transformer 的前向流程模型拿到的是最近 N 天的波动率曲面序列形状是 (天数, 到期日档位, 行权价档位)。每一步前向传播都按这个顺序走先做曲面网格嵌入把三维数据压成 token 序列每个 token 进入 Transformer 编码器前经过一层 SDE 预演用当前隐状态计算漂移和扩散采样出一个更新后的隐状态注意力层在这个隐状态序列上做模式匹配最后通过解码头预测未来某个时间点的曲面增量。这里的关键点是增量。模型学的是当前曲面未来会变多少而不是直接输出未来曲面长什么样。前者需要随机过程来描述不确定性后者只是一个回归函数。这个区别在后面的数据处理里会有很大影响。3. 数据准备是成功的一半从期权报价到干净的曲面张量3.1 隐含波动率反解二分法还是牛顿法期权报价一般给的是权利金价格需要先反解出隐含波动率。常见做法是牛顿法它收敛快但在深度虚值区域容易震荡。我惯用二分法做兜底设定一个合理的波动率上下界保证每个合约都能在 64 次迭代内收敛。def implied_vol_bisection(S, K, T, r, q, market_price, lo1e-4, hi5.0): for _ in range(64): mid (lo hi) / 2 price bs_price(S, K, T, r, q, mid) if price market_price: hi mid else: lo mid return (lo hi) / 2 def bs_price(S, K, T, r, q, sigma): from math import log, sqrt, exp from scipy.stats import norm d1 (log(S / K) (r - q 0.5 * sigma ** 2) * T) / (sigma * sqrt(T)) d2 d1 - sigma * sqrt(T) call S * exp(-q * T) * norm.cdf(d1) - K * exp(-r * T) * norm.cdf(d2) return call这里 64 次迭代是固定循环不用 while 判断浮点差值避免有些价格在边界上永远不收敛。hi5.0表示 500% 波动率上限对绝大多数场内期权足够了如果数据里有个别异常深虚值期权超过这个范围应该在清洗阶段直接剔除而不是放宽边界。3.2 曲面网格标准化到期日与行权价的对齐每个交易日可用的期权行权价和到期日都不同必须映射到统一网格上模型才能训练。常见做法是选固定的到期日档位比如 7 天、30 天、90 天、180 天、365 天行权价用对数金钱度 mln(K/F) 表示从 -0.3 到 0.3 分成 20 档。维度常用档位说明到期日5 档7D/30D/90D/180D/365D覆盖主要交易期限行权价20 档对数金钱度等间距避免存续期带来的水平漂移输入序列长度60 天过去 60 个交易日历史曲面预测目标未来 1/5/10 天分别对应短线对冲和中线风险场景每个网格点用三次样条插值补齐。行权价方向的插值比到期日方向敏感得多因为近月曲面凸度变化剧烈所以我会在行权价方向用自然三次样条、在到期日方向用线性插值两者混搭比全部三次样条更稳。3.3 无套利条件先清洗还是后惩罚波动率曲面不是随便什么形状都能存在的。理论上任一时刻的曲面对应到期权价格必须满足日历价差单调性和蝶式价差非负性否则市场里存在套利机会。数据清洗阶段我会先做一次轻量检查如果某个格点插值结果导致蝶式价差明显为负就把它剔除用相邻值补上。这是为了不让模型的训练样例里出现完全违背金融常识的输入。真正强约束的套利剔除会放在损失函数里作为软惩罚加入训练。清洗和惩罚两者是配合关系前者防脏数据后者约束模型输出只做一个都不够。3.4 特征标准化曲面增量比绝对水平更容易学数据通道只用绝对波动率数值模型往往学到的是预测当前曲面等于上一个时间点曲面的退化解。我常用的做法是构造目标为曲面差分你不用预测未来曲面的绝对值而是预测未来与当前值之间的变化量。def make_samples(vol_surface, target_days5): X, y [], [] for t in range(len(vol_surface) - target_days): x vol_surface[t - 60:t] # 输入最近60天 y vol_surface[t target_days] - vol_surface[t] # 预测差分 X.append(x) y_list.append(y) return torch.tensor(X, dtypetorch.float32), torch.tensor(y_list, dtypetorch.float32)差分目标天然剔除了随机水平偏移。模型中即使只学到未来变化量均值接近 0也能给出不差的绝对值但如果目标是绝对水平模型很容易陷入拷贝输入。此外差分目标对异常行情更敏感当真实市场发生跳跃时差分序列会产生明显的尖峰SDE 模块才能在训练中见到这种跳跃模式。4. 核心工程实现随机过程 Transformer 的 PyTorch 代码骨架4.1 模型输入的数据形态说明进入模型前每个样本的形状是 (B, 60, 5, 20)分别对应批量、历史天数、到期日档位、行权价档位。我会先把它压成二维 token 序列每一天的 5x20 小矩阵拉平成 100 维向量然后序列长度就是 60。这样的建模方式把同一天内的曲面结构装进一个 token 内部让注意力机制在 60 个连续时间 token 之间寻找跨期规律。比把每个格点当成独立 token 更高效也符合期货曲面低秩的特性。4.2 SDE 预演模块欧拉丸山采样实现先写最重要的 SDE 模块。这个模块做的事情是接收一个 token 向量输出一个经随机微分方程演化后的新向量。import torch import torch.nn as nn import torch.nn.functional as F import math class SDEBlock(nn.Module): def __init__(self, dim, dt0.05): super().__init__() self.drift_net nn.Sequential( nn.Linear(dim, dim), nn.ReLU(), nn.Linear(dim, dim) ) self.diffusion_net nn.Sequential( nn.Linear(dim, dim), nn.ReLU(), nn.Linear(dim, dim) ) self.dt dt def forward(self, x): mu self.drift_net(x) # 漂移项刻画状态均值走向 sigma F.softplus(self.diffusion_net(x)) 1e-3 noise torch.randn_like(x) return x mu * self.dt sigma * noise * math.sqrt(self.dt)逻辑说明这里走的是欧拉丸山积分的最简形式。漂移网络决定下一状态往哪个方向走扩散网络决定随机扰动的强度。扩散部分用 softplus 保证输出永远是正数再加 1e-3 防止退化到零否则模型能学会把随机项关掉等于静态 Transformer。参数说明dt不宜设太大0.05 是一个保守起步值。它相当于把单位时间步拆成 20 个子步给随机过程足够细的粒度。如果训练中发现预测曲面过于平滑可以把 dt 调大到 0.1如果训练不稳定先把它调小到 0.01。理论上可以做可学习的 dt但我试过几次都容易在训练后期发散最后还是固定值更省心。4.3 完整模型SDE 块加 TransformerEncoderclass StochasticProcessTransformer(nn.Module): def __init__(self, d_in100, d_model256, nhead8, num_layers6, num_sde_layers2, dropout0.1): super().__init__() self.input_proj nn.Linear(d_in, d_model) self.sde_layers nn.ModuleList( [SDEBlock(d_model, dt0.05) for _ in range(num_sde_layers)] ) encoder_layer nn.TransformerEncoderLayer( d_modeld_model, nheadnhead, dim_feedforward1024, dropoutdropout, batch_firstTrue, activationgelu ) self.encoder nn.TransformerEncoder(encoder_layer, num_layersnum_layers) self.head nn.Linear(d_model, 100) def forward(self, x): # x: (B, 60, 100) x self.input_proj(x) # (B, 60, 256) for sde_layer in self.sde_layers: x sde_layer(x) # 在进入注意力前完成过程演化 x self.encoder(x) # (B, 60, 256) x x[:, -1, :] # 取最后一天的状态代表整个序列 return self.head(x) # (B, 100) 输出未来曲面差分逻辑说明input projection 负责升维每一个 SDE 层对序列的所有时间点做一次独立随机演化然后进入多头注意力。这里把 SDE 放在注意力前面是为了让注意力感知的不是原始粗糙特征而是已经携带过程演化信息的隐状态。参数说明d_model256 是一个性价比很高的起始值太小了表达不了曲面太大了在小批量上容易过拟合。num_sde_layers2 是因为 SDE 层多了会造成训练不稳定它的职责是建模时间过程不需要堆深真正的模式匹配交给后面的 6 层 TransformerEncoder。提示如果显存有限先把 num_layers 从 6 降到 4比先砍 d_model 更稳妥。序列长度 60 不算长4 层注意力处理跨期依赖通常够用了。4.4 损失函数曲面误差加无套利软惩罚损失函数我拆成三块。第一块是预测曲面差分的均方误差。第二块是蝶式价差的负部惩罚用来约束行权价方向的凸度。第三块是日历价差单调性惩罚。def loss_func(pred_diff, target_diff, current_surface): mse F.mse_loss(pred_diff, target_diff) pred_surface current_surface pred_diff # 近似蝶式价差二阶差分 butterfly torch.clamp(-pred_surface[:, :-2] 2 * pred_surface[:, 1:-1] - pred_surface[:, 2:], min0) butterfly_penalty butterfly.mean() # 日历价差单调性短期 iv 不应低于长期太多做软约束 calendar_diff pred_surface[:, 1:] - pred_surface[:, :-1] calendar_penalty torch.clamp(-calendar_diff - 0.02, min0).mean() total_loss mse 0.2 * butterfly_penalty 0.05 * calendar_penalty return total_loss三个权重需要在验证集上手动调整。我一般先固定 mse 权重为 1观察无套利惩罚项的量级再调两个系数。如果蝶式惩罚把曲面压得过平就把 0.2 下调到 0.1。日历项前的 0.02 是一个容忍阈值允许长期和短期之间存在最多两个点的倒挂过于严格会让模型预判出凭空的正向期限结构。4.5 训练计划与超参盘点训练批次我取 64优化器用 AdamW学习率 1e-4 配合余弦退火。经验上随机过程 Transformer 对学习率比普通 Transformer 更敏感初始学习率超过 3e-4 时有很大概率在前 500 步发散。原因是 SDEBlock 的扩散项在高学习率下会让隐状态方差撑爆。超参数推荐值说明batch_size64太小则 SDE 随机性难以平均掉学习率1e-4超过 3e-4 极易发散亲身踩过num_sde_layers2太多层会造成训练振荡dt0.05 固定不学固定能减少数值漂移注意力层数4~64 层够用时没必要上 6 层dropout0.1过拟合时先调 dropout不先加正则训练总轮数大约 200 轮就够这一步不要贪多。我们真正要的是随机过程的泛化能力不是把训练集曲面背下来早停机制比长训更有效。5. 训练随机过程 Transformer 的四个典型避坑现场5.1 预测曲面整个摊平了像被熨斗烫过一样现象训练集 loss 一路下降但验证集上曲面形态越来越单调曲面凸度几乎消失所有行权价上的预测值挤在一起。原因目标用了绝对波动率模型发现复制输入就能拿到极低 loss。Transformer 本身不擅长外推它学到的偏置就是把输出拉向历史均值。复制输入和拉向均值都是安全牌所以 loss 很低但曲面科幻化了。解决改用差分目标后立刻缓解。我还在数据里加了曲面曲率特征作为监督信号的辅助通道——让模型预测的不只是格点值还包括二阶导形态。具体做法是把蝶式价差损失在训练开头就提高权重到 0.3逼它保留凸度。5.2 面对真实跳跃行情预测反应总慢半拍现象模型在正常波动区间表现良好但遇到财报日或突发消息预测曲面基本没有反应等到跳空已经发生时才开始调整。原因训练集里跳跃样本太少SDE 的扩散网络学到了一个偏小的平均方差。这相当于模型自己做了平滑把跳跃当作异常值给滤掉了。解决先看数据里波动率单日变化超过 10% 的样本占比。如果低于 2%要对这些样本做重复采样。我会把跳跃样本复制三份混入训练集并把 SDEBlock 中 diffusion net 的权重初始化调大一点。另一个更直接的手段是给输入加一维 realized variance 特征让模型能在跳跃形成期就捕捉到异常信号。5.3 训练后期 loss 突然出现尖峰模型像抽风现象训练到 80 轮左右loss 会偶尔跳到平时的 5 到 10 倍然后下几个 step 又恢复但整个模型的精度再也回不到最好位置。原因SDEBlock 的随机噪声在长时间训练后累积出异常大的隐状态范数梯度经过这个范数被放大产生了一次不稳定的参数更新。解决给隐状态加梯度裁剪同时限制 SDE 输出。我在 forward 函数的最后加了一个硬约束return x mu * self.dt sigma * noise * sqrt(self.dt) 之后对输出做了 LayerNorm。这个 LayerNorm 非常关键它一方面稳定分布一方面不让随机扰动无上限地污染表示。训练时梯度裁剪设置为 norm 上限 5.0。5.4 无套利惩罚项起了反作用曲面越训越平现象加上日历价差和蝶式惩罚之后曲面确实没有套利了但代价是预测结果完全失去交易价值几乎认不出原有曲面形态。原因惩罚项权重过高约束了模型表达能力的空间。模型发现最好的方式就是把所有格点预测成完全相同的均值让二阶差分和期限差都为零惩罚自然为零。解决惩罚项的系数不是越大越好。我的调参顺序是先算出三项 loss 各自的量级然后让无套利项的量级只占主 MSE 的 10% 到 20%。另外增加了项数约束蝶式惩罚只作用在相邻三档行权价上不要扩大感受野这样模型还能保留部分凸度。6. 落地验证与进阶技巧别只盯着 RMSE6.1 用三类独立检验替代单纯看整体误差预测曲面拿到手第一件事不是看平均绝对误差而是看预测曲面是否通过三关蝶式无套利、日历价差方向合理、以及期权价格单调性。我在实际部署时会在每天收盘后用模型输出一个虚拟曲面与当日市场闭盘价对比再检查这三个指标。连续三天有一项大幅超限就需要重新审视模型是不是已经失效。6.2 进阶技巧模型只预测变化量交易时挂在市场当前曲面上最后一条实战里最值钱的经验模型给出的是曲面差分真正落地时不要直接用它替换市场曲面。正确做法是以当天市场实盘波动率曲面为基准把预测出的差分叠加在基准上得到一个校准后曲面。这样模型误差不会全盘套在曲面上市场自身提供的一阶信息得到了保留。6.3 我自己的使用习惯与边界认知训练完多组模型做集成是我最后一道工序。同一个数据配三组不同随机种子SDE 层的初值大不相同预测结果天然自带一个分布区间。交易复盘时这个区间比点估计有用得多它能直观告诉你哪些到期日档位的预测分歧大那些地方原来就是模型最不确定的区域。我的教训是这类模型的预测结果要当建议用不当结论用做市系统接入前一定要留好人工打断开关。希望帮到你。本文还有配套的精品资源点击获取
返回列表