本文根據Black-Scholes選擇權定價公式及python計算理論價格,最後繪製在不同履約價下的理論價格。由於屬於筆記性質並非學術文章,故選擇權的定價細節不在本文討論,僅用python實作定價。
首先Call的理論價格為
其中C為call價格,St為現貨價格,K為履約價格,N(.)為標準常態的cdf,T及t分別為距到期日及目前時間點(常用單位為天),r為無風險利率,σ為標的資產的歷史股價報酬。當中可將距到期日及目前時間點的差距視為Δt,並且除上365或是250變成年為單位。由call的公式中,可知需要的變數有6個,分別為St, K, T, t, r, σ,不過也有人視為5個,St, K, Δt, r, σ。因此只要設定好參數,即可以根據公式並寫進python,則求出理論的call價格。
先是引入套件numpy
及norm
。接著是設定參數。接著依照公式先求d1及d2,最後則是計算出call理論價格。
#import packages
import numpy as np
from scipy.stats import norm
#parameter setting
T = 250 #maturity T
t = 50 #time t
delta_t = (T - t)/ 365 #annualized the time to maturity
S = 12500 #Strike price
K = 12400 #Exercise price
r = 0.01 #risk-free rate
sigma = 0.05 #volatility
#find the d1 and d2
d1 = (np.log(S/K) + (r + sigma**2/2)*(delta_t)) / (sigma*np.sqrt(delta_t))
d2 = d1 - sigma * np.sqrt(delta_t)
print('d1: ', d1)
print('d2: ', d2)
#call price
call = S * norm.cdf(d1) - K * np.exp(-r*(delta_t)) * norm.cdf(d2)
print('call: ', call)
而Put理論價格為
其中的參數與call相同。故手法與call相同。
#parameter setting
T = 250 #maturity T
t = 50 #time t
delta_t = (T - t)/ 365 #annualized the time to maturity
S = 12500 #Strike price
K = 12400 #Exercise price
r = 0.01 #risk-free rate
sigma = 0.05 #volatility
#find the d1 and d2
d1 = (np.log(S/K) + (r + sigma**2/2)*(delta_t)) / (sigma*np.sqrt(delta_t))
d2 = d1 - sigma* np.sqrt(delta_t)
print('d1: ', d1)
print('d2: ', d2)
#put price
put = K * np.exp(-r*(delta_t)) * norm.cdf(-d2) - S * norm.cdf(-d1)
print('put: ', put)
為了方便使用,可以將call及put計算的理論價格變成函示庫def
。
def option_price(S, K, sigma, T, t, r):
delta_t = (T-t)/365
d1 = (np.log(S/K) + (r + sigma**2/2)*(delta_t)) / (sigma*np.sqrt(delta_t)) #d1
d2 = d1 - sigma * np.sqrt(delta_t) #d2
call = S * norm.cdf(d1) - K * np.exp(-r*(delta_t)) * norm.cdf(d2) #call price
put = K * np.exp(-r*(delta_t)) * norm.cdf(-d2) - S * norm.cdf(-d1) #put price
return call, put
#parameter setting
T = 250 #maturity T
t = 50 #time t
S = 12500 #Strike price
K = 12400 #Exercise price
r = 0.01 #risk-free rate
sigma = 0.05 #volatility
call, put = option_price(S, K, sigma, T, t, r)
print('call: ', call)
print('put: ', put)
最後則是探討在不同履約價下的選擇權理論價格。由於需要不同的履約價,故根據初始的參數設定,建構一系列的履約價K_ls
,並用lambda
、map
、list
將不同履約價代入到option_price
中計算call及put的理論價格,並變成list型態,而此處使用array
是為了後續的方便使用。
#parameter setting
T = 250 #maturity T
t = 50 #time t
S = 12500 #Strike price
K = 12400 #Exercise price
r = 0.01 #risk-free rate
sigma = 0.05 #volatility
K_ls = np.arange(S-2000, S+2000)#strike price array
price_ls = np.array(list(map(lambda i: option_price(S, i, sigma, T, t, r), K_ls)))
print('K: ', K_ls)
print('Pirce: ', price_ls)
最後則是將理論價格在不同履約價的條件下繪製出來,先展示call。
import matplotlib.pyplot as plt
import matplotlib as mpl
mpl.rcParams['xtick.labelsize'] = 16
mpl.rcParams['ytick.labelsize'] = 16
x=K_ls
y=price_ls[:,:1].flatten(order='C')#convert array into one dimension
plt.plot(x, y, label='call')
plt.fill_between(x=x, y1=y, y2=0, color='C0', alpha=0.3)
plt.axvline(S, linestyle='--', color='grey') #strike price line
plt.axhline(0, linestyle='--', color='black') #0 line
plt.xlabel('Strike price (K)', fontsize=14)
plt.ylabel('Theoretical Price', fontsize=14)
plt.title('Call Option', fontsize=16)
plt.legend(fontsize=14)
# plt.savefig('/CallOption.png', bbox_inches='tight')#save fig
plt.show()
後是put。
x=K_ls
y=price_ls[:,1:].flatten(order='C')#convert array into one dimension
plt.plot(x, y, label='pall', color='C1')
plt.fill_between(x=x, y1=y, y2=0, color='C1', alpha=0.3)
plt.axvline(S, linestyle='--', color='grey') #strike price line
plt.axhline(0, linestyle='--', color='black') #0 line
plt.xlabel('Strike Price (K)', fontsize=14)
plt.ylabel('Theoretical Price', fontsize=14)
plt.title('Put Option', fontsize=16)
plt.legend(fontsize=14)
# plt.savefig('/PutOption.png', bbox_inches='tight')#save fig
plt.show()
因此可以得知,對於call來說,履約價越低則理論價格越高越有價值;對於put來說,履約價越大則理論價格越高則理論價格越小。
本文程式碼在https://github.com/MinKuanIsHere/OptionPricing/blob/main/BSmodel.ipynb