Example #1
0
    def handle_bid(self, id: int, auction: Auction):
        assert isinstance(id, int)
        assert isinstance(auction, Auction)

        output = auction.model_output()

        if output is None:
            return

        bid_price, bid_transact, cost = self.strategy.bid(id, output.price)
        # If we can't afford the bid, log a warning/error and back out.
        # By continuing, we'll burn through gas fees while the keeper pointlessly retries the bid.
        if cost is not None:
            if not self.check_bid_cost(cost):
                return

        if bid_price is not None and bid_transact is not None:
            # if no transaction in progress, send a new one
            transaction_in_progress = auction.transaction_in_progress()

            if transaction_in_progress is None:
                self.logger.info(
                    f"Sending new bid @{output.price} (gas_price={output.gas_price})"
                )

                auction.price = bid_price
                auction.gas_price = UpdatableGasPrice(output.gas_price)
                auction.register_transaction(bid_transact)

                self._run_future(
                    bid_transact.transact_async(gas_price=auction.gas_price))
                if self.arguments.bid_delay:
                    logging.debug(f"Waiting {self.arguments.bid_delay}s")
                    time.sleep(self.arguments.bid_delay)

            # if transaction in progress and gas price went up...
            elif output.gas_price and output.gas_price > auction.gas_price.gas_price:

                # ...replace the entire bid if the price has changed...
                if bid_price != auction.price:
                    self.logger.info(
                        f"Overriding pending bid with new bid @{output.price} (gas_price={output.gas_price})"
                    )

                    auction.price = bid_price
                    auction.gas_price = UpdatableGasPrice(output.gas_price)
                    auction.register_transaction(bid_transact)

                    self._run_future(
                        bid_transact.transact_async(
                            replace=transaction_in_progress,
                            gas_price=auction.gas_price))
                # ...or just replace gas_price if price stays the same
                else:
                    self.logger.info(
                        f"Overriding pending bid with new gas_price ({output.gas_price})"
                    )

                    auction.gas_price.update_gas_price(output.gas_price)
Example #2
0
    def handle_bid(self, id: int, auction: Auction, reservoir: Reservoir):
        assert isinstance(id, int)
        assert isinstance(auction, Auction)
        assert isinstance(reservoir, Reservoir)

        output = auction.model_output()
        if output is None:
            return

        if isinstance(self.strategy, StrategyTakeAvailable):
            bid_price, bid_transact, cost = self.strategy.bid_available(
                id, output.price, reservoir.level)
        else:
            bid_price, bid_transact, cost = self.strategy.bid(id, output.price)
        # If we can't afford the bid, log a warning/error and back out.
        # By continuing, we'll burn through gas fees while the keeper pointlessly retries the bid.
        if cost is not None:
            if not self.check_bid_cost(id, cost, reservoir):
                return

        if bid_price is not None and bid_transact is not None:
            assert isinstance(bid_price, Wad)
            # Ensure this auction has a gas strategy assigned
            (new_gas_strategy,
             fixed_gas_price_changed) = auction.determine_gas_strategy_for_bid(
                 output, self.gas_price)

            # if no transaction in progress, send a new one
            transaction_in_progress = auction.transaction_in_progress()

            logging.debug(
                f"Handling bid for auction {id}: tx in progress={transaction_in_progress is not None}, "
                f"auction.price={auction.price}, bid_price={bid_price}")

            # if transaction has not been submitted...
            if transaction_in_progress is None:
                self.logger.info(
                    f"Sending new bid @{output.price} for auction {id}")
                auction.price = bid_price
                auction.gas_price = new_gas_strategy if new_gas_strategy else auction.gas_price
                auction.register_transaction(bid_transact)

                # ...submit a new transaction and wait the delay period (if so configured)
                self._run_future(
                    bid_transact.transact_async(gas_price=auction.gas_price))
                if self.arguments.bid_delay:
                    logging.debug(f"Waiting {self.arguments.bid_delay}s")
                    time.sleep(self.arguments.bid_delay)

            # if transaction in progress and the bid price changed...
            elif auction.price and bid_price != auction.price:
                self.logger.info(
                    f"Attempting to override pending bid with new bid @{output.price} for auction {id}"
                )
                auction.price = bid_price
                if new_gas_strategy:  # gas strategy changed
                    auction.gas_price = new_gas_strategy
                elif fixed_gas_price_changed:  # gas price updated
                    assert isinstance(auction.gas_price, UpdatableGasPrice)
                    auction.gas_price.update_gas_price(output.gas_price)
                auction.register_transaction(bid_transact)

                # ...ask pymaker to replace the transaction
                self._run_future(
                    bid_transact.transact_async(
                        replace=transaction_in_progress,
                        gas_price=auction.gas_price))

            # if model has been providing a gas price, and only that changed...
            elif fixed_gas_price_changed:
                assert isinstance(auction.gas_price, UpdatableGasPrice)
                self.logger.info(
                    f"Overriding pending bid with new gas_price ({output.gas_price}) for auction {id}"
                )
                auction.gas_price.update_gas_price(output.gas_price)

            # if transaction in progress, bid price unchanged, but gas strategy changed...
            elif new_gas_strategy:
                self.logger.info(
                    f"Changing gas strategy for pending bid @{output.price} for auction {id}"
                )
                auction.price = bid_price
                auction.gas_price = new_gas_strategy
                auction.register_transaction(bid_transact)

                # ...ask pymaker to replace the transaction
                self._run_future(
                    bid_transact.transact_async(
                        replace=transaction_in_progress,
                        gas_price=auction.gas_price))
