def test_profitability_without_conversion(self):
        self.clock.remove_iterator(self.strategy)
        self.strategy: CrossExchangeMarketMakingStrategy = CrossExchangeMarketMakingStrategy(
            [self.market_pair],
            0.01,
            order_size_portfolio_ratio_limit=0.3,
            logging_options=self.logging_options)
        self.clock.add_iterator(self.strategy)

        self.clock.backtest_til(self.start_timestamp + 5)
        self.assertEqual(0, len(self.strategy.active_bids))
        self.assertEqual(0, len(self.strategy.active_asks))
        self.assertEqual((False, False),
                         self.strategy.has_market_making_profit_potential(
                             self.market_pair, self.maker_data.order_book,
                             self.taker_data.order_book))

        self.clock.remove_iterator(self.strategy)
        self.strategy: CrossExchangeMarketMakingStrategy = CrossExchangeMarketMakingStrategy(
            [self.market_pair],
            0.004,
            order_size_portfolio_ratio_limit=0.3,
            logging_options=self.logging_options)
        self.clock.add_iterator(self.strategy)
        self.clock.backtest_til(self.start_timestamp + 10)
        self.assertEqual(1, len(self.strategy.active_bids))
        self.assertEqual(1, len(self.strategy.active_asks))
        self.assertEqual((True, True),
                         self.strategy.has_market_making_profit_potential(
                             self.market_pair, self.maker_data.order_book,
                             self.taker_data.order_book))
    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)
Ejemplo n.º 3
0
    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)
Ejemplo n.º 4
0
    def test_price_and_size_limit_calculation_with_slippage_buffer(self):
        self.taker_market.set_balance("ETH", 3)
        self.taker_market.set_balanced_order_book(
            self.taker_trading_pairs[0],
            mid_price=Decimal("1.0"),
            min_price=Decimal("0.5"),
            max_price=Decimal("1.5"),
            price_step_size=Decimal("0.1"),
            volume_step_size=Decimal("100"),
        )
        self.strategy: CrossExchangeMarketMakingStrategy = CrossExchangeMarketMakingStrategy()
        self.strategy.init_params(
            [self.market_pair],
            order_size_taker_volume_factor=Decimal("1"),
            order_size_taker_balance_factor=Decimal("1"),
            order_size_portfolio_ratio_limit=Decimal("1"),
            min_profitability=Decimal("0.25"),
            logging_options=self.logging_options,
            slippage_buffer=Decimal("0"),
            order_amount=Decimal("4"),
        )
        strategy_with_slippage_buffer: CrossExchangeMarketMakingStrategy = CrossExchangeMarketMakingStrategy()
        strategy_with_slippage_buffer.init_params(
            [self.market_pair],
            order_size_taker_volume_factor=Decimal("1"),
            order_size_taker_balance_factor=Decimal("1"),
            order_size_portfolio_ratio_limit=Decimal("1"),
            min_profitability=Decimal("0.25"),
            logging_options=self.logging_options,
            slippage_buffer=Decimal("0.25"),
            order_amount=Decimal("4"),
        )

        bid_size = self.strategy.get_market_making_size(self.market_pair, True)
        bid_price = self.strategy.get_market_making_price(self.market_pair, True, bid_size)
        ask_size = self.strategy.get_market_making_size(self.market_pair, False)
        ask_price = self.strategy.get_market_making_price(self.market_pair, False, ask_size)
        slippage_bid_size = strategy_with_slippage_buffer.get_market_making_size(self.market_pair, True)
        slippage_bid_price = strategy_with_slippage_buffer.get_market_making_price(
            self.market_pair, True, slippage_bid_size
        )
        slippage_ask_size = strategy_with_slippage_buffer.get_market_making_size(self.market_pair, False)
        slippage_ask_price = strategy_with_slippage_buffer.get_market_making_price(
            self.market_pair, False, slippage_ask_size
        )

        self.assertEqual(Decimal("4"), bid_size)  # the user size
        self.assertEqual(Decimal("0.75999"), bid_price)  # price = bid_VWAP(4) / profitability = 0.95 / 1.25
        self.assertEqual(Decimal("2.8571"), ask_size)  # size = balance / (ask_VWAP(3) * slippage) = 3 / (1.05 * 1)
        self.assertEqual(Decimal("1.3125"), ask_price)  # price = ask_VWAP(2.8571) * profitability = 1.05 * 1.25
        self.assertEqual(Decimal("4"), slippage_bid_size)  # the user size
        self.assertEqual(Decimal("0.75999"), slippage_bid_price)  # price = bid_VWAP(4) / profitability = 0.9 / 1.25
        self.assertEqual(Decimal("2.2857"), slippage_ask_size)  # size = balance / (ask_VWAP(3) * slippage) = 3 / (1.05 * 1.25)
        self.assertEqual(Decimal("1.3125"), slippage_ask_price)  # price = ask_VWAP(2.2857) * profitability = 1.05 * 1.25
Ejemplo n.º 5
0
    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_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_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))
Ejemplo n.º 8
0
    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_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))
Ejemplo n.º 10
0
    def test_profitability_with_conversion(self):
        self.clock.remove_iterator(self.strategy)
        self.market_pair: CrossExchangeMarketPair = CrossExchangeMarketPair(
            *(
                [self.maker_market] + ["COINALPHA-QETH", "COINALPHA", "QETH"] +
                [self.taker_market] + self.taker_symbols +
                [2]
            )
        )
        self.maker_data: MockOrderBookLoader = MockOrderBookLoader("COINALPHA-QETH", "COINALPHA", "QETH")
        self.maker_data.set_balanced_order_book(1.05263, 0.55, 1.55, 0.01, 10)
        self.maker_market.add_data(self.maker_data)
        self.strategy: CrossExchangeMarketMakingStrategy = CrossExchangeMarketMakingStrategy(
            [self.market_pair],
            0.01,
            order_size_portfolio_ratio_limit=0.3,
            logging_options=self.logging_options
        )
        self.clock.add_iterator(self.strategy)
        self.clock.backtest_til(self.start_timestamp + 5)
        self.assertEqual(0, len(self.strategy.active_bids))
        self.assertEqual(0, len(self.strategy.active_asks))
        self.assertEqual((False, False), self.strategy.has_market_making_profit_potential(
            self.market_pair,
            self.maker_data.order_book,
            self.taker_data.order_book
        ))

        self.clock.remove_iterator(self.strategy)
        self.strategy: CrossExchangeMarketMakingStrategy = CrossExchangeMarketMakingStrategy(
            [self.market_pair],
            0.003,
            order_size_portfolio_ratio_limit=0.3,
            logging_options=self.logging_options
        )
        self.clock.add_iterator(self.strategy)
        self.clock.backtest_til(self.start_timestamp + 10)
        self.assertEqual(1, len(self.strategy.active_bids))
        self.assertEqual(1, len(self.strategy.active_asks))
        self.assertEqual((True, True), self.strategy.has_market_making_profit_potential(
            self.market_pair,
            self.maker_data.order_book,
            self.taker_data.order_book
        ))
Ejemplo n.º 11
0
def main():
    # Define the data cache path.
    hummingsim.set_data_path(os.path.join(os.environ["PWD"], "data"))

    # Define the parameters for the backtest.
    start = pd.Timestamp("2018-12-12", tz="UTC")
    end = pd.Timestamp("2019-01-12", tz="UTC")
    binance_symbol = ("ETHUSDT", "ETH", "USDT")
    ddex_symbol = ("WETH-DAI", "WETH", "DAI")

    binance_market = BacktestMarket()
    ddex_market = BacktestMarket()
    binance_market.config = MarketConfig(AssetType.BASE_CURRENCY, 0.001,
                                         AssetType.QUOTE_CURRENCY, 0.001, {})
    ddex_market.config = MarketConfig(AssetType.BASE_CURRENCY, 0.001,
                                      AssetType.QUOTE_CURRENCY, 0.001, {})
    binance_loader = BinanceOrderBookLoaderV2(*binance_symbol)
    ddex_loader = DDEXOrderBookLoader(*ddex_symbol)

    binance_market.add_data(binance_loader)
    ddex_market.add_data(ddex_loader)

    binance_market.set_quantization_param(
        QuantizationParams("ETHUSDT", 5, 3, 5, 3))
    ddex_market.set_quantization_param(
        QuantizationParams("WETH-DAI", 5, 3, 5, 3))

    market_pair = CrossExchangeMarketPair(*([ddex_market] + list(ddex_symbol) +
                                            [binance_market] +
                                            list(binance_symbol)))
    strategy = CrossExchangeMarketMakingStrategy(
        [market_pair],
        0.003,
        logging_options=CrossExchangeMarketMakingStrategy.
        OPTION_LOG_MAKER_ORDER_FILLED)

    clock = Clock(ClockMode.BACKTEST,
                  start_time=start.timestamp(),
                  end_time=end.timestamp())
    clock.add_iterator(binance_market)
    clock.add_iterator(ddex_market)
    clock.add_iterator(strategy)

    binance_market.set_balance("ETH", 10.0)
    binance_market.set_balance("USDT", 1000.0)
    ddex_market.set_balance("WETH", 10.0)
    ddex_market.set_balance("DAI", 1000.0)

    clock.backtest()
    binance_loader.close()
    ddex_loader.close()
Ejemplo n.º 12
0
    def setUp(self):
        self.clock: Clock = Clock(ClockMode.BACKTEST, 1.0, self.start_timestamp, self.end_timestamp)
        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, 3)
        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.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(
            *(
                [self.maker_market] + self.maker_symbols +
                [self.taker_market] + self.taker_symbols +
                [2]
            )
        )

        logging_options: int = (CrossExchangeMarketMakingStrategy.OPTION_LOG_ALL &
                                (~CrossExchangeMarketMakingStrategy.OPTION_LOG_NULL_ORDER_SIZE))
        self.strategy: CrossExchangeMarketMakingStrategy = CrossExchangeMarketMakingStrategy(
            [self.market_pair],
            0.003,
            order_size_portfolio_ratio_limit=0.3,
            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)
Ejemplo n.º 13
0
    def test_with_adjust_orders_enabled(self):
        self.clock.remove_iterator(self.strategy)
        self.clock.remove_iterator(self.maker_market)
        self.maker_market: MockPaperExchange = MockPaperExchange(
            client_config_map=ClientConfigAdapter(ClientConfigMap()))
        self.maker_market.set_balanced_order_book(self.trading_pairs_maker[0],
                                                  1.0, 0.5, 1.5, 0.1, 10)
        self.market_pair: CrossExchangeMarketPair = CrossExchangeMarketPair(
            MarketTradingPairTuple(self.maker_market,
                                   *self.trading_pairs_maker),
            MarketTradingPairTuple(self.taker_market,
                                   *self.trading_pairs_taker),
        )

        config_map_raw = deepcopy(self.config_map_raw)
        config_map_raw.order_size_portfolio_ratio_limit = Decimal("30")
        config_map_raw.min_profitability = Decimal("0.5")
        config_map_raw.adjust_order_enabled = True
        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.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.trading_pairs_maker[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))
Ejemplo n.º 14
0
    async def start_market_making(self, strategy_name: str):
        strategy_cm = get_strategy_config_map(strategy_name)
        if strategy_name == "cross_exchange_market_making":
            maker_market = strategy_cm.get("maker_market").value.lower()
            taker_market = strategy_cm.get("taker_market").value.lower()
            raw_maker_symbol = strategy_cm.get(
                "maker_market_symbol").value.upper()
            raw_taker_symbol = strategy_cm.get(
                "taker_market_symbol").value.upper()
            min_profitability = strategy_cm.get("min_profitability").value
            trade_size_override = strategy_cm.get("trade_size_override").value
            strategy_report_interval = global_config_map.get(
                "strategy_report_interval").value
            limit_order_min_expiration = strategy_cm.get(
                "limit_order_min_expiration").value
            cancel_order_threshold = strategy_cm.get(
                "cancel_order_threshold").value
            active_order_canceling = strategy_cm.get(
                "active_order_canceling").value
            top_depth_tolerance_rules = [(re.compile(re_str), value)
                                         for re_str, value in strategy_cm.get(
                                             "top_depth_tolerance").value]
            top_depth_tolerance = 0.0

            for regex, tolerance_value in top_depth_tolerance_rules:
                if regex.match(raw_maker_symbol) is not None:
                    top_depth_tolerance = tolerance_value

            try:
                maker_assets: Tuple[str, str] = SymbolSplitter.split(
                    maker_market, raw_maker_symbol)
                taker_assets: Tuple[str, str] = SymbolSplitter.split(
                    taker_market, raw_taker_symbol)
            except ValueError as e:
                self.app.log(str(e))
                return

            market_names: List[Tuple[str,
                                     str]] = [(maker_market, raw_maker_symbol),
                                              (taker_market, raw_taker_symbol)]

            self._initialize_wallet(
                token_symbols=list(set(maker_assets + taker_assets)))
            self._initialize_markets(market_names)

            self.market_pair = CrossExchangeMarketPair(
                *([self.markets[maker_market], raw_maker_symbol] +
                  list(maker_assets) +
                  [self.markets[taker_market], raw_taker_symbol] +
                  list(taker_assets) + [top_depth_tolerance]))

            strategy_logging_options = (
                CrossExchangeMarketMakingStrategy.OPTION_LOG_CREATE_ORDER
                | CrossExchangeMarketMakingStrategy.OPTION_LOG_ADJUST_ORDER |
                CrossExchangeMarketMakingStrategy.OPTION_LOG_MAKER_ORDER_FILLED
                | CrossExchangeMarketMakingStrategy.OPTION_LOG_REMOVING_ORDER
                | CrossExchangeMarketMakingStrategy.OPTION_LOG_STATUS_REPORT |
                CrossExchangeMarketMakingStrategy.OPTION_LOG_MAKER_ORDER_HEDGED
            )

            self.strategy = CrossExchangeMarketMakingStrategy(
                market_pairs=[self.market_pair],
                min_profitability=min_profitability,
                status_report_interval=strategy_report_interval,
                logging_options=strategy_logging_options,
                trade_size_override=trade_size_override,
                limit_order_min_expiration=limit_order_min_expiration,
                cancel_order_threshold=cancel_order_threshold,
                active_order_canceling=active_order_canceling)

        elif strategy_name == "arbitrage":
            primary_market = strategy_cm.get("primary_market").value.lower()
            secondary_market = strategy_cm.get(
                "secondary_market").value.lower()
            raw_primary_symbol = strategy_cm.get(
                "primary_market_symbol").value.upper()
            raw_secondary_symbol = strategy_cm.get(
                "secondary_market_symbol").value.upper()
            min_profitability = strategy_cm.get("min_profitability").value
            try:
                primary_assets: Tuple[str, str] = SymbolSplitter.split(
                    primary_market, raw_primary_symbol)
                secondary_assets: Tuple[str, str] = SymbolSplitter.split(
                    secondary_market, raw_secondary_symbol)

            except ValueError as e:
                self.app.log(str(e))
                return

            market_names: List[Tuple[str, str]] = [
                (primary_market, raw_primary_symbol),
                (secondary_market, raw_secondary_symbol)
            ]
            self._initialize_wallet(
                token_symbols=list(set(primary_assets + secondary_assets)))

            self._initialize_markets(market_names)
            self.market_pair = ArbitrageMarketPair(
                *([self.markets[primary_market], raw_primary_symbol] +
                  list(primary_assets) +
                  [self.markets[secondary_market], raw_secondary_symbol] +
                  list(secondary_assets)))

            strategy_logging_options = ArbitrageStrategy.OPTION_LOG_ALL

            self.strategy = ArbitrageStrategy(
                market_pairs=[self.market_pair],
                min_profitability=min_profitability,
                logging_options=strategy_logging_options)

        else:
            raise NotImplementedError

        try:
            self.clock = Clock(ClockMode.REALTIME)
            if self.wallet is not None:
                self.clock.add_iterator(self.wallet)
            for market in self.markets.values():
                if market is not None:
                    self.clock.add_iterator(market)
            self.clock.add_iterator(self.strategy)
            self.strategy_task: asyncio.Task = asyncio.ensure_future(
                self.clock.run())
            self.app.log(
                f"\n'{strategy_name}' strategy started.\n"
                f"You can use the `status` command to query the progress.")
        except Exception as e:
            self.logger().error(str(e), exc_info=True)
