2. 基于Delta中性对冲的做市策略

任务目标

构建一个含期权与标的资产的Delta中性组合,通过动态调整标的持仓使组合Delta趋近于零,并对比不同对冲频率(每日、每周、不对冲)对最终损益的影响。

环境与依赖

本案例使用Python 3.8+,依赖NumPy与SciPy。Black-Scholes公式用于计算期权理论价格与Delta,无需额外数据源,通过模拟标的价格路径完成回测。

核心实现

import numpy as np
from scipy.stats import norm

# ---------- Black-Scholes定价与希腊字母 ----------
def bs_price(S, K, T, r, sigma, option_type='call'):
    if T <= 0:
        return max(0, (S - K) if option_type == 'call' else (K - S))
    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':
        return S * norm.cdf(d1) - K * np.exp(-r * T) * norm.cdf(d2)
    else:
        return K * np.exp(-r * T) * norm.cdf(-d2) - S * norm.cdf(-d1)

def bs_delta(S, K, T, r, sigma, option_type='call'):
    if T <= 0:
        return 1.0 if (S > K and option_type == 'call') or (S < K and option_type == 'put') else 0.0
    d1 = (np.log(S / K) + (r + 0.5 * sigma**2) * T) / (sigma * np.sqrt(T))
    if option_type == 'call':
        return norm.cdf(d1)
    else:
        return norm.cdf(d1) - 1.0

# ---------- 模拟标的价格路径(几何布朗运动) ----------
def simulate_path(S0, mu, sigma, T, steps, seed=42):
    np.random.seed(seed)
    dt = T / steps
    returns = (mu - 0.5 * sigma**2) * dt + sigma * np.sqrt(dt) * np.random.standard_normal(steps)
    path = S0 * np.exp(np.cumsum(returns))
    return np.concatenate(([S0], path))

# ---------- 对冲回测 ----------
def run_hedge_backtest(hedge_freq='daily'):
    # 参数设置
    S0, K, T, r, sigma = 100.0, 100.0, 30/365, 0.02, 0.20
    mu = 0.05
    steps = 30  # 每日一个时间步
    dt = T / steps
    path = simulate_path(S0, mu, sigma, T, steps)
    
    # 持仓:卖出1份看涨期权(做市商义务),持有delta份标的对冲
    option_position = -1  # 卖出1份看涨
    stock_position = 0.0  # 初始无标的持仓
    cash = 0.0
    
    # 记录每日对冲后的组合价值
    portfolio_values = []
    
    for i in range(steps + 1):
        t = i * dt
        remaining_T = T - t
        S = path[i]
        
        # 期权价值(做市商负债)
        option_value = bs_price(S, K, remaining_T, r, sigma, 'call')
        
        # 组合价值 = 现金 + 标的市值 - 期权负债
        portfolio_value = cash + stock_position * S - option_value
        portfolio_values.append(portfolio_value)
        
        if i == steps:
            break
        
        # 计算当前Delta并决定是否调整
        current_delta = bs_delta(S, K, remaining_T, r, sigma, 'call')
        target_stock = option_position * current_delta  # 卖出期权需持有+delta份标的
        
        if hedge_freq == 'daily':
            # 每日调整至Delta中性
            trade = target_stock - stock_position
            cash -= trade * S
            stock_position = target_stock
        elif hedge_freq == 'weekly':
            # 每5个交易日调整一次
            if i % 5 == 0:
                trade = target_stock - stock_position
                cash -= trade * S
                stock_position = target_stock
        # 'none':不调整,保持初始0持仓
    
    # 最终清算:平掉期权与标的
    final_S = path[-1]
    final_option_value = bs_price(final_S, K, 0, r, sigma, 'call')
    final_pnl = cash + stock_position * final_S - final_option_value
    return final_pnl, portfolio_values

# ---------- 执行对比 ----------
if __name__ == '__main__':
    for freq in ['daily', 'weekly', 'none']:
        pnl, _ = run_hedge_backtest(freq)
        print(f'{freq}: final PnL = {pnl:.4f}')

运行方式

将上述代码保存为 delta_hedge.py,在命令行执行:

python delta_hedge.py

验证方法与判定标准

程序输出三种对冲频率下的最终损益。判定逻辑:

  • Delta中性验证:每日对冲策略的持仓Delta应始终接近零(代码中通过每次调仓至目标Delta实现),最终损益应显著小于不hedge的裸卖空期权损益波动。
  • 对冲频率影响:预期输出中daily与weekly的PnL值应小于none,且daily的PnL方差通常低于weekly(因对冲更频繁,Gamma风险暴露更小)。
  • 数值合理性:由于模拟路径固定(seed=42),每次运行结果应完全一致。若修改seed,结果变化但相对关系不变。

示例输出(基于固定随机种子,非实测结果):

daily: final PnL = 0.3124
weekly: final PnL = -0.1876
none: final PnL = -2.8451

以上仅为演示格式,实际数值取决于模拟路径。通过条件:none的PnL值明显大于daily与weekly,且daily与weekly的PnL处于同一量级但不同。

关键说明

本案例采用固定波动率与无交易成本的简化模型,聚焦Delta对冲机制本身。实际做市中还需考虑交易成本、波动率微笑与订单流不平衡,但核心对冲逻辑与本实现一致。若需评估真实市场影响,可将simulate_path替换为历史行情数据,并在调仓时扣除手续费。