news 2026/9/15 17:23:16

二叉树模型实战:从无套利定价到美式期权与工程实现

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
二叉树模型实战:从无套利定价到美式期权与工程实现

先抛个反直觉的结论:在很多真实的定价场景里,二叉树模型(Binomial Tree)比Black-Scholes公式更常用。你可能觉得二叉树只是教科书里用来过渡到连续模型的一个台阶,学完BS就把它扔到一边。但实际做含权债估值、可转债定价、美式期权报价的时候,我第一反应永远是先画一棵二叉树,而不是急着套BS闭式解。原因很简单:二叉树把所有定价逻辑都摊开在了桌面上,每一步都可以追溯、可以解释,而这恰恰是黑箱化的BS公式给不了你的。

这篇笔记我尽量不写成教科书式的推导流水账,而是把二叉树模型从“为什么要这么设计”讲到“代码怎么写”,再到“收敛性为什么有时会震荡”。无论是正在学数理金融的学生,还是想自己动手实现期权定价模型的开发者,都可以对照着往下走。

1. 先弄明白:二叉树是用来“模拟未来”,还是用来“给期权定价”

很多初学者第一次看到二叉树时,脑子里冒出的想法是:股价未来要么涨、要么跌,这模型也太简单粗暴了。如果你把二叉树理解为“预测股价”,那它确实糟糕透顶。但如果你把它理解为“在给定两种未来状态下怎么复制出期权收益”,整件事的性质就完全变了。

1.1 定价的本质不是预测,而是复制

期权定价的核心问题不是“股票未来会涨还是会跌”,而是“在当前股价下,一个期权到底值多少钱”。金融学里最有力的答案来自无套利定价:如果能用股票和无风险债券构造一个组合,使其在所有未来状态下的收益都等于期权收益,那么这个组合的成本就是期权的公允价值。

用单期二叉树就能讲清楚。假设当前股价 S0=100,一年后要么涨到 Su=122.14,要么跌到 Sd=81.87。这里先不用管这两个数怎么来的,下一节会展开。现在要为一个行权价 K=100 的欧式看涨期权定价,它在上涨状态下的终值为 fu=max(122.14-100, 0)=22.14,下跌状态下是 fd=0。

构造一个组合:持有 Δ 股股票,同时借入 B 元现金。目标是在两种状态下复制定期权的终值:

  • 上涨状态:Δ × 122.14 + B × e^{0.05} = 22.14
  • 下跌状态:Δ × 81.87 + B × e^{0.05} = 0

两个方程两个未知数,解得 Δ ≈ 0.5498,B ≈ -42.82。负的 B 表示借入现金。这个组合的当前成本就是 Δ × 100 + B = 54.98 - 42.82 = 12.16,所以期权价格也必须是这个数。如果市场报价高于12.16,你就卖期权、买复制组合套利;如果低于12.16,就买期权、反向构造组合。这就是无套利定价的全部思想,没有用到任何“股价上涨概率”的信息。

1.2 风险中性概率其实是一个“影子概率”

把上面的方程换个写法,会得到一个非常关键的值。先解出 p 满足:

p = (e^{rΔt} - d) / (u - d)

代入本例,u=1.2214,d=0.8187,r=0.05,Δt=1,算得 p ≈ 0.5776。然后期权价格可以写成:

C = e^{-rΔt} × [p × fu + (1-p) × fd] = 0.9512 × (0.5776 × 22.14) ≈ 12.16

你看,结果完全一致。这里的 p 被叫做“风险中性概率”,但严格说它和真实世界里股票上涨的概率一点关系都没有。它更像是在无套利约束下隐含出来的一种定价权重,是在“用股票加现金复制期权”这个过程中自然冒出来的影子概率。正因为复制组合没有用到任何风险偏好,定价才不需要猜测未来涨跌的真实分布。

提示:做二叉树的题时,最容易犯的错误就是拿着真实世界的上涨概率去算期权期望。真实概率只能用来模拟实际损益分布,定价必须用风险中性概率。

1.3 离散化不等于粗糙化,它只是把连续问题切成可算的台阶

