예제 #1
0
    def test_distribution_is_uniform_like(self):
        rng = PimpedRandom()

        for _ in range(10):
            seed = np.random.randint(0, 100 * 1000)
            rng.seed(seed)
            n_variables = rng.randint(1, 10)
            sd = SobolGenerator(n_variables)
            n_paths = 1 << rng.randint(8, 12)
            sample = sd.generate(n_paths)

            for i_var in range(n_variables):
                v = sample[i_var]

                self.check_mean(v,
                                expected=0.5,
                                tol=0.03,
                                msg=f"Seed = {seed}")
                self.check_std_dev(v,
                                   expected=1.0 / np.sqrt(12),
                                   tol=0.01,
                                   msg=f"Seed = {seed}")

                for j_var in range(i_var + 1, n_variables):
                    self.check_uncorrelated(sample[i_var],
                                            sample[j_var],
                                            tol=0.03,
                                            msg=f"Seed = {seed}")
예제 #2
0
    def test_state_ranges(self):
        rng = PimpedRandom()

        for _ in range(100):
            seed = np.random.randint(0, 100 * 1000)
            # seed = 9120
            rng.seed(seed)

            max_volume = rng.randint(2, 6)
            initial_volume = rng.randint(0, max_volume)
            n_times = rng.randint(2, max_volume * 2)

            m1, m2 = state_ranges(initial_volume, max_volume, n_times)

            self.assertLessEqual(max(m2), max_volume, f"seed = {seed}")
            self.assertLessEqual(max(m1), max_volume, f"seed = {seed}")
            self.assertGreaterEqual(min(m2), 0, f"seed = {seed}")
            self.assertGreaterEqual(min(m1), 0, f"seed = {seed}")

            self.assertEqual(m1[0], initial_volume)
            self.assertEqual(m2[0], initial_volume)
            self.assertEqual(m1[n_times], initial_volume)
            self.assertEqual(m2[n_times], initial_volume)

            for i_time in range(0, n_times):
                self.assertLessEqual(abs(m1[i_time] - m1[i_time + 1]), 1,
                                     f"Seed = {seed}")
                self.assertLessEqual(m1[i_time], initial_volume,
                                     f"Seed = {seed}")
                self.assertGreaterEqual(m2[i_time], initial_volume,
                                        f"Seed = {seed}")
                self.assertLessEqual(abs(m2[i_time] - m2[i_time + 1]), 1,
                                     f"Seed = {seed}")
예제 #3
0
    def test_spike(self):
        rng = PimpedRandom()
        for _ in range(10):
            seed = np.random.randint(0, 100 * 1000)
            rng.seed(seed)
            n_times = np.random.randint(1, 10)
            times = random_times(rng, n_times)
            n_paths = 1024 << 2
            uniforms = np.random.rand(n_paths, n_times)
            bldr = BrownianBridge(times)
            paths = [bldr.generate(u) for u in uniforms]

            for i_time in range(n_times):
                sample = [p[i_time] for p in paths]
                expected_std_dev = np.sqrt(times[i_time])
                self.assertAlmostEqual(np.asscalar(np.mean(sample)),
                                       0.0,
                                       delta=expected_std_dev * 4.0 /
                                       np.sqrt(n_paths),
                                       msg=f"Seed = {seed}")

                sample_std_dev = np.asscalar(np.std(sample))
                self.assertAlmostEqual(sample_std_dev,
                                       expected_std_dev,
                                       delta=0.02,
                                       msg=f"Seed = {seed}")
예제 #4
0
    def test_european_close_to_black_scholes(self):
        rng = PimpedRandom()

        for _ in range(10):
            seed = np.random.randint(0, 100 * 1000)
            rng.seed(seed)

            market_day = Day(2018, 1, 1)
            option = random_option(rng, ex_style=ExerciseStyle.EUROPEAN)
            sigma = rng.random() * 0.5
            fwd_price = rng.uniform(option.strike - 1.0, option.strike + 1.0)

            r = 0.1 * rng.random()

            numeric_value = option.cn_value(market_day, fwd_price, sigma, r)

            def bs_value(s):
                return option.european_value(market_day, fwd_price, s, r)

            analytic_value = bs_value(sigma)
            tol = max(
                bs_value(sigma + 0.01) - analytic_value, 0.01,
                analytic_value * 0.01)

            self.assertAlmostEqual(numeric_value,
                                   analytic_value,
                                   delta=tol,
                                   msg=f"Seed was {seed}")
