Ejemplo n.º 1
0
    def test_order_amended(self):
        # Arrange
        uuid = uuid4()
        event = OrderAmended(
            account_id=AccountId("SIM", "000"),
            cl_ord_id=ClientOrderId("O-2020872378423"),
            order_id=OrderId("123456"),
            quantity=Quantity(500000),
            price=Price('1.95000'),
            amended_time=UNIX_EPOCH,
            event_id=uuid,
            event_timestamp=UNIX_EPOCH,
        )

        # Act
        self.assertEqual(
            f"OrderAmended(account_id=SIM-000, cl_order_id=O-2020872378423, "
            f"order_id=123456, qty=500,000, price=1.95000, id={uuid})",
            str(event))
        self.assertEqual(
            f"OrderAmended(account_id=SIM-000, cl_order_id=O-2020872378423, "
            f"order_id=123456, qty=500,000, price=1.95000, id={uuid})",
            repr(event))
    def test_can_submit_order(self):
        # Arrange
        strategy = TradingStrategy(order_id_tag='001')
        strategy.change_clock(self.clock)

        self.exec_engine.register_strategy(strategy)

        position_id = strategy.position_id_generator.generate()
        order = strategy.order_factory.market(AUDUSD_FXCM, OrderSide.BUY,
                                              Quantity(100000))

        submit_order = SubmitOrder(self.trader_id, self.account_id,
                                   strategy.id, position_id, order,
                                   self.guid_factory.generate(),
                                   self.clock.time_now())

        # Act
        self.exec_engine.execute_command(submit_order)

        # Assert
        self.assertIn(submit_order, self.exec_client.received_commands)
        self.assertTrue(self.exec_db.order_exists(order.id))
        self.assertEqual(position_id, self.exec_db.get_position_id(order.id))
Ejemplo n.º 3
0
    def test_pack_and_unpack_stop_limit_orders_with_expire_time(self):
        # Arrange
        order = StopLimitOrder(
            self.trader_id,
            self.strategy_id,
            AUDUSD_SIM.id,
            ClientOrderId("O-123456"),
            OrderSide.BUY,
            Quantity(100000, precision=0),
            price=Price(1.00000, precision=5),
            trigger=Price(1.00010, precision=5),
            time_in_force=TimeInForce.GTD,
            expire_time=UNIX_EPOCH,
            init_id=UUID4(),
            ts_init=0,
        )

        # Act
        packed = OrderInitialized.to_dict(order.last_event)
        unpacked = self.unpacker.unpack(packed)

        # Assert
        assert unpacked == order
Ejemplo n.º 4
0
    def test_serialize_and_deserialize_order_amended_events(self):
        # Arrange
        event = OrderUpdated(
            self.trader_id,
            self.strategy_id,
            self.account_id,
            AUDUSD_SIM.id,
            ClientOrderId("O-123456"),
            VenueOrderId("1"),
            Quantity(100000, precision=0),
            Price(0.80010, precision=5),
            Price(0.80050, precision=5),
            UUID4(),
            0,
            0,
        )

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

        # Assert
        assert deserialized == event
    def test_order_serializer_methods_raise_not_implemented_error(self):
        # Arrange
        order_factory = OrderFactory(
            trader_id=TraderId("TESTER", "000"),
            strategy_id=StrategyId("S", "001"),
            clock=TestClock(),
        )

        order = order_factory.market(
            AUDUSD_SIM.id,
            OrderSide.BUY,
            Quantity(100000),
        )

        serializer = OrderSerializer()

        # Act
        # Assert
        with pytest.raises(NotImplementedError):
            serializer.serialize(order)

        with pytest.raises(NotImplementedError):
            serializer.deserialize(bytes())
    def test_cancel_order_when_not_connected_logs_and_does_not_send(self):
        # Arrange
        order = self.order_factory.market(
            ETHUSDT_BINANCE.symbol,
            OrderSide.BUY,
            Quantity(100),
        )

        command = CancelOrder(
            BINANCE,
            self.trader_id,
            self.account_id,
            order.cl_ord_id,
            order.id,
            self.uuid_factory.generate(),
            self.clock.utc_now(),
        )

        # Act
        self.exec_client.cancel_order(command)

        # Assert
        self.assertTrue(True)  # No exceptions raised
    def test_apply_order_invalid_event(self):
        # Arrange
        order = self.order_factory.market(
            AUDUSD_SIM.id,
            OrderSide.BUY,
            Quantity.from_int(100000),
        )

        invalid = OrderInvalid(
            order.client_order_id,
            "SOME_REASON",
            uuid4(),
            0,
        )

        # Act
        order.apply(invalid)

        # Assert
        self.assertEqual(OrderState.INVALID, order.state)
        self.assertEqual(2, order.event_count)
        self.assertEqual(invalid, order.last_event)
        self.assertTrue(order.is_completed)
