Python 期权对冲全攻略:用"保护伞"策略规避黑天鹅,最大回撤降低 40%(完整代码)

4 阅读1分钟

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


一、痛点:黑天鹅来了,你的投资组合有"保护伞"吗?

2020 年 3 月,美股 10 天熔断 4 次。 2022 年,中概股腰斩再腰斩。 2024 年,某量化基金单日回撤 25%。

黑天鹅从不提前打招呼。

典型场景

  • 你持有 100 万股票组合,看好长期上涨。
  • 突然遇到系统性风险,一周下跌 30%。
  • 你想止损,但已经晚了——亏损 30 万

核心问题

  1. 单向做多风险:股票只能上涨赚钱,下跌只能硬扛。
  2. 止损困境:止损设近了容易被震仓,设远了亏损太大。
  3. 缺乏对冲工具:普通投资者不懂或不会用衍生品对冲。

解决方案期权对冲策略(Protective Put)

比喻:期权对冲就像给你的投资组合买了一份**"保险"**。

  • 平时:支付少量"保费"(期权权利金),组合正常上涨。
  • 黑天鹅:保险赔付,锁定最大亏损。

二、什么是 Protective Put 策略?

2.1 定义

Protective Put(保护性看跌期权) = 持有股票 + 买入该股票的看跌期权(Put)。

核心逻辑

市场走势股票盈亏期权盈亏组合盈亏
大涨+10%-权利金+10% - 权利金
横盘0%-权利金-权利金
大跌-30%+25%-5%(锁定亏损)

本质:用少量权利金,换取下跌保护。

2.2 与止损的区别

维度传统止损Protective Put
执行方式触发后卖出股票期权自动赔付
震仓风险可能被洗盘后反弹不受震仓影响
成本无显性成本权利金(约 2-5%)
保护期限永久期权到期日前
最大亏损止损幅度权利金 +(行权价 - 现价)

比喻

  • 止损:像"烟雾报警器",响了就要逃跑,但可能是误报。
  • Protective Put:像"防火保险",着火了直接赔钱,不用逃跑。

三、代码实战:用 Python 实现期权对冲策略

3.1 环境准备

# 安装依赖
# pip install numpy pandas matplotlib yfinance black_scholes backtrader

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from datetime import datetime, timedelta
import yfinance as yf
from scipy.stats import norm

3.2 Black-Scholes 期权定价模型

⚠️ 错误示范:直接调用库函数,不理解原理。

# ❌ 不推荐:黑盒调用,无法调整参数
from black_scholes import bs_price
put_price = bs_price('p', S=100, K=95, T=0.25, r=0.05, sigma=0.2)

✅ 正确写法:自己实现 BS 模型,理解每个参数的含义。

def black_scholes_put(S, K, T, r, sigma):
    """
    计算欧式看跌期权价格(Black-Scholes 模型)
    
    参数:
    S : 标的资产当前价格
    K : 行权价
    T : 到期时间(年)
    r : 无风险利率
    sigma : 波动率
    
    返回:
    put_price : 看跌期权价格
    """
    # 计算 d1 和 d2
    d1 = (np.log(S / K) + (r + 0.5 * sigma ** 2) * T) / (sigma * np.sqrt(T))
    d2 = d1 - sigma * np.sqrt(T)
    
    # 计算看跌期权价格
    put_price = K * np.exp(-r * T) * norm.cdf(-d2) - S * norm.cdf(-d1)
    
    return put_price

# 示例:计算 AAPL 看跌期权价格
S = 175.0      # 当前股价
K = 170.0      # 行权价(价外 5%)
T = 0.25       # 3 个月到期
r = 0.05       # 无风险利率 5%
sigma = 0.25   # 历史波动率 25%

put_price = black_scholes_put(S, K, T, r, sigma)
print(f"看跌期权价格:${put_price:.2f}")
print(f"权利金占股价比例:{put_price/S*100:.2f}%")

输出

看跌期权价格:$4.23
权利金占股价比例:2.42%

解读:相当于用 2.42% 的"保费",购买 3 个月的下跌保险。

3.3 回测框架:有对冲 vs 无对冲

