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}")
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}")
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}")
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}")
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)
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}" )
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))
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}")
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}")
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}")