期权方法论 4.1: 隐波与波动率曲面(一)

论坛 期权论坛 期权     
OPPO   2019-9-4 21:47   10933   0
一、波动率曲面  波动率曲面,是由隐含波动率构成的
1、为什么要了解曲面  曲面是客观存在的,由买卖双方的供求导致。研究曲面的本质,就是在研究和利用T价表的供求关系。可以看作,买卖双方基于各自对标的资产的预期做的投票,它是个情绪化的产物,是种羊群效应。
  
2、术语与图解  整个T价表的隐含波动率,构成波动率曲面Implied Volatility Surface。同日期的隐含波动率,或同价格不同日期的隐含波动率,构成波动率微笑曲线Implied Volatility Smile或者波动率倾斜Implied Volatility Skew
   波动率微笑曲线与波动率倾斜图解
  
3、隐含波动率的变化  随着到期日的临近,虚值OTM期权,进入平值ATM的几率越小,但是一旦能进入ATM它的增值潜力越大,它的表现越来越趋近于一张彩票。
  对于OTM卖方来看,由于权利金Premium能赚的额度很少,他们宁可不卖也不会把“彩票”给卖便宜了,因为一旦进入ATM,他们承受的损失远远大于他们收到的权利金,自然要求更高的利益“补偿”
  对于OTM买方来看,损失很有限,增值潜力翻了几百几千倍,但是中奖率比彩票高多了,这“彩票”贵了几元,几十元,对于博彩的人来说,不是那么的“敏感”。
  因此随着到期日的临近,越是OTM的期权合约,隐含波动率越高。
  
4、波动率微笑曲线Implied Volatility Smile  价外OTM期权的波动率高于价内ATM的。那么高的程度如何描述呢?
  相对理想的情况是,离标的价格一样远的认购和认沽合约,他们的波动率水平大体相同,隐含波动率大体对称,就像一张嘴在微笑一样,我们因此称之为,波动率微笑曲线Implied Volatility Smile。这是一种比较理想的状态。
  所以需要再强调一遍,执行价离标的价格距离一样远的虚值认购和认沽期权,未必有一样的隐含波动率(有就是微笑曲线)
  
5、波动率倾斜Implied Volatility Skew  更多情况下,隐含波动率表现得明显倾斜于一边,故名波动率倾斜Implied Volatility Skew。这是因为认购与认沽两侧供求关系的不同造成的。
  通常来说,股票期权,会有更多购买者为了保护标的资产的突然下跌,因此认沽的波动率大于认购的波动率,OTM Put> ATM>OTM Call。我们称之为反向倾斜Reverse Skew, 或者叫向下倾斜Downside Skew
  商品期货期权,更多购买者为了保护标的价格暴涨,因此认购的波动率大于认沽的波动率,OTM Call> ATM>OTM Put。我们称之为正向倾斜Normal Skew, 或者叫向上倾斜Upside Skew
  
二、隐波与标的资产的关系1、隐波与标的波动率范围  隐波是一种年化的百分比率,统计学意义上,相当于标的资产的一个方差(68%的统计学概率)
  假如,IQT的股价为2.35,9月份合约的隐波平均在16%,9月份还要22天到期
  那么期权市场买卖9月份的隐波的人的整体投票认为,IQT的股价在9月份的波动范围为,围绕2.35做上下2.35*16%*sqrt(22/365)=-0.0923的波动,即人们一致认为9月份的股价波动范围有68%的可能性在2.2577到2.4423之间。
  
2、如何巧用技术指标  首先,我们知道了隐波是人们对于标的的预期而来,那么人们如何对标的产生各类预期的呢?行业调研,读研报,专家分析?当然不是,记住之前的话,曲面是种羊群效应,你要割羊群的韭菜,你只需要知道羊会怎么想就行了。在我国,羊群无非就是博方向,看K线图。各种群里的大师喊单,解释的玄乎其玄的原理,归根到底还是K线。这是羊群的认知,可以被我们当前所合理应用的。
  其次,技术指标体系已经发展得相当成熟,我们可以拿来主义。但我们要知道,我们拿它来用什么?所有的技术指标,本质都只是一种统计公式,既然是统计学公式,那么本质上是在一定条件下,有一定的可能性发生的描述性公式。羊群拿它来预测方向,满仓,加杠杆。我们拿它来监控羊群行为,通过期权的概率优势,来套利。通常来说,根据监控高波动率和低波动率情况的指标,可以做如下划分。
  
