def test_with_adjust_orders_enabled(self): self.clock.remove_iterator(self.strategy) self.clock.remove_iterator(self.maker_market) self.maker_market: BacktestMarket = BacktestMarket() self.maker_data: MockOrderBookLoader = MockOrderBookLoader(*self.maker_trading_pairs) self.maker_data.set_balanced_order_book(1.0, 0.5, 1.5, 0.1, 10) self.maker_market.add_data(self.maker_data) self.market_pair: CrossExchangeMarketPair = CrossExchangeMarketPair( MarketTradingPairTuple(self.maker_market, *self.maker_trading_pairs), MarketTradingPairTuple(self.taker_market, *self.taker_trading_pairs), ) self.strategy: CrossExchangeMarketMakingStrategy = CrossExchangeMarketMakingStrategy( [self.market_pair], order_size_portfolio_ratio_limit=Decimal("0.3"), min_profitability=Decimal("0.005"), logging_options=self.logging_options, ) self.maker_market.set_balance("COINALPHA", 5) self.maker_market.set_balance("WETH", 5) self.maker_market.set_balance("QETH", 5) self.maker_market.set_quantization_param(QuantizationParams(self.maker_trading_pairs[0], 4, 4, 4, 4)) self.clock.add_iterator(self.strategy) self.clock.add_iterator(self.maker_market) self.clock.backtest_til(self.start_timestamp + 5) self.assertEqual(1, len(self.strategy.active_bids)) self.assertEqual(1, len(self.strategy.active_asks)) bid_order: LimitOrder = self.strategy.active_bids[0][1] ask_order: LimitOrder = self.strategy.active_asks[0][1] # place above top bid (at 0.95) self.assertAlmostEqual(Decimal("0.9501"), bid_order.price) # place below top ask (at 1.05) self.assertAlmostEqual(Decimal("1.049"), ask_order.price) self.assertAlmostEqual(Decimal("3"), round(bid_order.quantity, 4)) self.assertAlmostEqual(Decimal("3"), round(ask_order.quantity, 4))
def test_empty_maker_orderbook(self): self.clock.remove_iterator(self.strategy) self.clock.remove_iterator(self.maker_market) self.maker_market: MockPaperExchange = MockPaperExchange() # Orderbook is empty self.maker_market.new_empty_order_book(self.maker_trading_pairs[0]) self.market_pair: CrossExchangeMarketPair = CrossExchangeMarketPair( MarketTradingPairTuple(self.maker_market, *self.maker_trading_pairs), MarketTradingPairTuple(self.taker_market, *self.taker_trading_pairs), ) self.strategy: CrossExchangeMarketMakingStrategy = CrossExchangeMarketMakingStrategy() self.strategy.init_params( [self.market_pair], order_amount=1, min_profitability=Decimal("0.005"), logging_options=self.logging_options, adjust_order_enabled=False ) self.maker_market.set_balance("COINALPHA", 5) self.maker_market.set_balance("WETH", 5) self.maker_market.set_balance("QETH", 5) self.maker_market.set_quantization_param(QuantizationParams(self.maker_trading_pairs[0], 4, 4, 4, 4)) self.clock.add_iterator(self.strategy) self.clock.add_iterator(self.maker_market) self.clock.backtest_til(self.start_timestamp + 5) self.assertEqual(1, len(self.strategy.active_bids)) self.assertEqual(1, len(self.strategy.active_asks)) bid_order: LimitOrder = self.strategy.active_bids[0][1] ask_order: LimitOrder = self.strategy.active_asks[0][1] # Places orders based on taker orderbook self.assertEqual(Decimal("0.9945"), bid_order.price) self.assertEqual(Decimal("1.006"), ask_order.price) self.assertAlmostEqual(Decimal("1"), round(bid_order.quantity, 4)) self.assertAlmostEqual(Decimal("1"), round(ask_order.quantity, 4))
def setUp(self): self.clock_tick_size = 1 self.clock: Clock = Clock(ClockMode.BACKTEST, self.clock_tick_size, self.start_timestamp, self.end_timestamp) self.market: BacktestMarket = BacktestMarket() self.book_data: MockOrderBookLoader = MockOrderBookLoader( self.trading_pair, self.base_asset, self.quote_asset) self.mid_price = 100 self.bid_spread = 0.01 self.ask_spread = 0.01 self.order_refresh_time = 30 self.book_data.set_balanced_order_book(mid_price=self.mid_price, min_price=1, max_price=200, price_step_size=1, volume_step_size=10) self.market.add_data(self.book_data) self.market.set_balance("HBOT", 500) self.market.set_balance("ETH", 5000) self.market.set_quantization_param( QuantizationParams(self.trading_pair, 6, 6, 6, 6)) self.market_info = MarketTradingPairTuple(self.market, self.trading_pair, self.base_asset, self.quote_asset) self.clock.add_iterator(self.market) self.order_fill_logger: EventLogger = EventLogger() self.cancel_order_logger: EventLogger = EventLogger() self.market.add_listener(MarketEvent.OrderFilled, self.order_fill_logger) self.market.add_listener(MarketEvent.OrderCancelled, self.cancel_order_logger) self.ext_market: BacktestMarket = BacktestMarket() self.ext_data: MockOrderBookLoader = MockOrderBookLoader( self.trading_pair, self.base_asset, self.quote_asset) self.ext_market_info: MarketTradingPairTuple = MarketTradingPairTuple( self.ext_market, self.trading_pair, self.base_asset, self.quote_asset) self.ext_data.set_balanced_order_book(mid_price=100, min_price=1, max_price=400, price_step_size=1, volume_step_size=100) self.ext_market.add_data(self.ext_data) self.order_book_asset_del = OrderBookAssetPriceDelegate( self.ext_market, self.trading_pair) self.one_level_strategy = PureMarketMakingStrategy() self.one_level_strategy.init_params( self.market_info, bid_spread=Decimal("0.01"), ask_spread=Decimal("0.01"), order_amount=Decimal("1"), order_refresh_time=3.0, filled_order_delay=3.0, order_refresh_tolerance_pct=-1, minimum_spread=-1, asset_price_delegate=self.order_book_asset_del, take_if_crossed=True)
async def _test_create_arb_proposals(self): market_info1 = MarketTradingPairTuple( MockConnector1( client_config_map=ClientConfigAdapter(ClientConfigMap())), trading_pair, base, quote) market_info2 = MarketTradingPairTuple( MockConnector2( client_config_map=ClientConfigAdapter(ClientConfigMap())), trading_pair, base, quote) arb_proposals = await utils.create_arb_proposals( market_info1, market_info2, [], [], Decimal("1")) # there are 2 proposal combination possible - (buy_1, sell_2) and (buy_2, sell_1) self.assertEqual(2, len(arb_proposals)) # Each proposal has a buy and a sell proposal sides self.assertNotEqual(arb_proposals[0].first_side.is_buy, arb_proposals[0].second_side.is_buy) self.assertNotEqual(arb_proposals[1].first_side.is_buy, arb_proposals[1].second_side.is_buy) buy_1_sell_2_profit_pct = (Decimal("100") - Decimal("105")) / Decimal("105") self.assertEqual(buy_1_sell_2_profit_pct, arb_proposals[0].profit_pct()) buy_2_sell_1_profit_pct = (Decimal("104") - Decimal("103")) / Decimal("103") self.assertEqual(buy_2_sell_1_profit_pct, arb_proposals[1].profit_pct())
def test_with_adjust_orders_disabled(self): self.clock.remove_iterator(self.strategy) self.clock.remove_iterator(self.maker_market) self.maker_market: MockPaperExchange = MockPaperExchange() self.maker_market.set_balanced_order_book(self.maker_trading_pairs[0], 1.0, 0.5, 1.5, 0.1, 10) self.taker_market.set_balanced_order_book(self.taker_trading_pairs[0], 1.0, 0.5, 1.5, 0.001, 20) self.market_pair: CrossExchangeMarketPair = CrossExchangeMarketPair( MarketTradingPairTuple(self.maker_market, *self.maker_trading_pairs), MarketTradingPairTuple(self.taker_market, *self.taker_trading_pairs), ) self.strategy: CrossExchangeMarketMakingStrategy = CrossExchangeMarketMakingStrategy() self.strategy.init_params( [self.market_pair], order_size_portfolio_ratio_limit=Decimal("0.3"), min_profitability=Decimal("0.005"), logging_options=self.logging_options, adjust_order_enabled=False ) self.maker_market.set_balance("COINALPHA", 5) self.maker_market.set_balance("WETH", 5) self.maker_market.set_balance("QETH", 5) self.maker_market.set_quantization_param(QuantizationParams(self.maker_trading_pairs[0], 4, 4, 4, 4)) self.clock.add_iterator(self.strategy) self.clock.add_iterator(self.maker_market) self.clock.backtest_til(self.start_timestamp + 5) self.assertEqual(1, len(self.strategy.active_bids)) self.assertEqual(1, len(self.strategy.active_asks)) bid_order: LimitOrder = self.strategy.active_bids[0][1] ask_order: LimitOrder = self.strategy.active_asks[0][1] self.assertEqual(Decimal("0.9945"), bid_order.price) self.assertEqual(Decimal("1.006"), ask_order.price) self.assertAlmostEqual(Decimal("3"), round(bid_order.quantity, 4)) self.assertAlmostEqual(Decimal("3"), round(ask_order.quantity, 4))
def test_profit_is_zero_when_no_available_sell_to_buy_quote_rate(self): buy_market_info = MarketTradingPairTuple(self.buy_market, "BTC-USDT", "BTC", "USDT") sell_market_info = MarketTradingPairTuple(self.sell_market, "BTC-DAI", "BTC", "DAI") buy_side = ArbProposalSide( buy_market_info, True, Decimal(30000), Decimal(30000), Decimal(10), [] ) sell_side = ArbProposalSide( sell_market_info, False, Decimal(32000), Decimal(32000), Decimal(10), [] ) proposal = ArbProposal(buy_side, sell_side) proposal.logger().setLevel(1) proposal.logger().addHandler(self) self.assertEqual(proposal.profit_pct(), Decimal(0)) self.assertTrue(self._is_logged('WARNING', ("The arbitrage proposal profitability could not be calculated due to" " a missing rate (BTC-BTC=1, DAI-USDT=None)")))
def test_arb_proposal(self): spot_connector = MagicMock() spot_connector.display_name = "Binance" spot_market_info = MarketTradingPairTuple(spot_connector, self.trading_pair, self.base_token, self.quote_token) perp_connector = MagicMock() perp_connector.display_name = "Binance Perpetual" perp_market_info = MarketTradingPairTuple(perp_connector, self.trading_pair, self.base_token, self.quote_token) spot_side = ArbProposalSide(spot_market_info, True, Decimal(100)) perp_side = ArbProposalSide(perp_market_info, False, Decimal(110)) proposal = ArbProposal(spot_side, perp_side, Decimal("1")) self.assertEqual(Decimal("0.1"), proposal.profit_pct()) expected_str = "Spot: Binance: Buy BTC at 100 USDT.\n" \ "Perpetual: Binance perpetual: Sell BTC at 110 USDT.\n" \ "Order amount: 1\n" \ "Profit: 10.00%" self.assertEqual(expected_str, str(proposal)) perp_side = ArbProposalSide(perp_market_info, True, Decimal(110)) with self.assertRaises(Exception) as context: proposal = ArbProposal(spot_side, perp_side, Decimal("1")) self.assertEqual( 'Spot and perpetual arb proposal cannot be on the same side.', str(context.exception))
def test_with_conversion(self): self.clock.remove_iterator(self.strategy) self.market_pair: CrossExchangeMarketPair = CrossExchangeMarketPair( MarketTradingPairTuple(self.maker_market, *["COINALPHA-QETH", "COINALPHA", "QETH"]), MarketTradingPairTuple(self.taker_market, *self.taker_trading_pairs), ) self.maker_data: MockOrderBookLoader = MockOrderBookLoader( "COINALPHA-QETH", "COINALPHA", "QETH") self.maker_data.set_balanced_order_book(1.05, 0.55, 1.55, 0.01, 10) self.maker_market.add_data(self.maker_data) self.strategy: CrossExchangeMarketMakingStrategy = CrossExchangeMarketMakingStrategy( [self.market_pair], Decimal("0.01"), order_size_portfolio_ratio_limit=Decimal("0.3"), logging_options=self.logging_options) self.clock.add_iterator(self.strategy) self.clock.backtest_til(self.start_timestamp + 5) self.assertEqual(1, len(self.strategy.active_bids)) self.assertEqual(1, len(self.strategy.active_asks)) bid_order: LimitOrder = self.strategy.active_bids[0][1] ask_order: LimitOrder = self.strategy.active_asks[0][1] self.assertAlmostEqual(Decimal("1.0417"), round(bid_order.price, 4)) self.assertAlmostEqual(Decimal("1.0637"), round(ask_order.price, 4)) self.assertAlmostEqual(Decimal("2.9286"), round(bid_order.quantity, 4)) self.assertAlmostEqual(Decimal("2.9286"), round(ask_order.quantity, 4))
def setUp(self): self.amm_1: MockAMM = MockAMM("onion") self.amm_1.set_balance(base_asset, 500) self.amm_1.set_balance(quote_asset, 500) self.market_info_1 = MarketTradingPairTuple(self.amm_1, trading_pair, base_asset, quote_asset) self.amm_2: MockAMM = MockAMM("garlic") self.amm_2.set_balance(base_asset, 500) self.amm_2.set_balance(quote_asset, 500) self.market_info_2 = MarketTradingPairTuple(self.amm_2, trading_pair, base_asset, quote_asset) self.strategy = AmmArbStrategy( self.market_info_1, self.market_info_2, min_profitability=Decimal("0.01"), order_amount=Decimal("1"), market_1_slippage_buffer=Decimal("0.001"), market_2_slippage_buffer=Decimal("0.002"), ) self.clock.add_iterator(self.amm_1) self.clock.add_iterator(self.amm_2) self.clock.add_iterator(self.strategy) self.market_order_fill_logger: EventLogger = EventLogger() self.amm_1.add_listener(MarketEvent.OrderFilled, self.market_order_fill_logger) self.amm_2.add_listener(MarketEvent.OrderFilled, self.market_order_fill_logger)
def test_with_conversion(self): self.clock.remove_iterator(self.strategy) self.market_pair: CrossExchangeMarketPair = CrossExchangeMarketPair( MarketTradingPairTuple(self.maker_market, *["COINALPHA-QETH", "COINALPHA", "QETH"]), MarketTradingPairTuple(self.taker_market, *self.trading_pairs_taker), ) self.maker_market.set_balanced_order_book("COINALPHA-QETH", 1.05, 0.55, 1.55, 0.01, 10) config_map_raw = deepcopy(self.config_map_raw) config_map_raw.min_profitability = Decimal("1") config_map_raw.order_size_portfolio_ratio_limit = Decimal("30") config_map_raw.conversion_rate_mode.taker_to_maker_base_conversion_rate = Decimal( "0.95") config_map = ClientConfigAdapter(config_map_raw) self.strategy: CrossExchangeMarketMakingStrategy = CrossExchangeMarketMakingStrategy( ) self.strategy.init_params( config_map=config_map, market_pairs=[self.market_pair], logging_options=self.logging_options, ) self.clock.add_iterator(self.strategy) self.clock.backtest_til(self.start_timestamp + 5) self.assertEqual(1, len(self.strategy.active_bids)) self.assertEqual(1, len(self.strategy.active_asks)) bid_order: LimitOrder = self.strategy.active_bids[0][1] ask_order: LimitOrder = self.strategy.active_asks[0][1] self.assertAlmostEqual(Decimal("1.0417"), round(bid_order.price, 4)) self.assertAlmostEqual(Decimal("1.0636"), round(ask_order.price, 4)) self.assertAlmostEqual(Decimal("2.9286"), round(bid_order.quantity, 4)) self.assertAlmostEqual(Decimal("2.9286"), round(ask_order.quantity, 4))
def test_profit_without_fees_for_different_quotes_trading_pairs(self): buy_market = MagicMock() buy_market_info = MarketTradingPairTuple(buy_market, "BTC-USDT", "BTC", "USDT") sell_market = MagicMock() sell_market_info = MarketTradingPairTuple(sell_market, "BTC-ETH", "BTC", "ETH") buy_side = ArbProposalSide(buy_market_info, True, Decimal(30000), Decimal(30000), Decimal(10)) sell_side = ArbProposalSide(sell_market_info, False, Decimal(10), Decimal(10), Decimal(10)) proposal = ArbProposal(buy_side, sell_side) rate_source = FixedRateSource() rate_source.add_rate("BTC-USDT", Decimal(30000)) rate_source.add_rate("BTC-ETH", Decimal(10)) rate_source.add_rate("ETH-USDT", Decimal(3000)) expected_sell_result = sell_side.amount * sell_side.quote_price sell_quote_to_buy_quote_rate = rate_source.rate("ETH-USDT") adjusted_sell_result = expected_sell_result * sell_quote_to_buy_quote_rate expected_buy_result = buy_side.amount * buy_side.quote_price expected_profit_pct = (adjusted_sell_result - expected_buy_result) / expected_buy_result profit = proposal.profit_pct(account_for_fee=False, rate_source=rate_source) self.assertEqual(profit, expected_profit_pct)
def start(self): try: order_amount = dev_5_vwap_config_map.get("order_amount").value order_type = dev_5_vwap_config_map.get("order_type").value is_buy = dev_5_vwap_config_map.get("is_buy").value time_delay = dev_5_vwap_config_map.get("time_delay").value is_vwap = dev_5_vwap_config_map.get("is_vwap").value num_individual_orders = dev_5_vwap_config_map.get( "num_individual_orders").value percent_slippage = dev_5_vwap_config_map.get("percent_slippage").value order_percent_of_volume = dev_5_vwap_config_map.get( "order_percent_of_volume").value market = dev_5_vwap_config_map.get("market").value.lower() raw_market_symbol = dev_5_vwap_config_map.get( "market_trading_pair_tuple").value order_price = None cancel_order_wait_time = None if order_type == "limit": order_price = dev_5_vwap_config_map.get("order_price").value cancel_order_wait_time = dev_5_vwap_config_map.get( "cancel_order_wait_time").value try: assets: Tuple[str, str] = self._initialize_market_assets( market, [raw_market_symbol])[0] except ValueError as e: self._notify(str(e)) return market_names: List[Tuple[str, List[str]]] = [(market, [raw_market_symbol])] self._initialize_wallet(token_symbols=list(set(assets))) self._initialize_markets(market_names) self.assets = set(assets) maker_data = [self.markets[market], raw_market_symbol] + list(assets) self.market_trading_pair_tuples = [MarketTradingPairTuple(*maker_data)] strategy_logging_options = Dev5TwapTradeStrategy.OPTION_LOG_ALL self.strategy = Dev5TwapTradeStrategy( market_infos=[MarketTradingPairTuple(*maker_data)], order_type=order_type, order_price=order_price, cancel_order_wait_time=cancel_order_wait_time, is_buy=is_buy, time_delay=time_delay, is_vwap=is_vwap, num_individual_orders=num_individual_orders, percent_slippage=percent_slippage, order_percent_of_volume=order_percent_of_volume, order_amount=order_amount, logging_options=strategy_logging_options) except Exception as e: self._notify(str(e)) self.logger().error("Unknown error during initialization.", exc_info=True)
def setUp(self): self.clock: Clock = Clock(ClockMode.BACKTEST, 1.0, self.start_timestamp, self.end_timestamp) self.min_profitbality = Decimal("0.005") self.maker_market: MockPaperExchange = MockPaperExchange() self.taker_market: MockPaperExchange = MockPaperExchange() self.maker_market.set_balanced_order_book(self.maker_trading_pairs[0], 1.0, 0.5, 1.5, 0.01, 10) self.taker_market.set_balanced_order_book(self.taker_trading_pairs[0], 1.0, 0.5, 1.5, 0.001, 4) self.maker_market.set_balance("COINALPHA", 5) self.maker_market.set_balance("WETH", 5) self.maker_market.set_balance("QETH", 5) self.taker_market.set_balance("COINALPHA", 5) self.taker_market.set_balance("ETH", 5) self.maker_market.set_quantization_param(QuantizationParams(self.maker_trading_pairs[0], 5, 5, 5, 5)) self.taker_market.set_quantization_param(QuantizationParams(self.taker_trading_pairs[0], 5, 5, 5, 5)) self.market_pair: CrossExchangeMarketPair = CrossExchangeMarketPair( MarketTradingPairTuple(self.maker_market, *self.maker_trading_pairs), MarketTradingPairTuple(self.taker_market, *self.taker_trading_pairs), ) logging_options: int = ( CrossExchangeMarketMakingStrategy.OPTION_LOG_ALL & (~CrossExchangeMarketMakingStrategy.OPTION_LOG_NULL_ORDER_SIZE) ) self.strategy: CrossExchangeMarketMakingStrategy = CrossExchangeMarketMakingStrategy() self.strategy.init_params( [self.market_pair], order_size_portfolio_ratio_limit=Decimal("0.3"), min_profitability=Decimal(self.min_profitbality), logging_options=logging_options, slippage_buffer=Decimal("0"), ) self.strategy_with_top_depth_tolerance: CrossExchangeMarketMakingStrategy = CrossExchangeMarketMakingStrategy() self.strategy_with_top_depth_tolerance.init_params( [self.market_pair], order_size_portfolio_ratio_limit=Decimal("0.3"), min_profitability=Decimal(self.min_profitbality), logging_options=logging_options, top_depth_tolerance=1, slippage_buffer=Decimal("0"), ) self.logging_options = logging_options self.clock.add_iterator(self.maker_market) self.clock.add_iterator(self.taker_market) self.clock.add_iterator(self.strategy) self.maker_order_fill_logger: EventLogger = EventLogger() self.taker_order_fill_logger: EventLogger = EventLogger() self.cancel_order_logger: EventLogger = EventLogger() self.maker_order_created_logger: EventLogger = EventLogger() self.taker_order_created_logger: EventLogger = EventLogger() self.maker_market.add_listener(MarketEvent.OrderFilled, self.maker_order_fill_logger) self.taker_market.add_listener(MarketEvent.OrderFilled, self.taker_order_fill_logger) self.maker_market.add_listener(MarketEvent.OrderCancelled, self.cancel_order_logger) self.maker_market.add_listener(MarketEvent.BuyOrderCreated, self.maker_order_created_logger) self.maker_market.add_listener(MarketEvent.SellOrderCreated, self.maker_order_created_logger) self.taker_market.add_listener(MarketEvent.BuyOrderCreated, self.taker_order_created_logger) self.taker_market.add_listener(MarketEvent.SellOrderCreated, self.taker_order_created_logger)
def setUp(self): self.clock: Clock = Clock(ClockMode.BACKTEST, 1.0, self.start_timestamp, self.end_timestamp) self.min_profitbality = 0.005 self.maker_market: BacktestMarket = BacktestMarket() self.taker_market: BacktestMarket = BacktestMarket() self.maker_data: MockOrderBookLoader = MockOrderBookLoader( *self.maker_symbols) self.taker_data: MockOrderBookLoader = MockOrderBookLoader( *self.taker_symbols) self.maker_data.set_balanced_order_book(1.0, 0.5, 1.5, 0.01, 10) self.taker_data.set_balanced_order_book(1.0, 0.5, 1.5, 0.001, 4) self.maker_market.add_data(self.maker_data) self.taker_market.add_data(self.taker_data) self.maker_market.set_balance("COINALPHA", 5) self.maker_market.set_balance("WETH", 5) self.maker_market.set_balance("QETH", 5) self.taker_market.set_balance("COINALPHA", 5) self.taker_market.set_balance("ETH", 5) self.maker_market.set_quantization_param( QuantizationParams(self.maker_symbols[0], 5, 5, 5, 5)) self.taker_market.set_quantization_param( QuantizationParams(self.taker_symbols[0], 5, 5, 5, 5)) self.market_pair: CrossExchangeMarketPair = CrossExchangeMarketPair( MarketTradingPairTuple(self.maker_market, *self.maker_symbols), MarketTradingPairTuple(self.taker_market, *self.taker_symbols), ) logging_options: int = ( CrossExchangeMarketMakingStrategy.OPTION_LOG_ALL & (~CrossExchangeMarketMakingStrategy.OPTION_LOG_NULL_ORDER_SIZE)) self.strategy: CrossExchangeMarketMakingStrategy = CrossExchangeMarketMakingStrategy( [self.market_pair], order_size_portfolio_ratio_limit=0.3, min_profitability=self.min_profitbality, logging_options=logging_options, ) self.strategy_with_top_depth_tolerance: CrossExchangeMarketMakingStrategy = CrossExchangeMarketMakingStrategy( [self.market_pair], order_size_portfolio_ratio_limit=0.3, min_profitability=self.min_profitbality, logging_options=logging_options, top_depth_tolerance=1) self.logging_options = logging_options self.clock.add_iterator(self.maker_market) self.clock.add_iterator(self.taker_market) self.clock.add_iterator(self.strategy) self.maker_order_fill_logger: EventLogger = EventLogger() self.taker_order_fill_logger: EventLogger = EventLogger() self.cancel_order_logger: EventLogger = EventLogger() self.maker_market.add_listener(MarketEvent.OrderFilled, self.maker_order_fill_logger) self.taker_market.add_listener(MarketEvent.OrderFilled, self.taker_order_fill_logger) self.maker_market.add_listener(MarketEvent.OrderCancelled, self.cancel_order_logger)
def setUp(self): self.order_fill_logger: EventLogger = EventLogger() self.cancel_order_logger: EventLogger = EventLogger() self.clock: Clock = Clock(ClockMode.BACKTEST, 1, self.start_timestamp, self.end_timestamp) self.spot_connector: BacktestMarket = BacktestMarket() self.spot_obook: MockOrderBookLoader = MockOrderBookLoader(self.trading_pair, self.base_asset, self.quote_asset) self.spot_obook.set_balanced_order_book(mid_price=100, min_price=1, max_price=200, price_step_size=1, volume_step_size=10) self.spot_connector.add_data(self.spot_obook) self.spot_connector.set_balance("HBOT", 500) self.spot_connector.set_balance("ETH", 5000) self.spot_connector.set_quantization_param( QuantizationParams( self.trading_pair, 6, 6, 6, 6 ) ) self.spot_market_info = MarketTradingPairTuple(self.spot_connector, self.trading_pair, self.base_asset, self.quote_asset) self.perp_connector: MockPerpConnector = MockPerpConnector() self.perp_obook: MockOrderBookLoader = MockOrderBookLoader(self.trading_pair, self.base_asset, self.quote_asset) self.perp_obook.set_balanced_order_book(mid_price=110, min_price=1, max_price=200, price_step_size=1, volume_step_size=10) self.perp_connector.add_data(self.perp_obook) self.perp_connector.set_balance("HBOT", 500) self.perp_connector.set_balance("ETH", 5000) self.perp_connector.set_quantization_param( QuantizationParams( self.trading_pair, 6, 6, 6, 6 ) ) self.perp_market_info = MarketTradingPairTuple(self.perp_connector, self.trading_pair, self.base_asset, self.quote_asset) self.clock.add_iterator(self.spot_connector) self.clock.add_iterator(self.perp_connector) self.spot_connector.add_listener(MarketEvent.OrderFilled, self.order_fill_logger) self.spot_connector.add_listener(MarketEvent.OrderCancelled, self.cancel_order_logger) self.perp_connector.add_listener(MarketEvent.OrderFilled, self.order_fill_logger) self.perp_connector.add_listener(MarketEvent.OrderCancelled, self.cancel_order_logger) self.strategy = SpotPerpetualArbitrageStrategy( self.spot_market_info, self.perp_market_info, order_amount=Decimal("1"), derivative_leverage=5, min_divergence=Decimal("0.05"), min_convergence=Decimal("0.01") )
def setUp(self): self.maxDiff = None self.clock: Clock = Clock(ClockMode.BACKTEST, 1.0, self.start_timestamp, self.end_timestamp) self.market_1: BacktestMarket = BacktestMarket() self.market_2: BacktestMarket = BacktestMarket() self.market_1_data: MockOrderBookLoader = MockOrderBookLoader(*self.market_1_trading_pairs) self.market_2_data: MockOrderBookLoader = MockOrderBookLoader(*self.market_2_trading_pairs) self.market_1_data.set_balanced_order_book(1.0, 0.5, 1.5, 0.01, 10) self.market_2_data.set_balanced_order_book(1.0, 0.5, 1.5, 0.005, 5) self.market_1.add_data(self.market_1_data) self.market_2.add_data(self.market_2_data) self.market_1.set_balance("COINALPHA", 500) self.market_1.set_balance("WETH", 500) self.market_2.set_balance("COINALPHA", 500) self.market_2.set_balance("ETH", 500) self.market_1.set_quantization_param( QuantizationParams( self.market_1_trading_pairs[0], 5, 5, 5, 5 ) ) self.market_2.set_quantization_param( QuantizationParams( self.market_2_trading_pairs[0], 5, 5, 5, 5 ) ) self.market_trading_pair_tuple_1 = MarketTradingPairTuple(*([self.market_1] + self.market_1_trading_pairs)) self.market_trading_pair_tuple_2 = MarketTradingPairTuple(*([self.market_2] + self.market_2_trading_pairs)) self.market_pair: ArbitrageMarketPair = ArbitrageMarketPair( self.market_trading_pair_tuple_1, self.market_trading_pair_tuple_2 ) self.logging_options: int = ArbitrageStrategy.OPTION_LOG_ALL self.strategy: ArbitrageStrategy = ArbitrageStrategy( [self.market_pair], min_profitability=Decimal("0.03"), logging_options=self.logging_options, secondary_to_primary_quote_conversion_rate=Decimal("0.95") ) self.clock.add_iterator(self.market_1) self.clock.add_iterator(self.market_2) self.clock.add_iterator(self.strategy) self.market_1_order_fill_logger: EventLogger = EventLogger() self.market_2_order_fill_logger: EventLogger = EventLogger() self.market_1.add_listener(MarketEvent.OrderFilled, self.market_1_order_fill_logger) self.market_2.add_listener(MarketEvent.OrderFilled, self.market_2_order_fill_logger)
def start(self): try: order_amount = dev_4_twap_config_map.get("order_amount").value order_type = dev_4_twap_config_map.get("order_type").value is_buy = dev_4_twap_config_map.get("is_buy").value time_delay = dev_4_twap_config_map.get("time_delay").value num_individual_orders = dev_4_twap_config_map.get( "num_individual_orders").value exchange = dev_4_twap_config_map.get("exchange").value.lower() raw_market_trading_pair = dev_4_twap_config_map.get("market").value order_price = None cancel_order_wait_time = None if order_type == "limit": order_price = dev_4_twap_config_map.get("order_price").value cancel_order_wait_time = dev_4_twap_config_map.get( "cancel_order_wait_time").value try: assets: Tuple[str, str] = self._initialize_market_assets( exchange, [raw_market_trading_pair])[0] except ValueError as e: self._notify(str(e)) return market_names: List[Tuple[str, List[str]]] = [ (exchange, [raw_market_trading_pair]) ] self._initialize_wallet(token_trading_pairs=list(set(assets))) self._initialize_markets(market_names) self.assets = set(assets) maker_data = [self.markets[exchange], raw_market_trading_pair ] + list(assets) self.market_trading_pair_tuples = [MarketTradingPairTuple(*maker_data)] self.strategy = Dev4TwapTradeStrategy( market_infos=[MarketTradingPairTuple(*maker_data)], order_type=order_type, order_price=order_price, cancel_order_wait_time=cancel_order_wait_time, is_buy=is_buy, time_delay=time_delay, num_individual_orders=num_individual_orders, order_amount=order_amount) except Exception as e: self._notify(str(e)) self.logger().error("Unknown error during initialization.", exc_info=True)
def setUpClass(cls): cls.maxDiff = None cls.trade_fill_sql = SQLConnectionManager( SQLConnectionType.TRADE_FILLS, db_path="") cls.ev_loop: asyncio.BaseEventLoop = asyncio.get_event_loop() cls._weth_price = 1.0 cls._eth_price = 1.0 cls._dai_price = 0.95 cls._usdc_price = 1.05 cls.trading_pair_tuple_1 = MarketTradingPairTuple( MockMarket1(), "WETHDAI", "WETH", "DAI") cls.trading_pair_tuple_2 = MarketTradingPairTuple( MockMarket2(), "WETHDAI", "WETH", "DAI") cls.strategy_1 = "strategy_1"
def setUp(self): self.clock: Clock = Clock(ClockMode.REALTIME) self.stack: contextlib.ExitStack = contextlib.ExitStack() self.amm_1: MockAMM = MockAMM( name="onion", client_config_map=ClientConfigAdapter(ClientConfigMap())) self.amm_1.set_balance(BASE_ASSET, 500) self.amm_1.set_balance(QUOTE_ASSET, 500) self.market_info_1 = MarketTradingPairTuple(self.amm_1, TRADING_PAIR, BASE_ASSET, QUOTE_ASSET) self.amm_2: MockAMM = MockAMM( name="garlic", client_config_map=ClientConfigAdapter(ClientConfigMap())) self.amm_2.set_balance(BASE_ASSET, 500) self.amm_2.set_balance(QUOTE_ASSET, 500) self.market_info_2 = MarketTradingPairTuple(self.amm_2, TRADING_PAIR, BASE_ASSET, QUOTE_ASSET) # Set some default prices. self.amm_1.set_prices(TRADING_PAIR, True, 101) self.amm_1.set_prices(TRADING_PAIR, False, 100) self.amm_2.set_prices(TRADING_PAIR, True, 105) self.amm_2.set_prices(TRADING_PAIR, False, 104) self.strategy = AmmArbStrategy() self.strategy.init_params( self.market_info_1, self.market_info_2, min_profitability=Decimal("0.01"), order_amount=Decimal("1"), market_1_slippage_buffer=Decimal("0.001"), market_2_slippage_buffer=Decimal("0.002"), ) self.rate_source: FixedRateSource = FixedRateSource() self.strategy.rate_source = self.rate_source self.clock.add_iterator(self.amm_1) self.clock.add_iterator(self.amm_2) self.clock.add_iterator(self.strategy) self.market_order_fill_logger: EventLogger = EventLogger() self.amm_1.add_listener(MarketEvent.OrderFilled, self.market_order_fill_logger) self.amm_2.add_listener(MarketEvent.OrderFilled, self.market_order_fill_logger) self.rate_source.add_rate("ETH-USDT", Decimal(3000)) self.stack.enter_context(self.clock) self.stack.enter_context(patch( "hummingbot.client.config.trade_fee_schema_loader.TradeFeeSchemaLoader.configured_schema_for_exchange", return_value=TradeFeeSchema() )) self.clock_task: asyncio.Task = safe_ensure_future(self.clock.run())
def setUp(self): self.clock_tick_size = 1 self.clock: Clock = Clock(ClockMode.BACKTEST, self.clock_tick_size, self.start_timestamp, self.end_timestamp) self.market: MockPaperExchange = MockPaperExchange() self.mid_price = 100 self.bid_spread = 0.01 self.ask_spread = 0.01 self.order_refresh_time = 30 self.market.set_balanced_order_book(trading_pair=self.trading_pair, mid_price=self.mid_price, min_price=1, max_price=200, price_step_size=1, volume_step_size=10) self.market.set_balance("HBOT", 500) self.market.set_balance("ETH", 5000) self.market.set_quantization_param( QuantizationParams(self.trading_pair, 6, 6, 6, 6)) self.market_info = MarketTradingPairTuple(self.market, self.trading_pair, self.base_asset, self.quote_asset) self.clock.add_iterator(self.market) self.maker_order_fill_logger: EventLogger = EventLogger() self.cancel_order_logger: EventLogger = EventLogger() self.market.add_listener(MarketEvent.OrderFilled, self.maker_order_fill_logger) self.market.add_listener(MarketEvent.OrderCancelled, self.cancel_order_logger)
def setUp(self): self.clock: Clock = Clock(ClockMode.REALTIME) self.stack: contextlib.ExitStack = contextlib.ExitStack() self.lp: MockAMMLP = MockAMMLP("onion") self.lp.set_balance(BASE_ASSET, 500) self.lp.set_balance(QUOTE_ASSET, 500) self.market_info = MarketTradingPairTuple(self.lp, TRADING_PAIR, BASE_ASSET, QUOTE_ASSET) # Set some default price. self.lp.set_price(TRADING_PAIR, 1) self.strategy = UniswapV3LpStrategy( self.market_info, "LOW", Decimal("0.2"), Decimal("1"), Decimal("10"), ) self.clock.add_iterator(self.lp) self.clock.add_iterator(self.strategy) self.stack.enter_context(self.clock) self.stack.enter_context(patch( "hummingbot.client.config.trade_fee_schema_loader.TradeFeeSchemaLoader.configured_schema_for_exchange", return_value=TradeFeeSchema() )) self.clock_task: asyncio.Task = safe_ensure_future(self.clock.run())
def setUp(self): super().setUp() self.log_records = [] self.clock: Clock = Clock(ClockMode.BACKTEST, self.clock_tick_size, self.start_timestamp, self.end_timestamp) self.market: BacktestMarket = BacktestMarket() self.maker_data: MockOrderBookLoader = MockOrderBookLoader( *self.maker_trading_pairs) self.mid_price = 100 self.order_delay_time = 15 self.cancel_order_wait_time = 45 self.maker_data.set_balanced_order_book(mid_price=self.mid_price, min_price=1, max_price=200, price_step_size=1, volume_step_size=10) self.market.add_data(self.maker_data) self.market.set_balance("COINALPHA", 500) self.market.set_balance("WETH", 50000) self.market.set_balance("QETH", 500) self.market.set_quantization_param( QuantizationParams(self.maker_trading_pairs[0], 6, 6, 6, 6)) self.market_info: MarketTradingPairTuple = MarketTradingPairTuple( *([self.market] + self.maker_trading_pairs)) # Define strategies to test self.limit_buy_strategy: TwapTradeStrategy = TwapTradeStrategy( [self.market_info], order_price=Decimal("99"), cancel_order_wait_time=self.cancel_order_wait_time, is_buy=True, order_delay_time=self.order_delay_time, target_asset_amount=Decimal("2.0"), order_step_size=Decimal("1.0")) self.limit_sell_strategy: TwapTradeStrategy = TwapTradeStrategy( [self.market_info], order_price=Decimal("101"), cancel_order_wait_time=self.cancel_order_wait_time, is_buy=False, order_delay_time=self.order_delay_time, target_asset_amount=Decimal("5.0"), order_step_size=Decimal("1.67")) self.clock.add_iterator(self.market) self.maker_order_fill_logger: EventLogger = EventLogger() self.cancel_order_logger: EventLogger = EventLogger() self.buy_order_completed_logger: EventLogger = EventLogger() self.sell_order_completed_logger: EventLogger = EventLogger() self.market.add_listener(MarketEvent.BuyOrderCompleted, self.buy_order_completed_logger) self.market.add_listener(MarketEvent.SellOrderCompleted, self.sell_order_completed_logger) self.market.add_listener(MarketEvent.OrderFilled, self.maker_order_fill_logger) self.market.add_listener(MarketEvent.OrderCancelled, self.cancel_order_logger)
def create_market( trading_pairs: List[str], mid_price, balances: Dict[str, int] ) -> (MockPaperExchange, Dict[str, MarketTradingPairTuple]): """ Create a BacktestMarket and marketinfo dictionary to be used by the liquidity mining strategy """ market: ExtendedMockPaperExchange = ExtendedMockPaperExchange() market_infos: Dict[str, MarketTradingPairTuple] = {} for trading_pair in trading_pairs: base_asset = trading_pair.split("-")[0] quote_asset = trading_pair.split("-")[1] market.set_balanced_order_book(trading_pair=trading_pair, mid_price=mid_price, min_price=1, max_price=200, price_step_size=1, volume_step_size=10) market.set_quantization_param( QuantizationParams(trading_pair, 6, 6, 6, 6)) market_infos[trading_pair] = MarketTradingPairTuple( market, trading_pair, base_asset, quote_asset) for asset, value in balances.items(): market.set_balance(asset, value) return market, market_infos
def setUp(self): self.market: MockPaperExchange = MockPaperExchange() self.market_info: MarketTradingPairTuple = MarketTradingPairTuple( self.market, self.trading_pair, *self.trading_pair.split("-")) self.strategy: StrategyPyBase = MockPyStrategy() self.strategy.add_markets([self.market])
def __init__( self, exchange: ExchangeBase, trading_pair: str, is_buy: bool, spread: Decimal, order_amount: Decimal, price_type: PriceType, hb_app_notification: bool = False, ): super().__init__() self._exchange = exchange self._trading_pair = trading_pair self._is_buy = is_buy self._spread = spread / Decimal("100") self._order_amount = order_amount self._price_type = price_type self._hb_app_notification = hb_app_notification self.add_markets([self._exchange]) base, quote = trading_pair.split("-") self._market_info: MarketTradingPairTuple = MarketTradingPairTuple( exchange, trading_pair, base, quote) self._ready = False self._current_price = s_decimal_zero self._last_own_trade_price = s_decimal_zero self._order_refresh_time: float = -1 self._tracked_order_ids: Set = set()
def setUp(self): self.clock_tick_size = 1 self.clock: Clock = Clock(ClockMode.BACKTEST, self.clock_tick_size, self.start_timestamp, self.end_timestamp) self.market: BacktestMarket = BacktestMarket() self.maker_data: MockOrderBookLoader = MockOrderBookLoader(*self.maker_trading_pairs) self.mid_price = 100 self.maker_data.set_balanced_order_book(mid_price=self.mid_price, min_price=1, max_price=200, price_step_size=1, volume_step_size=10) self.market.add_data(self.maker_data) self.market.set_balance("COINALPHA", 500) self.market.set_balance("WETH", 5000) self.market.set_balance("QETH", 500) self.market.set_quantization_param( QuantizationParams( self.maker_trading_pairs[0], 6, 6, 6, 6 ) ) self.market_info: MarketTradingPairTuple = MarketTradingPairTuple( self.market, self.maker_trading_pairs[0], self.maker_trading_pairs[1], self.maker_trading_pairs[2] ) self.strategy: PureMarketMakingStrategy = PureMarketMakingStrategy( self.market_info, bid_spread=Decimal(.05), ask_spread=Decimal(.05), order_amount=Decimal(1), order_refresh_time=30, minimum_spread=0, )
def setUp(self): self.maxDiff = None self.clock: Clock = Clock(ClockMode.BACKTEST, 1.0, self.start_timestamp, self.end_timestamp) self.market: MockPaperExchange = MockPaperExchange() self.market.set_balanced_order_book(self.trading_pair, 10, 5, 15, 0.1, 1) self.market.set_balance(self.base_asset, 500) self.market.set_balance(self.quote_asset, 500) self.market.set_quantization_param( QuantizationParams(self.trading_pair, 5, 5, 5, 5)) self.market_info = MarketTradingPairTuple(self.market, self.trading_pair, self.base_asset, self.quote_asset) self.logging_options: int = CeloArbStrategy.OPTION_LOG_ALL self.strategy = CeloArbStrategy() self.strategy.init_params(self.market_info, min_profitability=Decimal("0.01"), order_amount=Decimal("1"), celo_slippage_buffer=Decimal("0.001"), logging_options=self.logging_options, hb_app_notification=False, mock_celo_cli_mode=True) self.clock.add_iterator(self.market) self.clock.add_iterator(self.strategy) self.market_order_fill_logger: EventLogger = EventLogger() self.market.add_listener(MarketEvent.OrderFilled, self.market_order_fill_logger) CeloCLI.unlock_account(TEST_ADDRESS, TEST_PASSWORD)
def setUpClass(cls): cls.ev_loop = asyncio.get_event_loop() cls.trading_pair = "COINALPHA-HBOT" cls.limit_orders: List[LimitOrder] = [ LimitOrder(client_order_id=f"LIMIT//-{i}-{int(time.time()*1e3)}", trading_pair=cls.trading_pair, is_buy=True if i % 2 == 0 else False, base_currency=cls.trading_pair.split("-")[0], quote_currency=cls.trading_pair.split("-")[1], price=Decimal(f"{100 - i}") if i % 2 == 0 else Decimal(f"{100 + i}"), quantity=Decimal(f"{10 * (i + 1)}") ) for i in range(20) ] cls.market_orders: List[MarketOrder] = [ MarketOrder(order_id=f"MARKET//-{i}-{int(time.time()*1e3)}", trading_pair=cls.trading_pair, is_buy=True if i % 2 == 0 else False, base_asset=cls.trading_pair.split("-")[0], quote_asset=cls.trading_pair.split("-")[1], amount=float(f"{10 * (i + 1)}"), timestamp=time.time() ) for i in range(20) ] cls.market: BacktestMarket = BacktestMarket() cls.market_info: MarketTradingPairTuple = MarketTradingPairTuple( cls.market, cls.trading_pair, *cls.trading_pair.split("-") )
def start(self): pair = c_map.get("market").value fee_tier = c_map.get("fee_tier").value use_volatility = c_map.get("use_volatility").value volatility_period = c_map.get("volatility_period").value volatility_factor = c_map.get("volatility_factor").value buy_position_price_spread = c_map.get( "buy_position_price_spread").value / Decimal("100") sell_position_price_spread = c_map.get( "sell_position_price_spread").value / Decimal("100") base_token_amount = c_map.get("base_token_amount").value quote_token_amount = c_map.get("quote_token_amount").value min_profitability = c_map.get("min_profitability").value / Decimal("100") self._initialize_markets([("uniswap_v3", [pair])]) base, quote = pair.split("-") self.assets = set([base, quote]) market_info = MarketTradingPairTuple(self.markets["uniswap_v3"], pair, base, quote) self.market_trading_pair_tuples = [market_info] self.strategy = UniswapV3LpStrategy(market_info, fee_tier, use_volatility, volatility_period, volatility_factor, buy_position_price_spread, sell_position_price_spread, base_token_amount, quote_token_amount, min_profitability)
def setUp(self) -> None: np.random.seed(self.INITIAL_RANDOM_SEED) trade_fee_schema = TradeFeeSchema( maker_percent_fee_decimal=Decimal("0.25"), taker_percent_fee_decimal=Decimal("0.25")) client_config_map = ClientConfigAdapter(ClientConfigMap()) self.market: MockPaperExchange = MockPaperExchange( client_config_map, trade_fee_schema) self.market_info: MarketTradingPairTuple = MarketTradingPairTuple( self.market, self.trading_pair, *self.trading_pair.split("-")) self.market.set_balanced_order_book(trading_pair=self.trading_pair, mid_price=self.initial_mid_price, min_price=1, max_price=200, price_step_size=1, volume_step_size=10) self.market.set_balance("COINALPHA", 1) self.market.set_balance("HBOT", 500) self.market.set_quantization_param( QuantizationParams(self.trading_pair.split("-")[0], 6, 6, 6, 6)) self.price_delegate = OrderBookAssetPriceDelegate( self.market_info.market, self.trading_pair) self.indicator = TradingIntensityIndicator( order_book=self.market_info.order_book, price_delegate=self.price_delegate, sampling_length=self.BUFFER_LENGTH)