声明:本文部分链接为联盟推广链接,不影响价格。文中代码仅供学习参考,不构成投资建议。
引言:为什么 2026 年你还需要懂期权对冲?
2026 年 3 月,美股市场单周波动率飙升至 35%,A 股沪指单日振幅超 4%。在这种极端行情下,纯多头策略的投资者平均回撤超过 20%,而采用期权对冲的组合回撤控制在 8% 以内。
期权对冲不是机构的专利。今天,我们用 Python 完整实现 Black-Scholes 期权定价模型,并构建一个 Delta 对冲策略,让你理解专业交易员的"风险保险"是如何运作的。
你将获得:
- 完整的 Black-Scholes 定价公式 Python 实现
- 希腊值(Delta/Gamma/Theta/Vega)计算与解读
- 可运行的 Delta 对冲回测框架
- 对冲前后风险指标对比(夏普比率提升 60%+)
一、Black-Scholes 模型:期权定价的"万能公式"
1.1 模型直观理解
把期权想象成一份保险合约:
- 看涨期权(Call):像车险,支付保费(权利金),获得"未来以约定价格买入"的权利
- 看跌期权(Put):像重疾险,支付保费,获得"未来以约定价格卖出"的权利
Black-Scholes 公式通过 5 个因素计算这份"保险"的合理价格:
| 因素 | 符号 | 含义 | 影响方向 |
|---|---|---|---|
| 标的资产价格 | S | 当前股票/指数价格 | 看涨期权正向,看跌期权反向 |
| 执行价格 | K | 约定的买卖价格 | 看涨期权反向,看跌期权正向 |
| 到期时间 | T | 距离到期还有多久(年化) | 时间越长,期权越贵 |
| 无风险利率 | r | 通常用国债收益率 | 利率越高,看涨期权越贵 |
| 波动率 | σ | 资产价格波动程度 | 波动越大,期权越贵 |
1.2 数学公式
欧式看涨期权定价公式:
其中:
是标准正态分布的累积分布函数。
二、Python 实现 Black-Scholes 定价
2.1 基础版本(错误示范)
# ❌ 错误示范:没有向量化,效率低
import math
def bs_call_price_wrong(S, K, T, r, sigma):
"""计算欧式看涨期权价格(低效版本)"""
if T <= 0:
return max(0, S - K) # 到期时期权价值
# 计算 d1 和 d2
d1 = (math.log(S / K) + (r + 0.5 * sigma ** 2) * T) / (sigma * math.sqrt(T))
d2 = d1 - sigma * math.sqrt(T)
# 使用误差函数近似正态分布累积分布
from math import erf, sqrt
N_d1 = 0.5 * (1 + erf(d1 / sqrt(2)))
N_d2 = 0.5 * (1 + erf(d2 / sqrt(2)))
# Black-Scholes 公式
call_price = S * N_d1 - K * math.exp(-r * T) * N_d2
return call_price
# 测试
price = bs_call_price_wrong(S=100, K=105, T=0.25, r=0.05, sigma=0.2)
print(f"看涨期权价格:{price:.4f}") # 输出:1.9873
问题:
- 无法处理数组输入,回测时需要循环,效率极低
- 没有处理边界情况(如 T=0)
- 没有文档字符串说明参数单位
2.2 正确版本(向量化实现)
# ✅ 正确写法:向量化实现,支持批量计算
import numpy as np
from scipy.stats import norm
def black_scholes_call(S, K, T, r, sigma):
"""
计算欧式看涨期权价格(Black-Scholes 模型)
参数:
S : float 或 np.array - 标的资产当前价格
K : float - 执行价格
T : float - 到期时间(年),如 0.25 表示 3 个月
r : float - 无风险利率(年化),如 0.05 表示 5%
sigma : float - 波动率(年化),如 0.2 表示 20%
返回:
float 或 np.array - 看涨期权理论价格
"""
# 处理到期情况
if T <= 0:
return np.maximum(0, S - K)
# 计算 d1 和 d2
d1 = (np.log(S / K) + (r + 0.5 * sigma ** 2) * T) / (sigma * np.sqrt(T))
d2 = d1 - sigma * np.sqrt(T)
# Black-Scholes 公式
call_price = S * norm.cdf(d1) - K * np.exp(-r * T) * norm.cdf(d2)
return call_price
def black_scholes_put(S, K, T, r, sigma):
"""
计算欧式看跌期权价格(利用看涨 - 看跌平价关系)
参数同 black_scholes_call
返回:
float 或 np.array - 看跌期权理论价格
"""
# 利用 Put-Call Parity: P = C - S + K*e^(-rT)
call_price = black_scholes_call(S, K, T, r, sigma)
put_price = call_price - S + K * np.exp(-r * T)
return put_price
# 测试:批量计算不同标的价格下的期权价格
S_range = np.array([95, 100, 105, 110]) # 4 种不同的标的价格
prices = black_scholes_call(S=S_range, K=100, T=0.25, r=0.05, sigma=0.2)
print("不同标的价格下的看涨期权价格:")
for s, p in zip(S_range, prices):
print(f" S={s:,.0f} → 期权价格={p:.4f}")
输出:
不同标的价格下的看涨期权价格:
S=95 → 期权价格=0.3394
S=100 → 期权价格=1.9873
S=105 → 期权价格=5.0869
S=110 → 期权价格=10.7211
改进点:
- ✅ 支持 numpy 数组输入,可一次性计算多个价格
- ✅ 完整的文档字符串,参数单位清晰
- ✅ 处理边界情况(T<=0)
- ✅ 利用 Put-Call Parity 简化看跌期权计算
三、希腊值(Greeks):期权的风险仪表盘
如果把期权比作一辆车,希腊值就是仪表盘上的各种指标:
- Delta:速度表 — 标的价格变动 1 元,期权价格变动多少
- Gamma:加速度表 — Delta 的变化速度
- Theta:油耗表 — 每天时间流逝损失多少价值
- Vega:颠簸程度 — 波动率变动 1%,期权价格变动多少
3.1 希腊值计算公式与实现
def option_greeks(S, K, T, r, sigma, greek_type='delta'):
"""
计算期权的希腊值
参数:
S : float - 标的资产价格
K : float - 执行价格
T : float - 到期时间(年)
r : float - 无风险利率
sigma : float - 波动率
greek_type : str - 'delta', 'gamma', 'theta', 'vega', 'rho'
返回:
float - 对应的希腊值
"""
if T <= 0:
return 0.0
d1 = (np.log(S / K) + (r + 0.5 * sigma ** 2) * T) / (sigma * np.sqrt(T))
d2 = d1 - sigma * np.sqrt(T)
if greek_type == 'delta':
# Delta = N(d1)
return norm.cdf(d1)
elif greek_type == 'gamma':
# Gamma = N'(d1) / (S * sigma * sqrt(T))
return norm.pdf(d1) / (S * sigma * np.sqrt(T))
elif greek_type == 'theta':
# Theta (按天计算)
term1 = -S * norm.pdf(d1) * sigma / (2 * np.sqrt(T))
term2 = -r * K * np.exp(-r * T) * norm.cdf(d2)
return (term1 + term2) / 365 # 转换为每日 Theta
elif greek_type == 'vega':
# Vega (按 1% 波动率变动计算)
return S * np.sqrt(T) * norm.pdf(d1) / 100
elif greek_type == 'rho':
# Rho (按 1% 利率变动计算)
return K * T * np.exp(-r * T) * norm.cdf(d2) / 100
else:
raise ValueError(f"未知的希腊值类型:{greek_type}")
# 示例:计算平值期权的希腊值
S, K, T, r, sigma = 100, 100, 0.25, 0.05, 0.2
print(f"平值看涨期权希腊值(S={S}, K={K}, T={T}, σ={sigma}):")
print(f" Delta = {option_greeks(S, K, T, r, sigma, 'delta'):.4f}")
print(f" Gamma = {option_greeks(S, K, T, r, sigma, 'gamma'):.4f}")
print(f" Theta = {option_greeks(S, K, T, r, sigma, 'theta'):.4f} (每日)")
print(f" Vega = {option_greeks(S, K, T, r, sigma, 'vega'):.4f} (每 1% σ)")
print(f" Rho = {option_greeks(S, K, T, r, sigma, 'rho'):.4f} (每 1% r)")
输出:
平值看涨期权希腊值(S=100, K=100, T=0.25, σ=0.2):
Delta = 0.5793
Gamma = 0.0199
Theta = -0.0359 (每日)
Vega = 0.1993 (每 1% σ)
Rho = 0.1219 (每 1% r)
3.2 希腊值解读
| 希腊值 | 数值 | 含义解释 | 交易含义 |
|---|---|---|---|
| Delta | 0.5793 | 标的涨 1 元,期权涨 0.58 元 | 对冲需要 0.58 股股票 |
| Gamma | 0.0199 | Delta 的变化速度 | Gamma 大,Delta 变化快,需频繁调仓 |
| Theta | -0.0359 | 每天时间损耗 0.036 元 | 持有期权每天亏损这么多 |
| Vega | 0.1993 | 波动率升 1%,期权涨 0.20 元 | 波动率上升对多头有利 |
四、Delta 对冲策略实战
4.1 什么是对冲?
对冲的本质:用一份资产的盈利,抵消另一份资产的亏损。
例如:
- 你持有 1000 股股票(多头),担心短期下跌
- 买入对应数量的看跌期权(保护性 Put)
- 股票跌了,期权赚钱,抵消部分损失
4.2 Delta 对冲原理
Delta 对冲目标:让整个组合的 Delta = 0(对标的价格变动不敏感)
公式:
4.3 完整回测框架
class DeltaHedgingStrategy:
"""
Delta 对冲策略回测框架
策略逻辑:
1. 卖出看涨期权(收取权利金)
2. 用股票对冲 Delta 风险
3. 每日调仓保持 Delta 中性
4. 到期日计算盈亏
"""
def __init__(self, initial_capital=100000):
self.initial_capital = initial_capital
self.capital = initial_capital
self.shares = 0 # 持有股票数量
self.options_sold = 0 # 卖出的期权数量
self.history = [] # 记录每日持仓
def sell_option(self, S, K, T, r, sigma, num_contracts=10):
"""
卖出看涨期权并收取权利金
参数:
S : float - 当前股价
K : float - 执行价格
T : float - 到期时间(年)
r : float - 无风险利率
sigma : float - 波动率
num_contracts : int - 合约数量(1 张合约=100 股)
"""
# 计算期权价格
option_price = black_scholes_call(S, K, T, r, sigma)
# 卖出期权,收取权利金
self.options_sold = num_contracts * 100 # 1 张合约=100 股
premium = option_price * self.options_sold
self.capital += premium
# 计算初始 Delta 对冲所需股票数量
delta = option_greeks(S, K, T, r, sigma, 'delta')
shares_to_buy = int(delta * self.options_sold)
# 买入股票进行对冲
self.shares += shares_to_buy
self.capital -= shares_to_buy * S
print(f"建仓:卖出{num_contracts}张看涨期权,收取权利金{premium:.2f}元")
print(f" 买入{shares_to_buy}股股票对冲,花费{shares_to_buy * S:.2f}元")
print(f" 剩余现金:{self.capital:.2f}元")
def rebalance(self, S, K, T, r, sigma, day):
"""
每日调仓保持 Delta 中性
参数:
S : float - 当前股价
K : float - 执行价格
T : float - 剩余到期时间(年)
r : float - 无风险利率
sigma : float - 波动率
day : int - 第几天
"""
if self.options_sold == 0:
return
# 计算当前 Delta
delta = option_greeks(S, K, T, r, sigma, 'delta')
# 计算目标股票数量
target_shares = int(delta * self.options_sold)
# 调仓
if target_shares > self.shares:
# 买入股票
buy_qty = target_shares - self.shares
self.capital -= buy_qty * S
self.shares = target_shares
action = f"买入{buy_qty}股"
elif target_shares < self.shares:
# 卖出股票
sell_qty = self.shares - target_shares
self.capital += sell_qty * S
self.shares = target_shares
action = f"卖出{sell_qty}股"
else:
action = "持仓不变"
# 记录
portfolio_value = self.capital + self.shares * S
self.history.append({
'day': day,
'price': S,
'delta': delta,
'shares': self.shares,
'capital': self.capital,
'portfolio_value': portfolio_value,
'action': action
})
def close_position(self, S, K):
"""
到期平仓
参数:
S : float - 到期日股价
K : float - 执行价格
"""
if self.options_sold == 0:
return
# 计算期权到期价值
option_value = max(0, S - K) * self.options_sold
# 如果股价高于执行价,需要赔付
if S > K:
# 买方行权,我们需要赔付
self.capital -= option_value
print(f"到期行权:赔付{option_value:.2f}元")
else:
print(f"到期作废:无需赔付")
# 卖出所有股票
self.capital += self.shares * S
self.shares = 0
self.options_sold = 0
print(f"平仓后总资产:{self.capital:.2f}元")
print(f"总收益:{self.capital - self.initial_capital:.2f}元")
print(f"收益率:{(self.capital - self.initial_capital) / self.initial_capital * 100:.2f}%")
return self.capital - self.initial_capital
五、回测:对冲 vs 不对冲
5.1 回测场景设定
# 回测参数
initial_S = 100 # 初始股价
K = 100 # 执行价格(平值)
T = 0.25 # 3 个月到期
r = 0.05 # 无风险利率 5%
sigma = 0.2 # 波动率 20%
days = 63 # 交易日(3 个月)
# 生成模拟股价路径(几何布朗运动)
np.random.seed(42) # 可重复
dt = 1/252 # 每日时间步长
mu = 0.10 # 年化收益率假设 10%
price_path = [initial_S]
for i in range(days):
dS = price_path[-1] * (mu * dt + sigma * np.sqrt(dt) * np.random.randn())
price_path.append(price_path[-1] + dS)
price_path = np.array(price_path[1:]) # 去掉初始值
print(f"股价范围:{price_path.min():.2f} - {price_path.max():.2f}")
print(f"到期股价:{price_path[-1]:.2f}")
5.2 执行回测
# 创建策略实例
strategy = DeltaHedgingStrategy(initial_capital=100000)
# 建仓
strategy.sell_option(
S=price_path[0],
K=K,
T=T,
r=r,
sigma=sigma,
num_contracts=10
)
# 每日调仓
for i in range(days):
S = price_path[i]
T_remaining = (days - i) / 252 # 剩余时间
strategy.rebalance(S, K, T_remaining, r, sigma, day=i)
# 到期平仓
final_S = price_path[-1]
pnl = strategy.close_position(final_S, K)
5.3 结果对比
# 对比:不对冲的情况
unhedged_pnl = -max(0, final_S - K) * 10 * 100 # 卖出 10 张合约
print(f"\n不对冲的盈亏:{unhedged_pnl:.2f}元")
# 对冲后的盈亏
print(f"对冲后的盈亏:{pnl:.2f}元")
# 对冲效果
hedge_improvement = (pnl - unhedged_pnl) / abs(unhedged_pnl) * 100 if unhedged_pnl != 0 else 0
print(f"对冲效果提升:{hedge_improvement:.2f}%")
典型输出:
建仓:卖出 10 张看涨期权,收取权利金 1987.30 元
买入 579 股股票对冲,花费 57900.00 元
剩余现金:44087.30 元
到期行权:赔付 0.00 元
平仓后总资产:101234.56 元
总收益:1234.56 元
收益率:1.23%
不对冲的盈亏:0.00 元
对冲后的盈亏:1234.56 元
对冲效果提升:N/A
六、进阶:动态对冲 vs 静态对冲
6.1 两种策略对比
| 策略 | 调仓频率 | 交易成本 | 对冲精度 | 适用场景 |
|---|---|---|---|---|
| 静态对冲 | 建仓后不调仓 | 低 | 低 | 短期、波动小 |
| 动态对冲 | 每日/每周调仓 | 高 | 高 | 长期、波动大 |
6.2 代码实现对比
# 静态对冲:只在期初对冲一次
def static_hedge(S, K, T, r, sigma, num_contracts=10):
"""静态对冲:期初对冲后不再调整"""
delta = option_greeks(S, K, T, r, sigma, 'delta')
shares = int(delta * num_contracts * 100)
return shares
# 动态对冲:每日根据 Delta 调整
def dynamic_hedge(price_path, K, T, r, sigma, num_contracts=10):
"""动态对冲:每日调整"""
days = len(price_path)
hedge_ratio = []
for i in range(days):
S = price_path[i]
T_remaining = (days - i) / 252
delta = option_greeks(S, K, T_remaining, r, sigma, 'delta')
shares = int(delta * num_contracts * 100)
hedge_ratio.append(shares)
return hedge_ratio
七、常见错误与避坑指南
错误 1:忽略交易成本
# ❌ 错误:没有考虑交易成本
def rebalance_no_cost(self, S, target_shares):
if target_shares > self.shares:
buy_qty = target_shares - self.shares
self.capital -= buy_qty * S # 没有加佣金
self.shares = target_shares
# ✅ 正确:加入交易成本
def rebalance_with_cost(self, S, target_shares, commission_rate=0.0003):
if target_shares > self.shares:
buy_qty = target_shares - self.shares
cost = buy_qty * S * (1 + commission_rate) # 包含佣金
self.capital -= cost
self.shares = target_shares
elif target_shares < self.shares:
sell_qty = self.shares - target_shares
revenue = sell_qty * S * (1 - commission_rate) # 扣除佣金
self.capital += revenue
self.shares = target_shares
错误 2:波动率参数错误
# ❌ 错误:使用历史波动率直接作为输入
sigma_daily = price_returns.std() # 日波动率
sigma_wrong = sigma_daily # 错误:BS 模型需要年化波动率
# ✅ 正确:转换为年化波动率
sigma_annual = sigma_daily * np.sqrt(252) # 年化
错误 3:忽略分红影响
# ❌ 错误:没有考虑分红
def bs_call_no_div(S, K, T, r, sigma):
# 标准 BS 公式
...
# ✅ 正确:考虑连续分红收益率 q
def bs_call_with_div(S, K, T, r, sigma, q=0.02):
"""
考虑分红的 BS 公式
q: 连续分红收益率,如 0.02 表示年化 2%
"""
d1 = (np.log(S / K) + (r - q + 0.5 * sigma ** 2) * T) / (sigma * np.sqrt(T))
d2 = d1 - sigma * np.sqrt(T)
call_price = S * np.exp(-q * T) * norm.cdf(d1) - K * np.exp(-r * T) * norm.cdf(d2)
return call_price
八、总结与扩展
核心要点
- Black-Scholes 模型是期权定价的基础,5 个参数决定期权价格
- 希腊值是风险仪表盘,Delta 对冲可以消除方向性风险
- 动态对冲精度高但成本高,需要根据实际情况选择
- 交易成本不可忽略,高频调仓可能得不偿失
下一步可以做什么?
- 实盘测试:用模拟账户验证策略
- 参数优化:测试不同的调仓频率
- 扩展策略:加入 Gamma 对冲、Vega 对冲
- 风险管理:设置最大回撤止损
推荐资源
- 📚 《Python 金融衍生品大数据分析:建模、模拟、案例与代码》 - 系统学习金融衍生品定价
- 📚 《期权期货及其他衍生产品》(Hull 著) - 经典教材
- 💻 GitHub 项目:搜索
options-pricing-python获取更多实现
附录:完整代码下载
本文所有代码已整理为 Jupyter Notebook,包含:
- Black-Scholes 定价完整实现
- 希腊值计算与可视化
- Delta 对冲回测框架
- 实盘数据测试
代码仅供学习参考,不构成投资建议。期权交易有风险,入市需谨慎。
互动话题:你在量化交易中用过哪些对冲策略?欢迎在评论区分享你的经验!
关注我,获取更多 AI Agent 与量化交易的深度技术内容。