Manage MarketDataIncrementalRefresh

Hi,
it is not clear to me how to manage MarketDataIncrementalRefresh(X) message, in particular how to modify an existing book snapshot considering the MDUpdateAction(279) field.
When :

  • ‘0’ (New) → at which index ? (sort by price and then calc the index?)
  • ‘1’ (Update) → doc says, to replace the best book level with this one. How it is handled any update on other than the best position ?
  • ‘2’ (Delete) → which is the level index to be removed ?

Thanks,

Hi @frenz79,

Let me help clarify how to handle the MarketDataIncrementalRefresh message with respect to the MDUpdateAction(279) field.

Understanding the MDUpdateAction Field

'0' (New)

  • This indicates a new entry should be added to the order book.
  • To determine the index, entries are generally sorted by price in ascending order (for bids, descending for asks). Insert the new entry at the appropriate position based on this sorting logic.
  • If there’s already an entry at the same price level, this new entry might overwrite the existing one (depending on your application logic).

'1' (Update)

  • This action updates an existing book level.
  • The entry at the same price level (not necessarily the best price) should be replaced. Locate the price level using the Price field from the message, then update the corresponding Quantity or other details as provided in the update message.
  • If the Price level doesn’t exist in the book, you might need to log or handle this as a data inconsistency, depending on your requirements.

'2' (Delete)

  • This removes an entry from the order book.
  • Use the Price field to locate the index of the entry in the book. Once located, remove it from the snapshot.
  • If the price level is not found in the current snapshot, handle this as per your error-handling protocol (e.g., log a warning).

Clarification on BookTicker vs. Depth Stream

It’s worth noting that there may be some confusion between the BookTicker stream (depth = 1) and the Depth stream (depth >= 2).

  • For the BookTicker stream, this is approached as a “best quote stream” following FIX documentation. In this case, a change always replaces the previous quote entirely.
  • For the Depth stream, updates are handled as described above (new entries, updates, and deletions based on the specific price levels).

Best Practices

  1. Order Sorting: Ensure your order book is always sorted after any modification (New, Update, or Delete) for efficient access and integrity.
  2. Data Integrity: Cross-verify that the incremental updates align with the latest snapshot to prevent discrepancies.
  3. Edge Cases: Handle cases where an Update or Delete refers to a price level that does not exist gracefully, as this might happen during high-frequency updates.

Feel free to let me know if you’d like more examples or further clarifications!

1 Like

Thanks a lot, here I have all missing info!
However after a quick test, I can see that very often I get inconsistent updates. Here’s an example where the very first update is bad:

Market Data subscription:

18:52:14.180 [multiThreadIoEventLoopGroup-2-1] INFO  SESSION_MESSAGES - SND: 8=FIX.4.49=14335=V49=SPOTTEST56=SPOT34=252=20250204-17:52:14.178262=1b480fa9-b452-4c8a-9e44-600955ca512d263=1264=1146=155=BTCUSDT267=2269=0269=110=239

…getting the initial snapshot:

18:52:14.674 [multiThreadIoEventLoopGroup-2-1] INFO  SESSION_MESSAGES - RCV: 8=FIX.4.49=000021135=W49=SPOT56=SPOTTEST34=252=20250204-17:52:14.677470262=1b480fa9-b452-4c8a-9e44-600955ca512d55=BTCUSDT25044=14275971268=2269=0270=99013.39000000271=0.00359000269=1270=99013.40000000271=0.0039900010=198

…and then, 1 sec later, the update (279=1) but the two prices 99013.87000000 / 99013.88000000 don’t match the prices previously received 99013.39000000 / 99013.40000000.
No messages were lost in between as 35=W has seq=2 and 35=X has seq=3

18:52:15.739 [multiThreadIoEventLoopGroup-2-1] INFO  SESSION_MESSAGES - RCV: 8=FIX.4.49=000022335=X49=SPOT56=SPOTTEST34=352=20250204-17:52:15.743334262=1b480fa9-b452-4c8a-9e44-600955ca512d268=2**279=1**269=0270=99013.87000000271=0.0430300055=BTCUSDT25044=14275987**279=1**269=1270=99013.88000000271=0.0500000010=230

Hi frenz79,

I removed the previous comment after realizing it didn’t fully address your question and might have been confusing.

First of all, you have subscribed to the Book Ticker stream with DEPTH=1 (MarketDepth (264): '1'). This means the initial snapshot you receive will contain only the best BID and ASK price levels. All subsequent messages will continue to provide updates on the best BID and ASK in the current order book.

On the other hand, when you subscribe with DEPTH >= 2, you will receive a more detailed representation of the order book. However, it is important to note that this is still a partial representation, as the maximum depth is 5000. You can find more details in the documentation. All subsequent messages will provide updates (diffs) about the entire book.

To address your specific question: Since you subscribed to the top of the book only, you received 99013.87000000 as it was the top of the book at that given time. If you had subscribed to a greater depth, for example, MarketDepth=5000, you could have received a message about the 99013.39000000 price level if the quantity at this level had changed.

I hope this clarifies your query.

1 Like

Hi,
I’ve just fixed my code according to your details … definitely better now :smiley:
I will play a bit in the next days to check whether I’m still missing something, in any case thanks again for your precious support!

1 Like