在Python中绘制格子树

问题描述 投票:0回答:2

我正在寻找绘制元组树

t = ((4,), (3, 5,), (2, 4, 6,), (1, 3, 5, 7,))
的想法,如下图所示(假设这个二项式树大小可以改变)。我试图避免对非核心包的依赖(只坚持使用 pandas、numpy、matplotlib、scikit 等)。

enter image description here

python python-3.x binary-tree hierarchical-data mathematical-lattices
2个回答
2
投票

我正在使用这段代码,它给出了非常好的结果:

from matplotlib import pyplot as plt
import numpy as np

fig = plt.figure(figsize=[5, 5])
for i in range(3):
    x = [1, 0, 1]
    for j in range(i):
        x.append(0)
        x.append(1)
    x = np.array(x) + i
    y = np.arange(-(i+1), i+2)[::-1]
    plt.plot(x, y, 'bo-')
plt.show()

enter image description here


0
投票

这是一篇较旧的帖子,但我最近需要相同的解决方案。这是我的建议,其中有重大改进:代码是可重用的,我们对参数有更多的控制,并且我们在绘图上使用真实的值比例。

要绘制像

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-')

这将产生下图:

linear case

我们可以推广到一个非线性的例子。让我们使用利率二项式树模型(通常用于债券定价 - 类似的模型用于股票期权定价)。上下台阶不是等距的,它们的比例是,即台阶间隔

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-')

产生:

non linear case

© www.soinside.com 2019 - 2024. All rights reserved.