Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/reporting-services/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 隐含波动率计算器是错误的_Python_Finance - Fatal编程技术网

Python 隐含波动率计算器是错误的

Python 隐含波动率计算器是错误的,python,finance,Python,Finance,我是一名计算机科学家,试图学习更多有关定量金融的知识。我有一个在Black-Scholes模型中计算欧洲看涨期权价值的程序,我正在尝试添加一种计算隐含波动率的方法 import math import numpy as np import pdb from scipy.stats import norm class BlackScholes(object): '''Class wrapper for methods.''' def __init__(self, s, k, t, r,

我是一名计算机科学家,试图学习更多有关定量金融的知识。我有一个在Black-Scholes模型中计算欧洲看涨期权价值的程序,我正在尝试添加一种计算隐含波动率的方法

import math
import numpy as np
import pdb
from scipy.stats import norm

class BlackScholes(object):
  '''Class wrapper for methods.'''

  def __init__(self, s, k, t, r, sigma):
    '''Initialize a model with the given parameters.
       @param s: initial stock price
       @param k: strike price
       @param t: time to maturity (in years)
       @param r: Constant, riskless short rate (1 equals 100%)
       @param sigma: Guess for volatility. (1 equals 100%)
    '''
    self.s = s
    self.k = k
    self.t = t
    self.r = r
    self.sigma = sigma
    self.d = self.factors()

  def euro_call(self):
    ''' Calculate the value of a European call option
        using Black-Scholes. No dividends.
        @return: The value for an option with the given parameters.'''
    return norm.cdf(self.d[0]) * self.s - (norm.cdf(self.d[1]) * self.k *
                                     np.exp(-self.r * self.t))

  def factors(self):
    '''
      Calculates the d1 and d2 factors used in a large
      number of Black Scholes equations.
    '''
    d1 = (1.0 / (self.sigma * np.sqrt(self.t)) * (math.log(self.s / self.k)
                    + (self.r + self.sigma ** 2 / 2) * self.t))
    d2 = (1.0 / (self.sigma * np.sqrt(self.t)) * (math.log(self.s / self.k)
                    + (self.r - self.sigma ** 2 / 2) * self.t))
    if math.isnan(d1):
      pdb.set_trace()
    assert(not math.isnan(d1))
    assert(not math.isnan(d2))
    return (d1, d2) 

  def imp_vol(self, C0):
    ''' Calculate the implied volatility of a call option,
        where sigma is interpretered as a best guess.
        Updates sigma as a side effect.
        @rtype: float
        @return: Implied volatility.'''
    for i in range(128):
      self.sigma -= (self.euro_call() - C0) / self.vega()
      assert(self.sigma != -float("inf"))
      assert(self.sigma != float("inf"))
      self.d = self.factors()
    print(C0,
      BlackScholes(self.s, self.k, self.t, self.r, self.sigma).euro_call())
    return self.sigma

  def vega(self):
    ''' Returns vega, which is the derivative of the
        option value with respect to the asset's volatility.
        It is the same for both calls and puts.
        @rtype: float
        @return: vega'''
    v = self.s * norm.pdf(self.d[0]) * np.sqrt(self.t)
    assert(not math.isnan(v))
    return v
以下是我目前拥有的两个测试用例:

print(BlackScholes(17.6639, 1.0, 1.0, .01, 2.0).imp_vol(16.85))
print(BlackScholes(17.6639, 1.0, .049, .01, 2.0).imp_vol(16.85))
最上面的一个打印出1.94,这相当接近由给出的195.21%的值。但是,底部的一个(如果您删除了assert语句)打印出“nan”和以下警告消息。对于assert语句,
self.vega()
在imp_vol方法中返回零,然后
assert(self.sigma!=-float(“inf”)


你所做的没有多大意义。你是在试图放弃隐含的大量金钱,短期选择权。此选项上的织女星将有效地为0,因此您得到的隐含卷数将毫无意义。我一点也不奇怪,浮点舍入给了你无限的体积。

如果你使用vega来估计隐含的波动率,你可能在做牛顿梯度搜索的一些变体,它不会在所有情况下收敛到一个解,我用R或VBA编程,所以只能提供一个解供你翻译,两段搜索法简单、稳健且总是收敛,从撰写期权定价模型全集的人那里可以看出,Espen Haugs算法用于二分搜索以找到隐含波动率

Newton-Raphson方法需要了解部分 期权定价公式对波动率的导数 (织女星)搜索隐含波动率时。有些选择 (特别是异国情调和美国的选择),维加并不为人所知- 利基利。二分法是一种更简单的估计方法 vega未知时的隐含波动率。二分法 需要两个初始波动率估计值(种子值):

  • 隐含波动率的“低”估计值al,对应于 期权价值,CL
  • 一个“高”波动率估计,啊,对应于一个期权 价值,CH 期权市场价格Cm介于CL和cH之间。bisec- 两个参数之间的线性插值给出了偏差估计 估计: 如果c(cr,+)cm,直到lcm-C(cri+i)i
    函数GBlackScholesImpVolBisection(CallPutFlag
    作为字符串,S作为双精度,
    X为双精度,T为双精度,r为双精度_
    b为双精度,cm为双精度)为变体
    暗V为双精度,高V为双精度,vi为双精度
    Dim cLow双倍,cHigh双倍,epsilon双倍
    双重的
    作为整数的Dim计数器
    vLow=0.005
    vhig=4
    ε=le-08
    cLow=GBlackScholes(CallPutFlag、S、X、T、r、b、vLow)
    cHigh=GBlackScholes(CallPutFlag、S、X、T、r、b、vHigh)
    计数器=0
    vi=vLow+(cm-cLow)*(vHigh-vLow)/(cHigh-cLow)
    而Abs(cm-GBlackScholes(callputsflag,S,X,T,r,b,vi))>epsilon
    计数器=计数器+1
    如果计数器=100,则
    GBlackScholesImpVolBisection
    退出功能
    如果结束
    如果GBlackScholes(CallPutFlag,S,X,T,r,b,vi)
    您使用的是哪一个python版本?我使用的是python 2.7.8。当我在该网站上输入时,我将17.6639四舍五入到17.66,添加剩余的小数使其完全一致。期权定价中的无限波动的想法没有任何实际意义,因此我99%相信我的输出是一个bug,但我对Black-Scholes方程的理解还不够透彻,无法调试它。那么,是不是应该归咎于浮点的怪异呢?
    so.py:51: RuntimeWarning: divide by zero encountered in double_scalars
      self.sigma -= (self.euro_call() - C0) / self.vega()
    so.py:37: RuntimeWarning: invalid value encountered in double_scalars
      + (self.r + self.sigma ** 2 / 2) * self.t))
    so.py:39: RuntimeWarning: invalid value encountered in double_scalars
      + (self.r - self.sigma ** 2 / 2) * self.t))
    
          Function  GBlackScholesImpVolBisection(CallPutFlag 
           As String, S As Double,
           X As Double, T As Double, r As Double, _
           b As Double, cm As Double) As Variant
           Dim vLow As Double, vHigh As Double, vi As Double
           Dim cLow As Double, cHigh As Double, epsilon As 
       Double
       Dim counter As Integer
       vLow = 0.005
       vHigh = 4
       epsilon = le-08
       cLow = GBlackScholes ( CallPutFlag , S, X, T, r, b, vLow)
       cHigh = GBlackScholes ( CallPutFlag , S, X, T, r, b, vHigh)
       counter = 0
       vi = vLow + (cm — cLow ) * (vHigh — vLow) / ( cHigh — cLow)
       While Abs(cm — GBlackScholes ( CallPutFlag , S, X, T, r, b, vi )) > epsilon
       counter = counter + 1
       If counter = 100 Then
       GBlackScholesImpVolBisection
       Exit Function
       End If
       If GBlackScholes ( CallPutFlag , S, X, T, r, b, vi ) < cm Then
       vLow = vi
       Else
       vHigh = vi
       End If
       cLow = GBlackScholes ( CallPutFlag , S, X, T, r, b, vLow)
       cHigh = GBlackScholes ( CallPutFlag , S, X, T, r, b, vHigh )
       vi = vLow + (cm — cLow ) * (vHigh — vLow) / ( cHigh — cLow)
       Wend
       GBlackScholesImpVolBisection = vi
       End Function```