Ejemplo n.º 8
0
    def test_apply_order_denied_event(self):
        # Arrange
        order = self.order_factory.market(
            AUDUSD_SIM.id,
            OrderSide.BUY,
            Quantity(100000),
        )

        denied = OrderDenied(
            order.cl_ord_id,
            "SOME_REASON",
            uuid4(),
            UNIX_EPOCH,
        )

        # Act
        order.apply(denied)

        # Assert
        self.assertEqual(OrderState.DENIED, order.state)
        self.assertEqual(2, order.event_count)
        self.assertEqual(denied, order.last_event)
        self.assertTrue(order.is_completed)
Ejemplo n.º 9
0
    def test_limit_buy_post_only_reduce_only_order(self):
        # Arrange
        order = self.order_factory.limit(
            symbol=BTCUSDT,
            order_side=OrderSide.BUY,
            quantity=Quantity("1.0"),
            price=Price("50000"),
            post_only=True,
            reduce_only=True,
        )

        # Act
        result = self.builder.build_py(order)

        # Assert
        expected_args = ['BTC/USDT', 'Limit', 'Buy', '1.0', '50000']
        expected_custom_params = {
            'clOrdID': 'O-19700101-000000-000-001-1',
            'execInst': 'ParticipateDoNotInitiate,ReduceOnly',
            'timeInForce': 'GoodTillCancel'
        }
        self.assertTrue(order.is_post_only)
        self.assertEqual((expected_args, expected_custom_params), result)
Ejemplo n.º 10
0
    def test_passive_post_only_insert(self):
        # Arrange: Prepare market
        self.cache.add_instrument(USDJPY_SIM)
        # Market is 10 @ 15
        snapshot = TestStubs.order_book_snapshot(instrument_id=USDJPY_SIM.id,
                                                 bid_volume=1000,
                                                 ask_volume=1000)
        self.data_engine.process(snapshot)
        self.exchange.process_order_book(snapshot)

        # Act
        order = self.strategy.order_factory.limit(
            instrument_id=USDJPY_SIM.id,
            order_side=OrderSide.SELL,
            quantity=Quantity.from_int(2000),
            price=Price.from_str("14"),
            post_only=True,
        )
        self.strategy.submit_order(order)
        self.exchange.process(0)

        # Assert
        assert order.status == OrderStatus.ACCEPTED
Ejemplo n.º 11
0
    def test_hash_str_repr(self):
        # Arrange
        bar = Bar(
            AUDUSD_1_MIN_BID,
            Price.from_str("1.00001"),
            Price.from_str("1.00004"),
            Price.from_str("1.00002"),
            Price.from_str("1.00003"),
            Quantity.from_int(100000),
            0,
            0,
        )

        # Act, Assert
        assert isinstance(hash(bar), int)
        assert (
            str(bar) ==
            "AUD/USD.SIM-1-MINUTE-BID-EXTERNAL,1.00001,1.00004,1.00002,1.00003,100000,0"
        )
        assert (
            repr(bar) ==
            "Bar(AUD/USD.SIM-1-MINUTE-BID-EXTERNAL,1.00001,1.00004,1.00002,1.00003,100000,0)"
        )
    def test_execute_command(self):
        order = self.strategy.order_factory.market(
            BTCUSDT_BINANCE.id,
            OrderSide.BUY,
            Quantity.from_str("1.00000000"),
        )

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

        def execute_command():
            self.exec_engine.execute(command)

        self.benchmark.pedantic(execute_command,
                                iterations=100,
                                rounds=100,
                                warmup_rounds=5)
