Exemple #1
0
    def test_call_put_parity(self):
        current_price = 100.0
        interest_rate = 0.05
        vol = 0.2
        strike = 120.0
        maturity = 1.0

        call_price = util.black_scholes_call_price(current_price,
                                                   interest_rate, vol, strike,
                                                   maturity)
        put_price = util.black_scholes_put_price(current_price, interest_rate,
                                                 vol, strike, maturity)
        total_price = current_price - strike * tf.exp(
            -interest_rate * maturity)

        with self.test_session() as session:

            call_price_eval = session.run(call_price)
            put_price_eval = session.run(put_price)
            total_price_eval = session.run(total_price)

        self.assertGreater(call_price_eval, 0.0)
        self.assertGreater(put_price_eval, 0.0)
        self.assertAlmostEqual(call_price_eval - put_price_eval,
                               total_price_eval,
                               delta=1e-5)
Exemple #2
0
    def test_european_derivative_price_delta_mc_close_to_black_scholes(self):
        current_price = tf.constant(100.0, dtype=tf.float32)
        r = 0.05
        vol = tf.constant([[0.2]], dtype=tf.float32)
        strike = 100.0
        maturity = 0.1
        dt = 0.01

        bs_call_price = util.black_scholes_call_price(current_price, r, vol,
                                                      strike, maturity)
        bs_delta = monte_carlo_manager.sensitivity_autodiff(
            bs_call_price, current_price)

        num_samples = int(1e3)
        initial_states = tf.ones([num_samples, 1]) * current_price

        def _dynamics_op(log_s, t, dt):
            return dynamics.gbm_log_euler_step_nd(log_s, r, vol, t, dt, key=1)

        def _payoff_fn(log_s):
            return tf.exp(-r * maturity) * payoffs.call_payoff(
                tf.exp(log_s), strike)

        (_, _, outcomes) = monte_carlo_manager.non_callable_price_mc(
            tf.log(initial_states), _dynamics_op, _payoff_fn, maturity,
            num_samples, dt)

        mc_deltas = monte_carlo_manager.sensitivity_autodiff(
            outcomes, initial_states)

        mean_mc_deltas = tf.reduce_mean(mc_deltas)
        mc_deltas_std = tf.sqrt(
            tf.reduce_mean(mc_deltas**2) - (mean_mc_deltas**2))

        with self.test_session() as session:
            bs_delta_eval = session.run(bs_delta)
            mean_mc_deltas_eval, mc_deltas_std_eval = session.run(
                (mean_mc_deltas, mc_deltas_std))

        self.assertLessEqual(
            mean_mc_deltas_eval,
            bs_delta_eval + 3.0 * mc_deltas_std_eval / np.sqrt(num_samples))
        self.assertGreaterEqual(
            mean_mc_deltas_eval,
            bs_delta_eval - 3.0 * mc_deltas_std_eval / np.sqrt(num_samples))
Exemple #3
0
    def test_european_call_estimator_converges_close_to_black_scholes(self):
        current_price = 100.0
        r = interest_rate = 0.05
        vol = 0.2
        strike = 120.0
        maturity = 0.5
        dt = 0.001
        discount = tf.exp(-r * maturity)

        tol = 5e-2
        conf_level = 0.95
        batch_size = int(1e4)
        k = key_placeholder = tf.placeholder(shape=(), dtype=tf.int32)
        max_num_steps = 1e5

        bs_call_price = util.black_scholes_call_price(current_price,
                                                      interest_rate, vol,
                                                      strike, maturity)

        initial_state = tf.constant(current_price)

        dynamics_op = lambda s, t, dt: dynamics.gbm_euler_step(
            s, r, vol, t, dt, k)
        payoff_fn = lambda s: discount * payoffs.call_payoff(s, strike)

        (mean_est, mean_sq_est, _) = monte_carlo_manager.non_callable_price_mc(
            initial_state, dynamics_op, payoff_fn, maturity, batch_size, dt)

        with self.test_session() as session:
            (mean_est_eval, _, converged) = monte_carlo_manager.mc_estimator(
                mean_est, mean_sq_est, batch_size, key_placeholder, {}, tol,
                conf_level, max_num_steps, session)

            bs_call_price_eval = session.run(bs_call_price)

        self.assertTrue(converged)
        # Here the discretization bias would make these asserts fail with larger dt.
        self.assertLessEqual(mean_est_eval, bs_call_price_eval * (1.0 + tol))
        self.assertGreaterEqual(mean_est_eval,
                                bs_call_price_eval * (1.0 - tol))
Exemple #4
0
    def test_european_call_log_euler_mc_close_to_black_scholes(self):
        current_price = 100.0
        r = interest_rate = 0.05
        vol = 0.2
        strike = 120.0
        maturity = 0.5
        dt = 0.01
        discount = tf.exp(-r * maturity)

        bs_call_price = util.black_scholes_call_price(current_price,
                                                      interest_rate, vol,
                                                      strike, maturity)

        num_samples = int(1e4)
        initial_state = tf.constant(current_price)

        dynamics_op = lambda s, t, dt: dynamics.gbm_log_euler_step(
            s, r, vol, t, dt)
        payoff_fn = lambda s: discount * payoffs.call_payoff(tf.exp(s), strike)

        (mean_outcome, mean_sq_outcome,
         _) = monte_carlo_manager.non_callable_price_mc(
             tf.log(initial_state), dynamics_op, payoff_fn, maturity,
             num_samples, dt)

        std_outcomes = util.stddev_est(mean_outcome, mean_sq_outcome)

        with self.test_session() as session:
            bs_call_price_eval = session.run(bs_call_price)
            mean_outcome_eval, std_outcomes_eval = session.run(
                (mean_outcome, std_outcomes))

        self.assertLessEqual(
            mean_outcome_eval, bs_call_price_eval +
            3.0 * std_outcomes_eval / np.sqrt(num_samples))
        self.assertGreaterEqual(
            mean_outcome_eval, bs_call_price_eval -
            3.0 * std_outcomes_eval / np.sqrt(num_samples))