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.
crates/vike-mm/src/multi_asset.rs is the "multi-asset (correlation-aware) Guéant market-making
pure core — the covariance-matrix generalization of the single-asset A-S/GLFT inventory penalty".
It ports the Bergault–Guéant result (Guéant, Optimal market making; Bergault and Guéant, Size
matters for OTC market makers, arXiv 1606.01862 and 1810.04383): "for a maker holding an inventory
VECTOR q across N correlated assets with a returns covariance matrix Σ (per-ms σ², symmetric
PSD) and risk aversion γ, the reservation-price skew for asset i is the i-th component of the
matrix-vector product".
skew = γ · (Σ · q) → skewᵢ = γ · Σⱼ Σ[i][j]·q[j]
rᵢ = mᵢ − skewᵢBuilt, tested, and called by nothing on a live path
crates/vike-mm/src/lib.rs declares the module under #[allow(dead_code)]: it was "written ahead
of the live multi-symbol maker mount (a DEFERRED follow-up), so nothing on a live path calls it
yet; #[allow(dead_code)] keeps the merge-gate clippy green until the mount wires it in." Every
statement below is about a pure function with in-file tests, not about a maker you can mount.
Why a matrix
The header's argument: "This is the exact generalization of the single-asset reservation term
r = s − q·γ·V: the SCALAR variance penalty q·γ·V becomes the VECTOR penalty γ·(Σ·q). On a
DIAGONAL Σ (uncorrelated assets) it collapses back to N independent single-asset makers —
skewᵢ = γ·Σ[i][i]·q[i] — so the value of the matrix form is entirely in the OFF-DIAGONAL terms: a
position in a CORRELATED asset j leans asset i's reservation too. Holding a long BTC-perp
inventory therefore already skews the ETH-perp quote down, hedging the correlated exposure a fleet
of independent makers would each ignore — that cross-asset lean is the whole reason to run one
correlated maker over N separate ones."
The single-asset term it generalizes is crates/vike-mm/src/avellaneda.rs's
as_reservation_price, on the Avellaneda–Stoikov
page.
The two functions
multi_asset_skew(inventory, cov, gamma) returns the vector γ · (Σ · q); element i is
"gamma · Σⱼ cov[i][j]·inventory[j] (naive left-to-right fold, no mul_add)". Its guard is
deliberate: "a DIM MISMATCH — cov not square-of-side inventory.len() … returns a ZERO vector of
length inventory.len() (the inert, no-skew answer), rather than panicking or silently reading a
ragged matrix." An empty inventory returns an empty vector.
multi_asset_reservation(mids, inventory, cov, gamma) returns mids[i] − skew[i], "the multi-asset
twin of as_reservation_price's s − q_norm·γ·V. The shared quote assembly would post each side
around mids[i] − skewᵢ." On a mids/inventory length disagreement it falls back to the raw
mids — the same inert answer, one level up.
The dense matrix math is hand-rolled: "no linear-algebra crate — the matrices are tiny (N assets a
maker quotes, single digits), so a plain nested naive fold is both simplest and keeps the workspace
dependency/cargo deny surface flat." Two things are the caller's job, not this module's: "Σ
symmetry/PSD is the CALLER's contract (a covariance estimator's job), NOT enforced here."
What the tests pin
diagonal_cov_reduces_to_independent_single_asset: on a diagonal Σ eachskewᵢequalsγ·cov[i][i]·q[i], and the reservation matchesas_reservation_priceper asset "bit-for-parity".positive_off_diagonal_leans_correlated_asset: a long position in A with B flat and a positivecov[1][0]gives B a positive skew, so "B's reservationmid_B − skew_Bis pulled DOWN even with zero B inventory: the cross lean."negative_off_diagonal_flips_the_lean: a negative off-diagonal leans a flat B up.hand_computed_2x2_correlated_example: withγ = 0.5,q = [2, −3]andΣ = [[2, 1], [1, 2]], the skew is[0.5, −2.0]and mids[100, 50]become[99.5, 52.0].dim_mismatch_returns_zeros: wrong row count, a ragged row, and a mids/inventory mismatch all take the inert path.
The read a mount will need
The single-symbol seam cannot supply an inventory vector. crates/vike-model/src/strategy/mod.rs's
MultiHftBroker is "the MULTI-SYMBOL extension of HftBroker: the ONE extra read a
correlation-aware market maker needs that the single-symbol HftBroker cannot express — the signed
net inventory of a NAMED symbol", position_of(symbol), "so a maker quoting N correlated
instruments can read the WHOLE inventory vector q its covariance-matrix skew (γ·Σ·q, see
vike_mm::multi_asset) folds over." Because MultiHftBroker: HftBroker, a broker that answers
position_of can still mount any single-symbol maker, "and a plain single-symbol engine simply
cannot mount a maker that needs the multi read (the type system documents it)."
That trait exists; the maker that consumes it, and the covariance estimator that would own Σ, are the deferred follow-up the module was written ahead of. The index lists what is mounted today.
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.
Binary outcomes
Pricing a bounded [0,1] outcome token — the LMSR log-odds reservation, and the LS-LMSR and Glosten–Milgrom half-spread sources that replace the A-S vol/κ term.