Class VenueScorecard
java.lang.Object
com.quantfinlib.execution.VenueScorecard
Streaming per-venue execution quality — the equities counterpart of
fx.LpScorecard: displayed prices tell you where a venue CLAIMS
you'll trade; the scorecard tells you what actually happens when you send
there. Everything the AdaptiveSor needs beyond the quote:
- Fill rate — EWMA of {1 fill, 0 miss} per marketable child: the venue's reliability. Quotes fade, systems reject, sessions hiccup — a venue that fills 80% of what you send is worth less than its displayed price says;
- Response latency — EWMA of send→ack/fill time as YOU measure it, which routinely disagrees with the venue's advertised number;
- Hidden liquidity — for dark venues, an EWMA of the shares each probe actually found. "Unknown" hardens into an estimate the only honest way: by probing and remembering;
- Post-fill markout (adverse selection) — what the mid does
one horizon after your fill, signed in your trading direction:
positive = the price kept going your way (a clean fill), negative
= it reverted (you paid the spread to trade against informed or
stale flow — the "fade" venues). Arm it via the extended
onFill(int, long, boolean, double, long)and feed mids viaonMid(double, long); the equities counterpart offx.LpScorecard's post-REJECT markout. The markout leg makes the card single-symbol:onMid(double, long)matures every pending fill against the one mid it is given, and the markout is in absolute price units — one card per symbol once you use it (the fill-rate/latency stats alone were symbol-agnostic).
All statistics are exponentially weighted per event so the card tracks
current behavior (each EWMA seeds from the prior / first observation, so a
venue is never scored below "never tried" for its first fill). Before any
data, fillRate(int) returns a configurable optimistic prior (a new
venue deserves flow until it proves otherwise). Zero allocation per event,
single writer (the execution-events thread).
This is the streaming venue-quality tool for the routing hot
path; VenueBenchmark is the batch counterpart (fill rate,
effective spread and markout over a sample list) for post-trade venue
analysis.
-
Field Summary
FieldsModifier and TypeFieldDescriptionstatic final intPending fill-markout slots per venue (bursts deeper overwrite oldest). -
Constructor Summary
ConstructorsConstructorDescriptionVenueScorecard(int venueCount) 5% event weight, 0.95 prior, 100 ms markout horizon.VenueScorecard(int venueCount, double alpha, double fillRatePrior) 100 ms markout horizon.VenueScorecard(int venueCount, double alpha, double fillRatePrior, long markoutHorizonNanos) -
Method Summary
Modifier and TypeMethodDescriptiondoubleexpectedHiddenShares(int venue) EWMA shares found per dark probe (0 before any probe).longfilled(int venue) doublefillRate(int venue) EWMA fill probability; the optimistic prior before any data.doubleThe before-any-data prior (also what unregistered venues score as).longFill markouts matured across all venues — the wiring canary: zero while fills accrue meansonMid(double, long)is not being fed and the router's adverse-selection term is silently disabled.doublemeasuredLatencyNanos(int venue) EWMA measured response latency in nanos (0 before any data).voidonDarkProbe(int venue, long sharesFilled) A dark probe's outcome: how many shares it actually found (0 is a real observation — an empty pool teaches as much as a full one).voidonFill(int venue, long responseNanos) A marketable child filled (fully or partially counts as a fill).voidonFill(int venue, long responseNanos, boolean buy, double midAtFill, long timestampNanos) A fill WITH the context that arms its markout: direction, the mid at fill time, and the fill timestamp.voidonMid(double mid, long timestampNanos) Mid update FOR THE CARD'S ONE SYMBOL (see the class doc): matures every pending fill markout whose horizon has elapsed.voidonMiss(int venue, long responseNanos) A marketable child that came back unfilled (faded, rejected, expired).doublepostFillMarkout(int venue) EWMA post-fill markout in price units — positive means the mid kept moving your way after fills at this venue; negative means it reverted: you crossed the spread into informed or stale flow, the per-share costAdaptiveSorprices as adverse selection. 0 before any matured markout.longprobes(int venue) voidRestores the card; pending fill markouts (intraday) reset.longsent(int venue) intvoidwriteState(DataOutput out) Persists the learned venue quality — fill rates, measured latencies, dark-probe estimates and fill markouts are exactly what a router should not have to relearn every morning.
-
Field Details
-
PENDING_RING
public static final int PENDING_RINGPending fill-markout slots per venue (bursts deeper overwrite oldest).- See Also:
-
-
Constructor Details
-
VenueScorecard
public VenueScorecard(int venueCount, double alpha, double fillRatePrior, long markoutHorizonNanos) - Parameters:
venueCount- number of venues (dense indices)alpha- EWMA weight per event, e.g. 0.05fillRatePrior- fill rate assumed before any data, e.g. 0.95markoutHorizonNanos- how long after a fill the markout is read, e.g. 100ms =100_000_000L
-
VenueScorecard
public VenueScorecard(int venueCount, double alpha, double fillRatePrior) 100 ms markout horizon. -
VenueScorecard
public VenueScorecard(int venueCount) 5% event weight, 0.95 prior, 100 ms markout horizon.
-
-
Method Details
-
onFill
public void onFill(int venue, long responseNanos) A marketable child filled (fully or partially counts as a fill). -
onMiss
public void onMiss(int venue, long responseNanos) A marketable child that came back unfilled (faded, rejected, expired). -
onFill
public void onFill(int venue, long responseNanos, boolean buy, double midAtFill, long timestampNanos) A fill WITH the context that arms its markout: direction, the mid at fill time, and the fill timestamp. Feed mids viaonMid(double, long)and the move one horizon later is attributed to this venue. A NaN mid still counts the fill but can never start a markout (maturing against NaN would poison the EWMA and silently distort routing). -
onMid
public void onMid(double mid, long timestampNanos) Mid update FOR THE CARD'S ONE SYMBOL (see the class doc): matures every pending fill markout whose horizon has elapsed. Non-finite mids are ignored — one Inf sentinel maturing a slot would seed the EWMA at ±Inf and the next blend would NaN it forever, silently disabling the router's adverse-selection term. The common no-pending case is a single compare. -
onDarkProbe
public void onDarkProbe(int venue, long sharesFilled) A dark probe's outcome: how many shares it actually found (0 is a real observation — an empty pool teaches as much as a full one). The estimate seeds from the first probe rather than ramping from 0, so one good probe doesn't collapse subsequent probe sizes. -
fillRate
public double fillRate(int venue) EWMA fill probability; the optimistic prior before any data. -
fillRatePrior
public double fillRatePrior()The before-any-data prior (also what unregistered venues score as). -
measuredLatencyNanos
public double measuredLatencyNanos(int venue) EWMA measured response latency in nanos (0 before any data). -
postFillMarkout
public double postFillMarkout(int venue) EWMA post-fill markout in price units — positive means the mid kept moving your way after fills at this venue; negative means it reverted: you crossed the spread into informed or stale flow, the per-share costAdaptiveSorprices as adverse selection. 0 before any matured markout. -
maturedFillMarkouts
public long maturedFillMarkouts()Fill markouts matured across all venues — the wiring canary: zero while fills accrue meansonMid(double, long)is not being fed and the router's adverse-selection term is silently disabled. -
sent
public long sent(int venue) -
filled
public long filled(int venue) -
probes
public long probes(int venue) -
venueCount
public int venueCount() -
writeState
Persists the learned venue quality — fill rates, measured latencies, dark-probe estimates and fill markouts are exactly what a router should not have to relearn every morning. Format version 2 (version 1, from before the markout existed, is still readable). Seepersist.Checkpoint.- Throws:
IOException
-
readState
Restores the card; pending fill markouts (intraday) reset. Reads both format versions: a v1 checkpoint restores everything it has and leaves the markout state cold. Throws on a venue-count mismatch or an unknown version.- Throws:
IOException
-