Example #1
0
    def test_expire_items(self):
        # Arrange
        instance = WindowedMinMaxPrices(timedelta(minutes=5))

        # Act
        instance.add_price(
            datetime(2020, 1, 1, 0, 0, 0, tzinfo=pytz.utc),
            Price.from_str("1.0"),
        )
        # 5 min later (still in the window)
        instance.add_price(
            datetime(2020, 1, 1, 0, 5, 0, tzinfo=pytz.utc),
            Price.from_str("0.9"),
        )
        # Allow the first item to expire out
        # This also tests that the new tick is the new min/max
        instance.add_price(
            datetime(2020, 1, 1, 0, 5, 1, tzinfo=pytz.utc),
            Price.from_str("0.95"),
        )

        # Assert
        assert instance.min_price == Price.from_str("0.95")
        assert instance.max_price == Price.from_str("0.95")
Example #2
0
    def test_calculate_margin_init_with_no_leverage_for_inverse(
            self, inverse_as_quote, expected):
        # Arrange
        account = TestStubs.margin_account()
        instrument = TestInstrumentProvider.xbtusd_bitmex()

        result = account.calculate_margin_init(
            instrument=instrument,
            quantity=Quantity.from_int(100000),
            price=Price.from_str("11493.60"),
            inverse_as_quote=inverse_as_quote,
        )

        # Assert
        assert result == expected
    def ethusd_bitmex() -> CryptoPerpetual:
        """
        Return the BitMEX ETH/USD perpetual swap contract for backtesting.

        Returns
        -------
        CryptoPerpetual

        """
        return CryptoPerpetual(
            instrument_id=InstrumentId(
                symbol=Symbol("ETH/USD"),
                venue=Venue("BITMEX"),
            ),
            native_symbol=Symbol("ETHUSD"),
            base_currency=ETH,
            quote_currency=USD,
            settlement_currency=BTC,
            is_inverse=True,
            price_precision=2,
            size_precision=0,
            price_increment=Price.from_str("0.05"),
            size_increment=Quantity.from_int(1),
            max_quantity=Quantity.from_int(10000000),
            min_quantity=Quantity.from_int(1),
            max_notional=None,
            min_notional=None,
            max_price=Price.from_str("1000000.00"),
            min_price=Price.from_str("0.05"),
            margin_init=Decimal("0.02"),
            margin_maint=Decimal("0.007"),
            maker_fee=Decimal("-0.00025"),
            taker_fee=Decimal("0.00075"),
            ts_event=0,
            ts_init=0,
        )
    def test_apply_order_updated_event_to_stop_order(self):
        # Arrange
        order = self.order_factory.stop_market(
            AUDUSD_SIM.id,
            OrderSide.BUY,
            Quantity.from_int(100000),
            Price.from_str("1.00000"),
        )

        order.apply(TestStubs.event_order_submitted(order))
        order.apply(TestStubs.event_order_accepted(order))
        order.apply(TestStubs.event_order_pending_update(order))

        updated = OrderUpdated(
            self.account_id,
            order.client_order_id,
            VenueOrderId("1"),
            Quantity.from_int(120000),
            Price.from_str("1.00001"),
            None,
            0,
            uuid4(),
            0,
        )

        # Act
        order.apply(updated)

        # Assert
        self.assertEqual(OrderState.ACCEPTED, order.state)
        self.assertEqual(VenueOrderId("1"), order.venue_order_id)
        self.assertEqual(Quantity.from_int(120000), order.quantity)
        self.assertEqual(Price.from_str("1.00001"), order.price)
        self.assertTrue(order.is_working)
        self.assertFalse(order.is_completed)
        self.assertEqual(5, order.event_count)
    def xbtusd_bitmex() -> CryptoPerpetual:
        """
        Return the BitMEX XBT/USD perpetual contract for backtesting.

        Returns
        -------
        CryptoPerpetual

        """
        return CryptoPerpetual(
            instrument_id=InstrumentId(
                symbol=Symbol("BTC/USD"),
                venue=Venue("BITMEX"),
            ),
            native_symbol=Symbol("XBTUSD"),
            base_currency=BTC,
            quote_currency=USD,
            settlement_currency=BTC,
            is_inverse=True,
            price_precision=1,
            size_precision=0,
            price_increment=Price.from_str("0.5"),
            size_increment=Quantity.from_int(1),
            max_quantity=None,
            min_quantity=None,
            max_notional=Money(10_000_000.00, USD),
            min_notional=Money(1.00, USD),
            max_price=Price.from_str("1000000.0"),
            min_price=Price(0.5, precision=1),
            margin_init=Decimal("0.01"),
            margin_maint=Decimal("0.0035"),
            maker_fee=Decimal("-0.00025"),
            taker_fee=Decimal("0.00075"),
            ts_event=0,
            ts_init=0,
        )
    def ethusdt_perp_binance() -> CryptoPerpetual:
        """
        Return the Binance ETHUSDT-PERP instrument for backtesting.

        Returns
        -------
        CryptoPerpetual

        """
        return CryptoPerpetual(
            instrument_id=InstrumentId(
                symbol=Symbol("ETHUSDT-PERP"),
                venue=Venue("BINANCE"),
            ),
            native_symbol=Symbol("ETHUSDT"),
            base_currency=ETH,
            quote_currency=USDT,
            settlement_currency=USDT,
            is_inverse=False,
            price_precision=2,
            size_precision=3,
            price_increment=Price.from_str("0.01"),
            size_increment=Quantity.from_str("0.001"),
            max_quantity=Quantity.from_str("10000.000"),
            min_quantity=Quantity.from_str("0.001"),
            max_notional=None,
            min_notional=Money(10.00, USDT),
            max_price=Price.from_str("152588.43"),
            min_price=Price.from_str("29.91"),
            margin_init=Decimal("1.00"),
            margin_maint=Decimal("0.35"),
            maker_fee=Decimal("0.0002"),
            taker_fee=Decimal("0.0004"),
            ts_event=1646199312128000000,
            ts_init=1646199342953849862,
        )
