def test_create(self): vec = self.vec last = len(vec)-1 idx = 1 d = np.hstack((np.nan, np.diff(vec))) deltas = d sch0 = 'center' axis = 1 for sch1 in ['center', 'up', 'down']: for dv in [1,2]: oldX1 = utils.nonuniform_complete_coefficients(deltas, up_or_down=sch1, flip_idx=idx)[dv-1] X1 = FD.BO.for_vector(vec, scheme=sch1, derivative=dv, order=2, axis=axis) high, low = 1,-1 if (sch0 == 'up' and idx > 1) or (sch1 == 'up' and idx < last-1): high = 2 if (sch0 == 'down' and idx > 2) or (sch1 == 'down' and idx < last): low = -2 m = tuple(oldX1.offsets).index(0) oldX1.data = oldX1.data[m-high:m-low+1] oldX1.offsets = oldX1.offsets[m-high:m-low+1] # print "old D.todense()" # fp(oldX1.D.todense()) # print "new D.todense()" # fp(X1.D.todense()) # print # print X1.shape, oldX1.shape # print (X1.D.offsets, oldX1.offsets), "%s+%s (dv %i) idx %i" % (sch0, sch1, dv, idx) assert X1.axis == axis assert np.array_equal(X1.D.todense(), oldX1.todense()), "%s+%s (dv %i) idx %i" % (sch0, sch1, dv, idx) assert np.array_equal(X1.D.offsets, oldX1.offsets), "%s+%s (dv %i) idx %i" % (sch0, sch1, dv, idx) assert (X1.D.data.shape == oldX1.data.shape), "%s+%s (dv %i) idx %i" % (sch0, sch1, dv, idx) assert np.array_equal(X1.D.data, oldX1.data), "%s+%s (dv %i) idx %i" % (sch0, sch1, dv, idx)
), } # schemes = {(1,) : ({"scheme": "center"}, {"scheme": "backward", "from" : flip_idx_var})} utils.tic("Building FDE Engine") # F = FDE.FiniteDifferenceEngineADI(G, coefficients=coeffs, boundaries=bounds, schemes=schemes, force_bandwidth=(-2, 2)) F = HestonFiniteDifferenceEngine(H, nspots=nspots, nvols=nvols, flip_idx_spot=flip_idx_spot, flip_idx_var=flip_idx_var) utils.toc() L1_ = [] R1_ = [] utils.tic("Building As(s):\t") print "(Up/Down)wind from:", flip_idx_spot As_ = utils.nonuniform_complete_coefficients(dss, up_or_down=up_or_down_spot, flip_idx=flip_idx_spot)[0] Ass_ = utils.nonuniform_complete_coefficients(dss)[1] # As_, Ass_ = utils.nonuniform_forward_coefficients(dss) assert not np.isnan(As_.data).any() assert not np.isnan(Ass_.data).any() mu_sfunc = mu_s gamma2_sfunc = gamma2_s for j, v in enumerate(vars): # Be careful not to overwrite our operators As, Ass = As_.copy(), Ass_.copy() m = 2 mu_s = H.interest_rate.value * spots # mu_s = mu_sfunc(0, spots, v) # gamma2_s = gamma2_sfunc(0, spots, v) gamma2_s = 0.5 * v * spots ** 2
def setUp(self): s1_enable = 1 s2_enable = 1 v1_enable = 1 v2_enable = 1 r_enable = 1 dirichlet_s = 1 dirichlet_v = 1 kappa = 1 r = 0.06 theta = 0.04 sigma = 0.4 rho = 0.6 spot_max = 1500.0 var_max = 13.0 nspots = 5 nvols = 5 spotdensity = 7.0 # infinity is linear? varexp = 5 # TODO:!!!!XXX TODO XXX # var_max = nvols-1 # spot_max = nspots-1 up_or_down_spot = 'up' up_or_down_var = 'down' flip_idx_spot = nspots // 2 flip_idx_var = nvols // 2 k = spot_max / 4.0 # spots = np.linspace(0, spot_max, nspots) # vars = np.linspace(0, var_max, nvols) spots = utils.sinh_space(k, spot_max, spotdensity, nspots) vars = utils.exponential_space(0.00, 0.04, var_max, varexp, nvols) def mu_s(t, *dim): return r * dim[0] * s1_enable def gamma2_s(t, *dim): return 0.5 * dim[1] * dim[0]**2 * s2_enable def mu_v(t, *dim): return kappa * (theta - dim[1]) * v1_enable def gamma2_v(t, *dim): return 0.5 * sigma**2 * dim[1] * v2_enable coeffs = { (): lambda t: -r * r_enable, (0, ): mu_s, (0, 0): gamma2_s, (1, ): mu_v, (1, 1): gamma2_v, (0, 1): lambda t, *dim: dim[0] * dim[1] * rho * sigma } bounds = { # D: U = 0 VN: dU/dS = 1 ( 0, ): ((0 if dirichlet_s else 1, lambda *args: 0.0), (1, lambda *args: 1.0)), # D: U = 0 Free boundary (0, 0): ((0 if dirichlet_s else 1, lambda *args: 0.0), (None, lambda *x: 1.0)), # Free boundary at low variance ( 1, ): ( (None, lambda *x: None), # (0.0, lambda t, *dim: 0), # D intrinsic value at high variance # (None, lambda *x: None) (0 if dirichlet_v else 1, lambda t, *dim: np.maximum(0.0, dim[0] - k))), # # Free boundary (1, 1): ( (1, lambda *x: 0), # D intrinsic value at high variance # (None, lambda *x: None) (0 if dirichlet_v else 1, lambda t, *dim: np.maximum(0.0, dim[0] - k))) } schemes = {} schemes[(0, )] = ({ "scheme": "center" }, { "scheme": up_or_down_spot, "from": flip_idx_spot }) schemes[(1, )] = ({ "scheme": "center" }, { "scheme": up_or_down_var, "from": flip_idx_var }) dss = np.hstack((np.nan, np.diff(spots))) dvs = np.hstack((np.nan, np.diff(vars))) As_ = utils.nonuniform_complete_coefficients( dss, up_or_down=up_or_down_spot, flip_idx=flip_idx_spot)[0] Ass_ = utils.nonuniform_complete_coefficients(dss)[1] L1_ = [] R1_ = [] # As_, Ass_ = utils.nonuniform_forward_coefficients(dss) assert (not np.isnan(As_.data).any()) assert (not np.isnan(Ass_.data).any()) for j, v in enumerate(vars): # Be careful not to overwrite operators As, Ass = As_.copy(), Ass_.copy() m = 2 mu_s = r * spots * s1_enable gamma2_s = 0.5 * v * spots**2 * s2_enable for i, z in enumerate(mu_s): # print z, coeffs[0,](0, spots[i]) assert z == coeffs[0, ](0, spots[i]) for i, z in enumerate(gamma2_s): # print z, coeffs[0,0](0, spots[i], v) assert z == coeffs[0, 0](0, spots[i], v) Rs = np.zeros(nspots) Rs[-1] = 1 As.data[m - 2, 2:] *= mu_s[:-2] As.data[m - 1, 1:] *= mu_s[:-1] As.data[m, :] *= mu_s As.data[m + 1, :-1] *= mu_s[1:] As.data[m + 2, :-2] *= mu_s[2:] Rs *= mu_s Rss = np.zeros(nspots) Rss[-1] = 2 * dss[-1] / dss[-1]**2 Ass.data[m + 1, -2] = 2 / dss[-1]**2 Ass.data[m, -1] = -2 / dss[-1]**2 Ass.data[m - 2, 2:] *= gamma2_s[:-2] Ass.data[m - 1, 1:] *= gamma2_s[:-1] Ass.data[m, :] *= gamma2_s Ass.data[m + 1, :-1] *= gamma2_s[1:] Ass.data[m + 2, :-2] *= gamma2_s[2:] Rss *= gamma2_s L1_.append(As.copy()) L1_[j].data += Ass.data L1_[j].data[m, :] -= 0.5 * r * r_enable L1_[j].data[m, 0] = 1 * dirichlet_s R1_.append((Rs + Rss).copy()) R1_[j][0] = 0 L2_ = [] R2_ = [] Av_ = utils.nonuniform_complete_coefficients(dvs, up_or_down=up_or_down_var, flip_idx=flip_idx_var)[0] Avv_ = utils.nonuniform_complete_coefficients(dvs)[1] assert (not np.isnan(Av_.data).any()) assert (not np.isnan(Avv_.data).any()) for i, s in enumerate(spots): mu_v = kappa * (theta - vars) * v1_enable gamma2_v = 0.5 * sigma**2 * vars * v2_enable # for j, z in enumerate(mu_v): # assert z == coeffs[1,](0, 0, vars[j]) # for j, z in enumerate(gamma2_v): # assert z == coeffs[1,1](0, 0, vars[j]) # Be careful not to overwrite our operators Av, Avv = Av_.copy(), Avv_.copy() m = 2 Av.data[m - 2, 2] = -dvs[1] / (dvs[2] * (dvs[1] + dvs[2])) Av.data[m - 1, 1] = (dvs[1] + dvs[2]) / (dvs[1] * dvs[2]) Av.data[m, 0] = (-2 * dvs[1] - dvs[2]) / (dvs[1] * (dvs[1] + dvs[2])) Av.data[m - 2, 2:] *= mu_v[:-2] Av.data[m - 1, 1:] *= mu_v[:-1] Av.data[m, :] *= mu_v Av.data[m + 1, :-1] *= mu_v[1:] Av.data[m + 2, :-2] *= mu_v[2:] Rv = np.zeros(nvols) Rv *= mu_v Avv.data[m - 1, 1] = 2 / dvs[1]**2 Avv.data[m, 0] = -2 / dvs[1]**2 Avv.data[m - 2, 2:] *= gamma2_v[:-2] Avv.data[m - 1, 1:] *= gamma2_v[:-1] Avv.data[m, :] *= gamma2_v Avv.data[m + 1, :-1] *= gamma2_v[1:] Avv.data[m + 2, :-2] *= gamma2_v[2:] Rvv = np.zeros(nvols) Rvv[0] = 2 * dvs[1] / dvs[1]**2 Rvv *= gamma2_v L2_.append(Av.copy()) L2_[i].data += Avv.data L2_[i].data[m, :] -= 0.5 * r * r_enable L2_[i].data[ m, -1] = 1 * dirichlet_v # This is to cancel out the previous value so we can # set the dirichlet boundary condition using R. # Then we have U_i + -U_i + R R2_.append(Rv + Rvv) R2_[i][-1] = 0 # np.maximum(0, s - k) def flatten_tensor(mats): diags = np.hstack([x.data for x in mats]) flatmat = scipy.sparse.dia_matrix( (diags, mats[0].offsets), shape=(diags.shape[1], diags.shape[1])) return flatmat L1 = flatten_tensor(L1_) L2 = flatten_tensor(L2_) R1 = np.array(R1_).T R2 = np.array(R2_) self.As_ = As_ self.Ass_ = Ass_ self.L1_ = L1 self.R1_ = R1 self.L2_ = L2 self.R2_ = R2 # G = Grid.Grid((spots, vars), initializer=lambda x0,x1: np.maximum(x0-k,0)) self.G = Grid.Grid((spots, vars), initializer=lambda x0, x1: x0 * x1) # print G self.F = FD.FiniteDifferenceEngineADI(self.G, coefficients=coeffs, boundaries=bounds, schemes=schemes, force_bandwidth=None) self.F.init()
def setUp(self): s1_enable = 1 s2_enable = 1 v1_enable = 1 v2_enable = 1 r_enable = 1 dirichlet_s = 1 dirichlet_v = 1 kappa = 1 r = 0.06 theta = 0.04 sigma = 0.4 rho = 0.6 spot_max = 1500.0 var_max = 13.0 nspots = 5 nvols = 5 spotdensity = 7.0 # infinity is linear? varexp = 5 # TODO:!!!!XXX TODO XXX # var_max = nvols-1 # spot_max = nspots-1 up_or_down_spot = "up" up_or_down_var = "down" flip_idx_spot = nspots // 2 flip_idx_var = nvols // 2 k = spot_max / 4.0 # spots = np.linspace(0, spot_max, nspots) # vars = np.linspace(0, var_max, nvols) spots = utils.sinh_space(k, spot_max, spotdensity, nspots) vars = utils.exponential_space(0.00, 0.04, var_max, varexp, nvols) def mu_s(t, *dim): return r * dim[0] * s1_enable def gamma2_s(t, *dim): return 0.5 * dim[1] * dim[0] ** 2 * s2_enable def mu_v(t, *dim): return kappa * (theta - dim[1]) * v1_enable def gamma2_v(t, *dim): return 0.5 * sigma ** 2 * dim[1] * v2_enable coeffs = { (): lambda t: -r * r_enable, (0,): mu_s, (0, 0): gamma2_s, (1,): mu_v, (1, 1): gamma2_v, (0, 1): lambda t, *dim: dim[0] * dim[1] * rho * sigma, } bounds = { # D: U = 0 VN: dU/dS = 1 (0,): ((0 if dirichlet_s else 1, lambda *args: 0.0), (1, lambda *args: 1.0)), # D: U = 0 Free boundary (0, 0): ((0 if dirichlet_s else 1, lambda *args: 0.0), (None, lambda *x: 1.0)), # Free boundary at low variance (1,): ( (None, lambda *x: None), # (0.0, lambda t, *dim: 0), # D intrinsic value at high variance # (None, lambda *x: None) (0 if dirichlet_v else 1, lambda t, *dim: np.maximum(0.0, dim[0] - k)), ), # # Free boundary (1, 1): ( (1, lambda *x: 0), # D intrinsic value at high variance # (None, lambda *x: None) (0 if dirichlet_v else 1, lambda t, *dim: np.maximum(0.0, dim[0] - k)), ), } schemes = {} schemes[(0,)] = ({"scheme": "center"}, {"scheme": up_or_down_spot, "from": flip_idx_spot}) schemes[(1,)] = ({"scheme": "center"}, {"scheme": up_or_down_var, "from": flip_idx_var}) dss = np.hstack((np.nan, np.diff(spots))) dvs = np.hstack((np.nan, np.diff(vars))) As_ = utils.nonuniform_complete_coefficients(dss, up_or_down=up_or_down_spot, flip_idx=flip_idx_spot)[0] Ass_ = utils.nonuniform_complete_coefficients(dss)[1] L1_ = [] R1_ = [] # As_, Ass_ = utils.nonuniform_forward_coefficients(dss) assert not np.isnan(As_.data).any() assert not np.isnan(Ass_.data).any() for j, v in enumerate(vars): # Be careful not to overwrite operators As, Ass = As_.copy(), Ass_.copy() m = 2 mu_s = r * spots * s1_enable gamma2_s = 0.5 * v * spots ** 2 * s2_enable for i, z in enumerate(mu_s): # print z, coeffs[0,](0, spots[i]) assert z == coeffs[0,](0, spots[i]) for i, z in enumerate(gamma2_s): # print z, coeffs[0,0](0, spots[i], v) assert z == coeffs[0, 0](0, spots[i], v) Rs = np.zeros(nspots) Rs[-1] = 1 As.data[m - 2, 2:] *= mu_s[:-2] As.data[m - 1, 1:] *= mu_s[:-1] As.data[m, :] *= mu_s As.data[m + 1, :-1] *= mu_s[1:] As.data[m + 2, :-2] *= mu_s[2:] Rs *= mu_s Rss = np.zeros(nspots) Rss[-1] = 2 * dss[-1] / dss[-1] ** 2 Ass.data[m + 1, -2] = 2 / dss[-1] ** 2 Ass.data[m, -1] = -2 / dss[-1] ** 2 Ass.data[m - 2, 2:] *= gamma2_s[:-2] Ass.data[m - 1, 1:] *= gamma2_s[:-1] Ass.data[m, :] *= gamma2_s Ass.data[m + 1, :-1] *= gamma2_s[1:] Ass.data[m + 2, :-2] *= gamma2_s[2:] Rss *= gamma2_s L1_.append(As.copy()) L1_[j].data += Ass.data L1_[j].data[m, :] -= 0.5 * r * r_enable L1_[j].data[m, 0] = 1 * dirichlet_s R1_.append((Rs + Rss).copy()) R1_[j][0] = 0 L2_ = [] R2_ = [] Av_ = utils.nonuniform_complete_coefficients(dvs, up_or_down=up_or_down_var, flip_idx=flip_idx_var)[0] Avv_ = utils.nonuniform_complete_coefficients(dvs)[1] assert not np.isnan(Av_.data).any() assert not np.isnan(Avv_.data).any() for i, s in enumerate(spots): mu_v = kappa * (theta - vars) * v1_enable gamma2_v = 0.5 * sigma ** 2 * vars * v2_enable # for j, z in enumerate(mu_v): # assert z == coeffs[1,](0, 0, vars[j]) # for j, z in enumerate(gamma2_v): # assert z == coeffs[1,1](0, 0, vars[j]) # Be careful not to overwrite our operators Av, Avv = Av_.copy(), Avv_.copy() m = 2 Av.data[m - 2, 2] = -dvs[1] / (dvs[2] * (dvs[1] + dvs[2])) Av.data[m - 1, 1] = (dvs[1] + dvs[2]) / (dvs[1] * dvs[2]) Av.data[m, 0] = (-2 * dvs[1] - dvs[2]) / (dvs[1] * (dvs[1] + dvs[2])) Av.data[m - 2, 2:] *= mu_v[:-2] Av.data[m - 1, 1:] *= mu_v[:-1] Av.data[m, :] *= mu_v Av.data[m + 1, :-1] *= mu_v[1:] Av.data[m + 2, :-2] *= mu_v[2:] Rv = np.zeros(nvols) Rv *= mu_v Avv.data[m - 1, 1] = 2 / dvs[1] ** 2 Avv.data[m, 0] = -2 / dvs[1] ** 2 Avv.data[m - 2, 2:] *= gamma2_v[:-2] Avv.data[m - 1, 1:] *= gamma2_v[:-1] Avv.data[m, :] *= gamma2_v Avv.data[m + 1, :-1] *= gamma2_v[1:] Avv.data[m + 2, :-2] *= gamma2_v[2:] Rvv = np.zeros(nvols) Rvv[0] = 2 * dvs[1] / dvs[1] ** 2 Rvv *= gamma2_v L2_.append(Av.copy()) L2_[i].data += Avv.data L2_[i].data[m, :] -= 0.5 * r * r_enable L2_[i].data[m, -1] = 1 * dirichlet_v # This is to cancel out the previous value so we can # set the dirichlet boundary condition using R. # Then we have U_i + -U_i + R R2_.append(Rv + Rvv) R2_[i][-1] = 0 # np.maximum(0, s - k) def flatten_tensor(mats): diags = np.hstack([x.data for x in mats]) flatmat = scipy.sparse.dia_matrix((diags, mats[0].offsets), shape=(diags.shape[1], diags.shape[1])) return flatmat L1 = flatten_tensor(L1_) L2 = flatten_tensor(L2_) R1 = np.array(R1_).T R2 = np.array(R2_) self.As_ = As_ self.Ass_ = Ass_ self.L1_ = L1 self.R1_ = R1 self.L2_ = L2 self.R2_ = R2 # G = Grid.Grid((spots, vars), initializer=lambda x0,x1: np.maximum(x0-k,0)) self.G = Grid.Grid((spots, vars), initializer=lambda x0, x1: x0 * x1) # print G self.F = FD.FiniteDifferenceEngineADI( self.G, coefficients=coeffs, boundaries=bounds, schemes=schemes, force_bandwidth=None ) self.F.init()