def setup(self):
        # Fixture Setup
        self.clock = TestClock()
        self.uuid_factory = UUIDFactory()
        self.logger = Logger(self.clock)

        self.trader_id = TraderId("TESTER-000")
        self.account_id = AccountId("BINANCE", "000")

        self.cache = TestStubs.cache()

        self.portfolio = Portfolio(
            cache=self.cache,
            clock=self.clock,
            logger=self.logger,
        )

        self.exec_engine = ExecutionEngine(
            portfolio=self.portfolio,
            cache=self.cache,
            clock=self.clock,
            logger=self.logger,
        )

        self.exchange = SimulatedExchange(
            venue=Venue("BINANCE"),
            venue_type=VenueType.EXCHANGE,
            oms_type=OMSType.NETTING,
            account_type=AccountType.CASH,
            base_currency=None,  # Multi-currency account
            starting_balances=[Money(1_000_000, USDT)],
            is_frozen_account=False,
            instruments=[ETHUSDT_BINANCE],
            modules=[],
            cache=self.exec_engine.cache,
            fill_model=FillModel(),
            clock=self.clock,
            logger=self.logger,
        )

        self.exec_client = BacktestExecClient(
            exchange=self.exchange,
            account_id=self.account_id,
            account_type=AccountType.CASH,
            base_currency=None,  # Multi-currency account
            engine=self.exec_engine,
            clock=self.clock,
            logger=self.logger,
        )

        self.order_factory = OrderFactory(
            trader_id=self.trader_id,
            strategy_id=StrategyId("SCALPER-001"),
            clock=self.clock,
        )
    def setup(self):
        # Fixture Setup
        self.clock = TestClock()
        self.uuid_factory = UUIDFactory()
        self.logger = Logger(self.clock)

        self.trader_id = TraderId("TESTER", "000")
        self.account_id = AccountId("BINANCE", "000")

        self.portfolio = Portfolio(
            clock=self.clock,
            logger=self.logger,
        )
        self.portfolio.register_cache(DataCache(self.logger))

        self.analyzer = PerformanceAnalyzer()

        database = BypassExecutionDatabase(
            trader_id=self.trader_id,
            logger=self.logger,
        )

        self.exec_engine = ExecutionEngine(
            database=database,
            portfolio=self.portfolio,
            clock=self.clock,
            logger=self.logger,
        )

        self.exchange = SimulatedExchange(
            venue=Venue("BINANCE"),
            oms_type=OMSType.NETTING,
            is_frozen_account=False,
            starting_balances=[Money(1_000_000, USD)],
            instruments=[ETHUSDT_BINANCE],
            modules=[],
            exec_cache=self.exec_engine.cache,
            fill_model=FillModel(),
            clock=self.clock,
            logger=self.logger,
        )

        self.exec_client = BacktestExecClient(
            exchange=self.exchange,
            account_id=self.account_id,
            engine=self.exec_engine,
            clock=self.clock,
            logger=self.logger,
        )

        self.order_factory = OrderFactory(
            trader_id=self.trader_id,
            strategy_id=StrategyId("SCALPER", "000"),
            clock=self.clock,
        )
    def test_apply_given_new_state_event_updates_correctly(self):
        # Arrange
        event1 = AccountState(
            AccountId("SIM", "001"),
            [Money("10.00000000", BTC), Money("20.00000000", ETH)],
            [Money("10.00000000", BTC), Money("20.00000000", ETH)],
            [Money("0.00000000", BTC), Money("0.00000000", ETH)],
            info={},  # No default currency set
            event_id=uuid4(),
            event_timestamp=UNIX_EPOCH,
        )

        # Act
        account = Account(event1)

        # Wire up account to portfolio
        account.register_portfolio(self.portfolio)
        self.portfolio.register_account(account)

        event2 = AccountState(
            AccountId("SIM", "001"),
            [Money("9.00000000", BTC), Money("20.00000000", ETH)],
            [Money("8.50000000", BTC), Money("20.00000000", ETH)],
            [Money("0.50000000", BTC), Money("0.00000000", ETH)],
            info={},  # No default currency set
            event_id=uuid4(),
            event_timestamp=UNIX_EPOCH,
        )

        # Act
        account.apply(event2)

        # Assert
        self.assertEqual(event2, account.last_event)
        self.assertEqual([event1, event2], account.events)
        self.assertEqual(2, account.event_count)
        self.assertEqual(Money("9.00000000", BTC), account.balance(BTC))
        self.assertEqual(Money("8.50000000", BTC), account.balance_free(BTC))
        self.assertEqual(Money("0.50000000", BTC), account.balance_locked(BTC))
        self.assertEqual(Money("20.00000000", ETH), account.balance(ETH))
        self.assertEqual(Money("20.00000000", ETH), account.balance_free(ETH))
        self.assertEqual(Money("0.00000000", ETH), account.balance_locked(ETH))
