波动率恒定模型下的delta对冲模拟实验

       最近在学习delta对冲的相关内容,找到一篇财通证券在19年发布的《金融工程:场外期权专题之三——期权对冲方案设计》研报,里面有提到波动率恒定情况下的对冲模拟实验。

研报链接如下:

2019-04-21_财通证券_场外期权专题之三:期权对冲方案设计 - 道客巴巴 (doc88.com)http://www.doc88.com/p-1901752947005.html

原文提到期权的对冲成本主要分为 3 部分:

第一部分来自于动态持有 delta 份股指期货带来的资金损益。delta 对冲在具体的操作中就是 delta 升高的时候买入股指期货,delta 降低的时候卖出股指期货,那么,在这一过程中由于高买低卖产生的损失以及到期日的支付 K*(sign(s-k))就近似于期权费。

第二部分来自于调整股指期货持仓产生的交易费用。由于期权 delta 在股价出现变动时会动态调整,那么,由于每天股指期货的持仓 都会出现变化,期权复制会带来一笔交易费用。

第三部分来自于保证金的利息支出。

 

      原文的假设是:我们假定标的价格满足几何布朗运动,使用蒙特卡洛方法模拟出 1000 条路径,之后再分别计算在这 1000 条路径下进行对冲的持仓损益。我们假定:
S0 = 1;
T = 0.25;
K = 1;
Sigma = 0.2;
r = 0.05;
交易费率取万分之六
根据以上参数得到了 1000 条股价的路径:下面是部分股价路径
watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAenIgcnJy,size_20,color_FFFFFF,t_70,g_se,x_16

 对于这 1000 条路径,我们分别计算了每条路径相应的期权对冲组合的对冲损益,交易成本,资金占用成本以及无法被对冲的期权 Gamma 与 Theta 损益。

原文对冲结果如下:

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAenIgcnJy,size_20,color_FFFFFF,t_70,g_se,x_16

因此 我希望也进行一个对冲模拟实验,其中gamma损益和theta损益部分我参照了两篇知乎文章,基本公式为

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAenIgcnJy,size_20,color_FFFFFF,t_70,g_se,x_16

两篇知乎文章链接如下:(15 条消息) 想做期权损益的归因分析,有人能教教我吗? - 知乎 (zhihu.com)https://www.zhihu.com/question/423523791/answer/1504613138

期权价格变动之Greek字母归因分析 - 知乎 (zhihu.com)https://zhuanlan.zhihu.com/p/125100275话不多说,直接上代码,,,

首先是关于BSM的模型,之前的文章提到了delta和看涨期权价值的BSM模型代码,下面是关于gamma和theta_call的代码

from math import log, sqrt, exp
from scipy import stats
import numpy as np

class BSMOptionValuation:
    def __init__(self, S0, K, T, r, sigma,  div=0.0)
        self.S0 = float(S0)
        self.K = float(K)
        self.T = float(T)
        self.r = float(r)
        self.sigma = float(sigma)
        self.div = float(div)
        self.d1 = ((log(self.S0 / self.K) + (self.r - self.div + 0.5 * self.sigma ** 2) * self.T) / (self.sigma * sqrt(self.T)))
        self.d2 = self.d1 - self.sigma * sqrt(self.T)
    
    def gamma(self):
        gamma = exp(-self.div * self.T) * stats.norm.pdf(self.d1) / (self.S0 * self.sigma * sqrt(self.T))
        return gamma

    def theta(self):
        self.theta_part1 = self.div * self.S0 * exp(-self.div * self.T) * stats.norm.cdf(self.d1)
        self.theta_part2 = self.r * self.K * stats.norm.cdf(self.d2)*exp(-self.r * self.T)
        self.theta_part3 = (self.S0 * exp(-self.div * self.T) * stats.norm.pdf(self.d1) * self.sigma) / (2 * sqrt(self.T))
        theta_call = self.theta_part1 - self.theta_part2 - self.theta_part3
        theta_put = theta_call + self.r * self.K * exp(-self.r * self.T) - self.div * self.S0 * exp(-self.div * self.T)
        return theta_call,theta_put

然后开始蒙特卡洛模拟实验,代码如下:

import math
import datetime
import numpy as np
import pandas as pd
from scipy.stats import norm
from bsm import *
import matplotlib.pyplot as plt

if __name__ == '__main__':
    
    # 图像绘制基本设置
    plt.rcParams['font.sans-serif'] = ['SimHei']
    plt.rcParams['axes.unicode_minus'] = False
    plt.rcParams['xtick.direction'] = 'in'
    plt.rcParams['ytick.direction'] = 'in'

    # 1.波动率恒定模型下对冲模拟
    # 给定期权参数
    S0 = 1                                        # 标的初始价格
    K = 1                                         # 标的行权价
    T = 0.25                                      # 期权有效期
    r = 0.05                                      # 无风险利率
    sigma = 0.2                                   # 波动率
    feerate = 6/10000                             # 交易费率

    option = BSMOptionValuation(S0, K, T, r, sigma)  # 构造BSM模型下的初始期权

    times = 1000                                  # 模拟路径数
    simulation_steps = 63                         # 单条路径步数,等于252/4=63

    dt = T / simulation_steps
    random_seed = np.random.standard_normal((simulation_steps, times))

    # 蒙特卡洛模拟股票价格,并进行绘制
    montecarlo_path = S0 * np.exp(np.cumsum((r - 0.5 * sigma ** 2) * dt + sigma * sqrt(dt) * random_seed, axis=0))
    initial_row = np.ones((1, times))
    stock_price_paths = np.insert(montecarlo_path, 0, values=initial_row, axis=0)
    df = pd.DataFrame(stock_price_paths)
    df.plot()
    plt.legend().remove()
    plt.show()

