def test_iso8601_to_unix_nanos_given_iso8601_datetime_string( self, value, expected): # Arrange, Act result = dt_to_unix_nanos(value) # Assert assert result == pytest.approx(expected, 100) # 100 nanoseconds
def test_dt_to_unix_nanos(self, value, expected): # Arrange # Act result = dt_to_unix_nanos(value) # Assert assert result == expected
def _on_new_order(self, trade: IBTrade): self._log.debug(f"new_order: {IBTrade}") instrument_id = self._instrument_provider.contract_id_to_instrument_id[trade.contract.conId] 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] assert trade.log self.generate_order_submitted( strategy_id=strategy_id, instrument_id=instrument_id, client_order_id=client_order_id, ts_event=dt_to_unix_nanos(trade.log[-1].time), )
def _on_open_order(self, trade: IBTrade): instrument_id = self._instrument_provider.contract_id_to_instrument_id[trade.contract.conId] 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_accepted( strategy_id=strategy_id, instrument_id=instrument_id, client_order_id=client_order_id, venue_order_id=venue_order_id, ts_event=dt_to_unix_nanos(trade.log[-1].time), ) # We can remove the local `_venue_order_id_to_client_order_id` now, we have a permId self._venue_order_id_to_client_order_id.pop(trade.order.orderId)
def _on_top_level_snapshot(self, ticker: Ticker): instrument_id = self._instrument_provider.contract_id_to_instrument_id[ ticker.contract.conId] ts_event = dt_to_unix_nanos(ticker.time) ts_init = self._clock.timestamp_ns() snapshot = OrderBookSnapshot( book_type=BookType.L1_TBBO, instrument_id=instrument_id, bids=[(ticker.bid, ticker.bidSize)], asks=[(ticker.ask, ticker.askSize)], ts_event=ts_event, ts_init=ts_init, ) self._handle_data(snapshot)
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_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? )
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 _on_order_book_snapshot(self, ticker: Ticker, book_type: BookType = BookType.L2_MBP): instrument_id = self._instrument_provider.contract_id_to_instrument_id[ ticker.contract.conId] ts_event = dt_to_unix_nanos(ticker.time) ts_init = self._clock.timestamp_ns() if not (ticker.domBids or ticker.domAsks): return snapshot = OrderBookSnapshot( book_type=book_type, instrument_id=instrument_id, bids=[(level.price, level.size) for level in ticker.domBids], asks=[(level.price, level.size) for level in ticker.domAsks], ts_event=ts_event, ts_init=ts_init, ) self._handle_data(snapshot)
def _on_trade_ticker_update(self, ticker: Ticker): instrument_id = self._instrument_provider.contract_id_to_instrument_id[ ticker.contract.conId] for tick in ticker.ticks: price = str(tick.price) size = str(tick.size) ts_event = dt_to_unix_nanos(tick.time) update = TradeTick( instrument_id=instrument_id, price=Price.from_str(price), size=Quantity.from_str(size), aggressor_side=AggressorSide.UNKNOWN, trade_id=generate_trade_id(symbol=instrument_id.value, ts_event=ts_event, price=price, size=size), ts_event=ts_event, ts_init=self._clock.timestamp_ns(), ) self._handle_data(update)
def parse_historic_trade_ticks(historic_ticks: List[HistoricalTickLast], instrument_id: InstrumentId) -> List[TradeTick]: trades = [] for tick in historic_ticks: ts_init = dt_to_unix_nanos(tick.time) trade_tick = TradeTick( instrument_id=instrument_id, price=Price.from_str(str(tick.price)), size=Quantity.from_str(str(tick.size)), aggressor_side=AggressorSide.UNKNOWN, trade_id=generate_trade_id( symbol=instrument_id.symbol.value, ts_event=ts_init, price=tick.price, size=tick.size, ), ts_init=ts_init, ts_event=ts_init, ) trades.append(trade_tick) return trades
class TestTimeBarAggregator: def test_instantiate_given_invalid_bar_spec_raises_value_error(self): # Arrange clock = TestClock() bar_store = ObjectStorer() handler = bar_store.store instrument = AUDUSD_SIM bar_spec = BarSpecification(100, BarAggregation.TICK, PriceType.MID) bar_type = BarType(instrument.id, bar_spec) # Act # Assert with pytest.raises(ValueError): TimeBarAggregator( instrument, bar_type, handler, True, clock, Logger(clock), ) @pytest.mark.parametrize( "bar_spec, expected", [ [ BarSpecification(10, BarAggregation.SECOND, PriceType.MID), dt_to_unix_nanos( datetime(1970, 1, 1, 0, 0, 10, tzinfo=pytz.utc)), ], [ BarSpecification(1, BarAggregation.MINUTE, PriceType.MID), dt_to_unix_nanos(datetime(1970, 1, 1, 0, 1, tzinfo=pytz.utc)), ], [ BarSpecification(1, BarAggregation.HOUR, PriceType.MID), dt_to_unix_nanos(datetime(1970, 1, 1, 1, 0, tzinfo=pytz.utc)), ], [ BarSpecification(1, BarAggregation.DAY, PriceType.MID), dt_to_unix_nanos(datetime(1970, 1, 2, 0, 0, tzinfo=pytz.utc)), ], ], ) def test_instantiate_with_various_bar_specs(self, bar_spec, expected): # Arrange clock = TestClock() bar_store = ObjectStorer() handler = bar_store.store instrument_id = TestStubs.audusd_id() bar_type = BarType(instrument_id, bar_spec) # Act aggregator = TimeBarAggregator( AUDUSD_SIM, bar_type, handler, True, clock, Logger(clock), ) # Assert assert aggregator.next_close_ns == expected 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, True, 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_ns=0, ts_recv_ns=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_ns=0, ts_recv_ns=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_ns=2 * 60 * 1_000_000_000, # 2 minutes in nanoseconds ts_recv_ns=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_recv_ns