Exemple #1
0
    def test_should_cancel_all_orders_outside_bands(self, deployment: Deployment, tmpdir):
        # given
        config_file = BandConfig.sample_config(tmpdir)

        # and
        keeper = OasisMarketMakerKeeper(args=args(f"--eth-from {deployment.our_address} "
                                                  f"--tub-address {deployment.tub.address} "
                                                  f"--oasis-address {deployment.otc.address} "
                                                  f"--config {config_file}"),
                                        web3=deployment.web3)
        keeper.lifecycle = Web3Lifecycle(web3=keeper.web3)

        # and
        self.mint_tokens(deployment)
        self.set_price(deployment, Wad.from_number(100))

        # and
        keeper.approve()
        self.synchronize_orders_twice(keeper)
        assert len(deployment.otc.get_orders()) == 2

        # when
        deployment.otc.make(deployment.sai.address, Wad.from_number(5), deployment.gem.address, Wad.from_number(0.0538)).transact() #price=92.936802973977695
        deployment.otc.make(deployment.sai.address, Wad.from_number(5), deployment.gem.address, Wad.from_number(0.0505)).transact() #price=99.0
        deployment.otc.make(deployment.gem.address, Wad.from_number(0.5), deployment.sai.address, Wad.from_number(50.5)).transact() #price=101
        deployment.otc.make(deployment.gem.address, Wad.from_number(0.5), deployment.sai.address, Wad.from_number(53.5)).transact() #price=107
        assert len(deployment.otc.get_orders()) == 6
        # and
        self.synchronize_orders_twice(keeper)
        # then
        assert len(deployment.otc.get_orders()) == 2
    def test_should_not_cancel_anything_if_no_orders_to_cancel_regardless_of_price_availability(
            self, tmpdir):
        # given
        config = BandConfig.sample_config(tmpdir)
        bands = self.create_bands(config)

        # when
        price = Price(buy_price=Wad.from_number(100),
                      sell_price=Wad.from_number(200))
        orders_to_cancel = bands.cancellable_orders([], [], price)
        # then
        assert (orders_to_cancel == [])

        # when
        price = Price(buy_price=Wad.from_number(100), sell_price=None)
        orders_to_cancel = bands.cancellable_orders([], [], price)
        # then
        assert (orders_to_cancel == [])

        # when
        price = Price(buy_price=None, sell_price=Wad.from_number(200))
        orders_to_cancel = bands.cancellable_orders([], [], price)
        # then
        assert (orders_to_cancel == [])

        # when
        price = Price(buy_price=None, sell_price=None)
        orders_to_cancel = bands.cancellable_orders([], [], price)
        # then
        assert (orders_to_cancel == [])
Exemple #3
0
    def test_should_cancel_the_only_sell_order_and_place_a_new_one_if_above_max(self, deployment: Deployment, tmpdir):
        # given
        config_file = BandConfig.sample_config(tmpdir)

        # and
        keeper = OasisMarketMakerKeeper(args=args(f"--eth-from {deployment.our_address} "
                                                  f"--tub-address {deployment.tub.address} "
                                                  f"--oasis-address {deployment.otc.address} "
                                                  f"--config {config_file}"),
                                        web3=deployment.web3)
        keeper.lifecycle = Web3Lifecycle(web3=keeper.web3)

        # and
        self.mint_tokens(deployment)
        self.set_price(deployment, Wad.from_number(100))

        # and
        keeper.approve()

        # and
        # [one artificially created order above the max band threshold]
        deployment.otc.make(deployment.gem.address, Wad.from_number(20), deployment.sai.address, Wad.from_number(2080)).transact()

        # when
        self.synchronize_orders_twice(keeper)

        # then
        # [the artificial order gets cancelled, a new one gets created instead]
        assert len(deployment.otc.get_orders()) == 2
        assert self.orders_by_token(deployment, deployment.gem)[0].maker == deployment.our_address
        assert self.orders_by_token(deployment, deployment.gem)[0].pay_amount == Wad.from_number(7.5)
        assert self.orders_by_token(deployment, deployment.gem)[0].pay_token == deployment.gem.address
        assert self.orders_by_token(deployment, deployment.gem)[0].buy_amount == Wad.from_number(780)
        assert self.orders_by_token(deployment, deployment.gem)[0].buy_token == deployment.sai.address
    def test_should_not_cancel_anything_if_no_orders_to_cancel_regardless_of_price_availability(self, tmpdir):
        # given
        config = BandConfig.sample_config(tmpdir)
        bands = self.create_bands(config)

        # when
        price = Price(buy_price=Wad.from_number(100), sell_price=Wad.from_number(200))
        orders_to_cancel = bands.cancellable_orders([], [], price)
        # then
        assert(orders_to_cancel == [])

        # when
        price = Price(buy_price=Wad.from_number(100), sell_price=None)
        orders_to_cancel = bands.cancellable_orders([], [], price)
        # then
        assert(orders_to_cancel == [])

        # when
        price = Price(buy_price=None, sell_price=Wad.from_number(200))
        orders_to_cancel = bands.cancellable_orders([], [], price)
        # then
        assert(orders_to_cancel == [])

        # when
        price = Price(buy_price=None, sell_price=None)
        orders_to_cancel = bands.cancellable_orders([], [], price)
        # then
        assert(orders_to_cancel == [])
Exemple #5
0
    def test_should_create_both_buy_and_sell_orders_and_modifie_it_according_rules(self, tmpdir):
        config = BandConfig.sample_config(tmpdir)
        bands = self.create_bands(config)

        buy_price_to_round_up = Wad.from_number(100.009)
        sell_price_to_round_up = Wad.from_number(200.039)

        price = Price(buy_price=buy_price_to_round_up, sell_price=sell_price_to_round_up)
        new_orders, _, _ = bands.new_orders([], [], Wad.from_number(1000000), Wad.from_number(1000000), price)

        assert(len(new_orders) == 2)
        assert(new_orders[0].is_sell is False)
        assert(new_orders[0].price == Wad.from_number(96.01))
        assert(new_orders[0].amount == Wad.from_number(0.78117))
        assert(new_orders[1].is_sell is True)
        assert(new_orders[1].price == Wad.from_number(208.04))
        assert(new_orders[1].amount == Wad.from_number(7.5))

        buy_price_to_round_down = Wad.from_number(100.022)
        sell_price_to_round_down = Wad.from_number(200.014)

        price = Price(buy_price=buy_price_to_round_down, sell_price=sell_price_to_round_down)
        new_orders, _, _ = bands.new_orders([], [], Wad.from_number(1000000), Wad.from_number(1000000), price)

        assert(len(new_orders) == 2)
        assert(new_orders[0].is_sell is False)
        assert(new_orders[0].price == Wad.from_number(96.02))
        assert(new_orders[0].amount == Wad.from_number(0.78109))
        assert(new_orders[1].is_sell is True)
        assert(new_orders[1].price == Wad.from_number(208.01))
        assert(new_orders[1].amount == Wad.from_number(7.5))
def test_new_buy_orders_taker_amount_exceed_buy_balance_fail_case(tmpdir):
    bands_file = BandConfig.sample_config(tmpdir)
    bands_config = ReloadableConfig(str(bands_file))
    airswap_bands = AirswapBands.read(bands_config, EmptyFeed(), FixedFeed({'canBuy': True, 'canSell': True}), History())

    # maker_amount -> denominated in DAI
    maker_amount = Wad(0)
    taker_amount = Wad(11360000000000000000)
    our_buy_balance = Wad(50000000000000000)
    buy_limit = Wad(1562000000000000000000)
    target_price = WebSocketPriceFeed(FakeFeed({"buyPrice": "120", "sellPrice": "130"})).get_price()

    new_order = airswap_bands._new_side_orders('buy',
                                               maker_amount,
                                               taker_amount,
                                               our_buy_balance,
                                               buy_limit,
                                               airswap_bands.buy_bands[0],
                                               target_price.buy_price)

    # -- pricing logic --
    # buyPrice = 120 * minMargin = 0.02 = 117.6
    # maker_amount = 11.36000 / 117.6 = 0.09659863945
    # our_buy_balance = 0.050000000000000000 !!BREAK!!

    assert new_order == {}
