def test_gbm_log_euler_step_is_deterministic(self): drift = 0.2 vol = 0.1 t = 0.0 dt = 0.01 num_samples = 8 key = 13 log_states = tf.zeros([num_samples]) eps_t = contrib_stateless.stateless_random_normal( shape=[num_samples], seed=[key, int(t / dt)]) next_log_states = dynamics.gbm_log_euler_step( log_states, drift, vol, t, dt, random_normal_op=lambda: eps_t) next_log_states_bis = dynamics.gbm_log_euler_step(log_states, drift, vol, t, dt, key=key) with self.session() as session: next_log_states_eval, next_log_states_bis_eval = session.run( (next_log_states, next_log_states_bis)) self.assertEqual(next_log_states_eval.shape, (num_samples, )) self.assertEqual(next_log_states_bis_eval.shape, (num_samples, )) self.assertAllClose(next_log_states_eval, next_log_states_bis_eval)
def test_gbm_log_euler_step_output_changes_with_key(self): drift = 0.2 vol = 0.1 t = 0.0 dt = 0.01 num_samples = 8 key_0 = 1137 key_1 = 0 log_states = tf.zeros([num_samples]) next_log_states_0 = dynamics.gbm_log_euler_step(log_states, drift, vol, t, dt, key=key_0) next_log_states_1 = dynamics.gbm_log_euler_step(log_states, drift, vol, t, dt, key=key_1) with self.session() as session: next_log_states_0_eval, next_log_states_1_eval = session.run( (next_log_states_0, next_log_states_1)) self.assertEqual(next_log_states_0_eval.shape, (num_samples, )) self.assertEqual(next_log_states_1_eval.shape, (num_samples, )) # The step is a bijection w.r.t. dw_t, all terms should be different. self.assertAllDistinct(next_log_states_0_eval, next_log_states_1_eval)
def test_gbm_log_euler_step_expects_static_shape(self): drift = 0.2 vol = 0.1 t = 0.0 dt = 0.01 log_states = tf.placeholder(dtype=tf.float32, shape=[None]) with self.assertRaises(ValueError): dynamics.gbm_log_euler_step(log_states, drift, vol, t, dt)
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))
def test_gbm_log_euler_step_output_is_correct(self): np.random.seed(0) drift = 0.2 vol = 0.1 t = 0.0 dt = 0.01 num_samples = 8 log_states = tf.zeros([num_samples]) eps_t = np.ndarray.astype(np.random.normal(size=[num_samples]), dtype=np.float32) next_log_states = dynamics.gbm_log_euler_step( log_states, drift, vol, t, dt, random_normal_op=lambda: eps_t) with self.session() as session: next_log_states_eval = session.run(next_log_states) self.assertEqual(next_log_states_eval.shape, (num_samples, )) self.assertAllClose( next_log_states_eval, np.zeros([num_samples], dtype=np.float32) + (drift - 0.5 * (vol**2)) * dt + vol * eps_t * np.sqrt(dt))