Ejemplo n.º 13
0
    def test_order_amended(self):
        # Arrange
        uuid = uuid4()
        event = OrderUpdated(
            account_id=AccountId("SIM", "000"),
            client_order_id=ClientOrderId("O-2020872378423"),
            venue_order_id=VenueOrderId("123456"),
            quantity=Quantity.from_int(500000),
            price=Price.from_str("1.95000"),
            updated_ns=0,
            event_id=uuid,
            timestamp_ns=0,
        )

        # Act
        assert (
            f"OrderUpdated(account_id=SIM-000, cl_order_id=O-2020872378423, "
            f"venue_order_id=123456, qty=500_000, price=1.95000, event_id={uuid})"
            == str(event))
        assert (
            f"OrderUpdated(account_id=SIM-000, cl_order_id=O-2020872378423, "
            f"venue_order_id=123456, qty=500_000, price=1.95000, event_id={uuid})"
            == repr(event))
Ejemplo n.º 14
0
    def test_cancel_order_when_not_connected_logs_and_does_not_send(self):
        # Arrange
        order = self.order_factory.market(
            ETHUSDT_BINANCE.id,
            OrderSide.BUY,
            Quantity.from_int(100),
        )

        command = CancelOrder(
            self.trader_id,
            self.order_factory.strategy_id,
            order.instrument_id,
            order.client_order_id,
            order.venue_order_id,
            self.uuid_factory.generate(),
            self.clock.timestamp_ns(),
        )

        # Act
        self.exec_client.cancel_order(command)

        # Assert
        assert True  # No exceptions raised
Ejemplo n.º 15
0
    def test_handle_trade_tick_when_volume_below_threshold_updates(self):
        # Arrange
        bar_store = ObjectStorer()
        handler = bar_store.store
        symbol = TestStubs.symbol_audusd_fxcm()
        bar_spec = BarSpecification(10000, BarAggregation.VOLUME, PriceType.LAST)
        bar_type = BarType(symbol, bar_spec)
        aggregator = VolumeBarAggregator(bar_type, handler, TestLogger(TestClock()))

        tick1 = TradeTick(
            symbol=AUDUSD_SIM.symbol,
            price=Price("1.00001"),
            size=Quantity(1),
            side=OrderSide.BUY,
            match_id=TradeMatchId("123456"),
            timestamp=UNIX_EPOCH,
        )

        # Act
        aggregator.handle_trade_tick(tick1)

        # Assert
        self.assertEqual(0, len(bar_store.get_store()))
Ejemplo n.º 16
0
    def test_handle_trade_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.LAST)
        bar_type = BarType(instrument_id, bar_spec)
        aggregator = TickBarAggregator(bar_type, handler, Logger(TestClock()))

        tick1 = TradeTick(
            instrument_id=AUDUSD_SIM.id,
            price=Price("1.00001"),
            size=Quantity(1),
            aggressor_side=AggressorSide.BUY,
            match_id=TradeMatchId("123456"),
            timestamp_ns=0,
        )

        # Act
        aggregator.handle_trade_tick(tick1)

        # Assert
        self.assertEqual(0, len(bar_store.get_store()))
Ejemplo n.º 17
0
    def trailing_stop_buy(self, last_bar: Bar):
        """
        Users simple trailing stop BUY for (SHORT positions).

        Parameters
        ----------
        last_bar : Bar
            The last bar received.

        """
        # Round price to nearest 0.5 (for XBT/USD)
        price = (round((last_bar.high +
                        (self.atr.value * self.trail_atr_multiple)) * 2) / 2)
        order: StopMarketOrder = self.order_factory.stop_market(
            instrument_id=self.instrument_id,
            order_side=OrderSide.BUY,
            quantity=Quantity(self.trade_size),
            price=Price(price, self.instrument.price_precision),
            reduce_only=True,
        )

        self.trailing_stop = order
        self.submit_order(order)
Ejemplo n.º 18
0
    def test_serialize_and_deserialize_limit_orders_with_expire_time(self):
        # Arrange
        order = LimitOrder(
            ClientOrderId("O-123456"),
            StrategyId("S", "001"),
            AUDUSD_SIM.id,
            OrderSide.BUY,
            Quantity(100000),
            price=Price("1.00000"),
            time_in_force=TimeInForce.GTD,
            expire_time=UNIX_EPOCH,
            init_id=uuid4(),
            timestamp_ns=0,
        )

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

        # Assert
        assert deserialized == order
        print(b64encode(serialized))
        print(order)
