Market making
Market making is quoting both sides of a book — resting a bid below the market and an offer above it — and earning the spread between them when both get hit. The position you are paid for is the inventory you accumulate while doing it, and the two things that destroy a market maker are the same two things every model on this page is about: inventory risk, the chance the market moves against the position you were left holding, and adverse selection, the chance the flow hitting your quote knew something.
Vike Trader ships a market-making crate rather than a spread template. It carries a reference quoting strategy written against a tagged-resting-order broker seam, the Avellaneda–Stoikov reservation-price layer with its closed-form optimal half-spread, the Guéant–Lehalle–Fernandez-Tapia stationary form, LMSR and Glosten–Milgrom models native to binary-outcome venues, inventory skew with a round-trip-netting circuit breaker, ladder quoting, and a break-even floor that refuses to quote rather than quoting into a fee it cannot clear.
The maker
A market maker needs verbs an ordinary strategy does not, so it is written against an extension of the portable broker trait: a signed position read plus tagged submit, modify and cancel. A tag is a strategy-chosen stable id naming one resting order, so a later re-price or cancel resolves it without the strategy ever seeing a client order id — the id registry belongs to the runtime. The resting bid and ask carry the obvious two tags, and the maker re-prices them in place through a modify, which preserves venue queue priority, rather than cancelling and replacing.
Because that extension trait sits above the common denominator, the type system documents the requirement: a plain backtest engine over the portable trait cannot mount a maker at all. There is no runtime coupling either — the crate depends on the vocabulary crate alone, and the live core mounts the maker rather than owning it.
Layers that compose, and are inert when off
The maker is a stack of additions, each with the same contract: off by default, and byte-identical to the maker beneath it when off. In the strategy's own words, the breaker decides which sides quote, the skew decides their sizes, and the style and filter decide their prices.
| Layer | Its off state |
|---|---|
| Fixed mid-plus-or-minus-half-spread quoting | the base |
| Inventory-skewed sizes | a zero skew gives multipliers of exactly one |
| Per-side fill-rate circuit breaker | any of window, threshold or cooldown non-positive |
| Quote-style registry and own-order filtration | mid placement, filtration off |
| Avellaneda–Stoikov pricing | no reservation state attached |
| Refresh tolerance | unset, or an all-zero bag |
| Ladder quoting | one level per side |
| Liquidity-reward shaping | a zero weight |
| Flow-toxicity response | both knobs zero, or no reading ever delivered |
Placement, when the reservation layer is not pricing, is one of four pure styles: quote around the mid, join the touch, step one tick in front of it, or rest at a chosen depth level. Own-order filtration subtracts your own resting size from the public book before placement, so a step-in-front maker cannot step in front of — or rest on top of — itself. A level whose remaining size goes to zero is removed entirely, so the derived best shifts to the next genuine market level.
Configuration and state are separate
The maker's whole tunable configuration is one bag, and it is deliberately configuration only. Runtime state — the per-side resting snapshot, ladder rungs, breaker deadlines, the fill window, the own-order ladder, the learned venue tick — lives beside it and a live re-tune never touches it. So re-tuning a running maker keeps its resting orders, its queue position and its learned state, and a counter bumps so a caller can confirm the re-tune actually landed rather than assuming it.
Across a restart, deliberately little persists: the breaker's suppression deadlines and, where the reservation layer is on, the online estimator's accumulators. Not the resting-order cache, which the reconcile pass rediscovers, and not the parameters — because a restart with a different tuning should price with the new tuning, not with a stale saved one.
Avellaneda–Stoikov
The Avellaneda–Stoikov layer replaces symmetric quoting around the mid with a reservation price — the price at which the maker is indifferent given the inventory it is already carrying — and a half-spread with two named components: one paying for inventory risk over the holding horizon, one paying for adverse selection given how quickly quotes get filled.
reservation price r = s − q · γ · V
optimal half-spread d = ½·γ·V + (1/γ)·ln(1 + γ/κ)
effective variance V = min(σ̂²·H, p·(1−p))
Here s is the fair mid, q the size-normalised signed inventory,
γ risk aversion, κ the fill-intensity decay and H the
effective horizon. The final term is the bounded-price adaptation: on a venue whose prices live on
the unit interval, capping the variance by the Bernoulli variance makes skew and spread vanish at
the walls and peak at the coin-flip mid, which keeps the model from over-penalising inventory near
a boundary it cannot cross.
Every input has exactly one owner. Fair value is the raw mid, or optionally the micro-price weighted toward the side with less resting size; a one-sided book returns nothing and the maker holds rather than quoting off half a book. The volatility estimate is one exponentially weighted step over per-millisecond mid variance. The horizon is either a constant holding time or the smaller of that and the time to a known resolution. And the fill-intensity term is either a fixed constant, a maximum-likelihood fit over the public trade tape, or a censored fit over the maker's own fill outcomes — the last reflecting the adverse selection this maker actually faces at its own quoted distances, shrunk toward the public fit until it has enough samples.
The width ladder, and the refusal at the end of it
A raw model half-spread becomes a posted one through three stages, and the order is the whole design: a minimum floor in ticks (the sub-tick guard, without which the adverse-selection term snaps both quotes to one tick on a large-denomination book), a maximum cap re-floored against that minimum so a misconfigured cap can never sacrifice the two-sided quote, and a break-even fee floor derived from the venue's round-trip maker fee.
The third stage deliberately does not join the take-the-larger idiom. The cap answers "how wide may I go and still hope to fill?"; the fee floor answers "how wide must I be to not lose money?" — and when they disagree the answer is to post nothing. That disagreement is a fact about the instrument, not about the tuning: on one measured live perpetual mount a ceiling that permitted under two basis points of capture sat against a four-basis-point round-trip fee, which is a guaranteed loss per round trip, forever. The cure is a different instrument or a different fee tier, never a wider cap.
Whatever priced the quote, the posting geometry is shared: the bid is pushed no higher than the fair mid less a standoff and the ask no lower than the mid plus one, so inventory skew can never push a quote across the mid; the pair is clamped to the venue's price walls, snapped to the grid round-half-to-even, and accepted only if it is a genuine, correctly ordered two-sided quote that still straddles the fair mid. Anything else is a hold, the same contract a one-sided book gets.
The Guéant closed form
The Guéant–Lehalle–Fernandez-Tapia model gives a stationary solution to the same problem: a skew coefficient that depends on volatility, risk aversion, the intensity decay and the base fill intensity at the touch, with no holding horizon in it at all.
S = sqrt( σ̂²·γ / (2·κ·A) · (1 + γ/κ)^(1 + κ/γ) )
It rides the same posting assembly: feeding it through as an effective variance makes the posted depths the same affine shape the reservation form emits, so everything downstream — the size skew, the breaker, the own-order filtration, the modify-in-place tail — is unchanged. The horizon, the settlement term and the Bernoulli cap are ignored here, because this form is horizon-free by construction. A test pins the identity: at matching variance the two forms agree bit-exactly, which is how you know the second model is a re-parameterisation rather than a separate code path that happens to look similar.
Units are load-bearing here and the source says so. The base intensity is per millisecond, matching the per-millisecond variance estimate. Mixing time units in this formula produces a plausible number and a wrong spread, which is the worst failure mode available.
Binary-outcome models
A prediction market prices an outcome on the unit interval, and that geometry breaks the assumptions a continuous-price maker rests on. Two further models are native to it, both selected by name and both defaulting off so the ordinary path stays byte-identical.
- The LMSR reservation
- Hanson's Logarithmic Market Scoring Rule, in a live-anchored form: the binary price is the logistic of net inventory over a liquidity depth, so the reservation is computed by converting the live mid to log-odds, walking it by signed inventory, and mapping back. The reason for log-odds rather than a linear cash skew is exactly the wall problem: a linear skew walks a near-boundary quote straight off the edge, while log-odds keeps the reservation on the interval and reproduces the LMSR wall — a unit of inventory moves price a great deal at the coin-flip mid and vanishingly little near a boundary. Degenerate inputs return the mid unchanged, and zero inventory short-circuits to the mid exactly rather than round-tripping through two independently rounded transcendentals that need not compose back to it.
- The LS-LMSR half-spread
- A liquidity-sensitive automated market maker's liquidity parameter scales with volume, so its built-in overround is a volume-scaled spread — and this reads that overround off as a half-spread. A balanced book carries a wider spread than a lopsided one, because a near-resolved book's overround tends to nothing.
- The Glosten–Milgrom half-spread
- Spread as pure adverse selection: an informed fraction of traders knows the binary outcome, noise traders flip a coin, and a competitive dealer's zero-profit bid and ask are the conditional expectations given a sell and given a buy. The half-spread is literally the price of being picked off, and it is widest near the coin-flip mid and tends to nothing as the outcome resolves.
The two axes are orthogonal by design — one swaps how the reservation responds to inventory, the other swaps where the half-spread comes from — and both feed the same width ladder and the same posting assembly. At their defaults both read zero, which is precisely why the minimum-ticks floor exists: a zero read must not silently collapse the quote.
Inventory control
Pricing leans against inventory. Two further mechanisms act on it directly.
Size skew
Skew multipliers shape the two quote sizes from the gap between current and target inventory, and the properties they hold are each pinned: neutral (a zero skew reproduces the fixed-size path bit-for-bit, and also guards the division), directional (long shrinks the bid and grows the ask, leaning to sell the position down; short mirrors), symmetric about the target, monotonic in position, and clamped so an over-unit skew can never request a negative size. The shaped size is the base every ladder rung then multiplies.
The fill-rate circuit breaker
A side being repeatedly hit without offsetting fills on the other side is the signature of adverse selection — a falling market lifting your bid over and over. The breaker suppresses that side and lets it cool down, while the other side keeps quoting and re-skewing normally.
What makes it usable is that it nets. Fills inside the window are summed signed: a bid fill later offset by an equal ask fill sums back toward zero, which is a completed, inventory-neutral round trip — the desired outcome of market making, and exactly the thing that must not trip a guard. Only net one-directional accumulation survives the sum. Every timestamp is an event stamp rather than a wall clock, matching the runtime's determinism.
The impulse leg
Passive quoting cannot bound inventory on its own: an adverse run fills one side repeatedly and the position drifts. Guilbaud and Pham's answer is an impulse-control leg on top of the continuous quoting — at discrete moments the agent may cross the book with a market order to cut inventory it cannot skew its way out of. The crate implements that as one pure decision: it fires only when inventory is strictly over a tolerated band, and it cuts only the excess over the band, leaving the position resting exactly at it. Flattening all the way to zero would pay the taker spread on inventory the maker deliberately tolerates, and would fight the skew that is already leaning that inventory down for free. A caller wanting a hard flatten passes a band of zero.
It is stated as a practitioner heuristic rather than the optimal policy: the true impulse region is the solution of a quasi-variational inequality with no closed form, and a fixed band is the standard reduction of it to one tunable.
Nothing an operator can run reaches the impulse leg today. It is crate-private, and its only caller outside the crate's own tests is the cross-exchange maker — which is complete and tested and reachable by no binary, profile, flag or feature: the strategy registry carries no arm for it. The single-venue maker does not call it. That is stated here because "we implement Guilbaud–Pham" without it would be technically true and practically misleading.
Ladder quoting and refresh
Ladder mode rests several orders per side instead of one. The innermost rung is bit-for-bit the quote the single-order maker would have rested, and each deeper rung steps a fixed offset further out, away from the reservation price. The offset unit is the one grid-agnostic choice in the design: measured in multiples of the level-zero half-spread it needs no tick grid at all and reads identically on a unit-interval prediction market and a five-figure crypto book, while a tick-based unit needs the venue's grid and collapses the ladder to one level when that grid is unknown. Sizes are multipliers of the base size — arithmetic or geometric growth — so the inventory skew that shapes level zero flows through every rung. One level per side means the ladder is off, and the maker rests exactly the one order it always did.
Re-quoting has a cost the model does not see: a modify sent on every book delta is the maker's biggest wire cost on a rate-limited venue reached over a long link, and a quote that re-prices every tick forfeits its queue slot — a quote that never holds its place can never be hit. The refresh tolerance is the anti-churn gate for that. Given what a side already has resting and the target the current tick computed, it answers "close enough to leave alone", and a skip leaves the resting order and its queue position untouched.
Both of its axes — price and size — are relative, measured in basis points of the resting value, for the same reason the ladder offset is: that unit reads sanely on both price scales without the strategy knowing either venue's grid. A skip needs both axes inside tolerance. The edge rules go the conservative way: an exactly unchanged value always passes because there is nothing to send; a non-positive tolerance means only exact equality passes; and a zero, non-finite or not-a-number reference never skips, because re-pricing costs a wire message while silently stranding a stale quote costs money.
The break-even floor
This deserves its own heading because it is the one place the maker refuses to trade. The floor is derived from the round-trip maker fee expressed as a fraction of price, and it is checked against the width cap rather than merged into it. When no width clears the round-trip fee under the cap, the maker posts nothing and warns — on the edge into and out of the refusal, twice per episode rather than once per tick, because the quoting step runs on the latency-gated fold.
An unknown fee is distinguished from a zero fee, which sounds pedantic and is not: an absent round-trip rate means nobody could name this venue's maker fee as a fraction of price, and that is a different statement from a measured zero. A venue whose fee shape cannot be expressed as a fraction of price — a free schedule, or a probability-scaled one — cannot arm the floor at all, and that is stated rather than approximated.
Running one
The maker resolves from the same registry a backtest and the daemon share, under two names: the reservation-priced maker, and an alias that forces the stationary closed form so the identical knobs price with it. A bare parameter table yields the recommended reservation-priced configuration and each present key overrides one knob, and the registry reader mirrors how the live mount composes the maker, so a profile and a live mount cannot disagree about what a knob means.
A typo in an enum key fails the profile — it does not fall back. Each selector once returned "absent" for an unrecognized value as well as for a missing one, so a misspelt model name silently ran a different model than the profile named. A present-but-unrecognized value for any of the model, variance, horizon, price-domain, reservation, spread-source, intensity or style selectors now refuses to resolve.
Run it the way you would run anything else here: backtest it against a recorded book with the queue and latency models armed, since a maker backtested without them is being handed impossible queue position and impossible reflexes; then mount it paper on a live feed, where the paper exchange charges exactly what the simulator charged; then raise the venue's ceiling to demo, and only then to live. The arming ceiling and the risk gate sit in front of every one of those steps, and reconciliation is what proves the resting book you think you have is the resting book the venue has.
Run it yourself.
Every venue mounts paper by default. Nothing below trades anything until you say so.
Free. Source-available under FSL-1.1; every release becomes Apache-2.0 two years on.
Trading involves substantial risk of loss and is not suitable for every investor. Nothing on this page is investment, financial or trading advice, and no result shown or described — backtested, simulated, paper or live — is a promise of future performance. Backtested and simulated results in particular have inherent limitations: they are produced with hindsight, do not reflect every real-market condition, and no representation is made that any account will achieve results similar to them. Vike Trader is software; orders sent from your accounts, the credentials that authorize them and the decisions behind them remain yours. Consider your circumstances, and never trade money you cannot afford to lose.