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_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 monte_carlo_european_value(right: OptionRight, strike: float, fwd_price: float, sigma: float, r: float, time_to_expiry: float, n_paths: int) -> float: def to_payoff(z: float): price = fwd_price * exp(z * sigma - 0.5 * sigma * sigma * time_to_expiry) return intrinsic_value(right, strike, price) brownians = generate_brownians(n_paths, n_variables=1, times=np.array([time_to_expiry]))[:, 0, 0] payoffs = np.vectorize(to_payoff)(brownians) disc = exp(-r * time_to_expiry) return np.mean(payoffs) * disc
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 value_storage_unit( initial_volume: int, max_volume: int, process: CombinedPriceProcess, n_paths: int) -> float: n_times = len(process.times) brownians = generate_brownians(n_paths, n_variables=2, times=process.times) min_levels, max_levels = state_ranges(initial_volume, max_volume, n_times) n_states = max_volume + 1 state_values_eod = np.zeros((n_states, n_paths), float) state_values_sod = np.zeros((n_states, n_paths), float) for i_exercise in range(n_times - 1, -1, -1): sod_range = range(min_levels[i_exercise], max_levels[i_exercise] + 1) full_eod_range = range(min_levels[i_exercise + 1], max_levels[i_exercise + 1] + 1) dm = _design_matrix(brownians, i_exercise) cond_exps = np.zeros((len(full_eod_range), n_paths), float) min_eod_state = full_eod_range[0] for i_eod in full_eod_range: post_ex_values = state_values_eod[i_eod] cond_exps[i_eod - min_eod_state] = cond_exp(dm, post_ex_values) print(f"ex {i_exercise}") print(cond_exps) prices = process.generate(brownians, i_exercise) for i_sod in sod_range: i_eod_min = max(i_sod - 1, min_levels[i_exercise + 1]) i_eod_max = min(i_sod + 1, max_levels[i_exercise + 1]) def transfer_value(price, i_eod): d_volume = i_eod - i_sod return price * -d_volume def transition_value(price, i_eod, i_path): return transfer_value(price, i_eod) + cond_exps[i_eod - min_eod_state, i_path] for i_path in range(n_paths): price = prices[i_path] i_best_eod = i_eod_min best_transition_value = transition_value(price, i_eod_min, i_path) for i_eod in range(i_eod_min + 1, i_eod_max + 1): next_value = transition_value(price, i_eod, i_path) if next_value > best_transition_value: best_transition_value = next_value i_best_eod = i_eod state_values_sod[i_sod, i_path] = transfer_value(price, i_best_eod) + state_values_eod[i_best_eod, i_path] if i_path == 17: print(f"sod = {i_sod}, best eod {i_best_eod}, value {state_values_sod[i_sod, i_path]}") print("SOD") print(state_values_sod) tmp = state_values_eod state_values_eod = state_values_sod state_values_sod = tmp return np.mean(state_values_eod[initial_volume])