Beispiel #1
0
    def test_unrealized_pnl_when_insufficient_data_for_xrate_returns_none(
            self):
        # Arrange
        state = AccountState(
            account_id=AccountId("BITMEX", "01234"),
            account_type=AccountType.MARGIN,
            base_currency=BTC,
            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={},
            event_id=uuid4(),
            updated_ns=0,
            timestamp_ns=0,
        )

        self.exec_engine.process(state)

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

        self.exec_engine.cache.add_order(order, PositionId.null())
        self.exec_engine.process(TestStubs.event_order_submitted(order))
        self.exec_engine.process(TestStubs.event_order_accepted(order))

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

        self.exec_engine.process(fill)

        position = Position(instrument=ETHUSD_BITMEX, fill=fill)

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

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

        # # Assert
        self.assertEqual({}, result)
Beispiel #2
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)]
Beispiel #3
0
    def test_instantiate_multi_asset_cash_account(self):
        # Arrange
        event = AccountState(
            account_id=AccountId("SIM", "000"),
            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_event=0,
            ts_init=0,
        )

        # Act
        account = CashAccount(event)

        # Assert
        assert account.id == AccountId("SIM", "000")
        assert account.base_currency is None
        assert account.last_event == event
        assert account.events == [event]
        assert account.event_count == 1
        assert account.balance_total(BTC) == Money(10.00000000, BTC)
        assert account.balance_total(ETH) == Money(20.00000000, ETH)
        assert account.balance_free(BTC) == Money(10.00000000, BTC)
        assert account.balance_free(ETH) == Money(20.00000000, ETH)
        assert account.balance_locked(BTC) == Money(0.00000000, BTC)
        assert account.balance_locked(ETH) == Money(0.00000000, ETH)
        assert account.balances_total() == {
            BTC: Money(10.00000000, BTC),
            ETH: Money(20.00000000, ETH),
        }
        assert account.balances_free() == {
            BTC: Money(10.00000000, BTC),
            ETH: Money(20.00000000, ETH),
        }
        assert account.balances_locked() == {
            BTC: Money(0.00000000, BTC),
            ETH: Money(0.00000000, ETH),
        }
    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_apply_given_new_state_event_updates_correctly(self):
        # Arrange
        event1 = AccountState(
            account_id=AccountId("SIM", "001"),
            account_type=AccountType.BETTING,
            base_currency=None,  # Multi-currency
            reported=True,
            balances=[
                AccountBalance(
                    GBP,
                    Money(10.00000000, GBP),
                    Money(0.00000000, GBP),
                    Money(10.00000000, GBP),
                ),
            ],
            info={},  # No default currency set
            event_id=UUID4(),
            ts_event=0,
            ts_init=0,
        )

        # Act
        account = BettingAccount(event1)

        event2 = AccountState(
            account_id=AccountId("SIM", "001"),
            account_type=AccountType.BETTING,
            base_currency=None,  # Multi-currency
            reported=True,
            balances=[
                AccountBalance(
                    GBP,
                    Money(9.00000000, GBP),
                    Money(0.50000000, GBP),
                    Money(8.50000000, GBP),
                ),
            ],
            info={},  # No default currency set
            event_id=UUID4(),
            ts_event=0,
            ts_init=0,
        )

        # Act
        account.apply(event=event2)

        # Assert
        assert account.last_event == event2
        assert account.events == [event1, event2]
        assert account.event_count == 2
        assert account.balance_total(GBP) == Money(9.00000000, GBP)
        assert account.balance_free(GBP) == Money(8.50000000, GBP)
        assert account.balance_locked(GBP) == Money(0.50000000, GBP)
