Ejemplo n.º 1
0
class HestonOption_test(unittest.TestCase):

    def setUp(self):
        DefaultHeston = HestonOption(spot=100
                        , strike=100
                        , interest_rate=0.03
                        , volatility = 0.2
                        , tenor=1.0
                        , mean_reversion = 1
                        , mean_variance = 0.12
                        , vol_of_variance = 0.3
                        , correlation = 0.4
                        )
        option = DefaultHeston
        # option = HestonOption(tenor=1, strike=99.0, volatility=0.2,
                                        # mean_reversion=3, mean_variance=0.04,
                                        # vol_of_variance=0.6, correlation=-0.7)


        self.dt = 1.0/150.0
        self.F = HestonFiniteDifferenceEngine(option, nspots=150,
                                                   nvols=80,
                                                   force_bandwidth=None,
                                                   flip_idx_var=False)


        # self.F = HestonFiniteDifferenceEngine(H, nspots=100,
                                         # nvols=100, spotdensity=10, varexp=4,
                                         # var_max=12, flip_idx_spot=False,
                                         # flip_idx_var=False, verbose=False,
                                         # force_bandwidth=None,
                                         # force_exact=False)
        self.F.init()
        self.F.operators[1].diagonalize()


    def test_implicit(self):
        t, dt = self.F.option.tenor, self.dt
        dt = 1.0/600.0
        for d, o in self.F.operators.items():
            if type(d) != tuple:
                assert o.is_tridiagonal(), "%s, %s" % (d, o.D.offsets)
        V = self.F.solve_implicit(t/dt, dt)[self.F.idx]
        ans = self.F.option.analytical
        # print "Spot:", self.F.option.spot
        # print "Price:", V, ans, V - ans
        npt.assert_allclose(V, ans, rtol=0.001)


    def test_douglas(self):
        t, dt = self.F.option.tenor, self.dt
        for d, o in self.F.operators.items():
            if type(d) != tuple:
                assert o.is_tridiagonal(), "%s, %s" % (d, o.D.offsets)
        V = self.F.solve_douglas(t/dt, dt)[self.F.idx]
        ans = self.F.option.analytical
        # print "Spot:", self.F.option.spot
        # print "Price:", V, ans, V - ans
        npt.assert_allclose(V, ans, rtol=0.001)


    def test_smooth(self):
        t, dt = self.F.option.tenor, self.dt
        for d, o in self.F.operators.items():
            if type(d) != tuple:
                assert o.is_tridiagonal(), "%s, %s" % (d, o.D.offsets)
        V = self.F.solve_smooth(t/dt, dt)[self.F.idx]
        ans = self.F.option.analytical
        # print "Spot:", self.F.option.spot
        # print "Price:", V, ans, V - ans
        npt.assert_allclose(V, ans, rtol=0.001)
class HestonBarrierOption_test(unittest.TestCase):

    def setUp(self):
        DefaultHeston = HestonBarrierOption(spot=100
                        , strike=100
                        , interest_rate=0.06
                        , volatility = 0.2
                        , tenor=1.0
                        , mean_reversion = 1
                        , mean_variance = 0.12
                        , vol_of_variance = 0.3
                        , correlation = 0.4
                        , top = (False, 170.0)
                        )
        option = DefaultHeston
        # option = HestonOption(tenor=1, strike=99.0, volatility=0.2,
                                        # mean_reversion=3, mean_variance=0.04,
                                        # vol_of_variance=0.6, correlation=-0.7)


        self.dt = 1.0/150.0
        self.F = HestonFiniteDifferenceEngine(option, nspots=150,
                                                   nvols=80,
                                                   force_bandwidth=None,
                                                   flip_idx_var=False)


        self.F.init()
        self.F.operators[1].diagonalize()
        self.FG = FDG.HestonFiniteDifferenceEngine(option,
                                                   nspots=self.F.grid.shape[0],
                                                   nvols=self.F.grid.shape[1])
        self.FG.make_operator_templates()
        self.FG.set_zero_derivative()
        self.FG.scale_and_combine_operators()


    def test_implicit(self):
        t, dt = self.F.option.tenor, self.dt
        dt = 1/600.0
        for d, o in self.F.operators.items():
            if type(d) != tuple:
                assert o.is_tridiagonal(), "%s, %s" % (d, o.D.offsets)
        V = self.FG.solve_implicit(t/dt, dt, self.F.grid.domain[-1])[self.F.idx]
        V2 = self.F.solve_implicit(t/dt, dt, self.F.grid.domain[-1])[self.F.idx]
        # ans = self.F.option.analytical
        # print "Spot:", self.F.option.spot
        # print "Price:", V2, V, ans, V - ans
        npt.assert_array_almost_equal(V, V2, decimal=6)
        # npt.assert_allclose(V, ans, rtol=0.001)


    def test_douglas(self):
        t, dt = self.F.option.tenor, self.dt
        for d, o in self.F.operators.items():
            if type(d) != tuple:
                assert o.is_tridiagonal(), "%s, %s" % (d, o.D.offsets)
        V = self.FG.solve_douglas(t/dt, dt, self.F.grid.domain[-1])[self.F.idx]
        V2 = self.F.solve_douglas(t/dt, dt, self.F.grid.domain[-1])[self.F.idx]
        # ans = self.F.option.analytical
        # print "Spot:", self.F.option.spot
        # print "Price:", V, ans, V - ans
        # npt.assert_allclose(V, ans, rtol=0.001)
        npt.assert_array_almost_equal(V, V2, decimal=6)


    def test_hundsdorferverwer(self):
        t, dt = self.F.option.tenor, self.dt
        for d, o in self.F.operators.items():
            if type(d) != tuple:
                assert o.is_tridiagonal(), "%s, %s" % (d, o.D.offsets)
        V = self.FG.solve_hundsdorferverwer(t/dt, dt, self.F.grid.domain[-1])[self.F.idx]
        V2 = self.F.solve_hundsdorferverwer(t/dt, dt, self.F.grid.domain[-1])[self.F.idx]
        # ans = self.F.option.analytical
        # print "Spot:", self.F.option.spot
        # print "Price:", V2, V, ans, V - ans
        # npt.assert_allclose(V, ans, rtol=0.001)
        npt.assert_array_almost_equal(V, V2, decimal=7)


    def test_smooth(self):
        t, dt = self.F.option.tenor, self.dt
        for d, o in self.F.operators.items():
            if type(d) != tuple:
                assert o.is_tridiagonal(), "%s, %s" % (d, o.D.offsets)
        V = self.FG.solve_smooth(t/dt, dt, self.F.grid.domain[-1])[self.F.idx]
        V2 = self.F.solve_smooth(t/dt, dt, self.F.grid.domain[-1])[self.F.idx]
        # ans = self.F.option.analytical
        # print "Spot:", self.F.option.spot
        # print "Price:", V, ans, V - ans
        # npt.assert_allclose(V, ans, rtol=0.001)
        npt.assert_array_almost_equal(V, V2, decimal=7)