Exemple #7
0
    def test_should_cancel_orders_on_shutdown(self, deployment: Deployment,
                                              tmpdir):
        # given
        config_file = BandConfig.sample_config(tmpdir)

        # and
        keeper = OasisMarketMakerKeeper(args=args(
            f"--eth-from {deployment.our_address} "
            f"--tub-address {deployment.tub.address} "
            f"--oasis-address {deployment.otc.address} "
            f"--buy-token-address {deployment.sai.address} "
            f"--sell-token-address {deployment.gem.address} "
            f"--price-feed tub "
            f"--config {config_file}"),
                                        web3=deployment.web3)
        keeper.lifecycle = Lifecycle(web3=keeper.web3)

        # and
        self.mint_tokens(deployment)
        self.set_price(deployment, Wad.from_number(100))

        # and
        keeper.approve()
        self.synchronize_orders_twice(keeper)
        assert len(deployment.otc.get_orders()) == 2

        # when
        keeper.shutdown()

        # then
        assert len(deployment.otc.get_orders()) == 0
Exemple #8
0
    def test_should_cancel_selected_sell_orders_to_bring_the_band_total_below_max_and_closest_to_it(
            self, deployment: Deployment, tmpdir):
        # given
        config_file = BandConfig.sample_config(tmpdir)

        # and
        keeper = OasisMarketMakerKeeper(args=args(
            f"--eth-from {deployment.our_address} "
            f"--tub-address {deployment.tub.address} "
            f"--oasis-address {deployment.otc.address} "
            f"--buy-token-address {deployment.sai.address} "
            f"--sell-token-address {deployment.gem.address} "
            f"--price-feed tub "
            f"--config {config_file}"),
                                        web3=deployment.web3)
        keeper.lifecycle = Lifecycle(web3=keeper.web3)

        # and
        self.mint_tokens(deployment)
        self.set_price(deployment, Wad.from_number(100))

        # and
        keeper.approve()
        self.synchronize_orders_twice(keeper)
        assert len(deployment.otc.get_orders()) == 2

        # when [7.5+2.0 = 9.5]
        deployment.otc.make(deployment.gem.address,
                            Wad.from_number(2), deployment.sai.address,
                            Wad.from_number(208)).transact()
        # and
        keeper.order_book_manager.wait_for_order_book_refresh()
        # and
        self.synchronize_orders_twice(keeper)
        # then
        assert len(deployment.otc.get_orders()) == 3

        # when [9.5+0.5 = 10]
        deployment.otc.make(deployment.gem.address,
                            Wad.from_number(0.5), deployment.sai.address,
                            Wad.from_number(52)).transact()
        # and
        keeper.order_book_manager.wait_for_order_book_refresh()
        # and
        self.synchronize_orders_twice(keeper)
        # then
        assert len(deployment.otc.get_orders()) == 4

        # when [10+0.1 = 10.1] --> above max!
        deployment.otc.make(deployment.gem.address,
                            Wad.from_number(0.1), deployment.sai.address,
                            Wad.from_number(10.4)).transact()
        # and
        keeper.order_book_manager.wait_for_order_book_refresh()
        # and
        self.synchronize_orders_twice(keeper)
        # then
        assert len(deployment.otc.get_orders()) == 4
        assert reduce(Wad.__add__, map(lambda order: order.pay_amount, self.orders_by_token(deployment, deployment.gem)), Wad(0)) \
               == Wad.from_number(10.0)
def test_new_buy_orders_taker_amount_success_case(tmpdir):
    bands_file = BandConfig.sample_config(tmpdir)
    bands_config = ReloadableConfig(str(bands_file))
    airswap_bands = AirswapBands.read(bands_config, EmptyFeed(), FixedFeed({'canBuy': True, 'canSell': True}), History())

    # maker_amount -> denominated in DAI
    maker_amount = Wad(0)
    taker_amount = Wad(11360000000000000000)
    our_buy_balance = Wad(1562000000000000000000)
    buy_limit = Wad(1562000000000000000000)
    target_price = WebSocketPriceFeed(FakeFeed({"buyPrice": "120", "sellPrice": "130"})).get_price()

    new_order = airswap_bands._new_side_orders('buy',
                                               maker_amount,
                                               taker_amount,
                                               our_buy_balance,
                                               buy_limit,
                                               airswap_bands.buy_bands[0],
                                               target_price.buy_price)

    # -- pricing logic --
    # buyPrice = 120 * minMargin = 0.04 = 4.8
    # 120 - 4.8 = 115.2
    # maker_amount = 11.36000 / 115.2 = 0.09861111111111111111111

    assert new_order['taker_amount'].__float__() == 11.36000
    assert new_order['maker_amount'].__float__() == 0.09861111111111111111111
Exemple #10
0
    def test_should_use_specified_gas_price_for_all_transactions(
            self, deployment: Deployment, tmpdir):
        # given
        config_file = BandConfig.sample_config(tmpdir)

        # and
        keeper = OasisMarketMakerKeeper(args=args(
            f"--eth-from {deployment.our_address} "
            f"--tub-address {deployment.tub.address} "
            f"--oasis-address {deployment.otc.address} "
            f"--price-feed tub "
            f"--config {config_file} "
            f"--gas-price 70000000000"),
                                        web3=deployment.web3)
        keeper.lifecycle = Lifecycle(web3=keeper.web3)

        # and
        self.mint_tokens(deployment)
        self.set_price(deployment, Wad.from_number(100))

        # and
        start_block_number = deployment.web3.eth.blockNumber

        # when
        keeper.approve()
        self.synchronize_orders_twice(keeper)
        keeper.shutdown()

        # then
        for block_number in range(start_block_number + 1,
                                  deployment.web3.eth.blockNumber + 1):
            for transaction in deployment.web3.eth.getBlock(
                    block_number, full_transactions=True).transactions:
                assert transaction.gasPrice == 70000000000
Exemple #11
0
    def test_should_cancel_all_orders_but_not_terminate_if_market_gets_closed(
            self, deployment: Deployment, tmpdir):
        # given
        config_file = BandConfig.sample_config(tmpdir)

        # and
        keeper = OasisMarketMakerKeeper(args=args(
            f"--eth-from {deployment.our_address} "
            f"--tub-address {deployment.tub.address} "
            f"--oasis-address {deployment.otc.address} "
            f"--price-feed tub "
            f"--config {config_file}"),
                                        web3=deployment.web3)
        keeper.lifecycle = Lifecycle(web3=keeper.web3)

        # and
        self.mint_tokens(deployment)
        self.set_price(deployment, Wad.from_number(100))

        # when
        keeper.approve()
        self.synchronize_orders_twice(keeper)

        # then
        assert len(deployment.otc.get_orders()) == 2

        # when
        deployment.otc._contract.transact().stop()

        # and
        self.synchronize_orders_twice(keeper)

        # then
        assert len(deployment.otc.get_orders()) == 0
        assert not keeper.lifecycle.terminated_internally
    def test_should_cancel_orders_on_shutdown(self, deployment: Deployment, tmpdir):
        # given
        config_file = BandConfig.sample_config(tmpdir)

        # and
        keeper = OasisMarketMakerKeeper(args=args(f"--eth-from {deployment.our_address} "
                                                  f"--tub-address {deployment.tub.address} "
                                                  f"--oasis-address {deployment.otc.address} "
                                                  f"--buy-token-address {deployment.sai.address} "
                                                  f"--sell-token-address {deployment.gem.address} "
                                                  f"--price-feed tub "
                                                  f"--config {config_file}"),
                                        web3=deployment.web3)
        keeper.lifecycle = Lifecycle(web3=keeper.web3)

        # and
        self.mint_tokens(deployment)
        self.set_price(deployment, Wad.from_number(100))

        # and
        keeper.approve()
        self.synchronize_orders_twice(keeper)
        assert len(deployment.otc.get_orders()) == 2

        # when
        keeper.shutdown()

        # then
        assert len(deployment.otc.get_orders()) == 0