Esempio n. 4
0
    def test_calculate_pnls_for_multi_currency_cash_account_adabtc(self):
        # Arrange
        event = AccountState(
            account_id=AccountId("SIM", "001"),
            account_type=AccountType.CASH,
            base_currency=None,  # Multi-currency
            reported=True,
            balances=[
                AccountBalance(
                    BTC,
                    Money(1.00000000, BTC),
                    Money(0.00000000, BTC),
                    Money(1.00000000, BTC),
                ),
                AccountBalance(
                    ADA,
                    Money(1000.00000000, ADA),
                    Money(0.00000000, ADA),
                    Money(1000.00000000, ADA),
                ),
            ],
            info={},  # No default currency set
            event_id=UUID4(),
            ts_event=0,
            ts_init=0,
        )

        account = CashAccount(event)

        order = self.order_factory.market(
            ADABTC_BINANCE.id,
            OrderSide.BUY,
            Quantity.from_int(100),
        )

        fill = TestStubs.event_order_filled(
            order,
            instrument=ADABTC_BINANCE,
            position_id=PositionId("P-123456"),
            strategy_id=StrategyId("S-001"),
            last_px=Price.from_str("0.00004100"),
        )

        position = Position(ADABTC_BINANCE, fill)

        # Act
        result = account.calculate_pnls(
            instrument=ADABTC_BINANCE,
            position=position,
            fill=fill,
        )

        # Assert
        assert result == [Money(100.000000, ADA), Money(-0.00410410, BTC)]
Esempio n. 5
0
    def test_instantiated_accounts_basic_properties(self):
        # Arrange, Act
        account = TestExecStubs.cash_account()

        # Assert
        assert account == account
        assert not account != account
        assert account.id == AccountId("SIM", "000")
        assert str(account) == "CashAccount(id=SIM-000, type=CASH, base=USD)"
        assert repr(account) == "CashAccount(id=SIM-000, type=CASH, base=USD)"
        assert isinstance(hash(account), int)
    def test_exceed_free_balance_multi_currency_raises_account_balance_negative_exception(
            self):
        # Arrange
        AccountFactory.register_calculated_account("BINANCE")

        account_id = AccountId("BINANCE", "000")
        state = AccountState(
            account_id=account_id,
            account_type=AccountType.CASH,
            base_currency=None,  # Multi-currency account
            reported=True,
            balances=[
                AccountBalance(
                    Money(10.00000000, BTC),
                    Money(0.00000000, BTC),
                    Money(10.00000000, BTC),
                ),
                AccountBalance(
                    Money(100000.00000000, USDT),
                    Money(0.00000000, USDT),
                    Money(100000.00000000, USDT),
                ),
            ],
            margins=[],
            info={},
            event_id=UUID4(),
            ts_event=0,
            ts_init=0,
        )

        self.portfolio.update_account(state)

        # Create order
        order = self.order_factory.market(  # <-- order value 150_000 USDT
            BTCUSDT_BINANCE.id,
            OrderSide.BUY,
            Quantity.from_str("3.0"),
        )

        self.cache.add_order(order, position_id=None)

        self.exec_engine.process(
            TestEventStubs.order_submitted(order, account_id=account_id))

        # Act, Assert: push account to negative balance (wouldn't normally be allowed by risk engine)
        with pytest.raises(AccountBalanceNegative):
            fill = TestEventStubs.order_filled(
                order,
                instrument=BTCUSDT_BINANCE,
                account_id=account_id,
                last_px=Price.from_str("100_000"),
            )
            self.exec_engine.process(fill)
    def test_instantiated_accounts_basic_properties(self):
        # Arrange, Act
        account = TestExecStubs.margin_account()

        # Assert
        assert account.id == AccountId("SIM", "000")
        assert str(account) == "MarginAccount(id=SIM-000, type=MARGIN, base=USD)"
        assert repr(account) == "MarginAccount(id=SIM-000, type=MARGIN, base=USD)"
        assert isinstance(hash(account), int)
        assert account == account
        assert not account != account
        assert account.default_leverage == Decimal(1)
    def test_instantiated_accounts_basic_properties(self):
        # Arrange, Act
        account = TestStubs.betting_account()

        # Assert
        assert account == account
        assert not account != account
        assert account.id == AccountId("SIM", "000")
        assert str(
            account) == "BettingAccount(id=SIM-000, type=BETTING, base=GBP)"
        assert repr(
            account) == "BettingAccount(id=SIM-000, type=BETTING, base=GBP)"
        assert isinstance(hash(account), int)
