本文目錄
如果你正在學習python 選擇權相關的量化分析,一定會遇到一個共同的痛點:選擇權的理論價格到底怎麼算出來的?為什麼同一個標的、同一個履約價,波動率一改變,價格就天差地遠?這篇文章會帶你用 Python 從零實作 Black-Scholes 定價模型,計算選擇權的理論價格與 Greeks(Delta、Gamma、Theta、Vega),並示範隱含波動率的數值求解方法。文中所有數字都是假設範例,由程式碼實際計算得出,方便你複製貼上直接驗證。
為什麼要用 Python 做選擇權定價?Black-Scholes 模型原理拆解
Black-Scholes(簡稱 BS)模型是選擇權定價 Python 實作中最經典的入門模型,由 Fischer Black 與 Myron Scholes 在 1973 年提出。它假設標的資產價格服從幾何布朗運動,並在「無套利」與「連續避險」的前提下,推導出歐式選擇權的封閉解公式。
BS 模型需要五個輸入變數:
| 變數 | 說明 |
|---|---|
| S(標的價格) | 目前標的資產的市價 |
| K(履約價) | 選擇權的執行價格 |
| T(到期時間) | 以「年」為單位的剩餘時間 |
| r(無風險利率) | 通常用公債殖利率近似 |
| σ(波動率) | 標的資產報酬率的年化標準差 |
公式本身用到標準常態分配的累積分配函數(CDF),這也是為什麼 Python 很適合做這件事——scipy.stats.norm.cdf 已經幫你寫好了,不用自己手刻數值積分。
值得注意的是,BS 模型是針對「歐式選擇權」設計的,台指選擇權(TXO)在規格上屬於歐式,理論上可以用 BS 模型估算理論價,但實務交易時的合約規格(每點價值、保證金、交易時間、結算方式)請一律以臺灣期貨交易所官網最新公告為準,本文不提供任何具體數值,避免資訊過時誤導讀者。
實作選擇權定價 Python:Black-Scholes 公式完整程式碼
以下是用 Python 實作 Black-Scholes 定價公式的完整範例,所有輸入數值都是假設範例,你可以自行替換成想測試的參數:
import numpy as np
from scipy.stats import norm
def black_scholes_price(S, K, T, r, sigma, option_type="call"):
"""
S: 標的價格(假設範例)
K: 履約價(假設範例)
T: 到期時間(年),假設範例
r: 無風險利率(假設範例)
sigma: 年化波動率(假設範例)
option_type: "call" 或 "put"
"""
d1 = (np.log(S / K) + (r + 0.5 * sigma ** 2) * T) / (sigma * np.sqrt(T))
d2 = d1 - sigma * np.sqrt(T)
if option_type == "call":
price = S * norm.cdf(d1) - K * np.exp(-r * T) * norm.cdf(d2)
elif option_type == "put":
price = K * np.exp(-r * T) * norm.cdf(-d2) - S * norm.cdf(-d1)
else:
raise ValueError("option_type 必須是 'call' 或 'put'")
return price
# 假設範例:標的價格 100、履約價 100、剩餘 0.5 年、無風險利率 2%、波動率 20%
S, K, T, r, sigma = 100, 100, 0.5, 0.02, 0.20
call_price = black_scholes_price(S, K, T, r, sigma, "call")
put_price = black_scholes_price(S, K, T, r, sigma, "put")
print(f"假設範例 Call 理論價格: {call_price:.4f}")
print(f"假設範例 Put 理論價格: {put_price:.4f}")
這段程式碼的重點在於 d1、d2 的計算,以及用 norm.cdf 查表。只要輸入數值正確,就能快速得到理論價格,這也是許多程式交易系統計算「理論價 vs. 市價」價差的基礎邏輯。
選擇權 Greeks 計算:Delta、Gamma、Theta、Vega 一次搞懂
學會選擇權 Greeks 計算,才能真正理解部位的風險暴露。以下用同一組假設範例參數,示範四個最常用 Greeks 的計算方式:
import numpy as np
from scipy.stats import norm
def black_scholes_greeks(S, K, T, r, sigma, option_type="call"):
d1 = (np.log(S / K) + (r + 0.5 * sigma ** 2) * T) / (sigma * np.sqrt(T))
d2 = d1 - sigma * np.sqrt(T)
# Gamma 與 Vega 對 call/put 是相同的
gamma = norm.pdf(d1) / (S * sigma * np.sqrt(T))
vega = S * norm.pdf(d1) * np.sqrt(T) / 100 # 每 1% 波動率變動的影響
if option_type == "call":
delta = norm.cdf(d1)
theta = (
-S * norm.pdf(d1) * sigma / (2 * np.sqrt(T))
- r * K * np.exp(-r * T) * norm.cdf(d2)
) / 365 # 轉換成每日 theta
elif option_type == "put":
delta = norm.cdf(d1) - 1
theta = (
-S * norm.pdf(d1) * sigma / (2 * np.sqrt(T))
+ r * K * np.exp(-r * T) * norm.cdf(-d2)
) / 365
else:
raise ValueError("option_type 必須是 'call' 或 'put'")
return {"delta": delta, "gamma": gamma, "theta": theta, "vega": vega}
# 承上假設範例參數
S, K, T, r, sigma = 100, 100, 0.5, 0.02, 0.20
greeks_call = black_scholes_greeks(S, K, T, r, sigma, "call")
for name, value in greeks_call.items():
print(f"假設範例 Call {name}: {value:.6f}")
簡單說明這四個 Greeks 的意義:
- Delta:標的價格變動 1 單位,選擇權價格大約變動多少,也常被理解為「避險比率」。
- Gamma:Delta 對標的價格變動的敏感度,Gamma 越大,部位的方向性風險變化越快。
- Theta:時間流逝對選擇權價值的侵蝕,通常以「每日」為單位呈現。
- Vega:波動率每變動 1% 對選擇權價格的影響。
把這些函式封裝好之後,你可以把它接到即時報價資料上,動態追蹤整體部位的 Greeks 加總,這是許多台指選擇權程式交易系統監控風險的基本做法。
隱含波動率數值求解 + 到期損益圖繪製
市場上看到的選擇權報價是「市價」,而 BS 公式是用波動率反推價格。如果我們想從市價反推「市場認為的波動率」(隱含波動率),就需要用數值方法求解,因為 BS 公式無法直接解出 σ 的封閉解。這裡用 scipy.optimize.brentq 示範:
import numpy as np
from scipy.stats import norm
from scipy.optimize import brentq
def bs_price_for_iv(sigma, S, K, T, r, market_price, option_type="call"):
d1 = (np.log(S / K) + (r + 0.5 * sigma ** 2) * T) / (sigma * np.sqrt(T))
d2 = d1 - sigma * np.sqrt(T)
if option_type == "call":
price = S * norm.cdf(d1) - K * np.exp(-r * T) * norm.cdf(d2)
else:
price = K * np.exp(-r * T) * norm.cdf(-d2) - S * norm.cdf(-d1)
return price - market_price
# 假設範例:市場上這張 call 的報價是 6.5
S, K, T, r, market_price = 100, 100, 0.5, 0.02, 6.5
implied_vol = brentq(
bs_price_for_iv, 0.001, 3.0,
args=(S, K, T, r, market_price, "call")
)
print(f"假設範例隱含波動率: {implied_vol:.4%}")
接著示範到期損益圖,這是驗證策略邏輯最直觀的方式:
import numpy as np
import matplotlib.pyplot as plt
K = 100 # 假設範例履約價
premium = 6.5 # 假設範例權利金
spot_range = np.linspace(70, 130, 200)
payoff_call_buy = np.maximum(spot_range - K, 0) - premium
plt.figure(figsize=(8, 5))
plt.plot(spot_range, payoff_call_buy, label="買進 Call 到期損益(假設範例)")
plt.axhline(0, color="black", linewidth=0.8)
plt.xlabel("到期標的價格(假設範例)")
plt.ylabel("損益")
plt.legend()
plt.title("選擇權到期損益圖(假設範例參數)")
plt.show()
這張圖能幫助你視覺化不同策略組合(例如買權、賣權、價差組合)在到期時的損益曲線,是回測前確認邏輯正確性的重要步驟。
避雷防坑指南:Python 選擇權程式交易常見錯誤
寫程式算選擇權理論價格看似簡單,但實務上有幾個地雷特別容易踩到:
1. 未來函數(Look-ahead Bias)
在回測歷史資料時,若誤用「當天收盤後才會知道」的波動率或隱含波動率去反推當天的理論價,就會產生未來函數,導致回測結果嚴重失真。成因通常是資料時間戳沒對齊,或是用整段歷史資料計算的「已實現波動率」去代入當天的定價模型。防範建議:所有輸入 BS 模型的參數,都必須是「當下時間點已知」的資料,並在程式中明確標註資料的時間戳,避免跨期混用。
2. 忽略交易成本與滑價
很多人在計算理論價格與 Greeks 時,只看模型算出來的數字,卻忘了實際下單會有手續費、交易稅,以及買賣價差(spread)造成的滑價。這些成本在短天期、低波動的選擇權上占比特別高,容易把看似合理的價差策略侵蝕到無利可圖。防範建議:在任何策略評估流程中,固定把預估的交易成本當作一個變數扣除,而不是事後才補算。
3. 過度最佳化(Overfitting)
在用歷史資料校準波動率參數或尋找「最佳」履約價、到期日組合時,如果反覆調整參數直到歷史表現好看為止,很容易得到一個只對過去資料有效、對未來毫無預測力的模型。成因是參數自由度太高、驗證資料與訓練資料沒有確實切割。防範建議:務必保留「樣本外」資料做驗證,並對參數數量保持警覺,越簡單、邏輯越直觀的模型通常越穩健。
4. 誤用歐式模型套用到有提前履約特性的商品
BS 模型假設是歐式選擇權,如果拿去直接套用在允許提前履約的美式選擇權商品上,理論價格會產生系統性偏差。防範建議:先確認商品規格屬於歐式或美式,若為美式,需改用二項樹模型或其他適用方法。
工具與方法比較:手動建模 vs 現成套件 vs 圖表平台
學習 Python 選擇權定價時,常見的做法大致分三種,各有適合的使用情境:
| 方法 | 優點 | 限制 | 適合對象 |
|---|---|---|---|
| 手動用 numpy/scipy 寫 BS 公式 | 完全掌握計算邏輯,方便客製化 Greeks 與延伸策略 | 需要自行處理資料清洗、商品規格差異 | 想深入理解原理的學習者 |
| 現成選擇權定價函式庫 | 開發速度快,減少重複造輪子 | 彈性較低,客製化需研究原始碼 | 想快速驗證想法的開發者 |
| 圖表與報價平台(如 TradingView) | 即時報價、技術指標、繪圖介面直觀,方便交叉驗證理論價與市場價 | 不提供完整的 Python 程式化定價引擎 | 需要同時看盤與做策略構思的使用者 |
如果你在學習選擇權定價 Python 的過程中,需要一個方便查看即時報價、畫圖驗證進出場邏輯的平台,可以搭配 TradingView 一起使用,把模型算出來的理論價,拿去跟圖表上的市場報價互相比對,會更有感覺。
FAQ 常見問題
Q1:Python 選擇權定價一定要用 Black-Scholes 嗎?
不一定。BS 模型只適用於歐式選擇權,且假設波動率固定不變。如果標的具有提前履約特性(美式選擇權),或你想考慮波動率微笑(volatility smile),就需要用二項樹模型、蒙地卡羅模擬,或其他更進階的隨機波動率模型。BS 模型的優點是計算快速、公式封閉解,很適合做為入門學習與快速估價的基礎工具。
Q2:隱含波動率跟歷史波動率有什麼不同?
歷史波動率是用過去一段時間的報酬率計算出來的統計值,反映「過去」的波動程度;隱含波動率則是從目前市場報價反推出來,反映「市場對未來波動的預期」。兩者數值不一定相同,這也是選擇權交易者常常關注的觀察指標之一。
Q3:用 Python 算出來的理論價格跟台指選擇權實際報價會一樣嗎?
不會完全一樣。理論價格是基於模型假設(例如波動率固定、無套利、連續避險)計算出來的估計值,實際市場報價還會受到供需、流動性、交易成本、提前履約風險等因素影響。這也是為什麼學習選擇權定價 Python 的重點,是理解「模型與市場的落差從何而來」,而不是追求兩者完全吻合。
結論與下一步行動
這篇文章帶你用 Python 實作了 Black-Scholes 選擇權定價公式、Greeks 計算、隱含波動率數值求解,以及到期損益圖繪製,所有範例數字都是假設情境,方便你直接複製程式碼動手驗證。選擇權定價的數學看起來複雜,但拆解成 scipy.stats.norm 與 scipy.optimize.brentq 這些現成工具後,其實門檻並沒有想像中高。
如果你想進一步把這些計算結果拿去跟真實市場報價互相驗證,建議搭配一個順手的圖表平台同步觀察,你可以參考 TradingView(https://tw.tradingview.com/pricing/?share_your_love=vick528chiu),一邊看即時報價、一邊用 Python 驗證理論價格與 Greeks,會讓學習選擇權定價的過程更紮實。記得,實際交易前務必以臺灣期貨交易所官網最新公告的合約規格為準,並謹慎評估風險。