Example #7
0
 def trade_tick_5decimal(
     instrument_id=None,
     price=None,
     aggressor_side=None,
     quantity=None,
 ) -> TradeTick:
     return TradeTick(
         instrument_id=instrument_id or TestStubs.audusd_id(),
         price=price or Price.from_str("1.00001"),
         size=quantity or Quantity.from_int(100000),
         aggressor_side=aggressor_side or AggressorSide.BUY,
         trade_id="123456",
         ts_event=0,
         ts_init=0,
     )
    def test_submit_bracket_order_when_instrument_not_in_cache_then_denies(
            self):
        # Arrange
        self.exec_engine.start()

        strategy = TradingStrategy()
        strategy.register(
            trader_id=self.trader_id,
            portfolio=self.portfolio,
            msgbus=self.msgbus,
            cache=self.cache,
            clock=self.clock,
            logger=self.logger,
        )

        bracket = strategy.order_factory.bracket_market(
            GBPUSD_SIM.id,
            OrderSide.BUY,
            Quantity.from_int(100000),
            stop_loss=Price.from_str("1.00000"),
            take_profit=Price.from_str("1.00010"),
        )

        submit_bracket = SubmitOrderList(
            self.trader_id,
            strategy.id,
            bracket,
            self.uuid_factory.generate(),
            self.clock.timestamp_ns(),
        )

        # Act
        self.risk_engine.execute(submit_bracket)

        # Assert
        assert self.exec_engine.command_count == 0  # <-- command never reaches engine
Example #9
0
def price_to_probability(price: str) -> Price:
    PyCondition.type(price, str, "price", "str")
    PyCondition.positive(float(price), "price")
    price = Price.from_str(price)
    if price in BETFAIR_PRICE_TO_PROBABILITY_MAP:
        return BETFAIR_PRICE_TO_PROBABILITY_MAP[price]
    else:
        # This is likely a trade tick that has been currency adjusted, simply return the nearest price
        value = Price.from_int(1) / price
        bid = BETFAIR_TICK_SCHEME.next_bid_price(value=value)
        ask = BETFAIR_TICK_SCHEME.next_ask_price(value=value)
        if abs(bid - value) < abs(ask - value):
            return bid
        else:
            return ask
    def test_submit_bracket_with_default_settings_sends_to_client(self):
        # Arrange
        self.exec_engine.start()

        strategy = TradingStrategy()
        strategy.register(
            trader_id=self.trader_id,
            portfolio=self.portfolio,
            msgbus=self.msgbus,
            cache=self.cache,
            clock=self.clock,
            logger=self.logger,
        )

        bracket = strategy.order_factory.bracket_market(
            AUDUSD_SIM.id,
            OrderSide.BUY,
            Quantity.from_int(100000),
            stop_loss=Price.from_str("1.00000"),
            take_profit=Price.from_str("1.00010"),
        )

        submit_bracket = SubmitOrderList(
            self.trader_id,
            strategy.id,
            bracket,
            self.uuid_factory.generate(),
            self.clock.timestamp_ns(),
        )

        # Act
        self.risk_engine.execute(submit_bracket)

        # Assert
        assert self.exec_engine.command_count == 1
        assert self.exec_client.calls == ["_start", "submit_order_list"]
