自定义利率模拟函数的输出结果不符合预期
下面是我自定义的一个名为vasicek_sim的函数用来模拟一段时间内利率的变化路径。
def vasicek_sim(initial, final_time, sim_path_len, num_paths=None, *,
a, b, sigma, allow_neg=True):
"""
Parameters
----------
inital : float
the initial value of interest rate, i.e. r(0).
final_time : int
the time when the simulation stops.
sim_path_len : int
the number of points generated after the initial data.
num_paths : int, optional
the number of paths simulated. The default is None.
a : float
the parameter used in corresponding interest rate model.
b : float
the parameter used in corresponding interest rate model.
sigma : float
the parameter used in corresponding interest rate model.
allow_neg : bool, optional
when it equals to True, a negative interest rate is allowable
in the simulation. The default is True.
Returns
-------
None.
"""
import math, random
""""Create a list to store a path of interest rate(IR)"""
if type(initial) == list:
path_initial = initial
else:
path_initial = [initial]
delta = final_time / sim_path_len
"""" Generate a original path_box which has num_paths identical initial."""
if num_paths == None:
num_paths = 1
path_box = [path_initial for i in range(num_paths)]
y = [] # Used to store the paths of IR that have negative IR.
exp = math.exp(-a*delta)
"""" When num_paths is default value, there is only one path."""
for i in path_box:
for j in range(sim_path_len):
#print(i[-1])
r_old = i[-1]
W_1 = random.gauss(0, 1)
W_2 = random.gauss(0, 1)
#print(f'{W_1 = }\n{W_2 = }')
r_new = (exp*r_old
+ b*(1-exp)
+ sigma*((1-exp**2)/(2*a))**0.5*(W_2-W_1))
if allow_neg == False and r_new < 0:
print(r_new)
break
#print(r_new)
#print(i)
i.append(r_new)
# The paths removed before are appended to path_box again.
if y != []:
path_box.append(y)
return path_box
下图是我的测试代码
if __name__ == '__main__':
z = vasicek_sim([0.25, 0.3, 0.4], 2, 3, 2, a=0.5, b=0.6, sigma=0.2)
print(f'The path of interest rate is\n {z}')
最后是我的运行结果
The path of interest rate is
[[0.25, 0.3, 0.4, 0.3479323841038564, 0.2375140125192349, 0.40864261608808583, 0.5588591529202444, 0.3464802076221359, 0.2132402884958335], [0.25, 0.3, 0.4, 0.3479323841038564, 0.2375140125192349, 0.40864261608808583, 0.5588591529202444, 0.3464802076221359, 0.2132402884958335]]
预期结果是,返回的path_box中的两个子列表各包含6个元素,其中前三个相同,后三个不同,但运行后发现每个子列表各有9个元素,并且两个子列表完全一样。通过检查发现,第一个子列表的最后三个元素本应该储存在第二个子列表的[3:5]部分,同时,debug的过程中每次最里面的回圈结束一圈后,path_box的两个子列表会同时被改变而非只改变当前这一个。
请问是哪部分代码导致了这个问题?
关于 LearnKu
If nothing wrong, it is caused by following statement.
The items in list,
path_box, will be all referenced to same variablepath_initial, needed to be done shallow copy, likethen you will get the expected result
这个vasicek_sim函数是用来模拟Vasicek利率模型的。Vasicek模型是一种常用于金融衍生品定价的短期利率模型。但是,你的代码中存在一些问题,我将指出并提供修正建议。
首先,我们来看代码的目的:
模拟Vasicek利率模型的一条或多条路径。 允许用户指定是否允许负利率。 现在,我们分析代码中的问题:
变量y被初始化为空列表,但在后面的代码中并没有被使用。看起来你可能想用它来存储那些产生负利率的路径,但实际上并没有这么做。 在模拟路径时,如果allow_neg为False并且产生了负利率,你只是打印了这个负利率并跳出了内层循环。这并不会停止对整个path_box的遍历,也不会将这条路径添加到y列表中。 你的代码中使用了两个高斯随机数W_1和W_2,但在Vasicek模型的离散化版本中通常只需要一个。这可能是个错误。 你的代码没有处理num_paths为None的情况,尽管你在函数签名中指定了默认值为None。但实际上,你在函数一开始就检查了它的值,并为其分配了默认值1。为了更清晰,你应该在函数签名中直接为其指定默认值。 注释中的“Create a list to store a path of interest rate(IR)”和其他类似的注释与代码行之间应该有一个空行,以符合Python的PEP 8风格指南。 下面是对代码的修正:
python import math
import random
def vasicek_sim(initial, final_time, sim_path_len, num_paths=1, a=None, b=None, sigma=None, *, allow_neg=True):
"""
Simulate paths using the Vasicek interest rate model.
注意:在这个修正版本中,我改变了函数的一些行为。例如,我现在允许initial是一个列表,这样你可以为每条路径指定一个不同的初始利率。我还添加了错误处理来确保a、b和sigma参数被提供。最后,我改变了如何处理负利率的情况。如果allow_neg为False并且产生了负利率,我现在将其替换为0(但你可能想以不同的方式处理这种情况)。