MonteCarlo(蒙特卡洛模拟)雪球产品定价

蒙特卡洛模拟(MC)标准雪球定价
摘要由CSDN通过智能技术生成

        大家好,好久没更新了,我准备后面就一些相关场外衍生品的的研报进行复现,不仅是让自己加深对这一领域的理解,也希望国内这个发展迅速但不是特别大的市场能有更多的人能感兴趣甚至加入。这次我先就信达证券于明明老师的《雪球结构定价与风险深度分析》中的第一部分蒙特卡洛模拟对雪球定价进行复现,研报链接如下:

雪球结构定价与风险深度分析.pdf-原创力文档雪球结构定价与风险深度分析.pdf,雪球结构定价与风险深度分析 一、雪球结构简介 雪球(Snowball)结构属于路径依赖型奇异衍生品,其结构相对复杂,但自2019 年开始,雪球这种非保本型收 益凭证受到市场上越来越多的关注,各类金融机构纷纷以不同角色参与其中,雪球在市场中的影响也逐渐增强。 雪球型收益凭证实际是卖出了敲入结构的看跌期权,只要标的不发生大幅下跌,持有该收益凭证的时间越长,获 得票息收益越多,类似于滚雪球一样,只要地面不出现非常大的坑洼,雪球就会越滚越大。 不难发现,雪球类产品之所以受到热捧,与其具有固定收益的特征有https://max.book118.com/html/2021/0724/7006161103003150.shtm原文提供的模拟雪球基本信息如下:

c45513145d5b4655bbff6b52779fd4d9.png

具体雪球产品的多种收益情况和详细内容可以从研报中学习。

c8ff950c78604dbfb54d29a563eee128.png

 这就是MC定价雪球的初始条件设置表,从表中可以得知该雪球的期限为1年,敲出水平为103%,敲入水平为85%,年化票息为20%,无风险利率为3%,标的波动率为13%,每日观察敲入,每月观察敲出,总模拟路径条数为300000。

话不多少,直接开干,蒙特卡洛模拟就是模拟多条路径来计算大数据下的产品价格应该是多少,利用均值来表示。本文代码部分借鉴了一定知乎内容,有兴趣的朋友可以去看看: 雪球定价方法之蒙特卡洛模拟(附Python代码) - 知乎据说雪球最近要将认购门槛提高到1000万,可见其火爆程度。那么今天我们结合研报用蒙特卡洛模拟法来看看现在的合约的票息是否合理,同时对雪球的结构进行梳理。 这里我们用到的研报是信达证券《雪球结构定价与风险…https://zhuanlan.zhihu.com/p/527393555

下面是本文的MonteCarlo模拟标准雪球定价代码:

import numpy as np

def MonteCarlo_Simulation(S0, r, T, vol, times, steps):

    dt = float(T) / steps
    price_paths = np.zeros((steps + 1, times))
    price_paths[0] = S0

    for i in range(1, steps + 1):
        random_seed = np.random.standard_normal(times)
        middle = price_paths[i - 1, 0:times] * np.exp((r - 0.5 * vol ** 2) * dt + vol * np.sqrt(dt) * random_seed)
        uplimit = price_paths[i - 1] * 1.1                                 # 涨停设置
        downlimit = price_paths[i - 1] * 0.9                               # 跌停设置
        trail = np.where(uplimit < middle, uplimit, middle)
        trail = np.where(downlimit > middle, downlimit, trail)
        price_paths[i, 0:times] = trail
    return price_paths