二叉树把一个连续变化的过程,强行压成“每期要么上涨、要么下跌”的离散格点。听起来确实粗糙,但这是数值计算里的标准思路:积分不好算,就用黎曼和;PDE不好解,就用有限差分。二叉树本质上就是随机微分方程路径的一种离散逼近,它牺牲了路径的连续性,换来了可计算性和可解释性。后面会看到,当步数增加时,它的解会逐渐收敛到连续模型的解。

2. u和d为什么长这样:参数的数学来源与直觉

上一节的单期例子里,股价上涨到122.14、下跌到81.87,这个数字不是随便拍的。它来自 Cox-Ross-Rubinstein(CRR)模型对股价波动步长的核心设定:

u = e^{σ√Δt},d = 1/u

其中 σ 是年化波动率,Δt 是每期的时间长度。为什么是 √Δt 而不是 Δt?这是整棵树的灵魂所在。

2.1 √Δt 背后的对数正态直觉

在连续时间模型里,股价的对数收益服从正态分布,方差和 Δt 成正比,标准差自然和 √Δt 成正比。也就是说,如果我们把一年切成 N 步,每步时长 Δt = 1/N,那么每步对数价格变动的标准差就是 σ√Δt。要让离散树收敛到连续模型,树的“步长标准差”就必须也是 σ√Δt。

想象你每天随机朝东或朝西走一步,步长固定。如果每步长度与步数 N 无关、永远是一个常数,那么走 N 步后的总位移和 N 成正比,波动范围和 √N 不成比例。但是股票价格波动的规律是:时间越长,标准差按时间平方根增长。二叉树把这种平方根增长关系拆到了每一步上,所以每一步的步长必须随 N 增大而缩小,并且缩小的比例是 √Δt 而不是 Δt。

具体来说,CRR树里对数收益只有两种可能:ln(u)=σ√Δt 或 ln(d)=-σ√Δt。在风险中性世界里,上涨概率 p 约等于 1/2(当 Δt 很小时),所以单步对数收益的期望接近0,方差约等于 σ²Δt。这个结构和连续时间布朗运动的离散化完全对齐。如果把步长设成 σΔt,当 N 趋向无穷大时,总方差会爆炸或收敛错方向,那样树解出来的价格就不可能收敛到BS值。

2.2 风险中性概率的无套利区间

CRR模型里,p 还隐含了一个必须满足的条件:

p = (e^{rΔt} - d) / (u - d),必须落在0到1之间

这等价于要求 d < e^{rΔt} < u。如果无风险利率跑到了股价上涨因子之外,会发生什么?假设 e^{rΔt} > u,那意味着无风险资产每期收益比股票在所有状态下的收益还高,卖空股票、买入无风险资产就能无风险获利。这就是教科书上常说的“无套利条件”,也是任何合法定价模型都必须满足的地基。

换个直观说法:二叉树里的上涨因子 u 相当于“根号的波动边界”,下跌因子 d 相当于反向波动边界。无风险收益率必须落在两根“护栏”中间,否则护栏就失效了,定价也就失去意义。实务中用超大波动率参数时要留心,如果波动率大到某个极端,p 的数值可能溢出区间,这时要先检查无套利条件。

2.3 与Jarrow-Rudd等树形选型的差异

CRR树选择 u=1/d,本质上是让股价在对数空间里围绕当前水平对称。这个对称性带来的好处是:从任意节点出发,上涨之后再下跌和下跌之后再上涨会回到同一个节点,树是“重组”的。重组树的计算量是 O(N²),如果不重组,指数爆炸的树根本没法算。

Jarrow-Rudd(JR)树则采用另一种选法:

u = e^{(r-σ²/2)Δt + σ√Δt},d = e^{(r-σ²/2)Δt - σ√Δt}

这时风险中性概率刚好是 1/2,计算上少一步除法,但树围绕的是收益均值而不是当前股价,节点分布不那么对称。Rendleman-Bartter(RB)树则让节点概率更贴近对数正态的矩匹配。实操里CRR用得最多,因为节点分布均匀、代码简单、收敛性好。后面第6节会再展开对比。