Ejemplo n.º 15
0
    async def start_market_making(self, strategy_name: str):
        strategy_cm = get_strategy_config_map(strategy_name)
        if strategy_name == "cross_exchange_market_making":
            maker_market = strategy_cm.get("maker_market").value.lower()
            taker_market = strategy_cm.get("taker_market").value.lower()
            raw_maker_symbol = strategy_cm.get(
                "maker_market_symbol").value.upper()
            raw_taker_symbol = strategy_cm.get(
                "taker_market_symbol").value.upper()
            min_profitability = strategy_cm.get("min_profitability").value
            trade_size_override = strategy_cm.get("trade_size_override").value
            strategy_report_interval = global_config_map.get(
                "strategy_report_interval").value
            limit_order_min_expiration = strategy_cm.get(
                "limit_order_min_expiration").value
            cancel_order_threshold = strategy_cm.get(
                "cancel_order_threshold").value
            active_order_canceling = strategy_cm.get(
                "active_order_canceling").value
            top_depth_tolerance_rules = [(re.compile(re_str), value)
                                         for re_str, value in strategy_cm.get(
                                             "top_depth_tolerance").value]
            top_depth_tolerance = 0.0

            for regex, tolerance_value in top_depth_tolerance_rules:
                if regex.match(raw_maker_symbol) is not None:
                    top_depth_tolerance = tolerance_value

            try:
                maker_assets: Tuple[str, str] = SymbolSplitter.split(
                    maker_market, raw_maker_symbol)
                taker_assets: Tuple[str, str] = SymbolSplitter.split(
                    taker_market, raw_taker_symbol)
            except ValueError as e:
                self.app.log(str(e))
                return

            market_names: List[Tuple[str, List[str]]] = [
                (maker_market, [raw_maker_symbol]),
                (taker_market, [raw_taker_symbol])
            ]
            self._initialize_wallet(
                token_symbols=list(set(maker_assets + taker_assets)))
            self._initialize_markets(market_names)
            self.assets = set(maker_assets + taker_assets)

            self.market_pair = CrossExchangeMarketPair(
                *([self.markets[maker_market], raw_maker_symbol] +
                  list(maker_assets) +
                  [self.markets[taker_market], raw_taker_symbol] +
                  list(taker_assets) + [top_depth_tolerance]))

            strategy_logging_options = (
                CrossExchangeMarketMakingStrategy.OPTION_LOG_CREATE_ORDER
                | CrossExchangeMarketMakingStrategy.OPTION_LOG_ADJUST_ORDER |
                CrossExchangeMarketMakingStrategy.OPTION_LOG_MAKER_ORDER_FILLED
                | CrossExchangeMarketMakingStrategy.OPTION_LOG_REMOVING_ORDER
                | CrossExchangeMarketMakingStrategy.OPTION_LOG_STATUS_REPORT |
                CrossExchangeMarketMakingStrategy.OPTION_LOG_MAKER_ORDER_HEDGED
            )

            self.strategy = CrossExchangeMarketMakingStrategy(
                market_pairs=[self.market_pair],
                min_profitability=min_profitability,
                status_report_interval=strategy_report_interval,
                logging_options=strategy_logging_options,
                trade_size_override=trade_size_override,
                limit_order_min_expiration=limit_order_min_expiration,
                cancel_order_threshold=cancel_order_threshold,
                active_order_canceling=active_order_canceling)

        elif strategy_name == "arbitrage":
            primary_market = strategy_cm.get("primary_market").value.lower()
            secondary_market = strategy_cm.get(
                "secondary_market").value.lower()
            raw_primary_symbol = strategy_cm.get(
                "primary_market_symbol").value.upper()
            raw_secondary_symbol = strategy_cm.get(
                "secondary_market_symbol").value.upper()
            min_profitability = strategy_cm.get("min_profitability").value
            try:
                primary_assets: Tuple[str, str] = SymbolSplitter.split(
                    primary_market, raw_primary_symbol)
                secondary_assets: Tuple[str, str] = SymbolSplitter.split(
                    secondary_market, raw_secondary_symbol)

            except ValueError as e:
                self.app.log(str(e))
                return

            market_names: List[Tuple[str, List[str]]] = [
                (primary_market, [raw_primary_symbol]),
                (secondary_market, [raw_secondary_symbol])
            ]
            self._initialize_wallet(
                token_symbols=list(set(primary_assets + secondary_assets)))
            self._initialize_markets(market_names)
            self.assets = set(primary_assets + secondary_assets)

            self.market_pair = ArbitrageMarketPair(
                *([self.markets[primary_market], raw_primary_symbol] +
                  list(primary_assets) +
                  [self.markets[secondary_market], raw_secondary_symbol] +
                  list(secondary_assets)))

            strategy_logging_options = ArbitrageStrategy.OPTION_LOG_ALL

            self.strategy = ArbitrageStrategy(
                market_pairs=[self.market_pair],
                min_profitability=min_profitability,
                logging_options=strategy_logging_options)

        elif strategy_name == "pure_market_making":
            order_size = strategy_cm.get("order_amount").value
            cancel_order_wait_time = strategy_cm.get(
                "cancel_order_wait_time").value
            bid_place_threshold = strategy_cm.get("bid_place_threshold").value
            ask_place_threshold = strategy_cm.get("ask_place_threshold").value
            maker_market = strategy_cm.get("maker_market").value.lower()
            raw_maker_symbol = strategy_cm.get(
                "maker_market_symbol").value.upper()
            try:
                primary_assets: Tuple[str, str] = SymbolSplitter.split(
                    maker_market, raw_maker_symbol)

            except ValueError as e:
                self.app.log(str(e))
                return

            market_names: List[Tuple[str, List[str]]] = [(maker_market,
                                                          [raw_maker_symbol])]

            self._initialize_wallet(token_symbols=list(set(primary_assets)))
            self._initialize_markets(market_names)
            self.assets = set(primary_assets)

            self.market_pair = PureMarketPair(
                *([self.markets[maker_market], raw_maker_symbol] +
                  list(primary_assets)))
            strategy_logging_options = PureMarketMakingStrategy.OPTION_LOG_ALL

            self.strategy = PureMarketMakingStrategy(
                market_pairs=[self.market_pair],
                order_size=order_size,
                bid_place_threshold=bid_place_threshold,
                ask_place_threshold=ask_place_threshold,
                cancel_order_wait_time=cancel_order_wait_time,
                logging_options=strategy_logging_options)

        elif strategy_name == "discovery":
            try:
                market_1 = strategy_cm.get("primary_market").value.lower()
                market_2 = strategy_cm.get("secondary_market").value.lower()
                target_symbol_1 = list(
                    strategy_cm.get("target_symbol_1").value)
                target_symbol_2 = list(
                    strategy_cm.get("target_symbol_2").value)
                target_profitability = float(
                    strategy_cm.get("target_profitability").value)
                target_amount = float(strategy_cm.get("target_amount").value)
                equivalent_token: List[List[str]] = list(
                    strategy_cm.get("equivalent_tokens").value)

                if not target_symbol_2:
                    target_symbol_2 = SymbolFetcher.get_instance().symbols.get(
                        market_2, [])
                if not target_symbol_1:
                    target_symbol_1 = SymbolFetcher.get_instance().symbols.get(
                        market_1, [])

                market_names: List[Tuple[str, List[str]]] = [
                    (market_1, target_symbol_1), (market_2, target_symbol_2)
                ]

                target_base_quote_1: List[Tuple[str, str]] = [
                    SymbolSplitter.split(market_1, symbol)
                    for symbol in target_symbol_1
                ]
                target_base_quote_2: List[Tuple[str, str]] = [
                    SymbolSplitter.split(market_2, symbol)
                    for symbol in target_symbol_2
                ]

                self._trading_required = False
                self._initialize_wallet(
                    token_symbols=[]
                )  # wallet required only for dex hard dependency
                self._initialize_markets(market_names)
                self.market_pair = DiscoveryMarketPair(*([
                    self.markets[market_1],
                    self.markets[market_1].get_active_exchange_markets
                ] + [
                    self.markets[market_2],
                    self.markets[market_2].get_active_exchange_markets
                ]))
                self.strategy = DiscoveryStrategy(
                    market_pairs=[self.market_pair],
                    target_symbols=target_base_quote_1 + target_base_quote_2,
                    equivalent_token=equivalent_token,
                    target_profitability=target_profitability,
                    target_amount=target_amount)
            except Exception as e:
                self.app.log(str(e))
                self.logger().error("Error initializing strategy.",
                                    exc_info=True)
        else:
            raise NotImplementedError

        try:
            self.clock = Clock(ClockMode.REALTIME)
            if self.wallet is not None:
                self.clock.add_iterator(self.wallet)
            for market in self.markets.values():
                if market is not None:
                    self.clock.add_iterator(market)
            if self.strategy:
                self.clock.add_iterator(self.strategy)
            self.strategy_task: asyncio.Task = asyncio.ensure_future(
                self._run_clock())
            self.app.log(
                f"\n  '{strategy_name}' strategy started.\n"
                f"  You can use the `status` command to query the progress.")

            self.starting_balances = await self.wait_till_ready(
                self.balance_snapshot)
            self.stop_loss_tracker = StopLossTracker(
                self.data_feed, list(self.assets), list(self.markets.values()),
                lambda *args, **kwargs: asyncio.ensure_future(
                    self.stop(*args, **kwargs)))
            await self.wait_till_ready(self.stop_loss_tracker.start)
        except Exception as e:
            self.logger().error(str(e), exc_info=True)
