def build_base_operator(self, t):
"""
:param t: Not used as mu and sigma are constant
:return:
"""
# Update drift and volatility
self.build_moment_vectors(t)
base_operator = np.zeros((self.d, self.d))
nabla = linalg.block_diag(*[self.build_gradient_matrix(x) for x in range(1, self.d - 1)])
moments = np.zeros(2 * (self.d - 2))
for i in range(0, self.d - 2):
moments[2 * i] = self.drift[i + 1]
moments[2 * i + 1] = self.volatility[i + 1]
generator_elements = linalg.solve(nabla, moments)
r_idx, c_idx = np.diag_indices_from(base_operator)
base_operator[r_idx[1:-1], c_idx[:-2]] = generator_elements[::2]
base_operator[r_idx[1:-1], c_idx[2:]] = generator_elements[1::2]
np.fill_diagonal(base_operator, -np.sum(base_operator, axis=1))
# -- Boundary Condition: Volatility Matching --
nabla_0 = self.grid[1] - self.grid[0]
base_operator[0, 0] = - 1. * self.volatility[0] / (nabla_0 * nabla_0)
base_operator[0, 1] = - base_operator[0, 0]
nabla_d = self.grid[self.d - 1] - self.grid[self.d - 2]
base_operator[self.d - 1, self.d - 1] = - 1. * self.volatility[self.d - 1] / (nabla_d * nabla_d)
base_operator[self.d - 1, self.d - 2] = - base_operator[self.d - 1, self.d - 1]
# ----------------------------------------------
self.sanity_check_base_operator(base_operator)
return base_operator
评论列表
文章目录