コード例 #1
0
    def synchronize_orders(self):
        bands = Bands(self.bands_config, self.spread_feed, self.history)
        our_balances = self.our_balances()
        our_orders = self.our_orders()
        target_price = self.price_feed.get_price()

        # Cancel orders
        cancellable_orders = bands.cancellable_orders(our_buy_orders=self.our_buy_orders(our_orders),
                                                      our_sell_orders=self.our_sell_orders(our_orders),
                                                      target_price=target_price)
        if len(cancellable_orders) > 0:
            self.cancel_orders(cancellable_orders)
            return

        # Place new orders
        new_orders = bands.new_orders(our_buy_orders=self.our_buy_orders(our_orders),
                                      our_sell_orders=self.our_sell_orders(our_orders),
                                      our_buy_balance=self.our_available_balance(our_balances, self.token_buy()),
                                      our_sell_balance=self.our_available_balance(our_balances, self.token_sell()),
                                      target_price=target_price)[0]

        if len(new_orders) > 0:
            if self.can_create_orders():
                self.place_orders(new_orders)
                self.register_order_creation()
            else:
                self.logger.info("Too little time elapsed from last order creation, waiting...")
コード例 #2
0
    def synchronize_orders(self):
        bands = Bands(self.bands_config, self.spread_feed, self.history)
        order_book = self.order_book_manager.get_order_book()
        target_price = self.price_feed.get_price()

        # Cancel orders
        cancellable_orders = bands.cancellable_orders(
            our_buy_orders=self.our_buy_orders(order_book.orders),
            our_sell_orders=self.our_sell_orders(order_book.orders),
            target_price=target_price)
        if len(cancellable_orders) > 0:
            self.order_book_manager.cancel_orders(cancellable_orders)
            return

        # Do not place new orders if order book state is not confirmed
        if order_book.orders_being_placed or order_book.orders_being_cancelled:
            self.logger.debug(
                "Order book is in progress, not placing new orders")
            return

        # Place new orders
        self.order_book_manager.place_orders(
            bands.new_orders(
                our_buy_orders=self.our_buy_orders(order_book.orders),
                our_sell_orders=self.our_sell_orders(order_book.orders),
                our_buy_balance=self.our_available_balance(
                    order_book.balances, self.token_buy()),
                our_sell_balance=self.our_available_balance(
                    order_book.balances, self.token_sell()),
                target_price=target_price)[0])
    def synchronize_orders(self):
        """Update our positions in the order book to reflect keeper parameters."""
        if eth_balance(self.web3, self.our_address) < self.min_eth_balance:
            self.logger.warning(
                "Keeper ETH balance below minimum. Cancelling all orders.")
            self.cancel_orders(self.our_orders())
            return

        bands = Bands(self.bands_config)
        our_orders = self.our_orders()
        target_price = self.price()

        if target_price is None:
            self.logger.warning(
                "Cancelling all orders as no price feed available.")
            self.cancel_orders(our_orders)
            return

        # Cancel orders
        cancellable_orders = bands.cancellable_orders(
            our_buy_orders=self.our_buy_orders(our_orders),
            our_sell_orders=self.our_sell_orders(our_orders),
            target_price=target_price)
        if len(cancellable_orders) > 0:
            self.cancel_orders(cancellable_orders)
            return

        # Place new orders
        self.create_orders(
            bands.new_orders(
                our_buy_orders=self.our_buy_orders(our_orders),
                our_sell_orders=self.our_sell_orders(our_orders),
                our_buy_balance=self.our_balance(self.token_buy()),
                our_sell_balance=self.our_balance(self.token_sell()),
                target_price=target_price))
コード例 #4
0
    def synchronize_orders(self):
        bands = Bands(self.bands_config)
        our_balances = self.our_balances()
        our_orders = self.our_orders()
        target_price = self.price_feed.get_price()

        if target_price is None:
            self.logger.warning(
                "Cancelling all orders as no price feed available.")
            self.cancel_orders(our_orders)
            return

        # Cancel orders
        cancellable_orders = bands.cancellable_orders(
            our_buy_orders=self.our_buy_orders(our_orders),
            our_sell_orders=self.our_sell_orders(our_orders),
            target_price=target_price)
        if len(cancellable_orders) > 0:
            self.cancel_orders(cancellable_orders)
            return

        # Place new orders
        self.create_orders(
            bands.new_orders(
                our_buy_orders=self.our_buy_orders(our_orders),
                our_sell_orders=self.our_sell_orders(our_orders),
                our_buy_balance=self.our_balance(our_balances,
                                                 self.token_buy()),
                our_sell_balance=self.our_balance(our_balances,
                                                  self.token_sell()),
                target_price=target_price))
コード例 #5
0
    def synchronize_orders(self):
        bands = Bands(self.bands_config)
        our_balances = self.our_balances()
        our_orders = self.our_orders()
        target_price = self.price_feed.get_price()

        if target_price is None:
            self.logger.warning("Cancelling all orders as no price feed available.")
            self.cancel_orders(our_orders)
            return

        # Cancel orders
        cancellable_orders = bands.cancellable_orders(our_buy_orders=self.our_buy_orders(our_orders),
                                                      our_sell_orders=self.our_sell_orders(our_orders),
                                                      target_price=target_price)
        if len(cancellable_orders) > 0:
            self.cancel_orders(cancellable_orders)
            return

        # Place new orders
        new_orders = bands.new_orders(our_buy_orders=self.our_buy_orders(our_orders),
                                      our_sell_orders=self.our_sell_orders(our_orders),
                                      our_buy_balance=self.our_balance(our_balances, self.token_buy()),
                                      our_sell_balance=self.our_balance(our_balances, self.token_sell()),
                                      target_price=target_price)

        if len(new_orders) > 0:
            if self.can_create_orders():
                self.create_orders(new_orders)
                self.register_order_creation()
            else:
                self.logger.info("Too little time elapsed from last order creation, waiting...")
コード例 #6
0
    def synchronize_orders(self):
        # If market is closed, cancel all orders but do not terminate the keeper.
        if self.otc.is_closed():
            self.logger.warning("Market is closed. Cancelling all orders.")
            self.cancel_all_orders()
            return

        # If keeper balance is below `--min-eth-balance`, cancel all orders but do not terminate
        # the keeper, keep processing blocks as the moment the keeper gets a top-up it should
        # resume activity straight away, without the need to restart it.
        if eth_balance(self.web3, self.our_address) < self.min_eth_balance:
            self.logger.warning(
                "Keeper ETH balance below minimum. Cancelling all orders.")
            self.cancel_all_orders()
            return

        bands = Bands(self.bands_config)
        our_orders = self.our_orders()
        target_price = self.price()

        # If the is no target price feed, cancel all orders but do not terminate the keeper.
        # The moment the price feed comes back, the keeper will resume placing orders.
        if target_price is None:
            self.logger.warning(
                "No price feed available. Cancelling all orders.")
            self.cancel_all_orders()
            return

        # If there are any orders to be cancelled, cancel them. It is deliberate that we wait with topping-up
        # bands until the next block. This way we would create new orders based on the most recent price and
        # order book state. We could theoretically retrieve both (`target_price` and `our_orders`) again here,
        # but it just seems cleaner to do it in one place instead of in two.
        cancellable_orders = bands.cancellable_orders(
            our_buy_orders=self.our_buy_orders(our_orders),
            our_sell_orders=self.our_sell_orders(our_orders),
            target_price=target_price)

        if len(cancellable_orders) > 0:
            self.cancel_orders(cancellable_orders)
            return

        # If there are any new orders to be created, create them.
        new_orders = bands.new_orders(
            our_buy_orders=self.our_buy_orders(our_orders),
            our_sell_orders=self.our_sell_orders(our_orders),
            our_buy_balance=self.our_balance(self.token_buy()),
            our_sell_balance=self.our_balance(self.token_sell()),
            target_price=target_price)

        if len(new_orders) > 0:
            self.create_orders(new_orders)

            # We do wait some time after the orders have been created. The reason for that is sometimes
            # orders that have been just placed were not picked up by the next `our_orders()` call
            # (one can presume the block hasn't been fully imported into the node yet), which made
            # the keeper try to place same order(s) again. Of course the second transaction did fail, but it
            # resulted in wasted gas and significant delay in keeper operation.
            #
            # There is no specific reason behind choosing to wait exactly 3s.
            time.sleep(3)
    def synchronize_orders(self):
        """Update our positions in the order book to reflect keeper parameters."""
        if eth_balance(self.web3, self.our_address) < self.min_eth_balance:
            self.lifecycle.terminate(
                "Keeper balance is below the minimum, terminating.")
            self.cancel_orders(self.our_orders())
            return

        bands = Bands(self.bands_config)
        our_orders = self.our_orders()
        target_price = self.price_feed.get_price()

        if target_price is None:
            self.logger.warning(
                "Cancelling all orders as no price feed available.")
            self.cancel_orders(our_orders)
            return

        self.cancel_orders(
            itertools.chain(
                bands.excessive_buy_orders(self.our_buy_orders(our_orders),
                                           target_price),
                bands.excessive_sell_orders(self.our_sell_orders(our_orders),
                                            target_price),
                bands.outside_orders(self.our_buy_orders(our_orders),
                                     self.our_sell_orders(our_orders),
                                     target_price)))
        self.top_up_bands(our_orders, bands.buy_bands, bands.sell_bands,
                          target_price)
コード例 #8
0
    def synchronize_orders(self):
        if eth_balance(self.web3, self.our_address) < self.min_eth_balance:
            self.logger.warning("Keeper ETH balance below minimum. Cancelling all orders.")
            self.cancel_orders(self.our_orders())
            return

        bands = Bands(self.bands_config, self.spread_feed, self.history)
        our_orders = self.our_orders()
        target_price = self.price_feed.get_price()

        # Cancel orders
        cancellable_orders = bands.cancellable_orders(our_buy_orders=self.our_buy_orders(our_orders),
                                                      our_sell_orders=self.our_sell_orders(our_orders),
                                                      target_price=target_price)
        if len(cancellable_orders) > 0:
            self.cancel_orders(cancellable_orders)
            return

        # Balances returned by `our_total_balance` still contain amounts "locked"
        # by currently open orders, so we need to explicitly subtract these amounts.
        our_buy_balance = self.our_total_balance(self.token_buy) - Bands.total_amount(self.our_buy_orders(our_orders))
        our_sell_balance = self.our_total_balance(self.token_sell) - Bands.total_amount(self.our_sell_orders(our_orders))

        # Place new orders
        self.place_orders(bands.new_orders(our_buy_orders=self.our_buy_orders(our_orders),
                                           our_sell_orders=self.our_sell_orders(our_orders),
                                           our_buy_balance=our_buy_balance,
                                           our_sell_balance=our_sell_balance,
                                           target_price=target_price)[0])
コード例 #9
0
    def synchronize_orders(self):
        bands = Bands.read(self.bands_config, self.spread_feed, self.history)
        order_book = self.order_book_manager.get_order_book()
        target_price = self.price_feed.get_price()

        # Cancel orders
        cancellable_orders = bands.cancellable_orders(our_buy_orders=self.our_buy_orders(order_book.orders),
                                                      our_sell_orders=self.our_sell_orders(order_book.orders),
                                                      target_price=target_price)
        if len(cancellable_orders) > 0:
            self.order_book_manager.cancel_orders(cancellable_orders)
            return

        # Do not place new orders if order book state is not confirmed
        if order_book.orders_being_placed or order_book.orders_being_cancelled:
            self.logger.debug("Order book is in progress, not placing new orders")
            return

        # In case of Paradex, balances returned by `our_total_balance` still contain amounts "locked"
        # by currently open orders, so we need to explicitly subtract these amounts.
        our_buy_balance = self.our_total_buy_balance(order_book.balances) - Bands.total_amount(self.our_buy_orders(order_book.orders))
        our_sell_balance = self.our_total_sell_balance(order_book.balances) - Bands.total_amount(self.our_sell_orders(order_book.orders))

        # Place new orders
        self.place_orders(bands.new_orders(our_buy_orders=self.our_buy_orders(order_book.orders),
                                           our_sell_orders=self.our_sell_orders(order_book.orders),
                                           our_buy_balance=our_buy_balance,
                                           our_sell_balance=our_sell_balance,
                                           target_price=target_price)[0])
コード例 #10
0
    def synchronize_orders(self):
        # If keeper balance is below `--min-eth-balance`, cancel all orders but do not terminate
        # the keeper, keep processing blocks as the moment the keeper gets a top-up it should
        # resume activity straight away, without the need to restart it.
        if eth_balance(self.web3, self.our_address) < self.min_eth_balance:
            self.logger.warning(
                "Keeper ETH balance below minimum. Cancelling all orders.")
            self.cancel_all_orders()
            return

        bands = Bands(self.bands_config)
        block_number = self.web3.eth.blockNumber
        target_price = self.price()

        # If the is no target price feed, cancel all orders but do not terminate the keeper.
        # The moment the price feed comes back, the keeper will resume placing orders.
        if target_price is None:
            self.logger.warning(
                "Cancelling all orders as no price feed available.")
            self.cancel_all_orders()
            return

        # Remove expired orders from the local order list
        self.remove_expired_orders(block_number)

        # Cancel orders
        cancellable_orders = bands.cancellable_orders(self.our_buy_orders(),
                                                      self.our_sell_orders(),
                                                      target_price)
        if len(cancellable_orders) > 0:
            self.cancel_orders(cancellable_orders, block_number)
            return

        # Place new orders
        self.top_up_bands(bands.buy_bands, bands.sell_bands, target_price)
コード例 #11
0
    def synchronize_orders(self):
        bands = Bands(self.bands_config)
        order_book = self.bibox_order_book_manager.get_order_book()
        target_price = self.price()

        if target_price is None:
            self.logger.warning("Cancelling all orders as no price feed available.")
            self.cancel_orders(order_book.orders)
            return

        # Cancel orders
        cancellable_orders = bands.cancellable_orders(our_buy_orders=self.our_buy_orders(order_book.orders),
                                                      our_sell_orders=self.our_sell_orders(order_book.orders),
                                                      target_price=target_price)
        if len(cancellable_orders) > 0:
            self.cancel_orders(cancellable_orders)
            return

        # Do not place new orders if order book state is not confirmed
        if order_book.in_progress:
            self.logger.debug("Order book is in progress, not placing new orders")
            return

        # Place new orders
        self.create_orders(bands.new_orders(our_buy_orders=self.our_buy_orders(order_book.orders),
                                            our_sell_orders=self.our_sell_orders(order_book.orders),
                                            our_buy_balance=self.our_balance(order_book.balances, self.token_buy()),
                                            our_sell_balance=self.our_balance(order_book.balances, self.token_sell()),
                                            target_price=target_price))
コード例 #12
0
    def synchronize_orders(self):
        # If market is closed, cancel all orders but do not terminate the keeper.
        if self.otc.is_closed():
            self.logger.warning("Market is closed. Cancelling all orders.")
            self.order_book_manager.cancel_all_orders()
            return

        # If keeper balance is below `--min-eth-balance`, cancel all orders but do not terminate
        # the keeper, keep processing blocks as the moment the keeper gets a top-up it should
        # resume activity straight away, without the need to restart it.
        if eth_balance(self.web3, self.our_address) < self.min_eth_balance:
            self.logger.warning(
                "Keeper ETH balance below minimum. Cancelling all orders.")
            self.order_book_manager.cancel_all_orders()
            return

        bands = Bands(self.bands_config, self.spread_feed, self.history)
        order_book = self.order_book_manager.get_order_book()
        target_price = self.price_feed.get_price()

        # If there are any orders to be cancelled, cancel them. It is deliberate that we wait with topping-up
        # bands until the next block. This way we would create new orders based on the most recent price and
        # order book state. We could theoretically retrieve both (`target_price` and `our_orders`) again here,
        # but it just seems cleaner to do it in one place instead of in two.
        cancellable_orders = bands.cancellable_orders(
            our_buy_orders=self.our_buy_orders(order_book.orders),
            our_sell_orders=self.our_sell_orders(order_book.orders),
            target_price=target_price)

        if len(cancellable_orders) > 0:
            simulated_book = list(
                set(order_book.orders) - set(cancellable_orders))

            new_orders = bands.new_orders(
                our_buy_orders=self.our_buy_orders(simulated_book),
                our_sell_orders=self.our_sell_orders(simulated_book),
                our_buy_balance=self.our_available_balance(self.token_buy),
                our_sell_balance=self.our_available_balance(self.token_sell),
                target_price=target_price)[0]

            self.order_book_manager.replace_orders(cancellable_orders,
                                                   new_orders)

            return

        # Do not place new orders if order book state is not confirmed
        if order_book.orders_being_placed or order_book.orders_being_cancelled:
            self.logger.debug(
                "Order book is in progress, not placing new orders")
            return

        # Place new orders
        self.order_book_manager.place_orders(
            bands.new_orders(
                our_buy_orders=self.our_buy_orders(order_book.orders),
                our_sell_orders=self.our_sell_orders(order_book.orders),
                our_buy_balance=self.our_available_balance(self.token_buy),
                our_sell_balance=self.our_available_balance(self.token_sell),
                target_price=target_price)[0])
