コード例 #1
0
 def _setup(self, config):
     # Set buda trading client
     client_params = dict(timeout=self.timeout)
     self.buda = BudaTrading(
         config["market"], client_params, self.dry_run, self.log, self.store
     )
     # Set price multipliers
     self.buy_multiplier = Decimal(str(config["prices"]["buy_multiplier"]))
     self.sell_multiplier = Decimal(str(config["prices"]["sell_multiplier"]))
     self.max_base = Money(config["amounts"]["max_base"], self.buda.market.base)
     self.max_quote = Money(config["amounts"]["max_quote"], self.buda.market.quote)
コード例 #2
0
 def _setup(self, config):
     # Get configs
     self.from_currency = config["from"]["currency"]
     self.from_address = config["from"]["address"]
     self.to_currency = config["to"]["currency"]
     self.to_withdraw = config["to"]["withdraw"]
     self.to_address = config["to"]["address"]
     # Set market
     self.market = self._get_market(self.from_currency, self.to_currency)
     # Set side
     self.side = Side.SELL if self.market.base == self.from_currency else Side.BUY
     # Set buda trading client
     client_params = dict(timeout=self.timeout)
     self.buda = BudaTrading(self.market, client_params, self.dry_run,
                             self.log, self.store)
     # Get deposits
     self.deposits = self.store.get(self.from_currency + "_deposits") or {}
     # Set start timestamp
     if self.store.get("start_timestamp"):
         self.start_timestamp = self.store.get("start_timestamp")
     else:
         self.start_timestamp = maya.now().epoch
         self.store.set("start_timestamp", self.start_timestamp)
コード例 #3
0
class RelativeOrders(Bot):
    label = "RelativeOrders"

    def _setup(self, config):
        # Set buda trading client
        client_params = dict(timeout=self.timeout)
        self.buda = BudaTrading(
            config["market"], client_params, self.dry_run, self.log, self.store
        )
        # Set price multipliers
        self.buy_multiplier = Decimal(str(config["prices"]["buy_multiplier"]))
        self.sell_multiplier = Decimal(str(config["prices"]["sell_multiplier"]))
        self.max_base = Money(config["amounts"]["max_base"], self.buda.market.base)
        self.max_quote = Money(config["amounts"]["max_quote"], self.buda.market.quote)

    def _algorithm(self):
        # PREPARE ORDER PRICES
        # Get middle price
        ticker = self.buda.fetch_ticker()
        self.log.info(
            f"Ticker prices   | Bid: {ticker.bid} | Ask: {ticker.ask} | Mid: {ticker.mid}"
        )
        # Offset prices from middle using configured price multipliers
        price_buy = truncate_money(ticker.mid * self.buy_multiplier)
        price_sell = truncate_money(ticker.mid * self.sell_multiplier)
        self.log.info(f"Relative prices | Buy: {price_buy} | Sell: {price_sell}")
        # PREPARE ORDER AMOUNTS
        # Cancel open orders to get correct available amounts
        self.log.info("Closing open orders")
        self.buda.cancel_all_orders()
        # Fetch available balances
        available_base = self.buda.wallets.base.fetch_balance().free
        available_quote = self.buda.wallets.quote.fetch_balance().free
        # Adjust amounts to max in config
        amount_base = min(self.max_base, available_base)
        amount_quote = min(self.max_quote, available_quote)
        # Get order buy and sell amounts
        # *quote amount must be converted to base
        amount_buy = truncate_money(
            Money(amount_quote / price_buy, self.buda.market.base)
        )
        amount_sell = truncate_money(amount_base)
        self.log.info(f"Amounts | Buy {amount_buy} | Sell {amount_sell}")
        # PLACE ORDERS
        self.log.info("Starting order deployment")
        if amount_buy >= self.buda.min_order_amount:
            self.buda.place_limit_order(
                side=Side.BUY, amount=amount_buy, price=price_buy
            )
        if amount_sell >= self.buda.min_order_amount:
            self.buda.place_limit_order(
                side=Side.SELL, amount=amount_sell, price=price_sell
            )

    def _abort(self):
        self.log.error("Aborting strategy, cancelling all orders")
        try:
            self.buda.cancel_all_orders()
        except Exception:
            self.log.critical("Failed!, some orders might not be cancelled")
            raise
        else:
            self.log.info("All open orders were cancelled")