Esempio n. 9
0
    def setup(self):
        # Fixture Setup
        self.loop = asyncio.get_event_loop()
        self.loop.set_debug(True)

        self.clock = LiveClock()
        self.uuid_factory = UUIDFactory()
        self.logger = Logger(clock=self.clock)

        self.trader_id = TestIdStubs.trader_id()
        self.venue = BINANCE_VENUE
        self.account_id = AccountId(self.venue.value, "001")

        self.msgbus = MessageBus(
            trader_id=self.trader_id,
            clock=self.clock,
            logger=self.logger,
        )

        self.cache = TestComponentStubs.cache()

        self.http_client = BinanceHttpClient(  # noqa: S106 (no hardcoded password)
            loop=asyncio.get_event_loop(),
            clock=self.clock,
            logger=self.logger,
            key="SOME_BINANCE_API_KEY",
            secret="SOME_BINANCE_API_SECRET",
        )

        self.provider = BinanceSpotInstrumentProvider(
            client=self.http_client,
            logger=self.logger,
            config=InstrumentProviderConfig(load_all=True),
        )

        self.data_engine = DataEngine(
            msgbus=self.msgbus,
            cache=self.cache,
            clock=self.clock,
            logger=self.logger,
        )

        self.data_client = BinanceDataClient(
            loop=self.loop,
            client=self.http_client,
            msgbus=self.msgbus,
            cache=self.cache,
            clock=self.clock,
            logger=self.logger,
            instrument_provider=self.provider,
        )
    def test_market_value_when_insufficient_data_for_xrate_returns_none(self):
        # Arrange
        state = AccountState(
            account_id=AccountId("BITMEX", "01234"),
            balances=[Money("10.00000000", BTC), Money("10.00000000", ETH)],
            balances_free=[Money("10.00000000", BTC), Money("10.00000000", ETH)],
            balances_locked=[Money("0.00000000", BTC), Money("0.00000000", ETH)],
            info={},
            event_id=uuid4(),
            event_timestamp=UNIX_EPOCH,
        )

        account = Account(state)

        self.portfolio.register_account(account)

        order = self.order_factory.market(
            ETHUSD_BITMEX.symbol,
            OrderSide.BUY,
            Quantity(100),
        )

        fill = TestStubs.event_order_filled(
            order=order,
            instrument=ETHUSD_BITMEX,
            position_id=PositionId("P-123456"),
            strategy_id=StrategyId("S", "001"),
            fill_price=Price("376.05"),
        )

        last_ethusd = QuoteTick(
            ETHUSD_BITMEX.symbol,
            Price("376.05"),
            Price("377.10"),
            Quantity("16"),
            Quantity("25"),
            UNIX_EPOCH,
        )

        position = Position(fill)

        self.portfolio.update_position(TestStubs.event_position_opened(position))
        self.data_cache.add_quote_tick(last_ethusd)
        self.portfolio.update_tick(last_ethusd)

        # Act
        result = self.portfolio.market_values(BITMEX)

        # Assert
        # TODO: Currently no Quanto thus no xrate required
        self.assertEqual({ETH: Money('0.02659221', ETH)}, result)
Esempio n. 11
0
    def test_update_orders_working_cash_account(self):
        # Arrange
        AccountFactory.register_calculated_account("BINANCE")

        account_id = AccountId("BINANCE", "000")
        state = AccountState(
            account_id=account_id,
            account_type=AccountType.CASH,
            base_currency=None,  # Multi-currency account
            reported=True,
            balances=[
                AccountBalance(
                    BTC,
                    Money(10.00000000, BTC),
                    Money(0.00000000, BTC),
                    Money(10.00000000, BTC),
                ),
                AccountBalance(
                    USDT,
                    Money(100000.00000000, USDT),
                    Money(0.00000000, USDT),
                    Money(100000.00000000, USDT),
                ),
            ],
            info={},
            event_id=UUID4(),
            ts_event=0,
            ts_init=0,
        )

        self.portfolio.update_account(state)

        # Create two working orders
        order = self.order_factory.limit(
            BTCUSDT_BINANCE.id,
            OrderSide.BUY,
            Quantity.from_str("1.0"),
            Price.from_str("50000.00"),
        )

        self.cache.add_order(order, position_id=None)

        # Act: push order state to ACCEPTED
        self.exec_engine.process(
            TestStubs.event_order_submitted(order, account_id=account_id))
        self.exec_engine.process(
            TestStubs.event_order_accepted(order, account_id=account_id))

        # Assert
        assert self.portfolio.balances_locked(
            BINANCE)[USDT].as_decimal() == 50100
Esempio n. 12
0
    def test_order_accept_updates_margin_init(self):
        # Arrange
        AccountFactory.register_calculated_account("BINANCE")

        state = AccountState(
            account_id=AccountId("BETFAIR", "01234"),
            account_type=AccountType.MARGIN,
            base_currency=GBP,
            reported=True,
            balances=[
                AccountBalance(
                    currency=GBP,
                    total=Money(1000, GBP),
                    free=Money(1000, GBP),
                    locked=Money(0, GBP),
                ),
            ],
            info={},
            event_id=UUID4(),
            ts_event=0,
            ts_init=0,
        )

        AccountFactory.register_calculated_account("BETFAIR")

        self.portfolio.update_account(state)

        # Create a passive order
        order1 = self.order_factory.limit(
            BETTING_INSTRUMENT.id,
            OrderSide.BUY,
            Quantity.from_str("100"),
            Price.from_str("0.5"),
        )

        self.cache.add_order(order1, position_id=None)

        # Push states to ACCEPTED
        order1.apply(TestStubs.event_order_submitted(order1))
        self.cache.update_order(order1)
        order1.apply(
            TestStubs.event_order_accepted(order1,
                                           venue_order_id=VenueOrderId("1")))
        self.cache.update_order(order1)

        # Act
        self.portfolio.initialize_orders()

        # Assert
        assert self.portfolio.margins_init(BETFAIR)[
            BETTING_INSTRUMENT.id] == Money(200, GBP)
Esempio n. 13
0
    def setUp(self):
        # Fixture Setup
        self.clock = LiveClock()
        self.uuid_factory = UUIDFactory()
        self.logger = TestLogger(self.clock, bypass_logging=True)

        self.trader_id = TraderId("TESTER", "000")
        self.account_id = AccountId("BINANCE", "001")

        self.portfolio = Portfolio(
            clock=self.clock,
            logger=self.logger,
        )
        self.portfolio.register_cache(DataCache(self.logger))

        self.analyzer = PerformanceAnalyzer()

        # Fresh isolated loop testing pattern
        self.loop = asyncio.new_event_loop()
        asyncio.set_event_loop(self.loop)

        database = BypassExecutionDatabase(trader_id=self.trader_id,
                                           logger=self.logger)
        self.exec_engine = LiveExecutionEngine(
            loop=self.loop,
            database=database,
            portfolio=self.portfolio,
            clock=self.clock,
            logger=self.logger,
        )

        exec_client = MockExecutionClient(
            venue=Venue("BINANCE"),
            account_id=self.account_id,
            exec_engine=self.exec_engine,
            clock=self.clock,
            logger=self.logger,
        )

        self.exec_engine.register_client(exec_client)
        self.exec_engine.process(TestStubs.event_account_state(
            self.account_id))

        self.strategy = TradingStrategy(order_id_tag="001")
        self.strategy.register_trader(
            TraderId("TESTER", "000"),
            self.clock,
            self.logger,
        )

        self.exec_engine.register_strategy(self.strategy)
    def test_instantiate_single_asset_account(self):
        # Arrange
        event = AccountState(
            AccountId("SIM", "001"),
            [Money(1_000_000, USD)],
            [Money(1_000_000, USD)],
            [Money(0, USD)],
            info={"default_currency": "USD"},  # Set the default currency
            event_id=uuid4(),
            event_timestamp=UNIX_EPOCH,
        )

        # Act
        account = Account(event)

        # Wire up account to portfolio
        account.register_portfolio(self.portfolio)
        self.portfolio.register_account(account)

        # Assert
        self.assertEqual(AccountId("SIM", "001"), account.id)
        self.assertEqual(USD, account.default_currency)
        self.assertEqual(event, account.last_event)
        self.assertEqual([event], account.events)
        self.assertEqual(1, account.event_count)
        self.assertEqual(Money(1_000_000, USD), account.balance())
        self.assertEqual(Money(1_000_000, USD), account.balance_free())
        self.assertEqual(Money(0, USD), account.balance_locked())
        self.assertEqual({USD: Money(1_000_000, USD)}, account.balances())
        self.assertEqual({USD: Money(1_000_000, USD)}, account.balances_free())
        self.assertEqual({USD: Money(0, USD)}, account.balances_locked())
        self.assertEqual(Money(0, USD), account.unrealized_pnl())
        self.assertEqual(Money(1_000_000, USD), account.equity())
        self.assertEqual({}, account.init_margins())
        self.assertEqual({}, account.maint_margins())
        self.assertEqual(None, account.init_margin())
        self.assertEqual(None, account.maint_margin())
    def test_venue_when_brokerage_multi_venue_returns_none(self):
        # Arrange
        client = ExecutionClient(
            client_id=ClientId("IB"),
            venue_type=VenueType.BROKERAGE_MULTI_VENUE,
            account_id=AccountId("IB", "U1258001"),
            account_type=AccountType.MARGIN,
            base_currency=USD,
            engine=self.exec_engine,
            clock=self.clock,
            logger=self.logger,
        )

        # Act, Assert
        assert client.venue is None
Esempio n. 16
0
    def test_calculate_pnls_for_single_currency_cash_account(self):
        # Arrange
        event = AccountState(
            account_id=AccountId("SIM", "001"),
            account_type=AccountType.CASH,
            base_currency=USD,
            reported=True,
            balances=[
                AccountBalance(
                    Money(1_000_000.00, USD),
                    Money(0.00, USD),
                    Money(1_000_000.00, USD),
                ),
            ],
            margins=[],
            info={},  # No default currency set
            event_id=UUID4(),
            ts_event=0,
            ts_init=0,
        )

        account = CashAccount(event)

        order = self.order_factory.market(
            AUDUSD_SIM.id,
            OrderSide.BUY,
            Quantity.from_int(1_000_000),
        )

        fill = TestEventStubs.order_filled(
            order,
            instrument=AUDUSD_SIM,
            position_id=PositionId("P-123456"),
            strategy_id=StrategyId("S-001"),
            last_px=Price.from_str("0.80000"),
        )

        position = Position(AUDUSD_SIM, fill)

        # Act
        result = account.calculate_pnls(
            instrument=AUDUSD_SIM,
            position=position,
            fill=fill,
        )

        # Assert
        assert result == [Money(-800016.00, USD)]
Esempio n. 17
0
    def test_order_submitted(self):
        # Arrange
        uuid = uuid4()
        event = OrderSubmitted(
            account_id=AccountId("SIM", "000"),
            client_order_id=ClientOrderId("O-2020872378423"),
            submitted_ns=0,
            event_id=uuid,
            timestamp_ns=0,
        )

        # Act
        assert f"OrderSubmitted(account_id=SIM-000, client_order_id=O-2020872378423, event_id={uuid})", (
            str(event))
        assert f"OrderSubmitted(account_id=SIM-000, client_order_id=O-2020872378423, event_id={uuid})", (
            repr(event))