コード例 #13
0
    def synchronize_orders(self):
        bands = Bands.read(self.bands_config, self.spread_feed,
                           self.control_feed, self.history)
        order_book = self.order_book_manager.get_order_book()
        target_price = self.price_feed.get_price()

        # We filter out expired orders from the order book snapshot. The reason for that is that
        # it allows us to replace expired orders faster. Without it, we would have to wait
        # for the next order book refresh in order to realize an order has expired. Unfortunately,
        # in case of 0x order book refresh can be quite slow as it involves making multiple calls
        # to the Ethereum node.
        #
        # By filtering out expired orders here, we can replace them the next `synchronize_orders`
        # tick after they expire. Which is ~ 1s delay, instead of avg ~ 5s without this trick.
        orders = self.remove_expired_orders(order_book.orders)

        if self.our_eth_balance(order_book.balances) < self.min_eth_balance:
            self.logger.warning(
                "Keeper ETH balance below minimum. Cancelling all orders.")
            self.order_book_manager.cancel_all_orders()
            return

        # Cancel orders
        cancellable_orders = bands.cancellable_orders(
            our_buy_orders=self.our_buy_orders(orders),
            our_sell_orders=self.our_sell_orders(orders),
            target_price=target_price)
        if len(cancellable_orders) > 0:
            self.order_book_manager.cancel_orders(cancellable_orders)
            return

        # Do not place new orders if order book state is not confirmed
        if order_book.orders_being_placed or order_book.orders_being_cancelled:
            self.logger.debug(
                "Order book is in progress, not placing new orders")
            return

        # Balances returned by `our_total_***_balance` still contain amounts "locked"
        # by currently open orders, so we need to explicitly subtract these amounts.
        if self.arguments.use_full_balances:
            our_buy_balance = self.our_total_buy_balance(order_book.balances)
            our_sell_balance = self.our_total_sell_balance(order_book.balances)
        else:
            our_buy_balance = self.our_total_buy_balance(
                order_book.balances) - Bands.total_amount(
                    self.our_buy_orders(orders))
            our_sell_balance = self.our_total_sell_balance(
                order_book.balances) - Bands.total_amount(
                    self.our_sell_orders(orders))

        # Place new orders
        self.order_book_manager.place_orders(
            bands.new_orders(our_buy_orders=self.our_buy_orders(orders),
                             our_sell_orders=self.our_sell_orders(orders),
                             our_buy_balance=our_buy_balance,
                             our_sell_balance=our_sell_balance,
                             target_price=target_price)[0])
    def synchronize_orders(self):
        # If keeper balance is below `--min-eth-balance`, cancel all orders but do not terminate
        # the keeper, keep processing blocks as the moment the keeper gets a top-up it should
        # resume activity straight away, without the need to restart it.
        #
        # The exception is when we can withdraw some ETH from EtherDelta. Then we do it and carry on.
        if eth_balance(self.web3, self.our_address) < self.min_eth_balance:
            if self.etherdelta.balance_of(self.our_address) > self.eth_reserve:
                self.logger.warning(f"Keeper ETH balance below minimum, withdrawing {self.eth_reserve}.")
                self.etherdelta.withdraw(self.eth_reserve).transact()
            else:
                self.logger.warning(f"Keeper ETH balance below minimum, cannot withdraw. Cancelling all orders.")
                self.cancel_all_orders()

            return

        bands = Bands(self.bands_config, self.spread_feed, self.history)
        block_number = self.web3.eth.blockNumber
        target_price = self.price_feed.get_price()

        # Remove expired orders from the local order list
        self.remove_expired_orders(block_number)

        # Cancel orders
        cancellable_orders = bands.cancellable_orders(self.our_buy_orders(), self.our_sell_orders(), target_price)
        if len(cancellable_orders) > 0:
            self.cancel_orders(cancellable_orders, block_number)
            return

        # In case of EtherDelta, balances returned by `our_total_balance` still contain amounts "locked"
        # by currently open orders, so we need to explicitly subtract these amounts.
        our_buy_balance = self.our_total_balance(self.token_buy()) - Bands.total_amount(self.our_buy_orders())
        our_sell_balance = self.our_total_balance(self.token_sell()) - Bands.total_amount(self.our_sell_orders())

        # Evaluate if we need to create new orders, and how much do we need to deposit
        new_orders, missing_buy_amount, missing_sell_amount = bands.new_orders(our_buy_orders=self.our_buy_orders(),
                                                                               our_sell_orders=self.our_sell_orders(),
                                                                               our_buy_balance=our_buy_balance,
                                                                               our_sell_balance=our_sell_balance,
                                                                               target_price=target_price)

        # If deposited amount too low for placing buy orders, try to deposit.
        # If deposited amount too low for placing sell orders, try to deposit.
        made_deposit = False

        if missing_buy_amount > Wad(0):
            if self.deposit_for_buy_order():
                made_deposit = True

        if missing_sell_amount > Wad(0):
            if self.deposit_for_sell_order():
                made_deposit = True

        # If we managed to deposit something, do not do anything so we can reevaluate new orders to be created.
        # Otherwise, create new orders.
        if not made_deposit:
            self.place_orders(new_orders)
コード例 #15
0
    def synchronize_orders(self):
        # If keeper balance is below `--min-eth-balance`, cancel all orders but do not terminate
        # the keeper, keep processing blocks as the moment the keeper gets a top-up it should
        # resume activity straight away, without the need to restart it.
        if eth_balance(self.web3, self.our_address) < self.min_eth_balance:
            self.logger.warning(f"Keeper ETH balance below minimum, cancelling all orders.")
            self.cancel_all_orders()

            return

        bands = Bands(self.bands_config, self.spread_feed, self.history)
        our_balances = self.our_balances()
        our_orders = self.our_orders()
        target_price = self.price_feed.get_price()

        # Cancel orders
        cancellable_orders = bands.cancellable_orders(our_buy_orders=self.our_buy_orders(our_orders),
                                                      our_sell_orders=self.our_sell_orders(our_orders),
                                                      target_price=target_price)
        if len(cancellable_orders) > 0:
            self.cancel_orders(cancellable_orders)
            return

        # If we detect that our total balance reported by the API is not equal to the
        # total balance reported by the Ethereum contract, it probably means that some
        # deposits are still pending being credited to our account. In this case
        # we also do not create any new orders, but at the same time existing orders
        # can still be cancelled.
        if not self.balances_match(our_balances):
            self.logger.info("Balances do not match, probably deposits are in progress, waiting.")
            return

        # Evaluate if we need to create new orders, and how much do we need to deposit
        new_orders, missing_buy_amount, missing_sell_amount = bands.new_orders(our_buy_orders=self.our_buy_orders(our_orders),
                                                                               our_sell_orders=self.our_sell_orders(our_orders),
                                                                               our_buy_balance=self.our_available_balance(our_balances, self.token_buy()),
                                                                               our_sell_balance=self.our_available_balance(our_balances, self.token_sell()),
                                                                               target_price=target_price)

        # If deposited amount too low for placing buy orders, try to deposit.
        # If deposited amount too low for placing sell orders, try to deposit.
        made_deposit = False

        if missing_buy_amount > Wad(0):
            if self.deposit_for_buy_order(missing_buy_amount):
                made_deposit = True

        if missing_sell_amount > Wad(0):
            if missing_sell_amount > Wad(0):
                if self.deposit_for_sell_order(missing_sell_amount):
                    made_deposit = True

        # If we managed to deposit something, do not do anything so we can reevaluate new orders to be placed.
        # Otherwise, place new orders.
        if not made_deposit:
            self.place_orders(new_orders)
コード例 #16
0
    def synchronize_orders(self):
        bands = Bands.read(self.bands_config, self.spread_feed,
                           self.control_feed, self.history)

        order_book = self.order_book_manager.get_order_book()
        target_price = self.price_feed.get_price()
        target_price = self.adjust_target_price(target_price)
        self.logger.debug(
            f'target_price buy_price: {target_price.buy_price}, target_price sell_price: {target_price.sell_price}'
        )
        # Cancel orders
        cancellable_orders = bands.cancellable_orders(
            our_buy_orders=self.our_buy_orders(order_book.orders),
            our_sell_orders=self.our_sell_orders(order_book.orders),
            target_price=target_price)
        if len(cancellable_orders) > 0:
            self.order_book_manager.cancel_orders(cancellable_orders)
            return

        # Do not place new orders if order book state is not confirmed
        if order_book.orders_being_placed or order_book.orders_being_cancelled:
            self.logger.info(
                "Order book is in progress, not placing new orders")
            return

        # Place new orders
        new_orders = bands.new_orders(
            our_buy_orders=self.our_buy_orders(order_book.orders),
            our_sell_orders=self.our_sell_orders(order_book.orders),
            our_buy_balance=self.allocated_balance(self.token_buy()),
            our_sell_balance=self.allocated_balance(self.token_sell()),
            target_price=target_price)[0]
        self.place_orders(new_orders)
コード例 #17
0
    def read(reloadable_config: ReloadableConfig, spread_feed: Feed,
             control_feed: Feed, history: History, rules: BinanceUsRules):
        assert (isinstance(rules, BinanceUsRules))
        bands = Bands.read(reloadable_config, spread_feed, control_feed,
                           history)

        return BinanceBands(bands, rules)
コード例 #18
0
    def synchronize_orders(self):
        bands = Bands.read(self.bands_config, self.spread_feed, self.control_feed, self.history)
        order_book = self.order_book_manager.get_order_book()
        target_price = self.price_feed.get_price()

        # Cancel orders
        cancellable_orders = bands.cancellable_orders(our_buy_orders=self.our_buy_orders(order_book.orders),
                                                      our_sell_orders=self.our_sell_orders(order_book.orders),
                                                      target_price=target_price)
        if len(cancellable_orders) > 0:
            self.order_book_manager.cancel_orders(cancellable_orders)
            return

        # Do not place new orders if order book state is not confirmed
        if order_book.orders_being_placed or order_book.orders_being_cancelled:
            self.logger.debug("Order book is in progress, not placing new orders")
            return

        # Place new orders
        new_orders = bands.new_orders(our_buy_orders=self.our_buy_orders(order_book.orders),
                                      our_sell_orders=self.our_sell_orders(order_book.orders),
                                      our_buy_balance=self.our_available_balance(order_book.balances, self.token_buy()),
                                      our_sell_balance=self.our_available_balance(order_book.balances, self.token_sell()),
                                      target_price=target_price)[0]

        if len(new_orders) > 0:
            if self.can_create_orders():
                self.place_orders(new_orders)
                self.register_order_creation()
            else:
                self.logger.info("Too little time elapsed from last order creation, waiting...")
コード例 #19
0
 def create_bands(config_file):
     config = ReloadableConfig(str(config_file))
     return Bands.read(config, EmptyFeed(),
                       FixedFeed({
                           'canBuy': True,
                           'canSell': True
                       }), History())
コード例 #20
0
    def synchronize_orders(self):
        # If market is closed, cancel all orders but do not terminate the keeper.
        if self.otc.is_closed():
            self.logger.warning("Market is closed. Cancelling all orders.")
            self.cancel_all_orders()
            return

        # If keeper balance is below `--min-eth-balance`, cancel all orders but do not terminate
        # the keeper, keep processing blocks as the moment the keeper gets a top-up it should
        # resume activity straight away, without the need to restart it.
        if eth_balance(self.web3, self.our_address) < self.min_eth_balance:
            self.logger.warning("Keeper ETH balance below minimum. Cancelling all orders.")
            self.cancel_all_orders()
            return

        bands = Bands(self.bands_config, self.spread_feed, self.history)
        order_book = self.order_book_manager.get_order_book()
        target_price = self.price_feed.get_price()

        # If there are any orders to be cancelled, cancel them. It is deliberate that we wait with topping-up
        # bands until the next block. This way we would create new orders based on the most recent price and
        # order book state. We could theoretically retrieve both (`target_price` and `our_orders`) again here,
        # but it just seems cleaner to do it in one place instead of in two.
        cancellable_orders = bands.cancellable_orders(our_buy_orders=self.our_buy_orders(order_book.orders),
                                                      our_sell_orders=self.our_sell_orders(order_book.orders),
                                                      target_price=target_price)

        if len(cancellable_orders) > 0:
            self.cancel_orders(cancellable_orders)
            return

        # Do not place new orders if order book state is not confirmed
        if order_book.orders_being_placed or order_book.orders_being_cancelled:
            self.logger.debug("Order book is in progress, not placing new orders")
            return

        # Place new orders
        self.place_orders(bands.new_orders(our_buy_orders=self.our_buy_orders(order_book.orders),
                                           our_sell_orders=self.our_sell_orders(order_book.orders),
                                           our_buy_balance=self.our_available_balance(self.token_buy),
                                           our_sell_balance=self.our_available_balance(self.token_sell),
                                           target_price=target_price)[0])
コード例 #21
0
    def synchronize_orders(self):
        bands = Bands(self.bands_config, self.spread_feed, self.history)
        our_balances = self.our_balances()
        our_orders = self.our_orders()
        target_price = self.price_feed.get_price()

        # Cancel orders
        cancellable_orders = bands.cancellable_orders(our_buy_orders=self.our_buy_orders(our_orders),
                                                      our_sell_orders=self.our_sell_orders(our_orders),
                                                      target_price=target_price)
        if len(cancellable_orders) > 0:
            self.cancel_orders(cancellable_orders)
            return

        # Place new orders
        self.place_orders(bands.new_orders(our_buy_orders=self.our_buy_orders(our_orders),
                                           our_sell_orders=self.our_sell_orders(our_orders),
                                           our_buy_balance=self.our_available_balance(our_balances, self.token_buy()),
                                           our_sell_balance=self.our_available_balance(our_balances, self.token_sell()),
                                           target_price=target_price)[0])
コード例 #22
0
    def synchronize_orders(self):
        """Update our positions in the order book to reflect keeper parameters."""
        if eth_balance(self.web3, self.our_address) < self.min_eth_balance:
            self.logger.warning("Keeper ETH balance below minimum. Cancelling all orders.")
            self.cancel_orders(self.our_orders())
            return

        bands = Bands(self.bands_config, self.history)
        our_orders = self.our_orders()
        target_price = self.price_feed.get_price()

        if target_price is None:
            self.logger.warning("Cancelling all orders as no price feed available.")
            self.cancel_orders(our_orders)
            return

        # Cancel orders
        cancellable_orders = bands.cancellable_orders(our_buy_orders=self.our_buy_orders(our_orders),
                                                      our_sell_orders=self.our_sell_orders(our_orders),
                                                      target_price=target_price)
        if len(cancellable_orders) > 0:
            self.cancel_orders(cancellable_orders)
            return

        # Balances returned by `our_total_balance` still contain amounts "locked"
        # by currently open orders, so we need to explicitly subtract these amounts.
        our_buy_balance = self.our_total_balance(self.token_buy) - Bands.total_amount(self.our_buy_orders(our_orders))
        our_sell_balance = self.our_total_balance(self.token_sell) - Bands.total_amount(self.our_sell_orders(our_orders))

        # Place new orders
        self.place_orders(bands.new_orders(our_buy_orders=self.our_buy_orders(our_orders),
                                           our_sell_orders=self.our_sell_orders(our_orders),
                                           our_buy_balance=our_buy_balance,
                                           our_sell_balance=our_sell_balance,
                                           target_price=target_price)[0])
コード例 #23
0
    def synchronize_orders(self):
        bands = Bands(self.bands_config, self.spread_feed, self.history)
        our_balances = self.our_balances()
        our_orders = self.our_orders()
        target_price = self.price_feed.get_price()

        # Cancel orders
        cancellable_orders = bands.cancellable_orders(
            our_buy_orders=self.our_buy_orders(our_orders),
            our_sell_orders=self.our_sell_orders(our_orders),
            target_price=target_price)
        if len(cancellable_orders) > 0:
            self.cancel_orders(cancellable_orders)
            return

        # Place new orders
        self.place_orders(
            bands.new_orders(our_buy_orders=self.our_buy_orders(our_orders),
                             our_sell_orders=self.our_sell_orders(our_orders),
                             our_buy_balance=self.our_available_balance(
                                 our_balances, self.token_buy()),
                             our_sell_balance=self.our_available_balance(
                                 our_balances, self.token_sell()),
                             target_price=target_price)[0])
コード例 #24
0
    def synchronize_orders(self):
        bands = Bands(self.bands_config, self.spread_feed, self.history)
        order_book = self.order_book_manager.get_order_book()
        target_price = self.price_feed.get_price()

        # Cancel orders
        cancellable_orders = bands.cancellable_orders(our_buy_orders=self.our_buy_orders(order_book.orders),
                                                      our_sell_orders=self.our_sell_orders(order_book.orders),
                                                      target_price=target_price)
        if len(cancellable_orders) > 0:
            self.cancel_orders(cancellable_orders)
            return

        # Do not place new orders if order book state is not confirmed
        if order_book.orders_being_placed or order_book.orders_being_cancelled:
            self.logger.debug("Order book is in progress, not placing new orders")
            return

        # Place new orders
        self.place_orders(bands.new_orders(our_buy_orders=self.our_buy_orders(order_book.orders),
                                           our_sell_orders=self.our_sell_orders(order_book.orders),
                                           our_buy_balance=self.our_available_balance(order_book.balances, self.token_buy()),
                                           our_sell_balance=self.our_available_balance(order_book.balances, self.token_sell()),
                                           target_price=target_price)[0])