3、波动率的高低测量办法  既然提到了波动率高低,那么如何鉴定和测量呢?
  这就要引出两个重要概念:隐含波动率级别Implied Volatility Rank(简称IV Rank)和隐含波动率百分位数Implied Volatility Percentile(简称IV Percentile)。
  IV Rank比较IV Percentile公式更加简单, IV Percentile比IV Rank更加平滑。这俩者没有孰优孰劣,但是使用一定要一致。
  我们一方面使用期权波动率隐波的IV指标,再结合研究标的的技术指标来Double Check,帮助我们判断市场的T价各波动率水平和套利机会。
  
3.1 IV Rank  当前波动率占52周的波动率高低的百分比
  IV Rank = ((Current IV - 52-Week IV Low)/ (52-WeekIV High- 52-Week IV Low))*100%
  
3.2 IV Percentile  交易周期内(通常选252或者365天),低于当前波动率的天数占所有交易天数的百分比。
  IV Percentile = (# of Days Under Current IV/# of Trading Days) *100%
  
三、隐波的计算方法  有两种最基础的方法,牛顿-拉佛森方法Newton-Raphson method,和二分法Bisection Method。这两种方法的概念,网上都能查到,这里就直接网络截图,不赘述了。我们来讲讲如何应用到期权上和Python代码如何编写。
1、牛顿-拉弗森方法Newton-Raphsonmethod(代码见文章末尾,有两段)
  Newton-Raphson Method,迭代速度最快,但是有可能求不出解
  在这个情况下,我们等于是在不断迭代期权的sigma即波动率,使得它等到无法迭代(即前后值差异几乎为0时)时停止。这里面用于迭代的公式f(x)就是期权价值公式,df(x)即期权定价公式关于sigma的导数,那么脚趾头想想也知道,这不就是vega嘛。那么我们把之前的代码按照这个格式塞进去就行了。我们来算算看(迭代次数50次,精度小数点后五位)
  假如,IQT公司的股价为2.973,我们计算的合约为9月份(剩21天)的平值合约,即执行价为2950。当前无风险利率为4%,股利为0%,在T价表上,我们找到认购期权最新价为0.0543,认沽期权最新价为0.0400。我们快速得出:
  9月2950认购:0.1326475570945834   即隐波约 13.26%
  9月2950认沽:  0.18929809459574065  即隐波约 18.93%
  
2、二分法Bisection Method(代码见文章末尾,有两段)
  Bisection Method,速度最慢,但是肯定能求出解。不过可能需要重复步骤太多,超出计算机设定范围导致实际过程中无法求出解。
  在这个公式里,我们依葫芦画瓢的办法,当然是在两个给定的sigma区间内二分求解。波动率再高几乎不可能是200%,或者波动率等于0%, 那么我们就给定个0.0000000001到2的范围之间求解。F(x)公式跟上面一样,但是细心的人一定会发现,少了个Vega的helper function,自然,我们这里面不涉及求导,自然就不用担心有求不出导(分母过小趋近于0)的问题了
  还是上面Newton-RaphsonMethod用的例子,一模一样的参数输入,为了保护我们的计算机,依然是迭代次数50次,精度小数点后五位。我们得出如下结果。我们可以看出两种方法在最后几位小数略有差异。
  9月2950认购:  0.1326293954649353    即隐波约 13.26%
  9月2950认沽:  0.1893310555928345   即隐波约 18.93%
3、券商软件上的错误3.1 错误一:隐波计算错误  通常情况下,券商软件,为了照顾到所有人的计算机都能用,自然是寻求最快的办法(但不一定能求出解)。有得必有失,自然会造成很多显示错误。
  比如国内券商软件公司,常常会发现这类错误,隐波等于某个很小很小的常数例如图上隐波等于0.01%。如果你熟悉我上面的代码了,你会立马反应过来,这个数是代码里对于求解不出来的时候,设定的一个缺省值。
  一定要知道,这绝对绝对绝对不是这份合约便宜得一套糊涂,千万千万别犯傻!
3.2 错误二: vix计算错误  这种求解错误,经常发生在实值位置。由于这类错误很多,那么采用VIX方法来做波动率高低计算,自然也是错误多多了。网上可以搜到,国内所谓的VIX方法,是对合约的波动率们进行加权平均,经常把0.01%差异那么大的数字加权进去,无论这种加权再怎么完美,只要你的数学不是体育老师教的,你一定能知道这算出来的VIX指数有多么荒谬了吧
  
3.3 错误三:红利错误  因为50ETF分红过的合约已经不存在了,目前没有实图可以展示。不过等到下次分红后,感兴趣的可以试试看,策略组合里,用一份分红后的合约和一份没有分红的合约,或者两份分红的合约,组合个认购1权利:认购1义务,或者认沽1权利:认沽1义务,的价差组合。会发现软件显示,你的价差组合(盈亏有限的)在一个方向会无限涨,或者无限亏,跨的日期越多,越不符合常识。
  我认为主要原因是券商们使用的BlackScholes公式是最原始的不包含分红q的公式,所以导致涉及分红后的合约计算错误频出。我的隐含波动率代码的HelperFunction里特意把涉及分红的BlackScholes代码双手奉上,我也衷心希望这个错误软件商们能尽早修复。
  牛顿-拉弗森方法Newton-Raphsonmethod涉及的Python代码
import math
from scipy.integrate import quad

# 01-01 PDF normal distribution
def dN(x):
    return math.exp(-0.5*x**2)/math.sqrt(2*math.pi)

# 01-02 CDF normal distribution
def N(d):
    return quad(lambda x:dN(x),-20,d,limit=50)[0]

# 01-03 d1 function
def d1f(St,K,t,T,r,q,sigma):
    d1 = (math.log(St/K)+(r-q+0.5*sigma**2)*(T-t))/(sigma*math.sqrt(T-t))
    return d1

##### 02 BSM Model
# 02-01 BSM Call
def CallValue(St,K,t,T,r,q,sigma):
    St: float
    K: float
    t: float
    T: float
    r: float
    q: float
    sigma: float
    d1 = d1f(St,K,t,T,r,q,sigma)
    d2 = d1-sigma*math.sqrt(T-t)
    call_value = math.exp(-q*(T-t))*St*N(d1)-math.exp(-r*(T-t))*K*N(d2)
    return call_value

# 02-01 BSM Put
def PutValue(St,K,t,T,r,q,sigma):
    St: float
    K: float
    t: float
    T: float
    r: float
    q: float
    sigma: float
    d1 = d1f(St,K,t,T,r,q,sigma)
    d2 = d1-sigma*math.sqrt(T-t)
    put_value = -math.exp(-q*(T-t))*St*N(-d1)+math.exp(-r*(T-t))*K*N(-d2)
    return put_value

def Vega(St,K,t,T,r,q,sigma):
    St: float
    K: float
    t: float
    T: float
    r: float
    q: float
    sigma: float
    vega: float
    d1 = d1f(St,K,t,T,r,q,sigma)
    vega = math.exp(-q*(T-t))*St*dN(d1)*math.sqrt(T-t)
    return vega

def calloptionIV(CallOptionSpot,St,K,t,T,r,q):
    MAX_ITERATIONS = 50
    PRECISION = 1.0e-5
    sigma = 0.50
    for i in range(MAX_ITERATIONS):
        vega = Vega(St,K,t,T,r,q,sigma)
        bscall= CallValue(St,K,t,T,r,q,sigma)
        diff = CallOptionSpot-bscall
        if (abs(diff) < PRECISION):
            return sigma
        if(vega==0):
            sigma = sigma
        else: sigma = sigma + diff/vega
    return sigma

def putoptionIV(PutOptionSpot,St,K,t,T,r,q):
    MAX_ITERATIONS = 50
    PRECISION = 1.0e-5
    sigma = 0.50
    for i in range(MAX_ITERATIONS):
        vega = Vega(St,K,t,T,r,q,sigma)
        bsput= PutValue(St,K,t,T,r,q,sigma)
        diff = PutOptionSpot - bsput

        if (abs(diff) < PRECISION):
            return sigma
        if(vega==0):
            sigma = sigma
        else: sigma = sigma + diff/vega
    return sigma


St = 2.973  # IQT公司的股价
K = 2.950  # 执行价
t = 0
T = 21/365  # 合约剩下21天
r = 0.04  # 无风险利率为4%
q = 0  # 股利为0%
CallOptionSpot = 0.0543  # 认购期权价格
PutOptionSpot = 0.0400  # 认沽期权价格
ImpliedVolatilityCall2950 = calloptionIV(CallOptionSpot, St, K, t, T, r, q)
ImpliedVolatilityPut2950 = putoptionIV(PutOptionSpot, St, K, t, T, r, q)
print("9月2950认购:", ImpliedVolatilityCall2950, " 9月2950认沽:", ImpliedVolatilityPut2950)  

  二分法Bisection Method涉及的Python代码
import math
from scipy.integrate import quad

# 01-01 PDF normal distribution
def dN(x):
    return math.exp(-0.5*x**2)/math.sqrt(2*math.pi)

# 01-02 CDF normal distribution
def N(d):
    return quad(lambda x:dN(x),-20,d,limit=50)[0]

# 01-03 d1 function
def d1f(St,K,t,T,r,q,sigma):
    d1 = (math.log(St/K)+(r-q+0.5*sigma**2)*(T-t))/(sigma*math.sqrt(T-t))
    return d1

##### 02 BSM Model
# 02-01 BSM Call
def CallValue(St,K,t,T,r,q,sigma):
    St: float
    K: float
    t: float
    T: float
    r: float
    q: float
    sigma: float
    d1 = d1f(St,K,t,T,r,q,sigma)
    d2 = d1-sigma*math.sqrt(T-t)
    call_value = math.exp(-q*(T-t))*St*N(d1)-math.exp(-r*(T-t))*K*N(d2)
    return call_value

# 02-01 BSM Put
def PutValue(St,K,t,T,r,q,sigma):
    St: float
    K: float
    t: float
    T: float
    r: float
    q: float
    sigma: float
    d1 = d1f(St,K,t,T,r,q,sigma)
    d2 = d1-sigma*math.sqrt(T-t)
    put_value = -math.exp(-q*(T-t))*St*N(-d1)+math.exp(-r*(T-t))*K*N(-d2)
    return put_value


def ivbiseccall(C0, St, K, t, T, r, q):
    MAX_ITERATIONS = 50
    PRECISION = 1.0e-5
    sigmah = 2
    sigmal = 1.0e-9
    for i in range(MAX_ITERATIONS):
        sigma = 0.5*(sigmal+sigmah)
        call = CallValue(St, K, t, T, r, q, sigma)
        if abs(call - C0) < PRECISION:
            return sigma
        elif call-C0 < 0:
            sigmal = sigma
        else:
            sigmah = sigma


def ivbisecput(P0, St, K, t, T, r, q):
    MAX_ITERATIONS = 50
    PRECISION = 1.0e-5
    sigmah = 2
    sigmal = 1.0e-9
    for i in range(MAX_ITERATIONS):
        sigma = 0.5*(sigmal+sigmah)
        put = PutValue(St, K, t, T, r, q, sigma)
        if abs(put - P0) < PRECISION:
            return sigma
        elif put-P0 < 0:
            sigmal = sigma
        else:
            sigmah = sigma


St = 2.973  # IQT公司的股价
K = 2.950  # 执行价
t = 0
T = 21/365  # 合约剩下21天
r = 0.04  # 无风险利率为4%
q = 0  # 股利为0%
CallOptionSpot = 0.0543  # 认购期权价格
PutOptionSpot = 0.0400  # 认沽期权价格
ImpliedVolatilityCall2950 = ivbiseccall(CallOptionSpot, St, K, t, T, r, q)
ImpliedVolatilityPut2950 = ivbisecput(PutOptionSpot, St, K, t, T, r, q)
print("9月2950认购:", ImpliedVolatilityCall2950, " 9月2950认沽:", ImpliedVolatilityPut2950)  

  

  


分享到 :
1 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:1281
帖子:313
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP