def l1_feed():
     updates = []
     for _, row in TestDataProvider.usdjpy_ticks().iterrows():
         for side, order_side in zip(
             ("bid", "ask"), (OrderSide.BUY, OrderSide.SELL)
         ):
             updates.append(
                 {
                     "op": "update",
                     "order": Order(
                         price=Price(row[side], precision=6),
                         size=Quantity(1e9, precision=2),
                         side=order_side,
                     ),
                 }
             )
     return updates
    def test_add_position(self):
        # Arrange
        order = self.strategy.order_factory.market(
            AUDUSD_SIM.symbol,
            OrderSide.BUY,
            Quantity(100000),
        )

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

        order_filled = TestStubs.event_order_filled(
            order,
            instrument=AUDUSD_SIM,
            position_id=PositionId('P-1'),
            fill_price=Price("1.00000"),
        )

        position = Position(order_filled)

        # Act
        self.cache.add_position(position)

        # Assert
        self.assertTrue(self.cache.position_exists(position.id))
        self.assertIn(position.id, self.cache.position_ids())
        self.assertIn(position, self.cache.positions())
        self.assertIn(position, self.cache.positions_open())
        self.assertIn(position,
                      self.cache.positions_open(symbol=position.symbol))
        self.assertIn(position,
                      self.cache.positions_open(strategy_id=self.strategy.id))
        self.assertIn(
            position,
            self.cache.positions_open(symbol=position.symbol,
                                      strategy_id=self.strategy.id))
        self.assertNotIn(position, self.cache.positions_closed())
        self.assertNotIn(position,
                         self.cache.positions_closed(symbol=position.symbol))
        self.assertNotIn(
            position,
            self.cache.positions_closed(strategy_id=self.strategy.id))
        self.assertNotIn(
            position,
            self.cache.positions_closed(symbol=position.symbol,
                                        strategy_id=self.strategy.id))
    def test_update_order_raises_not_implemented_error(self):
        # Arrange
        # Act
        command = UpdateOrder(
            AUDUSD_SIM.id,
            self.trader_id,
            self.account_id,
            ClientOrderId("O-123456789"),
            Quantity(120000),
            Price("1.00000"),
            self.uuid_factory.generate(),
            self.clock.timestamp_ns(),
        )

        # Assert
        self.assertRaises(NotImplementedError, self.client.update_order,
                          command)
예제 #4
0
 def _on_order_modify(self, trade: IBTrade):
     instrument_id = self._instrument_provider.contract_id_to_instrument_id[trade.contract.conId]
     instrument: Instrument = self._cache.instrument(instrument_id)
     client_order_id = self._venue_order_id_to_client_order_id[trade.order.orderId]
     strategy_id = self._client_order_id_to_strategy_id[client_order_id]
     venue_order_id = VenueOrderId(str(trade.orderStatus.permId))
     self.generate_order_updated(
         strategy_id=strategy_id,
         instrument_id=instrument_id,
         client_order_id=client_order_id,
         venue_order_id=venue_order_id,
         quantity=Quantity(trade.order.totalQuantity, precision=instrument.size_precision),
         price=Price(trade.order.lmtPrice, precision=instrument.price_precision),
         trigger_price=None,
         ts_event=dt_to_unix_nanos(trade.log[-1].time),
         venue_order_id_modified=False,  # TODO - does this happen?
     )
예제 #5
0
    def test_to_serializable_returns_expected_string(self):
        # Arrange
        tick = TradeTick(
            AUDUSD_SIM.id,
            Price.from_str("1.00000"),
            Quantity.from_int(10000),
            AggressorSide.BUY,
            TradeMatchId("123456789"),
            0,
            0,
        )

        # Act
        result = tick.to_serializable_str()

        # Assert
        self.assertEqual("1.00000,10000,BUY,123456789,0,0", result)
예제 #6
0
    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,
        }
예제 #7
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("0.69930", 5)
    ]
    assert len(trades) == 5
    def trailing_stop_sell(self, last_bar: Bar):
        """
        Users simple trailing stop SELL for (LONG positions).
        """
        # Round price to nearest 0.5 (for XBT/USD)
        price = round((last_bar.low -
                       (self.atr.value * self.trail_atr_multiple)) * 2) / 2
        order: StopMarketOrder = self.order_factory.stop_market(
            symbol=self.symbol,
            order_side=OrderSide.SELL,
            quantity=Quantity(self.trade_size),
            price=Price(price, self.instrument.price_precision),
            reduce_only=True,
        )

        self.trailing_stop = order
        self.submit_order(order)
예제 #9
0
    def test_modify_order_raises_not_implemented_error(self):
        # Arrange
        # Act
        command = ModifyOrder(
            self.venue,
            self.trader_id,
            self.account_id,
            ClientOrderId("O-123456789"),
            Quantity(120000),
            Price("1.00000"),
            self.uuid_factory.generate(),
            self.clock.utc_now(),
        )

        # Assert
        self.assertRaises(NotImplementedError, self.client.modify_order,
                          command)
예제 #10
0
    def event_order_filled(
        order,
        instrument,
        position_id=None,
        strategy_id=None,
        fill_price=None,
        fill_qty=None,
        liquidity_side=LiquiditySide.TAKER,
    ) -> OrderFilled:
        if position_id is None:
            position_id = order.position_id
        if strategy_id is None:
            strategy_id = order.strategy_id
        if fill_price is None:
            fill_price = Price("1.00000")
        if fill_qty is None:
            fill_qty = order.quantity

        commission = instrument.calculate_commission(
            quantity=order.quantity,
            avg_price=fill_price,
            liquidity_side=liquidity_side,
        )

        return OrderFilled(
            account_id=TestStubs.account_id(),
            cl_ord_id=order.cl_ord_id,
            order_id=order.id,
            execution_id=ExecutionId(order.cl_ord_id.value.replace("O", "E")),
            position_id=position_id,
            strategy_id=strategy_id,
            symbol=order.symbol,
            order_side=order.side,
            fill_qty=fill_qty,
            cum_qty=Quantity(order.filled_qty + fill_qty),
            leaves_qty=Quantity(
                max(0, order.quantity - order.filled_qty - fill_qty)),
            fill_price=order.price if fill_price is None else fill_price,
            currency=instrument.quote_currency,
            is_inverse=instrument.is_inverse,
            commission=commission,
            liquidity_side=liquidity_side,
            execution_time=UNIX_EPOCH,
            event_id=uuid4(),
            event_timestamp=UNIX_EPOCH,
        )
예제 #11
0
    def test_from_dict_returns_expected_tick(self):
        # Arrange
        tick = TradeTick(
            AUDUSD_SIM.id,
            Price.from_str("1.00000"),
            Quantity.from_int(10000),
            AggressorSide.BUY,
            "123456789",
            0,
            0,
        )

        # Act
        result = TradeTick.from_dict(TradeTick.to_dict(tick))

        # Assert
        assert tick == result
예제 #12
0
    def test_from_dict_returns_expected_tick(self):
        # Arrange
        tick = TradeTick(
            instrument_id=AUDUSD_SIM.id,
            price=Price.from_str("1.00000"),
            size=Quantity.from_int(10000),
            aggressor_side=AggressorSide.BUY,
            trade_id=TradeId("123456789"),
            ts_event=0,
            ts_init=0,
        )

        # Act
        result = TradeTick.from_dict(TradeTick.to_dict(tick))

        # Assert
        assert tick == result
예제 #13
0
    def test_handle_trade_tick_sends_to_data_engine(self):
        # Arrange
        tick = TradeTick(
            AUDUSD_SIM.id,
            Price.from_str("1.00050"),
            Quantity.from_int(1),
            AggressorSide.BUY,
            "123456",
            0,
            0,
        )

        # Act
        self.client._handle_data_py(tick)

        # Assert
        self.assertEqual(1, self.data_engine.data_count)
예제 #14
0
    def test_pack_and_unpack_limit_orders(self):
        # Arrange
        order = self.order_factory.limit(
            AUDUSD_SIM.id,
            OrderSide.BUY,
            Quantity(100000, precision=0),
            Price(1.00000, precision=5),
            TimeInForce.DAY,
            display_qty=Quantity(50000, precision=0),
        )

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

        # Assert
        assert unpacked == order
예제 #15
0
    def test_submit_order_with_no_market_rejects_order(self):
        # Arrange
        order = self.strategy.order_factory.stop_market(
            USDJPY_SIM.symbol,
            OrderSide.BUY,
            Quantity(100000),
            Price("80.000"),
        )

        # Act
        self.strategy.submit_order(order)

        # Assert
        self.assertEqual(2, self.strategy.object_storer.count)
        self.assertTrue(
            isinstance(self.strategy.object_storer.get_store()[1],
                       OrderRejected))
예제 #16
0
    def test_position_to_dict(self):
        # Arrange
        order = self.order_factory.market(
            AUDUSD_SIM.id,
            OrderSide.BUY,
            Quantity.from_int(100000),
        )

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

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

        # Act
        result = position.to_dict()

        # Assert
        assert result == {
            "position_id": "P-123456",
            "account_id": "SIM-000",
            "from_order": "O-19700101-000000-000-001-1",
            "strategy_id": "S-001",
            "instrument_id": "AUD/USD.SIM",
            "entry": "BUY",
            "side": "LONG",
            "net_qty": "100000",
            "quantity": "100000",
            "peak_qty": "100000",
            "ts_opened": 0,
            "ts_closed": 0,
            "duration_ns": 0,
            "avg_px_open": "1.00001",
            "avg_px_close": "None",
            "quote_currency": "USD",
            "base_currency": "AUD",
            "cost_currency": "USD",
            "realized_points": "0",
            "realized_return": "0.00000",
            "realized_pnl": "-2.00 USD",
            "commissions": "['2.00 USD']",
        }
예제 #17
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="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_get_trade_tick(self):
        tick = TradeTick(
            AUDUSD_FXCM,
            Price("1.00000"),
            Quantity(10000),
            Maker.BUYER,
            MatchId("123456789"),
            datetime(2018, 1, 1, 19, 59, 1, 0, pytz.utc),
        )

        self.data_engine.handle_trade_tick(tick)

        # Act
        result = self.strategy.trade_tick(tick.symbol, 0)

        # Assert
        self.assertEqual(tick, result)
예제 #19
0
    def create_buy_order(self, last: QuoteTick):
        """
        A market makers simple buy limit method (example).
        """
        price: Decimal = last.bid - (self.atr.value * self.atr_multiple)
        order: LimitOrder = self.order_factory.limit(
            instrument_id=self.instrument_id,
            order_side=OrderSide.BUY,
            quantity=Quantity(self.trade_size),
            price=Price(price, self.price_precision),
            time_in_force=TimeInForce.GTC,
            post_only=True,  # Default value is True
            hidden=False,  # Default value is False
        )

        self.buy_order = order
        self.submit_order(order)
예제 #20
0
 def test_stop_order_with_gtd_and_expire_time_none_raises_exception(self):
     # Arrange
     # Act
     self.assertRaises(
         TypeError,
         StopMarketOrder,
         ClientOrderId("O-123456"),
         StrategyId("S", "001"),
         AUDUSD_SIM.symbol,
         OrderSide.BUY,
         Quantity(100000),
         price=Price("1.00000"),
         init_id=uuid4(),
         timestamp=UNIX_EPOCH,
         time_in_force=TimeInForce.GTD,
         expire_time=None,
     )