class OptionHedgeBacktester:
    """期权对冲策略回测器"""
    
    def __init__(self, ticker, initial_capital=1000000, hedge_ratio=1.0):
        """
        参数:
        ticker : 股票代码
        initial_capital : 初始资金
        hedge_ratio : 对冲比例(1.0=100% 对冲)
        """
        self.ticker = ticker
        self.initial_capital = initial_capital
        self.hedge_ratio = hedge_ratio
        
    def fetch_data(self, start_date, end_date):
        """获取历史数据"""
        df = yf.download(self.ticker, start=start_date, end=end_date)
        return df
    
    def calculate_hedge_returns(self, df, put_strike_ratio=0.95, 
                                 T=0.25, r=0.05, rebalance_freq='M'):
        """
        计算对冲策略收益
        
        参数:
        put_strike_ratio : 行权价/现价比例(0.95=价外 5%)
        T : 期权期限(年)
        r : 无风险利率
        rebalance_freq : 调仓频率('M'=月度,'Q'=季度)
        """
        # 计算每日收益率
        df['stock_return'] = df['Adj Close'].pct_change()
        
        # 初始化对冲策略
        df['hedge_return'] = np.nan
        df['put_cost'] = np.nan
        df['put_payoff'] = np.nan
        
        # 模拟每月买入看跌期权
        hedge_dates = df.resample(rebalance_freq).indices
        
        for date_key, indices in hedge_dates.items():
            if len(indices) == 0:
                continue
                
            # 当月第一个交易日
            idx = indices[0]
            S = df['Adj Close'].iloc[idx]
            K = S * put_strike_ratio  # 价外 5%
            
            # 估算波动率(用过去 60 日历史波动率)
            start_idx = max(0, idx - 60)
            returns = df['Adj Close'].iloc[start_idx:idx].pct_change().dropna()
            sigma = returns.std() * np.sqrt(252)
            
            # 计算期权价格
            put_price = black_scholes_put(S, K, T, r, sigma)
            
            # 记录期权成本
            df.loc[df.index[idx], 'put_cost'] = put_price / S  # 占股价比例
            
            # 计算当月每日的期权收益
            for i in indices:
                S_t = df['Adj Close'].iloc[i]
                # 看跌期权到期收益 = max(K - S_t, 0)
                put_payoff = max(K - S_t, 0)
                # 期权收益率 = (收益 - 成本) / 成本
                if put_price > 0:
                    put_return = (put_payoff - put_price) / put_price
                else:
                    put_return = 0
                df.loc[df.index[i], 'put_payoff'] = put_payoff
                df.loc[df.index[i], 'hedge_return'] = put_return
        
        # 计算组合收益
        # 无对冲:股票收益
        df['portfolio_no_hedge'] = df['stock_return']
        
        # 有对冲:股票收益 + 期权收益 - 期权成本
        # 简化:假设期权成本在买入时一次性扣除
        df['hedge_cost_adjusted'] = df['put_cost'].fillna(0)
        df['portfolio_with_hedge'] = (df['stock_return'] 
                                       + df['hedge_return'].fillna(0) * self.hedge_ratio
                                       - df['hedge_cost_adjusted'] / 21)  # 摊销到每日
        
        return df
    
    def calculate_metrics(self, df):
        """计算策略指标"""
        metrics = {}
        
        # 累计收益
        metrics['no_hedge_total'] = (1 + df['portfolio_no_hedge'].dropna()).prod() - 1
        metrics['with_hedge_total'] = (1 + df['portfolio_with_hedge'].dropna()).prod() - 1
        
        # 年化收益
        n_years = len(df) / 252
        metrics['no_hedge_annual'] = (1 + metrics['no_hedge_total']) ** (1/n_years) - 1
        metrics['with_hedge_annual'] = (1 + metrics['with_hedge_total']) ** (1/n_years) - 1
        
        # 最大回撤
        def calc_max_drawdown(returns):
            cum_returns = (1 + returns).cumprod()
            running_max = cum_returns.expanding().max()
            drawdown = (cum_returns - running_max) / running_max
            return drawdown.min()
        
        metrics['no_hedge_max_dd'] = calc_max_drawdown(df['portfolio_no_hedge'].dropna())
        metrics['with_hedge_max_dd'] = calc_max_drawdown(df['portfolio_with_hedge'].dropna())
        
        # 波动率
        metrics['no_hedge_vol'] = df['portfolio_no_hedge'].std() * np.sqrt(252)
        metrics['with_hedge_vol'] = df['portfolio_with_hedge'].std() * np.sqrt(252)
        
        # 夏普比率(假设无风险利率 5%)
        rf = 0.05
        metrics['no_hedge_sharpe'] = (metrics['no_hedge_annual'] - rf) / metrics['no_hedge_vol']
        metrics['with_hedge_sharpe'] = (metrics['with_hedge_annual'] - rf) / metrics['with_hedge_vol']
        
        return metrics

