I’ve been recording raw logs from NinjaTrader’s OnMarketDepth event (e.g., lines indicating "Add", "Remove", "Update" at certain positions and prices) and want to reconstruct a valid order book (DOM) from those logs alone. I’m aware NinjaTrader typically uses several events (OnOrderUpdate, OnMarketData, etc.) to get a complete picture, but I’m interested only in the OnMarketDepth approach.
Here are the main questions and uncertainties I have:
- Shifting Logic
- In some existing code examples, I’ve seen an array-based approach that “shifts up” the entire side when position=0 changes to a new best price.
- Does the official NinjaTrader OnMarketDepth pipeline explicitly shift arrays behind the scenes, or is that purely a UI concept (e.g., re-sorting rows)?
- Under which conditions should I forcibly shift levels in my code if I’m strictly using the (operation, position, price, volume) logs from OnMarketDepth?
- Position vs. Price
- The logs might say "Add, position=7, price=2891.25, volume=5". Do I store that in a dictionary keyed by position or do I store data keyed by price and treat position as more of a “visual rank”?
- Which approach (array-based vs. dictionary-based) is recommended to remain consistent with how NinjaTrader’s DOM is updated in real time?
- Add / Remove / Update
- From the logs, I see lines like:Ask, Add, 7, 2891.25, 5
Ask, Remove, 0, 2888, 0
Ask, Update, 0, 2900, 15- How exactly does NinjaTrader handle these behind the scenes?
- If I see "Remove" at position=0, do I zero out volume for that slot, or must I re-index subsequent positions?
- If I see "Add" at position=7 with a new price, do I overwrite any existing price at 7 or do I shift the old price to position 8?
- How exactly does NinjaTrader handle these behind the scenes?
- From the logs, I see lines like:Ask, Add, 7, 2891.25, 5
- Data Stability
- If my logs arrive in chronological order, can I assume all “Remove” operations for a level happen before a new “Add” for that same position?
- What if the feed sends “Remove at pos=0, price=2891.25” and immediately “Add at pos=0, price=2892.00, volume=10”?
- Which validations does NinjaTrader do internally to avoid a corrupt DOM if logs arrive slightly out of sequence?
- Partial Fills / Volume Changes
- Even though I’m ignoring OnOrderUpdate or OnMarketData, OnMarketDepth can reflect volume decreases (like “Update” from volume=8 to volume=3 at the same (side, pos, price)).
- How do we handle partial volume changes in the official approach? Does NinjaTrader do anything special to track the “queue position,” or is it purely (new volume, old volume) differences?
- Recommended “Best Practice”
- Ultimately, I want a stable approach:
- Minimal resets—avoid discarding the entire book if a single line references a surprising price.
- Accurate shifting—only apply a “shift up/down” if that’s truly how NinjaTrader organizes the DOM.
- Valid final snapshot—my code should end up with a list/array/dictionary that matches the official DOM if I replay all the logs from OnMarketDepth.
- Ultimately, I want a stable approach:
- Missing Classes
- The partial code I’ve seen references classes like MarketDepth, LadderRow, or PriceRow. Could you clarify how they work with OnMarketDepth behind the scenes?
- Which of these classes is primarily responsible for the re-sorting or shifting?
- Sample or Reference Implementation
- Are there official (or community) examples demonstrating how to store and update the DOM purely from OnMarketDepth logs?
- Any “exact” logic on how NinjaTrader merges 'Add', 'Remove', and 'Update' lines for the same (side, pos)?
I’d greatly appreciate any guidance or clarifications from NinjaTrader staff or experienced community members on how to replicate a valid order book exclusively using the OnMarketDepth feed. Specifically, when to shift levels, how to store (pos, price, volume) consistently, and what checks to perform to keep the data stable.
Thank you in advance for your expertise and time!

Comment