Class FixMarketDataView

java.lang.Object
com.quantfinlib.fix.FixMarketDataView

public final class FixMarketDataView extends Object
Garbage-free FIX 4.4 market-data reader — the feed half of the FIX hot path. FIX is the lingua franca of e-FX liquidity: most bank streams and many ECNs deliver prices as MarketDataSnapshotFullRefresh (35=W) and MarketDataIncrementalRefresh (35=X). Where FixMessage materializes Strings per tag (right for session plumbing), this is a flyweight in the mold of FixExecReportView: wrap(byte[], int, int) performs one pass over the framed bytes recording primitives into preallocated entry arrays, and every getter is primitive.

Subset (documented, honest): single-instrument messages — one Symbol (55) per message, entries carrying MDUpdateAction (279, X only; W entries are implicitly NEW), MDEntryType (269: '0' bid / '1' offer), MDEntryPx (270, scaled long: mantissa × 10^-decimals — the same representation the order encoder takes, so feed-to-order never touches a double) and MDEntrySize (271). Entry order within the message is preserved: for tiered LP streams, position IS the tier. Unknown tags are skipped without materializing anything.

Assumes an already-framed message: buffer[offset] is the first byte of a tag, every field is SOH-terminated (including the last), and checksum validation happened upstream — framing belongs to the transport layer (the session-lane FixDecoder materializes messages and is not this flyweight's feeder). Single-threaded: one view per feed thread — wrap, read, repeat. Zero allocation after construction.

  • Field Details

  • Constructor Details

    • FixMarketDataView

      public FixMarketDataView(int maxEntries)
      Parameters:
      maxEntries - entries retained per message (beyond that: counted, dropped)
    • FixMarketDataView

      public FixMarketDataView()
      32 entries — deeper than any real LP tier stack.
  • Method Details

    • wrap

      public boolean wrap(byte[] buffer, int offset, int length)
      Parses one framed message in place. Returns true for 35=W or 35=X; any other message type returns false immediately and leaves the getters undefined. Zero allocation.
    • isSnapshot

      public boolean isSnapshot()
      True for 35=W (full refresh), false for 35=X (incremental).
    • entryCount

      public int entryCount()
      Entries actually retained (bounded by the constructor's maxEntries).
    • declaredEntries

      public int declaredEntries()
      NoMDEntries (268) as declared by the sender.
    • action

      public byte action(int entry)
    • type

      public byte type(int entry)
    • pxMantissa

      public long pxMantissa(int entry)
      MDEntryPx as a scaled long: mantissa × 10^-decimals. Decimals follow the wire formatting and can differ per entry ("1.0850" → (10850, 4), "1.085" → (1085, 3)): never apply one entry's decimals to another's mantissa — compare via price(int) or rescale explicitly.
    • pxDecimals

      public int pxDecimals(int entry)
    • price

      public double price(int entry)
      MDEntryPx as a double — the safe conversion for double-domain consumers (fx.FxTierBook, fx.AggregatedBook). The scaled-long getters remain for pipelines that never touch a double.
    • size

      public long size(int entry)
    • droppedEntries

      public long droppedEntries()
      Entries dropped across the view's lifetime for exceeding maxEntries.
    • symbolEquals

      public boolean symbolEquals(byte[] asciiSymbol)
      In-place symbol comparison — same discipline as FixExecReportView.