Beispiel #6
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
    def test_generate_accounts_report_with_initial_account_state_returns_expected(self):
        # Arrange
        state = AccountState(
            account_id=AccountId("BITMEX", "1513111"),
            account_type=AccountType.MARGIN,
            base_currency=BTC,
            reported=True,
            balances=[
                AccountBalance(
                    currency=BTC,
                    total=Money(10.00000000, BTC),
                    free=Money(10.00000000, BTC),
                    locked=Money(0.00000000, BTC),
                )
            ],
            info={},
            event_id=uuid4(),
            ts_updated_ns=0,
            timestamp_ns=0,
        )

        account = Account(state)

        report_provider = ReportProvider()

        # Act
        report = report_provider.generate_account_report(account)

        # Assert
        self.assertEqual(1, len(report))
 async def test_account_statement(self):
     with patch.object(BetfairClient,
                       "request",
                       return_value=BetfairResponses.account_details()):
         detail = await self.client.get_account_details()
     with patch.object(
             BetfairClient,
             "request",
             return_value=BetfairResponses.account_funds_no_exposure()):
         funds = await self.client.get_account_funds()
     result = betfair_account_to_account_state(
         account_detail=detail,
         account_funds=funds,
         event_id=self.uuid,
         ts_event=0,
         ts_init=0,
     )
     expected = AccountState(
         account_id=AccountId(issuer="BETFAIR", number="Testy-McTest"),
         account_type=AccountType.CASH,
         base_currency=GBP,
         reported=True,  # reported
         balances=[
             AccountBalance(GBP, Money(1000.0, GBP), Money(0.00, GBP),
                            Money(1000.0, GBP))
         ],
         info={
             "funds": funds,
             "detail": detail
         },
         event_id=self.uuid,
         ts_event=result.ts_event,
         ts_init=result.ts_init,
     )
     assert result == expected
    def test_account_state_event_to_from_dict_and_str_repr(self):
        # Arrange
        uuid = UUID4()
        balance = AccountBalance(
            currency=USD,
            total=Money(1525000, USD),
            locked=Money(0, USD),
            free=Money(1525000, USD),
        )
        event = AccountState(
            account_id=AccountId("SIM", "000"),
            account_type=AccountType.MARGIN,
            base_currency=USD,
            reported=True,
            balances=[balance],
            info={},
            event_id=uuid,
            ts_event=0,
            ts_init=0,
        )

        # Act, Assert
        assert AccountState.from_dict(AccountState.to_dict(event)) == event
        assert (
            str(event) ==
            f"AccountState(account_id=SIM-000, account_type=MARGIN, base_currency=USD, is_reported=True, balances=[AccountBalance(total=1_525_000.00 USD, locked=0.00 USD, free=1_525_000.00 USD)], event_id={uuid})"  # noqa
        )
        assert (
            repr(event) ==
            f"AccountState(account_id=SIM-000, account_type=MARGIN, base_currency=USD, is_reported=True, balances=[AccountBalance(total=1_525_000.00 USD, locked=0.00 USD, free=1_525_000.00 USD)], event_id={uuid})"  # noqa
        )
    def test_account_state_str_repr(self):
        # Arrange
        uuid = uuid4()
        balance = AccountBalance(
            currency=USD,
            total=Money(1525000, USD),
            locked=Money(0, USD),
            free=Money(1525000, USD),
        )
        event = AccountState(
            account_id=AccountId("SIM", "000"),
            account_type=AccountType.MARGIN,
            base_currency=USD,
            reported=True,
            balances=[balance],
            info={},
            event_id=uuid,
            updated_ns=0,
            timestamp_ns=0,
        )

        print(event)
        # Act
        # Assert
        assert (
            f"AccountState(account_id=SIM-000, account_type=MARGIN, base_currency=USD, is_reported=True, balances=[AccountBalance(total=1_525_000.00 USD, locked=0.00 USD, free=1_525_000.00 USD)], event_id={uuid})"  # noqa
            == str(event))
        assert (
            f"AccountState(account_id=SIM-000, account_type=MARGIN, base_currency=USD, is_reported=True, balances=[AccountBalance(total=1_525_000.00 USD, locked=0.00 USD, free=1_525_000.00 USD)], event_id={uuid})"  # noqa
            == repr(event))
def betfair_account_to_account_state(
    account_detail,
    account_funds,
    event_id,
    ts_event,
    ts_init,
    account_id="001",
) -> AccountState:
    currency = Currency.from_str(account_detail["currencyCode"])
    balance = float(account_funds["availableToBetBalance"])
    locked = -float(
        account_funds["exposure"]) if account_funds["exposure"] else 0.0
    free = balance - locked
    return AccountState(
        account_id=AccountId(issuer=BETFAIR_VENUE.value, number=account_id),
        account_type=AccountType.BETTING,
        base_currency=currency,
        reported=False,
        balances=[
            AccountBalance(
                total=Money(balance, currency),
                locked=Money(locked, currency),
                free=Money(free, currency),
            ),
        ],
        margins=[],
        info={
            "funds": account_funds,
            "detail": account_detail
        },
        event_id=event_id,
        ts_event=ts_event,
        ts_init=ts_init,
    )