예제 #21
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(10),
            Price("0.50"),
        )
        return order
    def create_sell_order(self, last: QuoteTick):
        """
        A market makers simple sell limit method (example).
        """
        price: Decimal = last.ask + (self.atr.value * self.atr_multiple)
        order: LimitOrder = self.order_factory.limit(
            symbol=self.symbol,
            order_side=OrderSide.SELL,
            quantity=Quantity(self.trade_size),
            price=Price(price, self.price_precision),
            time_in_force=TimeInForce.GTC,
            post_only=True,  # Default value is True
            hidden=False,  # Default value is False
        )

        self.sell_order = order
        self.submit_order(order)
예제 #23
0
async def test_post_order_update_success(execution_client, exec_engine):
    # Add fake order to cache
    order = BetfairTestStubs.make_order(exec_engine)
    order.apply(BetfairTestStubs.event_order_submitted(order=order))
    order.apply(
        BetfairTestStubs.event_order_accepted(
            order=order, venue_order_id=VenueOrderId("229435133092")))
    exec_engine.cache.add_order(order, PositionId("1"))
    client_order_id = exec_engine.cache.orders()[0].client_order_id

    f = asyncio.Future()
    f.set_result(BetfairTestStubs.replace_orders_resp_success())
    execution_client._post_update_order(f, client_order_id)
    await asyncio.sleep(0)
    event = exec_engine.events[0]
    assert isinstance(event, OrderUpdated)
    assert event.price == Price("0.47619")
예제 #24
0
 def test_stop_market_order_with_gtd_and_expire_time_none_raises_type_error(
         self):
     # Arrange, Act, Assert
     with pytest.raises(TypeError):
         StopMarketOrder(
             self.trader_id,
             self.strategy_id,
             AUDUSD_SIM.id,
             ClientOrderId("O-123456"),
             OrderSide.BUY,
             Quantity.from_int(100000),
             price=Price.from_str("1.00000"),
             init_id=UUID4(),
             ts_init=0,
             time_in_force=TimeInForce.GTD,
             expire_time=None,
         )
    def test_handle_trade_tick_when_volume_at_threshold_sends_bar_to_handler(self):
        # Arrange
        bar_store = ObjectStorer()
        handler = bar_store.store
        instrument_id = TestStubs.audusd_id()
        bar_spec = BarSpecification(10000, BarAggregation.VOLUME, PriceType.LAST)
        bar_type = BarType(instrument_id, bar_spec)
        aggregator = VolumeBarAggregator(bar_type, handler, Logger(TestClock()))

        tick1 = TradeTick(
            instrument_id=AUDUSD_SIM.id,
            price=Price("1.00001"),
            size=Quantity(3000),
            side=OrderSide.BUY,
            match_id=TradeMatchId("123456"),
            timestamp_ns=0,
        )

        tick2 = TradeTick(
            instrument_id=AUDUSD_SIM.id,
            price=Price("1.00002"),
            size=Quantity(4000),
            side=OrderSide.BUY,
            match_id=TradeMatchId("123457"),
            timestamp_ns=0,
        )

        tick3 = TradeTick(
            instrument_id=AUDUSD_SIM.id,
            price=Price("1.00000"),
            size=Quantity(3000),
            side=OrderSide.BUY,
            match_id=TradeMatchId("123458"),
            timestamp_ns=0,
        )

        # Act
        aggregator.handle_trade_tick(tick1)
        aggregator.handle_trade_tick(tick2)
        aggregator.handle_trade_tick(tick3)

        # Assert
        self.assertEqual(1, len(bar_store.get_store()))
        self.assertEqual(Price("1.00001"), bar_store.get_store()[0].open)
        self.assertEqual(Price("1.00002"), bar_store.get_store()[0].high)
        self.assertEqual(Price("1.00000"), bar_store.get_store()[0].low)
        self.assertEqual(Price("1.00000"), bar_store.get_store()[0].close)
        self.assertEqual(Quantity(10000), bar_store.get_store()[0].volume)
