【发布时间】:2015-05-20 21:37:14
【问题描述】:
我是一名计算机科学家,试图更多地了解量化金融。我有一个用于计算 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,这与http://www.option-price.com/implied-volatility.php 给出的 195.21% 的值相当接近。然而,底部的(如果您删除断言语句)会打印出“nan”和以下警告消息。使用 assert 语句,self.vega() 在 imp_vol 方法中返回零,然后是 assert(self.sigma != -float("inf"))。
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))
【问题讨论】:
-
你用的是哪个python版本?
-
我使用的是 Python 2.7.8。
-
我在该网站上输入时将 17.6639 舍入到 17.66,加上剩余的小数使其完全一致。
-
期权定价中无限波动的想法没有任何实际意义,所以我有 99% 的把握我的输出是一个错误,但我对 Black-Scholes 方程的理解不够好调试它。
-
那么,怪罪浮点怪异?