Ejemplo n.º 16
0
    def test_check_if_sufficient_balance_adjusts_including_slippage(self):
        self.taker_market.set_balance("COINALPHA", 4)
        self.taker_market.set_balance("ETH", 3)
        self.taker_market.set_balanced_order_book(
            self.taker_trading_pairs[0],
            mid_price=Decimal("1.0"),
            min_price=Decimal("0.5"),
            max_price=Decimal("1.5"),
            price_step_size=Decimal("0.1"),
            volume_step_size=Decimal("1"),
        )
        strategy_with_slippage_buffer: CrossExchangeMarketMakingStrategy = CrossExchangeMarketMakingStrategy(
        )
        strategy_with_slippage_buffer.init_params(
            [self.market_pair],
            order_size_taker_volume_factor=Decimal("1"),
            order_size_taker_balance_factor=Decimal("1"),
            order_size_portfolio_ratio_limit=Decimal("1"),
            min_profitability=Decimal("0.25"),
            logging_options=self.logging_options,
            slippage_buffer=Decimal("0.25"),
            order_amount=Decimal("4"),
        )
        self.clock.remove_iterator(self.strategy)
        self.clock.add_iterator(strategy_with_slippage_buffer)
        self.clock.backtest_til(self.start_timestamp + 1)

        active_bids = strategy_with_slippage_buffer.active_bids
        active_asks = strategy_with_slippage_buffer.active_asks

        self.assertEqual(1, len(active_bids))
        self.assertEqual(1, len(active_asks))

        active_bid = active_bids[0][1]
        active_ask = active_asks[0][1]

        self.emit_order_created_event(self.maker_market, active_bid)
        self.emit_order_created_event(self.maker_market, active_ask)

        self.clock.backtest_til(self.start_timestamp + 2)

        active_bids = strategy_with_slippage_buffer.active_bids
        active_asks = strategy_with_slippage_buffer.active_asks

        self.assertEqual(1, len(active_bids))
        self.assertEqual(1, len(active_asks))

        active_bid = active_bids[0][1]
        active_ask = active_asks[0][1]
        bids_quantum = self.taker_market.get_order_size_quantum(
            self.taker_trading_pairs[0], active_bid.quantity)
        asks_quantum = self.taker_market.get_order_size_quantum(
            self.taker_trading_pairs[0], active_ask.quantity)

        self.taker_market.set_balance("COINALPHA", Decimal("4") - bids_quantum)
        self.taker_market.set_balance("ETH", Decimal("3") - asks_quantum * 1)

        self.clock.backtest_til(self.start_timestamp + 3)
        active_bids = strategy_with_slippage_buffer.active_bids
        active_asks = strategy_with_slippage_buffer.active_asks

        self.assertEqual(0, len(active_bids))  # cancelled
        self.assertEqual(0, len(active_asks))  # cancelled

        self.clock.backtest_til(self.start_timestamp + 4)

        new_active_bids = strategy_with_slippage_buffer.active_bids
        new_active_asks = strategy_with_slippage_buffer.active_asks

        self.assertEqual(1, len(new_active_bids))
        self.assertEqual(1, len(new_active_asks))

        new_active_bid = new_active_bids[0][1]
        new_active_ask = new_active_asks[0][1]

        self.assertEqual(Decimal(str(active_bid.quantity - bids_quantum)),
                         new_active_bid.quantity)
        self.assertEqual(Decimal(str(active_ask.quantity - asks_quantum)),
                         new_active_ask.quantity)