Esempio n. 18
0
    def test_order_submitted(self):
        # Arrange
        uuid = uuid4()
        event = OrderSubmitted(
            account_id=AccountId("SIM", "000"),
            cl_ord_id=ClientOrderId("O-2020872378423"),
            submitted_time=UNIX_EPOCH,
            event_id=uuid,
            event_timestamp=UNIX_EPOCH,
        )

        # Act
        assert f"OrderSubmitted(account_id=SIM-000, cl_ord_id=O-2020872378423, event_id={uuid})", str(
            event)
        assert f"OrderSubmitted(account_id=SIM-000, cl_ord_id=O-2020872378423, event_id={uuid})", repr(
            event)
    def test_can_add_account(self):
        # Arrange
        event = AccountStateEvent(
            AccountId.py_from_string('SIMULATED-123456-SIMULATED'),
            Currency.USD, Money(1000000, Currency.USD),
            Money(1000000, Currency.USD), Money(0, Currency.USD),
            Money(0, Currency.USD), Money(0, Currency.USD), Decimal(0),
            ValidString('N'), GUID(uuid.uuid4()), UNIX_EPOCH)

        account = Account(event)

        # Act
        self.database.add_account(account)

        # Assert
        self.assertTrue(True)  # Did not raise exception
    def test_unrealized_pnl_when_insufficient_data_for_xrate_returns_none(
            self):
        # Arrange
        state = AccountState(
            account_id=AccountId("BITMEX", "01234"),
            balances=[Money("10.00000000", BTC),
                      Money("10.00000000", ETH)],
            balances_free=[
                Money("10.00000000", BTC),
                Money("10.00000000", ETH)
            ],
            balances_locked=[
                Money("0.00000000", BTC),
                Money("0.00000000", ETH)
            ],
            info={},
            event_id=uuid4(),
            event_timestamp=UNIX_EPOCH,
        )

        account = Account(state)

        self.portfolio.register_account(account)
        order = self.order_factory.market(
            ETHUSD_BITMEX.symbol,
            OrderSide.BUY,
            Quantity(100),
        )

        fill = TestStubs.event_order_filled(
            order=order,
            instrument=ETHUSD_BITMEX,
            position_id=PositionId("P-123456"),
            strategy_id=StrategyId("S", "001"),
            fill_price=Price("376.05"),
        )

        position = Position(fill)

        self.portfolio.update_position(
            TestStubs.event_position_opened(position))

        # Act
        result = self.portfolio.unrealized_pnls(BITMEX)

        # # Assert
        self.assertIsNone(result)
Esempio n. 21
0
    def test_order_expired(self):
        # Arrange
        uuid = uuid4()
        event = OrderExpired(
            account_id=AccountId("SIM", "000"),
            cl_ord_id=ClientOrderId("O-2020872378423"),
            order_id=OrderId("123456"),
            expired_time=UNIX_EPOCH,
            event_id=uuid,
            event_timestamp=UNIX_EPOCH,
        )

        # Act
        assert f"OrderExpired(account_id=SIM-000, cl_ord_id=O-2020872378423, order_id=123456, event_id={uuid})" == str(
            event)
        assert f"OrderExpired(account_id=SIM-000, cl_ord_id=O-2020872378423, order_id=123456, event_id={uuid})" == repr(
            event)
Esempio n. 22
0
    def test_order_cancelled(self):
        # Arrange
        uuid = uuid4()
        event = OrderCancelled(
            account_id=AccountId("SIM", "000"),
            cl_ord_id=ClientOrderId("O-2020872378423"),
            order_id=OrderId("123456"),
            cancelled_time=UNIX_EPOCH,
            event_id=uuid,
            event_timestamp=UNIX_EPOCH,
        )

        # Act
        self.assertEqual(f"OrderCancelled(account_id=SIM-000, cl_ord_id=O-2020872378423, "
                         f"order_id=123456, event_id={uuid})", str(event))
        self.assertEqual(f"OrderCancelled(account_id=SIM-000, cl_ord_id=O-2020872378423, "
                         f"order_id=123456, event_id={uuid})", repr(event))
Esempio n. 23
0
    def test_order_rejected(self):
        # Arrange
        uuid = uuid4()
        event = OrderRejected(
            account_id=AccountId("SIM", "000"),
            cl_ord_id=ClientOrderId("O-2020872378423"),
            rejected_time=UNIX_EPOCH,
            reason="INSUFFICIENT_MARGIN",
            event_id=uuid,
            event_timestamp=UNIX_EPOCH,
        )

        # Act
        assert f"OrderRejected(account_id=SIM-000, cl_ord_id=O-2020872378423, reason='INSUFFICIENT_MARGIN', event_id={uuid})", str(
            event)  # noqa
        assert f"OrderRejected(account_id=SIM-000, cl_ord_id=O-2020872378423, reason='INSUFFICIENT_MARGIN', event_id={uuid})", repr(
            event)  # noqa
    def test_margin_available_for_multi_asset_account(self):
        # Arrange
        event = AccountState(
            account_id=AccountId("SIM", "001"),
            account_type=AccountType.CASH,
            base_currency=None,  # Multi-currency
            reported=True,
            balances=[
                AccountBalance(
                    BTC,
                    Money(10.00000000, BTC),
                    Money(0.00000000, BTC),
                    Money(10.00000000, BTC),
                ),
                AccountBalance(
                    ETH,
                    Money(20.00000000, ETH),
                    Money(0.00000000, ETH),
                    Money(20.00000000, ETH),
                ),
            ],
            info={},  # No default currency set
            event_id=uuid4(),
            ts_updated_ns=0,
            timestamp_ns=0,
        )

        account = Account(event)

        # Wire up account to portfolio
        account.register_portfolio(self.portfolio)
        self.portfolio.register_account(account)

        # Act
        result1 = account.margin_available(BTC)
        account.update_initial_margin(Money(0.00010000, BTC))
        result2 = account.margin_available(BTC)
        account.update_maint_margin(Money(0.00020000, BTC))
        result3 = account.margin_available(BTC)
        result4 = account.margin_available(ETH)

        # Assert
        self.assertEqual(Money(10.00000000, BTC), result1)
        self.assertEqual(Money(9.99990000, BTC), result2)
        self.assertEqual(Money(9.99970000, BTC), result3)
        self.assertEqual(Money(20.00000000, ETH), result4)
    def test_instantiate_single_asset_account(self):
        # Arrange
        event = AccountState(
            account_id=AccountId("SIM", "001"),
            account_type=AccountType.CASH,
            base_currency=USD,
            reported=True,
            balances=[
                AccountBalance(
                    USD,
                    Money(1_000_000, USD),
                    Money(0, USD),
                    Money(1_000_000, USD),
                ),
            ],
            info={},
            event_id=uuid4(),
            ts_updated_ns=0,
            timestamp_ns=0,
        )

        # Act
        account = Account(event)

        # Prepare components
        account.register_portfolio(self.portfolio)
        self.portfolio.register_account(account)

        # Assert
        self.assertEqual(USD, account.base_currency)
        self.assertEqual(event, account.last_event)
        self.assertEqual([event], account.events)
        self.assertEqual(1, account.event_count)
        self.assertEqual(Money(1_000_000, USD), account.balance_total())
        self.assertEqual(Money(1_000_000, USD), account.balance_free())
        self.assertEqual(Money(0, USD), account.balance_locked())
        self.assertEqual({USD: Money(1_000_000, USD)},
                         account.balances_total())
        self.assertEqual({USD: Money(1_000_000, USD)}, account.balances_free())
        self.assertEqual({USD: Money(0, USD)}, account.balances_locked())
        self.assertEqual(Money(0, USD), account.unrealized_pnl())
        self.assertEqual(Money(1_000_000, USD), account.equity())
        self.assertEqual({}, account.initial_margins())
        self.assertEqual({}, account.maint_margins())
        self.assertEqual(None, account.initial_margin())
        self.assertEqual(None, account.maint_margin())
Esempio n. 26
0
    def __init__(
        self,
        loop: asyncio.AbstractEventLoop,
        client: BetfairClient,
        base_currency: Currency,
        msgbus: MessageBus,
        cache: Cache,
        clock: LiveClock,
        logger: Logger,
        market_filter: Dict,
        instrument_provider: BetfairInstrumentProvider,
    ):
        super().__init__(
            loop=loop,
            client_id=ClientId(BETFAIR_VENUE.value),
            venue=BETFAIR_VENUE,
            oms_type=OMSType.NETTING,
            account_type=AccountType.BETTING,
            base_currency=base_currency,
            instrument_provider=instrument_provider
            or BetfairInstrumentProvider(
                client=client, logger=logger, filters=market_filter),
            msgbus=msgbus,
            cache=cache,
            clock=clock,
            logger=logger,
        )

        self._client: BetfairClient = client
        self.stream = BetfairOrderStreamClient(
            client=self._client,
            logger=logger,
            message_handler=self.handle_order_stream_update,
        )

        self.venue_order_id_to_client_order_id: Dict[VenueOrderId,
                                                     ClientOrderId] = {}
        self.pending_update_order_client_ids: Set[Tuple[ClientOrderId,
                                                        VenueOrderId]] = set()
        self.published_executions: Dict[ClientOrderId,
                                        TradeId] = defaultdict(list)

        self._set_account_id(AccountId(BETFAIR_VENUE.value,
                                       "001"))  # TODO(cs): Temporary
        AccountFactory.register_calculated_account(BETFAIR_VENUE.value)
