Beispiel #1
0
    def _get_fee(self,
                 base_currency: str,
                 quote_currency: str,
                 order_type: OrderType,
                 order_side: TradeType,
                 amount: Decimal,
                 price: Decimal = s_decimal_NaN,
                 is_maker: Optional[bool] = None) -> AddedToCostTradeFee:

        is_maker = is_maker or (order_type is OrderType.LIMIT_MAKER)
        trading_pair = combine_to_hb_trading_pair(base=base_currency,
                                                  quote=quote_currency)
        if trading_pair in self._trading_fees:
            fees_data = self._trading_fees[trading_pair]
            fee_value = Decimal(
                fees_data["makerFeeRate"]) if is_maker else Decimal(
                    fees_data["takerFeeRate"])
            fee = AddedToCostTradeFee(percent=fee_value)
        else:
            fee = build_trade_fee(
                self.name,
                is_maker,
                base_currency=base_currency,
                quote_currency=quote_currency,
                order_type=order_type,
                order_side=order_side,
                amount=amount,
                price=price,
            )
        return fee
Beispiel #2
0
 def get_fee(self,
             base_currency: str,
             quote_currency: str,
             order_type: OrderType,
             order_side: TradeType,
             amount: Decimal,
             price: Decimal = s_decimal_NaN,
             is_maker: Optional[bool] = None) -> TradeFeeBase:
     """
     Calculates the estimated fee an order would pay based on the connector configuration
     :param base_currency: the order base currency
     :param quote_currency: the order quote currency
     :param order_type: the type of order (MARKET, LIMIT, LIMIT_MAKER)
     :param order_side: if the order is for buying or selling
     :param amount: the order amount
     :param price: the order price
     :return: the estimated fee for the order
     """
     """
     To get trading fee, this function is simplified by using fee override configuration. Most parameters to this
     function are ignore except order_type. Use OrderType.LIMIT_MAKER to specify you want trading fee for
     maker order.
     """
     is_maker = order_type is OrderType.LIMIT_MAKER
     trade_base_fee = build_trade_fee(exchange=self.name,
                                      is_maker=is_maker,
                                      order_side=order_side,
                                      order_type=order_type,
                                      amount=amount,
                                      price=price,
                                      base_currency=base_currency,
                                      quote_currency=quote_currency)
     return trade_base_fee
    def _get_fee(self, exchange: 'ExchangeBase') -> TradeFeeBase:
        trading_pair = self.trading_pair
        price = self.price
        base, quote = split_hb_trading_pair(trading_pair)
        fee = build_trade_fee(
            exchange.name,
            self.is_maker,
            base,
            quote,
            self.order_type,
            self.order_side,
            self.amount,
            price,
        )

        return fee
Beispiel #4
0
 def _get_fee(self,
              base_currency: str,
              quote_currency: str,
              order_type: OrderType,
              order_side: TradeType,
              amount: Decimal,
              price: Decimal = s_decimal_NaN,
              is_maker: Optional[bool] = None) -> TradeFeeBase:
     """
     Calculates the estimated fee an order would pay based on the connector configuration
     :param base_currency: the order base currency
     :param quote_currency: the order quote currency
     :param order_type: the type of order (MARKET, LIMIT, LIMIT_MAKER)
     :param order_side: if the order is for buying or selling
     :param amount: the order amount
     :param price: the order price
     :param is_maker: if we take into account maker fee (True) or taker fee (None, False)
     :return: the estimated fee for the order
     """
     trading_pair = combine_to_hb_trading_pair(base=base_currency,
                                               quote=quote_currency)
     fee_schema = self._trading_fees.get(trading_pair, None)
     if fee_schema is None:
         self.logger().warning(
             f"For trading pair = {trading_pair} there is no fee schema loaded, using presets!"
         )
         fee = build_trade_fee(exchange=self.name,
                               is_maker=is_maker,
                               base_currency=base_currency,
                               quote_currency=quote_currency,
                               order_type=order_type,
                               order_side=order_side,
                               amount=amount,
                               price=price)
     else:
         if fee_schema.type == LatokenTakeType.PROPORTION or fee_schema.take == LatokenCommissionType.PERCENT:
             pass  # currently not implemented but is nice to have in next release(s)
         percent = fee_schema.maker_fee if order_type is OrderType.LIMIT_MAKER or (
             is_maker is not None and is_maker) else fee_schema.taker_fee
         fee = AddedToCostTradeFee(
             percent=percent
         ) if order_side == TradeType.BUY else DeductedFromReturnsTradeFee(
             percent=percent)
     return fee
    def get_fee(self,
                base_currency: str,
                quote_currency: str,
                order_type: OrderType,
                order_side: TradeType,
                amount: Decimal,
                price: Decimal = s_decimal_NaN,
                is_maker: Optional[bool] = None) -> AddedToCostTradeFee:
        """
        Calculates the fee to pay based on the fee information provided by the exchange for the account and the token pair.
        If exchange info is not available it calculates the estimated fee an order would pay based on the connector
            configuration

        :param base_currency: the order base currency
        :param quote_currency: the order quote currency
        :param order_type: the type of order (MARKET, LIMIT, LIMIT_MAKER)
        :param order_side: if the order is for buying or selling
        :param amount: the order amount
        :param price: the order price
        :param is_maker: True if the order is a maker order, False if it is a taker order

        :return: the calculated or estimated fee
        """

        is_maker = is_maker or (order_type is OrderType.LIMIT_MAKER)
        trading_pair = combine_to_hb_trading_pair(base=base_currency, quote=quote_currency)
        if trading_pair in self._trading_fees:
            fees_data = self._trading_fees[trading_pair]
            fee_value = Decimal(fees_data["makerFeeRate"]) if is_maker else Decimal(fees_data["takerFeeRate"])
            fee = AddedToCostTradeFee(percent=fee_value)
        else:
            fee = build_trade_fee(
                self.name,
                is_maker,
                base_currency=base_currency,
                quote_currency=quote_currency,
                order_type=order_type,
                order_side=order_side,
                amount=amount,
                price=price,
            )
        return fee
