相关文章推荐
乖乖的韭菜  ·  Electron Microscopy ...·  9 月前    · 
乖乖的韭菜  ·  nodejs gzip ...·  9 月前    · 
乖乖的韭菜  ·  HBuilderX.vue文件 以及 ...·  10 月前    · 
乖乖的韭菜  ·  CSS3变形 ...·  10 月前    · 
乖乖的韭菜  ·  Uploading to Steam ...·  10 月前    · 
销魂的大白菜  ·  pycharm报错:ModuleNotFou ...·  4 分钟前    · 
神勇威武的长颈鹿  ·  python ...·  4 分钟前    · 
会开车的企鹅  ·  python ...·  4 分钟前    · 
挂过科的企鹅  ·  Java ...·  1小时前    · 

期权计算器

使用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 ( t1 - t0 ) . days / 252.0 def get_option_price_bs ( self ) : This function will calculate the option price under classic BSM formula d1 = ( np . log ( self . S0 / self . K ) + ( self . r + self . div + 0.5 * self . vol ** 2 ) * self . t ) / ( self . vol * np . sqrt ( self . t ) ) d2 = d1 - self . vol * np . sqrt ( self . t ) if self . OptionType == 'C' : self . bs_price = norm . cdf ( d1 ) * self . S0 - \ self . K * np . exp ( - self . r * self . t ) * norm . cdf ( d2 ) else : self . bs_price = self . K * \ np . exp ( - self . r * self . t ) * norm . cdf ( - d2 ) - norm . cdf ( - d1 ) * self . S0 return self . bs_price def get_option_price_MonteCarlo ( self , n = 10000000 ) : This function will calculate the option price under the Monte-Carlo simulation methods # array can save CPU time rather than for-loop z = np . random . randn ( 1 , n ) # type(z) is np.ndarray # calculation of ndarray returns a list of lists st = self . S0 * np . exp ( ( self . r - 0.5 * self . vol ** 2 ) * self . t + self . vol * np . sqrt ( self . t ) * z ) [ 0 ] if self . OptionType == 'C' : value = st - self . K else : value = self . K - st self . montecarlo_price = np . exp ( - self . r * self . t ) * \ np . mean ( [ max ( value , 0 ) for value in value ] ) return self . montecarlo_price def get_option_delta ( self ) : d1 = ( np . log ( self . S0 / self . K ) + ( self . r + 0.5 * self . vol ** 2 ) * self . t ) / ( self . vol * np . sqrt ( self . t ) ) if self . OptionType == 'C' : self . delta = norm . cdf ( d1 ) else : self . delta = - norm . cdf ( - d1 ) # 股票价格变化ds时,期权价格变化delta ds return self . delta def get_option_gamma ( self , ds = 0.00001 ) : pre_delta = self . get_option_delta ( ) S0 = self . S0 + ds K = self . K r = self . r t = self . t * 252 # annualize t vol = self . vol OptionType = self . OptionType post_option = Option ( S0 = S0 , K = K , r = r , t = t , vol = vol , OptionType = OptionType ) post_delta = post_option . get_option_delta ( ) self . gamma = ( post_delta - pre_delta ) / ds # 股票价格变化ds时,期权delta变化gamma ds return self . gamma def get_option_theta ( self , dt = 1.0 / 252 ) : pre_price = self . get_option_price_bs ( ) S0 = self . S0 K = self . K r = self . r t = ( self . t - dt ) * 252 # annualize t vol = self . vol OptionType = self . OptionType post_option = Option ( S0 = S0 , K = K , r = r , t = t , vol = vol , OptionType = OptionType ) post_price = post_option . get_option_price_bs ( ) # (post_price-pre_price)/dt的时间以年为单位,通常计算theta时以天为单位,因此,需要将得出的结果除以交易天数 # theta为其他变量不变时,在一天过后的交易组合的价值变化 self . theta = ( post_price - pre_price ) / dt / 252.0 # 每过一天,期权价格变化theta return self . theta def get_option_vega ( self , dvol = 0.00001 ) : pre_price = self . get_option_price_bs ( ) S0 = self . S0 K = self . K r = self . r t = self . t * 252 # annualize t vol = self . vol + dvol OptionType = self . OptionType post_option = Option ( S0 = S0 , K = K , r = r , t = t , vol = vol , OptionType = OptionType ) post_price = post_option . get_option_price_bs ( ) self . vega = ( post_price - pre_price ) / dvol # 隐含波动率增加1%(0.01)时,期权价格变化vega*0.01 return self . vega def get_option_rho ( self , dr = 0.00001 ) : pre_price = self . get_option_price_bs ( ) S0 = self . S0 K = self . K r = self . r + dr t = self . t * 252 # annualize t vol = self . vol OptionType = self . OptionType post_option = Option ( S0 = S0 , K = K , r = r , t = t , vol = vol , OptionType = OptionType ) post_price = post_option . get_option_price_bs ( ) self . rho = ( post_price - pre_price ) / dr # 利率增加1%(0.01)时,期权价格变化rho*0.01 return self . rho def get_option_price ( self ) : bs_price = self . get_option_price_bs ( ) mc_price = self . get_option_price_MonteCarlo ( ) print ( '----------Calculate the option price----------' ) print ( 'The Black-Scholes-Merton option price is: %.2f' % bs_price ) print ( 'The Monte-Carlo simulation option price is: %.2f' % mc_price ) def get_option_greeks ( self ) : delta = self . get_option_delta ( ) gamma = self . get_option_gamma ( ) theta = self . get_option_theta ( ) vega = self . get_option_vega ( ) rho = self . get_option_rho ( ) print ( '----------Calculate the option greeks----------' ) print ( 'Delta: %.4f' % delta ) print ( 'Gamma: %.4f' % gamma ) print ( 'Theta: %.4f' % theta ) print ( 'Vega: %.4f' % vega ) print ( 'Rho: %.4f' % rho ) def __get_implied_vol_Newton ( self ) : p = self . price self . vol = 0.5 n = 1 p_guess = 0.0 while abs ( p - p_guess ) > 0.0000001 and n < 100 : p_guess = self . get_option_price_bs ( ) self . vol = self . vol - ( p_guess - p ) / self . get_option_vega ( ) n += 1 print ( '----------Newton-Raphson method:' ) print ( 'Iteration: %s' % n ) print ( 'Accuracy: %.2e' % ( p - p_guess ) ) print ( 'The implied volatility is: %.2f%%' % ( self . vol * 100 ) ) return self . vol def __get_implied_vol_bisection ( self ) : p = self . price self . vol = 0.5 vol_low = 0.0 vol_high = 1.0 n = 1 p_guess = 0.0 while abs ( p - p_guess ) > 0.0000001 and n < 100 : p_guess = self . get_option_price_bs ( ) if p_guess > p : vol_high = self . vol else : vol_low = self . vol self . vol = ( vol_high + vol_low ) / 2 n += 1 print ( '----------Bisection method:' ) print ( 'Iteration: %s' % n ) print ( 'Accuracy: %.2e' % ( p - p_guess ) ) print ( 'The implied volatility is: %.2f%%' % ( self . vol * 100 ) ) return self . vol def get_option_implied_vol ( self ) : print ( '----------Calculate the option implied vol----------' ) newton_vol = self . __get_implied_vol_Newton ( ) bisection_vol = self . __get_implied_vol_bisection ( )

实例化结果

定价及希腊值

option1 = Option(t=0.3846*252, S0=49, K=50, OptionType='C', r=0.05, vol=0.2)
option1.get_option_price()
option1.get_option_greeks()
 

----------Calculate the option price----------
The Black-Scholes-Merton option price is: 2.40
The Monte-Carlo simulation option price is: 2.40
----------Calculate the option greeks----------
Delta: 0.5216
Gamma: 0.0655
Theta: -0.0171
Vega: 12.1052
Rho: 8.9067

option2 = Option(t=0.5*252, S0=42, K=40, OptionType='P', r=0.1, vol=0.2)
option2.get_option_price()
option2.get_option_greeks()
 

----------Calculate the option price----------
The Black-Scholes-Merton option price is: 0.81
The Monte-Carlo simulation option price is: 0.81
----------Calculate the option greeks----------
Delta: -0.2209
Gamma: 0.0500
Theta: -0.0030
Vega: 8.8135
Rho: -5.0424

隐含波动率

option3 = Option(t=0.5*252, S0=42, K=40, OptionType='C', r=0.1, price=4.759)
option3.get_option_implied_vol()
 

----------Calculate the option implied vol----------
----------Newton-Raphson method:
Iteration: 6
Accuracy: -6.59e-12
The implied volatility is: 20.00%
----------Bisection method:
Iteration: 25
Accuracy: 4.54e-08
The implied volatility is: 20.00%

隐含波动率的解析解

Options Greeks calculation with Python:
http://www.quantacademy.com/2014/09/options-greeks-calculation-with-python/

《Options, Futures, and Other Derivatives (10th edition)》by John C. Hull

更多精彩内容请访问我的博客,一起来康康吧!Options Calculator这是一个全能的期权计算器,涵盖 BS法,蒙特卡洛法,二叉数法,能够对看涨期权,看跌期权,欧式期权,美式期权,有股利期权,无股利期权进行定价,并附带GUI客户端。本计算器的特色在于支持非常全面的期权类型美观优雅简洁大方的界面采用了多线程的方式来优化用户体验可以直接提取使用其中的 Option 类来应用于你所需要的计算期权价... Options Calculator这是一个全能的期权计算器,涵盖 BS法,蒙特卡洛法,二叉数法,能够对看涨期权,看跌期权,欧式期权,美式期权,有股利期权,无股利期权进行定价,并附带GUI客户端。本计算器的特色在于支持非常全面的期权类型美观优雅简洁大方的界面可以直接提取使用其中的 Option 类来应用于你所需要的计算期权价格的地方。可以指定具体日期而不用再手动算时间间隔可以直接输入一年计无风险利... 1 编写一个期权类“万物皆对象”,既然我们需要针对一个欧式期权进行计算,不妨将期权编写成一个类,在将某个期权实例化为对象时,将其各种属性赋予这个对象。编写类时,要先给类起一个名字,比如Option.然后想象一下,一个欧式期权应该具有哪些属性,从而编写一个初始化函数。我们的欧式期权,应该具有以下几个属性。看涨或看跌(c or p)标的资产现价(S0)期权执行价格(K)期权到期时间(t)适用的无风险利...
 
推荐文章