Exemplo n.º 1
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}"
                        )
Exemplo n.º 2
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)
Exemplo n.º 3
0
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
Exemplo n.º 4
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))
Exemplo n.º 5
0
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])