コード例 #25
0
    def synchronize_orders(self):
        # If market is closed, cancel all orders but do not terminate the keeper.
        if self.otc.is_closed():
            self.logger.warning("Market is closed. Cancelling all orders.")
            self.order_book_manager.cancel_all_orders()
            return

        # If keeper balance is below `--min-eth-balance`, cancel all orders but do not terminate
        # the keeper, keep processing blocks as the moment the keeper gets a top-up it should
        # resume activity straight away, without the need to restart it.
        if eth_balance(self.web3, self.our_address) < self.min_eth_balance:
            self.logger.warning(
                "Keeper ETH balance below minimum. Cancelling all orders.")
            self.order_book_manager.cancel_all_orders()
            return

        bands = Bands.read(self.bands_config, self.spread_feed,
                           self.control_feed, self.history)
        order_book = self.order_book_manager.get_order_book()
        target_price = self.price_feed.get_price()

        # Cancel orders
        cancellable_orders = bands.cancellable_orders(
            our_buy_orders=self.our_buy_orders(order_book.orders),
            our_sell_orders=self.our_sell_orders(order_book.orders),
            target_price=target_price)
        if len(cancellable_orders) > 0:
            self.order_book_manager.cancel_orders(cancellable_orders)
            return

        # Do not place new orders if other new orders are being placed. In contrary to other keepers,
        # we allow placing new orders when other orders are being cancelled. This is because Ethereum
        # transactions are ordered so we are sure that the order placement will not 'overtake'
        # order cancellation.
        if order_book.orders_being_placed:
            self.logger.debug(
                "Other orders are being placed, not placing new orders")
            return

        # Place new orders
        self.order_book_manager.place_orders(
            bands.new_orders(
                our_buy_orders=self.our_buy_orders(order_book.orders),
                our_sell_orders=self.our_sell_orders(order_book.orders),
                our_buy_balance=self.our_available_balance(self.token_buy),
                our_sell_balance=self.our_available_balance(self.token_sell),
                target_price=target_price)[0])
コード例 #26
0
    def synchronize_orders(self):
        bands = Bands.read(self.bands_config, self.spread_feed,
                           self.control_feed, self.history)
        order_book = self.order_book_manager.get_order_book()
        target_price = self.price_feed.get_price()

        # Cancel orders
        cancellable_orders = bands.cancellable_orders(
            our_buy_orders=self.our_buy_orders(order_book.orders),
            our_sell_orders=self.our_sell_orders(order_book.orders),
            target_price=target_price)
        if len(cancellable_orders) > 0:
            self.cancel_orders(cancellable_orders)
            return

        # Do not place new orders if order book state is not confirmed
        if order_book.orders_being_placed or order_book.orders_being_cancelled:
            self.logger.debug(
                "Order book is in progress, not placing new orders")
            return

        # Evaluate if we need to create new orders, and how much do we need to deposit
        new_orders, missing_buy_amount, missing_sell_amount = bands.new_orders(
            our_buy_orders=self.our_buy_orders(order_book.orders),
            our_sell_orders=self.our_sell_orders(order_book.orders),
            our_buy_balance=self.our_available_balance(self.token_buy_wrapper),
            our_sell_balance=self.our_available_balance(
                self.token_sell_wrapper),
            target_price=target_price)

        # If deposited amount too low for placing buy orders, try to deposit.
        # If deposited amount too low for placing sell orders, try to deposit.
        made_deposit = False

        if missing_buy_amount > Wad(0):
            if self.deposit_for_buy_order(missing_buy_amount):
                made_deposit = True

        if missing_sell_amount > Wad(0):
            if missing_sell_amount > Wad(0):
                if self.deposit_for_sell_order(missing_sell_amount):
                    made_deposit = True

        # If we managed to deposit something, do not do anything so we can reevaluate new orders to be placed.
        # Otherwise, place new orders.
        if not made_deposit:
            self.place_orders(new_orders)
コード例 #27
0
    def synchronize_orders(self):
        if eth_balance(self.web3, self.our_address) < self.min_eth_balance:
            self.logger.warning(
                "Keeper ETH balance below minimum. Cancelling all orders.")
            self.order_book_manager.cancel_all_orders()
            return

        bands = Bands(self.bands_config, self.spread_feed, self.history)
        order_book = self.order_book_manager.get_order_book()
        target_price = self.price_feed.get_price()

        # Cancel orders
        cancellable_orders = bands.cancellable_orders(
            our_buy_orders=self.our_buy_orders(order_book.orders),
            our_sell_orders=self.our_sell_orders(order_book.orders),
            target_price=target_price)
        if len(cancellable_orders) > 0:
            self.order_book_manager.cancel_orders(cancellable_orders)
            return

        # Do not place new orders if order book state is not confirmed
        if order_book.orders_being_placed or order_book.orders_being_cancelled:
            self.logger.debug(
                "Order book is in progress, not placing new orders")
            return

        # In case of Ddex, balances returned by `our_total_balance` still contain amounts "locked"
        # by currently open orders, so we need to explicitly subtract these amounts.
        our_buy_balance = self.our_total_balance(
            self.token_buy) - Bands.total_amount(
                self.our_buy_orders(order_book.orders))
        our_sell_balance = self.our_total_balance(
            self.token_sell) - Bands.total_amount(
                self.our_sell_orders(order_book.orders))

        # Place new orders
        self.place_orders(
            bands.new_orders(
                our_buy_orders=self.our_buy_orders(order_book.orders),
                our_sell_orders=self.our_sell_orders(order_book.orders),
                our_buy_balance=our_buy_balance,
                our_sell_balance=our_sell_balance,
                target_price=target_price)[0])
コード例 #28
0
    def synchronize_orders(self):
        if eth_balance(self.web3, self.our_address) < self.min_eth_balance:
            self.logger.warning(
                "Keeper ETH balance below minimum. Cancelling all orders.")
            self.cancel_orders(self.our_orders())
            return

        bands = Bands(self.bands_config, self.spread_feed, self.history)
        our_orders = self.our_orders()
        target_price = self.price_feed.get_price()

        # Cancel orders
        cancellable_orders = bands.cancellable_orders(
            our_buy_orders=self.our_buy_orders(our_orders),
            our_sell_orders=self.our_sell_orders(our_orders),
            target_price=target_price)
        if len(cancellable_orders) > 0:
            self.cancel_orders(cancellable_orders)
            return

        # In case of Paradex, balances returned by `our_total_balance` still contain amounts "locked"
        # by currently open orders, so we need to explicitly subtract these amounts.
        our_buy_balance = self.our_total_balance(
            self.token_buy) - Bands.total_amount(
                self.our_buy_orders(our_orders))
        our_sell_balance = self.our_total_balance(
            self.token_sell) - Bands.total_amount(
                self.our_sell_orders(our_orders))

        # Place new orders
        self.place_orders(
            bands.new_orders(our_buy_orders=self.our_buy_orders(our_orders),
                             our_sell_orders=self.our_sell_orders(our_orders),
                             our_buy_balance=our_buy_balance,
                             our_sell_balance=our_sell_balance,
                             target_price=target_price)[0])
コード例 #29
0
 def create_bands(config_file):
     config = ReloadableConfig(str(config_file))
     return Bands(config, EmptyFeed(), History())
コード例 #30
0
    def synchronize_orders(self):
        bands = Bands.read(self.bands_config, self.spread_feed,
                           self.control_feed, self.history)
        order_book = self.order_book_manager.get_order_book()
        target_price = self.price_feed.get_price()

        # Cancel orders
        cancellable_orders = bands.cancellable_orders(
            our_buy_orders=self.our_buy_orders(order_book.orders),
            our_sell_orders=self.our_sell_orders(order_book.orders),
            target_price=target_price)
        if len(cancellable_orders) > 0:
            self.order_book_manager.cancel_orders(cancellable_orders)
            return

        # Do not place new orders if order book state is not confirmed
        if order_book.orders_being_placed or order_book.orders_being_cancelled:
            self.logger.debug(
                "Order book is in progress, not placing new orders")
            return

        our_buy_balance = self.our_available_balance(order_book.balances,
                                                     self.token_buy())
        our_sell_balance = self.our_available_balance(order_book.balances,
                                                      self.token_sell())
        total_in_buy_orders = total_buy_amount(
            self.our_buy_orders(order_book.orders))
        total_in_sell_orders = total_sell_amount(
            self.our_sell_orders(order_book.orders))
        our_buy_orders = self.our_buy_orders(order_book.orders)
        our_sell_orders = self.our_sell_orders(order_book.orders)

        # check that placing buy new orders won't require margin
        for band in bands.buy_bands:
            orders = [
                order for order in our_buy_orders
                if band.includes(order, target_price.buy_price)
            ]
            total_amount = total_buy_amount(orders)
            if total_amount < band.min_amount:
                pay_amount = Wad.min(band.avg_amount - total_amount,
                                     our_buy_balance)
                if total_in_buy_orders + pay_amount > our_buy_balance:
                    band.min_amount = Wad(0)

        # check that placing new sell orders won't require margin
        for band in bands.sell_bands:
            orders = [
                order for order in our_sell_orders
                if band.includes(order, target_price.sell_price)
            ]
            total_amount = total_sell_amount(orders)
            if total_amount < band.min_amount:
                pay_amount = Wad.min(band.avg_amount - total_amount,
                                     our_sell_balance)
                if total_in_sell_orders + pay_amount > our_sell_balance:
                    band.min_amount = Wad(0)

        # Place new orders
        self.place_orders(
            bands.new_orders(our_buy_orders=our_buy_orders,
                             our_sell_orders=our_sell_orders,
                             our_buy_balance=our_buy_balance,
                             our_sell_balance=our_sell_balance,
                             target_price=target_price)[0])
