Table of Contents
1997年諾貝爾經濟學獎,在眾多入圍者中,Robert Merton 與 Myron Scholes 憑藉著 Black-Scholes options pricing formula 喜提金盃。Black-Scholes 模型也憑著其優秀的數學性質、簡易且易用的特性,至今仍是金融機構或投資人愛用的選擇權定價模型。今天我們就是要針對該模型進行程式化,並且介紹與程式化其衍生的 Greeks。
本文使用 Window 作業系統以及 Jupyter Notebook 作為編輯器。
# 載入所需套件
import math
import tejapi
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import norm
plt.style.use('bmh')
plt.rcParams['font.sans-serif']=['Microsoft YaHei']
# 登入TEJ API
api_key = 'YOUR_KEY'
tejapi.ApiConfig.api_key = api_key
tejapi.ApiConfig.ignoretz = True
公司交易面資料庫: 未調整股價(日),資料代碼為(TWN/APRCD)。
衍生性金融商品資料庫: 選擇權日交易狀況,資料代碼為(TWN/AOPTION)。
使用台灣加權股價指數(Y9999)未調整收盤價,時間區間為2021/03/16到2023/04/10。並且載入台灣加權指數買權(TXO202304C15500),該選擇權為歐式買權、開始交易日為3/16,到期日為4/19,履約價格為15500。
gte, lte = '2021-03-16', '2023-04-10'
# 標的物價格
stocks = tejapi.get('TWN/APRCD',
paginate = True,
coid = 'Y9999',
mdate = {'gte':gte, 'lte':lte},
chinese_column_name = True,
opts = {
'columns':[ 'mdate','close_d']
}
)
# 選擇權價格
options = tejapi.get(
'TWN/AOPTION',
paginate = True,
coid = 'TXO202304C15500',
mdate = {'gte':gte, 'lte':lte},
chinese_column_name = True,
opts = {
'columns':['mdate', 'coid','settle', 'kk', 'theoremp', 'acls', 'ex_price', 'td1y', 'avolt', 'rtime']
}
)
# 重設日期為index
stocks = stocks.set_index('年月日')
options = options.set_index('日期')
計算大盤之日報酬並且計算移動報酬波動度,以252天也就是一年為窗格迭代下去。
stocks['日報酬'] = np.log(stocks['收盤價(元)']) - np.log(stocks['收盤價(元)'].shift(1))
stocks['移動報酬波動度'] = stocks['日報酬'].rolling(252).std()
所得標的物價格表格如下:
接著進行 Black Scholes formula 程式化,我們先看一下Black Scholes formula 長甚麼樣子。
其中:
● C(St,t), P(St,t) : 表示第t日的買、賣權理論價格。
● St, K : 表示第t日標的物價格與履約價格。
● T, t : 表示選擇權時間長度與第t天。
● sigma : 表示歷史報酬波動度,這裡採過去252日的報酬計算波動度。
● r : 表示無風險利率。
● N() : 標準常態分配的累積機率密度函數。
若觀察上述式子可以發現,影響買賣權理論價格的因素不外乎這五個: 標的物價格、履約價格、剩餘到期天數(T-t)、報酬波動度與無風險利率。除了履約價格外,其他因素都會隨著時間推移而產生變化,而財金學家為了探討這四個因素與買賣權價格間的連動,發明了 Greeks 來量化四個因素與價格間的關係。分別為 delta、gamma、vega、theta 與 rho。
而這五個 greeks 就是讓選擇權價格分別對標的物價格、波動度、剩餘到期時間與無風險利率做微分,而gamma是選擇權價格對標的物價格作兩次微分。有賴於先人的努力,每個 greeks 都有解析解,讓我們不用處理討厭的偏微分方程式😆。以下公式,從上到下就是買權delta →賣權delta →買、賣權gamma →買、賣權vega →買權theta →賣權theta →買權rho →賣權rho的解析解。
廢話不多說,直接上code 😎。
class BS_formula:
def __init__(self, s0, k, r, sigma, T):
self.s0 = s0 # 標的物價格
self.k = k # 履約價格
self.r = r # 無風險利率
self.sigma = sigma # 歷史波動度
self.T = T # 剩餘到期時間
self.d1 = (np.log(s0/k)+(r+sigma**2/2)*T) / (sigma * np.sqrt(T))
self.d2 = ((np.log(s0/k)+(r+sigma**2/2)*T) / (sigma * np.sqrt(T))) - sigma*np.sqrt(T)
def BS_price(self): # 計算理論價格
c = self.s0*norm.cdf(self.d1) - self.k*np.exp(-self.r*self.T)*norm.cdf(self.d2)
p = self.k*np.exp(-self.r*self.T)*norm.cdf(-self.d2) - self.s0*norm.cdf(-self.d1)
return c,p
def BS_delta(self): # 計算 delta
return norm.cdf(self.d1), norm.cdf(self.d1)-1
def BS_gamma(self): # 計算 gamma
return norm.pdf(self.d1)/(self.s0*self.sigma*np.sqrt(self.T)), norm.pdf(self.d1)/(self.s0*self.sigma*np.sqrt(self.T))
def BS_vega(self): # 計算 vega
return self.s0*np.sqrt(self.T)*norm.pdf(self.d1), self.s0*np.sqrt(self.T)*norm.pdf(self.d1)
def BS_theta(self): # 計算 theta
c_theta = -self.s0*norm.pdf(self.d1)*self.sigma / (2*np.sqrt(self.T)) - self.r*self.k*np.exp(-self.r*self.T)*norm.cdf(self.d2)
p_theta = -self.s0*norm.pdf(self.d1)*self.sigma / (2*np.sqrt(self.T)) + self.r*self.k*np.exp(-self.r*self.T)*norm.cdf(-self.d2)
return c_theta, p_theta
def BS_rho(self): # 計算 rho
return self.k*self.T*np.exp(-self.r*self.T)*norm.cdf(self.d2), -self.k*self.T*np.exp(-self.r*self.T)*norm.cdf(-self.d2)
接著我們用上述公式,在給定其他條件下,以視覺化方式觀察標的物價格對買賣權價格之影響。可以發現買權與賣權價格大致呈現對稱,買權價格與標的物價呈現正向變動,而賣權價格與標的物價呈現反向變動。除此之外,我們可以發現持有買權之下,具有風險有限、增值無限的特性,因為當深價外時,選擇權價值至多減損至0,然而深價內時報酬可趨近於無限。而持有賣權雖風險有限,但受限於標的物價格至多減損到0,故報酬無法達成無限。
s0 = np.linspace(200,800)
k = 500
r = 0.00
sigma = 0.2
T = 252/252
mybs = BS_formula(s0, k, r, sigma, T)
c, p = mybs.BS_price()
fig = plt.figure(figsize = (12,8))
plt.plot(s0, c, label = '買權')
plt.plot(s0, p, label = '賣權')
plt.axvline(x = 500, color = 'black', linestyle = '--')
plt.xlabel('標的物價格', fontsize = 15)
plt.ylabel('選擇權價格', fontsize = 15)
plt.title('選擇權價格 VS. 標的物價格', fontsize = 20)
plt.legend(fontsize = 14)
plt.savefig('black scholes put call price.png')
plt.show()
接著是看看畫出給定其他條件之下,不同履約價格與Delta之間的關係圖。delta在財務上的意義為每當標的物價格增加一單位,選擇權價格的增減量。可以發現在深價外時,買賣權的delta都趨近於0;深價內時,買權趨近於1、賣權趨近於-1。代表在深價外時,小幅的標的物價格變動對於選擇權價格是沒啥影響;在深價內時,小幅的標的物價格變動則會造成選擇權價格有較大的波動且波動幅度與標的物波動幅度相當。
s0 = np.linspace(200,800)
k = 500
r = 0.00
sigma = 0.2
T = 252/252
mybs = BS_formula(s0, k, r, sigma, T)
c, p = mybs.BS_delta()
fig = plt.figure(figsize = (12,8))
plt.plot(s0, c, label = '買權')
plt.plot(s0, p, label = '賣權')
plt.axvline(x = 500, color = 'black', linestyle = '--')
plt.axhline(y = 0, color = 'black', linestyle = '--')
plt.xlabel('標的物價格', fontsize = 15)
plt.ylabel('Delta值', fontsize = 15)
plt.title('Delta值 VS. 標的物價格', fontsize = 20)
plt.legend(fontsize = 14)
plt.savefig('black scholes put call delta.png')
plt.show()
gamma是標的物價格對選擇權價格的二次微分,可以理解為delta曲線的斜率,也就是在不同標的物價格之下,delta的增長速度。在給定其他條件下,可以視覺化 gamma 與標的物價格之關係。可以發現賣買權的gamma是一樣的,且在約價平時,gamma最大,表示若從深價外走到深價內時,delta的增長幅度會是遞增然後遞減。程式碼請見文末。
我們也可以觀察價內、平與外的選擇權在不同到期日之下,gamma 的變化。可以發現在價平且快到期時,gamma值竄升得不可思議。這就是鼎鼎大名的 gamma risk,也就是說快到期時,價平選擇權的價格波動往往很大,許多風險趨避較深的投資人往往在快到期時,就會將持有選擇權部位平倉。但也是有些人會反向操作,在快到期時買入,以較大的 gamma 拚搏較大的風險溢酬。
s0, s1, s2 = 400, 500, 600
k = 500
r = 0.00
sigma = 0.2
T = np.linspace(1, 0.01)
mybs0 = BS_formula(s0, k, r, sigma, T)
c0, p0 = mybs0.BS_gamma()
mybs1 = BS_formula(s1, k, r, sigma, T)
c1, p1 = mybs1.BS_gamma()
mybs2 = BS_formula(s2, k, r, sigma, T)
c2, p2 = mybs2.BS_gamma()
fig = plt.figure(figsize = (12,8))
plt.plot(T, c0, label = '買權(價外)')
plt.plot(T, c1, label = '買權(價平)')
plt.plot(T, c2, label = '買權(價內)')
plt.xlabel('剩餘時間', fontsize = 15)
plt.ylabel('Gamma值', fontsize = 15)
plt.title('Gamma值 VS. 剩餘時間', fontsize = 20)
plt.legend(fontsize = 14)
plt.axis([1.005, -0, -0.005, .045])
plt.savefig('black scholes put call gamma2.png')
plt.show()
與 Gamma 相似,買賣權的 vega 基本上是相同的。vega 是當波動度增加一單位時,選擇權價格的變動幅度。從下圖可以發現當價平附近時,vega值達到最大,表示在價平時,選擇權價格最容易受到波動度影響。程式碼請見文末。
theta 為每單位時間增加,選擇權價值變化的幅度。我們可以繪製一張在不同標的物價格且其他條件固定下,Theta值的變化圖。可以發現在深價內或價外時,Theta在快靠近到期日時,都會趨近於0;反之,價平卻有一個極大的向下幅度。可以注意到 theta 一直都為負值,是因為隨著時間移動,選擇權的時間價值會逐漸衰減。程式碼見文末。
最後我們將每單位無風險利率移動,造成選擇權價格移動的幅度,稱之為Rho。我們可以將 Rho 與標的物價格繪圖,可以發現隨著標的物價格上升,Rho值會越來越大。程式碼見文末。
接著我們使用台指買權作為舉例,計算出在履約價格為15500元,到期日為四月之下,4/10 的買權理論價格,並且比較實際價格的差異。
r = 0.012
s0 = stocks.loc['2023-04-10']['收盤價(元)']
k = 15500
sigma = stocks.loc['2023-04-10']['移動報酬波動度']*np.sqrt(252)
T = 6/252
mybs = BS_formula(s0, k, r, sigma, T)
c, p = mybs.BS_price()
c_delta, p_delta = mybs.BS_delta()
c_gamma, p_gamma = mybs.BS_gamma()
c_vega, p_vega = mybs.BS_vega()
c_theta, p_theta = mybs.BS_theta()
c_rho, p_rho = mybs.BS_rho()
print('==2023-04-10履約價為525的台積電買權==')
print('當前標的物價格為 %.3f, 年化波動度為 %.3f, 剩餘期間為 %.3f'%(s0, sigma, T*252))
print('買權理論價格: %.4f, 賣權理論價格: %.4f' %(c,p))
print('買權delta: %.4f, 賣權delta: %.4f' %(c_delta,p_delta))
print('買權gamma: %.4f, 賣權gamma: %.4f' %(c_gamma,p_gamma))
print('買權vega: %.4f, 賣權vega: %.4f' %(c_vega,p_vega))
print('買權theta: %.4f, 賣權theta: %.4f' %(c_theta,p_theta))
print('買權rho: %.4f, 賣權rho: %.4f' %(c_rho,p_rho))
options.loc['2023-04-10'] # 實際買權價格
比較我們算出的理論價格與結算價格,可以發現有不小的差距(435.54 – 385),表示目前買權可能是低估的。除此之外,TEJ API 在衍生性金融商品資料庫中,也有提供理論價格的服務。TEJ API 所算的理論價格與我們的有些許的差距(440.36 v.s. 435.54),有可能是因為計算歷史波動度的方法不同或是採用不同的無風險利率標準。
溫馨提醒,本次介紹與標的僅供參考,不代表任何商品或投資上的建議。之後也會介紹使用TEJ資料庫來建構各式選擇權模型,所以歡迎對選擇權交易有興趣的讀者,選購TEJ E-Shop的相關方案,用高品質的資料庫,建構出適合自己的訂價模型。
電子報訂閱