量化交易"期权保险"全攻略:用 Python 构建 Black-Scholes 定价系统,对冲效率提升 60%(完整代码)

0 阅读1分钟

本文完整实现期权定价、希腊值计算、对冲策略回测框架,代码可直接用于实盘参考。文末附风险声明。


一、痛点引入:为什么你需要懂期权定价?

2026 年 A 股波动率持续走高,上证指数单日涨跌幅超 2% 的天数同比增加 35%。对于持有股票仓位的投资者,如何对冲下行风险成为核心痛点。

期权被称为"金融市场的保险单",但很多量化爱好者面临三个问题:

  1. 定价黑箱:直接用券商软件报价,不知道期权价格是否合理
  2. 希腊值陌生:Delta、Gamma、Vega 等风险指标看不懂,更不知道如何用
  3. 回测缺失:对冲策略无法验证,实盘交学费

本文用 Python 从零实现 Black-Scholes 期权定价模型,包含:

  • 欧式期权定价公式完整实现
  • 5 个希腊值(Delta/Gamma/Vega/Theta/Rho)计算
  • 对冲策略回测框架
  • 实盘应用案例

学完本文,你将能够:

  • 独立计算任意期权的理论价格
  • 用 Delta 对冲降低组合波动
  • 评估期权策略的风险收益比

二、Black-Scholes 模型核心公式

Black-Scholes 模型是期权定价的基石,由 Fischer Black 和 Myron Scholes 于 1973 年提出。

欧式看涨期权定价公式

C=S0N(d1)KerTN(d2)C = S_0 N(d_1) - K e^{-rT} N(d_2)

其中:

  • CC:看涨期权价格
  • S0S_0:标的资产当前价格
  • KK:行权价
  • rr:无风险利率
  • TT:到期时间(年)
  • N()N(\cdot):标准正态分布累积分布函数

d1=ln(S0/K)+(r+σ2/2)TσTd_1 = \frac{\ln(S_0/K) + (r + \sigma^2/2)T}{\sigma\sqrt{T}} d2=d1σTd_2 = d_1 - \sigma\sqrt{T}

欧式看跌期权定价公式

P=KerTN(d2)S0N(d1)P = K e^{-rT} N(-d_2) - S_0 N(-d_1)


三、完整代码实现

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 元,期权价格变动多少方向性风险对冲
GammaDelta 对标的价格的敏感度调整 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}(可能为负,即净收入)")

六、风险声明

⚠️ 重要声明

  1. 本文代码仅供学习和研究使用,不构成投资建议
  2. Black-Scholes 模型假设市场无摩擦、波动率恒定,与实际市场存在差异
  3. 期权交易存在杠杆风险,可能导致本金全部损失
  4. 实盘前请务必进行充分回测和模拟交易
  5. 过往业绩不代表未来表现

七、总结

本文完整实现了:

  1. ✅ Black-Scholes 欧式期权定价模型
  2. ✅ 5 个希腊值(Delta/Gamma/Vega/Theta/Rho)计算
  3. ✅ Delta 对冲策略回测框架
  4. ✅ 实盘应用案例(50ETF 对冲)

核心收获

  • 期权不是赌博工具,而是风险管理工具
  • Delta 对冲可以将方向性风险降低 60%+
  • 对冲成本通常为持仓的 0.5%-2%,相当于"保险费"

下一步学习

  • 美式期权定价(二叉树模型)
  • 波动率曲面构建
  • 多资产组合对冲

互动话题

你在实盘中用过期权对冲吗?效果如何?有没有踩过坑?

欢迎在评论区分享你的经验!


参考来源:Hull《期权、期货及其他衍生产品》、CME 期权交易指南、上交所 50ETF 期权合约规格

声明:本文代码仅供学习参考,不构成投资建议。期权交易有风险,入市需谨慎。