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).
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.ⓘ
| Model | Cost | Time | Step-insⓘ | Autonomy | Outcome | Trustⓘ | Date | Compare |
|---|---|---|---|---|---|---|---|---|
| OGPT-6.1 Soldefault · thinking on | $0.06 | 1m | 0 | Fully autonomous | pass | Trust 80% | 2026-10-22 | |
| AClaude Haiku 5.5default · thinking on | $0.02 | 2m | 0 | Fully autonomous | pass | Trust 80% | 2026-10-20 | |
| AClaude Opus 5.5default · thinking on | $0.37 | 1m | 0 | Fully autonomous | pass | Trust 80% | 2026-10-20 | |
| AClaude Sonnet 5.5default · thinking on | $0.12 | 43s | 0 | Fully autonomous | pass | Trust 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.
Get new runs and ranking changes weekly
Which models got better or cheaper on real tasks like this one.