def test_update_correctly_updates_analyzer(self): # Arrange analyzer = SpreadAnalyzer(AUDUSD_SIM.id, 1000) tick1 = QuoteTick( instrument_id=AUDUSD_SIM.id, bid=Price.from_str("0.80000"), ask=Price.from_str("0.80010"), bid_size=Quantity.from_int(1), ask_size=Quantity.from_int(1), ts_event=0, ts_init=0, ) tick2 = QuoteTick( instrument_id=AUDUSD_SIM.id, bid=Price.from_str("0.80002"), ask=Price.from_str("0.80008"), bid_size=Quantity.from_int(1), ask_size=Quantity.from_int(1), ts_event=0, ts_init=0, ) # Act analyzer.handle_quote_tick(tick1) analyzer.handle_quote_tick(tick2) # Assert assert analyzer.current == pytest.approx(6e-05) assert analyzer.average == pytest.approx(8e-05)
def test_handle_quote_tick(self): # Arrange indicator = BidAskMinMax(self.instrument_id, timedelta(minutes=5)) # Act indicator.handle_quote_tick( QuoteTick( instrument_id=self.instrument_id, bid=Price.from_str("1.0"), ask=Price.from_str("2.0"), bid_size=Quantity.from_int(1), ask_size=Quantity.from_int(1), ts_event=0, ts_init=0, )) # 5 min later (still in the window) indicator.handle_quote_tick( QuoteTick( instrument_id=self.instrument_id, bid=Price.from_str("0.9"), ask=Price.from_str("2.1"), bid_size=Quantity.from_int(1), ask_size=Quantity.from_int(1), ts_event=3e11, ts_init=3e11, )) # Assert assert indicator.bids.min_price == Price.from_str("0.9") assert indicator.bids.max_price == Price.from_str("1.0") assert indicator.asks.min_price == Price.from_str("2.1") assert indicator.asks.max_price == Price.from_str("2.1")
def test_handle_quote_tick_when_value_beyond_threshold_sends_bar_to_handler( self): # Arrange bar_store = ObjectStorer() handler = bar_store.store instrument_id = TestStubs.audusd_id() bar_spec = BarSpecification(100000, BarAggregation.VALUE, PriceType.BID) bar_type = BarType(instrument_id, bar_spec) aggregator = ValueBarAggregator( AUDUSD_SIM, 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(20000), ask_size=Quantity.from_int(20000), ts_event=0, ts_init=0, ) tick2 = QuoteTick( instrument_id=AUDUSD_SIM.id, bid=Price.from_str("1.00002"), ask=Price.from_str("1.00005"), bid_size=Quantity.from_int(60000), ask_size=Quantity.from_int(20000), ts_event=0, ts_init=0, ) tick3 = QuoteTick( instrument_id=AUDUSD_SIM.id, bid=Price.from_str("1.00000"), ask=Price.from_str("1.00003"), bid_size=Quantity.from_int(30500), ask_size=Quantity.from_int(20000), ts_event=0, ts_init=0, ) # Act aggregator.handle_quote_tick(tick1) aggregator.handle_quote_tick(tick2) aggregator.handle_quote_tick(tick3) # Assert assert len(bar_store.get_store()) == 1 assert bar_store.get_store()[0].open == Price.from_str("1.00001") assert bar_store.get_store()[0].high == Price.from_str("1.00002") assert bar_store.get_store()[0].low == Price.from_str("1.00000") assert bar_store.get_store()[0].close == Price.from_str("1.00000") assert bar_store.get_store()[0].volume == Quantity.from_str("99999") assert aggregator.get_cumulative_value() == Decimal("10501.400")
def test_update_timed_with_test_clock_sends_single_bar_to_handler(self): # Arrange clock = TestClock() bar_store = ObjectStorer() handler = bar_store.store instrument_id = TestStubs.audusd_id() bar_spec = BarSpecification(1, BarAggregation.MINUTE, PriceType.MID) bar_type = BarType(instrument_id, bar_spec) aggregator = TimeBarAggregator( AUDUSD_SIM, bar_type, handler, TestClock(), Logger(clock), ) 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), ts_event=0, ts_init=0, ) tick2 = QuoteTick( instrument_id=AUDUSD_SIM.id, bid=Price.from_str("1.00002"), ask=Price.from_str("1.00005"), bid_size=Quantity.from_int(1), ask_size=Quantity.from_int(1), ts_event=0, ts_init=0, ) tick3 = QuoteTick( instrument_id=AUDUSD_SIM.id, bid=Price.from_str("1.00000"), ask=Price.from_str("1.00003"), bid_size=Quantity.from_int(1), ask_size=Quantity.from_int(1), ts_event=2 * 60 * 1_000_000_000, # 2 minutes in nanoseconds ts_init=2 * 60 * 1_000_000_000, # 2 minutes in nanoseconds ) # Act aggregator.handle_quote_tick(tick1) aggregator.handle_quote_tick(tick2) aggregator.handle_quote_tick(tick3) # Assert assert len(bar_store.get_store()) == 1 assert Price.from_str("1.000025") == bar_store.get_store()[0].open assert Price.from_str("1.000035") == bar_store.get_store()[0].high assert Price.from_str("1.000025") == bar_store.get_store()[0].low assert Price.from_str("1.000035") == bar_store.get_store()[0].close assert Quantity.from_int(2) == bar_store.get_store()[0].volume assert 60_000_000_000 == bar_store.get_store()[0].ts_init
def test_handle_quote_tick_when_volume_at_threshold_sends_bar_to_handler( self): # Arrange bar_store = ObjectStorer() handler = bar_store.store instrument = AUDUSD_SIM bar_spec = BarSpecification(10000, BarAggregation.VOLUME, PriceType.BID) bar_type = BarType(instrument.id, bar_spec) aggregator = VolumeBarAggregator( instrument, bar_type, handler, Logger(TestClock()), ) tick1 = QuoteTick( instrument_id=instrument.id, bid=Price.from_str("1.00001"), ask=Price.from_str("1.00004"), bid_size=Quantity.from_int(3000), ask_size=Quantity.from_int(2000), ts_event=0, ts_init=0, ) tick2 = QuoteTick( instrument_id=instrument.id, bid=Price.from_str("1.00002"), ask=Price.from_str("1.00005"), bid_size=Quantity.from_int(4000), ask_size=Quantity.from_int(2000), ts_event=0, ts_init=0, ) tick3 = QuoteTick( instrument_id=instrument.id, bid=Price.from_str("1.00000"), ask=Price.from_str("1.00003"), bid_size=Quantity.from_int(3000), ask_size=Quantity.from_int(2000), ts_event=0, ts_init=0, ) # Act aggregator.handle_quote_tick(tick1) aggregator.handle_quote_tick(tick2) aggregator.handle_quote_tick(tick3) # Assert assert len(bar_store.get_store()) == 1 assert bar_store.get_store()[0].open == Price.from_str("1.00001") assert bar_store.get_store()[0].high == Price.from_str("1.00002") assert bar_store.get_store()[0].low == Price.from_str("1.00000") assert bar_store.get_store()[0].close == Price.from_str("1.00000") assert bar_store.get_store()[0].volume == Quantity.from_int(10000)
def test_partial_fill_bracket_tp_updates_sl_order(self): # Arrange: Prepare market tick1 = QuoteTick( instrument_id=ETHUSD_FTX.id, bid=ETHUSD_FTX.make_price(3090.2), ask=ETHUSD_FTX.make_price(3090.5), bid_size=ETHUSD_FTX.make_qty(15.100), ask_size=ETHUSD_FTX.make_qty(15.100), ts_event=0, ts_init=0, ) self.data_engine.process(tick1) self.exchange.process_tick(tick1) bracket = self.strategy.order_factory.bracket_limit( instrument_id=ETHUSD_FTX.id, order_side=OrderSide.BUY, quantity=ETHUSD_FTX.make_qty(10.000), entry=ETHUSD_FTX.make_price(3100.0), stop_loss=ETHUSD_FTX.make_price(3050.0), take_profit=ETHUSD_FTX.make_price(3150.0), ) en = bracket.orders[0] sl = bracket.orders[1] tp = bracket.orders[2] self.strategy.submit_order_list(bracket) self.exchange.process(0) # Act tick2 = QuoteTick( instrument_id=ETHUSD_FTX.id, bid=ETHUSD_FTX.make_price(3150.0), ask=ETHUSD_FTX.make_price(3151.0), bid_size=ETHUSD_FTX.make_qty(5.000), ask_size=ETHUSD_FTX.make_qty(5.1000), ts_event=0, ts_init=0, ) self.exchange.process_tick(tick2) # Assert assert en.status == OrderStatus.FILLED assert sl.status == OrderStatus.ACCEPTED assert tp.status == OrderStatus.PARTIALLY_FILLED assert sl.quantity == Quantity.from_int(5) assert tp.leaves_qty == Quantity.from_int(5) assert tp.quantity == Quantity.from_int(10) assert len(self.exchange.get_open_orders()) == 2 assert len(self.exchange.cache.positions_open()) == 1
def test_handle_quote_tick_when_value_below_threshold_updates(self): # Arrange bar_store = ObjectStorer() handler = bar_store.store instrument_id = TestStubs.audusd_id() bar_spec = BarSpecification(100000, BarAggregation.VALUE, PriceType.BID) bar_type = BarType(instrument_id, bar_spec) aggregator = ValueBarAggregator( AUDUSD_SIM, 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(3000), ask_size=Quantity.from_int(2000), ts_event=0, ts_init=0, ) # Act aggregator.handle_quote_tick(tick1) # Assert assert len(bar_store.get_store()) == 0 assert aggregator.get_cumulative_value() == Decimal("3000.03000")
def test_submit_bracket_limit_sell_fills_then_triggers_sl_and_tp(self): # Arrange: Prepare market tick = QuoteTick( instrument_id=ETHUSD_FTX.id, bid=ETHUSD_FTX.make_price(3090.2), ask=ETHUSD_FTX.make_price(3090.5), bid_size=ETHUSD_FTX.make_qty(15.100), ask_size=ETHUSD_FTX.make_qty(15.100), ts_event=0, ts_init=0, ) self.data_engine.process(tick) self.exchange.process_tick(tick) bracket = self.strategy.order_factory.bracket_limit( instrument_id=ETHUSD_FTX.id, order_side=OrderSide.SELL, quantity=ETHUSD_FTX.make_qty(10.000), entry=ETHUSD_FTX.make_price(3050.0), stop_loss=ETHUSD_FTX.make_price(3150.0), take_profit=ETHUSD_FTX.make_price(3000.0), ) # Act self.strategy.submit_order_list(bracket) self.exchange.process(0) # Assert assert bracket.orders[0].status == OrderStatus.FILLED assert bracket.orders[1].status == OrderStatus.ACCEPTED assert bracket.orders[2].status == OrderStatus.ACCEPTED assert len(self.exchange.get_open_orders()) == 2 assert bracket.orders[1] in self.exchange.get_open_orders() assert bracket.orders[2] in self.exchange.get_open_orders()
def test_submit_bracket_limit_buy_has_sl_tp_pending(self): # Arrange: Prepare market tick = QuoteTick( instrument_id=ETHUSD_FTX.id, bid=ETHUSD_FTX.make_price(3090.2), ask=ETHUSD_FTX.make_price(3090.5), bid_size=ETHUSD_FTX.make_qty(15.100), ask_size=ETHUSD_FTX.make_qty(15.100), ts_event=0, ts_init=0, ) self.data_engine.process(tick) self.exchange.process_tick(tick) bracket = self.strategy.order_factory.bracket_limit( instrument_id=ETHUSD_FTX.id, order_side=OrderSide.BUY, quantity=ETHUSD_FTX.make_qty(10.000), entry=ETHUSD_FTX.make_price(3090.0), stop_loss=ETHUSD_FTX.make_price(3050.0), take_profit=ETHUSD_FTX.make_price(3150.0), ) # Act self.strategy.submit_order_list(bracket) self.exchange.process(0) # # # Assert assert bracket.orders[0].status == OrderStatus.ACCEPTED assert bracket.orders[1].status == OrderStatus.SUBMITTED assert bracket.orders[2].status == OrderStatus.SUBMITTED
async def test_subscribe_quote_ticks(self, monkeypatch): handler = [] self.msgbus.subscribe( topic="data.quotes.BINANCE.ETHUSDT", handler=handler.append, ) # Act self.data_client.subscribe_quote_ticks(ETHUSDT_BINANCE.id) raw_book_tick = pkgutil.get_data( package="tests.integration_tests.adapters.binance.resources.ws_messages", resource="ws_spot_ticker_book.json", ) # Assert self.data_client._handle_ws_message(raw_book_tick) await asyncio.sleep(1) assert self.data_engine.data_count == 1 assert len(handler) == 1 # <-- handler received tick assert handler[0] == QuoteTick( instrument_id=ETHUSDT_BINANCE.id, bid=Price.from_str("4507.24000000"), ask=Price.from_str("4507.25000000"), bid_size=Quantity.from_str("2.35950000"), ask_size=Quantity.from_str("2.84570000"), ts_event=handler[0].ts_init, # TODO: WIP ts_init=handler[0].ts_init, )
def test_partition_key_correctly_remapped(self): # Arrange instrument = TestInstrumentProvider.default_fx_ccy("AUD/USD") tick = QuoteTick( instrument_id=instrument.id, bid=Price(10, 1), ask=Price(11, 1), bid_size=Quantity(10, 1), ask_size=Quantity(10, 1), ts_init=0, ts_event=0, ) tables = dicts_to_dataframes(split_and_serialize([tick])) write_tables(catalog=self.catalog, tables=tables) # Act df = self.catalog.quote_ticks() # Assert assert len(df) == 1 assert self.fs.isdir( "/root/data/quote_tick.parquet/instrument_id=AUD-USD.SIM/") # Ensure we "unmap" the keys that we write the partition filenames as; # this instrument_id should be AUD/USD not AUD-USD assert df.iloc[0]["instrument_id"] == instrument.id.value
def test_to_dict_returns_expected_dict(self): # Arrange tick = QuoteTick( instrument_id=AUDUSD_SIM.id, bid=Price.from_str("1.00000"), ask=Price.from_str("1.00001"), bid_size=Quantity.from_int(1), ask_size=Quantity.from_int(1), ts_event=0, ts_init=0, ) # Act result = QuoteTick.to_dict(tick) print(result) # Assert assert result == { "type": "QuoteTick", "instrument_id": "AUD/USD.SIM", "bid": "1.00000", "ask": "1.00001", "bid_size": "1", "ask_size": "1", "ts_event": 0, "ts_init": 0, }
def test_handle_quote_tick_when_volume_below_threshold_updates(self): # Arrange bar_store = ObjectStorer() handler = bar_store.store instrument = AUDUSD_SIM bar_spec = BarSpecification(10000, BarAggregation.VOLUME, PriceType.BID) bar_type = BarType(instrument.id, bar_spec) aggregator = VolumeBarAggregator( instrument, bar_type, handler, Logger(TestClock()), ) tick1 = QuoteTick( instrument_id=instrument.id, bid=Price.from_str("1.00001"), ask=Price.from_str("1.00004"), bid_size=Quantity.from_int(3000), ask_size=Quantity.from_int(2000), ts_event=0, ts_init=0, ) # Act aggregator.handle_quote_tick(tick1) # Assert assert len(bar_store.get_store()) == 0
def test_filling_bracket_tp_cancels_sl_order(self): # Arrange: Prepare market tick1 = QuoteTick( instrument_id=ETHUSD_FTX.id, bid=ETHUSD_FTX.make_price(3090.2), ask=ETHUSD_FTX.make_price(3090.5), bid_size=ETHUSD_FTX.make_qty(15.100), ask_size=ETHUSD_FTX.make_qty(15.100), ts_event=0, ts_init=0, ) self.data_engine.process(tick1) self.exchange.process_tick(tick1) bracket = self.strategy.order_factory.bracket_limit( instrument_id=ETHUSD_FTX.id, order_side=OrderSide.BUY, quantity=ETHUSD_FTX.make_qty(10.000), entry=ETHUSD_FTX.make_price(3100.0), stop_loss=ETHUSD_FTX.make_price(3050.0), take_profit=ETHUSD_FTX.make_price(3150.0), ) self.strategy.submit_order_list(bracket) self.exchange.process(0) # Act tick2 = QuoteTick( instrument_id=ETHUSD_FTX.id, bid=ETHUSD_FTX.make_price(3150.0), ask=ETHUSD_FTX.make_price(3151.0), bid_size=ETHUSD_FTX.make_qty(10.000), ask_size=ETHUSD_FTX.make_qty(10.000), ts_event=0, ts_init=0, ) self.exchange.process_tick(tick2) # Assert assert bracket.orders[0].status == OrderStatus.FILLED assert bracket.orders[1].status == OrderStatus.CANCELED assert bracket.orders[2].status == OrderStatus.FILLED assert len(self.exchange.get_open_orders()) == 0 assert len(self.exchange.cache.positions_open()) == 0
def parse_quote_tick_ws(instrument_id: InstrumentId, msg: Dict, ts_init: int) -> QuoteTick: return QuoteTick( instrument_id=instrument_id, bid=Price.from_str(msg["b"]), ask=Price.from_str(msg["a"]), bid_size=Quantity.from_str(msg["B"]), ask_size=Quantity.from_str(msg["B"]), ts_event=ts_init, ts_init=ts_init, )
def test_partially_filling_position_updates_bracket_ocos(self): # Arrange: Prepare market tick1 = QuoteTick( instrument_id=ETHUSD_FTX.id, bid=ETHUSD_FTX.make_price(3090.2), ask=ETHUSD_FTX.make_price(3090.5), bid_size=ETHUSD_FTX.make_qty(15.100), ask_size=ETHUSD_FTX.make_qty(15.100), ts_event=0, ts_init=0, ) self.data_engine.process(tick1) self.exchange.process_tick(tick1) bracket = self.strategy.order_factory.bracket_market( instrument_id=ETHUSD_FTX.id, order_side=OrderSide.BUY, quantity=ETHUSD_FTX.make_qty(10.000), stop_loss=ETHUSD_FTX.make_price(3050.0), take_profit=ETHUSD_FTX.make_price(3150.0), ) en = bracket.orders[0] sl = bracket.orders[1] tp = bracket.orders[2] self.strategy.submit_order_list(bracket) self.exchange.process(0) # Act reduce_order = self.strategy.order_factory.market( instrument_id=ETHUSD_FTX.id, order_side=OrderSide.SELL, quantity=ETHUSD_FTX.make_qty(5.000), ) self.strategy.submit_order( reduce_order, position_id=self.cache.position_for_order(en.client_order_id).id, ) self.exchange.process(0) # Assert assert en.status == OrderStatus.FILLED assert sl.status == OrderStatus.ACCEPTED assert tp.status == OrderStatus.ACCEPTED assert sl.quantity == ETHUSD_FTX.make_qty(5.000) assert tp.quantity == ETHUSD_FTX.make_qty(5.000) assert len(self.exchange.get_open_orders()) == 2 assert len(self.exchange.cache.positions_open()) == 1
def parse_quote_tick_ws( instrument_id: InstrumentId, data: BinanceQuoteData, ts_init: int, ) -> QuoteTick: return QuoteTick( instrument_id=instrument_id, bid=Price.from_str(data.b), ask=Price.from_str(data.a), bid_size=Quantity.from_str(data.B), ask_size=Quantity.from_str(data.A), ts_event=ts_init, ts_init=ts_init, )
def parse_quote_tick_ws( instrument: Instrument, data: Dict[str, Any], ts_init: int, ) -> QuoteTick: return QuoteTick( instrument_id=instrument.id, bid=Price(data["bid"], instrument.price_precision), ask=Price(data["ask"], instrument.price_precision), bid_size=Quantity(data["bidSize"], instrument.size_precision), ask_size=Quantity(data["askSize"], instrument.size_precision), ts_event=secs_to_nanos(data["time"]), ts_init=ts_init, )
def quote_tick_5decimal( instrument_id=None, bid=None, ask=None, ) -> QuoteTick: return QuoteTick( instrument_id=instrument_id or TestIdStubs.audusd_id(), bid=bid or Price.from_str("1.00001"), ask=ask or Price.from_str("1.00003"), bid_size=Quantity.from_int(1_000_000), ask_size=Quantity.from_int(1_000_000), ts_event=0, ts_init=0, )
def parse_csv_tick(df, instrument_id): yield instrument for r in df.values: ts = secs_to_nanos(pd.Timestamp(r[0]).timestamp()) tick = QuoteTick( instrument_id=instrument_id, bid=Price.from_str(str(r[1])), ask=Price.from_str(str(r[2])), bid_size=Quantity.from_int(1_000_000), ask_size=Quantity.from_int(1_000_000), ts_event=ts, ts_init=ts, ) yield tick
def test_update_with_incorrect_tick_raises_exception(self): # Arrange analyzer = SpreadAnalyzer(AUDUSD_SIM.id, 1000) tick = QuoteTick( instrument_id=USDJPY_SIM.id, bid=Price.from_str("117.80000"), ask=Price.from_str("117.80010"), bid_size=Quantity.from_int(1), ask_size=Quantity.from_int(1), ts_event=0, ts_init=0, ) # Act, Assert with pytest.raises(ValueError): analyzer.handle_quote_tick(tick)
def test_extract_volume_with_invalid_price_raises_value_error(self): # Arrange tick = QuoteTick( instrument_id=AUDUSD_SIM.id, bid=Price.from_str("1.00000"), ask=Price.from_str("1.00001"), bid_size=Quantity.from_int(1), ask_size=Quantity.from_int(1), ts_event=0, ts_init=0, ) # Act, Assert with pytest.raises(ValueError): tick.extract_volume(0)
def quote_tick_3decimal( instrument_id=None, bid=None, ask=None, bid_volume=None, ask_volume=None, ) -> QuoteTick: return QuoteTick( instrument_id=instrument_id or TestIdStubs.usdjpy_id(), bid=bid or Price.from_str("90.002"), ask=ask or Price.from_str("90.005"), bid_size=bid_volume or Quantity.from_int(1_000_000), ask_size=ask_volume or Quantity.from_int(1_000_000), ts_event=0, ts_init=0, )
def test_tick_hash_str_and_repr(self): # Arrange tick = QuoteTick( instrument_id=AUDUSD_SIM.id, bid=Price.from_str("1.00000"), ask=Price.from_str("1.00001"), bid_size=Quantity.from_int(1), ask_size=Quantity.from_int(1), ts_event=0, ts_init=0, ) # Act, Assert assert isinstance(hash(tick), int) assert str(tick) == "AUD/USD.SIM,1.00000,1.00001,1,1,0" assert repr(tick) == "QuoteTick(AUD/USD.SIM,1.00000,1.00001,1,1,0)"
def test_from_dict_returns_expected_tick(self): # Arrange tick = QuoteTick( instrument_id=AUDUSD_SIM.id, bid=Price.from_str("1.00000"), ask=Price.from_str("1.00001"), bid_size=Quantity.from_int(1), ask_size=Quantity.from_int(1), ts_event=0, ts_init=0, ) # Act result = QuoteTick.from_dict(QuoteTick.to_dict(tick)) # Assert assert tick == result
def parse_historic_quote_ticks(historic_ticks: List[HistoricalTickBidAsk], instrument_id: InstrumentId) -> List[QuoteTick]: trades = [] for tick in historic_ticks: ts_init = dt_to_unix_nanos(tick.time) quote_tick = QuoteTick( instrument_id=instrument_id, bid=Price.from_str(str(tick.priceBid)), bid_size=Quantity.from_str(str(tick.sizeBid)), ask=Price.from_str(str(tick.priceAsk)), ask_size=Quantity.from_str(str(tick.sizeAsk)), ts_init=ts_init, ts_event=ts_init, ) trades.append(quote_tick) return trades
def _on_quote_tick_update(self, tick: Ticker, contract: Contract): instrument_id = self._instrument_provider.contract_id_to_instrument_id[ contract.conId] ts_event = dt_to_unix_nanos(tick.time) ts_init = self._clock.timestamp_ns() quote_tick = QuoteTick( instrument_id=instrument_id, bid=Price.from_str(str(tick.bid)) if tick.bid else None, bid_size=Quantity.from_str(str(tick.bidSize)) if tick.bidSize else None, ask=Price.from_str(str(tick.ask)) if tick.ask else None, ask_size=Quantity.from_str(str(tick.askSize)) if tick.askSize else None, ts_event=ts_event, ts_init=ts_init, ) self._handle_data(quote_tick)
def test_submit_limit_order_aggressive_multiple_levels(self): # Arrange: Prepare market self.cache.add_instrument(USDJPY_SIM) quote = QuoteTick( instrument_id=USDJPY_SIM.id, bid=Price.from_str("110.000"), ask=Price.from_str("110.010"), bid_size=Quantity.from_int(1500000), ask_size=Quantity.from_int(1500000), ts_event=0, ts_init=0, ) self.data_engine.process(quote) snapshot = TestDataStubs.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) # Create order order = self.strategy.order_factory.limit( instrument_id=USDJPY_SIM.id, order_side=OrderSide.BUY, quantity=Quantity.from_int(2000), price=Price.from_int(20), post_only=False, ) # Act self.strategy.submit_order(order) self.exchange.process(0) # Assert assert order.status == OrderStatus.FILLED assert order.filled_qty == Decimal("2000.0") # No slippage assert order.avg_px == Decimal("15.33333333333333333333333333") assert self.exchange.get_account().balance_total(USD) == Money( 999999.96, USD)
def test_closing_position_cancels_bracket_ocos(self): # Arrange: Prepare market tick1 = QuoteTick( instrument_id=ETHUSD_FTX.id, bid=ETHUSD_FTX.make_price(3090.2), ask=ETHUSD_FTX.make_price(3090.5), bid_size=ETHUSD_FTX.make_qty(15.100), ask_size=ETHUSD_FTX.make_qty(15.100), ts_event=0, ts_init=0, ) self.data_engine.process(tick1) self.exchange.process_tick(tick1) bracket = self.strategy.order_factory.bracket_market( instrument_id=ETHUSD_FTX.id, order_side=OrderSide.BUY, quantity=ETHUSD_FTX.make_qty(10.000), stop_loss=ETHUSD_FTX.make_price(3050.0), take_profit=ETHUSD_FTX.make_price(3150.0), ) en = bracket.orders[0] sl = bracket.orders[1] tp = bracket.orders[2] self.strategy.submit_order_list(bracket) self.exchange.process(0) # Act self.strategy.flatten_position( self.strategy.cache.position(en.position_id)) self.exchange.process(0) # Assert assert en.status == OrderStatus.FILLED assert sl.status == OrderStatus.CANCELED assert tp.status == OrderStatus.CANCELED assert len(self.exchange.get_open_orders()) == 0 assert len(self.exchange.cache.positions_open()) == 0
def test_get_xrate_with_conversion(self): # Arrange self.cache.add_instrument(AUDUSD_SIM) tick = QuoteTick( instrument_id=AUDUSD_SIM.id, bid=Price.from_str("0.80000"), ask=Price.from_str("0.80010"), bid_size=Quantity.from_int(1), ask_size=Quantity.from_int(1), ts_event=0, ts_init=0, ) self.cache.add_quote_tick(tick) # Act result = self.cache.get_xrate(SIM, AUD, USD) # Assert assert result == Decimal("0.80005")