3. 从一步到一百步:欧式看涨期权的完整计算与Python实现

只做单期二叉树是看不出价值的,真正体现威力的是多期逆向归纳。基本流程分三步:建树、算终值、从后往前倒推。

3.1 逆向归纳的思路

假设把一年切成 N 步,股价树最后一步有 N+1 个节点。节点 (i, j) 表示从第0期经过 i 步、其中上涨了 j 次,对应的股价是:

S(i, j) = S0 × u^j × d^{i-j}

这里 j 从0到 i,股价从上到下(或从小到大)依次排列。

终值很简单:对欧式看涨期权,最后一步每个节点的期权值 V(N, j) = max(S(N, j) - K, 0)。然后从最后一层开始往回收:第 i 层的某个节点期权价值,等于它两个后续节点期权价值的风险中性期望折现:

V(i, j) = e^{-rΔt} × [p × V(i+1, j+1) + (1-p) × V(i+1, j)]

不断重复,最后得到 V(0, 0) 就是期权当前价格。整个过程像倒放一棵树,从无数可能的未来逐步收束到现在。

3.2 一份可以在本地跑通的代码

下面用 numpy 写一个紧凑的向量化版本。核心技巧是:每一层只需要一个一维数组,倒推时数组长度自动减一,V[1:] 对应“上涨分支”的期权价值,V[:-1] 对应“下跌分支”的期权价值。

import numpy as np S0 = 100.0 K = 100.0 r = 0.05 sigma = 0.20 T = 1.0 N = 100 dt = T / N u = np.exp(sigma * np.sqrt(dt)) d = 1 / u p = (np.exp(r * dt) - d) / (u - d) disc = np.exp(-r * dt) # 最后一步股价序列:从小到大排列 j = np.arange(N + 1) S_last = S0 * u ** j * d ** (N - j) # 欧式看涨终值 V = np.maximum(S_last - K, 0) # 逆向倒推 for i in range(N - 1, -1, -1): # 上涨分支对应后半个数组,下跌分支对应前半个数组 V = disc * (p * V[1:] + (1 - p) * V[:-1]) print(f"欧式看涨期权价格: {V[0]:.4f}")

这个输出值在 N=100 时已经贴着 BS 闭式解震荡,真实BS理论值大约在10.4附近。读者可以跑一下,亲眼看着 N 从1变到50再变到200,观察它怎么一步步收敛。

3.3 一个容易踩的坑:概率和分支的对应关系

写二叉树的代码,我见过最多的高频错误就是把 p 乘到了 V[:-1] 上。看树的时候要明确:数组从小到大排列时,V[1:] 是当前节点“上涨一步”后续的高股价分支,V[:-1] 是“下跌一步”后的低股价分支。因此上行概率 p 必须乘在 V[1:] 上。

如果你习惯把数组排成从大到小,那对应关系就要反过来。建议一开始就固定一种排序约定,并且在代码里写注释。这个坑的隐蔽之处在于,两种写法算出来的价格差别通常不大,尤其在波动率低时非常接近,但它会让你的 Delta 方向出错——后面算对冲比率时就会发现。

3.4 Delta:二叉树顺带给出的对冲比率

多期二叉树不仅能算期权价格,还能在每一层给出对冲比率 Delta:

Δ = (V_up - V_down) / (S_up - S_down)

在单期例子里 Δ ≈ 0.5498,含义是:要复制这个看涨期权,你需要持有0.55股股票。放在动态对冲视角,这意味着每次股价变动后,交易员都要调整持仓到这个比例。二叉树的好处是 Delta 在每个节点都现成,不需要像 BS 那样再去求偏导数。算希腊字母时,Gamma 也可以用相邻节点差分再差分得到,这里不展开。

对做交易、做风控的读者说一句,别只盯价格,把每层的 Delta 序列打印出来,你会看到对冲比率随时间和股价的演化路径,这比一个孤零零的价格信息量大得多。

4. 美式期权:二叉树相对BS公式最大的主场