Example #3
0
    def handle_bid(self, id: int, auction: Auction):
        assert isinstance(id, int)
        assert isinstance(auction, Auction)

        input = self.strategy.get_input(id)  #get auction params from chain
        output = auction.model_output()  #get params from own price model

        if output is None:
            return

        managed_price = self.balance_manager.analyze_profit(
            self.gas_price, output.price, input.lot, input.end, input.price,
            input.beg, id)

        if managed_price is None:
            return

        withdrew = self.balance_manager.dsr_withdraw(self.gas_price, id)
        if withdrew:
            self.rebalance_dai()
            time.sleep(1)

        bid_price, bid_transact, cost = self.strategy.bid(id, managed_price)
        # If we can't afford the bid, log a warning/error and back out.
        # By continuing, we'll burn through gas fees while the keeper pointlessly retries the bid.
        logging.info(f"should bid @ {bid_price} {cost}")

        if cost is not None:
            if not self.check_bid_cost(cost):
                return

        if bid_price is not None and bid_transact is not None:
            # Ensure this auction has a gas strategy assigned
            (new_gas_strategy,
             fixed_gas_price_changed) = auction.determine_gas_strategy_for_bid(
                 output, self.gas_price)

            # if no transaction in progress, send a new one
            transaction_in_progress = auction.transaction_in_progress()
            logging.info(f"should be bidding")
            # if transaction has not been submitted...
            if transaction_in_progress is None:
                self.logger.info(
                    f"Sending new bid @{managed_price} (gas_price={output.gas_price})"
                )

                auction.price = bid_price
                auction.gas_price = new_gas_strategy if new_gas_strategy else auction.gas_price
                auction.register_transaction(bid_transact)

                # ...submit a new transaction and wait the delay period (if so configured)
                self._run_future(
                    bid_transact.transact_async(gas_price=auction.gas_price))
                if self.arguments.bid_delay:
                    logging.debug(f"Waiting {self.arguments.bid_delay}s")
                    time.sleep(self.arguments.bid_delay)

            # if transaction in progress and the bid price changed...
            elif bid_price != auction.price:
                self.logger.info(
                    f"Attempting to override pending bid with new bid @{managed_price} for auction {id}"
                )
                auction.price = bid_price
                if new_gas_strategy:  # gas strategy changed
                    auction.gas_price = new_gas_strategy
                elif fixed_gas_price_changed:  # gas price updated
                    assert isinstance(auction.gas_price, UpdatableGasPrice)
                    auction.gas_price.update_gas_price(output.gas_price)
                auction.register_transaction(bid_transact)

                # ...ask pymaker to replace the transaction
                self._run_future(
                    bid_transact.transact_async(
                        replace=transaction_in_progress,
                        gas_price=auction.gas_price))

            # if model has been providing a gas price, and only that changed...
            elif fixed_gas_price_changed:
                assert isinstance(auction.gas_price, UpdatableGasPrice)
                self.logger.info(
                    f"Overriding pending bid with new gas_price ({output.gas_price}) for auction {id}"
                )
                auction.gas_price.update_gas_price(output.gas_price)

            # if transaction in progress, bid price unchanged, but gas strategy changed...
            elif new_gas_strategy:
                self.logger.info(
                    f"Changing gas strategy for pending bid @{managed_price} for auction {id}"
                )
                auction.price = bid_price
                auction.gas_price = new_gas_strategy
                auction.register_transaction(bid_transact)

                # ...ask pymaker to replace the transaction
                self._run_future(
                    bid_transact.transact_async(
                        replace=transaction_in_progress,
                        gas_price=auction.gas_price))