期权计算器
使用Python复现了一个完整的期权计算器,包含期权定价,希腊值计算,数值方法计算隐含波动率。详细注释已给出。
Option price 分别使用BSM模型定价和Monte-Carlo模拟定价;Greeks使用数值方法计算,解析解在文中给出;implied volatility 分别使用牛顿-拉弗森迭代法和二分迭代法求数值解,并给出迭代次数和精度。
完整代码
使用jupyter notebook autopep8 插件调整至符合PEP8代码规范。
'''
This Module Contains Black-Scholes-Merton Calculations of Prices and Greeks for Options.
'''
import numpy as np
import pandas as pd
from scipy.stats import norm
import datetime
import matplotlib.pyplot as plt
class Option:
'''
This class will generate few BSM model calculations for an option.
'''
def __init__(self, set_date=datetime.date.today(), exp_date=datetime.date.today(), t=None, S0=1, K=1, OptionType='C', r=0.05, vol=0.3, div=0, price=np.nan):
self.OptionType = OptionType.upper()
self.K = float(K)
self.r = float(r)
self.vol = float(vol)
self.set_date = set_date
self.exp_date = exp_date
self.div = div
self.price = price
# when directly input the days to expire
if t:
self.t = t/252.0
# when use set_date and exp_date
else:
self.t = self.__calculate_t()
# case in expiration date
if self.t == 0:
self.t = 0.000001
# self.S0 = float(S0)*np.exp(self.r*self.t)
self.S0 = float(S0)
# calculate the days to expire under different types of date parameters
def __calculate_t(self):
# re-format set_date into datetime.date
# when the date parameter is string
if type(self.set_date) == str:
# when the delimeter is '/'
if '/' in self.set_date:
t0 = datetime.datetime.strptime(self.set_date, '%Y/%m/%d')
# when the delimeter is '-'
elif '-' in self.set_date:
t0 = datetime.datetime.strptime(self.set_date, '%Y-%m-%d')
# when the string has no delimeters
else:
t0 = datetime.datetime(int(self.set_date[0:4]), int(
self.set_date[4:6]), int(self.set_date[6:8]))
# when the date parameter is number
elif type(self.set_date) == int or type(self.set_date) == long or type(self.set_date) == float:
t0 = datetime.datetime(int(str(self.set_date)[0:4]), int(
str(self.set_date)[4:6]), int(str(self.set_date)[6:8]))
# when the date parameter is date
elif type(self.set_date) == datetime.date or type(self.set_date) == datetime.datetime:
if type(self.set_date) == datetime.date:
t0 = datetime.datetime(
self.set_date.year, self.set_date.month, self.set_date.day)
else:
t0 = self.set_date
else:
t0 = self.set_date
# re-format exp_date into datetime.date
if type(self.exp_date) == str:
if '/' in self.exp_date:
t1 = datetime.datetime.strptime(self.exp_date, '%Y/%m/%d')
elif '-' in self.exp_date:
t1 = datetime.datetime.strptime(self.exp_date, '%Y-%m-%d')
else:
t1 = datetime.datetime(int(self.exp_date[0:4]), int(
self.exp_date[4:6]), int(self.exp_date[6:8]))
elif type(self.exp_date) == int or type(self.exp_date) == long or type(self.exp_date) == float:
t1 = datetime.datetime(int(str(self.exp_date)[0:4]), int(
str(self.exp_date)[4:6]), int(str(self.exp_date)[6:8]))
elif type(self.exp_date) == datetime.date or type(self.exp_date) == datetime.datetime:
if type(self.exp_date) == datetime.date:
t1 = datetime.datetime(
self.exp_date.year, self.exp_date.month, self.exp_date.day)
else:
t1 = self.exp_date
else:
t1 = self.exp_date
# calculate the days to expire
return</