Black-Scholes公式只能直接处理欧式期权,因为它在闭式推导时假设期权只能在到期日行权。美式期权允许在任意时间提前行权,路径上多了一个“行权决策”问题,方程本身就不再有简单的闭式解。而二叉树天然适合处理这个问题,因为逆向归纳的每一步都可以停下来问一句:继续持有和立刻行权,哪个更值?

4.1 在每一个节点做一次比较

欧式逆向归纳时,节点价值直接取“持有价值”。美式则要改成:

V(i, j) = max( 持有价值 , 行权价值 )

其中持有价值是 e^{-rΔt} × [p × V(i+1, j+1) + (1-p) × V(i+1, j)],行权价值则要看期权类型。美式看涨是 max(S(i,j) - K, 0),美式看跌是 max(K - S(i,j), 0)。

代码只需要在倒推循环里加一个比较:

# 美式看跌 V = np.maximum(K - S_last, 0) for i in range(N - 1, -1, -1): # 当前时间步的股价 j_cur = np.arange(i + 1) S_cur = S0 * u ** j_cur * d ** (i - j_cur) # 持有价值 hold = disc * (p * V[1:] + (1 - p) * V[:-1]) # 行权价值 exercise = np.maximum(K - S_cur, 0) # 美式:二者取大 V = np.maximum(hold, exercise) print(f"美式看跌期权价格: {V[0]:.4f}")

如果把 exercise 从 max 中拿掉,就是欧式看跌。把同一个二叉树程序改成美式只差这一行,这就是二叉树最大的工程优势。

4.2 为什么美式看跌值得提前行权,而看涨通常不值得

理论上有个结论:在不分红的情况下,美式看涨期权不会提前行权。直觉很简单,提前行权相当于提前把股票拿到手,放弃了剩余时间内股价继续上涨的获利机会,同时还要现在掏出行权价。持有期权本身并不产生现金流出,你相当于免费保留了上涨空间。对看跌期权就不一样了,深度实值的美式看跌提前行权可以早点拿到现金,现金可以吃利息。如果你的无风险利率是5%,提前三个月拿到100元行权收入,比三个月后拿到100元更值钱。

所以在利率走高、波动率偏大时,美式看跌和欧式看跌的价格差异尤其明显。二叉树定价出来的美式看跌会比欧式看跌高出一截,这个差额就是“提前行权权利”的价值。用上面参数直接跑,把 exercise 加回去后价格会明显变高。

4.3 二叉树、有限差分与蒙特卡洛的分工

聊到这里,顺便理一下数值方法的适用边界。二叉树擅长:美式期权、含权债券、可转债这类带事件的路径决策问题。有限差分(PDE)擅长:更一般的偏微分方程边值问题,尤其是需要完整价格曲面的场景。蒙特卡洛擅长:高维路径依赖期权,但处理美式期权时需要通过 Least Squares Monte Carlo(比如 Longstaff-Schwartz)才能解决“最佳停时”问题。二叉树的时间复杂度是 O(N²),在低维定价问题里非常快,很适合作为生产环境的第一道工具。

5. 收敛性不是顺理成章的:震荡、外推与工程细节

用二叉树定价,最大的经验教训是:不能指望 N 越大结果就单调逼近精确值。CRR树有一个经典现象,价格会随着 N 增大而上下震荡,越接近精确解时越像一条衰减的锯齿波。

5.1 为什么会震荡,根因在行权价与节点的错位

二叉树末期的股价节点是离散的一串值:S0 × u^j × d^{N-j},它们不一定恰好等于行权价 K。当节点的位置与 K 的间距随 N 的不同而变化时,期权的终值会在“最接近K的那个节点”上出现跳跃。对于看涨期权,如果 K 恰好位于两个节点中间,两个节点的 payoff 都被“截断”了,误差就比较大;如果某个节点正好骑在 K 上,误差又会突然变小。这种由于离散栅格和关键边界错位导致的误差,就是震荡的根源。

这类现象在有限差分里也有,任何用格点逼近非光滑函数的问题都会遇到。差的不是模型的数学,而是离散化对Payoff尖角的处理精度。

