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
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
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
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
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
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)