コード例 #31
0
    def _get_price_response(self):
        base = self.get_query_argument('base')
        quote = self.get_query_argument('quote')
        side = str(self.get_query_argument('side'))

        if side != "BUY" and side != "SELL":
            return {
                "result": False,
                "exchangeable": False,
                "minAmount": 0.0,
                "maxAmount": 0.0,
                "message": "side value should be BUY or SELL"
            }

        query_pair = f"{quote}/{base}"
        if query_pair != self.pair.base_pair and query_pair != self.pair.counter_pair:
            logging.info(f"Pair {base}/{quote} not supported")
            return {
                "result": False,
                "exchangeable": False,
                "minAmount": 0.0,
                "maxAmount": 0.0,
                "message": f"pair not supported"
            }
        if side == "SELL":
            our_side = "BUY"
        else:
            our_side = "SELL"
        target_price = self.price_feed.get_price()
        logging.info(
            f" Base pair is {self.pair.base_pair} ; Query pair is {query_pair}"
        )

        if query_pair == self.pair.counter_pair and our_side == "BUY":
            bands = Bands.read(self.base_bands_config, self.spread_feed,
                               self.control_feed, self.history)
            band = bands.buy_bands[0]
            price = band.avg_price(target_price.buy_price)

        if query_pair == self.pair.counter_pair and our_side == "SELL":
            bands = Bands.read(self.counter_bands_config, self.spread_feed,
                               self.control_feed, self.history)
            band = bands.sell_bands[0]
            price = band.avg_price(target_price.sell_price)

        if query_pair == self.pair.base_pair and our_side == "SELL":
            bands = Bands.read(self.counter_bands_config, self.spread_feed,
                               self.control_feed, self.history)
            band = bands.buy_bands[0]
            price = 1 / int(band.avg_price(target_price.sell_price))

        if query_pair == self.pair.base_pair and our_side == "BUY":
            bands = Bands.read(self.base_bands_config, self.spread_feed,
                               self.control_feed, self.history)
            band = bands.sell_bands[0]
            price = 1 / int(band.avg_price(target_price.buy_price))

        logging.info(
            f"price: {str(price)}  minAmount: {str(band.min_amount)}  maxAmount: {str(band.max_amount)}"
        )

        return {
            "result": True,
            "exchangeable": True,
            "price": str(price),
            "minAmount": str(band.min_amount),
            "maxAmount": str(band.max_amount)
        }
コード例 #32
0
    def synchronize_orders(self):
        # If keeper balance is below `--min-eth-balance`, cancel all orders but do not terminate
        # the keeper, keep processing blocks as the moment the keeper gets a top-up it should
        # resume activity straight away, without the need to restart it.
        if eth_balance(self.web3, self.our_address) < self.min_eth_balance:
            self.logger.warning(f"Keeper ETH balance below minimum, cancelling all orders.")
            self.cancel_all_orders()

            return

        bands = Bands(self.bands_config, self.history)
        our_balances = self.our_balances()
        our_orders = self.our_orders()
        target_price = self.price_feed.get_price()

        # If the is no target price feed, cancel all orders but do not terminate the keeper.
        # The moment the price feed comes back, the keeper will resume placing orders.
        if target_price is None:
            self.logger.warning("Cancelling all orders as no price feed available.")
            self.cancel_all_orders()
            return

        # Cancel orders
        cancellable_orders = bands.cancellable_orders(our_buy_orders=self.our_buy_orders(our_orders),
                                                      our_sell_orders=self.our_sell_orders(our_orders),
                                                      target_price=target_price)
        if len(cancellable_orders) > 0:
            self.cancel_orders(cancellable_orders)
            return

        # If we detect that our total balance reported by the API is not equal to the
        # total balance reported by the Ethereum contract, it probably means that some
        # deposits are still pending being credited to our account. In this case
        # we also do not create any new orders, but at the same time existing orders
        # can still be cancelled.
        if not self.balances_match(our_balances):
            self.logger.info("Balances do not match, probably deposits are in progress, waiting.")
            return

        # Evaluate if we need to create new orders, and how much do we need to deposit
        new_orders, missing_buy_amount, missing_sell_amount = bands.new_orders(our_buy_orders=self.our_buy_orders(our_orders),
                                                                               our_sell_orders=self.our_sell_orders(our_orders),
                                                                               our_buy_balance=self.our_available_balance(our_balances, self.token_buy()),
                                                                               our_sell_balance=self.our_available_balance(our_balances, self.token_sell()),
                                                                               target_price=target_price)

        # If deposited amount too low for placing buy orders, try to deposit.
        # If deposited amount too low for placing sell orders, try to deposit.
        made_deposit = False

        if missing_buy_amount > Wad(0):
            if self.deposit_for_buy_order(missing_buy_amount):
                made_deposit = True

        if missing_sell_amount > Wad(0):
            if missing_sell_amount > Wad(0):
                if self.deposit_for_sell_order(missing_sell_amount):
                    made_deposit = True

        # If we managed to deposit something, do not do anything so we can reevaluate new orders to be placed.
        # Otherwise, place new orders.
        if not made_deposit:
            self.place_orders(new_orders)
コード例 #33
0
    def synchronize_orders(self):
        # If keeper balance is below `--min-eth-balance`, cancel all orders but do not terminate
        # the keeper, keep processing blocks as the moment the keeper gets a top-up it should
        # resume activity straight away, without the need to restart it.
        #
        # The exception is when we can withdraw some ETH from EtherDelta. Then we do it and carry on.
        if eth_balance(self.web3, self.our_address) < self.min_eth_balance:
            if self.etherdelta.balance_of(self.our_address) > self.eth_reserve:
                self.logger.warning(
                    f"Keeper ETH balance below minimum, withdrawing {self.eth_reserve}."
                )
                self.etherdelta.withdraw(self.eth_reserve).transact()
            else:
                self.logger.warning(
                    f"Keeper ETH balance below minimum, cannot withdraw. Cancelling all orders."
                )
                self.cancel_all_orders()

            return

        bands = Bands.read(self.bands_config, self.spread_feed,
                           self.control_feed, self.history)
        block_number = self.web3.eth.blockNumber
        target_price = self.price_feed.get_price()

        # Remove expired orders from the local order list
        self.remove_expired_orders(block_number)

        # Cancel orders
        cancellable_orders = bands.cancellable_orders(self.our_buy_orders(),
                                                      self.our_sell_orders(),
                                                      target_price)
        if len(cancellable_orders) > 0:
            self.cancel_orders(cancellable_orders, block_number)
            return

        # In case of EtherDelta, balances returned by `our_total_balance` still contain amounts "locked"
        # by currently open orders, so we need to explicitly subtract these amounts.
        our_buy_balance = self.our_total_balance(
            self.token_buy()) - Bands.total_amount(self.our_buy_orders())
        our_sell_balance = self.our_total_balance(
            self.token_sell()) - Bands.total_amount(self.our_sell_orders())

        # Evaluate if we need to create new orders, and how much do we need to deposit
        new_orders, missing_buy_amount, missing_sell_amount = bands.new_orders(
            our_buy_orders=self.our_buy_orders(),
            our_sell_orders=self.our_sell_orders(),
            our_buy_balance=our_buy_balance,
            our_sell_balance=our_sell_balance,
            target_price=target_price)

        # If deposited amount too low for placing buy orders, try to deposit.
        # If deposited amount too low for placing sell orders, try to deposit.
        made_deposit = False

        if missing_buy_amount > Wad(0):
            if self.deposit_for_buy_order():
                made_deposit = True

        if missing_sell_amount > Wad(0):
            if self.deposit_for_sell_order():
                made_deposit = True

        # If we managed to deposit something, do not do anything so we can reevaluate new orders to be created.
        # Otherwise, create new orders.
        if not made_deposit:
            self.place_orders(new_orders)
