Ejemplo n.º 1
0
    def create_order_candidates_for_budget_check(self, proposal: Proposal):
        order_candidates = []

        is_maker = True
        order_candidates.extend([
            PerpetualOrderCandidate(
                self.trading_pair,
                is_maker,
                OrderType.LIMIT,
                TradeType.BUY,
                buy.size,
                buy.price,
                leverage=Decimal(self._leverage),
            ) for buy in proposal.buys
        ])
        order_candidates.extend([
            PerpetualOrderCandidate(
                self.trading_pair,
                is_maker,
                OrderType.LIMIT,
                TradeType.SELL,
                sell.size,
                sell.price,
                leverage=Decimal(self._leverage),
            ) for sell in proposal.sells
        ])
        return order_candidates
Ejemplo n.º 2
0
    def test_populate_collateral_fields_buy_order_with_leverage(self):
        order_candidate = PerpetualOrderCandidate(
            trading_pair=self.trading_pair,
            is_maker=True,
            order_type=OrderType.LIMIT,
            order_side=TradeType.BUY,
            amount=Decimal("10"),
            price=Decimal("2"),
            leverage=Decimal("2"))
        populated_candidate = self.budget_checker.populate_collateral_entries(
            order_candidate)

        self.assertEqual(self.quote_asset,
                         populated_candidate.order_collateral.token)
        self.assertEqual(Decimal("10"),
                         populated_candidate.order_collateral.amount)
        self.assertEqual(self.quote_asset,
                         populated_candidate.percent_fee_collateral.token)
        self.assertEqual(Decimal("0.2"),
                         populated_candidate.percent_fee_collateral.amount)
        self.assertEqual(self.quote_asset,
                         populated_candidate.percent_fee_value.token)
        self.assertEqual(Decimal("0.2"),
                         populated_candidate.percent_fee_value.amount)
        self.assertEqual(0, len(populated_candidate.fixed_fee_collaterals))
        self.assertIsNone(populated_candidate.potential_returns
                          )  # order results in position open
Ejemplo n.º 3
0
    def test_adjust_candidate_sufficient_funds(self):
        self.exchange.set_balance(self.quote_asset, Decimal("100"))

        order_candidate = PerpetualOrderCandidate(
            trading_pair=self.trading_pair,
            is_maker=True,
            order_type=OrderType.LIMIT,
            order_side=TradeType.BUY,
            amount=Decimal("10"),
            price=Decimal("2"),
        )
        adjusted_candidate = self.budget_checker.adjust_candidate(
            order_candidate)

        self.assertEqual(Decimal("10"), adjusted_candidate.amount)
        self.assertEqual(self.quote_asset,
                         adjusted_candidate.order_collateral.token)
        self.assertEqual(Decimal("20"),
                         adjusted_candidate.order_collateral.amount)
        self.assertEqual(self.quote_asset,
                         adjusted_candidate.percent_fee_collateral.token)
        self.assertEqual(Decimal("0.2"),
                         adjusted_candidate.percent_fee_collateral.amount)
        self.assertEqual(self.quote_asset,
                         adjusted_candidate.percent_fee_value.token)
        self.assertEqual(Decimal("0.2"),
                         adjusted_candidate.percent_fee_value.amount)
        self.assertEqual(0, len(adjusted_candidate.fixed_fee_collaterals))
        self.assertIsNone(adjusted_candidate.potential_returns
                          )  # order results in position open
