예제 #1
0
    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)
예제 #2
0
    ),
}

# 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
예제 #3
0
    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()