Example #11
0
    def from_dict(values: Dict[str, Any]) -> "FTXTicker":
        """
        Return an `FTX` ticker parsed from the given values.

        Parameters
        ----------
        values : dict[str, Any]
            The values for initialization.

        Returns
        -------
        FTXTicker

        """
        return FTXTicker(
            instrument_id=InstrumentId.from_str(values["instrument_id"]),
            bid=Price.from_str(values["bid"]),
            ask=Price.from_str(values["ask"]),
            bid_size=Quantity.from_str(values["bid_size"]),
            ask_size=Quantity.from_str(values["ask_size"]),
            last=Price.from_str(values["last"]),
            ts_event=values["ts_event"],
            ts_init=values["ts_init"],
        )
    def test_apply_order_triggered_event(self):
        # Arrange
        order = self.order_factory.stop_limit(
            AUDUSD_SIM.id,
            OrderSide.BUY,
            Quantity.from_int(100000),
            Price.from_str("1.00000"),
            Price.from_str("0.99990"),
            TimeInForce.GTD,
            expire_time=UNIX_EPOCH,
        )

        order.apply(TestStubs.event_order_submitted(order))
        order.apply(TestStubs.event_order_accepted(order))

        # Act
        order.apply(TestStubs.event_order_triggered(order))

        # Assert
        assert order.status == OrderStatus.TRIGGERED
        assert order.is_active
        assert not order.is_inflight
        assert order.is_working
        assert not order.is_completed
    def test_calculate_unrealized_pnl_for_short(self):
        # Arrange
        order = self.order_factory.market(
            BTCUSDT_BINANCE.id,
            OrderSide.SELL,
            Quantity.from_str("5.912000"),
        )

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

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

        pnl = position.unrealized_pnl(Price.from_str("10407.15"))

        # Assert
        self.assertEqual(Money(582.03640000, USDT), pnl)
        self.assertEqual(Money(-62.10910720, USDT), position.realized_pnl)
        self.assertEqual([Money(62.10910720, USDT)], position.commissions())
    def test_handle_quote_tick_when_count_below_threshold_updates(self):
        # Arrange
        bar_store = ObjectStorer()
        handler = bar_store.store
        instrument_id = TestStubs.audusd_id()
        bar_spec = BarSpecification(3, BarAggregation.TICK, PriceType.MID)
        bar_type = BarType(instrument_id, bar_spec)
        aggregator = TickBarAggregator(bar_type, handler, Logger(TestClock()))

        tick1 = QuoteTick(
            instrument_id=AUDUSD_SIM.id,
            bid=Price.from_str("1.00001"),
            ask=Price.from_str("1.00004"),
            bid_size=Quantity.from_int(1),
            ask_size=Quantity.from_int(1),
            timestamp_origin_ns=0,
            timestamp_ns=0,
        )

        # Act
        aggregator.handle_quote_tick(tick1)

        # Assert
        self.assertEqual(0, len(bar_store.get_store()))
    def test_calculate_margin_maint_with_no_leverage(self):
        # Arrange
        account = TestExecStubs.margin_account()
        instrument = TestInstrumentProvider.xbtusd_bitmex()

        # Act
        result = account.calculate_margin_maint(
            instrument=instrument,
            side=PositionSide.LONG,
            quantity=Quantity.from_int(100000),
            avg_open_px=Price.from_str("11493.60"),
        )

        # Assert
        assert result == Money(0.03697710, BTC)
    def test_submit_order_when_invalid_trigger_price_then_denies(self):
        # Arrange
        self.exec_engine.start()

        strategy = TradingStrategy()
        strategy.register(
            trader_id=self.trader_id,
            portfolio=self.portfolio,
            msgbus=self.msgbus,
            cache=self.cache,
            clock=self.clock,
            logger=self.logger,
        )

        order = strategy.order_factory.stop_limit(
            AUDUSD_SIM.id,
            OrderSide.BUY,
            Quantity.from_int(100000),
            Price.from_str("1.00000"),
            Price.from_str("0.999999999999999"),  # <- invalid trigger
        )

        submit_order = SubmitOrder(
            self.trader_id,
            strategy.id,
            None,
            order,
            self.uuid_factory.generate(),
            self.clock.timestamp_ns(),
        )

        # Act
        self.risk_engine.execute(submit_order)

        # Assert
        assert self.exec_engine.command_count == 0  # <-- command never reaches engine
