Ejemplo n.º 1
0
def add_butterfly(init_instruments, book, spread):
    dimension = book.instrument_dim
    if dimension != len(init_instruments):
        raise ValueError("wrong dimension of init_instruments.")
    for link, spot in enumerate(init_instruments):
        itm = derivatives.PutCall(
            book.maturity,
            spot - spread / 2,
            book.numeraire_simulator.rate,
            book.instrument_simulator.volatility[link],
            1)
        atm = derivatives.PutCall(
            book.maturity,
            spot,
            book.numeraire_simulator.rate,
            book.instrument_simulator.volatility[link],
            1)
        otm = derivatives.PutCall(
            book.maturity,
            spot + spread / 2,
            book.numeraire_simulator.rate,
            book.instrument_simulator.volatility[link],
            1)

        book.add_derivative(itm, link, 1 / dimension)
        book.add_derivative(atm, link, -2 / dimension)
        book.add_derivative(otm, link, 1 / dimension)
Ejemplo n.º 2
0
    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)
Ejemplo n.º 3
0
    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)
Ejemplo n.º 4
0
def add_calls(init_instruments, book):
    dimension = book.instrument_dim
    if dimension != len(init_instruments):
        raise ValueError("wrong dimension of init_instruments.")

    for link in tf.range(dimension):
        derivative = derivatives.PutCall(
            book.maturity,
            init_instruments[link],
            book.numeraire_simulator.rate,
            book.instrument_simulator.volatility[link],
            1
            )

        book.add_derivative(derivative, link, 1 / dimension)
Ejemplo n.º 5
0
    def test_call(self):
        drift = tf.constant([0.0191846154, 0.0171541667, 0.0045500000],
                            FLOAT_DTYPE)
        volatility = tf.constant([0.2920484681, 0.2823561581, 0.2100000000],
                                 FLOAT_DTYPE)

        gs = tf.constant(
            [[398.1071705535, 297.8632906618, 484.5364955981, 455.9051533831],
             [450.6200285030, 510.0596651041, 505.0054119235, 396.7001896122]],
            FLOAT_DTYPE)

        scale = tf.constant(
            [[5.1753932172, 4.8402784733, 4.8453649560, 2.9012146124],
             [5.3255094278, 5.4799798730, 5.0500541192, 3.2669427380]],
            FLOAT_DTYPE)

        result_value = self.option.value(self.time, self.instrument,
                                         self.numeraire)
        result_delta = self.option.delta(self.time, self.instrument,
                                         self.numeraire)
        result_adjoint = self.option.adjoint(self.time, self.instrument,
                                             self.numeraire)

        for k, (d, v) in enumerate(zip(drift, volatility)):
            benchmark = derivatives.PutCall(self.maturity, self.strike, d, v,
                                            self.option.theta)

            expected_value = benchmark.value(self.time, gs, self.numeraire)
            expected_delta = benchmark.delta(self.time, gs, self.numeraire) \
                * scale
            expected_adjoint = benchmark.adjoint(self.time, gs,
                                                 self.numeraire) * scale

            tf.debugging.assert_near(result_value[..., k], expected_value[...,
                                                                          k])

            tf.debugging.assert_near(result_delta[..., k], expected_delta[...,
                                                                          k])

            tf.debugging.assert_near(result_adjoint[..., k],
                                     expected_adjoint[..., k])
Ejemplo n.º 6
0
def add_random_putcalls(init_instruments, book, number_of_derivatives=3):
    dimension = book.instrument_dim
    if dimension != len(init_instruments):
        raise ValueError("wrong dimension of init_instruments.")

    for link in tf.range(dimension):
        for _ in tf.range(number_of_derivatives):
            spot = init_instruments[link]
            strike = tf.random.uniform((1, ), minval=spot - 10.0,
                                       maxval=spot + 10.0)
            theta = tf.sign(tf.random.uniform((1, )) - 0.5)

            derivative = derivatives.PutCall(
                book.maturity,
                strike,
                book.numeraire_simulator.rate,
                book.instrument_simulator.volatility[link],
                theta
                )

            book.add_derivative(derivative, link, 1 / dimension)
Ejemplo n.º 7
0
        d = (instrument - self.strike) / vol_time

        return -d * self.delta(time, instrument, numeraire)


cost = False

spot = 1
strike = 1
timesteps = 14
sigma = 0.2
maturity = timesteps / 250

if cost:
    instrument_simulator = simulators.GBM(0.0, 0.0, [[sigma]])
    derivative = derivatives.PutCall(maturity, strike, 0.0, sigma, 1)
else:
    instrument_simulator = BrownianMotion(sigma)
    derivative = BachelierBinary(maturity, strike, sigma)
numeraire_simulator = simulators.ConstantBankAccount(0.0)

book = books.DerivativeBook(maturity, instrument_simulator,
                            numeraire_simulator)

book.add_derivative(derivative, 0, 1.0)

init_instruments = tf.constant([spot], FLOAT_DTYPE)
init_numeraire = tf.constant([1.0], FLOAT_DTYPE)

driver = utils.HedgeDriver(
    timesteps=timesteps,
Ejemplo n.º 8
0
import derivatives
import random_books
import gradient_models
import gradient_driver
import hedge_models

tf.get_logger().setLevel('ERROR')

timesteps = 13
init_instruments, init_numeraire, book = random_books.random_empty_book(
    timesteps / 52, 1, 0.02, 0.05, 0.2)
init_numeraire = tf.ones_like(init_numeraire)

spread = 10
itm = derivatives.PutCall(book.maturity, init_instruments - spread / 2,
                          book.instrument_simulator.rate,
                          book.instrument_simulator.volatility, 1)
atm = derivatives.PutCall(book.maturity, init_instruments,
                          book.instrument_simulator.rate,
                          book.instrument_simulator.volatility, 1)
otm = derivatives.PutCall(book.maturity, init_instruments + spread / 2,
                          book.instrument_simulator.rate,
                          book.instrument_simulator.volatility, 1)

book.add_derivative(itm, 0, 1)
book.add_derivative(atm, 0, -2)
book.add_derivative(otm, 0, 1)

# ==============================================================================
# === train gradient models
warmup_train_size = int(sys.argv[1])
Ejemplo n.º 9
0
import random_books
import utils
import hedge_models
import derivatives

# ==============================================================================
# === hyperparameters
train_size, test_size, timesteps = int(2**10), int(2**20), 30
alpha = 0.95

# ==============================================================================
# === sample data
init_instruments, init_numeraire, book = random_books.random_empty_book(
    1.0, 1, 0.05, 0.1, 0.2, seed=69)
derivative = derivatives.PutCall(book.maturity, 105.0,
                                 book.numeraire_simulator.rate,
                                 book.instrument_simulator.volatility, 1)
book.add_derivative(derivative, 0, 1.0)

driver = utils.HedgeDriver(
    timesteps=timesteps,
    frequency=0,  # no need for frequency
    init_instruments=init_instruments,
    init_numeraire=init_numeraire,
    book=book,
    cost=None,
    risk_neutral=False,
    learning_rate=1e-1)

driver.add_testcase("delta",
                    hedge_models.FeatureHedge(),