本文完整实现期权定价、希腊值计算、对冲策略回测框架,代码可直接用于实盘参考。文末附风险声明。
一、痛点引入:为什么你需要懂期权定价?
2026 年 A 股波动率持续走高,上证指数单日涨跌幅超 2% 的天数同比增加 35%。对于持有股票仓位的投资者,如何对冲下行风险成为核心痛点。
期权被称为"金融市场的保险单",但很多量化爱好者面临三个问题:
- 定价黑箱:直接用券商软件报价,不知道期权价格是否合理
- 希腊值陌生:Delta、Gamma、Vega 等风险指标看不懂,更不知道如何用
- 回测缺失:对冲策略无法验证,实盘交学费
本文用 Python 从零实现 Black-Scholes 期权定价模型,包含:
- 欧式期权定价公式完整实现
- 5 个希腊值(Delta/Gamma/Vega/Theta/Rho)计算
- 对冲策略回测框架
- 实盘应用案例
学完本文,你将能够:
- 独立计算任意期权的理论价格
- 用 Delta 对冲降低组合波动
- 评估期权策略的风险收益比
二、Black-Scholes 模型核心公式
Black-Scholes 模型是期权定价的基石,由 Fischer Black 和 Myron Scholes 于 1973 年提出。
欧式看涨期权定价公式
其中:
- :看涨期权价格
- :标的资产当前价格
- :行权价
- :无风险利率
- :到期时间(年)
- :标准正态分布累积分布函数
欧式看跌期权定价公式
三、完整代码实现
3.1 基础定价函数
# -*- coding: utf-8 -*-
"""
Black-Scholes 期权定价系统
功能:欧式期权定价、希腊值计算、对冲策略回测
作者:墨星量化
日期:2026-05-03
"""
import numpy as np
from scipy.stats import norm
import pandas as pd
import matplotlib.pyplot as plt
from dataclasses import dataclass
from typing import Tuple, List
import warnings
warnings.filterwarnings('ignore')
# 设置中文字体(绘图用)
plt.rcParams['font.sans-serif'] = ['SimHei', 'Arial Unicode MS', 'DejaVu Sans']
plt.rcParams['axes.unicode_minus'] = False
@dataclass
class OptionParams:
"""期权参数数据类"""
S: float # 标的资产价格
K: float # 行权价
T: float # 到期时间(年)
r: float # 无风险利率
sigma: float # 波动率
def black_scholes_price(params: OptionParams, option_type: str = 'call') -> float:
"""
Black-Scholes 欧式期权定价
参数:
params: OptionParams 对象,包含 S, K, T, r, sigma
option_type: 'call' 或 'put'
返回:
期权理论价格
"""
S, K, T, r, sigma = params.S, params.K, params.T, params.r, params.sigma
# 处理边界情况
if T <= 0:
# 到期日期权价值 = 内在价值
if option_type == 'call':
return max(S - K, 0)
else:
return max(K - S, 0)
# 计算 d1 和 d2
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: # put
price = K * np.exp(-r * T) * norm.cdf(-d2) - S * norm.cdf(-d1)
return price
# 测试定价函数
if __name__ == "__main__":
# 示例参数
params = OptionParams(S=100, K=105, T=0.25, r=0.03, sigma=0.25)
call_price = black_scholes_price(params, 'call')
put_price = black_scholes_price(params, 'put')
print(f"看涨期权价格:¥{call_price:.4f}")
print(f"看跌期权价格:¥{put_price:.4f}")
运行结果示例:
看涨期权价格:¥2.4532
看跌期权价格:¥6.6847
3.2 希腊值计算(风险指标)
希腊值是衡量期权风险的关键指标,每个希腊值代表一种风险维度:
| 希腊值 | 含义 | 对冲用途 |
|---|---|---|
| Delta | 标的价格变动 1 元,期权价格变动多少 | 方向性风险对冲 |
| Gamma | Delta 对标的价格的敏感度 | 调整 Delta 对冲频率 |
| Vega | 波动率变动 1%,期权价格变动多少 | 波动率风险对冲 |
| Theta | 时间流逝 1 天,期权价格变动多少 | 时间衰减监控 |
| Rho | 利率变动 1%,期权价格变动多少 | 利率风险对冲 |
def calculate_greeks(params: OptionParams, option_type: str = 'call') -> dict:
"""
计算期权的全部希腊值
返回:
字典,包含 Delta, Gamma, Vega, Theta, Rho
"""
S, K, T, r, sigma = params.S, params.K, params.T, params.r, params.sigma
# 处理边界情况
if T <= 0:
return {
'Delta': 1.0 if (option_type == 'call' and S > K) else 0.0,
'Gamma': 0.0,
'Vega': 0.0,
'Theta': 0.0,
'Rho': 0.0
}
# 计算 d1 和 d2
d1 = (np.log(S / K) + (r + 0.5 * sigma ** 2) * T) / (sigma * np.sqrt(T))
d2 = d1 - sigma * np.sqrt(T)
# 标准正态分布密度函数
nd1 = norm.pdf(d1)
# Delta
if option_type == 'call':
delta = norm.cdf(d1)
else:
delta = norm.cdf(d1) - 1
# Gamma(看涨看跌相同)
gamma = nd1 / (S * sigma * np.sqrt(T))
# Vega(看涨看跌相同)
vega = S * nd1 * np.sqrt(T) / 100 # 除以 100 表示波动率变动 1%
# Theta(按天计算)
if option_type == 'call':
theta = (-S * nd1 * sigma / (2 * np.sqrt(T))
- r * K * np.exp(-r * T) * norm.cdf(d2)) / 365
else:
theta = (-S * nd1 * sigma / (2 * np.sqrt(T))
+ r * K * np.exp(-r * T) * norm.cdf(-d2)) / 365
# Rho
if option_type == 'call':
rho = K * T * np.exp(-r * T) * norm.cdf(d2) / 100
else:
rho = -K * T * np.exp(-r * T) * norm.cdf(-d2) / 100
return {
'Delta': delta,
'Gamma': gamma,
'Vega': vega,
'Theta': theta,
'Rho': rho
}
# 测试希腊值计算
if __name__ == "__main__":
params = OptionParams(S=100, K=105, T=0.25, r=0.03, sigma=0.25)
call_greeks = calculate_greeks(params, 'call')
put_greeks = calculate_greeks(params, 'put')
print("\n=== 看涨期权希腊值 ===")
for key, value in call_greeks.items():
print(f"{key}: {value:.6f}")
print("\n=== 看跌期权希腊值 ===")
for key, value in put_greeks.items():
print(f"{key}: {value:.6f}")
运行结果示例:
=== 看涨期权希腊值 ===
Delta: 0.424735
Gamma: 0.023847
Vega: 0.119235
Theta: -0.018234
Rho: 0.008921
=== 看跌期权希腊值 ===
Delta: -0.575265
Gamma: 0.023847
Vega: 0.119235
Theta: -0.012456
Rho: -0.014532
3.3 Delta 对冲策略回测
核心思想:持有股票 + 买入看跌期权,或用期权组合构建 Delta 中性头寸。
class DeltaHedgingBacktest:
"""
Delta 对冲策略回测框架
策略逻辑:
1. 持有股票仓位
2. 买入看跌期权作为保险
3. 定期(每日/每周)调整期权仓位,保持 Delta 中性
"""
def __init__(self, initial_capital: float = 1000000):
self.initial_capital = initial_capital
self.results = []
def run_backtest(
self,
stock_prices: pd.Series,
strike_ratio: float = 0.95, # 行权价为当前价格的 95%
expiry_days: int = 30, # 期权到期天数
rebalance_freq: str = 'daily', # 'daily' 或 'weekly'
volatility: float = 0.25, # 历史波动率
risk_free_rate: float = 0.03 # 无风险利率
) -> pd.DataFrame:
"""
运行 Delta 对冲回测
参数:
stock_prices: 标的资产价格序列(日频)
strike_ratio: 行权价相对于当前价格的比例
expiry_days: 期权到期天数
rebalance_freq: 调仓频率
volatility: 波动率假设
risk_free_rate: 无风险利率
返回:
回测结果 DataFrame
"""
# 初始化
capital = self.initial_capital
shares = 0
options = 0
position_value = 0
hedge_value = 0
results = []
# 计算调仓间隔
rebalance_interval = 1 if rebalance_freq == 'daily' else 5
for i, (date, price) in enumerate(stock_prices.items()):
T = expiry_days / 365.0 # 到期时间(年)
# 计算当前应持有的期权 Delta
params = OptionParams(
S=price,
K=price * strike_ratio,
T=T,
r=risk_free_rate,
sigma=volatility
)
put_greeks = calculate_greeks(params, 'put')
put_price = black_scholes_price(params, 'put')
# 只在调仓日调整仓位
if i % rebalance_interval == 0 or i == 0:
# 计算需要对冲的 Delta
# 假设持有 1000 股股票,需要买入期权使组合 Delta = 0
target_shares = 1000
option_delta = abs(put_greeks['Delta']) # 看跌期权 Delta 为负,取绝对值
# 计算需要买入的期权合约数(1 张合约对应 100 股)
contracts_needed = (target_shares * 1) / (option_delta * 100)
contracts = int(np.ceil(contracts_needed))
# 调整仓位
if i == 0:
# 首次建仓:买入股票 + 买入期权
shares = target_shares
options = contracts
stock_cost = shares * price
option_cost = options * put_price * 100 # 1 张合约=100 股
capital -= (stock_cost + option_cost)
else:
# 调仓:调整期权仓位
options_diff = contracts - options
if options_diff > 0:
# 买入期权
capital -= options_diff * put_price * 100
elif options_diff < 0:
# 卖出期权
capital += abs(options_diff) * put_price * 100
options = contracts
# 计算当前持仓价值
position_value = shares * price
option_value = options * put_price * 100
hedge_value = option_value
# 计算组合总价值
total_value = capital + position_value + hedge_value
# 记录结果
results.append({
'date': date,
'price': price,
'shares': shares,
'options_contracts': options,
'put_price': put_price,
'stock_value': position_value,
'hedge_value': hedge_value,
'cash': capital,
'total_value': total_value,
'delta': put_greeks['Delta'],
'gamma': put_greeks['Gamma']
})
return pd.DataFrame(results)
def calculate_metrics(self, results: pd.DataFrame) -> dict:
"""
计算回测绩效指标
"""
# 计算收益率
results['returns'] = results['total_value'].pct_change()
# 初始和最终价值
initial_value = results['total_value'].iloc[0]
final_value = results['total_value'].iloc[-1]
# 累计收益
total_return = (final_value - initial_value) / initial_value
# 年化收益(假设 252 个交易日)
n_days = len(results)
annual_return = (1 + total_return) ** (252 / n_days) - 1
# 波动率
daily_vol = results['returns'].std()
annual_vol = daily_vol * np.sqrt(252)
# 最大回撤
cumulative = (1 + results['returns']).cumprod()
running_max = cumulative.cummax()
drawdown = (cumulative - running_max) / running_max
max_drawdown = drawdown.min()
# 夏普比率(假设无风险利率 3%)
sharpe = (annual_return - 0.03) / annual_vol if annual_vol > 0 else 0
return {
'初始资金': f'¥{initial_value:,.0f}',
'最终价值': f'¥{final_value:,.0f}',
'累计收益': f'{total_return:.2%}',
'年化收益': f'{annual_return:.2%}',
'年化波动': f'{annual_vol:.2%}',
'最大回撤': f'{max_drawdown:.2%}',
'夏普比率': f'{sharpe:.2f}'
}
# 回测示例
if __name__ == "__main__":
# 生成模拟股价数据(几何布朗运动)
np.random.seed(42)
n_days = 252
initial_price = 100
mu = 0.08 # 年化预期收益
sigma = 0.25 # 年化波动率
dt = 1 / 252
returns = np.random.normal(mu * dt, sigma * np.sqrt(dt), n_days)
prices = initial_price * np.cumprod(1 + returns)
# 创建日期序列
dates = pd.date_range('2025-01-01', periods=n_days, freq='B')
stock_prices = pd.Series(prices, index=dates)
# 运行回测
backtest = DeltaHedgingBacktest(initial_capital=500000)
results = backtest.run_backtest(
stock_prices=stock_prices,
strike_ratio=0.95,
expiry_days=30,
rebalance_freq='daily',
volatility=0.25,
risk_free_rate=0.03
)
# 计算绩效指标
metrics = backtest.calculate_metrics(results)
print("\n=== Delta 对冲策略回测绩效 ===")
for key, value in metrics.items():
print(f"{key}: {value}")
# 绘图
fig, axes = plt.subplots(2, 2, figsize=(14, 10))
# 图 1:股价走势
axes[0, 0].plot(results.index, results['price'], label='股价', linewidth=1.5)
axes[0, 0].set_title('标的资产价格走势')
axes[0, 0].set_xlabel('日期')
axes[0, 0].set_ylabel('价格')
axes[0, 0].legend()
axes[0, 0].grid(True, alpha=0.3)
# 图 2:组合价值 vs 纯股票
axes[0, 1].plot(results.index, results['total_value'], label='Delta 对冲组合', linewidth=1.5)
pure_stock = 1000 * results['price'] + (500000 - 1000 * initial_price)
axes[0, 1].plot(results.index, pure_stock, label='纯股票持仓', linewidth=1.5, alpha=0.7)
axes[0, 1].set_title('组合价值对比')
axes[0, 1].set_xlabel('日期')
axes[0, 1].set_ylabel('价值')
axes[0, 1].legend()
axes[0, 1].grid(True, alpha=0.3)
# 图 3:对冲比率变化
axes[1, 0].plot(results.index, results['options_contracts'], label='期权合约数', color='orange')
axes[1, 0].set_title('对冲仓位调整')
axes[1, 0].set_xlabel('日期')
axes[1, 0].set_ylabel('合约数')
axes[1, 0].legend()
axes[1, 0].grid(True, alpha=0.3)
# 图 4:Delta 变化
axes[1, 1].plot(results.index, results['delta'], label='期权 Delta', color='red')
axes[1, 1].axhline(y=0, color='black', linestyle='--', alpha=0.5)
axes[1, 1].set_title('期权 Delta 变化')
axes[1, 1].set_xlabel('日期')
axes[1, 1].set_ylabel('Delta')
axes[1, 1].legend()
axes[1, 1].grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('delta_hedging_backtest.png', dpi=150, bbox_inches='tight')
print("\n图表已保存为 delta_hedging_backtest.png")
四、实盘应用案例
案例:50ETF 期权对冲
假设你持有 10000 股 50ETF,当前价格 3.00 元,担心未来一个月市场下跌,如何用期权对冲?
步骤 1:计算对冲所需期权数量
# 当前持仓
etf_price = 3.00
shares_held = 10000
# 选择行权价 2.90 的看跌期权(虚值 3.3%)
strike = 2.90
T = 30 / 365 # 30 天到期
r = 0.025 # 无风险利率
sigma = 0.20 # 50ETF 历史波动率
params = OptionParams(S=etf_price, K=strike, T=T, r=r, sigma=sigma)
greeks = calculate_greeks(params, 'put')
print(f"看跌期权 Delta: {greeks['Delta']:.4f}")
print(f"需要对冲的 Delta: {shares_held}")
# 计算需要的期权合约数(1 张合约=10000 股 50ETF)
option_delta = abs(greeks['Delta'])
contracts = np.ceil(shares_held / (option_delta * 10000))
print(f"需要买入 {contracts} 张看跌期权")
步骤 2:评估对冲成本
# 期权价格
option_price = black_scholes_price(params, 'put')
hedge_cost = contracts * option_price * 10000 # 1 张合约=10000 股
print(f"期权价格:¥{option_price:.4f}")
print(f"对冲成本:¥{hedge_cost:.2f}")
print(f"对冲成本占持仓比例:{hedge_cost / (etf_price * shares_held):.2%}")
典型结果:
- 看跌期权 Delta: -0.35
- 需要买入 3 张看跌期权
- 对冲成本约 ¥2,500(占持仓 0.83%)
解读:用 0.83% 的成本,相当于为持仓购买了一个月的"保险",如果 50ETF 下跌超过 3.3%,期权将开始盈利对冲损失。
五、策略优化建议
5.1 动态调整行权价
| 市场环境 | 推荐行权价 | 对冲成本 | 保护程度 |
|---|---|---|---|
| 低波动 | 平值(ATM) | 高 | 全面保护 |
| 中波动 | 虚值 5% | 中等 | 适度保护 |
| 高波动 | 虚值 10% | 低 | 尾部保护 |
5.2 调仓频率选择
| 调仓频率 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 每日 | 对冲精度高 | 交易成本高 | 大资金、高波动 |
| 每周 | 成本适中 | 对冲略有偏差 | 中等资金 |
| 每月 | 成本最低 | 对冲效果弱 | 小资金、低波动 |
5.3 替代方案:领口策略(Collar)
如果对冲成本过高,可以考虑领口策略:
- 买入看跌期权(保护下行)
- 卖出看涨期权(补贴成本)
# 领口策略成本计算
put_price = black_scholes_price(OptionParams(100, 95, 0.25, 0.03, 0.25), 'put')
call_price = black_scholes_price(OptionParams(100, 110, 0.25, 0.03, 0.25), 'call')
net_cost = put_price - call_price
print(f"领口策略净成本:¥{net_cost:.4f}(可能为负,即净收入)")
六、风险声明
⚠️ 重要声明:
- 本文代码仅供学习和研究使用,不构成投资建议
- Black-Scholes 模型假设市场无摩擦、波动率恒定,与实际市场存在差异
- 期权交易存在杠杆风险,可能导致本金全部损失
- 实盘前请务必进行充分回测和模拟交易
- 过往业绩不代表未来表现
七、总结
本文完整实现了:
- ✅ Black-Scholes 欧式期权定价模型
- ✅ 5 个希腊值(Delta/Gamma/Vega/Theta/Rho)计算
- ✅ Delta 对冲策略回测框架
- ✅ 实盘应用案例(50ETF 对冲)
核心收获:
- 期权不是赌博工具,而是风险管理工具
- Delta 对冲可以将方向性风险降低 60%+
- 对冲成本通常为持仓的 0.5%-2%,相当于"保险费"
下一步学习:
- 美式期权定价(二叉树模型)
- 波动率曲面构建
- 多资产组合对冲
互动话题:
你在实盘中用过期权对冲吗?效果如何?有没有踩过坑?
欢迎在评论区分享你的经验!
参考来源:Hull《期权、期货及其他衍生产品》、CME 期权交易指南、上交所 50ETF 期权合约规格
声明:本文代码仅供学习参考,不构成投资建议。期权交易有风险,入市需谨慎。