Contingent orders
One-triggers-other arming and one-cancels-other cancellation are decided by a single resolver that every fill lane calls, so the paper book and the backtest broker can no longer disagree about what a bracket does.
A bracket is three orders with two relationships between them: the protective stop and the
take-profit are held until the entry fills (one-triggers-other), and once armed, whichever exit
fills cancels the other (one-cancels-other). crates/vike-exec/src/contingency.rs is the one
place those two relationships are resolved, and its header says why it had to be one place.
The defect that made it one resolver
Before this module the law lived lane-dependently. The paper book ran full one-cancels-other on
every fill, while the backtest SimBroker cancelled a fired protective stop's exit siblings only on
its granular sub-bar lane — its coarse and tick lanes left the take-profit limit resting on a flat
book, so one wide bar could fire the stop and the take-profit and open a spurious reversed
position. The paper book's own apply_contingency was the semantic template the module lifts.
The module owns only the decision — which children arm, which siblings cancel. Both callers
keep their own book mechanics: resting-order storage, event emission, the actual cancels. That
split is what makes the two lanes structurally unable to disagree again, and the
paper exchange's r7 gate has a bracket row that proves it — the
backtest broker's entry-with-protective-stop plus resting take-profit fills bit-identically to the
live submit_bracket's triple resting in the paper book, with both stops firing through the one
trigger oracle and both sides cancelling the surviving exit.
Two linkage shapes, one law
Coid-linked — ContingencyBook. Explicit parent and linked client-order-ids ride on the
order request, which is what the bracket lowering vike_model::build_bracket emits: an entry with
no parent, linked to both exits; a stop whose parent is the entry, linked to the take-profit; a
take-profit whose parent is the entry, linked to the stop. Live, OrderIntent::Bracket is the verb
— the runtime mints the three ids and wires the links — and the paper book keys its own book by
those ids.
Kind-linked — is_protective_exit_sibling. The backtest SimBroker arms an id-less implicit
bracket through WorkingOrder::stop, so after a protective-stop fill flattens the position there is
no id to follow. Its siblings are identified by kind: a resting order is that stop's
one-cancels-other partner, and must cancel, if and only if it is a closing-side Limit or
LimitClose exit. Entries and adds on the opposite side never match, and neither do stop or
trailing kinds — a second protective layer is not a take-profit. The test pins both directions: a
long stopped out cancels sell limits and keeps a re-entry buy limit and a second stop; a short
stopped out mirrors it.
What the book does on a fill
ContingencyBook::insert records a leg's linkage. A held exit — one with a parent — starts
inactive; an entry starts active immediately. is_held is the question a fill pass asks before
letting an order fill: a held order must not, and every plain order, which is never inserted at
all, is never held. That absence is the byte-identical path for non-bracket runs — a book with no
brackets stays empty and every resolver call is a cheap no-op.
on_fill resolves one fill in two steps: arm every held child of the filled id, then return its
one-cancels-other siblings — its linked ids that are not its own children — in linked order.
The caller cancels whichever of those still rest in its book and calls remove for each one it
actually cancelled; a sibling already gone cancels nothing. The bracket test shows the shape: the
entry's fill arms both exits and cancels nothing, because the entry's linked ids are its own
children; the stop's fill then returns exactly the take-profit. A plain, unrecorded fill arms nothing
and returns empty.
siblings_of answers the same sibling question read-only, so a dying protective exit — cancelled
or expired rather than filled — resolves its surviving partner off the same linkage a fill would,
and the terminal-cancel and fill-cancel paths cannot disagree about who the sibling is.
children_of is the walk step of the expire/cancel cascade: a child whose parent terminated
without filling can never arm. clear is the mass-cancel twin.
Restarting with an armed bracket in flight
insert derives active from "has no parent", which is wrong for a child that was already armed by
its parent's fill before a crash: re-inserting it would silently re-hold an armed exit. So the book
exposes snapshot — every entry as (coid, parent, linked, active) in insertion order — for the
journal's Snap record, and insert_active takes the flag explicitly for the restart re-seed.
Neither is used on the live submit path; both exist so replay
reproduces the same arm and cancel iteration order the live book had, which is also why the book is
an IndexMap: the arm sweep and children_of iterate the map, and insertion order keeps the event
stream reproducible.
Live, the drive is gated on the fold's verdict
On the venue ingest lane the runtime drives this resolver only when the
event bus reports that the engine actually applied the fill. The
Fold verdict was added for exactly this consumer: a fabricated OrderFilled on an unknown
client-order-id used to cancel its sibling and arm its held children even though the engine had
dropped the event — a naked position on the strength of a fill that never happened.
crates/vike-core/src/runtime/mod.rs's pump_client records that the in-process client seam is
deliberately not gated the same way.
One boundary of the coid-linked shape is declared where it bites. The paper client's combo book does not support contingency links on a multi-leg combo — a combo request carrying a parent or linked ids is terminally rejected, because the hold and cascade machinery enforce against the single-symbol resting book only — while a plain order may link a resting combo as a sibling, and a combo's fill arms plain held children as any fill does. What each order kind means, and which venues carry it natively, is under orders; a conditional the core emulates for a venue without one is emulated orders.
The account
Positions and realized PnL are a read model folded from the fill stream, with one writer, no equity cache, insertion-ordered sums pinned by the parity gate, and a fill-dedup ledger welded to the money it protects.
Halt
An engaged halt stops orders that open risk and admits orders that close it; the two mechanisms that enforce that rule agree on policy and differ only in how much they can verify.