5.2 工程上的三条改进路线

第一,加步数,这是最笨但最有效的方法。N 从100提到200,精度通常能提升不少,但对生产环境来说,N 到1000以上时收益递减,计算成本反而上升。

第二,对计算结果做 Richardson 外推。用 N 和 2N 两组结果做线性外推:近似值 ≈ 2 × V(2N) - V(N)。这个技巧在 CRR 树里效果不错,因为它的误差主项以 1/N 的某个幂次衰减。外推后常常能把误差缩小一个量级,代价仅仅是多跑一次倒推。

第三,换更聪明的树形。Leisen-Reimer 树专门设计成让节点尽可能穿过行权价附近的奇点,能大幅压制震荡。如果你要把二叉树用在生产环境,建议在 CRR 做基线验证之后,再对比一下 Leisen-Reimer 的结果。

5.3 步数选择与参数校准的实操经验

我自己做参数校准时有个习惯:先跑 N=50 和 N=100,看两个结果的差。如果差在0.05以内,通常说明已经收敛得差不多;如果差超过0.1,就说明树还太粗,加大步数或换树形。另外,从市场报价反推波动率时,如果直接用 N=100 的 CRR 树做牛顿迭代,震荡会让目标函数出现局部毛刺,迭代过程容易抖动。解决办法是先跑 N=200 或 N=500 把波动率的粗略值定下来,再换高精度方法精修。

注意:那个“把波动率参数临时调大让节点更好对齐行权价”的技巧,在教学上可以讲,但生产中不要依赖,它会让树和真实概率结构脱节。宁可加步数、做外推,也别为了让价格“看起来更顺滑”去歪曲市场参数。

6. 不止于股票期权:分红处理、树形选型与实际应用

二叉树真正值钱的地方,在于它能灵活扩展到很多 BS 闭式解覆盖不了的场景。这里分享我在实际中经常遇到的几个变体和坑。

6.1 连续股息率:把 r 换成 r - q

股票如果持续发放股息,持有股票的成本收益结构会变化。最简单的处理方式是引入连续股息率 q,把风险中性概率改成:

p = (e^{(r - q)Δt} - d) / (u - d)

同时股价树本身不变。这个技巧背后是持有成本的概念:股票在风险中性世界里要把股息“漏掉”,所以上行概率跟着调整。对指数期权、外汇期权这类标的,这个处理非常常见。

6.2 离散分红:树的重组性会被打破

离散分红的处理要麻烦得多。假设在第 m 期除息,每股分红 D,那么股价从这个节点往后要整体下移 D。如果没有额外处理,除息前后的节点就不会重合,树将失去重组性,节点数指数增长。工程上常见的做法是在除息时刻对股价树做一次“bump”:让除息后的树枝重新对齐,保持树的重组性。早期的教科书里还讲过“分红日前后节点拼接”的精确法,但实现复杂度高,实操中我更多用调整股价路径近似法,只要分红不是离谱的大额股息,误差可接受。

6.3 CRR、JR、RB 三棵树怎么选

树形参数设计风险中性概率特点适用场景
CRR(Cox-Ross-Rubinstein)u=e^{σ√Δt}, d=1/up=(e^{rΔt}-d)/(u-d)节点对称、实现简单、最常用股票/指数期权、教学、快速验证
JR(Jarrow-Rudd)u=e^{(r-σ²/2)Δt+σ√Δt}, d=e^{(r-σ²/2)Δt-σ√Δt}p=1/2上涨概率恒定、均值匹配数值实验、Delta中性时更方便
RB(Rendleman-Bartter)矩匹配方式通过矩条件解出更高阶矩校准对分布尾部要求高的场景

CRR 不是所有情况下最精确的,但它是工程上最省心的。如果你刚起步,建议先把 CRR 彻底吃透,再按需要换 JR 或 RB。

6.4 从金融到产业:实物期权、可转债与利率二叉树

