Python 選擇權視覺化教學:用 Matplotlib 繪製 Vanilla 與 Exotic Option 損益圖
在「新金融商品的組裝藝術」一文中,我們談論過如何透過融合的方式,利用簡單型態的選擇權,組裝出新商品。
在研究、設計金融商品時,可以透過了解既有商品的特性,選擇投資人偏好的元素將之組合形成新商品;這些商品的特性包含:
- 成本 / 收益
成本與收益為一體之兩面,投資人通常會偏好帶有高收益報酬的商品;而發行商為了迎合投資人的喜好,則會需要增加其他特性來減少選擇權的成本。 - 時間
跟時間有關的特性,例如,障礙價 (Barrier Level)。在選擇權存續期間,標的股價碰觸到障礙價之後選擇權才會生效、失效,這類特性可以讓選擇權成本 (價格) 降低。
從商品的收益面著手會是最為方便,也最容易能讓人理解金融商品的組成元素。
不過,靜態的到期損益圖 (Payoff Diagram) 只是第一步。在真實交易中,我們更需要監控隨著時間 (Time) 與波動率 (Volatility) 變化的「動態風險」。本文將先帶您掌握基礎的靜態繪圖,如果您想進一步實現動態 3D 風險視覺化或歷史回測,請務必閱讀文末的進階資源。
工欲善其事,必先利其器。在開始之前,我們先要把基本選擇權的收益曲線函數、繪圖函數準備好,以下範例皆由 Python 編寫。
Python 程式碼
收益曲線 (Payoff Diagram)
使用類別 (class) 定義各類型選擇權的收益曲線函數以及相關評價函數。
一般選擇權 (Plain Vanilla Option) – 買/賣權
一般選擇權的收益計算方式為:
買權
賣權
class bs_pv_option(object):
def __init__(self, S, K, r, T, sigma, b, CallPut, PorS):
"""
初始化選擇權參數
S: 標的價格
K: 履約價格
r: 無風險利率
T: 到期期間 (年)
sigma: 波動率
b: Cost of Carry (b=r 為 Black-Scholes)
CallPut: 'Call' 或 'Put'
PorS: 'P' (Purchase/Long) 或 'S' (Sell/Short)
"""
self.S = S
self.K = K
self.r = r
self.T = T
self.sigma = sigma
self.b = b
# 將字串參數轉換為數值係數 (1 或 -1)
self.CallPut = 1 if CallPut == 'Call' else -1
self.PorS = 1 if PorS == 'P' else -1
def payoff(self):
payoff = max(self.CallPut * self.S - self.CallPut * self.K, 0)
return payoff * self.PorS
其中類別中的 __init__ 函數決定了輸入參數的使用方式,並將參數傳遞給類別中的其他函數使用。
payoff 函數相對簡單,只需要考慮按上述收益計算邏輯判斷買賣權的收益報酬,並且將買賣方向 (PorS – purchase or sell) 也納入考量。
數位選擇權 (Digital Option) – 買/賣權
數位選擇權的收益計算方式為:
買權
賣權
class bs_digital_option(object):
def __init__(self, S, K, r, T, sigma, b, CallPut, PorS):
...
def payoff(self):
payoff = 1 if (self.CallPut * self.S - self.CallPut * self.K) >= 0 else 0
return payoff * self.PorS
對於數位選擇權而言,收益計算是二元性的。因此 payoff 函數也是根據股價與履約價的關係,判斷是否在價內 (ITM – in the money) 即可,同時也將買賣方向納入考量。
繪圖函數
計算區間內股價的選擇權收益曲線
以目前股價為參考,計算股價於向下 80% 到向上 120% 間的選擇權收益曲線。
from bs_option_class import *
import numpy as np
def opt_payoff(Opt_func, S0, K, r, T, sigma, b, CallPut, PorS, H = None, RB = None, Type = None):
Stock = np.linspace(S0 * 0.8, S0 * 1.2, 500)
o = Opt_func(S0, K, r, T, sigma, b, CallPut, PorS)
result = np.zeros_like(Stock)
for s in enumerate(Stock):
o.S = s[1]
result[s[0]] = o.payoff()
return result, Stock
這邊利用到 python 的函數功能,可以將不同選擇權的函數名稱 (Opt_func) 與參數做為輸入參數,增加這個函數的使用彈性,不需要維護多個版本的 opt_payoff 函數。
未來即使新增其他類型選擇權的評價類別,透過傳遞新類型選擇權的類別 (class) 名稱到 Opt_func 即可。
而後方參數的部分實際上也可以使用 **param 傳遞字典 (dict) 型態的變數,將選擇權評價公式中的參數存放在字典中即可。
繪圖
將取得的收益 (result) 繪製為 2D 的曲線圖。
from pylab import plt
def plot_payoff(Stock, result):
plt.figure(figsize=(10, 6))
plt.plot(Stock, result)
plt.xlabel('Price') plt.ylabel('Payoff')
plt.title('Option Payoff')
將股價區間與收益曲線的結果做為輸入參數,並進行繪圖。
收益曲線繪圖
一般買、賣權與組合策略
計算買入一般買權的收益並繪圖:
result1, Stock = opt_payoff(bs_pv_option, 100, 105, 0.02, 1, 0.2, 0.02, 'Call', 'P')
plot_payoff(Stock, result1)