class HestonBarrierOption_test(unittest.TestCase):
    def setUp(self):
        DefaultHeston = HestonBarrierOption(spot=100,
                                            strike=100,
                                            interest_rate=0.06,
                                            volatility=0.2,
                                            tenor=1.0,
                                            mean_reversion=1,
                                            mean_variance=0.12,
                                            vol_of_variance=0.3,
                                            correlation=0.4,
                                            top=(False, 170.0))
        option = DefaultHeston
        # option = HestonOption(tenor=1, strike=99.0, volatility=0.2,
        # mean_reversion=3, mean_variance=0.04,
        # vol_of_variance=0.6, correlation=-0.7)

        self.dt = 1.0 / 150.0
        self.F = HestonFiniteDifferenceEngine(option,
                                              nspots=150,
                                              nvols=80,
                                              force_bandwidth=None,
                                              flip_idx_var=False)

        self.F.init()
        self.F.operators[1].diagonalize()
        self.FG = FDG.HestonFiniteDifferenceEngine(option,
                                                   nspots=self.F.grid.shape[0],
                                                   nvols=self.F.grid.shape[1])
        self.FG.make_operator_templates()
        self.FG.set_zero_derivative()
        self.FG.scale_and_combine_operators()

    def test_implicit(self):
        t, dt = self.F.option.tenor, self.dt
        dt = 1 / 600.0
        for d, o in self.F.operators.items():
            if type(d) != tuple:
                assert o.is_tridiagonal(), "%s, %s" % (d, o.D.offsets)
        V = self.FG.solve_implicit(t / dt, dt,
                                   self.F.grid.domain[-1])[self.F.idx]
        V2 = self.F.solve_implicit(t / dt, dt,
                                   self.F.grid.domain[-1])[self.F.idx]
        # ans = self.F.option.analytical
        # print "Spot:", self.F.option.spot
        # print "Price:", V2, V, ans, V - ans
        npt.assert_array_almost_equal(V, V2, decimal=6)
        # npt.assert_allclose(V, ans, rtol=0.001)

    def test_douglas(self):
        t, dt = self.F.option.tenor, self.dt
        for d, o in self.F.operators.items():
            if type(d) != tuple:
                assert o.is_tridiagonal(), "%s, %s" % (d, o.D.offsets)
        V = self.FG.solve_douglas(t / dt, dt,
                                  self.F.grid.domain[-1])[self.F.idx]
        V2 = self.F.solve_douglas(t / dt, dt,
                                  self.F.grid.domain[-1])[self.F.idx]
        # ans = self.F.option.analytical
        # print "Spot:", self.F.option.spot
        # print "Price:", V, ans, V - ans
        # npt.assert_allclose(V, ans, rtol=0.001)
        npt.assert_array_almost_equal(V, V2, decimal=6)

    def test_hundsdorferverwer(self):
        t, dt = self.F.option.tenor, self.dt
        for d, o in self.F.operators.items():
            if type(d) != tuple:
                assert o.is_tridiagonal(), "%s, %s" % (d, o.D.offsets)
        V = self.FG.solve_hundsdorferverwer(t / dt, dt,
                                            self.F.grid.domain[-1])[self.F.idx]
        V2 = self.F.solve_hundsdorferverwer(t / dt, dt,
                                            self.F.grid.domain[-1])[self.F.idx]
        # ans = self.F.option.analytical
        # print "Spot:", self.F.option.spot
        # print "Price:", V2, V, ans, V - ans
        # npt.assert_allclose(V, ans, rtol=0.001)
        npt.assert_array_almost_equal(V, V2, decimal=7)

    def test_smooth(self):
        t, dt = self.F.option.tenor, self.dt
        for d, o in self.F.operators.items():
            if type(d) != tuple:
                assert o.is_tridiagonal(), "%s, %s" % (d, o.D.offsets)
        V = self.FG.solve_smooth(t / dt, dt,
                                 self.F.grid.domain[-1])[self.F.idx]
        V2 = self.F.solve_smooth(t / dt, dt,
                                 self.F.grid.domain[-1])[self.F.idx]
        # ans = self.F.option.analytical
        # print "Spot:", self.F.option.spot
        # print "Price:", V, ans, V - ans
        # npt.assert_allclose(V, ans, rtol=0.001)
        npt.assert_array_almost_equal(V, V2, decimal=7)