Exemple #13
0
    def test_should_cancel_orders_if_price_disappears(self, tmpdir):
        # given
        config = BandConfig.sample_config(tmpdir)
        bands = self.create_bands(config)

        # and
        buy_order = FakeOrder(Wad.from_number(75), Wad.from_number(96))
        sell_order = FakeOrder(Wad.from_number(7.5), Wad.from_number(208))

        # when
        price = Price(buy_price=Wad.from_number(100), sell_price=Wad.from_number(200))
        orders_to_cancel = bands.cancellable_orders([buy_order], [sell_order], price)
        # then
        assert(orders_to_cancel == [])

        # when
        price = Price(buy_price=Wad.from_number(100), sell_price=None)
        orders_to_cancel = bands.cancellable_orders([buy_order], [sell_order], price)
        # then
        assert(orders_to_cancel == [sell_order])

        # when
        price = Price(buy_price=None, sell_price=Wad.from_number(200))
        orders_to_cancel = bands.cancellable_orders([buy_order], [sell_order], price)
        # then
        assert(orders_to_cancel == [buy_order])

        # when
        price = Price(buy_price=None, sell_price=None)
        orders_to_cancel = bands.cancellable_orders([buy_order], [sell_order], price)
        # then
        assert(orders_to_cancel == [buy_order, sell_order])
    def test_should_cancel_all_orders_but_not_terminate_if_market_gets_closed(self, deployment: Deployment, tmpdir):
        # given
        config_file = BandConfig.sample_config(tmpdir)

        # and
        keeper = OasisMarketMakerKeeper(args=args(f"--eth-from {deployment.our_address} "
                                                  f"--tub-address {deployment.tub.address} "
                                                  f"--oasis-address {deployment.otc.address} "
                                                  f"--buy-token-address {deployment.sai.address} "
                                                  f"--sell-token-address {deployment.gem.address} "
                                                  f"--price-feed tub "
                                                  f"--config {config_file}"),
                                        web3=deployment.web3)
        keeper.lifecycle = Lifecycle(web3=keeper.web3)

        # and
        self.mint_tokens(deployment)
        self.set_price(deployment, Wad.from_number(100))

        # when
        keeper.approve()
        self.synchronize_orders_twice(keeper)

        # then
        assert len(deployment.otc.get_orders()) == 2

        # when
        deployment.otc._contract.transact().stop()

        # and
        self.synchronize_orders_twice(keeper)

        # then
        assert len(deployment.otc.get_orders()) == 0
        assert not keeper.lifecycle.terminated_internally
    def test_should_use_specified_gas_price_for_all_transactions(self, deployment: Deployment, tmpdir):
        # given
        config_file = BandConfig.sample_config(tmpdir)

        # and
        keeper = OasisMarketMakerKeeper(args=args(f"--eth-from {deployment.our_address} "
                                                  f"--tub-address {deployment.tub.address} "
                                                  f"--oasis-address {deployment.otc.address} "
                                                  f"--buy-token-address {deployment.sai.address} "
                                                  f"--sell-token-address {deployment.gem.address} "
                                                  f"--price-feed tub "
                                                  f"--config {config_file} "
                                                  f"--gas-price 70000000000"),
                                        web3=deployment.web3)
        keeper.lifecycle = Lifecycle(web3=keeper.web3)

        # and
        self.mint_tokens(deployment)
        self.set_price(deployment, Wad.from_number(100))

        # and
        start_block_number = deployment.web3.eth.blockNumber

        # when
        keeper.approve()
        self.synchronize_orders_twice(keeper)
        keeper.shutdown()

        # then
        for block_number in range(start_block_number+1, deployment.web3.eth.blockNumber+1):
            for transaction in deployment.web3.eth.getBlock(block_number, full_transactions=True).transactions:
                assert transaction.gasPrice == 70000000000
Exemple #16
0
    def test_should_reload_config_file_if_changed(self, deployment: Deployment,
                                                  tmpdir):
        # given
        config_file = BandConfig.with_variables_config(tmpdir)

        # and
        keeper = OasisMarketMakerKeeper(args=args(
            f"--eth-from {deployment.our_address} "
            f"--tub-address {deployment.tub.address} "
            f"--oasis-address {deployment.otc.address} "
            f"--price-feed tub "
            f"--config {config_file}"),
                                        web3=deployment.web3)
        keeper.lifecycle = Lifecycle(web3=keeper.web3)

        # and
        self.mint_tokens(deployment)
        self.set_price(deployment, Wad.from_number(100))

        # when
        keeper.approve()
        self.synchronize_orders_twice(keeper)

        # then
        assert len(deployment.otc.get_orders()) == 1

        # when
        second_config_file = BandConfig.sample_config(tmpdir)
        shutil.copyfile(second_config_file, config_file)

        # and
        self.synchronize_orders_twice(keeper)

        # then
        assert len(deployment.otc.get_orders()) == 2
    def test_should_cancel_orders_if_price_disappears(self, tmpdir):
        # given
        config = BandConfig.sample_config(tmpdir)
        bands = self.create_bands(config)

        # and
        buy_order = FakeOrder(Wad.from_number(75), Wad.from_number(96))
        sell_order = FakeOrder(Wad.from_number(7.5), Wad.from_number(208))

        # when
        price = Price(buy_price=Wad.from_number(100), sell_price=Wad.from_number(200))
        orders_to_cancel = bands.cancellable_orders([buy_order], [sell_order], price)
        # then
        assert(orders_to_cancel == [])

        # when
        price = Price(buy_price=Wad.from_number(100), sell_price=None)
        orders_to_cancel = bands.cancellable_orders([buy_order], [sell_order], price)
        # then
        assert(orders_to_cancel == [sell_order])

        # when
        price = Price(buy_price=None, sell_price=Wad.from_number(200))
        orders_to_cancel = bands.cancellable_orders([buy_order], [sell_order], price)
        # then
        assert(orders_to_cancel == [buy_order])

        # when
        price = Price(buy_price=None, sell_price=None)
        orders_to_cancel = bands.cancellable_orders([buy_order], [sell_order], price)
        # then
        assert(orders_to_cancel == [buy_order, sell_order])
Exemple #18
0
    def test_should_cancel_the_only_buy_order_and_place_a_new_one_if_above_max(
            self, deployment: Deployment, tmpdir: py.path.local):
        # given
        config_file = BandConfig.sample_config(tmpdir)

        # and
        keeper = EtherDeltaMarketMakerKeeper(args=args(
            f"--eth-from {deployment.our_address} --config {config_file}"
            f" --tub-address {deployment.tub.address}"
            f" --etherdelta-address {deployment.etherdelta.address}"
            f" --etherdelta-socket https://127.0.0.1:99999/"
            f" --order-age 3600 --eth-reserve 10"
            f" --min-eth-deposit 1 --min-sai-deposit 400"),
                                             web3=deployment.web3)
        keeper.lifecycle = Lifecycle(web3=keeper.web3)
        keeper.etherdelta_api.publish_order = MagicMock()

        # and
        self.mint_tokens(deployment)
        self.set_price(deployment, Wad.from_number(100))

        # and
        keeper.approve()

        # and
        # [one artificially created order above the max band threshold]
        keeper.our_orders.append(
            deployment.etherdelta.create_order(deployment.sai.address,
                                               Wad.from_number(170),
                                               EtherDelta.ETH_TOKEN,
                                               Wad.from_number(1.770805),
                                               1000000))

        # when
        keeper.synchronize_orders(
        )  # ... first call is so it can cancel the order
        keeper.synchronize_orders(
        )  # ... second call is so it can made deposits
        keeper.synchronize_orders(
        )  # ... third call is so the actual orders can get placed

        # then
        # [the artificial order gets cancelled, a new one gets created instead]
        assert len(self.orders(keeper)) == 2
        assert self.orders_by_token(
            keeper, deployment.sai.address)[0].maker == deployment.our_address
        assert self.orders_by_token(
            keeper,
            deployment.sai.address)[0].pay_amount == Wad.from_number(75)
        assert self.orders_by_token(
            keeper,
            deployment.sai.address)[0].pay_token == deployment.sai.address
        assert self.orders_by_token(
            keeper,
            deployment.sai.address)[0].buy_amount == Wad.from_number(0.78125)
        assert self.orders_by_token(
            keeper,
            deployment.sai.address)[0].buy_token == EtherDelta.ETH_TOKEN
    def test_should_place_extra_order_only_if_order_brought_below_min(self, deployment: Deployment, tmpdir):
        # given
        config_file = BandConfig.sample_config(tmpdir)

        # and
        keeper = OasisMarketMakerKeeper(args=args(f"--eth-from {deployment.our_address} "
                                                  f"--tub-address {deployment.tub.address} "
                                                  f"--oasis-address {deployment.otc.address} "
                                                  f"--buy-token-address {deployment.sai.address} "
                                                  f"--sell-token-address {deployment.gem.address} "
                                                  f"--price-feed tub "
                                                  f"--config {config_file}"),
                                        web3=deployment.web3)
        keeper.lifecycle = Lifecycle(web3=keeper.web3)

        # and
        self.mint_tokens(deployment)
        self.set_price(deployment, Wad.from_number(100))

        # and
        keeper.approve()
        self.synchronize_orders_twice(keeper)
        assert len(deployment.otc.get_orders()) == 2
        sai_order_id = self.orders_by_token(deployment, deployment.sai)[0].order_id

        # when
        deployment.otc.take(sai_order_id, Wad.from_number(20)).transact()
        # and
        keeper.order_book_manager.wait_for_order_book_refresh()
        # and
        self.synchronize_orders_twice(keeper)
        # then
        assert len(deployment.otc.get_orders()) == 2

        # when
        deployment.otc.take(sai_order_id, Wad.from_number(5)).transact()
        # and
        keeper.order_book_manager.wait_for_order_book_refresh()
        # and
        self.synchronize_orders_twice(keeper)
        # then
        assert len(deployment.otc.get_orders()) == 2

        # when
        deployment.otc.take(sai_order_id, Wad.from_number(1)).transact()
        # and
        keeper.order_book_manager.wait_for_order_book_refresh()
        # and
        self.synchronize_orders_twice(keeper)
        # then
        assert len(deployment.otc.get_orders()) == 3
        assert deployment.otc.get_orders()[2].pay_amount == Wad.from_number(26)
        assert deployment.otc.get_orders()[2].pay_token == deployment.sai.address
        assert deployment.otc.get_orders()[2].buy_amount == Wad(270833333333333333)
        assert deployment.otc.get_orders()[2].buy_token == deployment.gem.address
    def test_should_place_extra_order_only_if_order_brought_below_min(self, deployment: Deployment, tmpdir):
        # given
        config_file = BandConfig.sample_config(tmpdir)

        # and
        keeper = OasisMarketMakerKeeper(args=args(f"--eth-from {deployment.our_address} "
                                                  f"--tub-address {deployment.tub.address} "
                                                  f"--oasis-address {deployment.otc.address} "
                                                  f"--buy-token-address {deployment.sai.address} "
                                                  f"--sell-token-address {deployment.gem.address} "
                                                  f"--price-feed eth_dai-tub "
                                                  f"--config {config_file}"),
                                        web3=deployment.web3)
        keeper.lifecycle = Lifecycle(web3=keeper.web3)

        # and
        self.mint_tokens(deployment)
        self.set_price(deployment, Wad.from_number(100))

        # and
        keeper.approve()
        self.synchronize_orders_twice(keeper)
        assert len(deployment.otc.get_orders()) == 2
        sai_order_id = self.orders_by_token(deployment, deployment.sai)[0].order_id

        # when
        deployment.otc.take(sai_order_id, Wad.from_number(20)).transact()
        # and
        keeper.order_book_manager.wait_for_order_book_refresh()
        # and
        self.synchronize_orders_twice(keeper)
        # then
        assert len(deployment.otc.get_orders()) == 2

        # when
        deployment.otc.take(sai_order_id, Wad.from_number(5)).transact()
        # and
        keeper.order_book_manager.wait_for_order_book_refresh()
        # and
        self.synchronize_orders_twice(keeper)
        # then
        assert len(deployment.otc.get_orders()) == 2

        # when
        deployment.otc.take(sai_order_id, Wad.from_number(1)).transact()
        # and
        keeper.order_book_manager.wait_for_order_book_refresh()
        # and
        self.synchronize_orders_twice(keeper)
        # then
        assert len(deployment.otc.get_orders()) == 3
        assert deployment.otc.get_orders()[2].pay_amount == Wad.from_number(26)
        assert deployment.otc.get_orders()[2].pay_token == deployment.sai.address
        assert deployment.otc.get_orders()[2].buy_amount == Wad(270833333333333333)
        assert deployment.otc.get_orders()[2].buy_token == deployment.gem.address
    def test_should_not_create_orders_if_neither_buy_nor_sell_price_available(self, tmpdir):
        # given
        config = BandConfig.sample_config(tmpdir)
        bands = self.create_bands(config)

        # when
        price = Price(buy_price=None, sell_price=None)
        new_orders, _, _ = bands.new_orders([], [], Wad.from_number(1000000), Wad.from_number(1000000), price)

        # then
        assert(new_orders == [])
Exemple #22
0
    def test_should_not_create_orders_if_neither_buy_nor_sell_price_available(self, tmpdir):
        # given
        config = BandConfig.sample_config(tmpdir)
        bands = self.create_bands(config)

        # when
        price = Price(buy_price=None, sell_price=None)
        new_orders, _, _ = bands.new_orders([], [], Wad.from_number(1000000), Wad.from_number(1000000), price)

        # then
        assert(new_orders == [])
Exemple #23
0
    def test_should_create_orders_on_startup(self, deployment: Deployment,
                                             tmpdir):
        # given
        config_file = BandConfig.sample_config(tmpdir)

        # and
        keeper = OasisMarketMakerKeeper(args=args(
            f"--eth-from {deployment.our_address} "
            f"--tub-address {deployment.tub.address} "
            f"--oasis-address {deployment.otc.address} "
            f"--buy-token-address {deployment.sai.address} "
            f"--sell-token-address {deployment.gem.address} "
            f"--price-feed tub "
            f"--config {config_file}"),
                                        web3=deployment.web3)
        keeper.lifecycle = Lifecycle(web3=keeper.web3)

        # and
        self.mint_tokens(deployment)
        self.set_price(deployment, Wad.from_number(100))

        # when
        keeper.approve()
        self.synchronize_orders_twice(keeper)

        # then
        assert len(deployment.otc.get_orders()) == 2

        # and
        assert self.orders_by_token(
            deployment, deployment.sai)[0].maker == deployment.our_address
        assert self.orders_by_token(
            deployment, deployment.sai)[0].pay_amount == Wad.from_number(75)
        assert self.orders_by_token(
            deployment, deployment.sai)[0].pay_token == deployment.sai.address
        assert self.orders_by_token(
            deployment,
            deployment.sai)[0].buy_amount == Wad.from_number(0.78125)
        assert self.orders_by_token(
            deployment, deployment.sai)[0].buy_token == deployment.gem.address

        # and
        assert self.orders_by_token(
            deployment, deployment.gem)[0].maker == deployment.our_address
        assert self.orders_by_token(
            deployment, deployment.gem)[0].pay_amount == Wad.from_number(7.5)
        assert self.orders_by_token(
            deployment, deployment.gem)[0].pay_token == deployment.gem.address
        assert self.orders_by_token(
            deployment, deployment.gem)[0].buy_amount == Wad.from_number(780)
        assert self.orders_by_token(
            deployment, deployment.gem)[0].buy_token == deployment.sai.address
