def test_handle_trade_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.LAST) bar_type = BarType(instrument.id, bar_spec) aggregator = VolumeBarAggregator( instrument, bar_type, handler, Logger(TestClock()), ) tick1 = TradeTick( instrument_id=instrument.id, price=Price.from_str("1.00001"), size=Quantity.from_int(3000), aggressor_side=AggressorSide.BUY, trade_id=TradeId("123456"), ts_event=0, ts_init=0, ) tick2 = TradeTick( instrument_id=instrument.id, price=Price.from_str("1.00002"), size=Quantity.from_int(4000), aggressor_side=AggressorSide.BUY, trade_id=TradeId("123457"), ts_event=0, ts_init=0, ) tick3 = TradeTick( instrument_id=instrument.id, price=Price.from_str("1.00000"), size=Quantity.from_int(3000), aggressor_side=AggressorSide.BUY, trade_id=TradeId("123458"), ts_event=0, ts_init=0, ) # Act aggregator.handle_trade_tick(tick1) aggregator.handle_trade_tick(tick2) aggregator.handle_trade_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_position_filled_with_buy_order_returns_expected_attributes(self): # Arrange order = self.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), ) fill = TestEventStubs.order_filled( order, instrument=AUDUSD_SIM, position_id=PositionId("P-123456"), strategy_id=StrategyId("S-001"), last_px=Price.from_str("1.00001"), ) last = Price.from_str("1.00050") # Act position = Position(instrument=AUDUSD_SIM, fill=fill) # Assert assert position.symbol == AUDUSD_SIM.id.symbol assert position.venue == AUDUSD_SIM.id.venue assert not position.is_opposite_side(fill.order_side) assert not position != position # Equality operator test assert position.from_order == ClientOrderId( "O-19700101-000000-000-001-1") assert position.quantity == Quantity.from_int(100000) assert position.peak_qty == Quantity.from_int(100000) assert position.entry == OrderSide.BUY assert position.side == PositionSide.LONG assert position.ts_opened == 0 assert position.duration_ns == 0 assert position.avg_px_open == Decimal("1.00001") assert position.event_count == 1 assert position.client_order_ids == [order.client_order_id] assert position.venue_order_ids == [VenueOrderId("1")] assert position.trade_ids == [TradeId("E-19700101-000000-000-001-1")] assert position.last_trade_id == TradeId("E-19700101-000000-000-001-1") assert position.id == PositionId("P-123456") assert len(position.events) == 1 assert position.is_long assert not position.is_short assert position.is_open assert not position.is_closed assert position.realized_points == 0 assert position.realized_return == 0 assert position.realized_pnl == Money(-2.00, USD) assert position.unrealized_pnl(last) == Money(49.00, USD) assert position.total_pnl(last) == Money(47.00, USD) assert position.commissions() == [Money(2.00, USD)] assert repr( position) == "Position(LONG 100_000 AUD/USD.SIM, id=P-123456)"
def test_position_partial_fills_with_sell_order_returns_expected_attributes( self): # Arrange order = self.order_factory.market( AUDUSD_SIM.id, OrderSide.SELL, Quantity.from_int(100000), ) fill1 = TestEventStubs.order_filled( order, instrument=AUDUSD_SIM, trade_id=TradeId("1"), position_id=PositionId("P-123456"), strategy_id=StrategyId("S-001"), last_px=Price.from_str("1.00001"), last_qty=Quantity.from_int(50000), ) fill2 = TestEventStubs.order_filled( order, instrument=AUDUSD_SIM, trade_id=TradeId("2"), position_id=PositionId("P-123456"), strategy_id=StrategyId("S-001"), last_px=Price.from_str("1.00002"), last_qty=Quantity.from_int(50000), ) position = Position(instrument=AUDUSD_SIM, fill=fill1) last = Price.from_str("1.00050") # Act position.apply(fill2) # Assert assert position.quantity == Quantity.from_int(100000) assert position.side == PositionSide.SHORT assert position.ts_opened == 0 assert position.avg_px_open == Decimal("1.000015") assert position.event_count == 2 assert not position.is_long assert position.is_short assert position.is_open assert not position.is_closed assert position.realized_points == 0 assert position.realized_return == 0 assert position.realized_pnl == Money(-4.00, USD) assert position.unrealized_pnl(last) == Money(-48.50, USD) assert position.total_pnl(last) == Money(-52.50, USD) assert position.commissions() == [Money(4.00, USD)] assert repr( position) == "Position(SHORT 100_000 AUD/USD.SIM, id=P-123456)"
def nautilus_objects() -> List[Any]: """A list of nautilus instances for testing serialization""" instrument = TestInstrumentProvider.default_fx_ccy("AUD/USD") position_id = PositionId("P-001") buy = TestExecStubs.limit_order() buy_submitted, buy_accepted, buy_filled = _make_order_events( buy, instrument=instrument, position_id=position_id, trade_id=TradeId("BUY"), ) sell = TestExecStubs.limit_order(order_side=OrderSide.SELL) _, _, sell_filled = _make_order_events( sell, instrument=instrument, position_id=position_id, trade_id=TradeId("SELL"), ) open_position = Position(instrument=instrument, fill=buy_filled) closed_position = Position(instrument=instrument, fill=buy_filled) closed_position.apply(sell_filled) return [ TestDataStubs.ticker(), TestDataStubs.quote_tick_5decimal(), TestDataStubs.trade_tick_5decimal(), TestDataStubs.bar_5decimal(), TestDataStubs.venue_status_update(), TestDataStubs.instrument_status_update(), TestEventStubs.component_state_changed(), TestEventStubs.trading_state_changed(), TestEventStubs.betting_account_state(), TestEventStubs.cash_account_state(), TestEventStubs.margin_account_state(), # ORDERS TestEventStubs.order_accepted(buy), TestEventStubs.order_rejected(buy), TestEventStubs.order_pending_update(buy_accepted), TestEventStubs.order_pending_cancel(buy_accepted), TestEventStubs.order_filled( order=buy, instrument=instrument, position_id=open_position.id, ), TestEventStubs.order_canceled(buy_accepted), TestEventStubs.order_expired(buy), TestEventStubs.order_triggered(buy), # POSITIONS TestEventStubs.position_opened(open_position), TestEventStubs.position_changed(open_position), TestEventStubs.position_closed(closed_position), ]
def test_add_trade_reports(self): report_id1 = UUID4() mass_status = ExecutionMassStatus( client_id=ClientId("IB"), account_id=AccountId("IB", "U123456789"), venue=Venue("IDEALPRO"), report_id=report_id1, ts_init=0, ) report_id2 = UUID4() report1 = TradeReport( account_id=AccountId("IB", "U123456789"), instrument_id=AUDUSD_IDEALPRO, client_order_id=ClientOrderId("O-123456789"), venue_order_id=VenueOrderId("1"), venue_position_id=PositionId("2"), trade_id=TradeId("3"), order_side=OrderSide.BUY, last_qty=Quantity.from_int(100), last_px=Price.from_str("100.50"), commission=Money("4.50", USD), liquidity_side=LiquiditySide.TAKER, report_id=report_id2, ts_event=0, ts_init=0, ) report_id3 = UUID4() report2 = TradeReport( account_id=AccountId("IB", "U123456789"), instrument_id=AUDUSD_IDEALPRO, client_order_id=ClientOrderId("O-123456790"), venue_order_id=VenueOrderId("1"), venue_position_id=PositionId("2"), trade_id=TradeId("4"), order_side=OrderSide.BUY, last_qty=Quantity.from_int(100), last_px=Price.from_str("100.60"), commission=Money("4.50", USD), liquidity_side=LiquiditySide.TAKER, report_id=report_id3, ts_event=0, ts_init=0, ) # Act mass_status.add_trade_reports([report1, report2]) # Assert assert mass_status.trade_reports()[VenueOrderId("1")] == [report1, report2]
def test_passive_fill_on_trade_tick(self): # Arrange: Prepare market # Market is 10 @ 15 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) order = self.strategy.order_factory.limit( instrument_id=USDJPY_SIM.id, order_side=OrderSide.SELL, quantity=Quantity.from_int(2000), price=Price.from_str("14"), post_only=False, ) self.strategy.submit_order(order) # Act tick1 = TradeTick( instrument_id=USDJPY_SIM.id, price=Price.from_str("14.0"), size=Quantity.from_int(1000), aggressor_side=AggressorSide.SELL, trade_id=TradeId("123456789"), ts_event=0, ts_init=0, ) self.exchange.process_tick(tick1) # Assert assert order.status == OrderStatus.PARTIALLY_FILLED assert order.filled_qty == Quantity.from_int(1000.0) # No slippage assert order.avg_px == Decimal("14.0")
async def test_subscribe_trade_ticks(self, monkeypatch): handler = [] self.msgbus.subscribe( topic="data.trades.BINANCE.ETHUSDT", handler=handler.append, ) # Act self.data_client.subscribe_trade_ticks(ETHUSDT_BINANCE.id) raw_trade = pkgutil.get_data( package="tests.integration_tests.adapters.binance.resources.ws_messages", resource="ws_spot_trade.json", ) # Assert self.data_client._handle_ws_message(raw_trade) await asyncio.sleep(1) assert self.data_engine.data_count == 1 assert len(handler) == 1 # <-- handler received tick assert handler[0] == TradeTick( instrument_id=ETHUSDT_BINANCE.id, price=Price.from_str("4149.74000000"), size=Quantity.from_str("0.43870000"), aggressor_side=AggressorSide.SELL, trade_id=TradeId("705291099"), ts_event=1639351062243000064, ts_init=handler[0].ts_init, )
def parse_trade_report_http( account_id: AccountId, instrument_id: InstrumentId, data: BinanceFuturesAccountTrade, report_id: UUID4, ts_init: int, ) -> TradeReport: return TradeReport( account_id=account_id, instrument_id=instrument_id, venue_order_id=VenueOrderId(str(data.orderId)), venue_position_id=PositionId( f"{instrument_id}-{data.positionSide.value}"), trade_id=TradeId(str(data.id)), order_side=OrderSide[data.side.value], last_qty=Quantity.from_str(data.qty), last_px=Price.from_str(data.price), commission=Money(data.commission, Currency.from_str(data.commissionAsset)), liquidity_side=LiquiditySide.MAKER if data.maker else LiquiditySide.TAKER, report_id=report_id, ts_event=millis_to_nanos(data.time), ts_init=ts_init, )
def test_handle_trade_tick_when_value_below_threshold_updates(self): # Arrange bar_store = ObjectStorer() handler = bar_store.store instrument_id = TestIdStubs.audusd_id() bar_spec = BarSpecification(100000, BarAggregation.VALUE, PriceType.LAST) bar_type = BarType(instrument_id, bar_spec) aggregator = ValueBarAggregator( AUDUSD_SIM, bar_type, handler, Logger(TestClock()), ) tick1 = TradeTick( instrument_id=AUDUSD_SIM.id, price=Price.from_str("15000.00"), size=Quantity.from_str("3.5"), aggressor_side=AggressorSide.BUY, trade_id=TradeId("123456"), ts_event=0, ts_init=0, ) # Act aggregator.handle_trade_tick(tick1) # Assert assert len(bar_store.get_store()) == 0 assert aggregator.get_cumulative_value() == Decimal("52500.000")
def test_data_catalog_instrument_ids_correctly_unmapped(self): # Arrange catalog = DataCatalog.from_env() instrument = TestInstrumentProvider.default_fx_ccy("AUD/USD", venue=Venue("SIM")) trade_tick = TradeTick( instrument_id=instrument.id, price=Price.from_str("2.0"), size=Quantity.from_int(10), aggressor_side=AggressorSide.UNKNOWN, trade_id=TradeId("1"), ts_event=0, ts_init=0, ) write_objects(catalog=catalog, chunk=[instrument, trade_tick]) # Act instrument = catalog.instruments(instrument_ids=["AUD/USD.SIM"], as_nautilus=True)[0] trade_tick = catalog.trade_ticks(instrument_ids=["AUD/USD.SIM"], as_nautilus=True)[0] # Assert assert instrument.id.value == "AUD/USD.SIM" assert trade_tick.instrument_id.value == "AUD/USD.SIM"
async def generate_trades_list( self, venue_order_id: VenueOrderId, symbol: Symbol, since: datetime = None # type: ignore ) -> List[TradeReport]: filled = self.client().betting.list_cleared_orders( bet_ids=[venue_order_id], ) if not filled["clearedOrders"]: self._log.warn(f"Found no existing order for {venue_order_id}") return [] fill = filled["clearedOrders"][0] ts_event = int(pd.Timestamp(fill["lastMatchedDate"]).to_datetime64()) return [ TradeReport( client_order_id=self. venue_order_id_to_client_order_id[venue_order_id], venue_order_id=VenueOrderId(fill["betId"]), venue_position_id=None, # Can be None trade_id=TradeId(fill["lastMatchedDate"]), last_qty=Quantity.from_str(str( fill["sizeSettled"])), # TODO: Incorrect precision? last_px=Price.from_str(str( fill["priceMatched"])), # TODO: Incorrect precision? commission=None, # Can be None liquidity_side=LiquiditySide.NONE, ts_event=ts_event, ts_init=ts_event, ) ]
def test_handle_trade_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.LAST) bar_type = BarType(instrument.id, bar_spec) aggregator = VolumeBarAggregator( instrument, bar_type, handler, Logger(TestClock()), ) tick1 = TradeTick( instrument_id=instrument.id, price=Price.from_str("1.00001"), size=Quantity.from_int(1), aggressor_side=AggressorSide.BUY, trade_id=TradeId("123456"), ts_event=0, ts_init=0, ) # Act aggregator.handle_trade_tick(tick1) # Assert assert len(bar_store.get_store()) == 0
def test_to_dict_returns_expected_dict(self): # Arrange tick = TradeTick( instrument_id=AUDUSD_SIM.id, price=Price.from_str("1.00000"), size=Quantity.from_int(10000), aggressor_side=AggressorSide.BUY, trade_id=TradeId("123456789"), ts_event=0, ts_init=0, ) # Act result = TradeTick.to_dict(tick) # Assert assert result == { "type": "TradeTick", "instrument_id": "AUD/USD.SIM", "price": "1.00000", "size": "10000", "aggressor_side": "BUY", "trade_id": "123456789", "ts_event": 0, "ts_init": 0, }
def test_instantiate_trade_report(self): # Arrange, Act report_id = UUID4() report = TradeReport( account_id=AccountId("SIM", "001"), instrument_id=AUDUSD_IDEALPRO, client_order_id=ClientOrderId("O-123456789"), venue_order_id=VenueOrderId("1"), venue_position_id=PositionId("2"), trade_id=TradeId("3"), order_side=OrderSide.BUY, last_qty=Quantity.from_int(10000000), last_px=Price.from_str("100.50"), commission=Money("4.50", USD), liquidity_side=LiquiditySide.TAKER, report_id=report_id, ts_event=0, ts_init=0, ) # Assert assert ( str(report) == f"TradeReport(account_id=SIM-001, instrument_id=AUD/USD.IDEALPRO, client_order_id=O-123456789, venue_order_id=1, venue_position_id=2, trade_id=3, order_side=BUY, last_qty=10_000_000, last_px=100.50, commission=4.50 USD, liquidity_side=TAKER, report_id={report_id}, ts_event=0, ts_init=0)" # noqa ) assert ( repr(report) == f"TradeReport(account_id=SIM-001, instrument_id=AUD/USD.IDEALPRO, client_order_id=O-123456789, venue_order_id=1, venue_position_id=2, trade_id=3, order_side=BUY, last_qty=10_000_000, last_px=100.50, commission=4.50 USD, liquidity_side=TAKER, report_id={report_id}, ts_event=0, ts_init=0)" # noqa )
def test_serialize_and_deserialize_order_filled_events(self): # Arrange event = OrderFilled( self.trader_id, self.strategy_id, self.account_id, AUDUSD_SIM.id, ClientOrderId("O-123456"), VenueOrderId("1"), TradeId("E123456"), PositionId("T123456"), OrderSide.SELL, OrderType.MARKET, Quantity(100000, precision=0), Price(1.00000, precision=5), AUDUSD_SIM.quote_currency, Money(0, USD), LiquiditySide.TAKER, UUID4(), 0, 0, ) # Act serialized = self.serializer.serialize(event) deserialized = self.serializer.deserialize(serialized) # Assert assert deserialized == event
def parse_trade_tick_http(instrument_id: InstrumentId, msg: Dict, ts_init: int) -> TradeTick: return TradeTick( instrument_id=instrument_id, price=Price.from_str(msg["price"]), size=Quantity.from_str(msg["qty"]), aggressor_side=AggressorSide.SELL if msg["isBuyerMaker"] else AggressorSide.BUY, trade_id=TradeId(str(msg["id"])), ts_event=millis_to_nanos(msg["time"]), ts_init=ts_init, )
async def test_reconcile_state_no_cached_with_partially_filled_order_and_trade( self): # Arrange venue_order_id = VenueOrderId("1") order_report = OrderStatusReport( account_id=self.account_id, instrument_id=AUDUSD_SIM.id, client_order_id=ClientOrderId("O-123456"), venue_order_id=venue_order_id, order_side=OrderSide.BUY, order_type=OrderType.LIMIT, time_in_force=TimeInForce.GTC, order_status=OrderStatus.PARTIALLY_FILLED, price=Price.from_str("1.00000"), quantity=Quantity.from_int(10_000), filled_qty=Quantity.from_int(5_000), avg_px=Decimal("1.00000"), post_only=True, report_id=UUID4(), ts_accepted=0, ts_triggered=0, ts_last=0, ts_init=0, ) trade_report = TradeReport( account_id=self.account_id, instrument_id=AUDUSD_SIM.id, client_order_id=ClientOrderId("O-123456"), venue_order_id=venue_order_id, venue_position_id=None, trade_id=TradeId("1"), order_side=OrderSide.BUY, last_qty=Quantity.from_int(5_000), last_px=Price.from_str("1.00000"), commission=Money(0, USD), liquidity_side=LiquiditySide.MAKER, report_id=UUID4(), ts_event=0, ts_init=0, ) self.client.add_order_status_report(order_report) self.client.add_trade_reports(venue_order_id, [trade_report]) # Act result = await self.exec_engine.reconcile_state() # Assert assert result assert len(self.cache.orders()) == 1 assert self.cache.orders()[0].status == OrderStatus.PARTIALLY_FILLED
def create_trade_id(uo: Dict) -> TradeId: data: bytes = orjson.dumps(( uo["id"], uo["p"], uo["s"], uo["side"], uo["pt"], uo["ot"], uo["pd"], uo.get("md"), uo.get("avp"), uo.get("sm"), )) return TradeId(hashlib.sha1(data).hexdigest()) # noqa (S303 insecure SHA1)
def parse_trade_tick_ws( instrument_id: InstrumentId, data: BinanceTradeData, ts_init: int, ) -> TradeTick: return TradeTick( instrument_id=instrument_id, price=Price.from_str(data.p), size=Quantity.from_str(data.q), aggressor_side=AggressorSide.SELL if data.m else AggressorSide.BUY, trade_id=TradeId(str(data.t)), ts_event=millis_to_nanos(data.T), ts_init=ts_init, )
def parse_line(d): if "status" in d: return {} elif "close_price" in d: # return {'timestamp': d['remote_timestamp'], "close_price": d['close_price']} return {} if "trade" in d: ts = millis_to_nanos( pd.Timestamp(d["remote_timestamp"]).timestamp()) return { "timestamp": d["remote_timestamp"], "op": "trade", "trade": TradeTick( instrument_id=InstrumentId(Symbol("TEST"), Venue("BETFAIR")), price=Price(d["trade"]["price"], 4), size=Quantity(d["trade"]["volume"], 4), aggressor_side=d["trade"]["side"], trade_id=TradeId(d["trade"]["trade_id"]), ts_event=ts, ts_init=ts, ), } elif "level" in d and d["level"]["orders"][0]["volume"] == 0: op = "delete" else: op = "update" order_like = d["level"]["orders"][0] if op != "trade" else d[ "trade"] return { "timestamp": d["remote_timestamp"], "op": op, "order": Order( price=Price(order_like["price"], precision=6), size=Quantity(abs(order_like["volume"]), precision=4), # Betting sides are reversed side={ 2: OrderSide.BUY, 1: OrderSide.SELL }[order_like["side"]], id=str(order_like["order_id"]), ), }
def trade_tick_3decimal( instrument_id=None, price=None, aggressor_side=None, quantity=None, ) -> TradeTick: return TradeTick( instrument_id=instrument_id or TestIdStubs.usdjpy_id(), price=price or Price.from_str("1.001"), size=quantity or Quantity.from_int(100000), aggressor_side=aggressor_side or AggressorSide.BUY, trade_id=TradeId("123456"), ts_event=0, ts_init=0, )
def _handle_fills(self, instrument: Instrument, data: Dict[str, Any]) -> None: if data["type"] != "order": self._log.error(f"Fill not for order, {data}") return # Parse identifiers venue_order_id = VenueOrderId(str(data["orderId"])) client_order_id = self._order_ids.get(venue_order_id) if client_order_id is None: client_order_id = ClientOrderId(str(uuid.uuid4())) # TODO(cs): WIP # triggers = await self._http_client.get_trigger_order_triggers(venue_order_id.value) # # for trigger in triggers: # client_order_id = self._open_triggers.get(trigger) # if client_order_id is not None: # break # if client_order_id is None: # client_order_id = ClientOrderId(str(uuid.uuid4())) # Fetch strategy ID strategy_id: StrategyId = self._cache.strategy_id_for_order( client_order_id) if strategy_id is None: self._generate_external_trade_report(instrument, data) return self.generate_order_filled( strategy_id=strategy_id, instrument_id=instrument.id, client_order_id=client_order_id, venue_order_id=venue_order_id, venue_position_id=None, # NETTING accounts trade_id=TradeId(str(data["id"])), # Trade ID order_side=OrderSideParser.from_str_py(data["side"].upper()), order_type=self._order_types[venue_order_id], last_qty=Quantity(data["size"], instrument.size_precision), last_px=Price(data["price"], instrument.price_precision), quote_currency=instrument.quote_currency, commission=Money(data["fee"], Currency.from_str(data["feeCurrency"])), liquidity_side=LiquiditySide.MAKER if data["liquidity"] == "maker" else LiquiditySide.TAKER, ts_event=pd.to_datetime(data["time"], utc=True).to_datetime64(), ) if not self._calculated_account: self._loop.create_task(self._update_account_state())
def test_hash_str_and_repr(self): # Arrange tick = TradeTick( instrument_id=AUDUSD_SIM.id, price=Price.from_str("1.00000"), size=Quantity.from_int(50000), aggressor_side=AggressorSide.BUY, trade_id=TradeId("123456789"), ts_event=0, ts_init=0, ) # Act, Assert assert isinstance(hash(tick), int) assert str(tick) == "AUD/USD.SIM,1.00000,50000,BUY,123456789,0" assert repr(tick) == "TradeTick(AUD/USD.SIM,1.00000,50000,BUY,123456789,0)"
def test_from_dict_returns_expected_tick(self): # Arrange tick = TradeTick( instrument_id=AUDUSD_SIM.id, price=Price.from_str("1.00000"), size=Quantity.from_int(10000), aggressor_side=AggressorSide.BUY, trade_id=TradeId("123456789"), ts_event=0, ts_init=0, ) # Act result = TradeTick.from_dict(TradeTick.to_dict(tick)) # Assert assert tick == result
def test_process(self): # Arrange instrument = TestInstrumentProvider.btcusdt_binance() wrangler = TradeTickDataWrangler(instrument=instrument) path = os.path.join(PACKAGE_ROOT, "data", "tardis_trades.csv") data = TardisTradeDataLoader.load(path) # Act ticks = wrangler.process(data) # Assert assert len(ticks) == 9999 assert ticks[0].price == Price.from_str("9682.00") assert ticks[0].size == Quantity.from_str("0.132000") assert ticks[0].aggressor_side == AggressorSide.BUY assert ticks[0].trade_id == TradeId("42377944") assert ticks[0].ts_event == 1582329602418379008 assert ticks[0].ts_init == 1582329602418379008
def test_process(self): # Arrange ethusdt = TestInstrumentProvider.ethusdt_binance() wrangler = TradeTickDataWrangler(instrument=ethusdt) provider = TestDataProvider() # Act ticks = wrangler.process( provider.read_csv_ticks("binance-ethusdt-trades.csv")[:100]) # Assert assert len(ticks) == 100 assert ticks[0].price == Price.from_str("423.760") assert ticks[0].size == Quantity.from_str("2.67900") assert ticks[0].aggressor_side == AggressorSide.SELL assert ticks[0].trade_id == TradeId("148568980") assert ticks[0].ts_event == 1597399200223000064 assert ticks[0].ts_init == 1597399200223000064
def parse_trade_ticks_ws( instrument: Instrument, data: List[Dict[str, Any]], ts_init: int, ) -> List[TradeTick]: ticks: List[TradeTick] = [] for trade in data: tick: TradeTick = TradeTick( instrument_id=instrument.id, price=Price(trade["price"], instrument.price_precision), size=Quantity(trade["size"], instrument.size_precision), aggressor_side=AggressorSide.BUY if trade["side"] == "buy" else AggressorSide.SELL, trade_id=TradeId(str(trade["id"])), ts_event=pd.to_datetime(trade["time"], utc=True).to_datetime64(), ts_init=ts_init, ) ticks.append(tick) return ticks
def parse_trade_report( account_id: AccountId, instrument: Instrument, data: Dict[str, Any], report_id: UUID4, ts_init: int, ) -> TradeReport: return TradeReport( account_id=account_id, instrument_id=instrument.id, venue_order_id=VenueOrderId(str(data["orderId"])), trade_id=TradeId(str(data["tradeId"])), order_side=OrderSide.BUY if data["side"] == "buy" else OrderSide.SELL, last_qty=instrument.make_qty(data["size"]), last_px=instrument.make_price(data["price"]), commission=Money(data["fee"], Currency.from_str(data["feeCurrency"])), liquidity_side=LiquiditySide.TAKER if data["liquidity"] == "taker" else LiquiditySide.MAKER, report_id=report_id, ts_event=int(pd.to_datetime(data["time"], utc=True).to_datetime64()), ts_init=ts_init, )
def parse_trade_report_http( account_id: AccountId, instrument_id: InstrumentId, data: Dict[str, Any], report_id: UUID4, ts_init: int, ) -> TradeReport: return TradeReport( account_id=account_id, instrument_id=instrument_id, venue_order_id=VenueOrderId(str(data["orderId"])), trade_id=TradeId(str(data["id"])), order_side=OrderSide.BUY if data["isBuyer"] else OrderSide.SELL, last_qty=Quantity.from_str(data["qty"]), last_px=Price.from_str(data["price"]), commission=Money(data["commission"], Currency.from_str(data["commissionAsset"])), liquidity_side=LiquiditySide.MAKER if data["isMaker"] else LiquiditySide.TAKER, report_id=report_id, ts_event=millis_to_nanos(data["time"]), ts_init=ts_init, )
def _handle_market_trades( runner, instrument, ts_event, ts_init, ): trade_ticks = [] for price, volume in runner.get("trd", []): if volume == 0: continue # Betfair doesn't publish trade ids, so we make our own # TODO - should we use clk here for ID instead of the hash? trade_id = hash_json(data=(ts_event, price, volume)) tick = TradeTick( instrument_id=instrument.id, price=price_to_probability(str(price)), size=Quantity(volume, precision=4), aggressor_side=AggressorSide.UNKNOWN, trade_id=TradeId(trade_id), ts_event=ts_event, ts_init=ts_init, ) trade_ticks.append(tick) return trade_ticks