首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >硬核蹭热点系列:负油价和巴舍利耶模型

硬核蹭热点系列:负油价和巴舍利耶模型

作者头像
用户5753894
发布2020-05-13 17:37:29
发布2020-05-13 17:37:29
1.6K0
举报
文章被收录于专栏:王的机器王的机器

本文含 4494 字,25 图表截屏

建议阅读 30 分钟

0

引言

本文是「硬核蹭热点系列」系列的第一篇

  1. 负油价和巴舍利耶模型

2020 年 4 月 20 日美国原油期货价格暴跌约 300%,收于每桶 -37.63 美元。各大财经号都开始分析表达自己的看法。看法无对错,但有利益方总是挑着对自己有利的观点看,比如多头受害者就疯狂转发【金融监管研究院】的文章,质疑为什么不帮他们平仓止损;某行员工们就疯狂转发【秦小明】的文章,表示产品结算前操作没问题;空头受益者啥也不转发,觉得这一切很美丽。

看法无对错,挑着自己想看的而去争个对错毫无意义,事实才有真假,但是内部人员又不会说,咋咋乎乎的全是没有 skin-in-the-game 的外部人员。

我能做的只是从量化金融和 Python 实现的角度来看看负油价事件带来的影响吧。在期货价格为负的第二天,芝加哥商品交易所(CME)就发了一则通知,截屏如下(注意高亮字段):

要看全文通告可点击下面的原文链接

CME 从 2020 年 4 月 21 日起将以原油期货为标的的期权定价和估值模型从布莱尔斯科尔斯(Black-Scholes, BS)模型换成巴舍利耶(Bachelier)模型。

很明显,CME 换模型就是要考虑“标的价格可以为负”的情景了,BS 模型下的价格永远为正,而 Bachelier 模型下的价格可正可负。

本帖内容结构如下:

  • 首先回顾 Black-Scholes 模型,介绍到期日的价格如何模拟,已经如何反解隐含波动率。
  • 接着研究 Bachelier 模型,包括从头到尾的详细公式推导,以及相同 BS 价格倒推出来的波动率和 BS 波动率有什么关系。

由于本帖蹭得是原油热点,我就按商品为资产类型来描述 BS 和 Bachelier 模型下的相关术语。

1

Black-Scholes 模型

原生资产 (商品现货价格) 的随机微分方程(SDE)如下:

其中

  • S(t) = 资产在时点 t 的值
  • r= 常数型瞬时利率
  • q = 常数型便利收益率 (net convenience yield)
  • σ = 常数型瞬时波动率
  • W(t) = 布朗运动

对于消费型商品(非投资型商品如黄金或白银),你持有现货会给你带来便利(convenience yield),但也会有存储费用(cost of carry),而上面的 q 是便利,就是便利和费用的差。

BS 的推导见得太多了,因此简叙一下推导步骤:

  1. 用伊藤公式解 SDE 得到 S(T)
  2. 将 S(T) 带入期权支付函数中求积分

首先根据伊藤公式解 S(T)

再求积分得到期权定价公式,看涨看跌期权用 ω 来区分,ω = 1 时为看涨,ω = -1 时为看跌:

通常我更喜欢把公式写成 F(t, T) 形式,ln(F(t, T)/K) 衡量着价内外状态(moneyness),而

才是 S 从 t 到 T 的真正的波动率,σ 并不是,它只是波动率系数。

路径模拟

在用代码来实现 BS 模型前,我们先来模拟 10 条不同路径的 S(T),按照以下公式,先模拟 lnS(T),再用 exp(lnS(T)) 返回到 S(T)

代码如下:

代码语言:javascript
复制
(S0, r, q, T, sigma) = (1, 0.02, 0.01, 1, 0.5)
(Nsim, Nt) = (10, 1000)
t = np.linspace(0,T,Nt)
dt = np.diff(t)

z = np.random.randn(Nsim, Nt-1)
A = (r-q-0.5*(sigma)**2)*dt + sigma*(z*np.sqrt(dt))

