def test_handle_quote_tick(self): # Arrange indicator = BidAskMinMax(self.instrument_id, timedelta(minutes=5)) # Act indicator.handle_quote_tick( QuoteTick( self.instrument_id, Price("1.0"), Price("2.0"), Quantity(1), Quantity(1), 0, )) # 5 min later (still in the window) indicator.handle_quote_tick( QuoteTick( self.instrument_id, Price("0.9"), Price("2.1"), Quantity(1), Quantity(1), 3e11, )) # Assert self.assertEqual(Price("0.9"), indicator.bids.min_price) self.assertEqual(Price("1.0"), indicator.bids.max_price) self.assertEqual(Price("2.1"), indicator.asks.min_price) self.assertEqual(Price("2.1"), indicator.asks.max_price)
def test_update_correctly_updates_analyzer(self): # Arrange analyzer = SpreadAnalyzer(AUDUSD_SIM.id, 1000) tick1 = QuoteTick( AUDUSD_SIM.id, Price("0.80000"), Price("0.80010"), Quantity(1), Quantity(1), 0, ) tick2 = QuoteTick( AUDUSD_SIM.id, Price("0.80002"), Price("0.80008"), Quantity(1), Quantity(1), 0, ) # Act analyzer.handle_quote_tick(tick1) analyzer.handle_quote_tick(tick2) # Assert self.assertAlmostEqual(6e-05, analyzer.current) self.assertAlmostEqual(8e-05, analyzer.average)
def test_to_dict_returns_expected_dict(self): # Arrange tick = QuoteTick( AUDUSD_SIM.id, Price.from_str("1.00000"), Price.from_str("1.00001"), Quantity.from_int(1), Quantity.from_int(1), 0, 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_ns": 0, "ts_recv_ns": 0, }
def test_quote_tick_with_two_ticks_returns_expected_tick(self): # Arrange tick1 = QuoteTick( AUDUSD_SIM.id, Price("1.00000"), Price("1.00001"), Quantity(1), Quantity(1), UNIX_EPOCH, ) tick2 = QuoteTick( AUDUSD_SIM.id, Price("1.00001"), Price("1.00003"), Quantity(1), Quantity(1), UNIX_EPOCH, ) self.cache.add_quote_tick(tick1) self.cache.add_quote_tick(tick2) # Act result = self.cache.quote_tick(AUDUSD_SIM.id, index=0) # Assert self.assertEqual(2, self.cache.quote_tick_count(AUDUSD_SIM.id)) self.assertEqual(tick2, result)
def test_handle_quote_tick(self): # Arrange indicator = BidAskMinMax(self.symbol, timedelta(minutes=5)) # Act indicator.handle_quote_tick( QuoteTick( self.symbol, Price("1.0"), Price("2.0"), Quantity(1), Quantity(1), datetime(2020, 1, 1, 0, 0, 0, tzinfo=pytz.utc), ) ) # 5 min later (still in the window) indicator.handle_quote_tick( QuoteTick( self.symbol, Price("0.9"), Price("2.1"), Quantity(1), Quantity(1), datetime(2020, 1, 1, 0, 5, 0, tzinfo=pytz.utc), ) ) # Assert self.assertEqual(Price("0.9"), indicator.bids.min_price) self.assertEqual(Price("1.0"), indicator.bids.max_price) self.assertEqual(Price("2.1"), indicator.asks.min_price) self.assertEqual(Price("2.1"), indicator.asks.max_price)
def test_update(self): # Arrange bar_spec = TestStubs.bar_spec_1min_mid() builder = BarBuilder(bar_spec, use_previous_close=True) tick1 = QuoteTick(symbol=AUDUSD_FXCM, bid=Price("1.00001"), ask=Price("1.00004"), bid_size=Quantity(1), ask_size=Quantity(1), timestamp=UNIX_EPOCH) tick2 = QuoteTick(symbol=AUDUSD_FXCM, bid=Price("1.00002"), ask=Price("1.00005"), bid_size=Quantity(1), ask_size=Quantity(1), timestamp=UNIX_EPOCH) tick3 = QuoteTick(symbol=AUDUSD_FXCM, bid=Price("1.00000"), ask=Price("1.00003"), bid_size=Quantity(1), ask_size=Quantity(1), timestamp=UNIX_EPOCH) # Act builder.handle_quote_tick(tick1) builder.handle_quote_tick(tick2) builder.handle_quote_tick(tick3) # Assert self.assertEqual(bar_spec, builder.bar_spec) self.assertEqual(3, builder.count) self.assertEqual(UNIX_EPOCH, builder.last_update)
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
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(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), timestamp_origin_ns=0, timestamp_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(60000), ask_size=Quantity.from_int(20000), timestamp_origin_ns=0, timestamp_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(30500), ask_size=Quantity.from_int(20000), timestamp_origin_ns=0, timestamp_ns=0, ) # Act aggregator.handle_quote_tick(tick1) aggregator.handle_quote_tick(tick2) aggregator.handle_quote_tick(tick3) # Assert self.assertEqual(1, len(bar_store.get_store())) self.assertEqual(Price.from_str("1.00001"), bar_store.get_store()[0].open) self.assertEqual(Price.from_str("1.00002"), bar_store.get_store()[0].high) self.assertEqual(Price.from_str("1.00000"), bar_store.get_store()[0].low) self.assertEqual(Price.from_str("1.00000"), bar_store.get_store()[0].close) self.assertEqual(Quantity.from_str("99999"), bar_store.get_store()[0].volume) self.assertEqual(Decimal("10501.400"), aggregator.get_cumulative_value())
def test_equality_and_comparisons(self): # Arrange # These are based on timestamp for tick sorting tick1 = QuoteTick( AUDUSD_SIM.id, Price("1.00000"), Price("1.00001"), Quantity(1), Quantity(1), UNIX_EPOCH + timedelta(seconds=1), ) tick2 = QuoteTick( AUDUSD_SIM.id, Price("1.00000"), Price("1.00001"), Quantity(1), Quantity(1), UNIX_EPOCH + timedelta(seconds=2), ) tick3 = QuoteTick( AUDUSD_SIM.id, Price("1.00000"), Price("1.00001"), Quantity(1), Quantity(1), UNIX_EPOCH + timedelta(seconds=3), ) self.assertTrue(tick1 == tick1) self.assertTrue(tick1 != tick2) self.assertEqual([tick1, tick2, tick3], sorted([tick2, tick3, tick1], key=lambda x: x.timestamp))
def test_handle_quote_tick_when_volume_beyond_threshold_sends_bars_to_handler(self): # Arrange bar_store = ObjectStorer() handler = bar_store.store instrument_id = TestStubs.audusd_id() bar_spec = BarSpecification(10000, BarAggregation.VOLUME, PriceType.BID) bar_type = BarType(instrument_id, bar_spec) aggregator = VolumeBarAggregator(bar_type, handler, Logger(TestClock())) tick1 = QuoteTick( instrument_id=AUDUSD_SIM.id, bid=Price("1.00001"), ask=Price("1.00004"), bid_size=Quantity(2000), ask_size=Quantity(2000), timestamp_ns=0, ) tick2 = QuoteTick( instrument_id=AUDUSD_SIM.id, bid=Price("1.00002"), ask=Price("1.00005"), bid_size=Quantity(3000), ask_size=Quantity(3000), timestamp_ns=0, ) tick3 = QuoteTick( instrument_id=AUDUSD_SIM.id, bid=Price("1.00000"), ask=Price("1.00003"), bid_size=Quantity(25000), ask_size=Quantity(25000), timestamp_ns=0, ) # Act aggregator.handle_quote_tick(tick1) aggregator.handle_quote_tick(tick2) aggregator.handle_quote_tick(tick3) # Assert self.assertEqual(3, 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) self.assertEqual(Price("1.00000"), bar_store.get_store()[1].open) self.assertEqual(Price("1.00000"), bar_store.get_store()[1].high) self.assertEqual(Price("1.00000"), bar_store.get_store()[1].low) self.assertEqual(Price("1.00000"), bar_store.get_store()[1].close) self.assertEqual(Quantity(10000), bar_store.get_store()[1].volume) self.assertEqual(Price("1.00000"), bar_store.get_store()[2].open) self.assertEqual(Price("1.00000"), bar_store.get_store()[2].high) self.assertEqual(Price("1.00000"), bar_store.get_store()[2].low) self.assertEqual(Price("1.00000"), bar_store.get_store()[2].close) self.assertEqual(Quantity(10000), bar_store.get_store()[2].volume)
def test_position_flipped_when_reduce_order_exceeds_original_quantity( self): # Arrange # Prepare market open_quote = QuoteTick( USDJPY_SIM.symbol, Price("90.002"), Price("90.003"), Quantity(1), Quantity(1), UNIX_EPOCH, ) self.data_engine.process(open_quote) self.exchange.process_tick(open_quote) order_open = self.strategy.order_factory.market( USDJPY_SIM.symbol, OrderSide.BUY, Quantity(100000), ) # Act 1 self.strategy.submit_order(order_open) reduce_quote = QuoteTick( USDJPY_SIM.symbol, Price("100.003"), Price("100.003"), Quantity(1), Quantity(1), UNIX_EPOCH, ) self.exchange.process_tick(reduce_quote) self.portfolio.update_tick(reduce_quote) order_reduce = self.strategy.order_factory.market( USDJPY_SIM.symbol, OrderSide.SELL, Quantity(150000), ) # Act 2 self.strategy.submit_order( order_reduce, PositionId("P-19700101-000000-000-001-1")) # Generated by platform # Assert print(self.exec_engine.cache.positions()) position_open = self.exec_engine.cache.positions_open()[0] position_closed = self.exec_engine.cache.positions_closed()[0] self.assertEqual(PositionSide.SHORT, position_open.side) self.assertEqual(Quantity(50000), position_open.quantity) self.assertEqual(Money(999619.98, JPY), position_closed.realized_pnl) self.assertEqual([Money(380.02, JPY)], position_closed.commissions())
def test_handle_quote_tick_when_count_at_threshold_sends_bar_to_handler( 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, ) 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), timestamp_origin_ns=0, timestamp_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), timestamp_origin_ns=0, timestamp_ns=0, ) # Act aggregator.handle_quote_tick(tick1) aggregator.handle_quote_tick(tick2) aggregator.handle_quote_tick(tick3) # Assert self.assertEqual(1, len(bar_store.get_store())) self.assertEqual(Price.from_str("1.000025"), bar_store.get_store()[0].open) self.assertEqual(Price.from_str("1.000035"), bar_store.get_store()[0].high) self.assertEqual(Price.from_str("1.000015"), bar_store.get_store()[0].low) self.assertEqual(Price.from_str("1.000015"), bar_store.get_store()[0].close) self.assertEqual(Quantity.from_int(3), bar_store.get_store()[0].volume)
def test_commission_maker_taker_order(self): # Arrange # Prepare market quote1 = QuoteTick( XBTUSD_BITMEX.symbol, Price("11493.70"), Price("11493.75"), Quantity(1500000), Quantity(1500000), UNIX_EPOCH, ) self.data_engine.process(quote1) self.exchange.process_tick(quote1) order_market = self.strategy.order_factory.market( XBTUSD_BITMEX.symbol, OrderSide.BUY, Quantity(100000), ) order_limit = self.strategy.order_factory.limit( XBTUSD_BITMEX.symbol, OrderSide.BUY, Quantity(100000), Price("11493.65"), ) # Act self.strategy.submit_order(order_market) self.strategy.submit_order(order_limit) quote2 = QuoteTick( XBTUSD_BITMEX.symbol, Price("11493.60"), Price("11493.64"), Quantity(1500000), Quantity(1500000), UNIX_EPOCH, ) self.exchange.process_tick(quote2) # Fill the limit order self.portfolio.update_tick(quote2) # Assert self.assertEqual( LiquiditySide.TAKER, self.strategy.object_storer.get_store()[2].liquidity_side) self.assertEqual( LiquiditySide.MAKER, self.strategy.object_storer.get_store()[7].liquidity_side) self.assertEqual(Money("0.00652529", BTC), self.strategy.object_storer.get_store()[2].commission) self.assertEqual(Money("-0.00217511", BTC), self.strategy.object_storer.get_store()[7].commission)
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(bar_type, handler, True, TestClock(), TestLogger(clock)) stop_time = UNIX_EPOCH + timedelta(minutes=2) tick1 = QuoteTick( instrument_id=AUDUSD_SIM.id, bid=Price("1.00001"), ask=Price("1.00004"), bid_size=Quantity(1), ask_size=Quantity(1), timestamp=UNIX_EPOCH, ) tick2 = QuoteTick( instrument_id=AUDUSD_SIM.id, bid=Price("1.00002"), ask=Price("1.00005"), bid_size=Quantity(1), ask_size=Quantity(1), timestamp=UNIX_EPOCH, ) tick3 = QuoteTick( instrument_id=AUDUSD_SIM.id, bid=Price("1.00000"), ask=Price("1.00003"), bid_size=Quantity(1), ask_size=Quantity(1), timestamp=stop_time, ) # Act aggregator.handle_quote_tick(tick1) aggregator.handle_quote_tick(tick2) aggregator.handle_quote_tick(tick3) # Assert self.assertEqual(1, len(bar_store.get_store())) self.assertEqual(Price("1.000025"), bar_store.get_store()[0].bar.open) self.assertEqual(Price("1.000035"), bar_store.get_store()[0].bar.high) self.assertEqual(Price("1.000025"), bar_store.get_store()[0].bar.low) self.assertEqual(Price("1.000035"), bar_store.get_store()[0].bar.close) self.assertEqual(Quantity(2), bar_store.get_store()[0].bar.volume) self.assertEqual(datetime(1970, 1, 1, 0, 1, tzinfo=pytz.utc), bar_store.get_store()[0].bar.timestamp)
def test_handle_quote_tick_when_value_beyond_threshold_sends_bar_to_handler( self): # Arrange bar_store = ObjectStorer() handler = bar_store.store symbol = TestStubs.symbol_audusd() bar_spec = BarSpecification(100000, BarAggregation.VALUE, PriceType.BID) bar_type = BarType(symbol, bar_spec) aggregator = ValueBarAggregator(bar_type, handler, TestLogger(TestClock())) tick1 = QuoteTick( symbol=AUDUSD_SIM.symbol, bid=Price("1.00001"), ask=Price("1.00004"), bid_size=Quantity(20000), ask_size=Quantity(20000), timestamp=UNIX_EPOCH, ) tick2 = QuoteTick( symbol=AUDUSD_SIM.symbol, bid=Price("1.00002"), ask=Price("1.00005"), bid_size=Quantity(60000), ask_size=Quantity(20000), timestamp=UNIX_EPOCH, ) tick3 = QuoteTick( symbol=AUDUSD_SIM.symbol, bid=Price("1.00000"), ask=Price("1.00003"), bid_size=Quantity(30500), ask_size=Quantity(20000), timestamp=UNIX_EPOCH, ) # Act aggregator.handle_quote_tick(tick1) aggregator.handle_quote_tick(tick2) aggregator.handle_quote_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("99999"), bar_store.get_store()[0].bar.volume) self.assertEqual(Decimal("10501.00000"), aggregator.cum_value)
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( bar_type, handler, True, TestClock(), Logger(clock) ) tick1 = QuoteTick( instrument_id=AUDUSD_SIM.id, bid=Price("1.00001"), ask=Price("1.00004"), bid_size=Quantity(1), ask_size=Quantity(1), timestamp_ns=0, ) tick2 = QuoteTick( instrument_id=AUDUSD_SIM.id, bid=Price("1.00002"), ask=Price("1.00005"), bid_size=Quantity(1), ask_size=Quantity(1), timestamp_ns=0, ) tick3 = QuoteTick( instrument_id=AUDUSD_SIM.id, bid=Price("1.00000"), ask=Price("1.00003"), bid_size=Quantity(1), ask_size=Quantity(1), timestamp_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 self.assertEqual(1, len(bar_store.get_store())) self.assertEqual(Price("1.000025"), bar_store.get_store()[0].open) self.assertEqual(Price("1.000035"), bar_store.get_store()[0].high) self.assertEqual(Price("1.000025"), bar_store.get_store()[0].low) self.assertEqual(Price("1.000035"), bar_store.get_store()[0].close) self.assertEqual(Quantity(2), bar_store.get_store()[0].volume) self.assertEqual(60_000_000_000, bar_store.get_store()[0].timestamp_ns)
def test_handle_quote_tick_when_count_at_threshold_sends_bar_to_handler( self): # Arrange bar_store = ObjectStorer() handler = bar_store.store symbol = TestStubs.symbol_audusd() bar_spec = BarSpecification(3, BarAggregation.TICK, PriceType.MID) bar_type = BarType(symbol, bar_spec) aggregator = TickBarAggregator(bar_type, handler, TestLogger(TestClock())) tick1 = QuoteTick( symbol=AUDUSD_SIM.symbol, bid=Price("1.00001"), ask=Price("1.00004"), bid_size=Quantity(1), ask_size=Quantity(1), timestamp=UNIX_EPOCH, ) tick2 = QuoteTick( symbol=AUDUSD_SIM.symbol, bid=Price("1.00002"), ask=Price("1.00005"), bid_size=Quantity(1), ask_size=Quantity(1), timestamp=UNIX_EPOCH, ) tick3 = QuoteTick( symbol=AUDUSD_SIM.symbol, bid=Price("1.00000"), ask=Price("1.00003"), bid_size=Quantity(1), ask_size=Quantity(1), timestamp=UNIX_EPOCH, ) # Act aggregator.handle_quote_tick(tick1) aggregator.handle_quote_tick(tick2) aggregator.handle_quote_tick(tick3) # Assert self.assertEqual(1, len(bar_store.get_store())) self.assertEqual(Price("1.000025"), bar_store.get_store()[0].bar.open) self.assertEqual(Price("1.000035"), bar_store.get_store()[0].bar.high) self.assertEqual(Price("1.000015"), bar_store.get_store()[0].bar.low) self.assertEqual(Price("1.000015"), bar_store.get_store()[0].bar.close) self.assertEqual(Quantity(3), bar_store.get_store()[0].bar.volume)
def test_extract_volume_with_invalid_price_raises_value_error(self): # Arrange tick = QuoteTick( AUDUSD_SIM.id, Price.from_str("1.00000"), Price.from_str("1.00001"), Quantity.from_int(1), Quantity.from_int(1), 0, 0, ) # Act, Assert with pytest.raises(ValueError): tick.extract_volume(0)
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(bar_type, handler, TestLogger(TestClock())) tick1 = QuoteTick( instrument_id=AUDUSD_SIM.id, bid=Price("1.00001"), ask=Price("1.00004"), bid_size=Quantity(3000), ask_size=Quantity(2000), timestamp=UNIX_EPOCH, ) # Act aggregator.handle_quote_tick(tick1) # Assert self.assertEqual(0, len(bar_store.get_store())) self.assertEqual(Decimal("3000.03000"), aggregator.cum_value)
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_ns=0, ts_recv_ns=0, ) # Act aggregator.handle_quote_tick(tick1) # Assert self.assertEqual(0, len(bar_store.get_store())) self.assertEqual(Decimal("3000.03000"), aggregator.get_cumulative_value())
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_ns=0, ts_recv_ns=0, ) # Act aggregator.handle_quote_tick(tick1) # Assert self.assertEqual(0, len(bar_store.get_store()))
def test_process_quote_tick_when_subscriber_then_sends_to_registered_handler( self): # Arrange self.data_engine.register_client(self.binance_client) self.binance_client.connect() handler = [] subscribe = Subscribe( client_id=ClientId(BINANCE.value), data_type=DataType(QuoteTick, metadata={"instrument_id": ETHUSDT_BINANCE.id}), handler=handler.append, command_id=self.uuid_factory.generate(), timestamp_ns=self.clock.timestamp_ns(), ) self.data_engine.execute(subscribe) tick = QuoteTick( ETHUSDT_BINANCE.id, Price.from_str("100.003"), Price.from_str("100.003"), Quantity.from_int(1), Quantity.from_int(1), 0, 0, ) # Act self.data_engine.process(tick) # Assert self.assertEqual([ETHUSDT_BINANCE.id], self.data_engine.subscribed_quote_ticks) self.assertEqual([tick], handler)
def test_parse_quote_tick_from_string(self): # Arrange tick = QuoteTick( AUDUSD_FXCM, Price("1.00000"), Price("1.00001"), Quantity(1), Quantity(1), UNIX_EPOCH, ) # Act result = QuoteTick.from_serializable_string(AUDUSD_FXCM, tick.to_serializable_string()) # Assert self.assertEqual(tick, result)
def test_process_quote_tick_fills_sell_limit_order(self): # Arrange # Prepare market tick = TestStubs.quote_tick_3decimal(USDJPY_SIM.symbol) self.data_engine.process(tick) self.exchange.process_tick(tick) order = self.strategy.order_factory.limit( USDJPY_SIM.symbol, OrderSide.SELL, Quantity(100000), Price("90.100"), ) self.strategy.submit_order(order) # Act tick2 = QuoteTick( USDJPY_SIM.symbol, Price("90.101"), Price("90.102"), Quantity(100000), Quantity(100000), UNIX_EPOCH, ) self.exchange.process_tick(tick2) # Assert self.assertEqual(0, len(self.exchange.get_working_orders())) self.assertEqual(OrderState.FILLED, order.state) self.assertEqual(Price("90.100"), order.avg_price)
def test_expire_order(self): # Arrange # Prepare market tick1 = TestStubs.quote_tick_3decimal(USDJPY_SIM.symbol) self.data_engine.process(tick1) self.exchange.process_tick(tick1) order = self.strategy.order_factory.stop_market( USDJPY_SIM.symbol, OrderSide.BUY, Quantity(100000), Price("96.711"), time_in_force=TimeInForce.GTD, expire_time=UNIX_EPOCH + timedelta(minutes=1), ) self.strategy.submit_order(order) tick2 = QuoteTick( USDJPY_SIM.symbol, Price("96.709"), Price("96.710"), Quantity(100000), Quantity(100000), UNIX_EPOCH + timedelta(minutes=1), ) # Act self.exchange.process_tick(tick2) # Assert self.assertEqual(0, len(self.exchange.get_working_orders()))
def test_to_serializable_returns_expected_string(self): # Arrange tick = QuoteTick( AUDUSD_SIM.symbol, Price("1.00000"), Price("1.00001"), Quantity(1), Quantity(1), UNIX_EPOCH, ) # Act result = tick.to_serializable_string() # Assert self.assertEqual("1.00000,1.00001,1,1,0", result)
def test_process_quote_tick_when_subscriber_then_sends_to_registered_handler(self): # Arrange self.data_engine.register_client(self.binance_client) self.binance_client.connect() handler = [] subscribe = Subscribe( provider=BINANCE.value, data_type=DataType(QuoteTick, metadata={"InstrumentId": ETHUSDT_BINANCE.id}), handler=handler.append, command_id=self.uuid_factory.generate(), command_timestamp=self.clock.utc_now(), ) self.data_engine.execute(subscribe) tick = QuoteTick( ETHUSDT_BINANCE.id, Price("100.003"), Price("100.003"), Quantity(1), Quantity(1), UNIX_EPOCH, ) # Act self.data_engine.process(tick) # Assert self.assertEqual([ETHUSDT_BINANCE.id], self.data_engine.subscribed_quote_ticks) self.assertEqual([tick], handler)
def test_handle_quote_tick_when_volume_below_threshold_updates(self): # Arrange bar_store = ObjectStorer() handler = bar_store.store symbol = TestStubs.symbol_audusd() bar_spec = BarSpecification(10000, BarAggregation.VOLUME, PriceType.BID) bar_type = BarType(symbol, bar_spec) aggregator = VolumeBarAggregator(bar_type, handler, TestLogger(TestClock())) tick1 = QuoteTick( symbol=AUDUSD_SIM.symbol, bid=Price("1.00001"), ask=Price("1.00004"), bid_size=Quantity(3000), ask_size=Quantity(2000), timestamp=UNIX_EPOCH, ) # Act aggregator.handle_quote_tick(tick1) # Assert self.assertEqual(0, len(bar_store.get_store()))
def test_from_serializable_string_given_valid_string_returns_expected_tick(self): # Arrange tick = QuoteTick( AUDUSD_SIM.id, Price("1.00000"), Price("1.00001"), Quantity(1), Quantity(1), UNIX_EPOCH, ) # Act result = QuoteTick.from_serializable_str(AUDUSD_SIM.id, tick.to_serializable_str()) # Assert self.assertEqual(tick, result)
def test_market_value_when_insufficient_data_for_xrate_returns_none(self): # Arrange state = AccountState( account_id=AccountId("BITMEX", "01234"), balances=[Money("10.00000000", BTC), Money("10.00000000", ETH)], balances_free=[ Money("10.00000000", BTC), Money("10.00000000", ETH) ], balances_locked=[ Money("0.00000000", BTC), Money("0.00000000", ETH) ], info={}, event_id=uuid4(), event_timestamp=UNIX_EPOCH, ) account = Account(state) self.portfolio.register_account(account) order = self.order_factory.market( ETHUSD_BITMEX.symbol, OrderSide.BUY, Quantity(100), ) fill = TestStubs.event_order_filled( order=order, instrument=ETHUSD_BITMEX, position_id=PositionId("P-123456"), strategy_id=StrategyId("S", "001"), fill_price=Price("376.05"), ) last_ethusd = QuoteTick( ETHUSD_BITMEX.symbol, Price("376.05"), Price("377.10"), Quantity("16"), Quantity("25"), UNIX_EPOCH, ) position = Position(fill) self.portfolio.update_position( TestStubs.event_position_opened(position)) self.data_cache.add_quote_tick(last_ethusd) self.portfolio.update_tick(last_ethusd) # Act result = self.portfolio.market_values(BITMEX) # Assert # TODO: Currently no Quanto thus no xrate required self.assertEqual({ETH: Money('0.02659221', ETH)}, result)