我正在寻找绘制元组树
t = ((4,), (3, 5,), (2, 4, 6,), (1, 3, 5, 7,))
的想法,如下图所示(假设这个二项式树大小可以改变)。我试图避免对非核心包的依赖(只坚持使用 pandas、numpy、matplotlib、scikit 等)。
这是一篇较旧的帖子,但我最近需要相同的解决方案。这是我的建议,其中有重大改进:代码是可重用的,我们对参数有更多的控制,并且我们在绘图上使用真实的值比例。
要绘制像
t = ((4,), (3, 5,), (2, 4, 6,), (1, 3, 5, 7,))
这样的元组树,我们从线性情况开始,其中向上和向下的步骤间隔相等,并且可以向上和向下步进vola=1
。
我们从定义树的基础(底部)开始,并在每个时间步上构建以
2*vola
间隔的值。然后我们将树的值存储在稀疏矩阵中。矩阵的address代表网格。在地址,我们存储该值。
注意:
mat.toarray()
只是稀疏矩阵的视觉表示。树的底部在从中心到左下角的对角线上可见。每一行都是一个时间步长。上下从右向左翻转。
nb_steps = 3
vola = 1
r = 4 - (np.arange(nb_steps+1) * vola) # the tree root starts at 4
print(r, "\n")
# [4 3 2 1]
mat = lil_matrix((nb_steps+1, nb_steps*2+1), dtype = np.float32)
for i in range(nb_steps+1):
value = r[i] + 2*vola * np.arange(0,i+1)
rows = np.zeros(i+1, dtype=np.int16) + i
cols = np.arange(i+1)*2+nb_steps-i
mat[rows, cols] = value
print(mat.toarray())
# [[0. 0. 0. 4. 0. 0. 0.]
# [0. 0. 3. 0. 5. 0. 0.]
# [0. 2. 0. 4. 0. 6. 0.]
# [1. 0. 3. 0. 5. 0. 7.]]
一旦我们在稀疏矩阵中定义了树,下面的代码片段将绘制连接树节点的线段,其中
x
是步骤轴(或 time 轴,如果你愿意),v
是该节点的值。
fig = plt.figure(figsize=[5, 5])
for i in range(nb_steps):
x = (np.arange(3 + i*2) % 2 == 0) + i
y = np.arange(0, 2*(i+1)+1) -1 + (nb_steps-i) #[::-1]
v = mat[x, y].toarray()[0]
plt.plot(x, v, 'bo-')
这将产生下图:
我们可以推广到一个非线性的例子。让我们使用利率二项式树模型(通常用于债券定价 - 类似的模型用于股票期权定价)。上下台阶不是等距的,它们的比例是,即台阶间隔
exp(2*vola)
。
和之前一样,我们需要首先定义树的基础。然后,我们将树步骤的值存储在稀疏矩阵中。
在以下代码片段中,我们更改这些行:
r = 0.03 *1/(1 + (np.arange(nb_steps+1) * 0.15) )
value = r[i] * np.exp(vola*2*np.arange(0,i+1))
nb_steps = 4
即:
nb_steps = 4
vola = 0.15
r = 0.03 *1/(1 + (np.arange(nb_steps+1) * 0.15) )
print(r, "\n")
# [0.03 0.02608696 0.02307692 0.02068966 0.01875 ]
mat = lil_matrix((nb_steps+1, nb_steps*2+1), dtype = np.float32)
for i in range(nb_steps+1):
value = r[i] * np.exp(vola*2*np.arange(0,i+1))
rows = np.zeros(i+1, dtype=np.int16) + i
cols = np.arange(i+1)*2+nb_steps-i
mat[rows, cols] = value
print(np.round(mat.toarray(), 4))
# [[0. 0. 0. 0. 0.03 0. 0. 0. 0. ]
# [0. 0. 0. 0.0261 0. 0.0352 0. 0. 0. ]
# [0. 0. 0.0231 0. 0.0312 0. 0.042 0. 0. ]
# [0. 0.0207 0. 0.0279 0. 0.0377 0. 0.0509 0. ]
# [0.0188 0. 0.0253 0. 0.0342 0. 0.0461 0. 0.0623]]
为了绘制该图,我们使用与之前相同的片段。
fig = plt.figure(figsize=[5, 5])
for i in range(nb_steps):
x = (np.arange(3 + i*2) % 2 == 0) + i
y = np.arange(0, 2*(i+1)+1) -1 + (nb_steps-i) #[::-1]
v = mat[x, y].toarray()[0]
plt.plot(x, v, 'bo-')
产生: