def test_order_side_parser_given_invalid_value_raises_value_error(self):
        # Arrange
        # Act
        # Assert
        with pytest.raises(ValueError):
            OrderSideParser.to_str_py(0)

        with pytest.raises(ValueError):
            OrderSideParser.from_str_py("")
    def test_order_side_from_str(self, string, expected):
        # Arrange
        # Act
        result = OrderSideParser.from_str_py(string)

        # Assert
        self.assertEqual(expected, result)
    def test_order_side_from_str(self, string, expected):
        # Arrange
        # Act
        result = OrderSideParser.from_str_py(string)

        # Assert
        assert expected == result
    def test_calculate_balance_locked(self, price, quantity, side,
                                      locked_balance):
        # Arrange
        event = self._make_account_state(starting_balance=1000.0)
        account = BettingAccount(event)

        # Act
        result = account.calculate_balance_locked(
            instrument=self.instrument,
            side=OrderSideParser.from_str_py(side),
            quantity=Quantity.from_int(quantity),
            price=Price.from_str(price),
        )

        # Assert
        assert result == Money(Price.from_str(locked_balance), GBP)
Example #5
0
    def _handle_execution_report(self, data: Dict[str, Any]):
        execution_type: str = data["x"]

        # Parse instrument ID
        symbol: str = data["s"]
        instrument_id: Optional[InstrumentId] = self._instrument_ids.get(
            symbol)
        if not instrument_id:
            instrument_id = InstrumentId(Symbol(symbol), BINANCE_VENUE)
            self._instrument_ids[symbol] = instrument_id

        # Parse client order ID
        client_order_id_str: str = data["c"]
        if not client_order_id_str or not client_order_id_str.startswith("O"):
            client_order_id_str = data["C"]
        client_order_id = ClientOrderId(client_order_id_str)

        # Fetch strategy ID
        strategy_id: StrategyId = self._cache.strategy_id_for_order(
            client_order_id)
        if strategy_id is None:
            # TODO(cs): Implement external order handling
            self._log.error(
                f"Cannot handle execution report: "
                f"strategy ID for {client_order_id} not found.", )
            return

        venue_order_id = VenueOrderId(str(data["i"]))
        order_type_str: str = data["o"]
        ts_event: int = millis_to_nanos(data["E"])

        if execution_type == "NEW":
            self.generate_order_accepted(
                strategy_id=strategy_id,
                instrument_id=instrument_id,
                client_order_id=client_order_id,
                venue_order_id=venue_order_id,
                ts_event=ts_event,
            )
        elif execution_type == "TRADE":
            instrument: Instrument = self._instrument_provider.find(
                instrument_id=instrument_id)

            # Determine commission
            commission_asset: str = data["N"]
            commission_amount: str = data["n"]
            if commission_asset is not None:
                commission = Money.from_str(
                    f"{commission_amount} {commission_asset}")
            else:
                # Binance typically charges commission as base asset or BNB
                commission = Money(0, instrument.base_currency)

            self.generate_order_filled(
                strategy_id=strategy_id,
                instrument_id=instrument_id,
                client_order_id=client_order_id,
                venue_order_id=venue_order_id,
                venue_position_id=None,  # NETTING accounts
                execution_id=ExecutionId(str(data["t"])),  # Trade ID
                order_side=OrderSideParser.from_str_py(data["S"]),
                order_type=parse_order_type(order_type_str),
                last_qty=Quantity.from_str(data["l"]),
                last_px=Price.from_str(data["L"]),
                quote_currency=instrument.quote_currency,
                commission=commission,
                liquidity_side=LiquiditySide.MAKER
                if data["m"] else LiquiditySide.TAKER,
                ts_event=ts_event,
            )
        elif execution_type == "CANCELED" or execution_type == "EXPIRED":
            self.generate_order_canceled(
                strategy_id=strategy_id,
                instrument_id=instrument_id,
                client_order_id=client_order_id,
                venue_order_id=venue_order_id,
                ts_event=ts_event,
            )