Class HftOrderBook

java.lang.Object
com.quantfinlib.orderbook.HftOrderBook

public final class HftOrderBook extends Object
Venue-grade price-time-priority matching engine: the zero-allocation sibling of OrderBook, built the way exchange cores are actually built. Where OrderBook favors clarity (TreeMap, per-order objects) for research, this class favors the disciplines of a matching venue:
  • Dense integer-tick price ladder — one array slot per tick per side over a configured band; no tree, no comparator, no boxing. Prices are int ticks (convert once at the edge, e.g. via microstructure.TickSizeSchedule);
  • Occupancy bitmaps — one bit per price level per side, so advancing the best price over emptied levels is a word scan (Long.numberOfTrailingZeros), not a tree walk;
  • Pooled intrusive order nodes — every order lives in preallocated parallel primitive arrays, linked into its level's FIFO queue by index; placing, filling and cancelling recycle pool slots and allocate nothing (proven by the allocation-counter test, like every hot-path claim in this library);
  • Primitive open-addressing id map — order-id → node lookup by linear probing over long[]/int[], with backward-shift deletion so cancel churn never degrades into tombstone soup;
  • No iterators, no listeners list — a single primitive HftOrderBook.TradeSink callback.

Correctness is enforced two ways: the price-time semantics are asserted directly, and a model-based equivalence test drives this book and the reference OrderBook with identical randomized operation streams and demands identical books — the readable implementation is the executable specification of this one.