コード例 #4
0
ファイル: bot.py プロジェクト: bellyfat/trading-bots
class AnyToAny(Bot):
    label = "AnyToAny"

    def _setup(self, config):
        # Get configs
        self.from_currency = config["from"]["currency"]
        self.from_address = config["from"]["address"]
        self.to_currency = config["to"]["currency"]
        self.to_withdraw = config["to"]["withdraw"]
        self.to_address = config["to"]["address"]
        # Set market
        self.market = self._get_market(self.from_currency, self.to_currency)
        # Set side
        self.side = Side.SELL if self.market.base == self.from_currency else Side.BUY
        # Set buda trading client
        client_params = dict(timeout=self.timeout)
        self.buda = BudaTrading(
            self.market, client_params, self.dry_run, self.log, self.store
        )
        # Get deposits
        self.deposits = self.store.get(self.from_currency + "_deposits") or {}
        # Set start timestamp
        if self.store.get("start_timestamp"):
            self.start_timestamp = self.store.get("start_timestamp")
        else:
            self.start_timestamp = maya.now().epoch
            self.store.set("start_timestamp", self.start_timestamp)

    def _algorithm(self):
        # Get new deposits
        self.log.info(f"Checking for new {self.from_currency} deposits")
        self.update_deposits()
        # Convert pending amounts
        self.log.info("Converting pending amounts")
        self.process_conversions()
        # Get available balances
        self.log.info("Processing pending withdrawals")
        self.process_withdrawals()

    def _abort(self):
        pass

    def update_deposits(self):
        # Set wallet from relevant currency according to side
        from_wallet = (
            self.buda.wallets.quote if self.side == Side.BUY else self.buda.wallets.base
        )
        # Get and filter deposits
        new_deposits = from_wallet.fetch_deposits_since(self.start_timestamp)
        if self.from_address != "Any":
            new_deposits = [
                deposit
                for deposit in new_deposits
                if deposit.data.address == self.from_address
            ]
        # Update states on existing keys and add new keys with base structure
        for deposit in new_deposits:
            idx = str(deposit.id)
            if idx in self.deposits.keys():
                if deposit.status.value != self.deposits[idx]["status"]:
                    self.deposits[idx]["status"] = deposit.status
            else:
                self.deposits[idx] = {
                    "status": deposit.status.value,
                    "amounts": {
                        "original_amount": repr(deposit.amount),
                        "converted_amount": repr(Money(0, self.from_currency)),
                        "converted_value": repr(Money(0, self.to_currency)),
                    },
                    "orders": [],
                    "pending_withdrawal": self.to_withdraw,
                }
            self.store.set(self.from_currency + "_deposits", self.deposits)

    def process_conversions(self):
        for deposit in self.deposits.values():
            # Calculate remaining amount to convert
            original_amount = Money.loads(deposit["amounts"]["original_amount"])
            converted_amount = Money.loads(deposit["amounts"]["converted_amount"])
            converted_value = Money.loads(deposit["amounts"]["converted_value"])
            remaining = original_amount - converted_amount
            if (
                self.side == Side.BUY
            ):  # Change remaining amount to base currency for order creation purposes
                remaining = (
                    self.buda.fetch_order_book().quote(self.side, remaining).base_amount
                )
            if (
                deposit["status"] == TxStatus.OK.value
                and remaining > self.buda.min_order_amount
            ):
                remaining = truncate_money(remaining)
                # Convert remaining amount using market order
                order = self.buda.place_market_order(self.side, remaining)
                # Wait for traded state to set updated values
                if order:
                    self.log.info(
                        f"{self.side} market order placed, waiting for traded state"
                    )
                    while order.status != OrderStatus.CLOSED:
                        order = self.buda.fetch_order(order.id)
                        maya.time.sleep(1)
                    self.log.info(f"{self.side} order traded, updating store values")
                    if self.side == Side.BUY:
                        converted_amount += order.cost
                        converted_value += order.filled - order.fee
                    if self.side == Side.SELL:
                        converted_amount += order.filled
                        converted_value += order.cost - order.fee
                    deposit["orders"].append(
                        order.id
                    )  # Save related orders for debugging
                # Save new values __str__
                deposit["amounts"]["converted_amount"] = repr(converted_amount)
                deposit["amounts"]["converted_value"] = repr(converted_value)
        # Store all deposits
        self.store.set(self.from_currency + "_deposits", self.deposits)

    def process_withdrawals(self):
        # Set wallet from relevant currency according to side
        to_wallet = (
            self.buda.wallets.base if self.side == Side.BUY else self.buda.wallets.quote
        )
        for deposit in self.deposits.values():
            # Load money amounts
            original_amount = Money.loads(deposit["amounts"]["original_amount"])
            converted_amount = Money.loads(deposit["amounts"]["converted_amount"])
            converted_value = Money.loads(deposit["amounts"]["converted_value"])
            remaining = original_amount - converted_amount
            if (
                self.side == Side.BUY
            ):  # Change remaining amount to base currency for minimum order amount check
                remaining = (
                    self.buda.fetch_order_book().quote(self.side, remaining).base_amount
                )
            # Filter deposits already converted and pending withdrawal
            original_amount_is_converted = remaining < self.buda.min_order_amount
            if (
                deposit["status"] == TxStatus.OK.value
                and deposit["pending_withdrawal"]
                and original_amount_is_converted
            ):
                withdrawal_amount = truncate_money(converted_value)
                available = to_wallet.fetch_balance().free
                if (
                    withdrawal_amount <= available
                ):  # We cannot withdraw more than available balance
                    w = to_wallet.request_withdrawal(
                        withdrawal_amount, self.to_address, subtract_fee=True
                    )
                    if (
                        w.status == TxStatus.PENDING
                    ):  # Check state to set and store updated values
                        self.log.info(
                            f"{self.to_currency} withdrawal request received, updating store values"
                        )
                        deposit["pending_withdrawal"] = False
                        self.store.set(self.from_currency + "_deposits", self.deposits)
                    else:
                        self.log.warning("Withdrawal failed")
                else:
                    self.log.warning(
                        f"Available balance not enough for withdrawal amount {withdrawal_amount}"
                    )

    def _get_market(self, from_currency, to_currency):
        buda_markets = BudaPublic().markets
        bases = [market.base for market in buda_markets]
        quotes = [market.quote for market in buda_markets]

        if from_currency in bases and to_currency in quotes:
            market = Market(from_currency, to_currency)
        elif from_currency in quotes and to_currency in bases:
            market = Market(to_currency, from_currency)
        else:
            raise NotImplementedError(f"No compatible market found!")
        return market