lnS0 = np.tile(np.log(S0),(Nsim,1))
lnS = lnS0 + np.cumsum(A, axis=1)
lnS = np.hstack( (lnS0, lnS) )
S = np.exp(lnS)

用 cufflinks 来画图:

代码语言:javascript
复制
label = [ x + ' ' + str(y) for x, y in zip(['path']*Nsim, np.arange(1,Nsim+1)) ]
df = pd.DataFrame(S.T, index=t, columns=label)
df.iplot( xTitle='t', 
          yTitle='S', 
          title='Black-Scholes 模型价格路径模拟', 
          theme='ggplot' )

要点:S(T) 没有负值

期权定价

实现 BS 模型的代码如下:

测试一下 blackscholes() 得到一个看涨期权价格为 7.5459,记住这是用 0.1 = 10% 的波动率计算出来的结果。

代码语言:javascript
复制
(S0, K, r, q, T, sigma, omega) = (100, 95, 0.01, 0, 1, 0.1, 1)
V_BS = blackscholes(S0, K, r, q, T, sigma, omega)
V_BS
代码语言:javascript
复制
7.545870893948695

反解波动率

给定市场上期权的交易价格,根据 BS 模型的公式可以反解出波动率,即波动率等于多少用 BS 公式可以刚好计算出期权价格。

实现起来非常简单,用 scipy.optimize 里面的 fsolve 即可,代码如下:

用上面计算出的结果 V_BS,看是否能反解出 0.1 的波动率呢。没有问题。

代码语言:javascript
复制
get_BS_IV( V_BS, S0, K, r, q, T, omega )
代码语言:javascript
复制
0.09999999999999983

上面这些 Quant 都玩熟了,直到 Bachelier 模型出现,我们还是可以按照上面的思路来继续玩。

2

Bachelier 模型

原生资产 (商品现货价格) 的随机微分方程(SDE)如下:

其中

  • S(t) = 资产在时点 t 的值
  • r= 常数型瞬时利率
  • q = 常数型便利收益率 (net convenience yield)
  • σ = 常数型波动率
  • W(t) = 布朗运动

上面大多参数含义和 BS 模型中的一样, 只有 σ 不再是瞬时波动率,而是波动率了,注意 SDE 的扩散项(diffusion term)只有 σ,没有 S(t) 了,那么这里 σ 指的是一个波动率的绝对数目,而不是比率。但是漂移项(drift term)还带 S(t),这点非常重要,因为 r 和 q 还是一个比率的概念,而不是一个具体数目的概念。

Bachelier 的推导虽然很早就有了,但可能大家没怎么关注,因此详叙一下推导步骤:

  1. 用通用线性 SDE 的解得到 S(T)
  2. 将 S(T) 带入期权支付函数中求积分

首先通用线性 SDE 的解 S(T)

想看推导的就看篮框里的内容,不想看的跳过篮框。

再用等距性质 (Isometry property) 得到

接下来再求积分得到期权定价公式,同样看涨看跌期权用 ω 来区分,ω = 1 时为看涨,ω = -1 时为看跌:

这时把 F(t, T) - K 衡量着价内外状态(moneyness),同理而 v 才是 S 从 t 到 T 的真正的波动率,σ 并不是,它只是波动率系数。

想看上面公式推导的就看篮框里的内容,不想看的跳过篮框。

硬核推导完了,接下来就来看看 Bachelier 下的路径模拟和期权定价。

路径模拟

代码如下:

代码语言:javascript
复制
(S0, r, q, T, sigma) = (1, 0.02, 0.01, 10, 0.5)
(Nsim, Nt) = (10, 1000)
t = np.linspace(0,T,Nt)
dt = np.diff(t)
z = np.random.randn(Nsim, Nt-1)

A = np.exp((r-q)*t)

if r == q:
    B = sigma*(z*np.sqrt(dt)) / A[1:]
else:
    B = sigma*(z*np.sqrt( (np.exp(2*(r-q)*dt)-1) / (2*(r-q)) )) / A[1:]