計算買入一般賣權的收益並繪圖:
result2, Stock = opt_payoff(bs_pv_option, 100, 95, 0.02, 1, 0.2, 0.02, 'Put', 'P')
plot_payoff(Stock, result2)

將買入買權 + 買入賣權的收益繪圖:
plot_payoff(Stock, result1+result2)

這也稱為選擇權的勒式組合 (Strangle),一般會用於對未來市場行情有大漲或大跌的看法時使用,支付權利金以換取大漲、大跌後的報酬。相對的,如果選擇權到期時股價沒有超過買、賣權的履約價區間 (95 – 105),則會損失權利金。
數位選擇權與組合策略
計算買入數位選擇權買權的收益並繪圖:
result3, Stock = opt_payoff(bs_digital_option, 100, 95, 0.02, 1, 0.2, 0.02, 'Call', 'P')
plot_payoff(Stock, result3)

計算買入數位選擇權賣權的收益並繪圖:
result2, Stock = opt_payoff(bs_digital_option, 100, 105, 0.02, 1, 0.2, 0.02, 'Put', 'P')
plot_payoff(Stock, result2)

將多個買入數位選擇權買權 + 賣權的收益繪圖:
result1, Stock = opt_payoff(bs_digital_option, 100, 85, 0.02, 1, 0.2, 0.02, 'Call', 'P')
result2, Stock = opt_payoff(bs_digital_option, 100, 105, 0.02, 1, 0.2, 0.02, 'Put', 'P')
result3, Stock = opt_payoff(bs_digital_option, 100, 95, 0.02, 1, 0.2, 0.02, 'Call', 'P')
result4, Stock = opt_payoff(bs_digital_option, 100, 115, 0.02, 1, 0.2, 0.02, 'Put', 'P')
plot_payoff(Stock, result1+result2+result3+result4)

這段程式碼完美展示了「積木堆疊」的威力。讓我們拆解這四個數位選擇權 (Digital Options) 如何堆出「結婚蛋糕」的形狀:
- 基底層 (最寬):由
Call @ 85與Put @ 115組成,只要股價在 85~115 之間,兩者皆為 1,提供基礎收益。 - 上層 (核心):由
Call @ 95與Put @ 105組成,當股價進入 95~105 的核心區間時,這兩者額外提供收益,將總 Payoff 推升至最高點。
透過簡單的加法運算,我們就能將冰冷的二元選項 (0 或 1),組裝成具有多層次收益的結構型商品。
結語:從靜態繪圖到動態量化實戰
作為「解構新金融商品:Barrier, Digital 與 Exotic Option 的組裝藝術」的延伸閱讀材料,透過本文的實作,您已經掌握了如何使用 Python 與 Matplotlib 繪製出標準的選擇權到期損益圖,也了解了財務工程實作上我們需要準備的基礎材料。
然而,在真實交易的世界中,「到期損益」只是冰山一角。
作為一名量化交易者,您更需要知道的是:
- 當波動率 (Volatility) 改變時,這張損益圖會如何變形?(Vega Risk)
- 當時間 (Time) 一天天過去,您的部位價值會如何衰退?(Theta Decay)
- 這個策略如果放在過去兩年的真實市場中,到底是賺是賠?(Backtesting)
如果您想從「畫圖」進階到真正的「策略分析與回測」,歡迎參考我們的進階課程:
在這堂課中,我們將提供:
- 3D 風險儀表板:透過滑桿即時互動,看見風險的形狀。
- 完整回測引擎原始碼:直接串接 Yahoo Finance 歷史數據,驗證您的策略績效。
- 動態損益分析:不僅看到期,更能看見「當下」的損益變化。
財務工程是需要複合能力的有趣工作,除了金融業的知識之外,還需要數學建模以及編寫程式碼實作。期待在進階課程中與您相見,一起探索量化交易的深層奧秘。