Beispiel #6
0
    def _get_fee(self,
                 base_currency: str,
                 quote_currency: str,
                 order_type: OrderType,
                 order_side: TradeType,
                 amount: Decimal,
                 price: Decimal = s_decimal_NaN,
                 is_maker: Optional[bool] = None) -> TradeFeeBase:

        is_maker = is_maker or (order_type is OrderType.LIMIT_MAKER)
        fee = build_trade_fee(
            self.name,
            is_maker,
            base_currency=base_currency,
            quote_currency=quote_currency,
            order_type=order_type,
            order_side=order_side,
            amount=amount,
            price=price,
        )
        return fee
Beispiel #7
0
    def profit_pct(
            self,
            rate_source: Optional[RateOracle] = None,
            account_for_fee: bool = False,
    ) -> Decimal:
        """
        Returns a profit in percentage value (e.g. 0.01 for 1% profitability)
        Assumes the base token is the same in both arbitrage sides
        """
        if not rate_source:
            rate_source = RateOracle.get_instance()

        buy_side: ArbProposalSide = self.first_side if self.first_side.is_buy else self.second_side
        sell_side: ArbProposalSide = self.first_side if not self.first_side.is_buy else self.second_side
        base_conversion_pair: str = f"{sell_side.market_info.base_asset}-{buy_side.market_info.base_asset}"
        quote_conversion_pair: str = f"{sell_side.market_info.quote_asset}-{buy_side.market_info.quote_asset}"

        sell_base_to_buy_base_rate: Decimal = Decimal(1)
        sell_quote_to_buy_quote_rate: Decimal = rate_source.rate(quote_conversion_pair)

        buy_fee_amount: Decimal = s_decimal_0
        sell_fee_amount: Decimal = s_decimal_0
        result: Decimal = s_decimal_0

        if sell_quote_to_buy_quote_rate and sell_base_to_buy_base_rate:
            if account_for_fee:
                buy_trade_fee: TradeFeeBase = build_trade_fee(
                    exchange=buy_side.market_info.market.name,
                    is_maker=False,
                    base_currency=buy_side.market_info.base_asset,
                    quote_currency=buy_side.market_info.quote_asset,
                    order_type=OrderType.MARKET,
                    order_side=TradeType.BUY,
                    amount=buy_side.amount,
                    price=buy_side.order_price,
                    extra_flat_fees=buy_side.extra_flat_fees
                )
                sell_trade_fee: TradeFeeBase = build_trade_fee(
                    exchange=sell_side.market_info.market.name,
                    is_maker=False,
                    base_currency=sell_side.market_info.base_asset,
                    quote_currency=sell_side.market_info.quote_asset,
                    order_type=OrderType.MARKET,
                    order_side=TradeType.SELL,
                    amount=sell_side.amount,
                    price=sell_side.order_price,
                    extra_flat_fees=sell_side.extra_flat_fees
                )
                buy_fee_amount: Decimal = buy_trade_fee.fee_amount_in_token(
                    trading_pair=buy_side.market_info.trading_pair,
                    price=buy_side.quote_price,
                    order_amount=buy_side.amount,
                    token=buy_side.market_info.quote_asset,
                    rate_source=rate_source
                )
                sell_fee_amount: Decimal = sell_trade_fee.fee_amount_in_token(
                    trading_pair=sell_side.market_info.trading_pair,
                    price=sell_side.quote_price,
                    order_amount=sell_side.amount,
                    token=sell_side.market_info.quote_asset,
                    rate_source=rate_source
                )

            buy_spent_net: Decimal = (buy_side.amount * buy_side.quote_price) + buy_fee_amount
            sell_gained_net: Decimal = (sell_side.amount * sell_side.quote_price) - sell_fee_amount
            sell_gained_net_in_buy_quote_currency: Decimal = (
                sell_gained_net * sell_quote_to_buy_quote_rate / sell_base_to_buy_base_rate
            )

            result: Decimal = (
                ((sell_gained_net_in_buy_quote_currency - buy_spent_net) / buy_spent_net)
                if buy_spent_net != s_decimal_0
                else s_decimal_0
            )
        else:
            self.logger().warning("The arbitrage proposal profitability could not be calculated due to a missing rate"
                                  f" ({base_conversion_pair}={sell_base_to_buy_base_rate},"
                                  f" {quote_conversion_pair}={sell_quote_to_buy_quote_rate})")
        return result
    def _update_inflight_order(self, tracked_order: BitmexInFlightOrder,
                               event: Dict[str, Any]):
        trading_pair_multiplier = self._trading_pair_to_multipliers[
            tracked_order.trading_pair]
        event["amount_remaining"] = Decimal(str(
            event["leavesQty"])) / trading_pair_multiplier.base_multiplier

        issuable_events: List[MarketEvent] = tracked_order.update(event)

        # Issue relevent events
        for (market_event, new_amount, new_price, new_fee) in issuable_events:
            base, quote = self.split_trading_pair(tracked_order.trading_pair)
            if market_event == MarketEvent.OrderFilled:
                self.trigger_event(
                    ORDER_FILLED_EVENT,
                    OrderFilledEvent(
                        self.current_timestamp, tracked_order.client_order_id,
                        tracked_order.trading_pair, tracked_order.trade_type,
                        tracked_order.order_type, new_price, new_amount,
                        build_trade_fee(self._domain, True, base, quote,
                                        tracked_order.order_type,
                                        tracked_order.trade_type, new_amount,
                                        new_price),
                        tracked_order.client_order_id))
            elif market_event == MarketEvent.OrderCancelled:
                self.logger().info(
                    f"Successfully cancelled order {tracked_order.client_order_id}"
                )
                self.stop_tracking_order(tracked_order.client_order_id)
                self.trigger_event(
                    ORDER_CANCELLED_EVENT,
                    OrderCancelledEvent(self.current_timestamp,
                                        tracked_order.client_order_id))
            elif market_event == MarketEvent.BuyOrderCompleted:
                self.logger().info(
                    f"The market buy order {tracked_order.client_order_id} has completed "
                    f"according to user stream.")
                self.trigger_event(
                    BUY_ORDER_COMPLETED_EVENT,
                    BuyOrderCompletedEvent(self.current_timestamp,
                                           tracked_order.client_order_id, base,
                                           quote,
                                           tracked_order.executed_amount_base,
                                           tracked_order.executed_amount_quote,
                                           tracked_order.order_type,
                                           tracked_order.exchange_order_id))
            elif market_event == MarketEvent.SellOrderCompleted:
                self.logger().info(
                    f"The market sell order {tracked_order.client_order_id} has completed "
                    f"according to user stream.")
                self.trigger_event(
                    SELL_ORDER_COMPLETED_EVENT,
                    SellOrderCompletedEvent(
                        self.current_timestamp, tracked_order.client_order_id,
                        base, quote, tracked_order.executed_amount_base,
                        tracked_order.executed_amount_quote,
                        tracked_order.order_type,
                        tracked_order.exchange_order_id))
            # Complete the order if relevent
            if tracked_order.is_done:
                self.stop_tracking_order(tracked_order.client_order_id)