예제 #26
0
    def test_handle_trade_tick_when_count_at_threshold_sends_bar_to_handler(self):
        # Arrange
        bar_store = ObjectStorer()
        handler = bar_store.store
        symbol = TestStubs.symbol_audusd_fxcm()
        bar_spec = BarSpecification(3, BarAggregation.TICK, PriceType.LAST)
        bar_type = BarType(symbol, bar_spec)
        aggregator = TickBarAggregator(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,
        )

        tick2 = TradeTick(
            symbol=AUDUSD_SIM.symbol,
            price=Price("1.00002"),
            size=Quantity(1),
            side=OrderSide.BUY,
            match_id=TradeMatchId("123457"),
            timestamp=UNIX_EPOCH,
        )

        tick3 = TradeTick(
            symbol=AUDUSD_SIM.symbol,
            price=Price("1.00000"),
            size=Quantity(1),
            side=OrderSide.BUY,
            match_id=TradeMatchId("123458"),
            timestamp=UNIX_EPOCH,
        )

        # Act
        aggregator.handle_trade_tick(tick1)
        aggregator.handle_trade_tick(tick2)
        aggregator.handle_trade_tick(tick3)

        # Assert
        self.assertEqual(1, len(bar_store.get_store()))
        self.assertEqual(Price("1.00001"), bar_store.get_store()[0].bar.open)
        self.assertEqual(Price("1.00002"), bar_store.get_store()[0].bar.high)
        self.assertEqual(Price("1.00000"), bar_store.get_store()[0].bar.low)
        self.assertEqual(Price("1.00000"), bar_store.get_store()[0].bar.close)
        self.assertEqual(Quantity(3), bar_store.get_store()[0].bar.volume)
    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={"instrument_id": 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={"instrument_id": 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,
            "123456789",
            0,
            0,
        )

        # Act
        self.data_engine.process(tick)

        # Assert
        self.assertEqual([tick], handler1)
        self.assertEqual([tick], handler2)
    def test_process(self):
        # Arrange
        instrument = TestInstrumentProvider.btcusdt_binance()
        wrangler = TradeTickDataWrangler(instrument=instrument)
        path = os.path.join(PACKAGE_ROOT, "data", "tardis_trades.csv")
        data = TardisTradeDataLoader.load(path)

        # Act
        ticks = wrangler.process(data)

        # Assert
        assert len(ticks) == 9999
        assert ticks[0].price == Price.from_str("9682.00")
        assert ticks[0].size == Quantity.from_str("0.132000")
        assert ticks[0].aggressor_side == AggressorSide.BUY
        assert ticks[0].trade_id == TradeId("42377944")
        assert ticks[0].ts_event == 1582329602418379008
        assert ticks[0].ts_init == 1582329602418379008
    def test_process(self):
        # Arrange
        ethusdt = TestInstrumentProvider.ethusdt_binance()
        wrangler = TradeTickDataWrangler(instrument=ethusdt)
        provider = TestDataProvider()

        # Act
        ticks = wrangler.process(
            provider.read_csv_ticks("binance-ethusdt-trades.csv")[:100])

        # Assert
        assert len(ticks) == 100
        assert ticks[0].price == Price.from_str("423.760")
        assert ticks[0].size == Quantity.from_str("2.67900")
        assert ticks[0].aggressor_side == AggressorSide.SELL
        assert ticks[0].trade_id == TradeId("148568980")
        assert ticks[0].ts_event == 1597399200223000064
        assert ticks[0].ts_init == 1597399200223000064
예제 #30
0
    def test_initialize_stop_order(self):
        # Arrange
        # Act
        order = self.order_factory.stop_market(
            AUDUSD_SIM.symbol,
            OrderSide.BUY,
            Quantity(100000),
            Price("1.00000"),
        )

        # Assert
        self.assertEqual(OrderType.STOP_MARKET, order.type)
        self.assertEqual(OrderState.INITIALIZED, order.state)
        self.assertEqual(TimeInForce.GTC, order.time_in_force)
        self.assertTrue(order.is_passive)
        self.assertFalse(order.is_aggressive)
        self.assertFalse(order.is_completed)
        self.assertEqual(OrderInitialized, type(order.init_event))