コード例 #34
0
    def synchronize_orders(self):
        bands = Bands.read(self.bands_config, self.spread_feed, self.history)
        order_book = self.order_book_manager.get_order_book()
        target_price = self.price_feed.get_price()
        # print(type(self.local_orders))
        # print(self.local_orders)
        # print(type(order_book.orders))
        # print(order_book.orders)

        print("---**---The lenght of local_orders " +
              str(self.local_orders.__len__()))
        print("---**---The lenght of order_book.orders " +
              str(len(order_book.orders)))

        local_order_ids = set(order.order_id for order in self.local_orders)
        order_book_ids = set(order.order_id for order in order_book.orders)

        completed_order_ids = list(local_order_ids - order_book_ids)
        # 如果没有后续的更新 local orders,只有这里的更新模块,肯定有问题的,因为一旦有成交,
        # completed_order_ids 不为0,则永远更新不了local orders 了
        # return if there none order be completed
        # 下面这种情况,只有在order_book订单完全"包含"local_order订单时,但是两者并不相等时,才会让本地订单等于远程订单;
        # 这种一般是远程订单比本地订单多,往往比如人工在系统提交了新的订单
        if completed_order_ids.__len__() == 0:
            if local_order_ids.__len__() != order_book_ids.__len__():
                print("update local order")
                self.local_orders = order_book.orders
            return

        # completed_orders = list(filter(lambda order: order.order_id in completed_order_ids, self.local_orders))
        completed_orders = [
            order for order in self.local_orders
            if order.order_id in completed_order_ids
        ]

        # completed_orders = list(filter(lambda order: order.order_id in local_order_ids, order_book.orders))
        print("---**---The lenght of completed orders " +
              str(len(completed_orders)))
        print(completed_orders)

        # completed_orders_new = list(set(self.local_orders) - set(order_book.orders))
        # print("---**---The lenght of completed new orders " + str(len(completed_orders_new)))
        # print(completed_orders_new)

        # completed_orders = [{'amount': Wad(2220000000000000000),
        #              'amount_symbol': 'BIX',
        #              'created_at': 1528203670000,
        #              'is_sell': True,
        #              'money': Wad(52779250000000000),
        #              'money_symbol': 'ETH',
        #              'order_id': 606026215,
        #              'price': Wad(2294750000000000)}, {'amount': Wad(2990000000000000000),
        #              'amount_symbol': 'BIX',
        #              'created_at': 1528203670000,
        #              'is_sell': False,
        #              'money': Wad(55779250000000000),
        #              'money_symbol': 'ETH',
        #              'order_id': 606026215,
        #              'price': Wad(2394750000000000)}]

        # our_buy_orders = self.our_buy_orders(order_book.orders)
        # our_sell_orders = self.our_sell_orders(order_book.orders)
        # print(our_buy_orders)
        # print(our_sell_orders)
        # Do not place new orders if order book state is not confirmed
        if order_book.orders_being_placed or order_book.orders_being_cancelled:
            self.logger.debug(
                "Order book is in progress, not placing new orders")
            return

        # if (self.local_orders.__len__() - len(order_book.orders) > 0):
        if len(completed_orders) > 0:
            print("--------- some orders have been done --------")
            new_orders = []
            step = 1
            count_sell_order = self.count_sell_orders(order_book.orders)
            count_buy_order = self.count_buy_orders(order_book.orders)

            for cod in completed_orders:
                # print(type(cod))
                # print(cod.is_sell)
                # the completed order is sell order, buy order should be placed
                if cod.is_sell:
                    # place buy order, pay attention to rotate bix - eth
                    price = float(cod.price) * (1 - self.arbitrage_percent)
                    print("----to submit a new buy order with price " +
                          str(price))
                    pay_amount = float(cod.amount) * price  # eth money 25
                    buy_amount = float(cod.amount)  # bix amount 0.05
                    new_orders.append(
                        NewOrder(is_sell=False,
                                 price=Wad.from_number(price),
                                 pay_amount=Wad.from_number(pay_amount),
                                 buy_amount=Wad.from_number(buy_amount),
                                 confirm_function=lambda: self.sell_limits.
                                 use_limit(time.time(), pay_amount)))
                    # 以当前价格为基数,重新submit一个高价格的 sell 订单,补充 sell list
                    # place sell a new order with higher price
                    # 需要判断订单的数量是否小于band order limits,并且按照差异补充订单
                    # count_sell_order = self.count_sell_orders(order_book.orders)
                    print(count_sell_order)
                    band_sell_order_gap = self.band_order_limit - count_sell_order
                    print("---band gap---- " + str(band_sell_order_gap))
                    # while band_sell_order_gap > 0: # 外部已经有循环了,不需要这个循环了,否则在多订单被吃时,会加倍补充
                    # 这里只需要判断,控制数量就够了
                    if band_sell_order_gap > 0:
                        current_price = self.bibox_api.get_last_price(
                            self.pair())
                        print("------current price---- " + str(current_price))
                        price = float(current_price) * (
                            1 + self.arbitrage_percent *
                            (step + count_sell_order))
                        print("----higher price to sell--- " + str(price))
                        pay_amount = self.each_order_amount * self.amount_disguise(
                        )  # bix amount
                        buy_amount = pay_amount * price  # eth money
                        new_orders.append(
                            NewOrder(is_sell=True,
                                     price=Wad.from_number(price),
                                     pay_amount=Wad.from_number(pay_amount),
                                     buy_amount=Wad.from_number(buy_amount),
                                     confirm_function=lambda: self.sell_limits.
                                     use_limit(time.time(), pay_amount)))
                        # step = step + 1
                        # band_sell_order_gap = band_sell_order_gap - 1
                        count_sell_order = count_sell_order + 1

                else:  # buy order had been completed
                    # to place a sell order
                    price = float(cod.price) * (1 + self.arbitrage_percent)
                    print("----price--- sell--- ")
                    print(price)
                    pay_amount = float(cod.amount)  # bix amount
                    buy_amount = pay_amount * price  # eth money
                    new_orders.append(
                        NewOrder(is_sell=True,
                                 price=Wad.from_number(price),
                                 pay_amount=Wad.from_number(pay_amount),
                                 buy_amount=Wad.from_number(buy_amount),
                                 confirm_function=lambda: self.sell_limits.
                                 use_limit(time.time(), pay_amount)))
                    # 以当前价格为基数,重新submit一个 buy 订单,补充 buy list
                    # 需要判断订单的数量是否小于band order limits,并且按照差异补充订单
                    # count_buy_order = self.count_buy_orders(order_book.orders)
                    band_buy_order_gap = self.band_order_limit - count_buy_order
                    print("---band gap----" + str(band_buy_order_gap))

                    # while band_buy_order_gap > 0:
                    if band_buy_order_gap > 0:
                        #基础价格放在循环里的话,能快速反映当前价格,特保是激烈波动的时候;但是增加了请求次数
                        current_price = self.bibox_api.get_last_price(
                            self.pair())
                        price = float(current_price) * (
                            1 - self.arbitrage_percent *
                            (step + count_buy_order))
                        print("----lower price order to buy--- " + str(price))
                        tmp = self.each_order_amount * self.amount_disguise()
                        pay_amount = tmp * price  # eth money 25
                        buy_amount = tmp  # bix amount 0.05
                        new_orders.append(
                            NewOrder(is_sell=False,
                                     price=Wad.from_number(price),
                                     pay_amount=Wad.from_number(pay_amount),
                                     buy_amount=Wad.from_number(buy_amount),
                                     confirm_function=lambda: self.sell_limits.
                                     use_limit(time.time(), pay_amount)))

                        # band_buy_order_gap = band_buy_order_gap - 1
                        count_buy_order = count_buy_order + 1
                    step = step + 1

            self.place_orders(new_orders)

            # update local orders, 前面有更新模块,与这边不完全相同,尤其是有成交的情况下,必须要更新
            # 是这样吗? 似乎也不是的,有成交的情况下,下一次订单也会让 set(local) - set(order book)=0的,集合相减的特殊之处
            # 如果这样就没有必要了。
            # 是这样简单的复制更新,还是本地自己维护一个 id list 好呢? 也就是把(1)确定成交的从 local 删除;
            # (2)确定提交的add 到本地;
            # 缩进到循环: if len(completed_orders) > 0:,在出现两者不一致的时候,同步更新订单;
            # 但是这个会导致一个问题,就是初始化的订单里,有price 为0,导致两者不一致的情况,怎么办?这里解决了,是通过 order id对比而不是
            # 直接的 order 对比,所以应该是解决了才对
            print("-----update local order------")
            self.local_orders = self.order_book_manager.get_order_book().orders
