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())
Exemplo n.º 2
0
    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])
Exemplo n.º 3
0
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
Exemplo n.º 4
0
    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
Exemplo n.º 5
0
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)
Exemplo n.º 6
0
def f_ln_payoff(mesh: Mesh, k: float) -> np_ndarray:
    return np.maximum(np.exp(mesh.get_points()) - k, 0.0)
Exemplo n.º 7
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
Exemplo n.º 8
0
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()
Exemplo n.º 9
0
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