蒙特卡洛模拟结果如图:

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAenIgcnJy,size_20,color_FFFFFF,t_70,g_se,x_16

接着进行对冲,计算各项成本:

    # 初始值和结构设定
    initial_delta = option.delta()[0]
    initial_gamma = option.gamma()
    initial_theta = option.theta()[0]
    expire_time= np.append((np.ones((simulation_steps , 1)) * dt).cumsum()[::-1],0)
    hedge_account = np.zeros((simulation_steps + 1, times))                   # 对冲账户
    feerate_account = np.zeros((simulation_steps , times))                    # 交易费账户
    interest = np.zeros((simulation_steps, times))                            # 保证金利息
    gamma_account = np.zeros((simulation_steps, times))                       # Gamma损益
    theta_account = np.zeros((simulation_steps + 1, times))                   # Theta损益
    delta = np.zeros((simulation_steps + 1, times))
    gamma = np.zeros((simulation_steps + 1, times))
    theta = np.zeros((simulation_steps + 1, times))

    # 模拟1000次
    for simulation in range(times):
        stock_price = stock_price_paths[:, simulation].reshape((simulation_steps + 1, 1))

        for step in range(simulation_steps + 1):
            # 开仓
            delta[0, simulation] = initial_delta
            gamma[0, simulation] = initial_gamma
            theta[0, simulation] = initial_theta
            hedge_account[0, simulation] = 0
            feerate_account[0, simulation] = 0
            interest[0, simulation] = delta[0, simulation] * stock_price_paths[0, simulation] * r * dt
            gamma_account[0, simulation] = 0
            theta_account[0, simulation] = 0

            # 对冲
            if step in range(1, simulation_steps):
                delta[step, simulation] = \
                BSMOptionValuation(stock_price_paths[step, simulation], K, expire_time[step], r, sigma).delta()[0]

                gamma[step, simulation] = \
                BSMOptionValuation(stock_price_paths[step, simulation], K, expire_time[step], r, sigma).gamma()

                theta[step, simulation] = \
                BSMOptionValuation(stock_price_paths[step, simulation], K, expire_time[step], r, sigma).theta()[0]

                hedge_account[step, simulation] = hedge_account[step-1, simulation] - \
                delta[step - 1, simulation] * (stock_price_paths[step, simulation] - stock_price_paths[step - 1,simulation])

                interest[step, simulation] = interest[step - 1, simulation] + \
                delta[step, simulation] * stock_price_paths[step, simulation] * r * dt

                feerate_account[step, simulation] = feerate_account[step - 1, simulation] + feerate * \
                abs((delta[step, simulation] - delta[step - 1, simulation]) * stock_price_paths[step, simulation])

                gamma_account[step, simulation] = gamma_account[step - 1, simulation] + \
                0.5 * gamma[step, simulation] * (stock_price_paths[step, simulation] - stock_price_paths[step - 1, simulation]) ** 2

                theta_account[step, simulation] = theta_account[step - 1,simulation] + theta[step - 1, simulation] * dt

            # 结算
            if step == simulation_steps:
                if stock_price_paths[step, simulation] > K:
                    hedge_account[step, simulation] = hedge_account[step - 1, simulation] - delta[step - 1, simulation] * \
                    (stock_price_paths[step, simulation] - stock_price_paths[step - 1, simulation]) + (stock_price_paths[step, simulation] - K)
                elif stock_price_paths[step, simulation] <= K:
                    hedge_account[step, simulation] = hedge_account[step - 1, simulation] - delta[step - 1, simulation] * \
                    (stock_price_paths[step, simulation] - stock_price_paths[step - 1, simulation])
                theta_account[step, simulation] = theta_account[step - 1,simulation] + theta[step - 1, simulation] * dt

    # 对冲后得到的各项结果
    hedge_cost = sum(hedge_account[-1,:]) / times
    feerate_cost = sum(feerate_account[-1, :]) / times
    interest_cost = sum(interest[-1, :]) / times
    gamma_cost = sum(gamma_account[-1, :]) / times
    theta_cost = sum(theta_account[-1, :]) / times
    print(hedge_cost,feerate_cost,interest_cost,gamma_cost,theta_cost)

 最终结果如下:

C:\Users\ys2005\PycharmProjects\pythonProject1\venv\Scripts\python.exe C:/Users/ys2005/PycharmProjects/pythonProject1/hedge_constant_vol.py
0.03973394785925671 0.0014791526966309774 0.007138575105098588 0.019029334338750092 -0.026088057013953066

我模拟出的结果分别为对冲头寸损益0.0397;交易费0.0015;资金占用费0.0071;Gamma损失为0.0190;Theta损失为-0.0261

正如原文解释,对冲头寸损益为0.0397,低于通过波动率估计得到的期权价格0.0461,其中的差异可以用卖出期权带来的theta安全垫收益超出gamma带来的损失进行解释。

PS:我的theta损益和原文一样,都采用了252个交易日的假设,所以每日的theta损益时长用dt来表示,但是参考知乎大佬的文章解释,其实应该用365个自然日来进行假设,因为期权无时无刻不在decay,因为即便周末也会有信息会被price in,并且资金成本是每天都算的,因此周末虽然market 不开市,但是到了周一,期权的time decay是按照三天算的。

 

 

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zr rrr

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值