Ejemplo n.º 19
0
    def test_can_modify_atomic_order_working_stop_loss(self):
        # Arrange
        strategy = TestStrategy1(bar_type=TestStubs.bartype_usdjpy_1min_bid())
        self.data_client.register_strategy(strategy)
        self.exec_engine.register_strategy(strategy)
        strategy.start()

        self.exec_client.process_tick(TestStubs.tick_3decimal(self.usdjpy.symbol))  # Prepare market
        atomic_order = strategy.order_factory.atomic_market(
            USDJPY_FXCM,
            OrderSide.BUY,
            Quantity(100000),
            Price(85.000, 3))

        strategy.submit_atomic_order(atomic_order, strategy.position_id_generator.generate())

        # Act
        strategy.modify_order(atomic_order.stop_loss, atomic_order.entry.quantity, Price(85.100, 3))

        # Assert
        self.assertEqual(Price(85.100, 3), strategy.order(atomic_order.stop_loss.id).price)
        self.assertEqual(8, strategy.object_storer.count)
        self.assertTrue(isinstance(strategy.object_storer.get_store()[7], OrderModified))
Ejemplo n.º 20
0
    def test_submit_bracket_market_order(self):
        # Arrange
        # Prepare market
        tick = TestStubs.quote_tick_3decimal(USDJPY_SIM.symbol)
        self.data_engine.process(tick)
        self.exchange.process_tick(tick)

        entry_order = self.strategy.order_factory.market(
            USDJPY_SIM.symbol,
            OrderSide.BUY,
            Quantity(100000),
        )

        bracket_order = self.strategy.order_factory.bracket(
            entry_order,
            Price("80.000"),
        )

        # Act
        self.strategy.submit_bracket_order(bracket_order)

        # Assert
        self.assertEqual(OrderState.FILLED, entry_order.state)
Ejemplo n.º 21
0
def parse_bars_http(
    instrument: Instrument,
    bar_type: BarType,
    data: List[Dict[str, Any]],
    ts_event_delta: int,
    ts_init: int,
) -> List[Bar]:
    bars: List[Bar] = []
    for row in data:
        bar: Bar = Bar(
            bar_type=bar_type,
            open=Price(row["open"], instrument.price_precision),
            high=Price(row["high"], instrument.price_precision),
            low=Price(row["low"], instrument.price_precision),
            close=Price(row["close"], instrument.price_precision),
            volume=Quantity(row["volume"], instrument.size_precision),
            check=True,
            ts_event=secs_to_nanos(row["time"]) + ts_event_delta,
            ts_init=ts_init,
        )
        bars.append(bar)

    return bars
Ejemplo n.º 22
0
    def test_order_initialized(self):
        # Arrange
        uuid = uuid4()
        event = OrderInitialized(cl_ord_id=ClientOrderId("O-2020872378423"),
                                 strategy_id=StrategyId("SCALPER", "001"),
                                 symbol=Symbol("BTC/USDT",
                                               Exchange("BINANCE")),
                                 order_side=OrderSide.BUY,
                                 order_type=OrderType.LIMIT,
                                 quantity=Quantity("0.561000"),
                                 time_in_force=TimeInForce.DAY,
                                 event_id=uuid,
                                 event_timestamp=UNIX_EPOCH,
                                 options={"Price": "15200.10"})

        # Act
        # Assert
        self.assertEqual(
            f"OrderInitialized(cl_ord_id=O-2020872378423, id={uuid})",
            str(event))
        self.assertEqual(
            f"OrderInitialized(cl_ord_id=O-2020872378423, id={uuid})",
            repr(event))
    def test_update_order_for_working_order(self):
        # Arrange
        order = self.strategy.order_factory.stop_market(
            AUDUSD_SIM.symbol,
            OrderSide.BUY,
            Quantity(100000),
            Price("1.00000"),
        )

        self.database.add_order(order)

        order.apply(TestStubs.event_order_submitted(order))
        self.database.update_order(order)

        order.apply(TestStubs.event_order_accepted(order))
        self.database.update_order(order)

        # Act
        order.apply(TestStubs.event_order_working(order))
        self.database.update_order(order)

        # Assert
        self.assertEqual(order, self.database.load_order(order.cl_ord_id))
Ejemplo n.º 24
0
    def test_serialize_and_deserialize_amend_order_commands(self):
        # Arrange
        command = ModifyOrder(
            self.trader_id,
            StrategyId("SCALPER-001"),
            AUDUSD_SIM.id,
            ClientOrderId("O-123456"),
            VenueOrderId("001"),
            Quantity(100000, precision=0),
            Price(1.00001, precision=5),
            None,
            UUID4(),
            0,
        )

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

        # Assert
        assert deserialized == command
        print(b64encode(serialized))
        print(command)
    def test_can_update_order_for_working_order(self):
        # Arrange
        order = self.strategy.order_factory.market(AUDUSD_FXCM, OrderSide.BUY,
                                                   Quantity(100000))
        position_id = self.strategy.position_id_generator.generate()
        self.database.add_order(order, self.strategy.id, position_id)

        order_working = TestStubs.event_order_working(order)
        order.apply(order_working)

        # Act
        self.database.update_order(order)

        # Assert
        self.assertTrue(self.database.order_exists(order.id))
        self.assertTrue(order.id in self.database.get_order_ids())
        self.assertTrue(order.id in self.database.get_orders())
        self.assertTrue(
            order.id in self.database.get_orders_working(self.strategy.id))
        self.assertTrue(order.id in self.database.get_orders_working())
        self.assertTrue(order.id not in self.database.get_orders_completed(
            self.strategy.id))
        self.assertTrue(order.id not in self.database.get_orders_completed())
    def test_serialize_and_deserialize_stop_orders_with_expire_time(self):
        # Arrange
        order = StopMarketOrder(
            ClientOrderId("O-123456"),
            StrategyId("S", "001"),
            AUDUSD_SIM.symbol,
            OrderSide.BUY,
            Quantity(100000),
            price=Price("1.00000"),
            time_in_force=TimeInForce.GTD,
            expire_time=UNIX_EPOCH,
            init_id=uuid4(),
            timestamp=UNIX_EPOCH,
        )

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

        # Assert
        self.assertEqual(order, deserialized)
        print(b64encode(serialized))
        print(order)
Ejemplo n.º 27
0
    def test_calculate_pnl_for_inverse2(self):
        # Arrange
        order = self.order_factory.market(
            ETHUSD_BITMEX.id,
            OrderSide.SELL,
            Quantity.from_int(100000),
        )

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

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

        # Act, Assert
        assert position.unrealized_pnl(Price.from_str("370.00")) == Money(
            4.27745208, ETH)
        assert position.notional_value(Price.from_str("370.00")) == Money(
            270.27027027, ETH)
Ejemplo n.º 28
0
    def test_submit_order_when_not_connected_logs_and_does_not_send(self):
        # Arrange
        strategy = TradingStrategy("000")
        order = self.order_factory.market(
            ETHUSDT_BINANCE.id,
            OrderSide.BUY,
            Quantity.from_int(100),
        )

        command = SubmitOrder(
            self.trader_id,
            strategy.id,
            PositionId.null(),
            order,
            self.uuid_factory.generate(),
            self.clock.timestamp_ns(),
        )

        # Act
        self.exec_client.submit_order(command)

        # Assert
        assert order.state == OrderState.INITIALIZED
    def test_submit_order_when_trading_halted_then_denies_order(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.market(
            AUDUSD_SIM.id,
            OrderSide.BUY,
            Quantity.from_int(100000),
        )

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

        # Halt trading
        self.risk_engine.set_trading_state(TradingState.HALTED)

        # Act
        self.risk_engine.execute(submit_order)

        # Assert
        assert self.risk_engine.command_count == 1  # <-- command never reaches engine
    def test_submit_order_when_duplicate_id_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.market(
            AUDUSD_SIM.id,
            OrderSide.BUY,
            Quantity.from_int(100000),
        )

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

        self.risk_engine.execute(submit_order)

        # Act
        self.risk_engine.execute(submit_order)

        # Assert
        assert self.exec_engine.command_count == 1
        assert self.exec_client.calls == ["_start", "submit_order"]