Exemple #24
0
    def test_should_cancel_selected_buy_orders_to_bring_the_band_total_below_max_and_closest_to_it(
            self, deployment: Deployment, tmpdir):
        # given
        config_file = BandConfig.sample_config(tmpdir)

        # and
        keeper = OasisMarketMakerKeeper(args=args(
            f"--eth-from {deployment.our_address} "
            f"--tub-address {deployment.tub.address} "
            f"--oasis-address {deployment.otc.address} "
            f"--price-feed tub "
            f"--config {config_file}"),
                                        web3=deployment.web3)
        keeper.lifecycle = Lifecycle(web3=keeper.web3)

        # and
        self.mint_tokens(deployment)
        self.set_price(deployment, Wad.from_number(100))

        # and
        keeper.approve()
        self.synchronize_orders_twice(keeper)
        assert len(deployment.otc.get_orders()) == 2

        # when [75+17 = 92]
        deployment.otc.make(deployment.sai.address,
                            Wad.from_number(17), deployment.gem.address,
                            Wad.from_number(0.1770805)).transact()
        # and
        self.synchronize_orders_twice(keeper)
        # then
        assert len(deployment.otc.get_orders()) == 3

        # when [92+2 = 94]
        deployment.otc.make(deployment.sai.address,
                            Wad.from_number(2), deployment.gem.address,
                            Wad.from_number(0.020833)).transact()
        # and
        self.synchronize_orders_twice(keeper)
        # then
        assert len(deployment.otc.get_orders()) == 4

        # when [94+7 = 101] --> above max!
        deployment.otc.make(deployment.sai.address,
                            Wad.from_number(7), deployment.gem.address,
                            Wad.from_number(0.072912)).transact()
        # and
        self.synchronize_orders_twice(keeper)
        # then
        assert len(deployment.otc.get_orders()) == 4
        assert reduce(Wad.__add__, map(lambda order: order.pay_amount, self.orders_by_token(deployment, deployment.sai)), Wad(0)) \
               == Wad.from_number(99)
    def test_should_cancel_selected_sell_orders_to_bring_the_band_total_below_max_and_closest_to_it(self, deployment: Deployment, tmpdir):
        # given
        config_file = BandConfig.sample_config(tmpdir)

        # and
        keeper = OasisMarketMakerKeeper(args=args(f"--eth-from {deployment.our_address} "
                                                  f"--tub-address {deployment.tub.address} "
                                                  f"--oasis-address {deployment.otc.address} "
                                                  f"--buy-token-address {deployment.sai.address} "
                                                  f"--sell-token-address {deployment.gem.address} "
                                                  f"--price-feed tub "
                                                  f"--config {config_file}"),
                                        web3=deployment.web3)
        keeper.lifecycle = Lifecycle(web3=keeper.web3)

        # and
        self.mint_tokens(deployment)
        self.set_price(deployment, Wad.from_number(100))

        # and
        keeper.approve()
        self.synchronize_orders_twice(keeper)
        assert len(deployment.otc.get_orders()) == 2

        # when [7.5+2.0 = 9.5]
        deployment.otc.make(deployment.gem.address, Wad.from_number(2), deployment.sai.address, Wad.from_number(208)).transact()
        # and
        keeper.order_book_manager.wait_for_order_book_refresh()
        # and
        self.synchronize_orders_twice(keeper)
        # then
        assert len(deployment.otc.get_orders()) == 3

        # when [9.5+0.5 = 10]
        deployment.otc.make(deployment.gem.address, Wad.from_number(0.5), deployment.sai.address, Wad.from_number(52)).transact()
        # and
        keeper.order_book_manager.wait_for_order_book_refresh()
        # and
        self.synchronize_orders_twice(keeper)
        # then
        assert len(deployment.otc.get_orders()) == 4

        # when [10+0.1 = 10.1] --> above max!
        deployment.otc.make(deployment.gem.address, Wad.from_number(0.1), deployment.sai.address, Wad.from_number(10.4)).transact()
        # and
        keeper.order_book_manager.wait_for_order_book_refresh()
        # and
        self.synchronize_orders_twice(keeper)
        # then
        assert len(deployment.otc.get_orders()) == 4
        assert reduce(Wad.__add__, map(lambda order: order.pay_amount, self.orders_by_token(deployment, deployment.gem)), Wad(0)) \
               == Wad.from_number(10.0)
Exemple #26
0
    def test_should_create_only_sell_orders_if_only_sell_price_is_available(self, tmpdir):
        # given
        config = BandConfig.sample_config(tmpdir)
        bands = self.create_bands(config)

        # when
        price = Price(buy_price=None, sell_price=Wad.from_number(200))
        new_orders, _, _ = bands.new_orders([], [], Wad.from_number(1000000), Wad.from_number(1000000), price)

        # then
        assert(len(new_orders) == 1)
        assert(new_orders[0].is_sell is True)
        assert(new_orders[0].price == Wad.from_number(208))
    def test_should_create_only_sell_orders_if_only_sell_price_is_available(self, tmpdir):
        # given
        config = BandConfig.sample_config(tmpdir)
        bands = self.create_bands(config)

        # when
        price = Price(buy_price=None, sell_price=Wad.from_number(200))
        new_orders, _, _ = bands.new_orders([], [], Wad.from_number(1000000), Wad.from_number(1000000), price)

        # then
        assert(len(new_orders) == 1)
        assert(new_orders[0].is_sell is True)
        assert(new_orders[0].price == Wad.from_number(208))
Exemple #28
0
    def test_should_create_both_buy_and_sell_orders_when_rules_allows_it(self, tmpdir):
        config = BandConfig.sample_config(tmpdir)
        bands = self.create_bands(config)

        price = Price(buy_price=Wad.from_number(100.01), sell_price=Wad.from_number(200.03))
        new_orders, _, _ = bands.new_orders([], [], Wad.from_number(1000000), Wad.from_number(1000000), price)

        assert(len(new_orders) == 2)
        assert(new_orders[0].is_sell is False)
        assert(new_orders[0].amount == Wad.from_number(0.78117))
        assert(new_orders[0].price == Wad.from_number(96.01))
        assert(new_orders[1].is_sell is True)
        assert(new_orders[1].price == Wad.from_number(208.03))
        assert(new_orders[1].amount == Wad.from_number(7.5))
Exemple #29
0
    def test_should_reload_config_file_if_changed(self, deployment: Deployment,
                                                  tmpdir: py.path.local):
        # given
        config_file = BandConfig.with_variables_config(tmpdir)

        # and
        keeper = EtherDeltaMarketMakerKeeper(args=args(
            f"--eth-from {deployment.our_address} --config {config_file}"
            f" --tub-address {deployment.tub.address}"
            f" --etherdelta-address {deployment.etherdelta.address}"
            f" --etherdelta-socket https://127.0.0.1:99999/"
            f" --order-age 3600 --eth-reserve 10"
            f" --min-eth-deposit 1 --min-sai-deposit 400"),
                                             web3=deployment.web3)
        keeper.lifecycle = Web3Lifecycle(web3=keeper.web3)
        keeper.etherdelta_api.publish_order = MagicMock()

        # and
        self.mint_tokens(deployment)
        self.set_price(deployment, Wad.from_number(100))

        # when
        keeper.approve()
        keeper.synchronize_orders(
        )  # ... first call is so it can made deposits
        keeper.synchronize_orders(
        )  # ... second call is so the actual orders can get placed

        # then
        assert len(self.orders(keeper)) == 1

        # when
        second_config_file = BandConfig.sample_config(tmpdir)
        shutil.copyfile(second_config_file, config_file)

        # and
        keeper.synchronize_orders(
        )  # ... first call is so it can made deposits
        keeper.synchronize_orders(
        )  # ... second call is so the actual orders can get placed

        # then
        assert len(self.orders(keeper)) == 2
Exemple #30
0
    def test_should_create_both_buy_and_sell_orders_if_both_prices_are_available(
            self, tmpdir):
        # given
        config = BandConfig.sample_config(tmpdir)
        bands = self.create_bands(config)

        # when
        price = Price(buy_price=Wad.from_number(100),
                      sell_price=Wad.from_number(200))
        new_orders, _, _ = bands.new_orders([], [], Wad.from_number(1000000),
                                            Wad.from_number(1000000), price)

        # then
        assert (len(new_orders) == 2)
        assert (new_orders[0].is_sell is False)
        assert (new_orders[0].price == Wad.from_number(96))
        assert (new_orders[0].amount == Wad.from_number(0.78125))
        assert (new_orders[1].is_sell is True)
        assert (new_orders[1].price == Wad.from_number(208))
        assert (new_orders[1].amount == Wad.from_number(7.5))