Ejemplo n.º 4
0
    def test_adjust_candidate_sell_insufficient_funds_partial_adjustment_allowed(self):
        q_params = QuantizationParams(
            trading_pair=self.trading_pair,
            price_precision=8,
            price_decimals=2,
            order_size_precision=8,
            order_size_decimals=2,
        )
        self.exchange.set_quantization_param(q_params)
        self.exchange.set_balance(self.quote_asset, Decimal("10"))

        order_candidate = PerpetualOrderCandidate(
            trading_pair=self.trading_pair,
            is_maker=True,
            order_type=OrderType.LIMIT,
            order_side=TradeType.SELL,
            amount=Decimal("10"),
            price=Decimal("2"),
        )
        adjusted_candidate = self.budget_checker.adjust_candidate(order_candidate, all_or_none=False)

        self.assertEqual(Decimal("4.95"), adjusted_candidate.amount)  # 5 * .99
        self.assertEqual(self.quote_asset, adjusted_candidate.order_collateral.token)
        self.assertEqual(Decimal("9.9"), adjusted_candidate.order_collateral.amount)  # 4.95 * 2
        self.assertEqual(self.quote_asset, adjusted_candidate.percent_fee_collateral.token)
        self.assertEqual(Decimal("0.099"), adjusted_candidate.percent_fee_collateral.amount)  # 9.9 * 0.01
        self.assertEqual(self.quote_asset, adjusted_candidate.percent_fee_value.token)
        self.assertEqual(Decimal("0.099"), adjusted_candidate.percent_fee_value.amount)  # 9.9 * 0.01
        self.assertEqual(0, len(adjusted_candidate.fixed_fee_collaterals))
        self.assertIsNone(adjusted_candidate.potential_returns)  # order results in position open
    def test_populate_collateral_fields_percent_fees_in_third_token(self):
        pfc_token = "PFC"
        trade_fee_schema = TradeFeeSchema(
            percent_fee_token=pfc_token,
            maker_percent_fee_decimal=Decimal("0.01"),
            taker_percent_fee_decimal=Decimal("0.01"),
        )
        exchange = MockPerpConnector(client_config_map=ClientConfigAdapter(
            ClientConfigMap()),
                                     trade_fee_schema=trade_fee_schema)
        pfc_quote_pair = combine_to_hb_trading_pair(self.quote_asset,
                                                    pfc_token)
        exchange.set_balanced_order_book(  # the quote to pfc price will be 1:2
            trading_pair=pfc_quote_pair,
            mid_price=1.5,
            min_price=1,
            max_price=2,
            price_step_size=1,
            volume_step_size=1,
        )
        budget_checker: PerpetualBudgetChecker = exchange.budget_checker

        order_candidate = PerpetualOrderCandidate(
            trading_pair=self.trading_pair,
            is_maker=True,
            order_type=OrderType.LIMIT,
            order_side=TradeType.BUY,
            amount=Decimal("10"),
            price=Decimal("2"),
            leverage=Decimal("2"),
        )
        populated_candidate = budget_checker.populate_collateral_entries(
            order_candidate)

        self.assertEqual(self.quote_asset,
                         populated_candidate.order_collateral.token)
        self.assertEqual(Decimal("10"),
                         populated_candidate.order_collateral.amount)
        self.assertEqual(pfc_token,
                         populated_candidate.percent_fee_collateral.token)
        self.assertEqual(Decimal("0.4"),
                         populated_candidate.percent_fee_collateral.amount)
        self.assertEqual(pfc_token,
                         populated_candidate.percent_fee_value.token)
        self.assertEqual(Decimal("0.4"),
                         populated_candidate.percent_fee_value.amount)
        self.assertEqual(0, len(populated_candidate.fixed_fee_collaterals))
        self.assertIsNone(populated_candidate.potential_returns
                          )  # order results in position open
Ejemplo n.º 6
0
    def check_perpetual_budget_constraint(self, proposal: ArbProposal) -> bool:
        """
        Check balance on spot exchange.
        :param proposal: An arbitrage proposal
        :return: True if user has available balance enough for both orders submission.
        """
        proposal_side = proposal.perp_side
        order_amount = proposal.order_amount
        market_info = proposal_side.market_info
        budget_checker = market_info.market.budget_checker

        position_close = False
        if self.perp_positions and abs(
                self.perp_positions[0].amount) == order_amount:
            perp_side = proposal.perp_side
            cur_perp_pos_is_buy = True if self.perp_positions[
                0].amount > 0 else False
            if perp_side != cur_perp_pos_is_buy:
                position_close = True

        order_candidate = PerpetualOrderCandidate(
            trading_pair=market_info.trading_pair,
            is_maker=False,
            order_type=OrderType.LIMIT,
            order_side=TradeType.BUY
            if proposal_side.is_buy else TradeType.SELL,
            amount=order_amount,
            price=proposal_side.order_price,
            leverage=Decimal(self._perp_leverage),
            position_close=position_close,
        )

        adjusted_candidate_order = budget_checker.adjust_candidate(
            order_candidate, all_or_none=True)

        if adjusted_candidate_order.amount < order_amount:
            self.logger().info(
                f"Cannot arbitrage, {proposal_side.market_info.market.display_name} balance"
                f" is insufficient to place the order candidate {order_candidate}."
            )
            return False

        return True
Ejemplo n.º 7
0
    def test_populate_collateral_for_position_close(self):
        order_candidate = PerpetualOrderCandidate(
            trading_pair=self.trading_pair,
            is_maker=True,
            order_type=OrderType.LIMIT,
            order_side=TradeType.SELL,
            amount=Decimal("10"),
            price=Decimal("2"),
            leverage=Decimal("2"),
            position_close=True,
        )
        populated_candidate = self.budget_checker.populate_collateral_entries(order_candidate)

        self.assertIsNone(populated_candidate.order_collateral)  # the collateral is the contract itself
        self.assertIsNone(populated_candidate.percent_fee_collateral)
        self.assertIsNone(populated_candidate.percent_fee_value)
        self.assertEqual(0, len(populated_candidate.fixed_fee_collaterals))
        self.assertEqual(self.quote_asset, populated_candidate.potential_returns.token)
        self.assertEqual(Decimal("19.8"), populated_candidate.potential_returns.amount)