discS0 = np.tile( S0/A[0], (Nsim,1) )
discS = discS0 + np.cumsum(B, axis=1)
discS = np.hstack( (discS0, discS) )
S = discS * A

用 cufflinks 来画图:

代码语言:javascript
复制
label = [ x + ' ' + str(y) for x, y in zip(['path']*Nsim, np.arange(1,Nsim+1)) ]
df = pd.DataFrame(S.T, index=t, columns=label)
df.iplot( xTitle='t', 
          yTitle='S', 
          title='Bachelier 模型价格路径模拟', 
          theme='ggplot' )

要点:S(T) 有负值

其实要模拟出负值,S 要小,σ 要大。这不正是 4 月 20 日晚上发生的情况吗?其他情况下模拟出负价格的概率也不大。

期权定价

实现 Bachelier 模型的代码如下:

用 blackscholes() 模型同样的参数(虽然不合理,等下讲)带入 bachelier() 得到一个看涨期权价格为 5.9453。

(S0, K, r, q, T, sigma, omega) = (100, 95, 0.01, 0, 1, 0.1, 1)V_BL = bachelier(S0, K, r, q, T, sigma, omega)V_BL

代码语言:javascript
复制
5.945265793829019

不合理的点在于 BS 和 Bachelier 中的波动率含义不一样:

  • BS 的 σ 是比率的概念,10%,20% 等
  • Bachelier 的 σ 是数目的概念,10, 20 等

因此输入波动率为 0.1*S0 才能得到和 BS 匹配的结果,来试试

V_BL = bachelier(S0, K, r, q, T, sigma*S0, omega)V_BL

代码语言:javascript
复制
7.630422479463851

果然和 BS 的家国 7.5459 很接近。那其实我们在反解 Bachelier 模型下的波动率时,可以近似用

BS 波动率 / S0

接下来我们来看看 Bachelier 是否能计算当 S0 为负时的期权价格,来假设模拟 20 日当天的情况,S0 = -37。期权刚发行时一般都按照当时的远期价格,假设 K = 20,来运行代码:

代码语言:javascript
复制
(S0, K) = (-37, 20)
V_BL = bachelier(S0, K, r, q, T, sigma*np.abs(S0), omega)
V_BL
代码语言:javascript
复制
1.246987875662463e-54

价格几乎为零,合理!

要点

Always Know Your Shit

When Playing Your Toys

反解波动率

给定市场上期权的交易价格,根据 Bachelier 模型的公式可以反解出波动率,即波动率等于多少用 Bachelier 公式可以刚好计算出期权价格。

实现起来非常简单,也用 scipy.optimize 里面的 fsolve 即可,代码如下:

现在我们用 V_BS 价格来反解出 Bachelier 模型的波动率。

代码语言:javascript
复制
(S0, K, r, q, T, omega) = (100, 95, 0.01, 0, 1, 1)
BS_sigma = 0.1
BS_price = blackscholes(S0, K, r, q, T, BS_sigma, omega)
BL_price = BS_price
BL_sigma = get_BL_IV( BL_price, S0, K, r, q, T, omega )
BL_sigma
代码语言:javascript
复制
9.744178790421072
代码语言:javascript
复制
用和近似解得到的 0.1*100 = 10 相比接近,合理。

3

总结

BS 和 Bachelier 最大的不同就是

  • BS 模型下的 S(T) 是对数正态分布,永远为正
  • Bachelier 模型下的 S(T) 是正态分布,可正可负

Bachelier 模型可以计算负期货价格下的期权价值,但我们上面一直在讲现货价格的 SDE。其实期货价格的 SDE 更简单,没有漂移项只有扩散项,上面所有公式还是能用,把 r 和 q 设定为零就行。

现在我在思考一个问题,用 shifted-lognormal 模型(即 S(t) - c 服从 lognormal 分布)可不可以?

Stay Tuned!

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-04-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 王的机器 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档