Skip to content

Limit order book matching engine with self-trade prevention, FOK and modify priority

Exact prompt

# Limit order book matching engine `input.json` has `events` (a list, processed in order, index = position) and `bbo_every` k. Write `solve.py` (Python 3 standard library only); `python solve.py input.json answer.json`. Fresh inputs are generated, including one with **60,000 events that must finish within 20 seconds** (other runs: 30 s). Prices and quantities are integers (ticks/lots); all arithmetic is exact. ## Events - `{"op": "new", "id", "side": "B"|"S", "type": "LMT"|"MKT", "qty", "px" (LMT only), "tif": "GTC"|"IOC"|"FOK" (LMT only, default GTC), "owner" (default ""), "stp": "cancel_resting"|"cancel_incoming" (default cancel_resting), "post_only" (default false)}` - `{"op": "cancel", "id"}` - `{"op": "modify", "id", "qty"?, "px"?}` (a missing field keeps the current value; `qty` is the new *remaining* quantity) - anything else: reject `bad_op`. ## Rules 1. A reject is recorded as `{"event": index, "id": event's id or null, "reason"}` and the event has no other effect. 2. New-order validation, first failure wins: `bad_id` (id not a non-empty string), `duplicate_id` (id already used by ANY earlier new event, including rejected ones once they passed `bad_id`), `bad_side`, `bad_type`, `bad_qty` (not a positive integer; booleans and floats are invalid), `bad_price` (LMT only: not a positive integer), `bad_tif` (LMT only). For MKT orders `px` and `tif` are ignored and the order behaves as IOC. 3. Then, in order: a `post_only` LMT that would cross the opposite best is rejected `post_only_would_cross`; a MKT order with an empty opposite side is rejected `no_liquidity`; a FOK order is rejected `fok_unfilled` if the fill check (rule 8) fails. 4. Matching: an incoming order trades against the opposite side in price-time priority (best price first; within a price, earlier arrival first) while it has quantity left and the best opposite price is acceptable (buy: ask <= limit; sell: bid >= limit; MKT: any). Each trade executes at the **resting** order's price for min(both remaining). 5. Self-trade prevention (same `owner` on both sides), using the **incoming** order's `stp`: `cancel_resting` removes that resting order (no trade) and matching continues; `cancel_incoming` cancels the incoming order's remaining quantity at that point (trades already done stand; it never rests). 6. After matching, a GTC LMT remainder rests on the book (as a new arrival). IOC/FOK/MKT remainders are discarded. 7. Trades: `{"seq": 1, 2, ..., "buy_id", "sell_id", "px", "qty", "aggressor": side of the incoming order}`. 8. FOK fill check: walk the opposite resting orders in priority order over acceptable prices; skip orders of the same owner if `stp` is `cancel_resting`; **stop** at the first same-owner order if `stp` is `cancel_incoming`. Pass if the summed quantity of the walked other-owner orders >= qty. 9. `cancel`: if the id is not a live resting order, reject `unknown_order`; otherwise remove it. 10. `modify`: not live -> `unknown_order`. New qty must be an integer >= 0 and new px a positive integer, else `bad_modify`. qty 0 -> remove the order. Same price and new qty <= current remaining -> update in place, **keeping time priority**. Otherwise (price change or qty increase) the order **loses priority**: it is taken off the book and re-entered as an incoming GTC LMT with the same id, owner and stp (no post-only, no duplicate-id check, no FOK), which may trade (rule 4-5) and rests last in time at its price. 11. After every k-th event (event index i with (i+1) % k == 0), append `[best_bid, best_ask]` to `bbo` (null for an empty side). ## answer.json `{"trades": [...], "rejects": [...], "bbo": [...], "book": {"bids": [[px, total_remaining, order_count], ...], "asks": [...]}` (top 5 price levels, bids high to low, asks low to high) `, "positions": {owner: net bought minus sold}, "cash": {owner: sum of sell px*qty minus buy px*qty}` (owners that traded, sorted by name) `, "volume": total traded qty, "vwap": volume-weighted price rounded to 4 decimals or null, "resting_orders": live resting orders at the end}` ## Scoring Hidden checks (partial credit = fraction passed; all must pass): `validation_rejects` (the rule-2/9/10 reasons in order), `all_rejects`, `first_50_trades`, `all_trades`, `bbo_path`, `final_book_and_counts`, `positions_cash_vwap` on the given input; `fresh_run_1`, `fresh_run_2` (every key) on fresh inputs; `big_input_60k_events_20s` (every key, 20-second limit). vwap within 0.0001, everything else exact.

One misplaced priority (modify), STP mode, or FOK-walk rule shifts every later trade and BBO; a list-based book times out on 60k events. Original benchmark task written for usecaserank.com (not based on a specific public post). Headless, offline run on a reproducible fixture. Each run's notes say how its cost was measured (estimates are marked).

Success criteria: 1. validation_rejects 2. all_rejects 3. first_50_trades 4. all_trades 5. bbo_path 6. final_book_and_counts 7. positions_cash_vwap 8. fresh_run_1 9. fresh_run_2 10. big_input_60k_events_20s

Best model for this task so far: Claude Haiku 5.5 (effort default (no --effort flag) · thinking on) (success, $0.02, 2m).

Run this on another model

All runs (4)

100% pass rate across 4 eligible runs: 4 pass, 0 partial, 0 fail. Partial and failed runs are listed below with everything else.ⓘ

Runs for this use case
ModelCostTimeStep-insⓘAutonomyOutcomeTrustⓘDateCompare
OGPT-6.1 Soldefault · thinking on$0.061m0Fully autonomouspassTrust 80%2026-10-22
AClaude Haiku 5.5default · thinking on$0.022m0Fully autonomouspassTrust 80%2026-10-20
AClaude Opus 5.5default · thinking on$0.371m0Fully autonomouspassTrust 80%2026-10-20
AClaude Sonnet 5.5default · thinking on$0.1243s0Fully autonomouspassTrust 80%2026-10-20

Embed this result

A live badge for this use case. It links back here and updates as new runs are published.

UseCaseRank badge for Limit order book matching engine with self-trade prevention, FOK and modify priority

Get new runs and ranking changes weekly

Which models got better or cheaper on real tasks like this one.