Exemple #31
0
    def test_should_cancel_orders_on_shutdown_and_withdraw_if_asked_to_do_so(
            self, deployment: Deployment, tmpdir: py.path.local):
        # given
        config_file = BandConfig.sample_config(tmpdir)

        # and
        keeper = EtherDeltaMarketMakerKeeper(args=args(
            f"--eth-from {deployment.our_address} --config {config_file}"
            f" --tub-address {deployment.tub.address}"
            f" --etherdelta-address {deployment.etherdelta.address}"
            f" --etherdelta-socket https://127.0.0.1:99999/"
            f" --order-age 3600 --eth-reserve 10"
            f" --min-eth-deposit 1 --min-sai-deposit 400"
            f" --cancel-on-shutdown --withdraw-on-shutdown"),
                                             web3=deployment.web3)
        keeper.lifecycle = Web3Lifecycle(web3=keeper.web3)
        keeper.etherdelta_api.publish_order = MagicMock()

        # and
        self.mint_tokens(deployment)
        self.set_price(deployment, Wad.from_number(100))

        # and
        keeper.approve()
        keeper.synchronize_orders(
        )  # ... first call is so it can made deposits
        keeper.synchronize_orders(
        )  # ... second call is so the actual orders can get placed
        assert len(self.orders(keeper)) == 2

        # when
        keeper.shutdown()

        # then
        assert len(self.orders(keeper)) == 0

        # and
        assert deployment.etherdelta.balance_of(
            deployment.our_address) == Wad(0)
        assert deployment.etherdelta.balance_of_token(
            deployment.sai.address, deployment.our_address) == Wad(0)
Exemple #32
0
    def test_should_use_specified_gas_price_for_all_transactions(
            self, deployment: Deployment, tmpdir: py.path.local):
        # given
        config_file = BandConfig.sample_config(tmpdir)

        # and
        keeper = EtherDeltaMarketMakerKeeper(args=args(
            f"--eth-from {deployment.our_address} --config {config_file}"
            f" --tub-address {deployment.tub.address}"
            f" --etherdelta-address {deployment.etherdelta.address}"
            f" --etherdelta-socket https://127.0.0.1:99999/"
            f" --order-age 3600 --eth-reserve 10"
            f" --min-eth-deposit 1 --min-sai-deposit 400"
            f" --cancel-on-shutdown"
            f" --gas-price 69000000000"),
                                             web3=deployment.web3)
        keeper.lifecycle = Web3Lifecycle(web3=keeper.web3)
        keeper.etherdelta_api.publish_order = MagicMock()

        # and
        self.mint_tokens(deployment)
        self.set_price(deployment, Wad.from_number(100))

        # and
        start_block_number = deployment.web3.eth.blockNumber

        # when
        keeper.approve()
        keeper.synchronize_orders(
        )  # ... first call is so it can made deposits
        keeper.synchronize_orders(
        )  # ... second call is so the actual orders can get placed
        keeper.shutdown()

        # then
        for block_number in range(start_block_number + 1,
                                  deployment.web3.eth.blockNumber + 1):
            for transaction in deployment.web3.eth.getBlock(
                    block_number, full_transactions=True).transactions:
                assert transaction.gasPrice == 69000000000
    def test_should_cancel_the_only_sell_order_and_place_a_new_one_if_above_max(self, deployment: Deployment, tmpdir):
        # given
        config_file = BandConfig.sample_config(tmpdir)

        # and
        keeper = OasisMarketMakerKeeper(args=args(f"--eth-from {deployment.our_address} "
                                                  f"--tub-address {deployment.tub.address} "
                                                  f"--oasis-address {deployment.otc.address} "
                                                  f"--buy-token-address {deployment.sai.address} "
                                                  f"--sell-token-address {deployment.gem.address} "
                                                  f"--price-feed tub "
                                                  f"--config {config_file}"),
                                        web3=deployment.web3)
        keeper.lifecycle = Lifecycle(web3=keeper.web3)

        # and
        self.mint_tokens(deployment)
        self.set_price(deployment, Wad.from_number(100))

        # and
        keeper.approve()

        # and
        # [one artificially created order above the max band threshold]
        deployment.otc.make(deployment.gem.address, Wad.from_number(20), deployment.sai.address, Wad.from_number(2080)).transact()
        # and
        keeper.order_book_manager.wait_for_order_book_refresh()

        # when
        self.synchronize_orders_twice(keeper)

        # then
        # [the artificial order gets cancelled, a new one gets created instead]
        assert len(deployment.otc.get_orders()) == 2
        assert self.orders_by_token(deployment, deployment.gem)[0].maker == deployment.our_address
        assert self.orders_by_token(deployment, deployment.gem)[0].pay_amount == Wad.from_number(7.5)
        assert self.orders_by_token(deployment, deployment.gem)[0].pay_token == deployment.gem.address
        assert self.orders_by_token(deployment, deployment.gem)[0].buy_amount == Wad.from_number(780)
        assert self.orders_by_token(deployment, deployment.gem)[0].buy_token == deployment.sai.address
Exemple #34
0
    def test_should_cancel_all_orders_but_not_terminate_if_config_file_becomes_invalid(
            self, deployment: Deployment, tmpdir):
        # given
        config_file = BandConfig.sample_config(tmpdir)

        # and
        keeper = OasisMarketMakerKeeper(args=args(
            f"--eth-from {deployment.our_address} "
            f"--tub-address {deployment.tub.address} "
            f"--oasis-address {deployment.otc.address} "
            f"--buy-token-address {deployment.sai.address} "
            f"--sell-token-address {deployment.gem.address} "
            f"--price-feed tub "
            f"--config {config_file}"),
                                        web3=deployment.web3)
        keeper.lifecycle = Lifecycle(web3=keeper.web3)

        # and
        self.mint_tokens(deployment)
        self.set_price(deployment, Wad.from_number(100))

        # when
        keeper.approve()
        self.synchronize_orders_twice(keeper)

        # then
        assert len(deployment.otc.get_orders()) == 2

        # when
        second_config_file = BandConfig.bands_overlapping_invalid_config(
            tmpdir)
        shutil.copyfile(second_config_file, config_file)

        # and
        self.synchronize_orders_twice(keeper)

        # then
        assert len(deployment.otc.get_orders()) == 0
        assert not keeper.lifecycle.terminated_internally
    def test_should_create_orders_on_startup(self, deployment: Deployment, tmpdir):
        # given
        config_file = BandConfig.sample_config(tmpdir)

        # and
        keeper = OasisMarketMakerKeeper(args=args(f"--eth-from {deployment.our_address} "
                                                  f"--tub-address {deployment.tub.address} "
                                                  f"--oasis-address {deployment.otc.address} "
                                                  f"--buy-token-address {deployment.sai.address} "
                                                  f"--sell-token-address {deployment.gem.address} "
                                                  f"--price-feed tub "
                                                  f"--config {config_file}"),
                                        web3=deployment.web3)
        keeper.lifecycle = Lifecycle(web3=keeper.web3)

        # and
        self.mint_tokens(deployment)
        self.set_price(deployment, Wad.from_number(100))

        # when
        keeper.approve()
        self.synchronize_orders_twice(keeper)

        # then
        assert len(deployment.otc.get_orders()) == 2

        # and
        assert self.orders_by_token(deployment, deployment.sai)[0].maker == deployment.our_address
        assert self.orders_by_token(deployment, deployment.sai)[0].pay_amount == Wad.from_number(75)
        assert self.orders_by_token(deployment, deployment.sai)[0].pay_token == deployment.sai.address
        assert self.orders_by_token(deployment, deployment.sai)[0].buy_amount == Wad.from_number(0.78125)
        assert self.orders_by_token(deployment, deployment.sai)[0].buy_token == deployment.gem.address

        # and
        assert self.orders_by_token(deployment, deployment.gem)[0].maker == deployment.our_address
        assert self.orders_by_token(deployment, deployment.gem)[0].pay_amount == Wad.from_number(7.5)
        assert self.orders_by_token(deployment, deployment.gem)[0].pay_token == deployment.gem.address
        assert self.orders_by_token(deployment, deployment.gem)[0].buy_amount == Wad.from_number(780)
        assert self.orders_by_token(deployment, deployment.gem)[0].buy_token == deployment.sai.address
    def test_should_cancel_all_orders_outside_bands(self, deployment: Deployment, tmpdir):
        # given
        config_file = BandConfig.sample_config(tmpdir)

        # and
        keeper = OasisMarketMakerKeeper(args=args(f"--eth-from {deployment.our_address} "
                                                  f"--tub-address {deployment.tub.address} "
                                                  f"--oasis-address {deployment.otc.address} "
                                                  f"--buy-token-address {deployment.sai.address} "
                                                  f"--sell-token-address {deployment.gem.address} "
                                                  f"--price-feed tub "
                                                  f"--config {config_file}"),
                                        web3=deployment.web3)
        keeper.lifecycle = Lifecycle(web3=keeper.web3)

        # and
        self.mint_tokens(deployment)
        self.set_price(deployment, Wad.from_number(100))

        # and
        keeper.approve()
        self.synchronize_orders_twice(keeper)
        assert len(deployment.otc.get_orders()) == 2

        # when
        deployment.otc.make(deployment.sai.address, Wad.from_number(5), deployment.gem.address, Wad.from_number(0.0538)).transact() #price=92.936802973977695
        deployment.otc.make(deployment.sai.address, Wad.from_number(5), deployment.gem.address, Wad.from_number(0.0505)).transact() #price=99.0
        deployment.otc.make(deployment.gem.address, Wad.from_number(0.5), deployment.sai.address, Wad.from_number(50.5)).transact() #price=101
        deployment.otc.make(deployment.gem.address, Wad.from_number(0.5), deployment.sai.address, Wad.from_number(53.5)).transact() #price=107
        assert len(deployment.otc.get_orders()) == 6
        # and
        keeper.order_book_manager.wait_for_order_book_refresh()
        # and
        self.synchronize_orders_twice(keeper)
        # then
        assert len(deployment.otc.get_orders()) == 2