Esempio n. 27
0
    def test_handle_position_status_report(self):
        # Arrange
        position_report = PositionStatusReport(
            account_id=AccountId("SIM", "001"),
            instrument_id=AUDUSD_SIM.id,
            venue_position_id=PositionId("1"),
            position_side=PositionSide.LONG,
            quantity=Quantity.from_int(1_000_000),
            report_id=UUID4(),
            ts_last=0,
            ts_init=0,
        )

        # Act
        self.exec_engine.reconcile_report(position_report)

        # Assert
        assert self.exec_engine.report_count == 1
    def test_serialize_and_deserialize_account_state_events(self):
        # Arrange
        event = AccountState(
            account_id=AccountId("SIM", "000"),
            balances=[Money(1525000, USD)],
            balances_free=[Money(1425000, USD)],
            balances_locked=[Money(0, USD)],
            info={"default_currency": "USD"},
            event_id=uuid4(),
            event_timestamp=UNIX_EPOCH,
        )

        # Act
        serialized = self.serializer.serialize(event)
        deserialized = self.serializer.deserialize(serialized)

        # Assert
        self.assertEqual(deserialized, event)
    def test_instantiate_order_status_report(self):
        # Arrange, Act
        report_id = UUID4()
        report = OrderStatusReport(
            account_id=AccountId("SIM", "001"),
            instrument_id=AUDUSD_IDEALPRO,
            client_order_id=ClientOrderId("O-123456"),
            order_list_id=OrderListId("1"),
            venue_order_id=VenueOrderId("2"),
            order_side=OrderSide.SELL,
            order_type=OrderType.STOP_LIMIT,
            contingency_type=ContingencyType.OCO,
            time_in_force=TimeInForce.DAY,
            expire_time=None,
            order_status=OrderStatus.REJECTED,
            price=Price.from_str("0.90090"),
            trigger_price=Price.from_str("0.90100"),
            trigger_type=TriggerType.DEFAULT,
            limit_offset=None,
            trailing_offset=Decimal("0.00010"),
            offset_type=TrailingOffsetType.PRICE,
            quantity=Quantity.from_int(1_000_000),
            filled_qty=Quantity.from_int(0),
            display_qty=None,
            avg_px=None,
            post_only=True,
            reduce_only=False,
            cancel_reason="SOME_REASON",
            report_id=report_id,
            ts_accepted=1_000_000,
            ts_triggered=1_500_000,
            ts_last=2_000_000,
            ts_init=3_000_000,
        )

        # Assert
        assert (
            str(report)
            == f"OrderStatusReport(account_id=SIM-001, instrument_id=AUD/USD.IDEALPRO, client_order_id=O-123456, order_list_id=1, venue_order_id=2, order_side=SELL, order_type=STOP_LIMIT, contingency_type=OCO, time_in_force=DAY, expire_time=None, order_status=REJECTED, price=0.90090, trigger_price=0.90100, trigger_type=DEFAULT, limit_offset=None, trailing_offset=0.00010, offset_type=PRICE, quantity=1_000_000, filled_qty=0, leaves_qty=1_000_000, display_qty=None, avg_px=None, post_only=True, reduce_only=False, cancel_reason=SOME_REASON, report_id={report_id}, ts_accepted=1000000, ts_triggered=1500000, ts_last=2000000, ts_init=3000000)"  # noqa
        )
        assert (
            repr(report)
            == f"OrderStatusReport(account_id=SIM-001, instrument_id=AUD/USD.IDEALPRO, client_order_id=O-123456, order_list_id=1, venue_order_id=2, order_side=SELL, order_type=STOP_LIMIT, contingency_type=OCO, time_in_force=DAY, expire_time=None, order_status=REJECTED, price=0.90090, trigger_price=0.90100, trigger_type=DEFAULT, limit_offset=None, trailing_offset=0.00010, offset_type=PRICE, quantity=1_000_000, filled_qty=0, leaves_qty=1_000_000, display_qty=None, avg_px=None, post_only=True, reduce_only=False, cancel_reason=SOME_REASON, report_id={report_id}, ts_accepted=1000000, ts_triggered=1500000, ts_last=2000000, ts_init=3000000)"  # noqa
        )
Esempio n. 30
0
    def test_account_state_str_repr(self):
        # Arrange
        uuid = uuid4()
        event = AccountState(
            account_id=AccountId("SIM", "000"),
            balances=[Money(1525000, USD)],
            balances_free=[Money(1525000, USD)],
            balances_locked=[Money(0, USD)],
            info={},
            event_id=uuid,
            event_timestamp=UNIX_EPOCH,
        )

        # Act
        # Assert
        assert f"AccountState(account_id=SIM-000, free=[1,525,000.00 USD], locked=[0.00 USD], event_id={uuid})" == str(
            event)
        assert f"AccountState(account_id=SIM-000, free=[1,525,000.00 USD], locked=[0.00 USD], event_id={uuid})" == repr(
            event)