예제 #1
0
    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)
예제 #3
0
    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,
        }
예제 #4
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)
예제 #6
0
    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)
예제 #7
0
    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
예제 #8
0
    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())
예제 #9
0
    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())
예제 #12
0
    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)
예제 #13
0
    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)
예제 #14
0
    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)
예제 #18
0
    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)
예제 #19
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)
예제 #20
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(
            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())
예제 #21
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_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)
예제 #23
0
    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)
예제 #24
0
    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)
예제 #25
0
    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()))
예제 #26
0
    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)
예제 #27
0
    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()))
예제 #29
0
    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)