예제 #5
0
    def test_process(self):

        rng = PimpedRandom()

        for _ in range(10):
            seed = np.random.randint(0, 100 * 1000)
            rng.seed(seed)

            sigma = rng.random() * 0.5
            tilt_vol = rng.uniform(0.0, 1.5)
            n_times = rng.randint(1, 5)
            n_paths = 1024
            times = random_times(rng, n_times)
            brownians = generate_brownians(n_paths, 2, times)
            fwd_price = rng.uniform(90.0, 100.0)
            fwd_prices = np.full((n_times, ), fwd_price)

            process = CombinedPriceProcess(fwd_prices,
                                           times,
                                           sigma,
                                           tilt_vol=tilt_vol)
            for i_time in range(n_times):
                t = times[i_time]
                s1 = lognorm.std(sigma * sqrt(t), 0,
                                 fwd_price * exp(-0. * sigma * sigma * t))
                s2 = tilt_vol * sqrt(t)
                std_dev = sqrt(s1 * s1 + s2 * s2)
                std_err = std_dev / sqrt(n_paths)
                prices = process.generate(brownians, i_time)
                self.check_mean(prices, fwd_price, 4.0 * std_err)
                self.check_std_dev(prices, std_dev, std_dev * 0.1)
예제 #6
0
    def test_independence(self):
        rng = PimpedRandom()

        for _ in range(5):
            seed = np.random.random()
            rng.seed(seed)

            n_paths = 1024 << 2
            n_variables = rng.randint(2, 4)
            n_times = rng.randint(1, 6)
            times = random_times(rng, n_times)

            brownians = generate_brownians(n_paths, n_variables, times)

            for i_time in range(n_times):
                for i_var in range(n_variables):
                    sample_i = brownians[:, i_var, i_time]

                    self.check_std_dev(sample_i, np.sqrt(times[i_time]), tol=0.03, msg=f"Seed = {seed}")
                    self.check_mean(sample_i, 0.0, tol=0.03, msg=f"Seed = {seed}")

                    for j_var in range(i_var + 1, n_variables):
                        sample_j = brownians[:, j_var, i_time]
                        self.check_uncorrelated(
                            sample_i,
                            sample_j,
                            tol=0.03,
                            msg=f"Seed = {seed}"
                        )
예제 #7
0
    def test_shape(self):

        rng = PimpedRandom()

        for _ in range(5):
            seed = np.random.random()
            rng.seed(seed)

            n_paths = 100
            n_variables = rng.randint(1, 4)
            n_times = rng.randint(50, 100)
            times = random_times(rng, n_times)

            brownians = generate_brownians(n_paths, n_variables, times)
            self.assertEqual(brownians.shape, (n_paths, n_variables, n_times))
예제 #8
0
    def test_intrinsic(self):
        rng = PimpedRandom()
        for _ in range(100):
            seed = np.random.randint(0, 100 * 1000)
            rng.seed(seed)
            option = random_option(rng, ex_style=ExerciseStyle.EUROPEAN)
            market_day = Day(2018, 1, 1)
            fwd_price = option.strike + rng.uniform(-2.0, 2.0)

            self.assertAlmostEqual(option.european_value(market_day,
                                                         fwd_price,
                                                         sigma=1e-5,
                                                         r=0.0),
                                   option.intrinsic(fwd_price),
                                   delta=1e-3,
                                   msg=f"Seed was {seed}")
예제 #9
0
    def test_american_worth_at_least_intrinsic(self):
        rng = PimpedRandom()

        for _ in range(5):
            seed = np.random.randint(0, 100 * 1000)
            rng.seed(seed)

            market_day = Day(2018, 1, 1)
            option = random_option(rng, ex_style=ExerciseStyle.AMERICAN)
            fwd_price = rng.uniform(option.strike - 1.0, option.strike + 1.0)
            sigma = rng.random() * 0.5
            r = 0.1 * rng.random()

            numeric_value = option.cn_value(market_day, fwd_price, sigma, r)
            intrinsic_value = option.intrinsic(fwd_price)

            self.assertGreaterEqual(numeric_value,
                                    intrinsic_value,
                                    msg=f"Seesd was {seed}")
예제 #10
0
    def test_mc_value_close_to_bs(self):
        rng = PimpedRandom()

        for _ in range(5):
            seed = np.random.randint(0, 100 * 1000)
            rng.seed(seed)

            market_day = Day(2018, 1, 1)
            option = random_option(rng, ex_style=ExerciseStyle.EUROPEAN)
            fwd_price = rng.uniform(option.strike - 1.0, option.strike + 1.0)
            sigma = rng.random() * 0.5
            r = 0.1 * rng.random()

            mc_value = option.mc_european_value(market_day, fwd_price, sigma,
                                                r)
            bs_value = option.european_value(market_day, fwd_price, sigma, r)

            self.assertAlmostEqual(mc_value,
                                   bs_value,
                                   delta=0.1,
                                   msg=f"Seesd was {seed}")