Ejemplo n.º 17
0
    def setUp(self):
        self.clock: Clock = Clock(ClockMode.BACKTEST, 1.0,
                                  self.start_timestamp, self.end_timestamp)
        self.min_profitability = Decimal("0.005")
        self.maker_market: MockPaperExchange = MockPaperExchange(
            client_config_map=ClientConfigAdapter(ClientConfigMap()))
        self.taker_market: MockPaperExchange = MockPaperExchange(
            client_config_map=ClientConfigAdapter(ClientConfigMap()))
        self.maker_market.set_balanced_order_book(self.trading_pairs_maker[0],
                                                  1.0, 0.5, 1.5, 0.01, 10)
        self.taker_market.set_balanced_order_book(self.trading_pairs_taker[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.trading_pairs_maker[0], 5, 5, 5, 5))
        self.taker_market.set_quantization_param(
            QuantizationParams(self.trading_pairs_taker[0], 5, 5, 5, 5))

        self.market_pair: CrossExchangeMarketPair = CrossExchangeMarketPair(
            MarketTradingPairTuple(self.maker_market,
                                   *self.trading_pairs_maker),
            MarketTradingPairTuple(self.taker_market,
                                   *self.trading_pairs_taker),
        )

        self.config_map_raw = CrossExchangeMarketMakingConfigMap(
            maker_market=self.exchange_name_maker,
            taker_market=self.exchange_name_taker,
            maker_market_trading_pair=self.trading_pairs_maker[0],
            taker_market_trading_pair=self.trading_pairs_taker[0],
            min_profitability=Decimal(self.min_profitability),
            slippage_buffer=Decimal("0"),
            order_amount=Decimal("0"),
            # Default values folllow
            order_size_taker_volume_factor=Decimal("25"),
            order_size_taker_balance_factor=Decimal("99.5"),
            order_size_portfolio_ratio_limit=Decimal("30"),
            adjust_order_enabled=True,
            anti_hysteresis_duration=60.0,
            order_refresh_mode=ActiveOrderRefreshMode(),
            top_depth_tolerance=Decimal(0),
            conversion_rate_mode=TakerToMakerConversionRateMode(),
        )

        self.config_map_raw.conversion_rate_mode.taker_to_maker_base_conversion_rate = Decimal(
            "1.0")
        self.config_map_raw.conversion_rate_mode.taker_to_maker_quote_conversion_rate = Decimal(
            "1.0")

        self.config_map = ClientConfigAdapter(self.config_map_raw)
        config_map_with_top_depth_tolerance_raw = deepcopy(self.config_map_raw)
        config_map_with_top_depth_tolerance_raw.top_depth_tolerance = Decimal(
            "1")
        config_map_with_top_depth_tolerance = ClientConfigAdapter(
            config_map_with_top_depth_tolerance_raw)

        logging_options: int = (
            CrossExchangeMarketMakingStrategy.OPTION_LOG_ALL
            & (~CrossExchangeMarketMakingStrategy.OPTION_LOG_NULL_ORDER_SIZE))
        self.strategy: CrossExchangeMarketMakingStrategy = CrossExchangeMarketMakingStrategy(
        )
        self.strategy.init_params(
            config_map=self.config_map,
            market_pairs=[self.market_pair],
            logging_options=logging_options,
        )
        self.strategy_with_top_depth_tolerance: CrossExchangeMarketMakingStrategy = CrossExchangeMarketMakingStrategy(
        )
        self.strategy_with_top_depth_tolerance.init_params(
            config_map=config_map_with_top_depth_tolerance,
            market_pairs=[self.market_pair],
            logging_options=logging_options,
        )
        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)