Beispiel #12
0
def test_account_statement(betfair_client, uuid, clock):
    detail = betfair_client.account.get_account_details()
    funds = betfair_client.account.get_account_funds()
    timestamp_ns = clock.timestamp_ns()
    result = betfair_account_to_account_state(
        account_detail=detail,
        account_funds=funds,
        event_id=uuid,
        ts_updated_ns=timestamp_ns,
        timestamp_ns=timestamp_ns,
    )
    expected = AccountState(
        account_id=AccountId(issuer="BETFAIR", number="Testy-McTest"),
        account_type=AccountType.CASH,
        base_currency=AUD,
        reported=True,  # reported
        balances=[
            AccountBalance(AUD, Money(1000.0, AUD), Money(0.00, AUD),
                           Money(1000.0, AUD))
        ],
        info={
            "funds": funds,
            "detail": detail
        },
        event_id=uuid,
        ts_updated_ns=result.timestamp_ns,
        timestamp_ns=result.timestamp_ns,
    )
    assert result == expected
    def test_generate_accounts_report_with_initial_account_state_returns_expected(
            self):
        # Arrange
        state = AccountState(
            account_id=AccountId("BITMEX", "1513111"),
            account_type=AccountType.MARGIN,
            base_currency=BTC,
            reported=True,
            balances=[
                AccountBalance(
                    currency=BTC,
                    total=Money(10.00000000, BTC),
                    free=Money(10.00000000, BTC),
                    locked=Money(0.00000000, BTC),
                )
            ],
            info={},
            event_id=UUID4(),
            ts_event=0,
            ts_init=0,
        )

        account = MarginAccount(state)

        # Act
        report = ReportProvider.generate_account_report(account)

        # Assert
        assert len(report) == 1