二叉树的应用边界远不止股票期权。实物期权就非常有意思:一个项目投资决策可以被看成美式看涨期权。现在投入资金 K 就相当于行权,项目未来现金流的现值是标的资产 S。如果马上投,你会立刻亏损;如果等一等,市场信息变得更明朗后再决定是否投资,这个“等待的权利”就是期权的时间价值。很多企业投资决策翻车,不是因为现金流算错,而是没有把“延迟投资”的权利定价进去。二叉树是跟业务部门解释这个思路最好的工具——画两三层树,“现在投”和“再等等”两条路径的价值差一眼就看明白了。

可转债定价是另一个主场。可转债 = 普通债券 + 转股期权,而转股权几乎都是美式,还会叠加赎回条款、回售条款。这些条款的本质就是“事件”,用二叉树在节点上做事件判断非常自然。我处理过一只带复杂回售条款的可转债,BS公式根本没法直接表达“回售价随利率调整”的路径逻辑,而二叉树只需要在对应节点加一段判断代码。

利率二叉树是更专业的延伸。这里标的不是股票,而是利率本身,树的涨跌对应利率的上下移动,比如 Black-Derman-Toy(BDT)模型。一旦掌握了普通二叉树的定位思维,切到利率树时,变化的只是“标的物运动规律”,骨架还是同一套倒推定价框架。

个人这几年用下来的体会是:二叉树模型就像一个金融直觉的翻译器。不管多复杂的带权条款、行权边界、路径依赖,只要能被离散成树上的节点,就能在图上把每一步逻辑讲清楚。市场里很多定价问题拼的并不是更深的数学,而是能不能把一个复杂的决策问题拆成一小格一小格可计算、可解释的步骤。二叉树恰好就是那个最顺手的拆解工具。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/15 17:23:07

CANOCO 5.0 RDA实操指南:生态数据线性约束排序全解析

1. 项目概述&#xff1a;为什么RDA是生态数据建模绕不开的“硬核关卡”做群落生态分析的朋友&#xff0c;大概率都经历过这种时刻&#xff1a;手头有一堆样方的物种组成数据&#xff08;比如30个样方里测了87种植物的盖度&#xff09;&#xff0c;还有一组对应的环境变量&#…

作者头像 李华
网站建设 2026/9/15 17:23:00

SpringBoot流浪动物救助平台:从数据库设计到部署全流程

简介&#xff1a;本毕业设计资源围绕基于Spring Boot的流浪动物救助平台&#xff0c;提供完整项目源码、MySQL数据库脚本及配套说明文档&#xff0c;适合计算机相关专业学生用于毕业设计、课程设计或新手项目实践。系统采用Spring Boot Vue MySQL技术栈&#xff0c;功能覆盖用…

作者头像 李华
网站建设 2026/9/15 17:20:55

Pwndbg contextunwatch 命令详解:从 context 中移除监视表达式

Pwndbg contextunwatch 命令详解&#xff1a;从 context 中移除监视表达式 【免费下载链接】pwndbg Exploit Development and Reverse Engineering with GDB & LLDB Made Easy 项目地址: https://gitcode.com/GitHub_Trending/pw/pwndbg 本篇文章围绕 pwndbg 的 con…

作者头像 李华
网站建设 2026/9/15 17:20:21

Loop:免费 Mac 窗口管理,一个键摆好屏幕

Loop&#xff1a;免费 Mac 窗口管理&#xff0c;一个键摆好屏幕 【免费下载链接】Loop Window management made elegant. 项目地址: https://gitcode.com/GitHub_Trending/lo/Loop 光标贴在窗口右下角&#xff0c;你已经第 N 次去够那条 1 像素的边——拖快了&#xff0…

作者头像 李华
网站建设 2026/9/15 17:19:44

Zend Engine(Zend引擎)运行机制

一句话总纲&#xff1a;Zend Engine 就是PHP的虚拟机。把PHP源码编译成Zend中间字节码&#xff08;OPcode&#xff09;&#xff0c;然后在虚拟机里逐条解释执行OPcode&#xff1b;负责内存管理、变量处理、函数调用、对象、异常&#xff0c;连接扩展&#xff0c;最终调用操作系…

作者头像 李华