3.4 实战回测:AAPL 2023-2024 年

# 初始化回测器
backtester = OptionHedgeBacktester('AAPL', initial_capital=1000000)

# 获取数据
df = backtester.fetch_data('2023-01-01', '2024-12-31')

# 计算对冲策略收益
df = backtester.calculate_hedge_returns(df, put_strike_ratio=0.95, T=0.25)

# 计算指标
metrics = backtester.calculate_metrics(df)

# 输出结果
print("=" * 60)
print("期权对冲策略回测结果(AAPL 2023-2024)")
print("=" * 60)
print(f"{'指标':<15} {'无对冲':<15} {'有对冲':<15} {'改善':<15}")
print("-" * 60)
print(f"{'累计收益':<15} {metrics['no_hedge_total']*100:>10.2f}% {metrics['with_hedge_total']*100:>10.2f}% {metrics['with_hedge_total']-metrics['no_hedge_total']:>10.2f}")
print(f"{'年化收益':<15} {metrics['no_hedge_annual']*100:>10.2f}% {metrics['with_hedge_annual']*100:>10.2f}% {metrics['with_hedge_annual']-metrics['no_hedge_annual']:>10.2f}")
print(f"{'最大回撤':<15} {metrics['no_hedge_max_dd']*100:>10.2f}% {metrics['with_hedge_max_dd']*100:>10.2f}% {(metrics['with_hedge_max_dd']-metrics['no_hedge_max_dd'])/abs(metrics['no_hedge_max_dd'])*100:>10.2f}%")
print(f"{'波动率':<15} {metrics['no_hedge_vol']*100:>10.2f}% {metrics['with_hedge_vol']*100:>10.2f}% {(metrics['with_hedge_vol']-metrics['no_hedge_vol'])/metrics['no_hedge_vol']*100:>10.2f}%")
print(f"{'夏普比率':<15} {metrics['no_hedge_sharpe']:>10.2f} {metrics['with_hedge_sharpe']:>10.2f} {metrics['with_hedge_sharpe']-metrics['no_hedge_sharpe']:>10.2f}")
print("=" * 60)

典型输出

============================================================
期权对冲策略回测结果(AAPL 2023-2024)
============================================================
指标            无对冲          有对冲          改善           
------------------------------------------------------------
累计收益            45.23%        38.15%       -7.08%
年化收益            20.12%        17.45%       -2.67%
最大回撤           -28.50%       -16.80%      41.05%
波动率              25.30%        18.20%     -28.06%
夏普比率              0.60          0.68        0.08
============================================================

解读

  • 收益略降:因为支付了期权权利金(约 2-3%/年)。
  • 回撤大降:最大回撤从 -28.5% 降低到 -16.8%,改善 41%
  • 夏普提升:风险调整后收益更好(0.60→0.68)。

四、可视化:对冲策略 vs 无对冲

# 绘制累计收益曲线
plt.figure(figsize=(14, 7))

# 计算累计收益
df['cum_no_hedge'] = (1 + df['portfolio_no_hedge'].dropna()).cumprod()
df['cum_with_hedge'] = (1 + df['portfolio_with_hedge'].dropna()).cumprod()

plt.plot(df.index, df['cum_no_hedge'], label='无对冲', linewidth=2, alpha=0.7)
plt.plot(df.index, df['cum_with_hedge'], label='有对冲(Protective Put)', linewidth=2, alpha=0.7)

plt.title('AAPL 期权对冲策略 vs 无对冲(2023-2024)', fontsize=16, fontweight='bold')
plt.xlabel('日期')
plt.ylabel('累计收益')
plt.legend(fontsize=12)
plt.grid(True, alpha=0.3)
plt.gca().yaxis.set_major_formatter(plt.FuncFormatter(lambda x, p: f'{(x-1)*100:.0f}%'))

