def update_operator(self, t: float, mesh: Mesh): diffusion = self._pde.diffusion(t, mesh.get_points()) convection = self._pde.convection(t, mesh.get_points(), diffusion) source = self._pde.source(t, mesh.get_points()) self._laplacian.update_operator(t, mesh) self._gradient.update_operator(t, mesh) Tools.update_diagonal(diffusion, convection, source, self._gradient.diagonal(), self._laplacian.diagonal(), self.diagonal()) Tools.update_diagonal_upper(diffusion, convection, self._gradient.diagonal_upper(), self._laplacian.diagonal_upper(), self.diagonal_upper()) Tools.update_diagonal_lower(diffusion, convection, self._gradient.diagonal_lower(), self._laplacian.diagonal_lower(), self.diagonal_lower())
def step_solver(self, mesh: Mesh, t_i_1: float, t_i: float, u_i_1: ndarray, u_i: ndarray): delta_i_1_i = (t_i - t_i_1) u_i_1_explicit = np.zeros(mesh.get_size()) self._operator[0].update_operator(t_i, mesh) self._operator[1].update_operator(t_i, mesh) self.modify_operators() self._operator[0].apply_boundary_condition( t_i_1=t_i_1, t_i=t_i, operator=self._operator[0], scheme_type=SchemeType.EXPLICIT) self._operator[1].apply_boundary_condition( t_i_1=t_i_1, t_i=t_i, operator=self._operator[1], scheme_type=SchemeType.IMPLICIT) np.copyto(u_i_1_explicit, self._operator[0].apply_explicit_operator(delta_i_1_i, u_i)) np.copyto( u_i_1, self._operator[1].apply_implicit_operator(delta_i_1_i, u_i_1_explicit)) self._operator[0].apply_boundary_condition_after_update( u_t=u_i_1, operator=self._operator[0]) self._operator[1].apply_boundary_condition_after_update( u_t=u_i_1, operator=self._operator[1])
def get_vetor_iv_cev(nu: float, alpha: float, T: float): # Smile curve with cev mesh_t = Mesh(uniform_mesh, 100, 0.0, T) mesh_x = LnUnderlyingMesh(0.0, 0.0, nu, f0, T, 0.999, uniform_mesh, 200) log_diffusion = partial(LocalVolFunctionals.log_cev_diffusion, beta=alpha - 1, sigma=nu) cev_pde = PDE.from_ipde_terms(LN_FORWARD_LOCAL_VOL_PDE(log_diffusion)) k_s = np.arange(f0 - 4.0, f0 + 4.0, 0.5) # k_s = [f0] tc_s = [TerminalCondition(partial(f_ln_payoff, k=k_i)) for k_i in k_s] bc = Zero_Laplacian_BC() operator_exp = PDEOperators.LinearPDEOperator(mesh_x, cev_pde, bc) operator_impl = PDEOperators.LinearPDEOperator(mesh_x, cev_pde, bc) operators = [operator_exp, operator_impl] pde_price = [] for tc_i in tc_s: pd_solver = PDESolvers.FDSolver(mesh_t, mesh_x, operators, SchemeType.CRANK_NICOLSON, BoundaryConditionType.ZERO_DIFFUSION, tc_i) pd_solver.solver() f = interp1d(mesh_x.get_points(), pd_solver._u_grid[:, 0], kind='linear', fill_value='extrapolate') pde_price.append(float(f(np.log(f0)))) # Hagan approximation expansion_hagan = ExpansionLocVol.hagan_loc_vol( lambda t: nu, lambda x: np.power(x, alpha), lambda x: alpha * np.power(x, alpha - 1.0), lambda x: alpha * (alpha - 1.0) * np.power(x, alpha - 2.0)) # Compute the iv no_elements = len(pde_price) # From hagan iv_hagan = [] iv_fd = [] z_s = [] for i in range(0, no_elements): z_s.append(np.log(k_s[i] / f0)) iv_fd.append( implied_volatility(pde_price[i], f0, k_s[i], T, 0.0, 0.0, 'c')) for i in range(0, no_elements): iv_hagan.append(expansion_hagan.get_implied_vol(T, f0, k_s[i])) return z_s, iv_fd, iv_hagan
def __init__(self, mesh_t: Mesh, mesh_x: Mesh, operators: List[LinearPDEOperator], scheme_type: SchemeType, bc_type: BoundaryConditionType, tc: TerminalCondition): self._operators = operators self._mesh_t = mesh_t self._mesh_x = mesh_x self._u_grid = np.zeros(shape=(mesh_x.get_size(), mesh_t.get_size())) if scheme_type == SchemeType.EXPLICIT: self._scheme = Schemes.ExplicitScheme(operators[0]) elif scheme_type == SchemeType.IMPLICIT: self._scheme = Schemes.ImplicitScheme(operators[0]) elif scheme_type == SchemeType.CRANK_NICOLSON: self._scheme = Schemes.ThetaScheme(operators, 0.5) else: raise ValueError("The operator type " + str(scheme_type)) self._bc = BoundaryCondition(bc_type) self._tc = tc
import numpy as np from Solvers.PDE_Solver import PDEOperators from Tools.Types import ndarray from Solvers.PDE_Solver.Meshes import uniform_mesh, Mesh from Solvers.PDE_Solver.PDEs import CEV_forward_PDE, PDE from Solvers.PDE_Solver.TerminalConditions import TerminalCondition def delta_terminal_condition(x: ndarray, x0: float, h: float): return np.exp(-0.5 * np.power(x - x0, 2.0) / h) / np.sqrt(2.0 * np.pi * h) T = 1.0 mesh_t = Mesh(uniform_mesh, 50, 0.0, T) mesh_x = Mesh(uniform_mesh, 100, 0.0, 5.0) sigma = 0.3 beta = 0.2 cev_forward_pde = PDE.from_ipde_terms(CEV_forward_PDE(sigma, beta)) bc = PDEOperators.ZeroLaplacianBC() operator_exp = PDEOperators.LinearPDEOperator(mesh_x, cev_forward_pde, bc) operator_impl = PDEOperators.LinearPDEOperator(mesh_x, cev_forward_pde, bc) operators = [operator_exp, operator_impl] tc = TerminalCondition(delta_terminal_condition)
def f_ln_payoff(mesh: Mesh, k: float) -> np_ndarray: return np.maximum(np.exp(mesh.get_points()) - k, 0.0)
def __init__(self, mesh: Mesh, bc: BoundaryCondition): self._diagonal_upper = np.zeros(mesh.get_size() - 1) self._diagonal_lower = np.zeros(mesh.get_size() - 1) self._diagonal = np.zeros(mesh.get_size()) self._mesh = mesh self._bc = bc
from Solvers.PDE_Solver.Meshes import uniform_mesh, Mesh, LnUnderlyingMesh from Solvers.PDE_Solver.PDEs import LN_BS_PDE, PDE from Solvers.PDE_Solver.Types import BoundaryConditionType, np_ndarray, SchemeType from Solvers.PDE_Solver.TerminalConditions import TerminalCondition from Solvers.PDE_Solver.BoundariesConditions import Zero_Laplacian_BC from py_vollib.black_scholes_merton import black_scholes_merton try: import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D from matplotlib import cm except ImportError: print('The import of matplotlib is not working.') T = 4.0 mesh_t = Mesh(uniform_mesh, 50, 0.0, T) r = 0.03 q = 0.01 sigma = 0.3 S0 = 100.0 K = np.exp((r - q) * T) * S0 + 10 log_K = np.log(K) f = np.exp((r - q) * T) * S0 df = np.exp(-r * T) start_time = time.time() analytic_price = df * black_scholes_merton('c', f, K, T, 0.0, sigma, 0.0) end_time = time.time()
import numpy as np from Solvers.PDE_Solver.Meshes import Mesh, finite_volume_mesh, uniform_mesh x_max = 1.0 x_min = -1.0 T = 3.0 mesh_t = Mesh(uniform_mesh, 50, 0.0, T) mesh_x = Mesh(finite_volume_mesh, 100, x_min, x_max) r = 0.03 q = 0.01 sigma = 0.3 S0 = 100.0 K = np.exp((r - q) * T) * S0 + 10