Exemple #37
0
    def test_should_send_replacement_orders_the_moment_old_ones_get_cancelled(
            self, deployment: Deployment, tmpdir):
        # given
        config_file = BandConfig.sample_config(tmpdir)

        # and
        keeper = OasisMarketMakerKeeper(args=args(
            f"--eth-from {deployment.our_address} "
            f"--tub-address {deployment.tub.address} "
            f"--oasis-address {deployment.otc.address} "
            f"--buy-token-address {deployment.sai.address} "
            f"--sell-token-address {deployment.gem.address} "
            f"--price-feed tub "
            f"--config {config_file}"),
                                        web3=deployment.web3)
        keeper.lifecycle = Lifecycle(web3=keeper.web3)

        # and
        self.mint_tokens(deployment)

        # and
        keeper.approve()

        # when
        self.set_price(deployment, Wad.from_number(100))
        self.synchronize_orders_once(keeper)

        # then
        assert len(deployment.otc.get_orders()) == 2

        # and
        assert self.orders_by_token(
            deployment, deployment.sai)[0].maker == deployment.our_address
        assert self.orders_by_token(
            deployment, deployment.sai)[0].pay_amount == Wad.from_number(75)
        assert self.orders_by_token(
            deployment, deployment.sai)[0].pay_token == deployment.sai.address
        assert self.orders_by_token(
            deployment,
            deployment.sai)[0].buy_amount == Wad.from_number(0.78125)
        assert self.orders_by_token(
            deployment, deployment.sai)[0].buy_token == deployment.gem.address

        # and
        assert self.orders_by_token(
            deployment, deployment.gem)[0].maker == deployment.our_address
        assert self.orders_by_token(
            deployment, deployment.gem)[0].pay_amount == Wad.from_number(7.5)
        assert self.orders_by_token(
            deployment, deployment.gem)[0].pay_token == deployment.gem.address
        assert self.orders_by_token(
            deployment, deployment.gem)[0].buy_amount == Wad.from_number(780)
        assert self.orders_by_token(
            deployment, deployment.gem)[0].buy_token == deployment.sai.address

        # when
        self.set_price(deployment, Wad.from_number(200))
        block_number_before = deployment.web3.eth.blockNumber
        self.synchronize_orders_once(keeper)
        block_number_after = deployment.web3.eth.blockNumber

        # then
        assert len(deployment.otc.get_orders()) == 2

        # and
        assert block_number_after - block_number_before == 4

        # and
        assert self.orders_by_token(
            deployment, deployment.sai)[0].maker == deployment.our_address
        assert self.orders_by_token(
            deployment, deployment.sai)[0].pay_amount == Wad.from_number(75)
        assert self.orders_by_token(
            deployment, deployment.sai)[0].pay_token == deployment.sai.address
        assert self.orders_by_token(
            deployment,
            deployment.sai)[0].buy_amount == Wad.from_number(0.78125 / 2)
        assert self.orders_by_token(
            deployment, deployment.sai)[0].buy_token == deployment.gem.address

        # and
        assert self.orders_by_token(
            deployment, deployment.gem)[0].maker == deployment.our_address
        assert self.orders_by_token(
            deployment, deployment.gem)[0].pay_amount == Wad.from_number(7.5)
        assert self.orders_by_token(
            deployment, deployment.gem)[0].pay_token == deployment.gem.address
        assert self.orders_by_token(
            deployment,
            deployment.gem)[0].buy_amount == Wad.from_number(780 * 2)
        assert self.orders_by_token(
            deployment, deployment.gem)[0].buy_token == deployment.sai.address
def test_airswap_read_bands(tmpdir):
    bands_file = BandConfig.sample_config(tmpdir)
    bands_config = ReloadableConfig(str(bands_file))
    airswap_bands = AirswapBands.read(bands_config, EmptyFeed(), FixedFeed({'canBuy': True, 'canSell': True}), History())
    assert isinstance(airswap_bands, AirswapBands)
Exemple #39
0
    def test_should_place_extra_order_only_if_order_brought_below_min(
            self, deployment: Deployment, tmpdir: py.path.local):
        # given
        config_file = BandConfig.sample_config(tmpdir)

        # and
        keeper = EtherDeltaMarketMakerKeeper(args=args(
            f"--eth-from {deployment.our_address} --config {config_file}"
            f" --tub-address {deployment.tub.address}"
            f" --etherdelta-address {deployment.etherdelta.address}"
            f" --etherdelta-socket https://127.0.0.1:99999/"
            f" --order-age 3600 --eth-reserve 10"
            f" --min-eth-deposit 1 --min-sai-deposit 400"),
                                             web3=deployment.web3)
        keeper.lifecycle = Web3Lifecycle(web3=keeper.web3)
        keeper.etherdelta_api.publish_order = MagicMock()

        # and
        self.mint_tokens(deployment)
        self.set_price(deployment, Wad.from_number(100))

        # and
        keeper.approve()
        keeper.synchronize_orders(
        )  # ... first call is so it can made deposits
        keeper.synchronize_orders(
        )  # ... second call is so the actual orders can get placed
        assert len(self.orders(keeper)) == 2
        sai_order = self.orders_by_token(keeper, deployment.sai.address)[0]

        # when
        print(sai_order.sell_to_buy_price)
        print(sai_order.buy_to_sell_price)
        deployment.etherdelta.trade(sai_order,
                                    Wad.from_number(20) /
                                    Wad.from_number(96)).transact()
        # and
        keeper.synchronize_orders()
        # then
        assert len(self.orders(keeper)) == 2

        # when
        deployment.etherdelta.trade(sai_order,
                                    Wad.from_number(5) /
                                    Wad.from_number(96)).transact()
        # and
        keeper.synchronize_orders()
        # then
        assert len(self.orders(keeper)) == 2

        # when
        deployment.etherdelta.trade(sai_order,
                                    Wad.from_number(1) /
                                    Wad.from_number(96)).transact()
        # and
        keeper.synchronize_orders()
        # then
        assert len(self.orders(keeper)) == 3
        assert self.orders(keeper)[2].pay_amount == Wad.from_number(26)
        assert self.orders(keeper)[2].pay_token == deployment.sai.address
        assert self.orders(keeper)[2].buy_amount == Wad(270833333000000000)
        assert self.orders(keeper)[2].buy_token == EtherDelta.ETH_TOKEN
