Short-term alpha
The Cartea–Jaimungal additive reservation shift, the book-imbalance and order-flow-imbalance signals that feed it, and the OFI-synthesized toxicity fallback.
crates/vike-mm/src/alpha.rs is "the Cartea–Jaimungal short-term-alpha slot the A–S reservation
currently lacks — the additive drift term a·h − φ·q·h and its two microstructure signal inputs,
isolated so they unit-test without a runtime." It is pure f64 with naive folds and no mul_add,
"the reservation stack pins fold order".
The header names both sources: Cartea, Jaimungal and Penalva's Algorithmic and High-Frequency
Trading (2015) for "the inventory-penalized short-alpha market-making formulation: the optimal
quotes ride a reservation price shifted by an additive signal term a·(T−t) and a running inventory
penalty −φ·q·(T−t)", and Cont, Kukanov and Stoikov's The Price Impact of Order Book Events
(Journal of Financial Econometrics 12(1):47–88) for "the signed order-flow-imbalance (OFI) variable
e_n built from best-quote queue changes".
The two signals
Book imbalance. book_imbalance is the "normalized queue lean at the touch":
(bid_sz − ask_sz) / (bid_sz + ask_sz), "+1 all bid, −1 all ask, 0 balanced". A
non-positive denominator returns 0.0, "which also guards the division". It is read from the top
level of the same book view the maker prices from, so an own-filtered view feeds an own-filtered
imbalance.
Order-flow imbalance. OfiTracker is "an EWMA-decayed rolling sum of the signed best-quote
queue change e_n per book update". With the previous best (b', bs', a', as'):
e_bid = (bid >= b' ? bid_sz : 0) − (bid <= b' ? bs' : 0)
e_ask = (ask <= a' ? ask_sz : 0) − (ask >= a' ? as' : 0)
e_n = e_bid − e_ask"A bid stepping up or growing adds size (buy pressure, e_n > 0); a bid stepping down or an ask
stepping down/growing subtracts (sell pressure, e_n < 0)." The first update has no previous best
and only seeds state. Then ofi = ofi·decay + e_n, the decay "in [0, 1): 0 = memoryless, only
the latest e_n; near 1 = a long-memory sum." The default ofi_decay on AsParams is 0.9, and
"a live re-tune preserves the warm tracker (like σ̂²), so this is inert on a re-tune."
combine_alpha joins them linearly, beta·imbalance + lambda·ofi, "so the caller tunes each
channel independently (either weight 0 drops that channel)."
The shift
cj_reservation_shift returns alpha_signal · horizon − phi · q_norm · horizon. "Positive alpha
RAISES the reservation (lean into predicted up-drift); long inventory (q_norm > 0) with phi > 0
LOWERS it (lean to unwind). horizon = 0 (terminal) ⇒ both terms vanish."
Where it is applied is AsState::price in crates/vike-mm/src/avellaneda.rs, on the Group-B
override path described on Avellaneda–Stoikov. Two
details of that call site matter for tuning. The OFI tracker is advanced "ONLY when λ is active, so
an imbalance-only (or penalty-only) maker never pays for it." And the horizon passed is 1.0: "for
a continuously-requoting live maker the CJ time horizon is folded into the gains (β/λ/φ), so the
normalized unit horizon h = 1.0 is used rather than a wall-clock (T−t)." The three weights are
therefore per-tick gains in price units, not rates.
The knobs on AsParams: alpha_beta_imbalance (0.0 default — "positive β leans the
reservation into the heavier book side"), alpha_lambda_ofi (0.0 default — "the OFI channel is
off AND the OFI tracker is never advanced ⇒ byte-identical + free"), ofi_decay, and
running_penalty_phi (0.0 default — "an ADDITIONAL, horizon-scaled pull" on top of the A-S γ·V
skew, which is unchanged). All at their defaults, price takes the verbatim fast path and never
constructs the shift at all.
The toxicity fallback
ofi_toxicity synthesizes "a flow-toxicity INTENSITY in [0, 1] from an order-flow-imbalance
magnitude — the internal fallback the SpreadMaker feeds its flow-toxicity guard when no external
Strategy::on_flow reading exists": tox = 1 − exp(−|ofi| / scale), "reaching ~0.63 (1 − e⁻¹) at
|ofi| = scale", scale <= 0 disabling it. It "depends on |ofi| only, so it is symmetric in the
sign of the OFI (the CALLER derives the toxic SIDE from that sign)."
The caller is stage (3c-i) of SpreadMaker::requote in crates/vike-mm/src/quote.rs. Its side
mapping: "positive OFI = buy pressure ⇒ aggressive BUY takers lift our ASK ⇒ the ASK is the
toxic/adverse side"; negative OFI marks the bid. The guard then widens the toxic side by
tox · widen · half and cuts its size by (1 − tox · size_cut).max(0), "the size-to-zero case
routing through the maker's existing per-side suppression PULL path."
Three conditions, and an external reading wins for good
The synthesis runs only when a ToxicityParams guard is configured, ofi_toxicity_scale != 0, and
"NO external on_flow reading has ever arrived". The flow_external latch on SpreadMaker is
"set once Strategy::on_flow ever fires and never cleared, so an external toxicity feed takes
PRECEDENCE permanently … and never clobbers the real reading." And because the tracker only advances
while alpha_lambda_ofi != 0, the AsParams::ofi_toxicity_scale doc notes that "a live
synthesized signal also requires that channel on."
From a registry table the guard is built when either toxicity_widen or toxicity_size_cut is
present, and ofi_toxicity_scale "pairs with" them "so the internally-synthesized OFI reading can
actually fire from a registry table — no external on_flow feed exists in a backtest."
The standalone depth-imbalance study in the order-flow tree
is a separate implementation — "pure functions over &L2Book + ImbalanceTracker, a small
streaming wrapper that recomputes on every book update"; the signal here is computed inside the
maker from the view it is about to price.
Intensity fits
The κ estimators the spread's adverse-selection floor reads — the public-tape MLE, the censored own-fill hazard fit, the shrink between them, and the base-intensity profile GLFT prices with.
Multi-asset
The correlation-aware Guéant core — a covariance-matrix inventory skew whose value is entirely in the off-diagonal terms — and the fact that no live path calls it yet.