Example #17
0
    def test_process_trade_tick_when_subscribers_then_sends_to_registered_handlers(
        self,
    ):
        # Arrange
        self.data_engine.register_client(self.binance_client)
        self.binance_client.connect()

        handler1 = []
        subscribe1 = Subscribe(
            client_id=ClientId(BINANCE.value),
            data_type=DataType(
                TradeTick, metadata={"InstrumentId": ETHUSDT_BINANCE.id}
            ),
            handler=handler1.append,
            command_id=self.uuid_factory.generate(),
            timestamp_ns=self.clock.timestamp_ns(),
        )

        handler2 = []
        subscribe2 = Subscribe(
            client_id=ClientId(BINANCE.value),
            data_type=DataType(
                TradeTick, metadata={"InstrumentId": ETHUSDT_BINANCE.id}
            ),
            handler=handler2.append,
            command_id=self.uuid_factory.generate(),
            timestamp_ns=self.clock.timestamp_ns(),
        )

        self.data_engine.execute(subscribe1)
        self.data_engine.execute(subscribe2)

        tick = TradeTick(
            ETHUSDT_BINANCE.id,
            Price.from_str("1050.00000"),
            Quantity.from_int(100),
            AggressorSide.BUY,
            TradeMatchId("123456789"),
            0,
            0,
        )

        # Act
        self.data_engine.process(tick)

        # Assert
        self.assertEqual([tick], handler1)
        self.assertEqual([tick], handler2)
Example #18
0
    async def test_trailing_stop_market_order(self, mocker):
        # Arrange
        mock_send_request = mocker.patch(
            target=
            "nautilus_trader.adapters.binance.http.client.BinanceHttpClient.send_request"
        )

        order = self.strategy.order_factory.trailing_stop_market(
            instrument_id=ETHUSDT_PERP_BINANCE.id,
            order_side=OrderSide.SELL,
            quantity=Quantity.from_int(10),
            trailing_offset=Decimal(100),
            offset_type=TrailingOffsetType.BASIS_POINTS,
            trigger_price=Price.from_str("10000.00"),
            trigger_type=TriggerType.MARK,
            reduce_only=True,
        )
        self.cache.add_order(order, None)

        submit_order = SubmitOrder(
            trader_id=self.trader_id,
            strategy_id=self.strategy.id,
            position_id=None,
            order=order,
            command_id=UUID4(),
            ts_init=0,
        )

        # Act
        self.exec_client.submit_order(submit_order)
        await asyncio.sleep(0.3)

        # Assert
        request = mock_send_request.call_args[0]
        assert request[0] == "POST"
        assert request[1] == "/fapi/v1/order"
        assert request[2]["symbol"] == "ETHUSDT"  # -PERP was stripped
        assert request[2]["side"] == "SELL"
        assert request[2]["type"] == "TRAILING_STOP_MARKET"
        assert request[2]["timeInForce"] == "GTC"
        assert request[2]["quantity"] == "10"
        assert request[2]["reduceOnly"] == "true"
        assert request[2]["newClientOrderId"] is not None
        assert request[2]["activationPrice"] == "10000.00"
        assert request[2]["callbackRate"] == "1"
        assert request[2]["workingType"] == "MARK_PRICE"
        assert request[2]["recvWindow"] == "5000"
        assert request[2]["signature"] is not None
