def run_test(self, instrument, barrier, outin, updown, price_expected, adjoint_expected): option = derivatives.BarrierCall(self.maturity, self.strike, barrier, self.rate, self.volatility, outin, updown) with tf.GradientTape() as tape: tape.watch(instrument) price_result = option.value(self.time, instrument, self.numeraire) delta_expected = tape.gradient(price_result, instrument) mask = tf.equal(delta_expected, delta_expected[..., -1, tf.newaxis]) updates = tf.cast(price_expected > 0, FLOAT_DTYPE) / self.numeraire delta_expected = tf.where(mask, updates, delta_expected) payoff_result = option.payoff(self.time, instrument, self.numeraire) delta_result = option.delta(self.time, instrument, self.numeraire) adjoint_result = option.adjoint(self.time, instrument, self.numeraire) payoff_expected = price_expected[..., -1] assert_near(price_result, price_expected, atol=1e-4) assert_near(delta_result[..., :-1], delta_expected[..., :-1]) assert_near(payoff_result, payoff_expected) assert_near(adjoint_result, adjoint_expected)
def test_value_delta(self): # https://www.math.drexel.edu/~pg/fin/VanillaCalculator.html maturity, strike, rate, volatility = 1, 100, 0.05, 0.2 binary = derivatives.BinaryCall(maturity, strike, volatility) time = tf.constant([0, 1 / 2, maturity], FLOAT_DTYPE) instrument = tf.constant([[100, 101, 91], [100., 121, 122]], FLOAT_DTYPE) numeraire = tf.math.exp(rate * time) price_expected = tf.constant([[ 0.532324834261914, 0.555946305588727, 0. ], [0.532324834261914, 0.904132417939148, 1.]]) / numeraire delta_expected = tf.constant([[ 0.018762017345847, 0.026819916282967, 0. ], [0.018762017345847, 0.007901435056954, 0.]]) / numeraire payoff_expected = price_expected[..., -1] adjoint_expected = tf.constant([[0., 0., 0.], [0., 0., 0.] ]) / numeraire[-1] price_result = binary.value(time, instrument, numeraire) delta_result = binary.delta(time, instrument, numeraire) payoff_result = binary.payoff(time, instrument, numeraire) adjoint_result = binary.adjoint(time, instrument, numeraire) assert_near(price_result, price_expected) assert_near(delta_result, delta_expected) assert_near(payoff_result, payoff_expected) assert_near(adjoint_result, adjoint_expected)
def test_call(self): maturity, strike, rate, volatility, theta = 0.25, 90, 0.05, 0.2, 1 jumpsize, jumpvol, intensity = 0.3, 0.2, 2.3 putcall = derivatives.JumpPutCall(maturity, strike, rate, volatility, intensity, jumpsize, jumpvol, theta) time = tf.constant([0, 0.1, maturity], FLOAT_DTYPE) instrument = tf.constant([[100, 110, 91], [100, 121, 85]], FLOAT_DTYPE) numeraire = tf.math.exp(rate * time) price_expected = tf.constant([[ 16.8930892792925, 21.1647925209847, 1.0 ], [16.8930892792925, 31.7191011838734, 0.0]]) / numeraire delta_expected = tf.constant([[ 0.573198330210462, 0.900506824015922, 1.0 ], [0.573198330210462, 0.990415604060569, 0.0]]) / numeraire payoff_expected = price_expected[..., -1] adjoint_expected = tf.constant([[0.91, 91 / 110, 1.], [0.0, 0.0, 0.0] ]) / numeraire[-1] price_result = putcall.value(time, instrument, numeraire) delta_result = putcall.delta(time, instrument, numeraire) payoff_result = putcall.payoff(time, instrument, numeraire) adjoint_result = putcall.adjoint(time, instrument, numeraire) assert_near(price_result, price_expected) assert_near(delta_result, delta_expected) assert_near(payoff_result, payoff_expected) assert_near(adjoint_result, adjoint_expected)
def test_value_delta_multivariate(self): init_instruments, init_numeraire, book = \ random_put_call_book(1.25, 10, 4, 3, 69) time, instruments, numeraire = book.sample_paths( init_instruments, init_numeraire, 3, 5, True) value_expected, delta_expected = self.lazy_marginal( instruments, numeraire, time, book) value_result = book.value(time, instruments, numeraire) delta_result = book.delta(time, instruments, numeraire) assert_near(value_result, value_expected) assert_near(delta_result, delta_expected)
def test_call(self): maturity, strike, rate, volatility, theta = 0.25, 90, 0.05, 0.2, 1 putcall = derivatives.PutCall(maturity, strike, rate, volatility, theta) time = tf.constant([0, 0.1, maturity], FLOAT_DTYPE) instrument = tf.constant([[100, 110, 91], [100., 121, 85]], FLOAT_DTYPE) numeraire = tf.math.exp(rate * time) price_expected = tf.constant([[ 11.670086691861101, 20.680949336572269, 1. ], [11.670086691861101, 31.672557545579522, 0.]]) / numeraire delta_expected = tf.constant([[ 0.89039005940552085, 0.99679661077351212, 1. ], [0.89039005940552085, 0.99996199608869929, 0.]]) / numeraire payoff_expected = price_expected[..., -1] adjoint_expected = tf.constant([[0.91, 91 / 110, 1.], [0., 0., 0.] ]) / numeraire[-1] price_result = putcall.value(time, instrument, numeraire) delta_result = putcall.delta(time, instrument, numeraire) payoff_result = putcall.payoff(time, instrument, numeraire) adjoint_result = putcall.adjoint(time, instrument, numeraire) assert_near(price_result, price_expected) assert_near(delta_result, delta_expected) assert_near(payoff_result, payoff_expected) assert_near(adjoint_result, adjoint_expected)
def test_value_delta_univariate(self): init_instruments, init_numeraire, book = simple_put_call_book( 1., 100., 105., 0.05, 0.1, 0.2, 1.) time, instruments, numeraire = book.sample_paths( init_instruments, init_numeraire, 1, 1, True) value_result = book.value(time, instruments, numeraire) delta_result = book.delta(time, instruments, numeraire) value_expected, delta_expected = self.lazy_marginal( instruments, numeraire, time, book) assert_near(value_result, value_expected) assert_near(delta_result, delta_expected)
def test_put_value_delta(self): maturity, strike, rate, volatility, theta = 1.3, 110, 0.02, 0.05, -1 putcall = derivatives.PutCall(maturity, strike, rate, volatility, theta) time = tf.constant([0, 0.41, maturity], FLOAT_DTYPE) instrument = tf.constant([[100, 110, 120], [110., 121, 85]], FLOAT_DTYPE) numeraire = tf.math.exp(rate * time) price_expected = tf.constant([[ 7.4973075500600146, 1.2255281792756278, 0. ], [1.3101071219942781, 0.014761684729265312, 25.]]) / numeraire delta_expected = tf.constant([[ -0.88244073147661295, -0.3442306041250397, 0. ], [-0.31398908314745166, -0.0077279609756593093, -1]]) / numeraire payoff_expected = price_expected[..., -1] price_result = putcall.value(time, instrument, numeraire) delta_result = putcall.delta(time, instrument, numeraire) payoff_result = putcall.payoff(time, instrument, numeraire) assert_near(price_result, price_expected) assert_near(delta_result, delta_expected) assert_near(payoff_result, payoff_expected)
def test_low_variance(self): batch, height, width = 2**20, 3, 2 x = get_low_variance_sample(batch, height, width, 69) inputs = [x[..., 0] for x in tf.split(x, width, axis=-1)] normaliser = preprocessing.MeanVarianceNormaliser() outputs = normaliser.fit_transform(inputs) for op in outputs: tf.debugging.assert_type(op, FLOAT_DTYPE) # test with FLOAT_DTYPE mean, variance = tf.nn.moments(op, 0) assert_near(mean, 0.) assert_near(variance, 1., atol=1e-2) # test with tf.float64 mean, variance = tf.nn.moments(tf.cast(op, tf.float64), 0) assert_near(mean, 0., atol=1e-8) assert_near(variance, 1., atol=1e-8) assert_near(normaliser.inverse_transform(outputs), inputs)
def test_sample_paths(self): one_dim = random_put_call_book(2.5, 1, 1, 1, 56) multi_dim = random_put_call_book(0.5, 4, 4, 1, 69) for init_instruments, init_numeraire, book in [one_dim, multi_dim]: num_paths, num_steps = 2**22, 2 time, instruments, numeraire = book.sample_paths( init_instruments, init_numeraire, num_paths, num_steps, True, use_sobol=True, skip=0) expected_dims = (num_paths, book.instrument_dim, num_steps + 1) self.assertTupleEqual(tuple(instruments.shape), expected_dims) expected_dims = (num_steps + 1, ) self.assertTupleEqual(tuple(numeraire.shape), expected_dims) payoff = book.payoff(time, instruments, numeraire) self.assertTupleEqual(tuple(payoff.shape), (num_paths, )) price_result = tf.reduce_mean(payoff) price_expected = book.value(time, instruments, numeraire)[0, 0] # convergence very slow assert_near(price_result, price_expected, atol=1e-1)
def test_degenerate_col(self): batch, height, width, degenerate = 6, 7, 8, 4 x = get_degenerate_sample(batch, height, width, degenerate, 69) inputs = [x[..., 0] for x in tf.split(x, width, axis=-1)] normaliser = preprocessing.MeanVarianceNormaliser() outputs = normaliser.fit_transform(inputs) for step, op in enumerate(outputs): assert_near(tf.reduce_mean(op, 0), 0.) expected_var = 0. if step == degenerate else 1. assert_near(tf.math.reduce_variance(op, 0), expected_var) assert_near(normaliser.inverse_transform(outputs), inputs)
def test_jaccard_index_loss(self, y_true, y_pred, expected): jaccard = JaccardIndexLoss() try: assert_near(jaccard(y_true, y_pred), expected) except errors.InvalidArgumentError as e: pytest.fail(e.message, pytrace=False)
def test_f1_score(self, y_true, y_pred, expected): try: assert_near(f1_score(y_true, y_pred), expected) except errors.InvalidArgumentError as e: pytest.fail(e.message, pytrace=False)
def test_dice_coef_metric(self, y_true, y_pred, expected): dice = DiceCoefMetric() try: assert_near(dice(y_true, y_pred), expected) except errors.InvalidArgumentError as e: pytest.fail(e.message, pytrace=False)