コード例 #35
0
    def _get_price_response(self, amount):
        #TODO: edit order calculation so as order amount increases so does our spread (the quote price).

        base = self.get_query_argument('base')
        quote = self.get_query_argument('quote')
        side = str(self.get_query_argument('side'))

        if side != "BUY" and side != "SELL":
            return {
                "result": False,
                "exchangeable": False,
                "minAmount": 0.0,
                "maxAmount": 0.0,
                "message": "side value should be BUY or SELL"
            }

        query_pair = f"{quote}/{base}"
        if query_pair not in self.configs:
            logging.info(f"Pair {base}/{quote} not supported")
            return {
                "result": False,
                "exchangeable": False,
                "minAmount": 0.0,
                "maxAmount": 0.0,
                "message": f"pair not supported"
            }
        if side == "SELL":
            our_side = "BUY"
        else:
            our_side = "SELL"
        target_price = self.configs[query_pair]['price_feed'].get_price()

        logging.info(
            f" Feed price: buy {target_price.buy_price} ; sell {target_price.sell_price}"
        )

        if target_price.buy_price is None or target_price.sell_price is None:
            return {
                "result": False,
                "exchangeable": False,
                "minAmount": 0.0,
                "maxAmount": 0.0,
                "message": f"internal server error, please retry later"
            }

        logging.info(f"Query pair is {query_pair}")

        bands = Bands.read(self.configs[query_pair]['bands_config'],
                           self.configs[query_pair]['spread_feed'],
                           self.configs[query_pair]['control_feed'],
                           self.configs[query_pair]['history'])

        if not self.is_base_pair(query_pair) and our_side == "BUY":
            band = bands.buy_bands[0]
            price = band.avg_price(target_price.buy_price)

        if not self.is_base_pair(query_pair) and our_side == "SELL":
            band = bands.sell_bands[0]
            price = band.avg_price(target_price.sell_price)

        if self.is_base_pair(query_pair) and our_side == "SELL":
            band = bands.buy_bands[0]
            price = Wad.from_number(1) / band.avg_price(
                target_price.sell_price)

        if self.is_base_pair(query_pair) and our_side == "BUY":
            band = bands.sell_bands[0]
            price = Wad.from_number(1) / band.avg_price(target_price.buy_price)

        logging.info(
            f"price: {str(price)}  minAmount: {str(band.min_amount)}  maxAmount: {str(band.max_amount)}"
        )

        return {
            "result": True,
            "exchangeable": Wad.from_number(amount) <= band.max_amount,
            "price": float(price),
            "minAmount": float(band.min_amount),
            "maxAmount": float(band.max_amount)
        }
コード例 #36
0
    def synchronize_orders(self):

        # 交易触发规则:随机触发。产生一个随机数,若命中概率则交易
        current_time = time.strftime("%H")
        freq_dict = {
            '00': np.random.randint(50, 200),
            '01': np.random.randint(50, 100),
            '02': np.random.randint(10, 100),
            '03': np.random.randint(10, 50),
            '04': np.random.randint(10, 50),
            '05': np.random.randint(10, 50),
            '06': np.random.randint(50, 100),
            '07': np.random.randint(100, 200),
            '08': np.random.randint(100, 200),
            '09': np.random.randint(100, 300),
            '10': np.random.randint(100, 300),
            '11': np.random.randint(100, 300),
            '12': np.random.randint(100, 300),
            '13': np.random.randint(100, 300),
            '14': np.random.randint(100, 300),
            '15': np.random.randint(100, 300),
            '16': np.random.randint(100, 300),
            '17': np.random.randint(100, 300),
            '18': np.random.randint(100, 300),
            '19': np.random.randint(100, 300),
            '20': np.random.randint(100, 300),
            '21': np.random.randint(100, 200),
            '22': np.random.randint(100, 200),
            '23': np.random.randint(100, 200)
        }
        freq = freq_dict[current_time]
        hit_number = np.random.random()
        hit_range = freq / (12 * 60.0)
        do_trade = True if hit_number < hit_range else False

        if not do_trade:
            total_freq = reduce(lambda x, y: x + y, list(freq_dict.values()))
            logging.debug(
                f"NOT HIT. total freq is {total_freq} per day. hit_number={hit_number}, hit_range={hit_range}"
            )
            return
        logging.info(
            f"[DO TRADING]hit_number={hit_number}, hit_range={hit_range}")

        order_book = self.order_book_manager.get_order_book()
        current_price = self.price_feed.get_price()
        if current_price.buy_price is None or current_price.sell_price is None:
            self.logger.warning(
                "Current_price:buy_price or sell_price is None")
            return
        logging.info(f"Current_price: {current_price}")

        # Do not place new orders if order book state is not confirmed
        if order_book.orders_being_placed or order_book.orders_being_cancelled:
            self.logger.debug(
                "Order book is in progress, not placing new orders")
            return

        # 只会使用到buy_bands的一个配置,同时应用于买和卖,买卖统一数量
        bands = Bands.read(self.bands_config, self.spread_feed,
                           self.control_feed, self.history)
        band = bands.buy_bands[0]
        price_gap = current_price.sell_price - current_price.buy_price

        # 确定交易的数量和价格
        trade_price = current_price.buy_price + Wad.from_number(
            np.random.uniform(0, float(price_gap)))
        trade_amount = Wad.from_number(
            np.random.uniform(float(band.min_amount), float(band.max_amount)))

        # Place new orders
        new_orders = self.create_new_orders(
            trade_amount=trade_amount,
            trade_price=trade_price,
            our_buy_balance=self.our_available_balance(order_book.balances,
                                                       self.token_buy()),
            our_sell_balance=self.our_available_balance(
                order_book.balances, self.token_sell()),
            band=band)
        self.place_orders(new_orders)
コード例 #37
0
    def synchronize_orders(self):
        bands = Bands.read(self.bands_config, self.spread_feed, self.control_feed, self.history)
        order_book = self.order_book_manager.get_order_book()
        target_price = self.price_feed.get_price()

        # Cancel orders
        cancellable_orders = bands.cancellable_orders(our_buy_orders=self.our_buy_orders(order_book.orders),
                                                      our_sell_orders=self.our_sell_orders(order_book.orders),
                                                      target_price=target_price)
        if len(cancellable_orders) > 0:
            self.order_book_manager.cancel_orders(cancellable_orders)
            return

        # Do not place new orders if order book state is not confirmed
        if order_book.orders_being_placed or order_book.orders_being_cancelled:
            self.logger.debug("Order book is in progress, not placing new orders")
            return

        """
        Check that placing new orders doesn't exceed available balance and won't require margin. 
        This is done separately for each band, to account for potential differences in configuration.
        
        On DyDx, balances aren't lowered if an order is placed,
        so we need to manually adjust balance with amounts in open orders. 
        Since keepers can be running on multiple pairs, orders across all pairs must be checked.
        
        If a potential new order would exceed available balance, 
        setting the minimum band amount to 0 will block the order through band.py conditional checks. 
        The band.min amount would then be reset to the original configuration on the next iteration of synchronize_orders().

        If a new band is valid, we need to then make sure that the available balance calculation
        is adjusted for the potential new order.
        """

        total_in_buy_orders = total_amount(self.our_buy_orders(order_book.orders))
        total_in_sell_orders = total_amount(self.our_sell_orders(order_book.orders))
        for pair in self.market_info.keys():
            other_pair_orders = []
            if self.pair().lower() != pair.lower():
                other_pair_orders = self.dydx_api.get_orders(pair)

            if self.token_buy() in pair.lower():
                total_in_buy_orders += total_amount(self.our_buy_orders(other_pair_orders))
            if self.token_sell() in pair.lower():
                total_in_sell_orders += total_amount(self.our_sell_orders(other_pair_orders))

        our_buy_orders = self.our_buy_orders(order_book.orders)
        our_sell_orders = self.our_sell_orders(order_book.orders)
        our_buy_balance = self.our_available_balance(order_book.balances, self.token_buy())
        our_sell_balance = self.our_available_balance(order_book.balances, self.token_sell())

        for band in bands.buy_bands:
            orders = [order for order in our_buy_orders if band.includes(order, target_price.buy_price)]
            band_total_remaining = total_amount(orders)
            buy_limit_amount = bands.buy_limits.available_limit(time.time())
            available_balance = our_buy_balance - total_in_buy_orders
            if band_total_remaining < band.min_amount:
                pay_amount = Wad.min(band.avg_amount - band_total_remaining, available_balance, buy_limit_amount)
                if total_in_buy_orders + pay_amount > available_balance:
                    band.min_amount = Wad(0)
                else:
                    our_buy_balance -= pay_amount

        for band in bands.sell_bands:
            orders = [order for order in our_sell_orders if band.includes(order, target_price.sell_price)]
            band_total_remaining = total_amount(orders)
            sell_limit_amount = bands.sell_limits.available_limit(time.time())
            available_balance = our_sell_balance - total_in_sell_orders
            if band_total_remaining < band.min_amount:
                pay_amount = Wad.min(band.avg_amount - band_total_remaining, available_balance, sell_limit_amount)
                if total_in_sell_orders + pay_amount > available_balance:
                    band.min_amount = Wad(0)
                else:
                    our_sell_balance -= pay_amount

        # Place new orders
        self.place_orders(bands.new_orders(our_buy_orders=our_buy_orders,
                                           our_sell_orders=our_sell_orders,
                                           our_buy_balance=self.our_available_balance(order_book.balances, self.token_buy()),
                                           our_sell_balance=self.our_available_balance(order_book.balances, self.token_sell()),
                                           target_price=target_price)[0])