Example #19
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)]
Example #20
0
    def test_hash_str_and_repr(self):
        # Arrange
        tick = TradeTick(
            instrument_id=AUDUSD_SIM.id,
            price=Price.from_str("1.00000"),
            size=Quantity.from_int(50000),
            aggressor_side=AggressorSide.BUY,
            trade_id=TradeId("123456789"),
            ts_event=0,
            ts_init=0,
        )

        # Act, Assert
        assert isinstance(hash(tick), int)
        assert str(tick) == "AUD/USD.SIM,1.00000,50000,BUY,123456789,0"
        assert repr(tick) == "TradeTick(AUD/USD.SIM,1.00000,50000,BUY,123456789,0)"
    def test_calculate_margin_maint_with_leverage_inverse_instrument(self):
        # Arrange
        account = TestExecStubs.margin_account()
        instrument = TestInstrumentProvider.xbtusd_bitmex()
        account.set_default_leverage(Decimal(10))

        # Act
        result = account.calculate_margin_maint(
            instrument=instrument,
            side=PositionSide.LONG,
            quantity=Quantity.from_int(100000),
            avg_open_px=Price.from_str("100000.00"),
        )

        # Assert
        assert result == Money(0.00042500, BTC)
    def test_calculate_margin_maint_with_leverage_fx_instrument(self):
        # Arrange
        account = TestExecStubs.margin_account()
        instrument = TestInstrumentProvider.default_fx_ccy("AUD/USD")
        account.set_default_leverage(Decimal(50))

        # Act
        result = account.calculate_margin_maint(
            instrument=instrument,
            side=PositionSide.LONG,
            quantity=Quantity.from_int(1_000_000),
            avg_open_px=Price.from_str("1.00000"),
        )

        # Assert
        assert result == Money(600.40, USD)
Example #23
0
    def test_hash_str_and_repr(self):
        # Arrange
        tick = TradeTick(
            AUDUSD_SIM.id,
            Price.from_str("1.00000"),
            Quantity.from_int(50000),
            AggressorSide.BUY,
            "123456789",
            0,
            0,
        )

        # Act, Assert
        assert isinstance(hash(tick), int)
        assert str(tick) == "AUD/USD.SIM,1.00000,50000,BUY,123456789,0"
        assert repr(tick) == "TradeTick(AUD/USD.SIM,1.00000,50000,BUY,123456789,0)"
    def test_load_order_when_stop_market_order_in_database_returns_order(self):
        # Arrange
        order = self.strategy.order_factory.stop_market(
            AUDUSD_SIM.id,
            OrderSide.BUY,
            Quantity.from_int(100000),
            Price.from_str("1.00000"),
        )

        self.database.add_order(order)

        # Act
        result = self.database.load_order(order.client_order_id)

        # Assert
        assert result == order
Example #25
0
 def es_future():
     return Future(
         instrument_id=InstrumentId(symbol=Symbol("ESZ21"),
                                    venue=Venue("CME")),
         local_symbol=Symbol("ESZ21"),
         asset_class=AssetClass.INDEX,
         currency=USD,
         price_precision=2,
         price_increment=Price.from_str("0.01"),
         multiplier=Quantity.from_int(1),
         lot_size=Quantity.from_int(1),
         underlying="ES",
         expiry_date=datetime.date(2021, 12, 17),
         ts_event=0,
         ts_init=0,
     )
    def test_update_order_for_submitted_order(self):
        # Arrange
        order = self.strategy.order_factory.stop_market(
            AUDUSD_SIM.id,
            OrderSide.BUY,
            Quantity.from_int(100000),
            Price.from_str("1.00000"),
        )

        position_id = PositionId("P-1")
        self.cache.add_order(order, position_id)

        order.apply(TestEventStubs.order_submitted(order))

        # Act
        self.cache.update_order(order)

        # Assert
        assert self.cache.order_exists(order.client_order_id)
        assert order.client_order_id in self.cache.client_order_ids()
        assert order in self.cache.orders()
        assert order in self.cache.orders_inflight()
        assert order in self.cache.orders_inflight(
            instrument_id=order.instrument_id)
        assert order in self.cache.orders_inflight(
            strategy_id=self.strategy.id)
        assert order in self.cache.orders_inflight(
            instrument_id=order.instrument_id, strategy_id=self.strategy.id)
        assert order not in self.cache.orders_open()
        assert order not in self.cache.orders_open(
            instrument_id=order.instrument_id)
        assert order not in self.cache.orders_open(
            strategy_id=self.strategy.id)
        assert order not in self.cache.orders_open(
            instrument_id=order.instrument_id, strategy_id=self.strategy.id)
        assert order not in self.cache.orders_closed()
        assert order not in self.cache.orders_closed(
            instrument_id=order.instrument_id)
        assert order not in self.cache.orders_closed(
            strategy_id=self.strategy.id)
        assert order not in self.cache.orders_closed(
            instrument_id=order.instrument_id, strategy_id=self.strategy.id)

        assert self.cache.orders_open_count() == 0
        assert self.cache.orders_closed_count() == 0
        assert self.cache.orders_inflight_count() == 1
        assert self.cache.orders_total_count() == 1
    def test_update_position_for_open_position(self):
        # Arrange
        order1 = self.strategy.order_factory.market(
            AUDUSD_SIM.id,
            OrderSide.BUY,
            Quantity.from_int(100000),
        )

        position_id = PositionId("P-1")
        self.cache.add_order(order1, position_id)
        order1.apply(TestStubs.event_order_submitted(order1))
        self.cache.update_order(order1)

        order1.apply(TestStubs.event_order_accepted(order1))
        self.cache.update_order(order1)
        fill1 = TestStubs.event_order_filled(
            order1,
            instrument=AUDUSD_SIM,
            position_id=PositionId("P-1"),
            last_px=Price.from_str("1.00001"),
        )

        position = Position(instrument=AUDUSD_SIM, fill=fill1)

        # Act
        self.cache.add_position(position, OMSType.HEDGING)

        # Assert
        assert self.cache.position_exists(position.id)
        assert position.id in self.cache.position_ids()
        assert position in self.cache.positions()
        assert position in self.cache.positions_open()
        assert position in self.cache.positions_open(instrument_id=position.instrument_id)
        assert position in self.cache.positions_open(strategy_id=self.strategy.id)
        assert position in self.cache.positions_open(
            instrument_id=position.instrument_id, strategy_id=self.strategy.id
        )
        assert position not in self.cache.positions_closed()
        assert position not in self.cache.positions_closed(instrument_id=position.instrument_id)
        assert position not in self.cache.positions_closed(strategy_id=self.strategy.id)
        assert position not in self.cache.positions_closed(
            instrument_id=position.instrument_id, strategy_id=self.strategy.id
        )
        assert self.cache.position(position_id) == position
        assert self.cache.positions_open_count() == 1
        assert self.cache.positions_closed_count() == 0
        assert self.cache.positions_total_count() == 1
