Closed x-zho14 closed 8 months ago
Hi @x-zho14
The instrument ID string also needs a venue component, because we need to be able to identify all TRBUSDT
instruments which could be trading on other venues.
@staticmethod
def from_str(value: str) -> InstrumentId:
"""
Return an instrument ID parsed from the given string value.
Must be correctly formatted including characters either side of a single
period.
Examples: "AUD/USD.IDEALPRO", "BTCUSDT.BINANCE"
Parameters
----------
value : str
The instrument ID string value to parse.
Returns
-------
InstrumentId
"""
return InstrumentId.from_str_c(value)
So in your case you would need InstrumentId.from_str("TRBUSDT.BINANCE")
.
I'll make sure to add the potential of the ValueError
to the docs.
Hope that helps.
Hi, the self.instrument_id is "InstrumentId.from_str("TRBUSDT-PERP.BINANCE")"! and I get it pass to self.subscribe_order_book_snapshots(instrument_id=self.instrument_id,depth=20). I think I pass the correct "InstrumentId.from_str("TRBUSDT-PERP.BINANCE")". It only fails at snapshots and don't fail at others. You can also replicate this bug on your example, nautilus_trader/nautilus_trader/examples/strategies/volatility_market_maker.py by masking off
self.subscribe_order_book_snapshots(
self.instrument_id,
depth=20,
interval_ms=1000,
) # For debugging
@cjdsellers
I believe this happens for instrument ids containing -
, like BTCUSDT-PERP.
timer_name
is using -
as delimiter and if the InstrumentId contains a -
it is breaking the parsing in
_snapshot_order_book
cpdef void _handle_subscribe_order_book_snapshots(
self,
MarketDataClient client,
InstrumentId instrument_id,
dict metadata,
):
Condition.not_none(client, "client")
Condition.not_none(instrument_id, "instrument_id")
Condition.not_none(metadata, "metadata")
if instrument_id.is_synthetic():
self._log.error("Cannot subscribe for synthetic instrument `OrderBook` data.")
return
cdef:
uint64_t interval_ms = metadata["interval_ms"]
uint64_t interval_ns
uint64_t timestamp_ns
key = (instrument_id, interval_ms)
if key not in self._order_book_intervals:
self._order_book_intervals[key] = []
timer_name = f"OrderBook-{instrument_id}-{interval_ms}"
interval_ns = millis_to_nanos(interval_ms)
timestamp_ns = self._clock.timestamp_ns()
start_time_ns = timestamp_ns - (timestamp_ns % interval_ns)
...
When the timer event callback is executed InstrumentId.from_str_c
is breaking.
cpdef void _snapshot_order_book(self, TimeEvent snap_event):
cdef tuple pieces = snap_event.name.partition('-')[2].partition('-')
cdef InstrumentId instrument_id = InstrumentId.from_str_c(pieces[0])
cdef int interval_ms = int(pieces[2])
Switching the delimiter to pipe(|
) might be a quick fix for it.
timer_name = f"OrderBook|{instrument_id}|{interval_ms}"
Thanks for the suggestion there @dimitar-petrov
I went with the pipes, but then changed the parsing to make sure an instrument ID containing pipes doesn't break the new version too (Betfair uses instrument IDs with pipes).
Also, thanks again for the report and patience @x-zho14, looks like I was too quick to dismiss the issue.
Fix will be pushed to develop
branch soon 🙏
It has such error: