Class HftMarketDataBus

java.lang.Object
com.quantfinlib.marketdata.HftMarketDataBus
All Implemented Interfaces:
AutoCloseable

public final class HftMarketDataBus extends Object implements AutoCloseable
Ultra-low-latency market data bus. The hot path — publish(int, double, double, long) through TickListener.onTick(int, double, double, long) — performs zero allocation, zero locking, and zero map lookups:
  • Ticks travel through a preallocated primitive TickRingBuffer.
  • Symbols are dense int ids (SymbolRegistry); listener dispatch and the last-price cache are plain array indexing.
  • The consumer thread can busy-spin (Thread.onSpinWait()) for minimum hand-off latency, or park when latency matters less than CPU.

Setup calls (registerSymbol, subscribe) are not hot-path and may allocate. For the convenience object-based API (String symbols, multiple producers) see MarketDataProcessor; this bus is the single-producer HFT path.

Dispatch cost note: each subscribed listener is an interface call; with three or more distinct TickListener implementations on one symbol the call site goes megamorphic (~10-20 ns per listener, no inlining). Keep the per-symbol listener count at one or two and fan out inside your own listener when you need more consumers.

  • Constructor Details

    • HftMarketDataBus

      public HftMarketDataBus(int ringCapacity, int maxSymbols, boolean busySpin)
    • HftMarketDataBus

      public HftMarketDataBus()
      Parked (non-spinning) consumer with a 64K ring and up to 1024 symbols.
  • Method Details

    • registerSymbol

      public int registerSymbol(String symbol)
      Registers a symbol and returns the dense id used on the hot path.
    • symbolId

      public int symbolId(String symbol)
    • symbol

      public String symbol(int id)
    • subscribe

      public void subscribe(int symbolId, TickListener listener)
    • subscribeAll

      public void subscribeAll(TickListener listener)
    • start

      public void start()
    • stop

      public void stop()
      Stops the consumer after draining queued ticks.
    • close

      public void close()
      Specified by:
      close in interface AutoCloseable
    • publish

      public boolean publish(int symbolId, double price, double size, long timestampNanos)
      Publishes a tick; single producer thread, zero allocation. Returns false when the ring is full (caller decides: spin, drop, or shed load).
    • latestPrice

      public double latestPrice(int symbolId)
      Last traded price by symbol id; NaN before the first tick.
    • latestPrice

      public double latestPrice(String symbol)
    • processedCount

      public long processedCount()
    • ringFullCount

      public long ringFullCount()
      Failed publish attempts due to a full ring (backpressure events). A retrying producer increments this per attempt; it does not by itself mean ticks were lost — that is the caller's backpressure policy.