Example #28
0
    def make_order(engine: MockLiveExecutionEngine) -> LimitOrder:
        strategy = TradingStrategy(order_id_tag="001")
        strategy.register_trader(
            TraderId("TESTER-000"),
            BetfairTestStubs.clock(),
            BetfairTestStubs.logger(),
        )

        engine.register_strategy(strategy)

        order = strategy.order_factory.limit(
            BetfairTestStubs.instrument_id(),
            OrderSide.BUY,
            Quantity.from_int(10),
            Price.from_str("0.50"),
        )
        return order
Example #29
0
def test_duplicate_trades(betfair_data_client):
    messages = []
    for update in BetfairTestStubs.raw_market_updates(market="1.180305278",
                                                      runner1="2696769",
                                                      runner2="4297085"):
        messages.extend(
            on_market_update(
                instrument_provider=betfair_data_client.instrument_provider(),
                update=update,
            ))
        if update["pt"] >= 1615222877785:
            break
    trades = [
        m for m in messages
        if isinstance(m, TradeTick) and m.price == Price.from_str("0.69930")
    ]
    assert len(trades) == 5
    def test_limit_order_to_dict(self):
        # Arrange
        order = self.order_factory.limit(
            AUDUSD_SIM.id,
            OrderSide.BUY,
            Quantity.from_int(100000),
            Price.from_str("1.00000"),
            display_qty=Quantity.from_int(20000),
        )

        # Act
        result = order.to_dict()

        # Assert
        assert result == {
            "trader_id": "TESTER-000",
            "strategy_id": "S-001",
            "instrument_id": "AUD/USD.SIM",
            "client_order_id": "O-19700101-000000-000-001-1",
            "venue_order_id": None,
            "position_id": None,
            "account_id": None,
            "execution_id": None,
            "type": "LIMIT",
            "side": "BUY",
            "quantity": "100000",
            "price": "1.00000",
            "liquidity_side": "NONE",
            "expire_time_ns": 0,
            "time_in_force": "GTC",
            "filled_qty": "0",
            "avg_px": None,
            "slippage": "0",
            "status": "INITIALIZED",
            "is_post_only": False,
            "is_reduce_only": False,
            "display_qty": "20000",
            "order_list_id": None,
            "parent_order_id": None,
            "child_order_ids": None,
            "contingency": "NONE",
            "contingency_ids": None,
            "tags": None,
            "ts_last": 0,
            "ts_init": 0,
        }