第2节 二叉树计算欧式和美式期权价格

本文介绍了二叉树模型在计算欧式和美式期权价格中的应用。详细阐述了算法原理,包括股票价格变化、概率计算、递推关系,并提供了Python代码实现。同时,给出了具体的计算示例和树形定价的收敛性分析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

第2节 二叉树计算欧式和美式期权价格



1.1 简介



       
考虑期权为股票期权,二叉树是指股票价格在期限内可能的变化路径的图形。

考虑时间段为0至T,对于步数为N的二叉树,在 t = 0 ,    Δ t , . . . , ( N − 1 ) Δ t t=0,\; \Delta t, ...,(N-1)\Delta t t=0,Δt,...,(N1)Δt 的时间节点上股票价格有概率 p p p由当前价格 S t S_t St变为 u S t uS_t uSt,有概率 ( 1 − p ) (1-p) (1p)变为 d S t dS_t dSt。其中 Δ t = T N \Delta t = \frac{T}{N} Δt=NT, u和d分别为上升和下降幅度。当二叉树的步数足够多时,股票价格的最后分布将为对数正态分布。

       
John Hull的《期权、期货及其他衍生产品》中说明了当我们要求没有无风险套利空间,选取 p = e r Δ t − d u − d p=\frac{e^{r\Delta t}-d}{u-d} p=uderΔtd时,期权在当前节点的价格为期权在分叉后价格期望的贴现后价格。此外我们需要选取的 u u u d d d会让股票价格的波动率与几何布朗运动:
d S S = r d t + σ d z \frac{dS}{S} = r dt + \sigma dz SdS=rdt+σdz
相符合。即考虑下列等式,

p u + ( 1 − p ) d = e r Δ t ,      p ( u − 1 ) 2 + ( 1 − p ) ( d − 1 ) 2 − [ p ( u − 1 ) + ( 1 − p ) ( d − 1 ) ] 2 = σ 2 Δ t . pu+(1-p)d = e^{r\Delta t}, \;\; p(u-1)^2+(1-p)(d-1)^2-[p(u-1)+(1-p)(d-1)]^2 = \sigma^2\Delta t . pu+(1p)d=erΔt,p(u1)2+(1p)(d1)2[p(u1)+(1p)(d1)]2=σ2Δt.
d = 1 / u d=1/u d=1/u,我们会得到一个重合的树形。这时忽略 Δ t \Delta t Δt 3 2 \frac{3}{2} 23阶小量后会有
u = e σ Δ t ,      d = e − σ Δ t . u=e^{\sigma\sqrt{\Delta t}}, \;\; d = e^{-\sigma\sqrt{\Delta t}}. u=eσΔt ,d=eσΔt .

       
下面左图和右图分别为一步和多步二叉树分叉过程,多步二叉树中每一个节点的分叉过程都是相同的。
在这里插入图片描述

2.2 二叉树计算期权价格算法

欧式期权价格

  1. 根据给定的股票价格的波动率 σ \sigma σ和无风险利率 r r r,按照上图中公式计算出 u ,    d , u,\;d, u,d p p p,其中 Δ t \Delta t Δt为每一步步长 T / N T/N T/N
  2. 计算出股票价格在树形末端每个节点的价格,如上右图右侧。
  3. 根据期权类型(看涨或看跌),以及期权的执行价格 K K K计算出期权在树形末端的价格分布。
  4. 用期权价格的递推关系计算出前一层节点上期权价格的期望值。期权价格的递推关系为
    f i , j = e − r Δ t ( p f i + 1 , j + 1 + ( 1 − p ) f i + 1 , j )    . f_{i,j} = e^{-r\Delta t}(pf_{i+1,j+1}+(1-p)f_{i+1,j})\;. fi,j=erΔt(pfi+1,j+1+(1p)fi+1,j).
    其中 f i , j f_{i, j} fi,j为期权在 i Δ t i\Delta t iΔt时刻,第 j j j层(由下往上数,从0开始)的价格。
  5. 重复过程4,直到计算出根节点处期权的价格 f 0 , 0 f_{0,0} f0,0

美式期权的价格

       
重复欧式期权价格的计算过程1~3,然后在递推上一层期权价格时考虑可以在该节点执行的情况,具体为:

  1. 根据给定的股票价格的波动率 σ \sigma σ和无风险利率 r r r,按照上图中公式计算出 u ,    d u,\;d u,d p p p
  2. 计算出股票价格在树形末端每个节点的价格。
  3. 根据期权类型(看涨或看跌),以及期权的执行价格 K K K计算出期权在树形末端的价格分布。
  4. 计算出前一层节点上期权价格的期望值。此时需要考虑可以在该节点执行期权,假设期权为看涨期权,则其价格的递推关系为
    f i , j = max ⁡ [ S i , j − K ,    e − r Δ t ( p f i + 1 , j + 1 + ( 1 − p ) f i + 1 , j ) ]    . f_{i,j} = \max{\left[S_{i, j}-K,\;e^{-r\Delta t}(pf_{i+1,j+1}+(1-p)f_{i+1,j})\right]}\;. fi,j=max[Si,jK,erΔt(pfi+1,j+1+(1p)fi+1,j)].
    其中 f i , j f_{i, j} fi,j为期权在 i Δ t i\Delta t iΔt时刻,第 j j j层的价格,    S i , j \;S_{i,j} Si,j为该处的股票价格。
  5. 重复过程4,计算出根节点处期权的价格 f 0 , 0 f_{0,0} f0,0

2.3 计算过程 Python 代码实现

import numpy as np
import math

E = math.e

