Ejemplo n.º 1
0
 def deposit_for_buy_orders(self):
     order_total = self.total_amount(self.our_buy_orders())
     currently_deposited = self.etherdelta.balance_of(self.our_address)
     if order_total > currently_deposited:
         depositable_eth = Wad.max(
             self.eth_balance(self.our_address) - self.eth_reserve, Wad(0))
         additional_deposit = Wad.min(order_total - currently_deposited,
                                      depositable_eth)
         if additional_deposit > Wad(0):
             self.etherdelta.deposit(additional_deposit)
Ejemplo n.º 2
0
    def bustable_amount_in_sai(self, tap: Tap):
        #TODO we always try to bust 10 SAI less than what the Tub reports
        #in order to discount the growth of `joy()` that might've have happened since the last drip
        #of course this is not the right solution and it won't even work properly if the last
        #drip happened enough time ago
        bustable_woe = tap.woe() - tap.joy() - Wad.from_number(10)

        # we deduct 0.000001 in order to avoid rounding errors
        bustable_fog = tap.fog() * tap.ask() - Wad.from_number(0.000001)

        return Wad.max(bustable_woe, bustable_fog, Wad.from_number(0))
Ejemplo n.º 3
0
 def __init__(self, lpc: Lpc):
     self.lpc = lpc
     rate = Ray(self.lpc.par() / (self.lpc.tag() * self.lpc.gap()))
     #TODO we always leave 0.000001 in the liquidity pool, in case of some rounding errors
     max_entry_ref = Wad.max(
         (ERC20Token(web3=lpc.web3, address=lpc.alt()).balance_of(
             lpc.address) / Wad(rate)) - Wad.from_number(0.000001),
         Wad.from_number(0))
     super().__init__(source_token=self.lpc.ref(),
                      target_token=self.lpc.alt(),
                      rate=rate,
                      max_source_amount=max_entry_ref,
                      method="lpc.take(alt)")
    def perform(self, auctionlet, context):
        auction = auctionlet.get_auction()

        # this strategy supports forward auctions only
        if not auction.is_forward():
            return StrategyResult(f"Not a forward auction. Forgetting it.",
                                  forget=True)

        # we trade only on our token pair
        if (auction.selling != self.we_buy) or (auction.buying !=
                                                self.we_sell):
            return StrategyResult("Unrecognized token pair. Forgetting it.",
                                  forget=True)

        # we do not do anything if we are already winning
        if auctionlet.last_bidder == context.trader_address:
            return StrategyResult(
                'We are the highest bidder. Not doing anything.')

        # handle expired auctions, we either claim them or forget them
        if auctionlet.expired:
            if auctionlet.unclaimed:
                if auctionlet.last_bidder == context.trader_address:
                    if auctionlet.claim():
                        return StrategyResult(
                            "Expired and unclaimed, we won, claimed by us successfully. Forgetting it.",
                            forget=True)
                    else:
                        return StrategyResult(
                            "Expired and unclaimed, we won, tried to claim it but claim failed"
                        )
                else:
                    return StrategyResult(
                        'Expired and unclaimed, waiting to be claimed by somebody else. Forgetting it.',
                        forget=True)
            else:
                return StrategyResult('Expired and claimed. Forgetting it.',
                                      forget=True)

        # get the current buy amount and the minimum possible increase
        auction_current_bid = auctionlet.buy_amount
        auction_min_next_bid = auction_current_bid * Wad.from_number(
            (100 + auction.min_increase) / 100)
        assert (auction_min_next_bid >= auction_current_bid)

        # calculate our maximum bid
        our_max_bid = auctionlet.sell_amount / self.mkr_dai_rate

        # if the current auction bid amount has already reached our maximum bid
        # then we can not go higher, so we do not bid
        if auction_current_bid >= our_max_bid:
            return StrategyResult(
                f"Our maximum possible bid ({our_max_bid} {auction.buying.name()}) reached"
            )

        # if the auction next minimum increase is greater than our maximum possible bid
        # then we can not go higher, so we do not bid
        if auction_min_next_bid > our_max_bid:
            return StrategyResult(
                f"Minimal increase ({auction_min_next_bid} {auction.buying.name()}) exceeds our maximum possible bid ({our_max_bid} {auction.buying.name()})"
            )

        # if the our global minimal bid is greater than our maximum possible bid then we do not bid
        if self.minimal_bid > our_max_bid:
            return StrategyResult(
                f"Minimal allowed bid ({self.minimal_bid} {auction.buying.name()}) exceeds our maximum possible bid ({our_max_bid} {auction.buying.name()})"
            )

        # we never bid if our available balance is below global minimal bid
        our_balance = auction.buying.balance_of(context.trader_address)
        if our_balance < self.minimal_bid:
            return StrategyResult(
                f"Not bidding as available balance ({our_balance} {auction.buying.name()}) is less than minimal allowed bid ({self.minimal_bid} {auction.buying.name()})"
            )

        # this his how much we want to bid in ideal conditions...
        our_preferred_bid = auction_current_bid + (
            our_max_bid - auction_current_bid) * self.step
        # ...but we can still end up bidding more (either because of the 'min_increase' auction parameter...
        our_preferred_bid = Wad.max(our_preferred_bid, auction_min_next_bid)
        # ...or because of the global minimal bid)
        our_preferred_bid = Wad.max(our_preferred_bid, self.minimal_bid)

        # at the end, we cannot bid more than we actually have in our account
        our_bid = Wad.min(our_preferred_bid, our_balance)

        if our_bid < auction_min_next_bid:
            if auctionlet.can_split():
                our_preferred_rate = our_preferred_bid / auctionlet.sell_amount
                our_bid = our_balance
                quantity = our_balance / our_preferred_rate

                # we check our allowance, and raise it if necessary
                if not self._ensure_allowance(auction, context, our_bid):
                    return StrategyResult(
                        f"Tried to raise {auction.buying.name()} allowance, but the attempt failed"
                    )

                if auctionlet.bid(our_bid, quantity):
                    return StrategyResult(
                        f"Placed a new partial bid at {our_bid} {auction.buying.name()} (for {quantity} {auction.selling.name()}), bid was successful, new auctionlet got created"
                    )
                else:
                    return StrategyResult(
                        f"Tried to place a new bid at {our_bid} {auction.buying.name()} (partial bid for {quantity} {auction.selling.name()}), but the bid failed"
                    )
            else:
                return StrategyResult(
                    f"Our available balance ({our_balance} {auction.buying.name()} is below minimal next bid ({auction_min_next_bid} {auction.buying.name()}) and splitting is unavailable"
                )
        else:
            # we check our allowance, and raise it if necessary
            if not self._ensure_allowance(auction, context, our_bid):
                return StrategyResult(
                    f"Tried to raise {auction.buying.name()} allowance, but the attempt failed"
                )

            # a set of assertions to double-check our calculations
            assert (our_bid > auction_current_bid)
            assert (our_bid >= auction_min_next_bid)
            assert (our_bid <= our_max_bid)

            if auctionlet.bid(our_bid):
                if our_bid < our_max_bid:
                    return StrategyResult(
                        f"Placed a new bid at {our_bid} {auction.buying.name()}, bid was successful. Our maximum bid on this auctionlet is {our_max_bid} {auction.buying.name()}"
                    )
                else:
                    return StrategyResult(
                        f"Placed a new bid at {our_bid} {auction.buying.name()}, bid was successful"
                    )
            else:
                return StrategyResult(
                    f"Tried to place a new bid at {our_bid} {auction.buying.name()}, but the bid failed"
                )
