动态对冲策略
动态对冲策略:波动率敏感性分析,Delta、Gamma、Theta、Vega和Rho的计算;交易成本模型调整头寸的成本;平均收益、标准差和最大回撤;
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import norm
# 设置matplotlib使用支持中文的字体(例如SimHei)
plt.rcParams['font.sans-serif'] = ['SimHei'] # 使用黑体
plt.rcParams['axes.unicode_minus'] = False # 正常显示负号
# 参数设定
risk_free_rate = 0.05
implied_volatility = 0.2
actual_volatility = 0.3
init_stock_price = 100
strike_price = 100
T = 1
simulation_steps = 1000
simulation_times = 10
dt = T / simulation_steps
random_seed = np.random.standard_normal((simulation_steps, simulation_times))
# Monte Carlo模拟标的价格路径
stock_price_paths = init_stock_price * np.exp(
np.cumsum((risk_free_rate - 0.5 * actual_volatility ** 2) * dt + actual_volatility * np.sqrt(dt) * random_seed, axis=0))
# Black-Scholes公式计算欧式看涨期权价格
def get_option_price(S, T, K, sigma, rf, option_type):
if T == 0:
return max(S - K, 0) if option_type == "Call" else max(K - S, 0)
d1 = (np.log(S / K) + (rf + 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(-rf * T) * norm.cdf(d2)
else:
return K * np.exp(-rf * T) * norm.cdf(-d2) - S * norm.cdf(-d1)
# 计算Delta值和其他Greeks
def get_greeks(S, T, K, sigma, rf, option_type):
d1 = (np.log(S / K) + (rf + 0.5 * sigma ** 2) * T) / (sigma * np.sqrt(T))
d2 = d1 - sigma * np.sqrt(T)
delta = norm.cdf(d1) if option_type == "Call" else norm.cdf(d1) - 1
gamma = norm.pdf(d1) / (S * sigma * np.sqrt(T))
theta = -(S * norm.pdf(d1) * sigma / (2 * np.sqrt(T))) - rf * K * np.exp(-rf * T) * norm.cdf(d2)
vega = S * norm.pdf(d1) * np.sqrt(T)
rho = K * T * np.exp(-rf * T) * norm.cdf(d2)
return {'Delta': delta, 'Gamma': gamma, 'Theta': theta, 'Vega': vega, 'Rho': rho}
# 动态对冲策略
def dynamic_hedging(stock_prices, strike_price, implied_volatility, risk_free_rate, option_type, dt, cost_per_trade=0.01):
steps = len(stock_prices)
deltas = np.zeros(steps)
cash_account = np.zeros(steps)
for step in range(steps):
if step == 0:
greeks = get_greeks(stock_prices[step], T - step*dt, strike_price, implied_volatility, risk_free_rate, option_type)
deltas[step] = greeks['Delta']
cash_account[step] = -deltas[step] * stock_prices[step]
else:
old_delta = deltas[step-1]
greeks = get_greeks(stock_prices[step], T - step*dt, strike_price, implied_volatility, risk_free_rate, option_type)
new_delta = greeks['Delta']
deltas[step] = new_delta
adjustment_cost = abs(old_delta - new_delta) * stock_prices[step] * cost_per_trade
cash_account[step] = cash_account[step-1] * np.exp(risk_free_rate * dt) + old_delta * stock_prices[step-1] - new_delta * stock_prices[step] - adjustment_cost
return cash_account, deltas
# 波动率敏感性分析
volatility_pairs = [(0.2, 0.3), (0.25, 0.35), (0.3, 0.4)]
results = {pair: [] for pair in volatility_pairs} # 初始化results为每个波动率对一个空列表
for iv, av in volatility_pairs:
cumulative_pnl_list = []
for sim in range(simulation_times):
stock_price_path = stock_price_paths[:, sim]
cash_account, deltas = dynamic_hedging(stock_price_path, strike_price, iv, risk_free_rate, "Call", dt)
final_pnl = cash_account[-1] + deltas[-1] * stock_price_path[-1] + get_option_price(stock_price_path[-1], 0, strike_price, iv, risk_free_rate, "Call")
cumulative_pnl_list.append(final_pnl)
results[(iv, av)] = cumulative_pnl_list # 存储每个波动率组合下的所有模拟结果
# 结果统计分析
mean_pnl = {k: np.mean(v) for k, v in results.items()}
std_dev_pnl = {k: np.std(v) for k, v in results.items()}
max_drawdown = {k: np.max(np.maximum.accumulate(v) - np.array(v)) if len(v) > 1 else 0 for k, v in results.items()}
# 创建图形和子图
fig, axs = plt.subplots(3, figsize=(10, 12))
# 绘制模拟价格走势图表
axs[0].plot(stock_price_paths[:, :], lw=1.5)
axs[0].set_xlabel('时间')
axs[0].set_ylabel('价格')
axs[0].set_title('模拟价格走势')
# 绘制累积收益图
for (iv, av), pnl_list in results.items():
cumulative_pnl = np.cumsum(pnl_list)
axs[1].plot(np.arange(1, len(cumulative_pnl) + 1), cumulative_pnl, label=f'IV:{iv}, AV:{av}')
axs[1].set_xlabel('Simulation')
axs[1].set_ylabel('Cumulative PnL')
axs[1].set_title('Dynamic Hedging Cumulative Profit and Loss')
axs[1].legend()
# 绘制统计分析结果
x = np.arange(len(volatility_pairs))
width = 0.2
axs[2].bar(x - width, [mean_pnl[k] for k in volatility_pairs], width, label='Mean PnL')
axs[2].bar(x, [std_dev_pnl[k] for k in volatility_pairs], width, label='Std Dev PnL')
axs[2].bar(x + width, [max_drawdown[k] for k in volatility_pairs], width, label='Max Drawdown')
axs[2].set_xticks(x)
axs[2].set_xticklabels([f'IV:{iv}, AV:{av}' for iv, av in volatility_pairs])
axs[2].legend()
axs[2].set_title('Statistical Analysis of Results')
plt.tight_layout()
plt.show()
print("波动率组合的结果统计:")
for (iv, av), mean in mean_pnl.items():
print(f"隐含波动率: {iv}, 实际波动率: {av} -> 平均PnL: {mean}, 标准差: {std_dev_pnl[(iv, av)]}, 最大回撤: {max_drawdown[(iv, av)]}")