Threading: single-threaded by design, like real matching cores — one engine thread owns the book; fan orders in via trading.OrderRingBuffer and trades out via the sink. Rejections are return codes, never exceptions, because a venue must not unwind its matching loop over a bad order.

  • Nested Class Summary

    Nested Classes
    Modifier and Type
    Class
    Description
    static interface 
    Primitive fill callback: maker is the resting order, taker the incoming one.
  • Field Summary

    Fields
    Modifier and Type
    Field
    Description
    static final long
     
    static final long
     
    static final long
    Accepted-order ids are positive; these are the rejection codes.
    static final long
    Post-only order would have crossed the spread and taken liquidity.
  • Constructor Summary

    Constructors
    Constructor
    Description
    HftOrderBook(int minPriceTick, int maxPriceTick, int maxOrders)
     
  • Method Summary

    Modifier and Type
    Method
    Description
    long
     
    int
    Best ask in absolute ticks; Integer.MAX_VALUE when no asks.
    long
     
    int
    Best bid in absolute ticks; Integer.MIN_VALUE when no bids.
    boolean
    cancel(long orderId)
    Cancels a resting order.
    long
     
    long
    openQuantity(long orderId)
    Open (unfilled, uncancelled) quantity of an order; 0 when gone.
    long
     
    long
    qtyAtTick(Side side, int priceTick)
    Resting quantity at an absolute tick (0 when off-band or empty).
    int
    Orders currently resting in the book (pool slots in use).
    int
    snapshot(Side side, int[] outTicks, long[] outQtys)
    Depth snapshot into caller-provided arrays (absolute ticks + level quantities, best-first): zero allocation.
    long
    submitFok(Side side, int priceTick, long quantity, long timestampNanos)
    Fill-or-kill: executes the full quantity within the limit price or does nothing at all.
    long
    submitIoc(Side side, int priceTick, long quantity, long timestampNanos)
    Immediate-or-cancel: a price-limited taker — matches while it crosses, and the remainder expires instead of resting.
    long
    submitLimit(Side side, int priceTick, long quantity, long timestampNanos)
    Limit order: matches against the opposite side while it crosses, rests any remainder at priceTick.
    long
    submitMarket(Side side, long quantity, long timestampNanos)
    Market order: matches against the whole opposite book, never rests.
    long
    submitPostOnly(Side side, int priceTick, long quantity, long timestampNanos)
    Post-only (add-liquidity-only) limit order: rests at priceTick, or is rejected with REJECT_WOULD_CROSS when it would trade on arrival — the maker-fee-preserving order type.
    long
     
    void
    Installs the (single) trade callback; call before trading.

    Methods inherited from class java.lang.Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Field Details

    • REJECT_POOL_FULL

      public static final long REJECT_POOL_FULL
      Accepted-order ids are positive; these are the rejection codes.
      See Also:
    • REJECT_OUT_OF_BAND

      public static final long REJECT_OUT_OF_BAND
      See Also:
    • REJECT_INVALID

      public static final long REJECT_INVALID
      See Also:
    • REJECT_WOULD_CROSS

      public static final long REJECT_WOULD_CROSS
      Post-only order would have crossed the spread and taken liquidity.
      See Also:
  • Constructor Details

    • HftOrderBook

      public HftOrderBook(int minPriceTick, int maxPriceTick, int maxOrders)
      Parameters:
      minPriceTick - lowest representable price, in ticks (inclusive)
      maxPriceTick - highest representable price, in ticks (inclusive)
      maxOrders - resting-order capacity (pool size, fixed forever)
  • Method Details

    • tradeSink

      public void tradeSink(HftOrderBook.TradeSink sink)
      Installs the (single) trade callback; call before trading.
    • submitLimit

      public long submitLimit(Side side, int priceTick, long quantity, long timestampNanos)
      Limit order: matches against the opposite side while it crosses, rests any remainder at priceTick. Returns the positive order id on acceptance (also the taker id in emitted trades — even a fully filled order was accepted), or a negative rejection code. Zero allocation.
    • submitMarket

      public long submitMarket(Side side, long quantity, long timestampNanos)
      Market order: matches against the whole opposite book, never rests. Returns the filled quantity (0 when the opposite side is empty).
    • submitIoc

      public long submitIoc(Side side, int priceTick, long quantity, long timestampNanos)
      Immediate-or-cancel: a price-limited taker — matches while it crosses, and the remainder expires instead of resting. Returns the filled quantity (0 when nothing crossed). Zero allocation.
    • submitFok

      public long submitFok(Side side, int priceTick, long quantity, long timestampNanos)
      Fill-or-kill: executes the full quantity within the limit price or does nothing at all. Returns quantity on fill, 0 on kill — a killed order emits no trades and consumes no id/counters, like a venue rejecting pre-match. Zero allocation (the liquidity probe walks the same occupancy bitmaps as matching).
    • submitPostOnly

      public long submitPostOnly(Side side, int priceTick, long quantity, long timestampNanos)
      Post-only (add-liquidity-only) limit order: rests at priceTick, or is rejected with REJECT_WOULD_CROSS when it would trade on arrival — the maker-fee-preserving order type. Returns the positive order id on acceptance.
    • cancel

      public boolean cancel(long orderId)
      Cancels a resting order. False when unknown/already gone — never throws.
    • bestBidTick

      public int bestBidTick()
      Best bid in absolute ticks; Integer.MIN_VALUE when no bids.
    • bestAskTick

      public int bestAskTick()
      Best ask in absolute ticks; Integer.MAX_VALUE when no asks.
    • bestBidSize

      public long bestBidSize()
    • bestAskSize

      public long bestAskSize()
    • qtyAtTick

      public long qtyAtTick(Side side, int priceTick)
      Resting quantity at an absolute tick (0 when off-band or empty).
    • openQuantity

      public long openQuantity(long orderId)
      Open (unfilled, uncancelled) quantity of an order; 0 when gone.
    • snapshot

      public int snapshot(Side side, int[] outTicks, long[] outQtys)
      Depth snapshot into caller-provided arrays (absolute ticks + level quantities, best-first): zero allocation. Returns levels written (bounded by the shorter array).
    • orderCount

      public long orderCount()
    • cancelCount

      public long cancelCount()
    • tradeCount

      public long tradeCount()
    • restingOrders

      public int restingOrders()
      Orders currently resting in the book (pool slots in use).