Beispiel #14
0
    def test_account_when_account_returns_the_account_facade(self):
        # Arrange
        account_state = AccountState(
            account_id=AccountId("BINANCE", "1513111"),
            account_type=AccountType.CASH,
            base_currency=None,
            reported=True,
            balances=[
                AccountBalance(
                    BTC,
                    Money(10.00000000, BTC),
                    Money(0.00000000, BTC),
                    Money(10.00000000, BTC),
                )
            ],
            info={},
            event_id=uuid4(),
            updated_ns=0,
            timestamp_ns=0,
        )
        self.exec_engine.process(account_state)

        # Act
        result = self.portfolio.account(BINANCE)

        # Assert
        self.assertEqual("BINANCE", result.id.issuer)
    def test_equity_with_single_asset_account_returns_expected_money(self):
        # Arrange
        event = AccountState(
            account_id=AccountId("SIM", "001"),
            account_type=AccountType.CASH,
            base_currency=USD,
            reported=True,
            balances=[
                AccountBalance(
                    USD,
                    Money(100000.00, USD),
                    Money(0.00, USD),
                    Money(100000.00, USD),
                ),
            ],
            info={},
            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
        result = account.equity()

        # Assert
        self.assertEqual(Money(100000.00, USD), result)
    def test_serialize_and_deserialize_account_state_without_base_currency_events(
            self):
        # Arrange
        event = AccountState(
            account_id=AccountId("SIM", "000"),
            account_type=AccountType.MARGIN,
            base_currency=None,
            reported=True,
            balances=[
                AccountBalance(
                    USDT,
                    Money(10000, USDT),
                    Money(0, USDT),
                    Money(10000, USDT),
                )
            ],
            info={},
            event_id=uuid4(),
            ts_updated_ns=0,
            timestamp_ns=1_000_000_000,
        )

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

        # Assert
        assert deserialized == event
Beispiel #17
0
    def test_account_when_account_returns_the_account_facade(self):
        # Arrange
        state = AccountState(
            account_id=AccountId("BINANCE", "1513111"),
            account_type=AccountType.CASH,
            base_currency=None,
            reported=True,
            balances=[
                AccountBalance(
                    BTC,
                    Money(10.00000000, BTC),
                    Money(0.00000000, BTC),
                    Money(10.00000000, BTC),
                )
            ],
            info={},
            event_id=UUID4(),
            ts_event=0,
            ts_init=0,
        )

        self.portfolio.update_account(state)

        # Act
        result = self.portfolio.account(BINANCE)

        # Assert
        assert result.id.issuer == "BINANCE"
Beispiel #18
0
    def test_serialize_and_deserialize_account_state_with_base_currency_events(self):
        # Arrange
        event = AccountState(
            account_id=AccountId("SIM", "000"),
            account_type=AccountType.MARGIN,
            base_currency=USD,
            reported=True,
            balances=[
                AccountBalance(
                    Money(1525000, USD),
                    Money(25000, USD),
                    Money(1500000, USD),
                ),
            ],
            margins=[
                MarginBalance(
                    Money(5000, USD),
                    Money(20000, USD),
                    AUDUSD_SIM.id,
                ),
            ],
            info={},
            event_id=UUID4(),
            ts_event=0,
            ts_init=1_000_000_000,
        )

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

        # Assert
        assert deserialized == event
Beispiel #19
0
def betfair_account_to_account_state(
    account_detail,
    account_funds,
    event_id,
    updated_ns,
    timestamp_ns,
    account_id="001",
) -> AccountState:
    currency = Currency.from_str(account_detail["currencyCode"])
    balance = float(account_funds["availableToBetBalance"])
    locked = -float(account_funds["exposure"])
    free = balance - locked
    return AccountState(
        account_id=AccountId(issuer=BETFAIR_VENUE.value, number=account_id),
        account_type=AccountType.CASH,
        base_currency=currency,
        reported=True,
        balances=[
            AccountBalance(
                currency=currency,
                total=Money(balance, currency),
                locked=Money(locked, currency),
                free=Money(free, currency),
            ),
        ],
        info={"funds": account_funds, "detail": account_detail},
        event_id=event_id,
        updated_ns=updated_ns,
        timestamp_ns=timestamp_ns,
    )
    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_update_maint_margin(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,
        )

        # Act
        account = Account(event)

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

        margin = Money(0.00050000, BTC)

        # Act
        account.update_maint_margin(margin)

        # Assert
        self.assertEqual(margin, account.maint_margin(BTC))
        self.assertEqual({BTC: margin}, account.maint_margins())
    def test_unrealized_pnl_with_multi_asset_account_when_no_open_positions_returns_zero(
        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(),
            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
        result = account.unrealized_pnl(BTC)

        # Assert
        self.assertEqual(Money(0.00000000, BTC), result)
Beispiel #23
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)
def parse_account_balances_http(assets: List[BinanceFuturesAssetInfo]) -> List[AccountBalance]:
    balances: List[AccountBalance] = []
    for a in assets:
        currency = Currency.from_str(a.asset)
        total = Decimal(a.walletBalance)
        locked = Decimal(a.initialMargin) + Decimal(a.maintMargin)
        free = total - locked

        balance = AccountBalance(
            total=Money(total, currency),
            locked=Money(locked, currency),
            free=Money(free, currency),
        )
        balances.append(balance)

    return balances
def parse_account_balances_ws(raw_balances: List[BinanceFuturesBalance]) -> List[AccountBalance]:
    balances: List[AccountBalance] = []
    for b in raw_balances:
        currency = Currency.from_str(b.a)
        free = Decimal(b.wb)
        locked = Decimal(b.bc) + Decimal(b.bc)
        total: Decimal = free + locked

        balance = AccountBalance(
            total=Money(total, currency),
            locked=Money(locked, currency),
            free=Money(free, currency),
        )
        balances.append(balance)

    return balances
 def _make_account_state(starting_balance: float):
     return AccountState(
         account_id=AccountId("SIM", "001"),
         account_type=AccountType.BETTING,
         base_currency=GBP,
         reported=True,
         balances=[
             AccountBalance(
                 GBP,
                 Money(starting_balance, GBP),
                 Money(0.00, GBP),
                 Money(starting_balance, GBP),
             ),
         ],
         info={},  # No default currency set
         event_id=UUID4(),
         ts_event=0,
         ts_init=0,
     )
Beispiel #27
0
    def _handle_account_info(self, info: Dict[str, Any]) -> None:
        total = Money(info["totalAccountValue"], USD)
        free = Money(info["freeCollateral"], USD)
        locked = Money(total - free, USD)

        balance = AccountBalance(
            total=total,
            locked=locked,
            free=free,
        )

        # TODO(cs): Uncomment for development
        # self._log.info(str(json.dumps(info, indent=4)), color=LogColor.GREEN)

        margins: List[MarginBalance] = []

        # TODO(cs): Margins on FTX are fractions - determine solution
        # for position in info["positions"]:
        #     margin = MarginBalance(
        #         initial=Money(position["initialMarginRequirement"], USD),
        #         maintenance=Money(position["maintenanceMarginRequirement"], USD),
        #         instrument_id=InstrumentId(Symbol(position["future"]), FTX_VENUE),
        #     )
        #     margins.append(margin)

        self.generate_account_state(
            balances=[balance],
            margins=margins,
            reported=True,
            ts_event=self._clock.timestamp_ns(),
            info=info,
        )

        self._log.info(
            f"initialMarginRequirement={info['initialMarginRequirement']}, "
            f"maintenanceMarginRequirement={info['maintenanceMarginRequirement']}, "
            f"marginFraction={info['marginFraction']}, "
            f"openMarginFraction={info['openMarginFraction']}, "
            f"totalAccountValue={info['totalAccountValue']}, "
            f"totalPositionSize={info['totalPositionSize']}",
            LogColor.BLUE,
        )
    def test_margin_available_for_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(100000.00, USD),
                    Money(0.00, USD),
                    Money(100000.00, USD),
                ),
            ],
            info={},
            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()
        account.update_initial_margin(Money(500.00, USD))
        result2 = account.margin_available()
        account.update_maint_margin(Money(1000.00, USD))
        result3 = account.margin_available()

        # Assert
        self.assertEqual(Money(100000.00, USD), result1)
        self.assertEqual(Money(99500.00, USD), result2)
        self.assertEqual(Money(98500.00, USD), result3)
Beispiel #29
0
def parse_balances(
    raw_balances: List[Dict[str, str]],
    asset_key: str,
    free_key: str,
    locked_key: str,
) -> List[AccountBalance]:
    parsed_balances: Dict[Currency, Tuple[Decimal, Decimal, Decimal]] = {}
    for b in raw_balances:
        currency = Currency.from_str(b[asset_key])
        free = Decimal(b[free_key])
        locked = Decimal(b[locked_key])
        total: Decimal = free + locked
        parsed_balances[currency] = (total, locked, free)

    balances: List[AccountBalance] = [
        AccountBalance(
            total=Money(values[0], currency),
            locked=Money(values[1], currency),
            free=Money(values[2], currency),
        ) for currency, values in parsed_balances.items()
    ]

    return balances
Beispiel #30
0
    def test_calculate_pnls_for_multi_currency_cash_account_btcusdt(self):
        # Arrange
        event = AccountState(
            account_id=AccountId("SIM", "001"),
            account_type=AccountType.CASH,
            base_currency=None,  # Multi-currency
            reported=True,
            balances=[
                AccountBalance(
                    Money(10.00000000, BTC),
                    Money(0.00000000, BTC),
                    Money(10.00000000, BTC),
                ),
                AccountBalance(
                    Money(20.00000000, ETH),
                    Money(0.00000000, ETH),
                    Money(20.00000000, ETH),
                ),
            ],
            margins=[],
            info={},  # No default currency set
            event_id=UUID4(),
            ts_event=0,
            ts_init=0,
        )

        account = CashAccount(event)

        order1 = self.order_factory.market(
            BTCUSDT_BINANCE.id,
            OrderSide.SELL,
            Quantity.from_str("0.50000000"),
        )

        fill1 = TestEventStubs.order_filled(
            order1,
            instrument=BTCUSDT_BINANCE,
            position_id=PositionId("P-123456"),
            strategy_id=StrategyId("S-001"),
            last_px=Price.from_str("45500.00"),
        )

        position = Position(BTCUSDT_BINANCE, fill1)

        # Act
        result1 = account.calculate_pnls(
            instrument=BTCUSDT_BINANCE,
            position=position,
            fill=fill1,
        )

        order2 = self.order_factory.market(
            BTCUSDT_BINANCE.id,
            OrderSide.BUY,
            Quantity.from_str("0.50000000"),
        )

        fill2 = TestEventStubs.order_filled(
            order2,
            instrument=BTCUSDT_BINANCE,
            position_id=PositionId("P-123456"),
            strategy_id=StrategyId("S-001"),
            last_px=Price.from_str("45500.00"),
        )

        position.apply(fill2)

        result2 = account.calculate_pnls(
            instrument=BTCUSDT_BINANCE,
            position=position,
            fill=fill2,
        )

        # Assert
        assert result1 == [
            Money(-0.50000000, BTC),
            Money(22727.25000000, USDT)
        ]
        assert result2 == [
            Money(0.50000000, BTC),
            Money(-22772.75000000, USDT)
        ]