Ejemplo n.º 5
0
 def boomable_amount_in_skr(self, tap: Tap):
     # we deduct 0.000001 in order to avoid rounding errors
     return Wad.max(
         Wad(self.boomable_amount_in_sai(tap) / (tap.bid())) -
         Wad.from_number(0.000001), Wad.from_number(0))
Ejemplo n.º 6
0
 def boomable_amount_in_sai(self, tap: Tap):
     return Wad.max(tap.joy() - tap.woe(), Wad.from_number(0))
Ejemplo n.º 7
0
 def test_max_value_should_reject_comparison_with_ints(self):
     with pytest.raises(ArithmeticError):
         Wad.max(Wad(10), 20)
     with pytest.raises(ArithmeticError):
         Wad.max(15, Wad(25))
Ejemplo n.º 8
0
 def test_max_value_should_reject_comparison_with_rays(self):
     with pytest.raises(ArithmeticError):
         Wad.max(Wad(10), Ray(20))
     with pytest.raises(ArithmeticError):
         Wad.max(Wad(25), Ray(15))
Ejemplo n.º 9
0
 def test_max_value(self):
     assert Wad.max(Wad(10), Wad(20)) == Wad(20)
     assert Wad.max(Wad(25), Wad(15)) == Wad(25)
     assert Wad.max(Wad(25), Wad(15), Wad(40)) == Wad(40)