class Binomial_tree_sim:
    def __init__(self, r, sigma, S_0, K, T, steps, option_type="european", call_or_put="call"):
        """ 用输入参数初始化树。
        """
        self.r = r
        self.sigma = sigma
        self.S_0 = S_0
        self.K = K
        self.T = T
        self.steps = steps
        
        self.option_type = option_type
        self.call_or_put = call_or_put
        
        # 计算出树形分叉参数
        self.dt = self.T/self.steps
        self.u = E**(self.sigma*self.dt**0.5)
        self.d = 1/self.u
        self.p = (E**(self.r*self.dt)-self.d)/(self.u-self.d)
        
        # 将会得到的结果
        self.tree = None
        self.option_price = None
        
        # 计算出一个树形
        self.build_tree()
        
    def build_tree(self):
        """ 计算出股票价格在树形上每个节点的价格。
        """
        self.tree = list()
        for lvl in range(self.steps+1):
            row = list()
            for j in range(lvl+1):
                node = dict()
                node["stock_price"] = self.S_0*self.u**(j)*self.d**(lvl-j)
                node["option_price"] = None
                row.append(node)
            self.tree.append(row)
        return
    
    def calculate_option_price(self):
        """ 计算给定类型期权的价格。
        """
        # 简化参数名称。
        r, K, steps = self.r, self.K, self.steps
        dt, p = self.dt, self.p
        
        # 计算出期权在树形末端的价格。
        for node in self.tree[-1]:
            # 如果是看涨期权。
            if self.call_or_put == "call":
                node["option_price"] = max(node["stock_price"]-K, 0)
            # 如果是看跌期权。
            else:
                node["option_price"] = max(K-node["stock_price"], 0)
        
        # 如果是欧式期权。
        if self.option_type == "european":
            # 递推出树形根节点期权的价格。
            for lvl in range(steps-1, -1, -1):
                for j in range(len(self.tree[lvl])):
                    self.tree[lvl][j]["option_price"] = E**(-r*dt)*(p*self.tree[lvl+1][j+1]["option_price"]+\
                                                    (1-p)*self.tree[lvl+1][j]["option_price"])
        
        # 如果是美式期权,过程同欧式期权,计算节点价格时考虑需不需要在该节点执行。
        else:
            for lvl in range(self.steps-1, -1, -1):
                for j in range(len(self.tree[lvl])):
                    self.tree[lvl][j]["option_price"] = E**(-r*dt)*(p*self.tree[lvl+1][j+1]["option_price"]+\
                                                    (1-p)*self.tree[lvl+1][j]["option_price"])
                    # 考虑要不要这时执行。
                    if self.call_or_put == "call":
                        self.tree[lvl][j]["option_price"] = max(self.tree[lvl][j]["option_price"], \
                                                            self.tree[lvl][j]["stock_price"]-K)
                    else:
                        self.tree[lvl][j]["option_price"] = max(self.tree[lvl][j]["option_price"], \
                                                            K-self.tree[lvl][j]["stock_price"])
        
        self.option_price = self.tree[0][0]["option_price"]

        return 

2.4 相关说明

2.4.1 计算例子

       
考虑一个期限在3年后,执行价格为10的期权。当前股票价格为10,无风险利率为10,股票价格波动率为0.2 。使用10步二叉树,可以如下计算出各种期权价格。

tree_obj = Binomial_tree_sim(0.05, 0.2, 10, 10, 3, 10, option_type="european", call_or_put="call")
tree_obj.calculate_option_price()
print("欧式看涨期权价格为: {:0.4f}".format(tree_obj.option_price))

tree_obj = Binomial_tree_sim(0.05, 0.2, 10, 10, 3, 10, option_type="european", call_or_put="put")
tree_obj.calculate_option_price()
print("欧式看跌期权价格为:{:0.4f}".format(tree_obj.option_price))

tree_obj = Binomial_tree_sim(0.05, 0.2, 10, 10, 3, 10, option_type="american", call_or_put="call")
tree_obj.calculate_option_price()
print("美式看涨期权价格为:{:0.4f}".format(tree_obj.option_price))

tree_obj = Binomial_tree_sim(0.05, 0.2, 10, 10, 3, 10, option_type="american", call_or_put="put")
tree_obj.calculate_option_price()
print("美式看跌期权价格为:{:0.4f}".format(tree_obj.option_price))

输出结果为:

欧式看涨期权价格为: 2.0585
欧式看跌期权价格为:0.6656
美式看涨期权价格为:2.0585
美式看跌期权价格为:0.8563

2.4.2 树形定价收敛情况

       
依旧考虑上面参数的欧式看涨期权,我们可以用解析公式计算出期权价格应该为2.0924。然后我们可以调整树形定价步数,将得到的期权价格和解析解数值进行比较。

X = np.arange(10, 210, 10)
Y = np.array([])
for steps in X:
    tree_obj = Binomial_tree_sim(0.05, 0.2, 10, 10, 3, steps, option_type="european", call_or_put="call")
    tree_obj.calculate_option_price()
    Y = np.append(Y, [tree_obj.option_price])
    
figure = plt.figure()
ax1 = figure.add_subplot(1, 1, 1)

line1, = ax1.plot(X, Y, '-s', color="blue", linewidth=1.5)
line2, = ax1.plot(X, len(X)*[2.0924], '-', color="red", linewidth=1)

ax1.set_xlabel("steps")
ax1.set_ylabel("price")
ax1.set_title("option price vs tree depth")
ax1.axis((10, 200, 2.04, 2.1))

得:
在这里插入图片描述




参考资料:

  1. 《期权、期货及其他衍生产品》,John C. Hull 著,王勇、索吾林译 。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值