Exemple #40
0
    def test_should_cancel_selected_sell_orders_to_bring_the_band_total_below_max_and_closest_to_it(
            self, deployment: Deployment, tmpdir: py.path.local):
        # given
        config_file = BandConfig.sample_config(tmpdir)

        # and
        keeper = EtherDeltaMarketMakerKeeper(args=args(
            f"--eth-from {deployment.our_address} --config {config_file}"
            f" --tub-address {deployment.tub.address}"
            f" --etherdelta-address {deployment.etherdelta.address}"
            f" --etherdelta-socket https://127.0.0.1:99999/"
            f" --order-age 3600 --eth-reserve 10"
            f" --min-eth-deposit 1 --min-sai-deposit 400"),
                                             web3=deployment.web3)
        keeper.lifecycle = Web3Lifecycle(web3=keeper.web3)
        keeper.etherdelta_api.publish_order = MagicMock()

        # and
        self.mint_tokens(deployment)
        self.set_price(deployment, Wad.from_number(100))

        # and
        keeper.approve()
        keeper.synchronize_orders(
        )  # ... first call is so it can made deposits
        keeper.synchronize_orders(
        )  # ... second call is so the actual orders can get placed
        assert len(self.orders(keeper)) == 2

        # when [7.5+2.0 = 9.5]
        keeper.our_orders.append(
            deployment.etherdelta.create_order(EtherDelta.ETH_TOKEN,
                                               Wad.from_number(2),
                                               deployment.sai.address,
                                               Wad.from_number(208), 1000000))
        # and
        keeper.synchronize_orders(
        )  # ... first call is so it can made deposits
        keeper.synchronize_orders(
        )  # ... second call is so the actual orders can get placed
        # then
        assert len(self.orders(keeper)) == 3

        # when [9.5+0.5 = 10]
        keeper.our_orders.append(
            deployment.etherdelta.create_order(EtherDelta.ETH_TOKEN,
                                               Wad.from_number(0.5),
                                               deployment.sai.address,
                                               Wad.from_number(52), 1000000))
        # and
        keeper.synchronize_orders(
        )  # ... first call is so it can made deposits
        keeper.synchronize_orders(
        )  # ... second call is so the actual orders can get placed
        # then
        assert len(self.orders(keeper)) == 4

        # when [10+0.1 = 10.1] --> above max!
        keeper.our_orders.append(
            deployment.etherdelta.create_order(EtherDelta.ETH_TOKEN,
                                               Wad.from_number(0.1),
                                               deployment.sai.address,
                                               Wad.from_number(10.4), 1000000))
        # and
        keeper.synchronize_orders(
        )  # ... first call is so it can made deposits
        keeper.synchronize_orders(
        )  # ... second call is so the actual orders can get placed
        # then
        assert len(self.orders(keeper)) == 4
        assert reduce(Wad.__add__, map(lambda order: order.pay_amount, self.orders_by_token(keeper, EtherDelta.ETH_TOKEN)), Wad(0)) \
               == Wad.from_number(10.0)
Exemple #41
0
    def test_should_deposit_and_create_orders_on_startup(
            self, deployment: Deployment, tmpdir: py.path.local):
        # given
        config_file = BandConfig.sample_config(tmpdir)

        # and
        keeper = EtherDeltaMarketMakerKeeper(args=args(
            f"--eth-from {deployment.our_address} --config {config_file}"
            f" --tub-address {deployment.tub.address}"
            f" --etherdelta-address {deployment.etherdelta.address}"
            f" --etherdelta-socket https://127.0.0.1:99999/"
            f" --order-age 3600 --eth-reserve 10"
            f" --min-eth-deposit 1 --min-sai-deposit 400"),
                                             web3=deployment.web3)
        keeper.lifecycle = Web3Lifecycle(web3=keeper.web3)
        keeper.etherdelta_api.publish_order = MagicMock()

        # and
        self.mint_tokens(deployment)
        self.set_price(deployment, Wad.from_number(100))

        # when
        keeper.approve()
        keeper.synchronize_orders(
        )  # ... first call is so it can made deposits
        keeper.synchronize_orders(
        )  # ... second call is so the actual orders can get placed

        # then
        assert deployment.etherdelta.balance_of(
            deployment.our_address) > Wad(0)
        assert deployment.etherdelta.balance_of_token(
            deployment.sai.address, deployment.our_address) > Wad(0)

        # and
        assert len(self.orders(keeper)) == 2
        assert keeper.etherdelta_api.publish_order.call_count == 2

        # and
        assert self.orders_by_token(
            keeper, deployment.sai.address)[0].maker == deployment.our_address
        assert self.orders_by_token(
            keeper,
            deployment.sai.address)[0].pay_amount == Wad.from_number(75)
        assert self.orders_by_token(
            keeper,
            deployment.sai.address)[0].pay_token == deployment.sai.address
        assert self.orders_by_token(
            keeper,
            deployment.sai.address)[0].buy_amount == Wad.from_number(0.78125)
        assert self.orders_by_token(
            keeper,
            deployment.sai.address)[0].buy_token == EtherDelta.ETH_TOKEN

        # and
        assert self.orders_by_token(
            keeper, EtherDelta.ETH_TOKEN)[0].maker == deployment.our_address
        assert self.orders_by_token(
            keeper, EtherDelta.ETH_TOKEN)[0].pay_amount == Wad.from_number(7.5)
        assert self.orders_by_token(
            keeper, EtherDelta.ETH_TOKEN)[0].pay_token == EtherDelta.ETH_TOKEN
        assert self.orders_by_token(
            keeper, EtherDelta.ETH_TOKEN)[0].buy_amount == Wad.from_number(780)
        assert self.orders_by_token(
            keeper,
            EtherDelta.ETH_TOKEN)[0].buy_token == deployment.sai.address
Exemple #42
0
    def test_should_cancel_all_orders_outside_bands(self,
                                                    deployment: Deployment,
                                                    tmpdir: py.path.local):
        # given
        config_file = BandConfig.sample_config(tmpdir)

        # and
        keeper = EtherDeltaMarketMakerKeeper(args=args(
            f"--eth-from {deployment.our_address} --config {config_file}"
            f" --tub-address {deployment.tub.address}"
            f" --etherdelta-address {deployment.etherdelta.address}"
            f" --etherdelta-socket https://127.0.0.1:99999/"
            f" --order-age 3600 --eth-reserve 10"
            f" --min-eth-deposit 1 --min-sai-deposit 400"),
                                             web3=deployment.web3)
        keeper.lifecycle = Web3Lifecycle(web3=keeper.web3)
        keeper.etherdelta_api.publish_order = MagicMock()

        # and
        self.mint_tokens(deployment)
        self.set_price(deployment, Wad.from_number(100))

        # and
        keeper.approve()
        keeper.synchronize_orders(
        )  # ... first call is so it can made deposits
        keeper.synchronize_orders(
        )  # ... second call is so the actual orders can get placed
        assert len(self.orders(keeper)) == 2

        # when
        keeper.our_orders.append(
            deployment.etherdelta.create_order(
                deployment.sai.address,
                Wad.from_number(5), EtherDelta.ETH_TOKEN,
                Wad.from_number(0.0538), 1000000))  #price=92.936802973977695
        keeper.our_orders.append(
            deployment.etherdelta.create_order(deployment.sai.address,
                                               Wad.from_number(5),
                                               EtherDelta.ETH_TOKEN,
                                               Wad.from_number(0.0505),
                                               1000000))  #price=99.0
        keeper.our_orders.append(
            deployment.etherdelta.create_order(EtherDelta.ETH_TOKEN,
                                               Wad.from_number(0.5),
                                               deployment.sai.address,
                                               Wad.from_number(50.5),
                                               1000000))  #price=101
        keeper.our_orders.append(
            deployment.etherdelta.create_order(EtherDelta.ETH_TOKEN,
                                               Wad.from_number(0.5),
                                               deployment.sai.address,
                                               Wad.from_number(53.5),
                                               1000000))  #price=107
        assert len(self.orders(keeper)) == 6
        # and
        keeper.synchronize_orders(
        )  # ... first call is so it can made deposits
        keeper.synchronize_orders(
        )  # ... second call is so the actual orders can get placed
        # then
        assert len(self.orders(keeper)) == 2