def standard_snowball_pricing(price_paths, coupon, times):
    payoff = np.zeros(times)
    knock_out_times = 0
    knock_in_times = 0
    existence_times = 0
    loss_times = 0
    knockout_m_list = []
    payoff_list = []
    for i in range(times):
        # 收盘价超过敲出线的交易日
        knockout_day = np.where(price_paths[:, i] >= knockout_barrier)
        # 收盘价超出敲出线的观察日(每月观察)
        knockout_mday = knockout_day[0][knockout_day[0] % 21 == 0]
        # 收盘价超出敲出线的观察日(超过封闭期)
        knockout_mday_overlock = knockout_mday[knockout_mday / 21 > lock_period]
        # 收盘价低于敲入线的观察日(每日观察)
        knockin_day = np.where(price_paths[:, i] < knockin_barrier)

        # 情景1:发生过向上敲出
        if len(knockout_mday_overlock) > 0:
            t = knockout_mday_overlock[0]
            payoff[i] = coupon * (t/252) * np.exp(-r * t/252)
            knock_out_times += 1
            knockout_m_list.append(t/21)
            payoff_list.append(payoff[i])

        # 情景2:未敲出且未敲入
        elif len(knockout_mday_overlock) == 0 and len(knockin_day[0]) == 0:
            payoff[i] = coupon * np.exp(-r * T)
            existence_times += 1
            payoff_list.append(payoff[i])

        # 情景3:只发生向下敲入,不发生向上敲出
        elif len(knockin_day[0]) > 0 and len(knockout_mday_overlock) == 0:
            # 只有向下敲入,没有向上敲出
            payoff[i] = 0 if price_paths[-1][i] >= S0 else (price_paths[-1][i] - S0) * np.exp(-r * T)
            knock_in_times += 1
            payoff_list.append(payoff[i])
            if payoff[i] < 0:
                loss_times += 1
        else:
            print(i)
    return payoff, knock_out_times, knock_in_times, existence_times, loss_times, knockout_m_list, payoff_list

if __name__=='__main__':
    # 设置参数
    np.random.seed(1)
    vol = 0.13
    T = 1
    S0 = 1
    r = 0.03
    knockout_barrier = 1.03
    knockin_barrier = 0.85
    times = 300000
    lock_period = 0
    coupon = 0.2
    steps = 252 * T
    price_paths = MonteCarlo_Simulation(S0, r, T, vol, times, steps)

    payoff, knock_out_times, knock_in_times, existence_times, loss_times, knockout_m_list, payoff_list = standard_snowball_pricing(price_paths, coupon, times)
    price = sum(payoff)/len(payoff)
    print('雪球价值: %f' % price)
    print('敲出: %f' % (knock_out_times/times))
    print('未敲入也未敲出: %f' % (existence_times / times))
    print('敲入未敲出: %f' % (knock_in_times/times))
    print('发生亏损: %f' % (loss_times/times))
    print('最大亏损: %f' % (min(payoff_list)))
    print('最大盈利: %f' % (max(payoff_list)))
    print('平均敲出月份: %f' % (sum(knockout_m_list) / len(knockout_m_list)))
    print('平均存续月份: %f' % (((times - len(knockout_m_list)) * 12 + sum(knockout_m_list)) / times))

大家可以利用np.random.seed来进行复现,代码跑出来的结果为:

09b35ac6d6ae49bd824d61786f612e8d.png

研报原文的回测结果如下:

b0f7b1f7f3e34606b07564645948441b.png

可以看出结果大致和研报结果都比较接近,最大的误差在于平均敲出月份,我的结果为3.51,研报结果为2.59,相差了近一个月,希望大家如果能够看出我代码中有什么错误的话,希望不吝指教,后面我也会继续更新PDE方法对雪球定价的研报复现。

 

 

  • 8
    点赞
  • 46
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
Monte Carlo雪球定价的希腊字母计算通常需要进行蒙特卡罗模拟,以估计各个希腊字母的值。以下是一些常见的希腊字母及其计算方法: 1. Delta:Delta指标是衡量资产价格变化对期权价格变化的敏感度,通常通过计算期权价格对标的资产价格的一阶导数来估计。在Monte Carlo模拟中,可以通过在模拟价格路径中对标的资产价格进行微小的变化,并计算对应的期权价格,来估计Delta指标。 2. Gamma:Gamma指标是衡量Delta指标变化率的敏感度,通常通过计算Delta指标对标的资产价格的一阶导数来估计。在Monte Carlo模拟中,可以通过计算Delta指标在不同价格水平上的值,然后对其进行差分来估计Gamma指标。 3. Vega:Vega指标是衡量隐含波动率变化对期权价格变化的敏感度,通常通过计算期权价格对隐含波动率的一阶导数来估计。在Monte Carlo模拟中,可以通过在模拟价格路径中对隐含波动率进行微小的变化,并计算对应的期权价格,来估计Vega指标。 4. Theta:Theta指标是衡量时间变化对期权价格变化的敏感度,通常通过计算期权价格对时间的一阶导数来估计。在Monte Carlo模拟中,可以通过在模拟价格路径中对模拟时间步长进行微小的变化,并计算对应的期权价格,来估计Theta指标。 需要注意的是,Monte Carlo模拟估计的希腊字母值通常会存在一定的误差,因此在实际应用中需要进行一定的调整和修正。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

zr rrr

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

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

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

打赏作者

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

抵扣说明:

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

余额充值