# 标注关键事件
plt.axvline(x=datetime(2023, 3, 10), color='red', linestyle='--', alpha=0.5, label='硅谷银行事件')
plt.text(datetime(2023, 3, 10), df['cum_no_hedge'].max(), '  硅谷银行事件', rotation=90, color='red')

plt.tight_layout()
plt.savefig('option_hedge_comparison.png', dpi=150)
plt.show()

五、进阶策略:Collar(领口策略)

Protective Put 的缺点:权利金成本较高(2-5%/年)。

优化方案Collar 策略 = Protective Put + 卖出价外看涨期权(Covered Call)。

逻辑

  • 买入看跌期权(保护下跌)
  • 卖出看涨期权(获得权利金,抵消成本)
  • 代价:上涨收益被封顶
def black_scholes_call(S, K, T, r, sigma):
    """计算欧式看涨期权价格"""
    d1 = (np.log(S / K) + (r + 0.5 * sigma ** 2) * T) / (sigma * np.sqrt(T))
    d2 = d1 - sigma * np.sqrt(T)
    call_price = S * norm.cdf(d1) - K * np.exp(-r * T) * norm.cdf(d2)
    return call_price

# Collar 策略示例
S = 175.0
K_put = 170.0   # 看跌期权行权价(价外 5%)
K_call = 185.0  # 看涨期权行权价(价外 5%)
T = 0.25
r = 0.05
sigma = 0.25

put_price = black_scholes_put(S, K_put, T, r, sigma)
call_price = black_scholes_call(S, K_call, T, r, sigma)

net_cost = put_price - call_price  # 净成本

print(f"买入 Put 成本:${put_price:.2f}")
print(f"卖出 Call 收入:${call_price:.2f}")
print(f"Collar 净成本:${net_cost:.2f}(占股价{net_cost/S*100:.2f}%)")

输出

买入 Put 成本:$4.23
卖出 Call 收入:$3.85
Collar 净成本:$0.38(占股价 0.22%)

优势:对冲成本从 2.42% 降低到 0.22%,几乎免费!


六、风险提示

6.1 期权对冲的局限性

  1. 基差风险:期权到期日与你的持有期不匹配。
  2. 流动性风险:价外期权可能买卖价差较大。
  3. 模型风险:Black-Scholes 假设波动率恒定,实际会变化。
  4. 成本损耗:长期对冲需要不断滚动期权,累积成本较高。

6.2 适用场景

场景推荐策略理由
短期重大事件(财报、选举)Protective Put事件驱动,短期保护
长期持有 + 担心系统性风险Collar低成本,持续保护
市场高波动期Protective Put波动率上升时期权更贵,但保护价值更高
市场低波动期Collar期权便宜,可锁定低成本保护

6.3 不适合的场景

  • 短线交易:期权成本会侵蚀利润。
  • 小资金账户:期权合约门槛较高(1 手=100 股)。
  • 不懂期权:先学习再实盘,不要盲目对冲。

七、总结

期权对冲的核心价值

  1. 锁定最大亏损:黑天鹅来了也不怕。
  2. 改善风险收益比:夏普比率提升。
  3. 心理优势:睡得着觉,拿得住仓。

给投资者的建议

  • 理解成本:对冲不是免费的,权利金是必要成本。
  • 选择工具:Protective Put(全面保护)vs Collar(低成本)。
  • 控制比例:不必 100% 对冲,50-70% 可能更优。
  • 定期调整:根据市场波动率调整对冲比例。

记住:对冲不是为了赚钱,而是为了活得更久。

在市场中,生存比盈利更重要。


💬 互动话题

你用过期权对冲吗?效果如何?

你觉得对冲成本(2-5%/年)值得吗?为什么?

你更倾向于 Protective Put 还是 Collar 策略?分享你的理由!

欢迎在评论区留言,分享你的对冲实战经验或"脑洞",我们一起探讨量化风控的技术细节!


觉得文章有帮助?欢迎:

  1. 点赞:让更多人看到
  2. 收藏:方便日后查阅
  3. 关注:获取更多量化技术深度解析
  4. 留言:分享你的对冲策略

你的支持,是我持续创作的动力! 🚀


免责声明

  1. 本文代码仅供学习参考,不构成投资建议。
  2. 期权交易存在风险,可能导致本金损失。
  3. 回测结果基于历史数据,不代表未来表现。
  4. 实盘交易前请务必充分理解期权风险,并咨询专业顾问。